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:
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user