Detailed changes
@@ -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(
@@ -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,
+ )
+ })
+}
@@ -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()