diff --git a/komorebi/src/process_command.rs b/komorebi/src/process_command.rs index f6f3c66d..2e655e55 100644 --- a/komorebi/src/process_command.rs +++ b/komorebi/src/process_command.rs @@ -148,6 +148,15 @@ impl WindowManager { self.set_workspace_layout(monitor_idx, workspace_idx, layout)?; } SocketMessage::FocusWorkspaceNumber(workspace_idx) => { + // This is to ensure that even on an empty workspace on a secondary monitor, the + // secondary monitor where the cursor is focused will be used as the target for + // the workspace switch op + let monitor_idx = self.monitor_idx_from_current_pos().ok_or_else(|| { + anyhow!("there is no monitor associated with the current cursor position") + })?; + + self.focus_monitor(monitor_idx)?; + self.focus_workspace(workspace_idx)?; } SocketMessage::Stop => { diff --git a/komorebi/src/window_manager.rs b/komorebi/src/window_manager.rs index 50422a77..86f3c8ee 100644 --- a/komorebi/src/window_manager.rs +++ b/komorebi/src/window_manager.rs @@ -1014,6 +1014,18 @@ impl WindowManager { None } + pub fn monitor_idx_from_current_pos(&mut self) -> Option { + let hmonitor = WindowsApi::monitor_from_point(WindowsApi::cursor_pos().ok()?); + + for (i, monitor) in self.monitors().iter().enumerate() { + if monitor.id() == hmonitor { + return Option::from(i); + } + } + + None + } + pub fn focused_workspace(&self) -> Result<&Workspace> { self.focused_monitor() .ok_or_else(|| anyhow!("there is no monitor"))? diff --git a/komorebi/src/windows_api.rs b/komorebi/src/windows_api.rs index abed190c..7e5ffcd9 100644 --- a/komorebi/src/windows_api.rs +++ b/komorebi/src/windows_api.rs @@ -23,6 +23,7 @@ use bindings::Windows::Win32::Graphics::Dwm::DWM_CLOAKED_INHERITED; use bindings::Windows::Win32::Graphics::Dwm::DWM_CLOAKED_SHELL; use bindings::Windows::Win32::Graphics::Gdi::EnumDisplayMonitors; use bindings::Windows::Win32::Graphics::Gdi::GetMonitorInfoW; +use bindings::Windows::Win32::Graphics::Gdi::MonitorFromPoint; use bindings::Windows::Win32::Graphics::Gdi::MonitorFromWindow; use bindings::Windows::Win32::Graphics::Gdi::HDC; use bindings::Windows::Win32::Graphics::Gdi::HMONITOR; @@ -227,6 +228,12 @@ impl WindowsApi { unsafe { MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST) }.0 } + pub fn monitor_from_point(point: POINT) -> isize { + // MONITOR_DEFAULTTONEAREST ensures that the return value will never be NULL + // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-monitorfromwindow + unsafe { MonitorFromPoint(point, MONITOR_DEFAULTTONEAREST) }.0 + } + pub fn position_window(hwnd: HWND, layout: &Rect, top: bool) -> Result<()> { let flags = SetWindowPosition::NO_ACTIVATE;