winit: Set the icon from the builder

Also simplify the code that sets the property to the builder
This commit is contained in:
Olivier Goffart 2022-09-13 12:42:40 +02:00 committed by Olivier Goffart
parent d0a1e42894
commit e17d07fbc8
2 changed files with 46 additions and 66 deletions

View file

@ -38,7 +38,7 @@ pub trait WinitWindow: WindowAdapter {
&self, &self,
constraints: (corelib::layout::LayoutInfo, corelib::layout::LayoutInfo), constraints: (corelib::layout::LayoutInfo, corelib::layout::LayoutInfo),
); );
fn set_icon(&self, icon: corelib::graphics::Image);
/// Called by the event loop when a WindowEvent::Resized is received. /// Called by the event loop when a WindowEvent::Resized is received.
fn resize_event(&self, _size: winit::dpi::PhysicalSize<u32>) {} fn resize_event(&self, _size: winit::dpi::PhysicalSize<u32>) {}

View file

@ -44,6 +44,38 @@ fn size_to_winit(pos: &corelib::api::RequestedSize) -> winit::dpi::Size {
} }
} }
fn icon_to_winit(icon: corelib::graphics::Image) -> Option<winit::window::Icon> {
let image_inner: &ImageInner = (&icon).into();
let pixel_buffer = match image_inner {
ImageInner::EmbeddedImage { buffer, .. } => buffer.clone(),
_ => return None,
};
// This could become a method in SharedPixelBuffer...
let rgba_pixels: Vec<u8> = match &pixel_buffer {
SharedImageBuffer::RGB8(pixels) => pixels
.as_bytes()
.chunks(3)
.flat_map(|rgb| IntoIterator::into_iter([rgb[0], rgb[1], rgb[2], 255]))
.collect(),
SharedImageBuffer::RGBA8(pixels) => pixels.as_bytes().to_vec(),
SharedImageBuffer::RGBA8Premultiplied(pixels) => pixels
.as_bytes()
.chunks(4)
.flat_map(|rgba| {
let alpha = rgba[3] as u32;
IntoIterator::into_iter(rgba)
.take(3)
.map(move |component| (*component as u32 * alpha / 255) as u8)
.chain(std::iter::once(alpha as u8))
})
.collect(),
};
winit::window::Icon::from_rgba(rgba_pixels, pixel_buffer.width(), pixel_buffer.height()).ok()
}
/// GraphicsWindow is an implementation of the [WindowAdapter][`crate::eventloop::WindowAdapter`] trait. This is /// GraphicsWindow is an implementation of the [WindowAdapter][`crate::eventloop::WindowAdapter`] trait. This is
/// typically instantiated by entry factory functions of the different graphics back ends. /// typically instantiated by entry factory functions of the different graphics back ends.
pub(crate) struct GLWindow<Renderer: WinitCompatibleRenderer + 'static> { pub(crate) struct GLWindow<Renderer: WinitCompatibleRenderer + 'static> {
@ -187,46 +219,6 @@ impl<Renderer: WinitCompatibleRenderer + 'static> WinitWindow for GLWindow<Rende
} }
} }
fn set_icon(&self, icon: corelib::graphics::Image) {
let image_inner: &ImageInner = (&icon).into();
let pixel_buffer = match image_inner {
ImageInner::EmbeddedImage { buffer, .. } => buffer.clone(),
_ => return,
};
// This could become a method in SharedPixelBuffer...
let rgba_pixels: Vec<u8> = match &pixel_buffer {
SharedImageBuffer::RGB8(pixels) => pixels
.as_bytes()
.chunks(3)
.flat_map(|rgb| IntoIterator::into_iter([rgb[0], rgb[1], rgb[2], 255]))
.collect(),
SharedImageBuffer::RGBA8(pixels) => pixels.as_bytes().to_vec(),
SharedImageBuffer::RGBA8Premultiplied(pixels) => pixels
.as_bytes()
.chunks(4)
.flat_map(|rgba| {
let alpha = rgba[3] as u32;
IntoIterator::into_iter(rgba)
.take(3)
.map(move |component| (*component as u32 * alpha / 255) as u8)
.chain(std::iter::once(alpha as u8))
})
.collect(),
};
self.with_window_handle(&mut |window| {
window.set_window_icon(
winit::window::Icon::from_rgba(
rgba_pixels.clone(), // FIXME: if the closure were FnOnce we could move rgba_pixels
pixel_buffer.width(),
pixel_buffer.height(),
)
.ok(),
);
})
}
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
fn input_method_focused(&self) -> bool { fn input_method_focused(&self) -> bool {
match self.virtual_keyboard_helper.try_borrow() { match self.virtual_keyboard_helper.try_borrow() {
@ -290,23 +282,16 @@ impl<Renderer: WinitCompatibleRenderer + 'static> WindowAdapterSealed for GLWind
return; return;
} }
let title = window_item.title();
let no_frame = window_item.no_frame();
let icon = window_item.icon();
let mut width = window_item.width() as f32; let mut width = window_item.width() as f32;
let mut height = window_item.height() as f32; let mut height = window_item.height() as f32;
self.set_icon(icon);
let mut must_resize = false; let mut must_resize = false;
self.with_window_handle(&mut |winit_window| { self.with_window_handle(&mut |winit_window| {
winit_window.set_title(&title); winit_window.set_window_icon(icon_to_winit(window_item.icon()));
if no_frame && winit_window.fullscreen().is_none() { winit_window.set_title(&window_item.title());
winit_window.set_decorations(false); winit_window
} else { .set_decorations(!window_item.no_frame() || winit_window.fullscreen().is_some());
winit_window.set_decorations(true);
}
if width <= 0. || height <= 0. { if width <= 0. || height <= 0. {
must_resize = true; must_resize = true;
@ -412,26 +397,24 @@ impl<Renderer: WinitCompatibleRenderer + 'static> WindowAdapterSealed for GLWind
GraphicsWindowBackendState::Mapped(_) => return, GraphicsWindowBackendState::Mapped(_) => return,
}; };
let mut window_builder = winit::window::WindowBuilder::new();
let runtime_window = WindowInner::from_pub(self_.window()); let runtime_window = WindowInner::from_pub(self_.window());
let component_rc = runtime_window.component(); let component_rc = runtime_window.component();
let component = ComponentRc::borrow_pin(&component_rc); let component = ComponentRc::borrow_pin(&component_rc);
let (window_title, no_frame, is_resizable) = if let Some(window_item) = window_builder = if let Some(window_item) =
runtime_window.window_item().as_ref().map(|i| i.as_pin_ref()) runtime_window.window_item().as_ref().map(|i| i.as_pin_ref())
{ {
( window_builder
window_item.title().to_string(), .with_title(window_item.title().to_string())
window_item.no_frame(), .with_resizable(window_item.height() <= 0 as _ || window_item.width() <= 0 as _)
window_item.height() <= 0 as _ && window_item.width() <= 0 as _, .with_decorations(!window_item.no_frame())
) .with_window_icon(icon_to_winit(window_item.icon()))
} else { } else {
("Slint Window".to_string(), false, true) window_builder.with_title("Slint Window".to_string())
}; };
let mut window_builder = winit::window::WindowBuilder::new()
.with_title(window_title)
.with_resizable(is_resizable);
let scale_factor_override = runtime_window.scale_factor(); let scale_factor_override = runtime_window.scale_factor();
// If the scale factor was already set programmatically, use that // If the scale factor was already set programmatically, use that
// else, use the SLINT_SCALE_FACTOR if set, otherwise use the one from winit // else, use the SLINT_SCALE_FACTOR if set, otherwise use the one from winit
@ -502,9 +485,6 @@ impl<Renderer: WinitCompatibleRenderer + 'static> WindowAdapterSealed for GLWind
} }
}; };
let window_builder =
if no_frame { window_builder.with_decorations(false) } else { window_builder };
let window_builder = if let Some(pos) = &requested_position { let window_builder = if let Some(pos) = &requested_position {
window_builder.with_position(position_to_winit(pos)) window_builder.with_position(position_to_winit(pos))
} else { } else {