From eabd472236632360ccb68aaf17e00424ac1841a6 Mon Sep 17 00:00:00 2001 From: Fredrik Fornwall Date: Sun, 3 Mar 2024 23:21:06 +0100 Subject: [PATCH] fix(windows): configure hidden and grabbed cursor This fixes issues where a hidden and grabbed cursor could leave the window and become visible on top of the windows taskbar (and potentially leave the window altogether if the taskbar is clicked) under at least two occasions: - When a window is overlapping the taskbar. - When a window is maximized and Automatically hide the taskbar has been enabled. This approach of confining the cursor to the center of the window is used in SDL. --- src/changelog/unreleased.md | 1 + src/platform_impl/windows/window_state.rs | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/changelog/unreleased.md b/src/changelog/unreleased.md index 870e599715..9ad14dffad 100644 --- a/src/changelog/unreleased.md +++ b/src/changelog/unreleased.md @@ -40,3 +40,4 @@ - **Breaking:** Removed `EventLoopBuilder::with_user_event`, the functionality is now available in `EventLoop::with_user_event`. - Add `Window::default_attributes` to get default `WindowAttributes`. - `log` has been replaced with `tracing`. The old behavior can be emulated by setting the `log` feature on the `tracing` crate. +- On Windows, confine cursor to center of window when grabbed and hidden. diff --git a/src/platform_impl/windows/window_state.rs b/src/platform_impl/windows/window_state.rs index a37a2383aa..85b70ba856 100644 --- a/src/platform_impl/windows/window_state.rs +++ b/src/platform_impl/windows/window_state.rs @@ -510,7 +510,22 @@ impl CursorFlags { if util::is_focused(window) { let cursor_clip = match self.contains(CursorFlags::GRABBED) { - true => Some(client_rect), + true => { + if self.contains(CursorFlags::HIDDEN) { + // Confine the cursor to the center of the window if the cursor is hidden. This avoids + // problems with the cursor activating the taskbar if the window borders or overlaps that. + let cx = (client_rect.left + client_rect.right) / 2; + let cy = (client_rect.top + client_rect.bottom) / 2; + Some(RECT { + left: cx, + right: cx + 1, + top: cy, + bottom: cy + 1, + }) + } else { + Some(client_rect) + } + } false => None, };