mirror of
https://github.com/rust-windowing/winit.git
synced 2026-09-03 07:10:05 -04:00
windows: add locked cursor
This commit is contained in:
@@ -43,6 +43,7 @@ changelog entry.
|
|||||||
### Added
|
### Added
|
||||||
|
|
||||||
- On Windows, add `IconExtWindows::from_resource_name`.
|
- On Windows, add `IconExtWindows::from_resource_name`.
|
||||||
|
- On Windows, add `CursorGrabMode::Locked`.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use std::{io, mem, ptr};
|
|||||||
|
|
||||||
use crate::utils::Lazy;
|
use crate::utils::Lazy;
|
||||||
use windows_sys::core::{HRESULT, PCWSTR};
|
use windows_sys::core::{HRESULT, PCWSTR};
|
||||||
use windows_sys::Win32::Foundation::{BOOL, HANDLE, HMODULE, HWND, RECT};
|
use windows_sys::Win32::Foundation::{BOOL, HANDLE, HMODULE, HWND, POINT, RECT};
|
||||||
use windows_sys::Win32::Graphics::Gdi::{ClientToScreen, HMONITOR};
|
use windows_sys::Win32::Graphics::Gdi::{ClientToScreen, HMONITOR};
|
||||||
use windows_sys::Win32::System::LibraryLoader::{GetProcAddress, LoadLibraryA};
|
use windows_sys::Win32::System::LibraryLoader::{GetProcAddress, LoadLibraryA};
|
||||||
use windows_sys::Win32::System::SystemServices::IMAGE_DOS_HEADER;
|
use windows_sys::Win32::System::SystemServices::IMAGE_DOS_HEADER;
|
||||||
@@ -17,9 +17,9 @@ use windows_sys::Win32::UI::HiDpi::{
|
|||||||
use windows_sys::Win32::UI::Input::KeyboardAndMouse::GetActiveWindow;
|
use windows_sys::Win32::UI::Input::KeyboardAndMouse::GetActiveWindow;
|
||||||
use windows_sys::Win32::UI::Input::Pointer::{POINTER_INFO, POINTER_PEN_INFO, POINTER_TOUCH_INFO};
|
use windows_sys::Win32::UI::Input::Pointer::{POINTER_INFO, POINTER_PEN_INFO, POINTER_TOUCH_INFO};
|
||||||
use windows_sys::Win32::UI::WindowsAndMessaging::{
|
use windows_sys::Win32::UI::WindowsAndMessaging::{
|
||||||
ClipCursor, GetClientRect, GetClipCursor, GetSystemMetrics, GetWindowPlacement, GetWindowRect,
|
ClipCursor, GetClientRect, GetClipCursor, GetCursorPos, GetSystemMetrics, GetWindowPlacement,
|
||||||
IsIconic, ShowCursor, IDC_APPSTARTING, IDC_ARROW, IDC_CROSS, IDC_HAND, IDC_HELP, IDC_IBEAM,
|
GetWindowRect, IsIconic, ShowCursor, IDC_APPSTARTING, IDC_ARROW, IDC_CROSS, IDC_HAND, IDC_HELP,
|
||||||
IDC_NO, IDC_SIZEALL, IDC_SIZENESW, IDC_SIZENS, IDC_SIZENWSE, IDC_SIZEWE, IDC_WAIT,
|
IDC_IBEAM, IDC_NO, IDC_SIZEALL, IDC_SIZENESW, IDC_SIZENS, IDC_SIZENWSE, IDC_SIZEWE, IDC_WAIT,
|
||||||
SM_CXVIRTUALSCREEN, SM_CYVIRTUALSCREEN, SM_XVIRTUALSCREEN, SM_YVIRTUALSCREEN, SW_MAXIMIZE,
|
SM_CXVIRTUALSCREEN, SM_CYVIRTUALSCREEN, SM_XVIRTUALSCREEN, SM_YVIRTUALSCREEN, SW_MAXIMIZE,
|
||||||
WINDOWPLACEMENT,
|
WINDOWPLACEMENT,
|
||||||
};
|
};
|
||||||
@@ -99,6 +99,13 @@ pub fn set_cursor_hidden(hidden: bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_cursor_position() -> Result<POINT, io::Error> {
|
||||||
|
unsafe {
|
||||||
|
let mut point: POINT = mem::zeroed();
|
||||||
|
win_to_err(GetCursorPos(&mut point)).map(|_| point)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_cursor_clip() -> Result<RECT, io::Error> {
|
pub fn get_cursor_clip() -> Result<RECT, io::Error> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut rect: RECT = mem::zeroed();
|
let mut rect: RECT = mem::zeroed();
|
||||||
|
|||||||
@@ -428,14 +428,6 @@ impl Window {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_cursor_grab(&self, mode: CursorGrabMode) -> Result<(), ExternalError> {
|
pub fn set_cursor_grab(&self, mode: CursorGrabMode) -> Result<(), ExternalError> {
|
||||||
let confine = match mode {
|
|
||||||
CursorGrabMode::None => false,
|
|
||||||
CursorGrabMode::Confined => true,
|
|
||||||
CursorGrabMode::Locked => {
|
|
||||||
return Err(ExternalError::NotSupported(NotSupportedError::new()))
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let window = self.window;
|
let window = self.window;
|
||||||
let window_state = Arc::clone(&self.window_state);
|
let window_state = Arc::clone(&self.window_state);
|
||||||
let (tx, rx) = channel();
|
let (tx, rx) = channel();
|
||||||
@@ -446,7 +438,10 @@ impl Window {
|
|||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.mouse
|
.mouse
|
||||||
.set_cursor_flags(window, |f| f.set(CursorFlags::GRABBED, confine))
|
.set_cursor_flags(window, |f| {
|
||||||
|
f.set(CursorFlags::GRABBED, mode != CursorGrabMode::None);
|
||||||
|
f.set(CursorFlags::LOCKED, mode == CursorGrabMode::Locked);
|
||||||
|
})
|
||||||
.map_err(|e| ExternalError::Os(os_error!(e)));
|
.map_err(|e| ExternalError::Os(os_error!(e)));
|
||||||
let _ = tx.send(result);
|
let _ = tx.send(result);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ bitflags! {
|
|||||||
const GRABBED = 1 << 0;
|
const GRABBED = 1 << 0;
|
||||||
const HIDDEN = 1 << 1;
|
const HIDDEN = 1 << 1;
|
||||||
const IN_WINDOW = 1 << 2;
|
const IN_WINDOW = 1 << 2;
|
||||||
|
const LOCKED = 1 << 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bitflags! {
|
bitflags! {
|
||||||
@@ -485,7 +486,22 @@ impl CursorFlags {
|
|||||||
if util::is_focused(window) {
|
if util::is_focused(window) {
|
||||||
let cursor_clip = match self.contains(CursorFlags::GRABBED) {
|
let cursor_clip = match self.contains(CursorFlags::GRABBED) {
|
||||||
true => {
|
true => {
|
||||||
if self.contains(CursorFlags::HIDDEN) {
|
if self.contains(CursorFlags::LOCKED) {
|
||||||
|
if let Ok(pos) = util::get_cursor_position() {
|
||||||
|
Some(RECT {
|
||||||
|
left: pos.x,
|
||||||
|
right: pos.x + 1,
|
||||||
|
top: pos.y,
|
||||||
|
bottom: pos.y + 1,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// If lock is applied while the cursor is not available, lock it to the
|
||||||
|
// middle of the window.
|
||||||
|
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 if self.contains(CursorFlags::HIDDEN) {
|
||||||
// Confine the cursor to the center of the window if the cursor is hidden.
|
// Confine the cursor to the center of the window if the cursor is hidden.
|
||||||
// This avoids problems with the cursor activating
|
// This avoids problems with the cursor activating
|
||||||
// the taskbar if the window borders or overlaps that.
|
// the taskbar if the window borders or overlaps that.
|
||||||
|
|||||||
@@ -1707,8 +1707,7 @@ pub enum CursorGrabMode {
|
|||||||
///
|
///
|
||||||
/// ## Platform-specific
|
/// ## Platform-specific
|
||||||
///
|
///
|
||||||
/// - **X11 / Windows:** Not implemented. Always returns [`ExternalError::NotSupported`] for
|
/// - **X11:** Not implemented. Always returns [`ExternalError::NotSupported`] for now.
|
||||||
/// now.
|
|
||||||
/// - **iOS / Android:** Always returns an [`ExternalError::NotSupported`].
|
/// - **iOS / Android:** Always returns an [`ExternalError::NotSupported`].
|
||||||
Locked,
|
Locked,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user