diff --git a/komorebi/src/process_command.rs b/komorebi/src/process_command.rs index 92b5a948..ca1d3f6d 100644 --- a/komorebi/src/process_command.rs +++ b/komorebi/src/process_command.rs @@ -499,11 +499,11 @@ impl WindowManager { ); self.focus_monitor(monitor_idx)?; - self.update_focused_workspace(self.mouse_follows_focus)?; + self.update_focused_workspace(self.mouse_follows_focus, true)?; } SocketMessage::FocusMonitorNumber(monitor_idx) => { self.focus_monitor(monitor_idx)?; - self.update_focused_workspace(self.mouse_follows_focus)?; + self.update_focused_workspace(self.mouse_follows_focus, true)?; } SocketMessage::Retile => self.retile_all(false)?, SocketMessage::FlipLayout(layout_flip) => self.flip_layout(layout_flip)?, @@ -914,7 +914,7 @@ impl WindowManager { } } - self.update_focused_workspace(false)?; + self.update_focused_workspace(false, false)?; } SocketMessage::FocusFollowsMouse(mut implementation, enable) => { if !CUSTOM_FFM.load(Ordering::SeqCst) { @@ -1020,7 +1020,7 @@ impl WindowManager { SocketMessage::CompleteConfiguration => { if !INITIAL_CONFIGURATION_LOADED.load(Ordering::SeqCst) { INITIAL_CONFIGURATION_LOADED.store(true, Ordering::SeqCst); - self.update_focused_workspace(false)?; + self.update_focused_workspace(false, false)?; } } SocketMessage::WatchConfiguration(enable) => { @@ -1127,7 +1127,7 @@ impl WindowManager { let resize: Vec> = serde_json::from_reader(file)?; workspace.set_resize_dimensions(resize); - self.update_focused_workspace(false)?; + self.update_focused_workspace(false, false)?; } SocketMessage::Save(ref path) => { let workspace = self.focused_workspace_mut()?; @@ -1150,7 +1150,7 @@ impl WindowManager { let resize: Vec> = serde_json::from_reader(file)?; workspace.set_resize_dimensions(resize); - self.update_focused_workspace(false)?; + self.update_focused_workspace(false, false)?; } SocketMessage::AddSubscriberSocket(ref socket) => { let mut sockets = SUBSCRIPTION_SOCKETS.lock(); @@ -1295,7 +1295,7 @@ impl WindowManager { SocketMessage::ToggleTitleBars => { let current = REMOVE_TITLEBARS.load(Ordering::SeqCst); REMOVE_TITLEBARS.store(!current, Ordering::SeqCst); - self.update_focused_workspace(false)?; + self.update_focused_workspace(false, false)?; } // Deprecated commands SocketMessage::AltFocusHack(_) diff --git a/komorebi/src/process_event.rs b/komorebi/src/process_event.rs index 5d714117..dddddd9f 100644 --- a/komorebi/src/process_event.rs +++ b/komorebi/src/process_event.rs @@ -153,6 +153,10 @@ impl WindowManager { }; for (j, workspace) in monitor.workspaces_mut().iter_mut().enumerate() { + if let WindowManagerEvent::FocusChange(_, window) = event { + let _ = workspace.focus_changed(window.hwnd); + } + let reaped_orphans = workspace.reap_orphans()?; if reaped_orphans.0 > 0 || reaped_orphans.1 > 0 { workspace.update(&work_area, offset)?; @@ -177,13 +181,12 @@ impl WindowManager { } match event { - WindowManagerEvent::Raise(window) => { - window.focus(false)?; + WindowManagerEvent::Raise(_window) => { self.has_pending_raise_op = false; } WindowManagerEvent::Destroy(_, window) | WindowManagerEvent::Unmanage(window) => { self.focused_workspace_mut()?.remove_window(window.hwnd)?; - self.update_focused_workspace(false)?; + self.update_focused_workspace(false, false)?; let mut already_moved_window_handles = self.already_moved_window_handles.lock(); @@ -201,7 +204,7 @@ impl WindowManager { if hide { self.focused_workspace_mut()?.remove_window(window.hwnd)?; - self.update_focused_workspace(false)?; + self.update_focused_workspace(false, false)?; } } WindowManagerEvent::Hide(_, window) => { @@ -242,7 +245,7 @@ impl WindowManager { if hide { self.focused_workspace_mut()?.remove_window(window.hwnd)?; - self.update_focused_workspace(false)?; + self.update_focused_workspace(false, false)?; } let mut already_moved_window_handles = self.already_moved_window_handles.lock(); @@ -250,6 +253,8 @@ impl WindowManager { already_moved_window_handles.remove(&window.hwnd); } WindowManagerEvent::FocusChange(_, window) => { + self.update_focused_workspace(true, false)?; + let workspace = self.focused_workspace_mut()?; if !workspace .floating_windows() @@ -324,14 +329,14 @@ impl WindowManager { match behaviour { WindowContainerBehaviour::Create => { workspace.new_container_for_window(window); - self.update_focused_workspace(false)?; + self.update_focused_workspace(false, false)?; } WindowContainerBehaviour::Append => { workspace .focused_container_mut() .ok_or_else(|| anyhow!("there is no focused container"))? .add_window(window); - self.update_focused_workspace(true)?; + self.update_focused_workspace(true, false)?; } } } @@ -481,11 +486,11 @@ impl WindowManager { // the origin monitor's focused workspace self.focus_monitor(origin_monitor_idx)?; self.focus_workspace(origin_workspace_idx)?; - self.update_focused_workspace(false)?; + self.update_focused_workspace(false, false)?; self.focus_monitor(target_monitor_idx)?; self.focus_workspace(target_workspace_idx)?; - self.update_focused_workspace(false)?; + self.update_focused_workspace(false, false)?; } // Here we handle a simple move on the same monitor which is treated as // a container swap @@ -496,11 +501,12 @@ impl WindowManager { Some(target_idx) => { workspace .swap_containers(focused_container_idx, target_idx); - self.update_focused_workspace(false)?; + self.update_focused_workspace(false, false)?; } None => { self.update_focused_workspace( self.mouse_follows_focus, + false, )?; } } @@ -509,11 +515,12 @@ impl WindowManager { match workspace.container_idx_from_current_point() { Some(target_idx) => { workspace.move_window_to_container(target_idx)?; - self.update_focused_workspace(false)?; + self.update_focused_workspace(false, false)?; } None => { self.update_focused_workspace( self.mouse_follows_focus, + false, )?; } } @@ -560,12 +567,12 @@ impl WindowManager { self.resize_window(edge, sizing, delta, true)?; } - self.update_focused_workspace(false)?; + self.update_focused_workspace(false, false)?; } } } WindowManagerEvent::ForceUpdate(_) => { - self.update_focused_workspace(false)?; + self.update_focused_workspace(false, true)?; } WindowManagerEvent::DisplayChange(..) | WindowManagerEvent::MouseCapture(..) diff --git a/komorebi/src/stackbar.rs b/komorebi/src/stackbar.rs index 33caa7f6..569eed25 100644 --- a/komorebi/src/stackbar.rs +++ b/komorebi/src/stackbar.rs @@ -55,6 +55,8 @@ use komorebi_core::Rect; use crate::window::Window; use crate::windows_api::WindowsApi; +use crate::winevent_listener::event_tx; +use crate::WindowManagerEvent; use crate::DEFAULT_CONTAINER_PADDING; use crate::STACKBAR_FOCUSED_TEXT_COLOUR; use crate::STACKBAR_TAB_BACKGROUND_COLOUR; @@ -234,8 +236,6 @@ impl Stackbar { for (i, window) in windows.iter().enumerate() { if window.hwnd == focused_hwnd { SetTextColor(hdc, COLORREF(focused_text_colour)); - - window.focus(false)?; } else { SetTextColor(hdc, COLORREF(unfocused_text_colour)); } diff --git a/komorebi/src/window_manager.rs b/komorebi/src/window_manager.rs index 7dbda4cb..01e092ea 100644 --- a/komorebi/src/window_manager.rs +++ b/komorebi/src/window_manager.rs @@ -617,7 +617,7 @@ impl WindowManager { // Only re-tile the focused workspace if we need to if should_update_focused_workspace { - self.update_focused_workspace(false)?; + self.update_focused_workspace(false, false)?; } Ok(()) @@ -796,7 +796,11 @@ impl WindowManager { } #[tracing::instrument(skip(self))] - pub fn update_focused_workspace(&mut self, follow_focus: bool) -> Result<()> { + pub fn update_focused_workspace( + &mut self, + follow_focus: bool, + trigger_focus: bool, + ) -> Result<()> { tracing::info!("updating"); let offset = self.work_area_offset; @@ -807,13 +811,19 @@ impl WindowManager { if follow_focus { if let Some(window) = self.focused_workspace()?.maximized_window() { - window.focus(self.mouse_follows_focus)?; - } else if let Some(container) = self.focused_workspace()?.monocle_container() { - if let Some(window) = container.focused_window() { + if trigger_focus { window.focus(self.mouse_follows_focus)?; } + } else if let Some(container) = self.focused_workspace()?.monocle_container() { + if let Some(window) = container.focused_window() { + if trigger_focus { + window.focus(self.mouse_follows_focus)?; + } + } } else if let Ok(window) = self.focused_window_mut() { - window.focus(self.mouse_follows_focus)?; + if trigger_focus { + window.focus(self.mouse_follows_focus)?; + } } else { let desktop_window = Window { hwnd: WindowsApi::desktop_window()?, @@ -841,7 +851,9 @@ impl WindowManager { && self.focused_workspace()?.monocle_container().is_none() { if let Ok(window) = self.focused_window_mut() { - window.focus(self.mouse_follows_focus)?; + if trigger_focus { + window.focus(self.mouse_follows_focus)?; + } } } } @@ -851,7 +863,9 @@ impl WindowManager { if !follow_focus { if let Some(window) = self.focused_workspace()?.maximized_window() { window.restore(); - window.focus(self.mouse_follows_focus)?; + if trigger_focus { + window.focus(self.mouse_follows_focus)?; + } } } @@ -934,7 +948,7 @@ impl WindowManager { workspace.resize_dimensions_mut()[focused_idx] = resize; return if update { - self.update_focused_workspace(false) + self.update_focused_workspace(false, false) } else { Ok(()) }; @@ -1070,7 +1084,7 @@ impl WindowManager { self.swap_monitor_workspaces(focused_monitor_idx, idx)?; - self.update_focused_workspace(mouse_follows_focus) + self.update_focused_workspace(mouse_follows_focus, true) } #[tracing::instrument(skip(self))] @@ -1117,7 +1131,7 @@ impl WindowManager { self.focus_monitor(monitor_idx)?; } - self.update_focused_workspace(self.mouse_follows_focus) + self.update_focused_workspace(self.mouse_follows_focus, true) } #[tracing::instrument(skip(self))] @@ -1134,7 +1148,7 @@ impl WindowManager { monitor.move_container_to_workspace(idx, follow)?; monitor.load_focused_workspace(mouse_follows_focus)?; - self.update_focused_workspace(mouse_follows_focus) + self.update_focused_workspace(mouse_follows_focus, true) } pub fn remove_focused_workspace(&mut self) -> Option { @@ -1163,7 +1177,7 @@ impl WindowManager { } self.focus_monitor(idx)?; - self.update_focused_workspace(mouse_follows_focus) + self.update_focused_workspace(mouse_follows_focus, true) } #[tracing::instrument(skip(self))] @@ -1324,7 +1338,7 @@ impl WindowManager { .id(); if !WindowsApi::monitors_have_same_dpi(a, b)? { - self.update_focused_workspace(self.mouse_follows_focus)?; + self.update_focused_workspace(self.mouse_follows_focus, true)?; } } Some(new_idx) => { @@ -1334,7 +1348,7 @@ impl WindowManager { } } - self.update_focused_workspace(self.mouse_follows_focus) + self.update_focused_workspace(self.mouse_follows_focus, true) } #[tracing::instrument(skip(self))] @@ -1392,7 +1406,7 @@ impl WindowManager { workspace.swap_containers(current_idx, new_idx); workspace.focus_container(new_idx); - self.update_focused_workspace(self.mouse_follows_focus) + self.update_focused_workspace(self.mouse_follows_focus, true) } #[tracing::instrument(skip(self))] @@ -1416,7 +1430,7 @@ impl WindowManager { container.focus_window(next_idx); container.load_focused_window(); - self.update_focused_workspace(self.mouse_follows_focus) + self.update_focused_workspace(self.mouse_follows_focus, true) } #[tracing::instrument(skip(self))] @@ -1453,7 +1467,7 @@ impl WindowManager { }; workspace.move_window_to_container(adjusted_new_index)?; - self.update_focused_workspace(self.mouse_follows_focus)?; + self.update_focused_workspace(self.mouse_follows_focus, false)?; } Ok(()) @@ -1473,7 +1487,7 @@ impl WindowManager { tracing::info!("promoting container"); workspace.promote_container()?; - self.update_focused_workspace(self.mouse_follows_focus) + self.update_focused_workspace(self.mouse_follows_focus, true) } #[tracing::instrument(skip(self))] @@ -1496,7 +1510,7 @@ impl WindowManager { }; workspace.focus_container(target_idx); - self.update_focused_workspace(self.mouse_follows_focus) + self.update_focused_workspace(self.mouse_follows_focus, true) } #[tracing::instrument(skip(self))] @@ -1512,14 +1526,14 @@ impl WindowManager { let workspace = self.focused_workspace_mut()?; workspace.new_container_for_focused_window()?; - self.update_focused_workspace(self.mouse_follows_focus) + self.update_focused_workspace(self.mouse_follows_focus, false) } #[tracing::instrument(skip(self))] pub fn toggle_tiling(&mut self) -> Result<()> { let workspace = self.focused_workspace_mut()?; workspace.set_tile(!*workspace.tile()); - self.update_focused_workspace(false) + self.update_focused_workspace(false, false) } #[tracing::instrument(skip(self))] @@ -1541,7 +1555,7 @@ impl WindowManager { self.float_window()?; } - self.update_focused_workspace(is_floating_window) + self.update_focused_workspace(is_floating_window, true) } #[tracing::instrument(skip(self))] @@ -1583,7 +1597,7 @@ impl WindowManager { Some(_) => self.monocle_off()?, } - self.update_focused_workspace(true) + self.update_focused_workspace(true, true) } #[tracing::instrument(skip(self))] @@ -1613,7 +1627,7 @@ impl WindowManager { Some(_) => self.unmaximize_window()?, } - self.update_focused_workspace(true) + self.update_focused_workspace(true, false) } #[tracing::instrument(skip(self))] @@ -1672,7 +1686,7 @@ impl WindowManager { } } - self.update_focused_workspace(false) + self.update_focused_workspace(false, false) } #[tracing::instrument(skip(self))] @@ -1697,7 +1711,7 @@ impl WindowManager { } workspace.set_layout(Layout::Default(layout)); - self.update_focused_workspace(self.mouse_follows_focus) + self.update_focused_workspace(self.mouse_follows_focus, false) } #[tracing::instrument(skip(self))] @@ -1720,7 +1734,7 @@ impl WindowManager { Layout::Custom(_) => {} } - self.update_focused_workspace(self.mouse_follows_focus) + self.update_focused_workspace(self.mouse_follows_focus, false) } #[tracing::instrument(skip(self))] @@ -1750,7 +1764,7 @@ impl WindowManager { workspace.set_layout(Layout::Custom(layout)); workspace.set_layout_flip(None); - self.update_focused_workspace(self.mouse_follows_focus) + self.update_focused_workspace(self.mouse_follows_focus, false) } #[tracing::instrument(skip(self))] @@ -1765,7 +1779,7 @@ impl WindowManager { workspace.set_workspace_padding(Option::from(sizing.adjust_by(padding, adjustment))); - self.update_focused_workspace(false) + self.update_focused_workspace(false, false) } #[tracing::instrument(skip(self))] @@ -1780,7 +1794,7 @@ impl WindowManager { workspace.set_container_padding(Option::from(sizing.adjust_by(padding, adjustment))); - self.update_focused_workspace(false) + self.update_focused_workspace(false, false) } #[tracing::instrument(skip(self))] @@ -1802,7 +1816,7 @@ impl WindowManager { workspace.set_tile(tile); - self.update_focused_workspace(false) + self.update_focused_workspace(false, false) } #[tracing::instrument(skip(self))] @@ -1846,7 +1860,7 @@ impl WindowManager { workspace.update(&work_area, offset)?; Ok(()) } else { - Ok(self.update_focused_workspace(false)?) + Ok(self.update_focused_workspace(false, false)?) } } @@ -1896,7 +1910,7 @@ impl WindowManager { workspace.update(&work_area, offset)?; Ok(()) } else { - Ok(self.update_focused_workspace(false)?) + Ok(self.update_focused_workspace(false, false)?) } } @@ -1937,7 +1951,7 @@ impl WindowManager { workspace.update(&work_area, offset)?; Ok(()) } else { - Ok(self.update_focused_workspace(false)?) + Ok(self.update_focused_workspace(false, false)?) } } @@ -1978,7 +1992,7 @@ impl WindowManager { workspace.update(&work_area, offset)?; Ok(()) } else { - Ok(self.update_focused_workspace(false)?) + Ok(self.update_focused_workspace(false, false)?) } } @@ -2023,7 +2037,7 @@ impl WindowManager { workspace.update(&work_area, offset)?; Ok(()) } else { - Ok(self.update_focused_workspace(false)?) + Ok(self.update_focused_workspace(false, false)?) } } @@ -2090,7 +2104,7 @@ impl WindowManager { workspace.set_workspace_padding(Option::from(size)); - self.update_focused_workspace(false) + self.update_focused_workspace(false, false) } #[tracing::instrument(skip(self))] @@ -2139,7 +2153,7 @@ impl WindowManager { workspace.set_container_padding(Option::from(size)); - self.update_focused_workspace(false) + self.update_focused_workspace(false, false) } pub fn focused_monitor_size(&self) -> Result { @@ -2243,7 +2257,7 @@ impl WindowManager { monitor.focus_workspace(idx)?; monitor.load_focused_workspace(mouse_follows_focus)?; - self.update_focused_workspace(false) + self.update_focused_workspace(false, true) } #[tracing::instrument(skip(self))] @@ -2275,7 +2289,7 @@ impl WindowManager { monitor.focus_workspace(monitor.new_workspace_idx())?; monitor.load_focused_workspace(mouse_follows_focus)?; - self.update_focused_workspace(self.mouse_follows_focus) + self.update_focused_workspace(self.mouse_follows_focus, false) } pub fn focused_container(&self) -> Result<&Container> { diff --git a/komorebi/src/workspace.rs b/komorebi/src/workspace.rs index 8ddae28d..20e14fbb 100644 --- a/komorebi/src/workspace.rs +++ b/komorebi/src/workspace.rs @@ -357,6 +357,33 @@ impl Workspace { Ok(()) } + // focus_changed performs updates in response to the fact that a focus + // change event has occurred. The focus change is assumed to be valid, and + // should not result in a new focus change - the intent here is to update + // focus-reactive elements, such as the stackbar. + pub fn focus_changed(&mut self, hwnd: isize) -> Result<()> { + if !self.tile() { + return Ok(()); + } + + let containers = self.containers_mut(); + + for container in containers.iter_mut() { + let container_windows = container.windows().clone(); + let container_topbar = container.stackbar().clone(); + + if let Some(idx) = container.idx_for_window(hwnd) { + container.focus_window(idx); + container.restore(); + } + + if let Some(stackbar) = container_topbar { + stackbar.update(&container_windows, hwnd)?; + } + } + Ok(()) + } + pub fn reap_orphans(&mut self) -> Result<(usize, usize)> { let mut hwnds = vec![]; let mut floating_hwnds = vec![];