From 7f7b8c7c05cb093bc8eda5c1e3e900c1efbd2d4f Mon Sep 17 00:00:00 2001 From: alex-ds13 <145657253+alex-ds13@users.noreply.github.com> Date: Tue, 29 Oct 2024 13:36:41 +0000 Subject: [PATCH] fix(borders): update border loc when moving Currently, komorebi checks if a move is happening by checking if the left mouse is pressed and updates the borders when there is a move while the left mouse button is pressed (BTW this is why when moving with the keyboard using the system move it only updates after pressing enter). However, for some reason AltSnap somehow steals this left button information and komorebi thinks the button is not pressed. This PR makes it so it checks for the state of the pending_move_op and keeps updating the borders while this is_some(). This fixes both that issue with AltSnap and the issue with system move, as well as any other situations that might allow moving a window with anything else that doesn't use a left mouse button press. --- komorebi/src/border_manager/mod.rs | 24 +++++++++++++++++++++--- komorebi/src/process_event.rs | 9 +++++---- komorebi/src/static_config.rs | 2 +- komorebi/src/window_manager.rs | 4 ++-- 4 files changed, 29 insertions(+), 10 deletions(-) diff --git a/komorebi/src/border_manager/mod.rs b/komorebi/src/border_manager/mod.rs index 2825d086..71f76057 100644 --- a/komorebi/src/border_manager/mod.rs +++ b/komorebi/src/border_manager/mod.rs @@ -157,7 +157,8 @@ pub fn handle_notifications(wm: Arc>) -> color_eyre::Result let focused_workspace_idx = state.monitors.elements()[focused_monitor_idx].focused_workspace_idx(); let monitors = state.monitors.clone(); - let pending_move_op = state.pending_move_op; + let weak_pending_move_op = Arc::downgrade(&state.pending_move_op); + let pending_move_op = *state.pending_move_op; let floating_window_hwnds = state.monitors.elements()[focused_monitor_idx].workspaces() [focused_workspace_idx] .floating_windows() @@ -413,7 +414,19 @@ pub fn handle_notifications(wm: Arc>) -> color_eyre::Result c.focused_window().copied().unwrap_or_default().hwnd, )?; - while WindowsApi::lbutton_is_pressed() { + // We create a new variable to track the actual pending move op so + // that the other variable `pending_move_op` still holds the + // pending move info so that when the move ends we know on the next + // notification that the previous pending move and pending move are + // different (because a move just finished) and still handle the + // notification. If otherwise we updated the pending_move_op here + // directly then the next pending move after finish would be the + // same because we had already updated it here. + let mut sync_pending_move_op = + weak_pending_move_op.upgrade().and_then(|p| *p); + while sync_pending_move_op.is_some() { + sync_pending_move_op = + weak_pending_move_op.upgrade().and_then(|p| *p); let border = match borders.entry(c.id().clone()) { Entry::Occupied(entry) => entry.into_mut(), Entry::Vacant(entry) => { @@ -496,7 +509,12 @@ pub fn handle_notifications(wm: Arc>) -> color_eyre::Result if pending_move_op.is_some() && hwnd == notification_hwnd { let mut rect = WindowsApi::window_rect(hwnd)?; - while WindowsApi::lbutton_is_pressed() { + // Check comment above for containers move + let mut sync_pending_move_op = + weak_pending_move_op.upgrade().and_then(|p| *p); + while sync_pending_move_op.is_some() { + sync_pending_move_op = + weak_pending_move_op.upgrade().and_then(|p| *p); let border = match borders.entry(hwnd.to_string()) { Entry::Occupied(entry) => entry.into_mut(), Entry::Vacant(entry) => { diff --git a/komorebi/src/process_event.rs b/komorebi/src/process_event.rs index e286bb74..ea98a154 100644 --- a/komorebi/src/process_event.rs +++ b/komorebi/src/process_event.rs @@ -436,16 +436,17 @@ impl WindowManager { WindowsApi::bring_window_to_top(window.hwnd)?; - self.pending_move_op = - Option::from((monitor_idx, workspace_idx, container_idx)); + let pending_move_op = Arc::make_mut(&mut self.pending_move_op); + *pending_move_op = Option::from((monitor_idx, workspace_idx, container_idx)); } } WindowManagerEvent::MoveResizeEnd(_, window) => { // We need this because if the event ends on a different monitor, // that monitor will already have been focused and updated in the state - let pending = self.pending_move_op; + let pending = *self.pending_move_op; // Always consume the pending move op whenever this event is handled - self.pending_move_op = None; + let pending_move_op = Arc::make_mut(&mut self.pending_move_op); + *pending_move_op = None; let target_monitor_idx = self .monitor_idx_from_current_pos() diff --git a/komorebi/src/static_config.rs b/komorebi/src/static_config.rs index 9857491d..86c28e55 100644 --- a/komorebi/src/static_config.rs +++ b/komorebi/src/static_config.rs @@ -1049,7 +1049,7 @@ impl StaticConfig { mouse_follows_focus: value.mouse_follows_focus.unwrap_or(true), hotwatch: Hotwatch::new()?, has_pending_raise_op: false, - pending_move_op: None, + pending_move_op: Arc::new(None), already_moved_window_handles: Arc::new(Mutex::new(HashSet::new())), }; diff --git a/komorebi/src/window_manager.rs b/komorebi/src/window_manager.rs index 1080e5fa..c5d28a3d 100644 --- a/komorebi/src/window_manager.rs +++ b/komorebi/src/window_manager.rs @@ -102,7 +102,7 @@ pub struct WindowManager { pub hotwatch: Hotwatch, pub virtual_desktop_id: Option>, pub has_pending_raise_op: bool, - pub pending_move_op: Option<(usize, usize, usize)>, + pub pending_move_op: Arc>, pub already_moved_window_handles: Arc>>, } @@ -339,7 +339,7 @@ impl WindowManager { mouse_follows_focus: true, hotwatch: Hotwatch::new()?, has_pending_raise_op: false, - pending_move_op: None, + pending_move_op: Arc::new(None), already_moved_window_handles: Arc::new(Mutex::new(HashSet::new())), }) }