From ff11721dcfba7c551f823e7091115b085b7ffab3 Mon Sep 17 00:00:00 2001 From: Eero Lehtinen Date: Sat, 18 Nov 2023 01:21:38 +0200 Subject: [PATCH] Use separate cursor and icon types to use correct win functions --- src/platform_impl/windows/icon.rs | 75 ++++++++++++++++++++--------- src/platform_impl/windows/window.rs | 6 +-- 2 files changed, 55 insertions(+), 26 deletions(-) diff --git a/src/platform_impl/windows/icon.rs b/src/platform_impl/windows/icon.rs index 7714e36696a..12398cd1f42 100644 --- a/src/platform_impl/windows/icon.rs +++ b/src/platform_impl/windows/icon.rs @@ -7,8 +7,9 @@ use windows_sys::{ Foundation::HWND, Graphics::Gdi::{CreateBitmap, CreateCompatibleBitmap, GetDC, ReleaseDC, SetBitmapBits}, UI::WindowsAndMessaging::{ - CreateIcon, CreateIconIndirect, DestroyIcon, LoadImageW, SendMessageW, HICON, ICONINFO, - ICON_BIG, ICON_SMALL, IMAGE_ICON, LR_DEFAULTSIZE, LR_LOADFROMFILE, WM_SETICON, + CreateIcon, CreateIconIndirect, DestroyCursor, DestroyIcon, LoadImageW, SendMessageW, + HCURSOR, HICON, ICONINFO, ICON_BIG, ICON_SMALL, IMAGE_ICON, LR_DEFAULTSIZE, + LR_LOADFROMFILE, WM_SETICON, }, }, }; @@ -138,11 +139,51 @@ impl WinIcon { } } - pub fn from_handle(handle: HICON) -> Self { + fn from_handle(handle: HICON) -> Self { Self { inner: Arc::new(RaiiIcon { handle }), } } +} + +impl Drop for RaiiIcon { + fn drop(&mut self) { + unsafe { DestroyIcon(self.handle) }; + } +} + +impl fmt::Debug for WinIcon { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + (*self.inner).fmt(formatter) + } +} + +pub fn unset_for_window(hwnd: HWND, icon_type: IconType) { + unsafe { + SendMessageW(hwnd, WM_SETICON, icon_type as usize, 0); + } +} + +#[derive(Debug)] +struct RaiiCursor { + handle: HCURSOR, +} + +#[derive(Clone, Debug)] +pub struct WinCursor { + inner: Arc, +} + +impl WinCursor { + pub fn as_raw_handle(&self) -> HICON { + self.inner.handle + } + + pub fn from_handle(handle: HCURSOR) -> Self { + Self { + inner: Arc::new(RaiiCursor { handle }), + } + } pub fn new_cursor(image: &CursorImage) -> Self { let mut bgra = image.rgba.clone(); @@ -192,14 +233,20 @@ impl WinIcon { panic!("Failed to create icon"); } - WinIcon::from_handle(handle) + Self::from_handle(handle) + } +} + +impl Drop for RaiiCursor { + fn drop(&mut self) { + unsafe { DestroyCursor(self.handle) }; } } #[derive(Debug, Clone)] pub enum SelectedCursor { Named(CursorIcon), - Custom(WinIcon), + Custom(WinCursor), } impl Default for SelectedCursor { @@ -207,21 +254,3 @@ impl Default for SelectedCursor { Self::Named(Default::default()) } } - -impl Drop for RaiiIcon { - fn drop(&mut self) { - unsafe { DestroyIcon(self.handle) }; - } -} - -impl fmt::Debug for WinIcon { - fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { - (*self.inner).fmt(formatter) - } -} - -pub fn unset_for_window(hwnd: HWND, icon_type: IconType) { - unsafe { - SendMessageW(hwnd, WM_SETICON, icon_type as usize, 0); - } -} diff --git a/src/platform_impl/windows/window.rs b/src/platform_impl/windows/window.rs index 16e7ec7a488..e59d2e9b023 100644 --- a/src/platform_impl/windows/window.rs +++ b/src/platform_impl/windows/window.rs @@ -67,13 +67,13 @@ use crate::{ dpi::{dpi_to_scale_factor, enable_non_client_dpi_scaling, hwnd_dpi}, drop_handler::FileDropHandler, event_loop::{self, EventLoopWindowTarget, DESTROY_MSG_ID}, - icon::{self, IconType}, + icon::{self, IconType, WinCursor}, ime::ImeContext, keyboard::KeyEventBuilder, monitor::{self, MonitorHandle}, util, window_state::{CursorFlags, SavedWindow, WindowFlags, WindowState}, - Fullscreen, PlatformSpecificWindowBuilderAttributes, SelectedCursor, WinIcon, WindowId, + Fullscreen, PlatformSpecificWindowBuilderAttributes, SelectedCursor, WindowId, }, window::{ CursorGrabMode, CursorIcon, ImePurpose, ResizeDirection, Theme, UserAttentionType, @@ -406,7 +406,7 @@ impl Window { #[inline] pub fn set_custom_cursor(&self, cursor: CustomCursor) { - let new_cursor = WinIcon::new_cursor(&cursor.inner); + let new_cursor = WinCursor::new_cursor(&cursor.inner); let handle = new_cursor.as_raw_handle(); self.window_state_lock().mouse.selected_cursor = SelectedCursor::Custom(new_cursor); self.thread_executor.execute_in_thread(move || unsafe {