@@ -55,6 +55,7 @@ pub enum DaemonCommand {
55
55
anchor : Option < AnchorPoint > ,
56
56
screen : Option < MonitorIdentifier > ,
57
57
should_toggle : bool ,
58
+ duration : Option < std:: time:: Duration > ,
58
59
sender : DaemonResponseSender ,
59
60
} ,
60
61
CloseWindows {
@@ -114,6 +115,9 @@ pub struct App<B> {
114
115
pub app_evt_send : UnboundedSender < DaemonCommand > ,
115
116
pub script_var_handler : ScriptVarHandlerHandle ,
116
117
118
+ /// Senders that will cancel a windows auto-close timer when started with --duration.
119
+ pub window_close_timer_abort_senders : HashMap < String , futures:: channel:: oneshot:: Sender < ( ) > > ,
120
+
117
121
pub paths : EwwPaths ,
118
122
}
119
123
@@ -181,20 +185,27 @@ impl<B: DisplayBackend> App<B> {
181
185
if should_toggle && self . open_windows . contains_key ( w) {
182
186
self . close_window ( w)
183
187
} else {
184
- self . open_window ( w, None , None , None , None )
188
+ self . open_window ( w, None , None , None , None , None )
185
189
}
186
190
} )
187
191
. filter_map ( Result :: err) ;
188
192
sender. respond_with_error_list ( errors) ?;
189
193
}
190
- DaemonCommand :: OpenWindow { window_name, pos, size, anchor, screen : monitor, should_toggle, sender } => {
194
+ DaemonCommand :: OpenWindow {
195
+ window_name,
196
+ pos,
197
+ size,
198
+ anchor,
199
+ screen : monitor,
200
+ should_toggle,
201
+ duration,
202
+ sender,
203
+ } => {
191
204
let is_open = self . open_windows . contains_key ( & window_name) ;
192
- let result = if !is_open {
193
- self . open_window ( & window_name, pos, size, monitor, anchor)
194
- } else if should_toggle {
205
+ let result = if should_toggle && is_open {
195
206
self . close_window ( & window_name)
196
207
} else {
197
- Ok ( ( ) )
208
+ self . open_window ( & window_name , pos , size , monitor , anchor , duration )
198
209
} ;
199
210
sender. respond_with_result ( result) ?;
200
211
}
@@ -294,6 +305,9 @@ impl<B: DisplayBackend> App<B> {
294
305
295
306
/// Close a window and do all the required cleanups in the scope_graph and script_var_handler
296
307
fn close_window ( & mut self , window_name : & str ) -> Result < ( ) > {
308
+ if let Some ( old_abort_send) = self . window_close_timer_abort_senders . remove ( window_name) {
309
+ _ = old_abort_send. send ( ( ) ) ;
310
+ }
297
311
let eww_window = self
298
312
. open_windows
299
313
. remove ( window_name)
@@ -320,11 +334,13 @@ impl<B: DisplayBackend> App<B> {
320
334
size : Option < Coords > ,
321
335
monitor : Option < MonitorIdentifier > ,
322
336
anchor : Option < AnchorPoint > ,
337
+ duration : Option < std:: time:: Duration > ,
323
338
) -> Result < ( ) > {
324
339
self . failed_windows . remove ( window_name) ;
325
340
log:: info!( "Opening window {}" , window_name) ;
326
341
327
342
// if an instance of this is already running, close it
343
+ // TODO make reopening optional via a --no-reopen flag?
328
344
if self . open_windows . contains_key ( window_name) {
329
345
self . close_window ( window_name) ?;
330
346
}
@@ -380,6 +396,34 @@ impl<B: DisplayBackend> App<B> {
380
396
}
381
397
} ) ) ;
382
398
399
+ if let Some ( duration) = duration {
400
+ let app_evt_sender = self . app_evt_send . clone ( ) ;
401
+ let window_name = window_name. to_string ( ) ;
402
+
403
+ let ( abort_send, abort_recv) = futures:: channel:: oneshot:: channel ( ) ;
404
+
405
+ glib:: MainContext :: default ( ) . spawn_local ( {
406
+ let window_name = window_name. clone ( ) ;
407
+ async move {
408
+ tokio:: select! {
409
+ _ = glib:: timeout_future( duration) => {
410
+ let ( response_sender, mut response_recv) = daemon_response:: create_pair( ) ;
411
+ let command = DaemonCommand :: CloseWindows { windows: vec![ window_name] , sender: response_sender } ;
412
+ if let Err ( err) = app_evt_sender. send( command) {
413
+ log:: error!( "Error sending close window command to daemon after gtk window destroy event: {}" , err) ;
414
+ }
415
+ _ = response_recv. recv( ) . await ;
416
+ }
417
+ _ = abort_recv => { }
418
+ }
419
+ }
420
+ } ) ;
421
+
422
+ if let Some ( old_abort_send) = self . window_close_timer_abort_senders . insert ( window_name, abort_send) {
423
+ _ = old_abort_send. send ( ( ) ) ;
424
+ }
425
+ }
426
+
383
427
self . open_windows . insert ( window_name. to_string ( ) , eww_window) ;
384
428
} ;
385
429
@@ -407,7 +451,7 @@ impl<B: DisplayBackend> App<B> {
407
451
let window_names: Vec < String > =
408
452
self . open_windows . keys ( ) . cloned ( ) . chain ( self . failed_windows . iter ( ) . cloned ( ) ) . dedup ( ) . collect ( ) ;
409
453
for window_name in & window_names {
410
- self . open_window ( window_name, None , None , None , None ) ?;
454
+ self . open_window ( window_name, None , None , None , None , None ) ?;
411
455
}
412
456
Ok ( ( ) )
413
457
}
0 commit comments