Windows: Better cursor (#9451)

Moved `SetCursor` calls to `WM_SETCURSOR`, which occurs when OS is
requires set cursor.

Release Notes:

- N/A
This commit is contained in:
白山風露
2024-03-25 10:06:52 -07:00
committed by GitHub
parent 053d05f6f5
commit 5361a4d72d
3 changed files with 60 additions and 29 deletions
+5 -27
View File
@@ -62,6 +62,8 @@ pub(crate) struct WindowsPlatformInner {
pub(crate) dispatch_event: OwnedHandle,
pub(crate) settings: RefCell<WindowsPlatformSystemSettings>,
pub icon: HICON,
// NOTE: standard cursor handles don't need to close.
pub(crate) current_cursor: Cell<HCURSOR>,
}
impl WindowsPlatformInner {
@@ -157,6 +159,7 @@ impl WindowsPlatform {
let raw_window_handles = RwLock::new(SmallVec::new());
let settings = RefCell::new(WindowsPlatformSystemSettings::new());
let icon = load_icon().unwrap_or_default();
let current_cursor = Cell::new(load_cursor(CursorStyle::Arrow));
let inner = Rc::new(WindowsPlatformInner {
background_executor,
foreground_executor,
@@ -167,6 +170,7 @@ impl WindowsPlatform {
dispatch_event,
settings,
icon,
current_cursor,
});
Self { inner }
}
@@ -646,29 +650,7 @@ impl Platform for WindowsPlatform {
}
fn set_cursor_style(&self, style: CursorStyle) {
let handle = match style {
CursorStyle::IBeam | CursorStyle::IBeamCursorForVerticalLayout => unsafe {
load_cursor(IDC_IBEAM)
},
CursorStyle::Crosshair => unsafe { load_cursor(IDC_CROSS) },
CursorStyle::PointingHand | CursorStyle::DragLink => unsafe { load_cursor(IDC_HAND) },
CursorStyle::ResizeLeft | CursorStyle::ResizeRight | CursorStyle::ResizeLeftRight => unsafe {
load_cursor(IDC_SIZEWE)
},
CursorStyle::ResizeUp | CursorStyle::ResizeDown | CursorStyle::ResizeUpDown => unsafe {
load_cursor(IDC_SIZENS)
},
CursorStyle::OperationNotAllowed => unsafe { load_cursor(IDC_NO) },
_ => unsafe { load_cursor(IDC_ARROW) },
};
if handle.is_err() {
log::error!(
"Error loading cursor image: {}",
std::io::Error::last_os_error()
);
return;
}
let _ = unsafe { SetCursor(HCURSOR(handle.unwrap().0)) };
self.inner.current_cursor.set(load_cursor(style));
}
// todo(windows)
@@ -773,10 +755,6 @@ impl Drop for WindowsPlatform {
}
}
unsafe fn load_cursor(name: PCWSTR) -> Result<HANDLE> {
LoadImageW(None, name, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED).map_err(|e| anyhow!(e))
}
fn open_target(target: &str) {
unsafe {
let ret = ShellExecuteW(
+36 -1
View File
@@ -1,6 +1,10 @@
use util::ResultExt;
use std::sync::OnceLock;
use ::util::ResultExt;
use windows::Win32::{Foundation::*, System::Threading::*, UI::WindowsAndMessaging::*};
use crate::*;
pub(crate) trait HiLoWord {
fn hiword(&self) -> u16;
fn loword(&self) -> u16;
@@ -100,3 +104,34 @@ pub(crate) fn create_event() -> windows::core::Result<OwnedHandle> {
pub(crate) fn windows_credentials_target_name(url: &str) -> String {
format!("zed:url={}", url)
}
pub(crate) fn load_cursor(style: CursorStyle) -> HCURSOR {
static ARROW: OnceLock<HCURSOR> = OnceLock::new();
static IBEAM: OnceLock<HCURSOR> = OnceLock::new();
static CROSS: OnceLock<HCURSOR> = OnceLock::new();
static HAND: OnceLock<HCURSOR> = OnceLock::new();
static SIZEWE: OnceLock<HCURSOR> = OnceLock::new();
static SIZENS: OnceLock<HCURSOR> = OnceLock::new();
static NO: OnceLock<HCURSOR> = OnceLock::new();
let (lock, name) = match style {
CursorStyle::IBeam | CursorStyle::IBeamCursorForVerticalLayout => (&IBEAM, IDC_IBEAM),
CursorStyle::Crosshair => (&CROSS, IDC_CROSS),
CursorStyle::PointingHand | CursorStyle::DragLink => (&HAND, IDC_HAND),
CursorStyle::ResizeLeft | CursorStyle::ResizeRight | CursorStyle::ResizeLeftRight => {
(&SIZEWE, IDC_SIZEWE)
}
CursorStyle::ResizeUp | CursorStyle::ResizeDown | CursorStyle::ResizeUpDown => {
(&SIZENS, IDC_SIZENS)
}
CursorStyle::OperationNotAllowed => (&NO, IDC_NO),
_ => (&ARROW, IDC_ARROW),
};
*lock.get_or_init(|| {
HCURSOR(
unsafe { LoadImageW(None, name, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED) }
.log_err()
.unwrap_or_default()
.0,
)
})
}
+19 -1
View File
@@ -228,6 +228,7 @@ impl WindowsWindowInner {
WM_IME_STARTCOMPOSITION => self.handle_ime_position(),
WM_IME_COMPOSITION => self.handle_ime_composition(lparam),
WM_IME_CHAR => self.handle_ime_char(wparam),
WM_SETCURSOR => self.handle_set_cursor(lparam),
_ => None,
};
if let Some(n) = handled {
@@ -1071,6 +1072,24 @@ impl WindowsWindowInner {
None
}
fn handle_set_cursor(&self, lparam: LPARAM) -> Option<isize> {
if matches!(
lparam.loword() as u32,
HTLEFT
| HTRIGHT
| HTTOP
| HTTOPLEFT
| HTTOPRIGHT
| HTBOTTOM
| HTBOTTOMLEFT
| HTBOTTOMRIGHT
) {
return None;
}
unsafe { SetCursor(self.platform_inner.current_cursor.get()) };
Some(1)
}
}
#[derive(Default)]
@@ -1572,7 +1591,6 @@ fn register_wnd_class(icon_handle: HICON) -> PCWSTR {
let wc = WNDCLASSW {
lpfnWndProc: Some(wnd_proc),
hIcon: icon_handle,
hCursor: unsafe { LoadCursorW(None, IDC_ARROW).ok().unwrap() },
lpszClassName: PCWSTR(CLASS_NAME.as_ptr()),
style: CS_HREDRAW | CS_VREDRAW,
..Default::default()