winit-core: move icon

This commit is contained in:
Kirill Chibisov 2025-05-01 19:59:29 +09:00
parent a491c2abed
commit cbb29ab526
8 changed files with 60 additions and 39 deletions

View file

@ -304,8 +304,7 @@ pub mod error;
mod cursor;
pub mod event;
pub mod event_loop;
pub mod icon;
pub use winit_core::{keyboard, monitor};
pub use winit_core::{icon, keyboard, monitor};
mod platform_impl;
use winit_core::as_any as utils;
pub mod window;

View file

@ -1,7 +1,18 @@
#![allow(clippy::assertions_on_constants)]
use super::*;
use crate::icon::{Pixel, RgbaIcon, PIXEL_SIZE};
use crate::icon::RgbaIcon;
pub(crate) const PIXEL_SIZE: usize = mem::size_of::<Pixel>();
#[repr(C)]
#[derive(Debug)]
pub(crate) struct Pixel {
pub(crate) r: u8,
pub(crate) g: u8,
pub(crate) b: u8,
pub(crate) a: u8,
}
impl Pixel {
pub fn to_packed_argb(&self) -> Cardinal {
@ -18,19 +29,17 @@ impl Pixel {
}
}
impl RgbaIcon {
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 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;
for pixel_index in 0..pixel_count {
let pixel = unsafe { &*pixels.add(pixel_index) };
data.push(pixel.to_packed_argb());
}
data
pub(crate) fn rgba_to_cardinals(icon: &RgbaIcon) -> Vec<Cardinal> {
assert_eq!(icon.buffer().len() % PIXEL_SIZE, 0);
let pixel_count = icon.buffer().len() / PIXEL_SIZE;
assert_eq!(pixel_count, (icon.width() * icon.height()) as usize);
let mut data = Vec::with_capacity(pixel_count);
data.push(icon.width() as Cardinal);
data.push(icon.height() as Cardinal);
let pixels = icon.buffer().as_ptr() as *const Pixel;
for pixel_index in 0..pixel_count {
let pixel = unsafe { &*pixels.add(pixel_index) };
data.push(pixel.to_packed_argb());
}
data
}

View file

@ -25,6 +25,7 @@ use x11rb::protocol::xproto::{self, ConnectionExt as _};
pub use self::cursor::*;
pub use self::geometry::*;
pub use self::hint::*;
pub(crate) use self::icon::rgba_to_cardinals;
pub use self::input::*;
pub use self::mouse::*;
pub use self::window_property::*;

View file

@ -35,6 +35,7 @@ use crate::monitor::{
use crate::platform::x11::WindowType;
use crate::platform_impl::common;
use crate::platform_impl::x11::atoms::*;
use crate::platform_impl::x11::util::rgba_to_cardinals;
use crate::platform_impl::x11::{
xinput_fp1616_to_float, MonitorHandle as X11MonitorHandle, WakeSender, X11Error,
};
@ -205,7 +206,7 @@ impl CoreWindow for Window {
fn set_window_icon(&self, window_icon: Option<crate::window::Icon>) {
let icon = match window_icon.as_ref() {
Some(icon) => icon.0.cast_ref::<RgbaIcon>(),
Some(icon) => icon.cast_ref::<RgbaIcon>(),
None => None,
};
self.0.set_window_icon(icon)
@ -771,7 +772,7 @@ impl UnownedWindow {
// Set window icons
if let Some(icon) =
window_attrs.window_icon.as_ref().and_then(|icon| icon.0.cast_ref::<RgbaIcon>())
window_attrs.window_icon.as_ref().and_then(|icon| icon.cast_ref::<RgbaIcon>())
{
leap!(window.set_icon_inner(icon)).ignore_error();
}
@ -1414,7 +1415,7 @@ impl UnownedWindow {
fn set_icon_inner(&self, icon: &RgbaIcon) -> Result<VoidCookie<'_>, X11Error> {
let atoms = self.xconn.atoms();
let icon_atom = atoms[_NET_WM_ICON];
let data = icon.to_cardinals();
let data = rgba_to_cardinals(icon);
self.xconn.change_property(
self.xwindow,
icon_atom,

View file

@ -20,6 +20,8 @@ use crate::error::RequestError;
use crate::icon::*;
use crate::platform::windows::WinIcon;
pub(crate) const PIXEL_SIZE: usize = mem::size_of::<Pixel>();
unsafe impl Send for WinIcon {}
impl WinIcon {
@ -92,10 +94,10 @@ impl WinIcon {
}
pub(crate) fn from_rgba(rgba: &RgbaIcon) -> Result<Self, BadIcon> {
let pixel_count = rgba.rgba.len() / PIXEL_SIZE;
let pixel_count = rgba.buffer().len() / PIXEL_SIZE;
let mut and_mask = Vec::with_capacity(pixel_count);
let pixels = unsafe {
std::slice::from_raw_parts_mut(rgba.rgba.as_ptr() as *mut Pixel, pixel_count)
std::slice::from_raw_parts_mut(rgba.buffer().as_ptr() as *mut Pixel, pixel_count)
};
for pixel in pixels {
and_mask.push(pixel.a.wrapping_sub(u8::MAX)); // invert alpha channel
@ -105,12 +107,12 @@ impl WinIcon {
let handle = unsafe {
CreateIcon(
ptr::null_mut(),
rgba.width as i32,
rgba.height as i32,
rgba.width() as i32,
rgba.height() as i32,
1,
(PIXEL_SIZE * 8) as u8,
and_mask.as_ptr(),
rgba.rgba.as_ptr(),
rgba.buffer().as_ptr(),
)
};
if !handle.is_null() {
@ -250,3 +252,12 @@ impl RaiiCursor {
self.handle
}
}
#[repr(C)]
#[derive(Debug)]
pub(crate) struct Pixel {
pub(crate) r: u8,
pub(crate) g: u8,
pub(crate) b: u8,
pub(crate) a: u8,
}

View file

@ -351,7 +351,7 @@ impl Window {
}
fn set_icon(&self, mut new_icon: Icon, icon_type: IconType) {
if let Some(icon) = new_icon.0.cast_ref::<RgbaIcon>() {
if let Some(icon) = new_icon.cast_ref::<RgbaIcon>() {
let icon = match WinIcon::from_rgba(icon) {
Ok(icon) => icon,
Err(err) => {
@ -362,7 +362,7 @@ impl Window {
new_icon = Icon(Arc::new(icon));
}
if let Some(icon) = new_icon.0.cast_ref::<WinIcon>() {
if let Some(icon) = new_icon.cast_ref::<WinIcon>() {
unsafe {
SendMessageW(
self.hwnd(),

View file

@ -1,30 +1,29 @@
use std::error::Error;
use std::ops::Deref;
use std::sync::Arc;
use std::{fmt, io, mem};
use crate::utils::{impl_dyn_casting, AsAny};
use crate::as_any::{impl_dyn_casting, AsAny};
pub(crate) const PIXEL_SIZE: usize = mem::size_of::<Pixel>();
pub(crate) const PIXEL_SIZE: usize = mem::size_of::<u32>();
/// An icon used for the window titlebar, taskbar, etc.
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct Icon(pub(crate) Arc<dyn IconProvider>);
pub struct Icon(pub Arc<dyn IconProvider>);
// TODO remove that once split.
pub trait IconProvider: AsAny + fmt::Debug + Send + Sync {}
impl_dyn_casting!(IconProvider);
impl Deref for Icon {
type Target = dyn IconProvider;
#[repr(C)]
#[derive(Debug)]
pub(crate) struct Pixel {
pub(crate) r: u8,
pub(crate) g: u8,
pub(crate) b: u8,
pub(crate) a: u8,
fn deref(&self) -> &Self::Target {
self.0.as_ref()
}
}
impl_dyn_casting!(IconProvider);
#[derive(Debug)]
/// An error produced when using [`RgbaIcon::new`] with invalid arguments.
pub enum BadIcon {

View file

@ -1,4 +1,5 @@
#[macro_use]
pub mod as_any;
pub mod icon;
pub mod keyboard;
pub mod monitor;