From eac4e0f55aff0bbf6cdb9a05962c801eae226f51 Mon Sep 17 00:00:00 2001 From: Benjamin Isbarn Date: Tue, 18 Jun 2024 20:09:29 +0200 Subject: [PATCH] Remove window flicker from open command This solves a problem that had been already solved in 0d1b5e0f9e532ade4b7c9fd77b46b6a29b1d8529 but was reintroduced in a9a35c1804d72ef92e04ee71555bd9e5a08fa17e. Basically before this, the window has been closed and reopened if it existed, which results in flickering due to the animations. In addition to remove the window flicker the timer (if started with --duration) will also be renewed. This fixes #892. --- crates/eww/src/app.rs | 62 ++++++++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 27 deletions(-) diff --git a/crates/eww/src/app.rs b/crates/eww/src/app.rs index 41b3364a..9eedbf60 100644 --- a/crates/eww/src/app.rs +++ b/crates/eww/src/app.rs @@ -362,14 +362,46 @@ impl App { Ok(()) } + fn setup_close_timer(&mut self, instance_id: &str, duration: Duration) { + let app_evt_sender = self.app_evt_send.clone(); + + let (abort_send, abort_recv) = futures::channel::oneshot::channel(); + + glib::MainContext::default().spawn_local({ + let instance_id = instance_id.to_string(); + async move { + tokio::select! { + _ = glib::timeout_future(duration) => { + let (response_sender, mut response_recv) = daemon_response::create_pair(); + let command = DaemonCommand::CloseWindows { windows: vec![instance_id.clone()], sender: response_sender }; + if let Err(err) = app_evt_sender.send(command) { + log::error!("Error sending close window command to daemon after gtk window destroy event: {}", err); + } + _ = response_recv.recv().await; + } + _ = abort_recv => {} + } + } + }); + + if let Some(old_abort_send) = self.window_close_timer_abort_senders.insert(instance_id.to_string(), abort_send) { + _ = old_abort_send.send(()); + } + } + fn open_window(&mut self, window_args: &WindowArguments) -> Result<()> { let instance_id = &window_args.instance_id; self.failed_windows.remove(instance_id); log::info!("Opening window {} as '{}'", window_args.window_name, instance_id); - // if an instance of this is already running, close it + // if an instance of this is already running, do nothing, but if a + // duration has been supplied refresh the window close timer + let duration = window_args.duration; if self.open_windows.contains_key(instance_id) { - self.close_window(instance_id)?; + if let Some(duration) = duration { + self.setup_close_timer(instance_id, duration); + } + return Ok(()); } self.instance_id_to_args.insert(instance_id.to_string(), window_args.clone()); @@ -431,32 +463,8 @@ impl App { } })); - let duration = window_args.duration; if let Some(duration) = duration { - let app_evt_sender = self.app_evt_send.clone(); - - let (abort_send, abort_recv) = futures::channel::oneshot::channel(); - - glib::MainContext::default().spawn_local({ - let instance_id = instance_id.to_string(); - async move { - tokio::select! { - _ = glib::timeout_future(duration) => { - let (response_sender, mut response_recv) = daemon_response::create_pair(); - let command = DaemonCommand::CloseWindows { windows: vec![instance_id.clone()], sender: response_sender }; - if let Err(err) = app_evt_sender.send(command) { - log::error!("Error sending close window command to daemon after gtk window destroy event: {}", err); - } - _ = response_recv.recv().await; - } - _ = abort_recv => {} - } - } - }); - - if let Some(old_abort_send) = self.window_close_timer_abort_senders.insert(instance_id.to_string(), abort_send) { - _ = old_abort_send.send(()); - } + self.setup_close_timer(instance_id, duration); } self.open_windows.insert(instance_id.to_string(), eww_window);