app: ship the Oak icon on every platform surface

- Runtime window icon: X11 takes the embedded 512px PNG up front
  (_NET_WM_ICON), Wayland resolves it from oak.desktop via the app id,
  Windows reads it from the exe's icon resource.
- assets/appicon: 512px PNG + 7-size ICO rasterized from Oak_Icon.svg.
- Windows: oak.rc (ICON resource ID 1, also the Explorer icon) compiled
  by build.rs through embed-resource.
- Linux packaging (deb/rpm/PKGBUILD/oak.spec): install Oak_Icon.svg
  into the hicolor scalable theme alongside the existing 512px PNG.
- macOS: no change needed - cargo packager already builds the .icns
  from the CD-generated icons/icon.png (same source art).
This commit is contained in:
2026-09-10 16:54:51 +08:00
parent 012659bf57
commit 71e41d2d82
11 changed files with 39 additions and 2 deletions
Generated
+1
View File
@@ -4723,6 +4723,7 @@ dependencies = [
name = "oak-app"
version = "0.5.0"
dependencies = [
"embed-resource",
"gpui",
"gpui_elements",
"gpui_platform",
Binary file not shown.

After

Width:  |  Height:  |  Size: 364 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

+8
View File
@@ -92,6 +92,14 @@ default = []
# is given at runtime (or this feature is enabled at build time).
mock-engine = []
# The Windows window/taskbar icon: embeds resources/windows/oak.rc (icon
# resource ID 1, read by gpui_windows' `load_icon`) into oak-editor.exe.
# Same crate gpui uses for its Windows manifest (see gpui's build.rs).
# Unconditional (not target-gated): the build script references it behind
# a runtime `CARGO_CFG_TARGET_OS` check, so it must resolve on every host.
[build-dependencies]
embed-resource = "3.0"
[dev-dependencies]
# `#[gpui::test]` harness for engine-seam smoke tests (test-support feature).
gpui = { path = "../../gpui/crates/gpui", features = ["test-support"] }
+10
View File
@@ -37,6 +37,16 @@ fn main() {
// at the real system library.
println!("cargo:rustc-link-arg=-Wl,-rpath,/usr/lib");
}
if os == "windows" {
// The window/taskbar icon on Windows comes from the exe's icon
// resource (ID 1 — gpui_windows' `load_icon`); compile it in. The
// same resource is the exe's Explorer icon.
println!("cargo:rerun-if-changed=resources/windows/oak.rc");
println!("cargo:rerun-if-changed=../../assets/appicon/icon.ico");
embed_resource::compile("resources/windows/oak.rc", embed_resource::NONE)
.manifest_optional()
.unwrap();
}
// --- OFX interact end-to-end test plugin ---------------------------------
// The app-side interact tests (src/oakui/ofx.rs) drive the *real*
// minimal test plugin (../../crates/oak-plugin/cbits/oak_test_plugin.c) through
+4
View File
@@ -0,0 +1,4 @@
// Icon resource ID 1 is what gpui_windows' `load_icon` reads for the
// window/taskbar icon; it is also the exe's Explorer icon. The path is
// resolved from the crate root (the build script's working directory).
1 ICON "../../assets/appicon/icon.ico"
+9
View File
@@ -3817,11 +3817,20 @@ fn run_with<E: AppEngine>(args: AppArgs) {
let bounds = Bounds::centered(None, size(px(1600.0), px(900.0)), cx);
let initial = initial.clone();
let show_manager = initial.is_none();
// The window/taskbar icon, per platform: X11 takes the pixels up
// front (_NET_WM_ICON, decoded here from the embedded PNG);
// Wayland resolves the icon from oak.desktop via the app id;
// Windows reads it from the exe's icon resource (see build.rs).
let icon = image::load_from_memory(include_bytes!("../../../assets/appicon/icon.png"))
.expect("the embedded app icon must decode")
.into_rgba8();
let mut root_slot = None;
let window = cx
.open_window(
WindowOptions {
window_bounds: Some(WindowBounds::Windowed(bounds)),
app_id: Some("oak".into()),
icon: Some(Arc::new(icon)),
..Default::default()
},
|window, cx| {
+1
View File
@@ -36,6 +36,7 @@ package() {
install -Dm755 "$OAK_BIN/oak-worker" "$pkgdir/usr/bin/oak-worker"
install -Dm644 "$OAK_ROOT/packaging/oak.desktop" "$pkgdir/usr/share/applications/oak.desktop"
install -Dm644 "$OAK_ROOT/icons/icon.png" "$pkgdir/usr/share/icons/hicolor/512x512/apps/oak.png"
install -Dm644 "$OAK_ROOT/Oak_Icon.svg" "$pkgdir/usr/share/icons/hicolor/scalable/apps/oak.svg"
for f in "$OAK_ROOT"/assets/i18n/*.yaml; do
install -Dm644 "$f" "$pkgdir/usr/share/oak/i18n/$(basename "$f")"
done
+2 -1
View File
@@ -26,12 +26,13 @@ STAGING=target/pkg/deb
rm -rf "$STAGING"
mkdir -p "$STAGING/usr/bin" "$STAGING/usr/share/applications" \
"$STAGING/usr/share/icons/hicolor/512x512/apps" "$STAGING/usr/share/oak/i18n" \
"$STAGING/DEBIAN"
"$STAGING/usr/share/icons/hicolor/scalable/apps" "$STAGING/DEBIAN"
install -m755 target/release/oak-editor target/release/oak-cli target/release/oak-worker \
"$STAGING/usr/bin/"
install -m644 packaging/oak.desktop "$STAGING/usr/share/applications/oak.desktop"
install -m644 icons/icon.png "$STAGING/usr/share/icons/hicolor/512x512/apps/oak.png"
install -m644 Oak_Icon.svg "$STAGING/usr/share/icons/hicolor/scalable/apps/oak.svg"
install -m644 assets/i18n/*.yaml "$STAGING/usr/share/oak/i18n/"
# The full shlib dependency set (FFmpeg/OCIO are statically linked, so
+3 -1
View File
@@ -28,11 +28,13 @@ mkdir -p "$TOP"/{BUILD,RPMS,SOURCES,SPECS,BUILDROOT}
ROOT="$TOP/BUILDROOT/oak-editor-$VERSION-1.x86_64"
mkdir -p "$ROOT/usr/bin" "$ROOT/usr/share/applications" \
"$ROOT/usr/share/icons/hicolor/512x512/apps" "$ROOT/usr/share/oak/i18n"
"$ROOT/usr/share/icons/hicolor/512x512/apps" "$ROOT/usr/share/oak/i18n" \
"$ROOT/usr/share/icons/hicolor/scalable/apps"
install -m755 target/release/oak-editor target/release/oak-cli target/release/oak-worker \
"$ROOT/usr/bin/"
install -m644 packaging/oak.desktop "$ROOT/usr/share/applications/oak.desktop"
install -m644 icons/icon.png "$ROOT/usr/share/icons/hicolor/512x512/apps/oak.png"
install -m644 Oak_Icon.svg "$ROOT/usr/share/icons/hicolor/scalable/apps/oak.svg"
install -m644 assets/i18n/*.yaml "$ROOT/usr/share/oak/i18n/"
rpmbuild -bb \
+1
View File
@@ -39,6 +39,7 @@ true
/usr/bin/oak-worker
/usr/share/applications/oak.desktop
/usr/share/icons/hicolor/512x512/apps/oak.png
/usr/share/icons/hicolor/scalable/apps/oak.svg
/usr/share/oak/i18n/
%changelog