From a50581f95ff8803ddd0d130c331819b3a4ecb9c0 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Sat, 23 Dec 2023 15:53:40 +0100 Subject: [PATCH] Windows: cache custom cursors --- src/platform_impl/windows/icon.rs | 50 +++++++++++++++++------------ src/platform_impl/windows/mod.rs | 2 +- src/platform_impl/windows/window.rs | 8 ++--- 3 files changed, 35 insertions(+), 25 deletions(-) diff --git a/src/platform_impl/windows/icon.rs b/src/platform_impl/windows/icon.rs index 70ce7c1ac3..3bfba7b528 100644 --- a/src/platform_impl/windows/icon.rs +++ b/src/platform_impl/windows/icon.rs @@ -17,9 +17,12 @@ use windows_sys::{ }; use crate::icon::*; -use crate::{cursor::CursorImage, dpi::PhysicalSize}; +use crate::{ + cursor::{CursorImage, OnlyCursorImageBuilder}, + dpi::PhysicalSize, +}; -use super::util; +use super::{util, EventLoopWindowTarget}; impl Pixel { fn convert_to_bgra(&mut self) { @@ -169,7 +172,7 @@ pub fn unset_for_window(hwnd: HWND, icon_type: IconType) { #[derive(Debug, Clone)] pub enum SelectedCursor { Named(CursorIcon), - Custom(WinCursor), + Custom(Arc), } impl Default for SelectedCursor { @@ -178,23 +181,14 @@ impl Default for SelectedCursor { } } -#[derive(Clone, Debug)] -pub struct WinCursor { - inner: Arc, +#[derive(Clone, Debug, Hash, Eq, PartialEq)] +pub enum WinCursor { + Cursor(Arc), + Failed, } impl WinCursor { - pub fn as_raw_handle(&self) -> HICON { - self.inner.handle - } - - fn from_handle(handle: HCURSOR) -> Self { - Self { - inner: Arc::new(RaiiCursor { handle }), - } - } - - pub(crate) fn new(image: &CursorImage) -> Result { + fn new(image: &CursorImage) -> Result { let mut bgra = image.rgba.clone(); bgra.chunks_exact_mut(4).for_each(|chunk| chunk.swap(0, 2)); @@ -239,13 +233,23 @@ impl WinCursor { return Err(io::Error::last_os_error()); } - Ok(Self::from_handle(handle)) + Ok(Self::Cursor(Arc::new(RaiiCursor { handle }))) + } + } + + pub(crate) fn build(cursor: OnlyCursorImageBuilder, _: &EventLoopWindowTarget) -> Self { + match Self::new(&cursor.0) { + Ok(cursor) => cursor, + Err(err) => { + log::warn!("Failed to create custom cursor: {err}"); + Self::Failed + } } } } -#[derive(Debug)] -struct RaiiCursor { +#[derive(Debug, Hash, Eq, PartialEq)] +pub struct RaiiCursor { handle: HCURSOR, } @@ -254,3 +258,9 @@ impl Drop for RaiiCursor { unsafe { DestroyCursor(self.handle) }; } } + +impl RaiiCursor { + pub fn as_raw_handle(&self) -> HICON { + self.handle + } +} diff --git a/src/platform_impl/windows/mod.rs b/src/platform_impl/windows/mod.rs index 270a2f86db..7cce3a76c8 100644 --- a/src/platform_impl/windows/mod.rs +++ b/src/platform_impl/windows/mod.rs @@ -16,8 +16,8 @@ pub(crate) use self::{ window::Window, }; +pub(crate) use self::icon::WinCursor as PlatformCustomCursor; pub use self::icon::WinIcon as PlatformIcon; -pub(crate) use crate::cursor::OnlyCursorImage as PlatformCustomCursor; pub(crate) use crate::cursor::OnlyCursorImageBuilder as PlatformCustomCursorBuilder; use crate::platform_impl::Fullscreen; diff --git a/src/platform_impl/windows/window.rs b/src/platform_impl/windows/window.rs index b4995ca4a0..44332f35b9 100644 --- a/src/platform_impl/windows/window.rs +++ b/src/platform_impl/windows/window.rs @@ -407,10 +407,10 @@ impl Window { }); } Cursor::Custom(cursor) => { - let new_cursor = match WinCursor::new(&cursor.inner.0) { - Ok(cursor) => cursor, - Err(err) => { - warn!("Failed to create custom cursor: {err}"); + let new_cursor = match cursor.inner { + WinCursor::Cursor(cursor) => cursor, + WinCursor::Failed => { + warn!("Requested to apply failed cursor"); return; } };