From 098fd5d602ee3b20372048db35aa3de432884aaa Mon Sep 17 00:00:00 2001 From: David Hewitt <1939362+davidhewitt@users.noreply.github.com> Date: Sat, 7 Mar 2020 19:42:21 +0000 Subject: [PATCH] Add ability to create Icons from embedded resources on Windows (#1410) * Add IconExtWindows trait * Move changelog entries to unreleased category Co-authored-by: Osspial --- CHANGELOG.md | 2 + src/icon.rs | 92 +++++++++---- src/platform/windows.rs | 44 ++++++- src/platform_impl/android/mod.rs | 2 + src/platform_impl/ios/mod.rs | 2 + src/platform_impl/linux/mod.rs | 2 + src/platform_impl/linux/x11/util/icon.rs | 15 ++- src/platform_impl/macos/mod.rs | 2 + src/platform_impl/web/mod.rs | 2 + src/platform_impl/windows/icon.rs | 153 +++++++++++++++------- src/platform_impl/windows/mod.rs | 6 +- src/platform_impl/windows/window.rs | 55 +++----- src/platform_impl/windows/window_state.rs | 13 +- src/window.rs | 2 +- 14 files changed, 266 insertions(+), 126 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e86e6d44..0111b943 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ - On Wayland, Hide CSD for fullscreen windows. - On Windows, ignore spurious mouse move messages. - **Breaking:** Move `ModifiersChanged` variant from `DeviceEvent` to `WindowEvent`. +- On Windows, add `IconExtWindows` trait which exposes creating an `Icon` from an external file or embedded resource +- Add `BadIcon::OsError` variant for when OS icon functionality fails - On Windows, fix crash at startup on systems that do not properly support Windows' Dark Mode # 0.21.0 (2020-02-04) diff --git a/src/icon.rs b/src/icon.rs index d512df1a..418ea03a 100644 --- a/src/icon.rs +++ b/src/icon.rs @@ -1,4 +1,5 @@ -use std::{error::Error, fmt, mem}; +use crate::platform_impl::PlatformIcon; +use std::{error::Error, fmt, io, mem}; #[repr(C)] #[derive(Debug)] @@ -11,7 +12,7 @@ pub(crate) struct Pixel { pub(crate) const PIXEL_SIZE: usize = mem::size_of::(); -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug)] /// An error produced when using `Icon::from_rgba` with invalid arguments. pub enum BadIcon { /// Produced when the length of the `rgba` argument isn't divisible by 4, thus `rgba` can't be @@ -25,6 +26,8 @@ pub enum BadIcon { width_x_height: usize, pixel_count: usize, }, + /// Produced when underlying OS functionality failed to create the icon + OsError(io::Error), } impl fmt::Display for BadIcon { @@ -43,6 +46,7 @@ impl fmt::Display for BadIcon { "The specified dimensions ({:?}x{:?}) don't match the number of pixels supplied by the `rgba` argument ({:?}). For those dimensions, the expected pixel count is {:?}.", width, height, pixel_count, width_x_height, ), + BadIcon::OsError(e) => write!(f, "OS error when instantiating the icon: {:?}", e), } } } @@ -54,38 +58,78 @@ impl Error for BadIcon { } #[derive(Debug, Clone, PartialEq, Eq)] -/// An icon used for the window titlebar, taskbar, etc. -pub struct Icon { +pub(crate) struct RgbaIcon { pub(crate) rgba: Vec, pub(crate) width: u32, pub(crate) height: u32, } +/// For platforms which don't have window icons (e.g. web) +#[derive(Debug, Clone, PartialEq, Eq)] +pub(crate) struct NoIcon; + +#[allow(dead_code)] // These are not used on every platform +mod constructors { + use super::*; + + impl RgbaIcon { + /// Creates an `Icon` from 32bpp RGBA data. + /// + /// The length of `rgba` must be divisible by 4, and `width * height` must equal + /// `rgba.len() / 4`. Otherwise, this will return a `BadIcon` error. + pub fn from_rgba(rgba: Vec, width: u32, height: u32) -> Result { + if rgba.len() % PIXEL_SIZE != 0 { + return Err(BadIcon::ByteCountNotDivisibleBy4 { + byte_count: rgba.len(), + }); + } + let pixel_count = rgba.len() / PIXEL_SIZE; + if pixel_count != (width * height) as usize { + Err(BadIcon::DimensionsVsPixelCount { + width, + height, + width_x_height: (width * height) as usize, + pixel_count, + }) + } else { + Ok(RgbaIcon { + rgba, + width, + height, + }) + } + } + } + + impl NoIcon { + pub fn from_rgba(rgba: Vec, width: u32, height: u32) -> Result { + // Create the rgba icon anyway to validate the input + let _ = RgbaIcon::from_rgba(rgba, width, height)?; + Ok(NoIcon) + } + } +} + +/// An icon used for the window titlebar, taskbar, etc. +#[derive(Clone)] +pub struct Icon { + pub(crate) inner: PlatformIcon, +} + +impl fmt::Debug for Icon { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + fmt::Debug::fmt(&self.inner, formatter) + } +} + impl Icon { /// Creates an `Icon` from 32bpp RGBA data. /// /// The length of `rgba` must be divisible by 4, and `width * height` must equal /// `rgba.len() / 4`. Otherwise, this will return a `BadIcon` error. pub fn from_rgba(rgba: Vec, width: u32, height: u32) -> Result { - if rgba.len() % PIXEL_SIZE != 0 { - return Err(BadIcon::ByteCountNotDivisibleBy4 { - byte_count: rgba.len(), - }); - } - let pixel_count = rgba.len() / PIXEL_SIZE; - if pixel_count != (width * height) as usize { - Err(BadIcon::DimensionsVsPixelCount { - width, - height, - width_x_height: (width * height) as usize, - pixel_count, - }) - } else { - Ok(Icon { - rgba, - width, - height, - }) - } + Ok(Icon { + inner: PlatformIcon::from_rgba(rgba, width, height)?, + }) } } diff --git a/src/platform/windows.rs b/src/platform/windows.rs index 6e43734c..a356f1e1 100644 --- a/src/platform/windows.rs +++ b/src/platform/windows.rs @@ -1,16 +1,19 @@ #![cfg(target_os = "windows")] use std::os::raw::c_void; +use std::path::Path; use libc; +use winapi::shared::minwindef::WORD; use winapi::shared::windef::HWND; use crate::{ + dpi::PhysicalSize, event::DeviceId, event_loop::EventLoop, monitor::MonitorHandle, - platform_impl::EventLoop as WindowsEventLoop, - window::{Icon, Window, WindowBuilder}, + platform_impl::{EventLoop as WindowsEventLoop, WinIcon}, + window::{BadIcon, Icon, Window, WindowBuilder}, }; /// Additional methods on `EventLoop` that are specific to Windows. @@ -171,3 +174,40 @@ impl DeviceIdExtWindows for DeviceId { self.0.persistent_identifier() } } + +/// Additional methods on `Icon` that are specific to Windows. +pub trait IconExtWindows: Sized { + /// Create an icon from a file path. + /// + /// Specify `size` to load a specific icon size from the file, or `None` to load the default + /// icon size from the file. + /// + /// In cases where the specified size does not exist in the file, Windows may perform scaling + /// to get an icon of the desired size. + fn from_path>(path: P, size: Option>) + -> Result; + + /// Create an icon from a resource embedded in this executable or library. + /// + /// Specify `size` to load a specific icon size from the file, or `None` to load the default + /// icon size from the file. + /// + /// In cases where the specified size does not exist in the file, Windows may perform scaling + /// to get an icon of the desired size. + fn from_resource(ordinal: WORD, size: Option>) -> Result; +} + +impl IconExtWindows for Icon { + fn from_path>( + path: P, + size: Option>, + ) -> Result { + let win_icon = WinIcon::from_path(path, size)?; + Ok(Icon { inner: win_icon }) + } + + fn from_resource(ordinal: WORD, size: Option>) -> Result { + let win_icon = WinIcon::from_resource(ordinal, size)?; + Ok(Icon { inner: win_icon }) + } +} diff --git a/src/platform_impl/android/mod.rs b/src/platform_impl/android/mod.rs index ef0639d1..cf189374 100644 --- a/src/platform_impl/android/mod.rs +++ b/src/platform_impl/android/mod.rs @@ -22,6 +22,8 @@ use crate::{ use raw_window_handle::{android::AndroidHandle, RawWindowHandle}; use CreationError::OsError; +pub(crate) use crate::icon::NoIcon as PlatformIcon; + pub type OsError = std::io::Error; pub struct EventLoop { diff --git a/src/platform_impl/ios/mod.rs b/src/platform_impl/ios/mod.rs index 3141dea4..da7b0185 100644 --- a/src/platform_impl/ios/mod.rs +++ b/src/platform_impl/ios/mod.rs @@ -83,6 +83,8 @@ pub use self::{ window::{PlatformSpecificWindowBuilderAttributes, Window, WindowId}, }; +pub(crate) use crate::icon::NoIcon as PlatformIcon; + #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct DeviceId { uiscreen: ffi::id, diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index 94117303..8958ddc0 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -18,6 +18,8 @@ use crate::{ window::{CursorIcon, Fullscreen, WindowAttributes}, }; +pub(crate) use crate::icon::RgbaIcon as PlatformIcon; + pub mod wayland; pub mod x11; diff --git a/src/platform_impl/linux/x11/util/icon.rs b/src/platform_impl/linux/x11/util/icon.rs index 5334d4a9..eb13d48b 100644 --- a/src/platform_impl/linux/x11/util/icon.rs +++ b/src/platform_impl/linux/x11/util/icon.rs @@ -1,5 +1,5 @@ use super::*; -use crate::window::{Icon, Pixel, PIXEL_SIZE}; +use crate::icon::{Icon, Pixel, PIXEL_SIZE}; impl Pixel { pub fn to_packed_argb(&self) -> Cardinal { @@ -18,13 +18,14 @@ impl Pixel { impl Icon { pub(crate) fn to_cardinals(&self) -> Vec { - assert_eq!(self.rgba.len() % PIXEL_SIZE, 0); - let pixel_count = self.rgba.len() / PIXEL_SIZE; - assert_eq!(pixel_count, (self.width * self.height) as usize); + let rgba_icon = &self.inner; + assert_eq!(rgba_icon.rgba.len() % PIXEL_SIZE, 0); + let pixel_count = rgba_icon.rgba.len() / PIXEL_SIZE; + assert_eq!(pixel_count, (rgba_icon.width * rgba_icon.height) as usize); let mut data = Vec::with_capacity(pixel_count); - data.push(self.width as Cardinal); - data.push(self.height as Cardinal); - let pixels = self.rgba.as_ptr() as *const Pixel; + data.push(rgba_icon.width as Cardinal); + data.push(rgba_icon.height as Cardinal); + let pixels = rgba_icon.rgba.as_ptr() as *const Pixel; for pixel_index in 0..pixel_count { let pixel = unsafe { &*pixels.offset(pixel_index as isize) }; data.push(pixel.to_packed_argb()); diff --git a/src/platform_impl/macos/mod.rs b/src/platform_impl/macos/mod.rs index 8b5ee6a5..72b8e0a3 100644 --- a/src/platform_impl/macos/mod.rs +++ b/src/platform_impl/macos/mod.rs @@ -25,6 +25,8 @@ use crate::{ error::OsError as RootOsError, event::DeviceId as RootDeviceId, window::WindowAttributes, }; +pub(crate) use crate::icon::NoIcon as PlatformIcon; + #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct DeviceId; diff --git a/src/platform_impl/web/mod.rs b/src/platform_impl/web/mod.rs index ba022db6..43bbb2af 100644 --- a/src/platform_impl/web/mod.rs +++ b/src/platform_impl/web/mod.rs @@ -44,3 +44,5 @@ pub use self::window::{ Id as WindowId, PlatformSpecificBuilderAttributes as PlatformSpecificWindowBuilderAttributes, Window, }; + +pub(crate) use crate::icon::NoIcon as PlatformIcon; diff --git a/src/platform_impl/windows/icon.rs b/src/platform_impl/windows/icon.rs index c865053d..1308c746 100644 --- a/src/platform_impl/windows/icon.rs +++ b/src/platform_impl/windows/icon.rs @@ -1,15 +1,17 @@ -use std::{io, mem, os::windows::ffi::OsStrExt, path::Path, ptr}; +use std::{fmt, io, iter::once, mem, os::windows::ffi::OsStrExt, path::Path, ptr, sync::Arc}; use winapi::{ ctypes::{c_int, wchar_t}, shared::{ - minwindef::{BYTE, LPARAM, WPARAM}, + minwindef::{BYTE, LPARAM, WORD, WPARAM}, windef::{HICON, HWND}, }, + um::libloaderapi, um::winuser, }; -use crate::icon::{Icon, Pixel, PIXEL_SIZE}; +use crate::dpi::PhysicalSize; +use crate::icon::*; impl Pixel { fn to_bgra(&mut self) { @@ -17,92 +19,149 @@ impl Pixel { } } +impl RgbaIcon { + fn into_windows_icon(self) -> Result { + let mut rgba = self.rgba; + let pixel_count = rgba.len() / PIXEL_SIZE; + let mut and_mask = Vec::with_capacity(pixel_count); + let pixels = + unsafe { std::slice::from_raw_parts_mut(rgba.as_mut_ptr() as *mut Pixel, pixel_count) }; + for pixel in pixels { + and_mask.push(pixel.a.wrapping_sub(std::u8::MAX)); // invert alpha channel + pixel.to_bgra(); + } + assert_eq!(and_mask.len(), pixel_count); + let handle = unsafe { + winuser::CreateIcon( + ptr::null_mut(), + self.width as c_int, + self.height as c_int, + 1, + (PIXEL_SIZE * 8) as BYTE, + and_mask.as_ptr() as *const BYTE, + rgba.as_ptr() as *const BYTE, + ) as HICON + }; + if !handle.is_null() { + Ok(WinIcon::from_handle(handle)) + } else { + Err(BadIcon::OsError(io::Error::last_os_error())) + } + } +} + #[derive(Debug)] pub enum IconType { Small = winuser::ICON_SMALL as isize, Big = winuser::ICON_BIG as isize, } -#[derive(Clone, Debug)] +#[derive(Debug)] +struct RaiiIcon { + handle: HICON, +} + +#[derive(Clone)] pub struct WinIcon { - pub handle: HICON, + inner: Arc, } unsafe impl Send for WinIcon {} impl WinIcon { - #[allow(dead_code)] - pub fn from_path>(path: P) -> Result { - let wide_path: Vec = path.as_ref().as_os_str().encode_wide().collect(); + pub fn as_raw_handle(&self) -> HICON { + self.inner.handle + } + + pub fn from_path>( + path: P, + size: Option>, + ) -> Result { + let wide_path: Vec = path + .as_ref() + .as_os_str() + .encode_wide() + .chain(once(0)) + .collect(); + + // width / height of 0 along with LR_DEFAULTSIZE tells windows to load the default icon size + let (width, height) = size.map(Into::into).unwrap_or((0, 0)); + let handle = unsafe { winuser::LoadImageW( ptr::null_mut(), wide_path.as_ptr() as *const wchar_t, winuser::IMAGE_ICON, - 0, // 0 indicates that we want to use the actual width - 0, // and height - winuser::LR_LOADFROMFILE, - ) as HICON - }; - if !handle.is_null() { - Ok(WinIcon { handle }) - } else { - Err(io::Error::last_os_error()) - } - } - - pub fn from_icon(icon: Icon) -> Result { - Self::from_rgba(icon.rgba, icon.width, icon.height) - } - - pub fn from_rgba(mut rgba: Vec, width: u32, height: u32) -> Result { - assert_eq!(rgba.len() % PIXEL_SIZE, 0); - let pixel_count = rgba.len() / PIXEL_SIZE; - assert_eq!(pixel_count, (width * height) as usize); - let mut and_mask = Vec::with_capacity(pixel_count); - let pixels = rgba.as_mut_ptr() as *mut Pixel; // how not to write idiomatic Rust - for pixel_index in 0..pixel_count { - let pixel = unsafe { &mut *pixels.offset(pixel_index as isize) }; - and_mask.push(pixel.a.wrapping_sub(std::u8::MAX)); // invert alpha channel - pixel.to_bgra(); - } - assert_eq!(and_mask.len(), pixel_count); - let handle = unsafe { - winuser::CreateIcon( - ptr::null_mut(), width as c_int, height as c_int, - 1, - (PIXEL_SIZE * 8) as BYTE, - and_mask.as_ptr() as *const BYTE, - rgba.as_ptr() as *const BYTE, + winuser::LR_DEFAULTSIZE | winuser::LR_LOADFROMFILE, ) as HICON }; if !handle.is_null() { - Ok(WinIcon { handle }) + Ok(WinIcon::from_handle(handle)) } else { - Err(io::Error::last_os_error()) + Err(BadIcon::OsError(io::Error::last_os_error())) } } + pub fn from_resource( + resource_id: WORD, + size: Option>, + ) -> Result { + // width / height of 0 along with LR_DEFAULTSIZE tells windows to load the default icon size + let (width, height) = size.map(Into::into).unwrap_or((0, 0)); + let handle = unsafe { + winuser::LoadImageW( + libloaderapi::GetModuleHandleW(ptr::null_mut()), + winuser::MAKEINTRESOURCEW(resource_id), + winuser::IMAGE_ICON, + width as c_int, + height as c_int, + winuser::LR_DEFAULTSIZE, + ) as HICON + }; + if !handle.is_null() { + Ok(WinIcon::from_handle(handle)) + } else { + Err(BadIcon::OsError(io::Error::last_os_error())) + } + } + + pub fn from_rgba(rgba: Vec, width: u32, height: u32) -> Result { + let rgba_icon = RgbaIcon::from_rgba(rgba, width, height)?; + rgba_icon.into_windows_icon() + } + pub fn set_for_window(&self, hwnd: HWND, icon_type: IconType) { unsafe { winuser::SendMessageW( hwnd, winuser::WM_SETICON, icon_type as WPARAM, - self.handle as LPARAM, + self.as_raw_handle() as LPARAM, ); } } + + fn from_handle(handle: HICON) -> Self { + Self { + inner: Arc::new(RaiiIcon { handle }), + } + } } -impl Drop for WinIcon { +impl Drop for RaiiIcon { fn drop(&mut self) { unsafe { winuser::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 { winuser::SendMessageW(hwnd, winuser::WM_SETICON, icon_type as WPARAM, 0 as LPARAM); diff --git a/src/platform_impl/windows/mod.rs b/src/platform_impl/windows/mod.rs index 47bf7fb5..021c903b 100644 --- a/src/platform_impl/windows/mod.rs +++ b/src/platform_impl/windows/mod.rs @@ -4,11 +4,15 @@ use winapi::{self, shared::windef::HWND}; pub use self::{ event_loop::{EventLoop, EventLoopProxy, EventLoopWindowTarget}, + icon::WinIcon, monitor::{MonitorHandle, VideoMode}, window::Window, }; -use crate::{event::DeviceId as RootDeviceId, window::Icon}; +pub use self::icon::WinIcon as PlatformIcon; + +use crate::event::DeviceId as RootDeviceId; +use crate::icon::Icon; #[derive(Clone, Default)] pub struct PlatformSpecificWindowBuilderAttributes { diff --git a/src/platform_impl/windows/window.rs b/src/platform_impl/windows/window.rs index 0f9a09c7..3c58e1fd 100644 --- a/src/platform_impl/windows/window.rs +++ b/src/platform_impl/windows/window.rs @@ -32,18 +32,19 @@ use winapi::{ use crate::{ dpi::{PhysicalPosition, PhysicalSize, Position, Size}, error::{ExternalError, NotSupportedError, OsError as RootOsError}, + icon::Icon, monitor::MonitorHandle as RootMonitorHandle, platform_impl::platform::{ dark_mode::try_dark_mode, dpi::{dpi_to_scale_factor, hwnd_dpi}, drop_handler::FileDropHandler, event_loop::{self, EventLoopWindowTarget, DESTROY_MSG_ID}, - icon::{self, IconType, WinIcon}, + icon::{self, IconType}, monitor, util, window_state::{CursorFlags, SavedWindow, WindowFlags, WindowState}, PlatformSpecificWindowBuilderAttributes, WindowId, }, - window::{CursorIcon, Fullscreen, Icon, WindowAttributes}, + window::{CursorIcon, Fullscreen, WindowAttributes}, }; /// The Win32 implementation of the main `Window` object. @@ -576,12 +577,11 @@ impl Window { } #[inline] - pub fn set_window_icon(&self, mut window_icon: Option) { - let window_icon = window_icon - .take() - .map(|icon| WinIcon::from_icon(icon).expect("Failed to create `ICON_SMALL`")); + pub fn set_window_icon(&self, window_icon: Option) { if let Some(ref window_icon) = window_icon { - window_icon.set_for_window(self.window.0, IconType::Small); + window_icon + .inner + .set_for_window(self.window.0, IconType::Small); } else { icon::unset_for_window(self.window.0, IconType::Small); } @@ -589,12 +589,11 @@ impl Window { } #[inline] - pub fn set_taskbar_icon(&self, mut taskbar_icon: Option) { - let taskbar_icon = taskbar_icon - .take() - .map(|icon| WinIcon::from_icon(icon).expect("Failed to create `ICON_BIG`")); + pub fn set_taskbar_icon(&self, taskbar_icon: Option) { if let Some(ref taskbar_icon) = taskbar_icon { - taskbar_icon.set_for_window(self.window.0, IconType::Big); + taskbar_icon + .inner + .set_for_window(self.window.0, IconType::Big); } else { icon::unset_for_window(self.window.0, IconType::Big); } @@ -636,7 +635,7 @@ unsafe impl Sync for WindowWrapper {} unsafe impl Send for WindowWrapper {} unsafe fn init( - mut attributes: WindowAttributes, + attributes: WindowAttributes, pl_attribs: PlatformSpecificWindowBuilderAttributes, event_loop: &EventLoopWindowTarget, ) -> Result { @@ -645,25 +644,8 @@ unsafe fn init( .chain(Some(0).into_iter()) .collect::>(); - let window_icon = { - let icon = attributes.window_icon.take().map(WinIcon::from_icon); - if let Some(icon) = icon { - Some(icon.map_err(|e| os_error!(e))?) - } else { - None - } - }; - let taskbar_icon = { - let icon = attributes.window_icon.take().map(WinIcon::from_icon); - if let Some(icon) = icon { - Some(icon.map_err(|e| os_error!(e))?) - } else { - None - } - }; - // registering the window class - let class_name = register_window_class(&window_icon, &taskbar_icon); + let class_name = register_window_class(&attributes.window_icon, &pl_attribs.taskbar_icon); let mut window_flags = WindowFlags::empty(); window_flags.set(WindowFlags::DECORATIONS, attributes.decorations); @@ -756,8 +738,7 @@ unsafe fn init( let window_state = { let window_state = WindowState::new( &attributes, - window_icon, - taskbar_icon, + pl_attribs.taskbar_icon, scale_factor, dark_mode, ); @@ -787,8 +768,8 @@ unsafe fn init( } unsafe fn register_window_class( - window_icon: &Option, - taskbar_icon: &Option, + window_icon: &Option, + taskbar_icon: &Option, ) -> Vec { let class_name: Vec<_> = OsStr::new("Window Class") .encode_wide() @@ -797,11 +778,11 @@ unsafe fn register_window_class( let h_icon = taskbar_icon .as_ref() - .map(|icon| icon.handle) + .map(|icon| icon.inner.as_raw_handle()) .unwrap_or(ptr::null_mut()); let h_icon_small = window_icon .as_ref() - .map(|icon| icon.handle) + .map(|icon| icon.inner.as_raw_handle()) .unwrap_or(ptr::null_mut()); let class = winuser::WNDCLASSEXW { diff --git a/src/platform_impl/windows/window_state.rs b/src/platform_impl/windows/window_state.rs index 9a5414a6..11794821 100644 --- a/src/platform_impl/windows/window_state.rs +++ b/src/platform_impl/windows/window_state.rs @@ -1,7 +1,8 @@ use crate::{ dpi::{PhysicalPosition, Size}, event::ModifiersState, - platform_impl::platform::{event_loop, icon::WinIcon, util}, + icon::Icon, + platform_impl::platform::{event_loop, util}, window::{CursorIcon, Fullscreen, WindowAttributes}, }; use parking_lot::MutexGuard; @@ -15,7 +16,6 @@ use winapi::{ }; /// Contains information about states and the window that the callback is going to use. -#[derive(Clone)] pub struct WindowState { pub mouse: MouseProperties, @@ -23,8 +23,8 @@ pub struct WindowState { pub min_size: Option, pub max_size: Option, - pub window_icon: Option, - pub taskbar_icon: Option, + pub window_icon: Option, + pub taskbar_icon: Option, pub saved_window: Option, pub scale_factor: f64, @@ -96,8 +96,7 @@ bitflags! { impl WindowState { pub fn new( attributes: &WindowAttributes, - window_icon: Option, - taskbar_icon: Option, + taskbar_icon: Option, scale_factor: f64, is_dark_mode: bool, ) -> WindowState { @@ -112,7 +111,7 @@ impl WindowState { min_size: attributes.min_inner_size, max_size: attributes.max_inner_size, - window_icon, + window_icon: attributes.window_icon.clone(), taskbar_icon, saved_window: None, diff --git a/src/window.rs b/src/window.rs index 99644fee..113e7c04 100644 --- a/src/window.rs +++ b/src/window.rs @@ -9,7 +9,7 @@ use crate::{ platform_impl, }; -pub use crate::icon::*; +pub use crate::icon::{BadIcon, Icon}; /// Represents a window. ///