mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2025-01-23 10:26:34 +11:00
Add ability to create Icons from embedded resources on Windows (#1410)
* Add IconExtWindows trait * Move changelog entries to unreleased category Co-authored-by: Osspial <osspial@gmail.com>
This commit is contained in:
parent
2f27f64cdb
commit
098fd5d602
14 changed files with 266 additions and 126 deletions
|
@ -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)
|
||||
|
|
92
src/icon.rs
92
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::<Pixel>();
|
||||
|
||||
#[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<u8>,
|
||||
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<u8>, width: u32, height: u32) -> Result<Self, BadIcon> {
|
||||
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<u8>, width: u32, height: u32) -> Result<Self, BadIcon> {
|
||||
// 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<u8>, width: u32, height: u32) -> Result<Self, BadIcon> {
|
||||
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)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<P: AsRef<Path>>(path: P, size: Option<PhysicalSize<u32>>)
|
||||
-> Result<Self, BadIcon>;
|
||||
|
||||
/// 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<PhysicalSize<u32>>) -> Result<Self, BadIcon>;
|
||||
}
|
||||
|
||||
impl IconExtWindows for Icon {
|
||||
fn from_path<P: AsRef<Path>>(
|
||||
path: P,
|
||||
size: Option<PhysicalSize<u32>>,
|
||||
) -> Result<Self, BadIcon> {
|
||||
let win_icon = WinIcon::from_path(path, size)?;
|
||||
Ok(Icon { inner: win_icon })
|
||||
}
|
||||
|
||||
fn from_resource(ordinal: WORD, size: Option<PhysicalSize<u32>>) -> Result<Self, BadIcon> {
|
||||
let win_icon = WinIcon::from_resource(ordinal, size)?;
|
||||
Ok(Icon { inner: win_icon })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -18,6 +18,8 @@ use crate::{
|
|||
window::{CursorIcon, Fullscreen, WindowAttributes},
|
||||
};
|
||||
|
||||
pub(crate) use crate::icon::RgbaIcon as PlatformIcon;
|
||||
|
||||
pub mod wayland;
|
||||
pub mod x11;
|
||||
|
||||
|
|
|
@ -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<Cardinal> {
|
||||
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());
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -44,3 +44,5 @@ pub use self::window::{
|
|||
Id as WindowId, PlatformSpecificBuilderAttributes as PlatformSpecificWindowBuilderAttributes,
|
||||
Window,
|
||||
};
|
||||
|
||||
pub(crate) use crate::icon::NoIcon as PlatformIcon;
|
||||
|
|
|
@ -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<WinIcon, BadIcon> {
|
||||
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<RaiiIcon>,
|
||||
}
|
||||
|
||||
unsafe impl Send for WinIcon {}
|
||||
|
||||
impl WinIcon {
|
||||
#[allow(dead_code)]
|
||||
pub fn from_path<P: AsRef<Path>>(path: P) -> Result<Self, io::Error> {
|
||||
let wide_path: Vec<u16> = path.as_ref().as_os_str().encode_wide().collect();
|
||||
pub fn as_raw_handle(&self) -> HICON {
|
||||
self.inner.handle
|
||||
}
|
||||
|
||||
pub fn from_path<P: AsRef<Path>>(
|
||||
path: P,
|
||||
size: Option<PhysicalSize<u32>>,
|
||||
) -> Result<Self, BadIcon> {
|
||||
let wide_path: Vec<u16> = 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, io::Error> {
|
||||
Self::from_rgba(icon.rgba, icon.width, icon.height)
|
||||
}
|
||||
|
||||
pub fn from_rgba(mut rgba: Vec<u8>, width: u32, height: u32) -> Result<Self, io::Error> {
|
||||
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<PhysicalSize<u32>>,
|
||||
) -> Result<Self, BadIcon> {
|
||||
// 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<u8>, width: u32, height: u32) -> Result<Self, BadIcon> {
|
||||
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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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<Icon>) {
|
||||
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<Icon>) {
|
||||
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<Icon>) {
|
||||
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<Icon>) {
|
||||
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<T: 'static>(
|
||||
mut attributes: WindowAttributes,
|
||||
attributes: WindowAttributes,
|
||||
pl_attribs: PlatformSpecificWindowBuilderAttributes,
|
||||
event_loop: &EventLoopWindowTarget<T>,
|
||||
) -> Result<Window, RootOsError> {
|
||||
|
@ -645,25 +644,8 @@ unsafe fn init<T: 'static>(
|
|||
.chain(Some(0).into_iter())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
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<T: 'static>(
|
|||
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<T: 'static>(
|
|||
}
|
||||
|
||||
unsafe fn register_window_class(
|
||||
window_icon: &Option<WinIcon>,
|
||||
taskbar_icon: &Option<WinIcon>,
|
||||
window_icon: &Option<Icon>,
|
||||
taskbar_icon: &Option<Icon>,
|
||||
) -> Vec<u16> {
|
||||
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 {
|
||||
|
|
|
@ -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<Size>,
|
||||
pub max_size: Option<Size>,
|
||||
|
||||
pub window_icon: Option<WinIcon>,
|
||||
pub taskbar_icon: Option<WinIcon>,
|
||||
pub window_icon: Option<Icon>,
|
||||
pub taskbar_icon: Option<Icon>,
|
||||
|
||||
pub saved_window: Option<SavedWindow>,
|
||||
pub scale_factor: f64,
|
||||
|
@ -96,8 +96,7 @@ bitflags! {
|
|||
impl WindowState {
|
||||
pub fn new(
|
||||
attributes: &WindowAttributes,
|
||||
window_icon: Option<WinIcon>,
|
||||
taskbar_icon: Option<WinIcon>,
|
||||
taskbar_icon: Option<Icon>,
|
||||
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,
|
||||
|
|
|
@ -9,7 +9,7 @@ use crate::{
|
|||
platform_impl,
|
||||
};
|
||||
|
||||
pub use crate::icon::*;
|
||||
pub use crate::icon::{BadIcon, Icon};
|
||||
|
||||
/// Represents a window.
|
||||
///
|
||||
|
|
Loading…
Add table
Reference in a new issue