diff --git a/crates/bevy_window/src/window.rs b/crates/bevy_window/src/window.rs index 0bcb3c6f73068..cce6aaac7af90 100644 --- a/crates/bevy_window/src/window.rs +++ b/crates/bevy_window/src/window.rs @@ -108,6 +108,27 @@ pub enum WindowCommand { }, } +#[derive(Debug, Clone)] +pub struct Icon { + pub rgba: Vec, + pub width: u32, + pub height: u32, +} + +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 icon will not be used. + pub fn from_rgba(rgba: Vec, width: u32, height: u32) -> Self { + Icon { + rgba, + width, + height, + } + } +} + /// Defines the way a window is displayed /// The use_size option that is used in the Fullscreen variant /// defines whether a videomode is chosen that best fits the width and height @@ -383,6 +404,8 @@ pub struct WindowDescriptor { pub cursor_visible: bool, pub cursor_locked: bool, pub mode: WindowMode, + #[cfg(any(target_os = "windows", target_os = "linux"))] + pub icon: Option, #[cfg(target_arch = "wasm32")] pub canvas: Option, } @@ -400,6 +423,8 @@ impl Default for WindowDescriptor { cursor_locked: false, cursor_visible: true, mode: WindowMode::Windowed, + #[cfg(any(target_os = "windows", target_os = "linux"))] + icon: None, #[cfg(target_arch = "wasm32")] canvas: None, } diff --git a/crates/bevy_winit/src/winit_windows.rs b/crates/bevy_winit/src/winit_windows.rs index d32b4d2e41233..1d54764b74783 100644 --- a/crates/bevy_winit/src/winit_windows.rs +++ b/crates/bevy_winit/src/winit_windows.rs @@ -81,6 +81,22 @@ impl WinitWindows { } } + #[cfg(any(target_os = "windows", target_os = "linux"))] + if let Some(icon) = &window_descriptor.icon { + let winit_icon = + match winit::window::Icon::from_rgba(icon.rgba.clone(), icon.width, icon.height) { + Ok(icon) => Some(icon), + Err(bad_icon) => { + println!( + "Bad icon supplied for window and defaulting to none. Error: {:?}", + bad_icon + ); + None + } + }; + winit_window_builder = winit_window_builder.with_window_icon(winit_icon); + } + let winit_window = winit_window_builder.build(&event_loop).unwrap(); match winit_window.set_cursor_grab(window_descriptor.cursor_locked) { diff --git a/examples/window/bevy_icon.rgba b/examples/window/bevy_icon.rgba new file mode 100644 index 0000000000000..18a20498e98ce Binary files /dev/null and b/examples/window/bevy_icon.rgba differ diff --git a/examples/window/window_settings.rs b/examples/window/window_settings.rs index d39a84b621202..0e12cb0eff64e 100644 --- a/examples/window/window_settings.rs +++ b/examples/window/window_settings.rs @@ -1,4 +1,6 @@ use bevy::prelude::*; +#[cfg(any(target_os = "windows", target_os = "linux"))] +use bevy::window::Icon; /// This example illustrates how to customize the default window settings fn main() { @@ -8,6 +10,12 @@ fn main() { width: 500., height: 300., vsync: true, + #[cfg(any(target_os = "windows", target_os = "linux"))] + icon: Some(Icon::from_rgba( + include_bytes!("bevy_icon.rgba").to_vec(), + 32, + 32, + )), ..Default::default() }) .add_plugins(DefaultPlugins)