Skip to content

Commit

Permalink
Remove window flicker from open command
Browse files Browse the repository at this point in the history
This solves a problem that had been already solved in
0d1b5e0 but was reintroduced in
a9a35c1. 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 elkowar#892.
  • Loading branch information
BeneSim committed Jun 18, 2024
1 parent d1fde92 commit 8f1cd1a
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 27 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ All notable changes to eww will be listed here, starting at changes since versio
## Unreleased

### Fixes
- Fix window flicker when opening an already existing window (By: benesim)
- Fix and refactor nix flake (By: w-lfchen)
- Fix remove items from systray (By: vnva)

Expand Down
62 changes: 35 additions & 27 deletions crates/eww/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -362,14 +362,46 @@ impl<B: DisplayBackend> App<B> {
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());
Expand Down Expand Up @@ -431,32 +463,8 @@ impl<B: DisplayBackend> App<B> {
}
}));

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);
Expand Down

0 comments on commit 8f1cd1a

Please sign in to comment.