Skip to content

Commit

Permalink
Windows: cache custom cursors (#3293)
Browse files Browse the repository at this point in the history
  • Loading branch information
daxpedda authored Jan 5, 2024
1 parent 37b6243 commit 787b2d7
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 25 deletions.
50 changes: 30 additions & 20 deletions src/platform_impl/windows/icon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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<RaiiCursor>),
}

impl Default for SelectedCursor {
Expand All @@ -178,23 +181,14 @@ impl Default for SelectedCursor {
}
}

#[derive(Clone, Debug)]
pub struct WinCursor {
inner: Arc<RaiiCursor>,
#[derive(Clone, Debug, Hash, Eq, PartialEq)]
pub enum WinCursor {
Cursor(Arc<RaiiCursor>),
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<Self, io::Error> {
fn new(image: &CursorImage) -> Result<Self, io::Error> {
let mut bgra = image.rgba.clone();
bgra.chunks_exact_mut(4).for_each(|chunk| chunk.swap(0, 2));

Expand Down Expand Up @@ -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<T>(cursor: OnlyCursorImageBuilder, _: &EventLoopWindowTarget<T>) -> 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,
}

Expand All @@ -254,3 +258,9 @@ impl Drop for RaiiCursor {
unsafe { DestroyCursor(self.handle) };
}
}

impl RaiiCursor {
pub fn as_raw_handle(&self) -> HICON {
self.handle
}
}
2 changes: 1 addition & 1 deletion src/platform_impl/windows/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
8 changes: 4 additions & 4 deletions src/platform_impl/windows/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
};
Expand Down

0 comments on commit 787b2d7

Please sign in to comment.