Skip to content

Commit

Permalink
fix(animation): add async focus manager for mff
Browse files Browse the repository at this point in the history
This commit adds a new focus manager module to be used to trigger async
focus changes with mouse follows focus updates. Currently this should
only need to be used with animations as all other focus calls are
synchronous.

fix #910
  • Loading branch information
LGUG2Z committed Jul 12, 2024
1 parent bdc1cad commit 2c8f25e
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 0 deletions.
70 changes: 70 additions & 0 deletions komorebi/src/focus_manager.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#![deny(clippy::unwrap_used, clippy::expect_used)]

use crossbeam_channel::Receiver;
use crossbeam_channel::Sender;
use parking_lot::Mutex;
use std::ops::Deref;
use std::sync::Arc;
use std::sync::OnceLock;

use crate::Window;
use crate::WindowManager;

pub struct Notification(isize);

impl Deref for Notification {
type Target = isize;

fn deref(&self) -> &Self::Target {
&self.0
}
}

static CHANNEL: OnceLock<(Sender<Notification>, Receiver<Notification>)> = OnceLock::new();

pub fn channel() -> &'static (Sender<Notification>, Receiver<Notification>) {
CHANNEL.get_or_init(|| crossbeam_channel::bounded(20))
}

fn event_tx() -> Sender<Notification> {
channel().0.clone()
}

fn event_rx() -> Receiver<Notification> {
channel().1.clone()
}

// Currently this should only be used for async focus updates, such as
// when an animation finishes and we need to focus to set the cursor
// position if the user has mouse follows focus enabled
pub fn send_notification(hwnd: isize) {
if event_tx().try_send(Notification(hwnd)).is_err() {
tracing::warn!("channel is full; dropping notification")
}
}

pub fn listen_for_notifications(wm: Arc<Mutex<WindowManager>>) {
std::thread::spawn(move || loop {
match handle_notifications(wm.clone()) {
Ok(()) => {
tracing::warn!("restarting finished thread");
}
Err(error) => {
tracing::warn!("restarting failed thread: {}", error);
}
}
});
}

pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result<()> {
tracing::info!("listening");

let receiver = event_rx();

for notification in receiver {
let mouse_follows_focus = wm.lock().mouse_follows_focus;
let _ = Window::from(*notification).focus(mouse_follows_focus);
}

Ok(())
}
1 change: 1 addition & 0 deletions komorebi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ pub mod com;
pub mod ring;
pub mod colour;
pub mod container;
pub mod focus_manager;
pub mod monitor;
pub mod monitor_reconciliator;
pub mod process_command;
Expand Down
2 changes: 2 additions & 0 deletions komorebi/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::EnvFilter;

use komorebi::border_manager;
use komorebi::focus_manager;
use komorebi::load_configuration;
use komorebi::monitor_reconciliator;
use komorebi::process_command::listen_for_commands;
Expand Down Expand Up @@ -265,6 +266,7 @@ fn main() -> Result<()> {
workspace_reconciliator::listen_for_notifications(wm.clone());
monitor_reconciliator::listen_for_notifications(wm.clone())?;
reaper::watch_for_orphans(wm.clone());
focus_manager::listen_for_notifications(wm.clone());

let (ctrlc_sender, ctrlc_receiver) = crossbeam_channel::bounded(1);
ctrlc::set_handler(move || {
Expand Down
4 changes: 4 additions & 0 deletions komorebi/src/window.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::border_manager;
use crate::com::SetCloak;
use crate::focus_manager;
use crate::stackbar_manager;
use crate::ANIMATIONS_IN_PROGRESS;
use crate::ANIMATION_DURATION;
Expand Down Expand Up @@ -189,6 +190,9 @@ impl Window {

if progress == 1.0 {
WindowsApi::position_window(hwnd, &new_rect, top)?;
if WindowsApi::foreground_window().unwrap_or_default() == hwnd.0 {
focus_manager::send_notification(hwnd.0)
}

if ANIMATIONS_IN_PROGRESS.load(Ordering::Acquire) == 0 {
border_manager::BORDER_TEMPORARILY_DISABLED.store(false, Ordering::SeqCst);
Expand Down

0 comments on commit 2c8f25e

Please sign in to comment.