Skip to content

Commit

Permalink
eframe: Set app icon on Mac and Windows (#2940)
Browse files Browse the repository at this point in the history
* eframe: Set app icon on Mac and Windows

Also: correctly set window title on Mac when launching from
another process, e.g. python.

Co-authored-by: Wumpf <[email protected]>

* lint fixes

* Fix web build

* fix typo

* Try fix windows build

---------

Co-authored-by: Wumpf <[email protected]>
  • Loading branch information
emilk and Wumpf authored Apr 20, 2023
1 parent 834e2e9 commit 7f2de42
Show file tree
Hide file tree
Showing 10 changed files with 363 additions and 21 deletions.
19 changes: 19 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 13 additions & 4 deletions crates/eframe/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ web_screen_reader = ["tts"]

## If set, eframe will look for the env-var `EFRAME_SCREENSHOT_TO` and write a screenshot to that location, and then quit.
## This is used to generate images for the examples.
__screenshot = ["dep:image"]
__screenshot = []

## Use [`wgpu`](https://docs.rs/wgpu) for painting (via [`egui-wgpu`](https://github.com/emilk/egui/tree/master/crates/egui-wgpu)).
## This overrides the `glow` feature.
Expand Down Expand Up @@ -98,6 +98,9 @@ egui-winit = { version = "0.21.1", path = "../egui-winit", default-features = fa
"clipboard",
"links",
] }
image = { version = "0.24", default-features = false, features = [
"png",
] } # Needed for app icon
raw-window-handle = { version = "0.5.0" }
winit = "0.28.1"

Expand All @@ -112,12 +115,18 @@ pollster = { version = "0.3", optional = true } # needed for wgpu
# this can be done at the same time we expose x11/wayland features of winit crate.
glutin = { version = "0.30", optional = true }
glutin-winit = { version = "0.3.0", optional = true }
image = { version = "0.24", optional = true, default-features = false, features = [
"png",
] }
puffin = { version = "0.14", optional = true }
wgpu = { version = "0.15.0", optional = true }

# mac:
[target.'cfg(any(target_os = "macos"))'.dependencies]
cocoa = "0.24.1"
objc = "0.2.7"

# windows:
[target.'cfg(any(target_os = "windows"))'.dependencies]
winapi = "0.3.9"

# -------------------------------------------
# web:
[target.'cfg(target_arch = "wasm32")'.dependencies]
Expand Down
64 changes: 64 additions & 0 deletions crates/eframe/src/epi/icon_data.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/// Image data for an application icon.
///
/// Use a square image, e.g. 256x256 pixels.
/// You can use a transparent background.
#[derive(Clone)]
pub struct IconData {
/// RGBA pixels, with separate/unmultiplied alpha.
pub rgba: Vec<u8>,

/// Image width. This should be a multiple of 4.
pub width: u32,

/// Image height. This should be a multiple of 4.
pub height: u32,
}

impl IconData {
/// Convert into [`image::RgbaImage`]
///
/// # Errors
/// If this is not a valid png.
pub fn try_from_png_bytes(png_bytes: &[u8]) -> Result<Self, image::ImageError> {
let image = image::load_from_memory(png_bytes)?;
Ok(Self::from_image(image))
}

fn from_image(image: image::DynamicImage) -> Self {
let image = image.into_rgba8();
Self {
width: image.width(),
height: image.height(),
rgba: image.into_raw(),
}
}

/// Convert into [`image::RgbaImage`]
///
/// # Errors
/// If `width*height != 4 * rgba.len()`, or if the image is too big.
pub fn to_image(&self) -> Result<image::RgbaImage, String> {
let Self {
rgba,
width,
height,
} = self.clone();
image::RgbaImage::from_raw(width, height, rgba).ok_or_else(|| "Invalid IconData".to_owned())
}

/// Encode as PNG.
///
/// # Errors
/// The image is invalid, or the PNG encoder failed.
pub fn to_png_bytes(&self) -> Result<Vec<u8>, String> {
let image = self.to_image()?;
let mut png_bytes: Vec<u8> = Vec::new();
image
.write_to(
&mut std::io::Cursor::new(&mut png_bytes),
image::ImageOutputFormat::Png,
)
.map_err(|err| err.to_string())?;
Ok(png_bytes)
}
}
19 changes: 6 additions & 13 deletions crates/eframe/src/epi.rs → crates/eframe/src/epi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@

#![warn(missing_docs)] // Let's keep `epi` well-documented.

#[cfg(not(target_arch = "wasm32"))]
mod icon_data;

#[cfg(not(target_arch = "wasm32"))]
pub use icon_data::IconData;

#[cfg(target_arch = "wasm32")]
use std::any::Any;

Expand Down Expand Up @@ -621,19 +627,6 @@ impl std::str::FromStr for Renderer {

// ----------------------------------------------------------------------------

/// Image data for an application icon.
#[derive(Clone)]
pub struct IconData {
/// RGBA pixels, unmultiplied.
pub rgba: Vec<u8>,

/// Image width. This should be a multiple of 4.
pub width: u32,

/// Image height. This should be a multiple of 4.
pub height: u32,
}

/// Represents the surroundings of your app.
///
/// It provides methods to inspect the surroundings (are we on the web?),
Expand Down
Loading

0 comments on commit 7f2de42

Please sign in to comment.