Skip to content

Commit 2ac7a5c

Browse files
committed
feat(macos): follow the system theme for the Dock icon
1 parent bfcb211 commit 2ac7a5c

5 files changed

Lines changed: 86 additions & 0 deletions

File tree

src-tauri/Cargo.lock

Lines changed: 24 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src-tauri/Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,11 @@ tracing-appender = "0.2"
9999
thiserror = "2"
100100
anyhow = "1"
101101

102+
[target.'cfg(target_os = "macos")'.dependencies]
103+
objc2 = "0.6"
104+
objc2-app-kit = { version = "0.3", features = ["NSApplication", "NSImage", "NSResponder"] }
105+
objc2-foundation = { version = "0.3", features = ["NSData"] }
106+
102107
[target.'cfg(windows)'.dependencies]
103108
winreg = "0.52"
104109

77.5 KB
Loading

src-tauri/src/dock_icon.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//
2+
// Aster Communications Inc.
3+
//
4+
// Copyright (c) 2026 Aster Communications Inc.
5+
//
6+
// This file is part of this project.
7+
//
8+
// This program is free software: you can redistribute it and/or modify
9+
// it under the terms of the GNU Affero General Public License as published by
10+
// the Free Software Foundation, either version 3 of the License, or
11+
// (at your option) any later version.
12+
//
13+
// This program is distributed in the hope that it will be useful,
14+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
// GNU Affero General Public License for more details.
17+
//
18+
// You should have received a copy of the GNU Affero General Public License
19+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
20+
//
21+
use objc2::{AnyThread, MainThreadMarker};
22+
use objc2_app_kit::{NSApplication, NSImage};
23+
use objc2_foundation::NSData;
24+
use tauri::Theme;
25+
26+
const LIGHT_ICON: &[u8] = include_bytes!("../icons/icon_macos.png");
27+
const DARK_ICON: &[u8] = include_bytes!("../icons/icon_macos_dark.png");
28+
29+
pub fn apply(theme: Theme) {
30+
let Some(main_thread) = MainThreadMarker::new() else {
31+
return;
32+
};
33+
let bytes = match theme {
34+
Theme::Dark => DARK_ICON,
35+
_ => LIGHT_ICON,
36+
};
37+
let data = NSData::with_bytes(bytes);
38+
let Some(image) = NSImage::initWithData(NSImage::alloc(), &data) else {
39+
return;
40+
};
41+
unsafe {
42+
NSApplication::sharedApplication(main_thread).setApplicationIconImage(Some(&image));
43+
}
44+
}

src-tauri/src/main.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ mod crypto;
2929
mod dav;
3030
mod db;
3131
mod diagnostics;
32+
#[cfg(target_os = "macos")]
33+
mod dock_icon;
3234
mod error;
3335
mod imap;
3436
mod jmap;
@@ -1805,6 +1807,13 @@ fn main() {
18051807
.setup(move |app| {
18061808
sync::poller::set_global_app_handle(Some(app.handle().clone()));
18071809

1810+
#[cfg(target_os = "macos")]
1811+
dock_icon::apply(
1812+
app.get_webview_window("main")
1813+
.and_then(|w| w.theme().ok())
1814+
.unwrap_or(tauri::Theme::Light),
1815+
);
1816+
18081817
let icon_bytes = include_bytes!("../icons/128x128.png");
18091818

18101819
let icon =
@@ -2335,6 +2344,10 @@ fn main() {
23352344
api.prevent_close();
23362345
let _ = window.hide();
23372346
}
2347+
#[cfg(target_os = "macos")]
2348+
if let WindowEvent::ThemeChanged(theme) = event {
2349+
dock_icon::apply(*theme);
2350+
}
23382351
})
23392352
.build(tauri::generate_context!())
23402353
.expect("failed to start aster bridge desktop")

0 commit comments

Comments
 (0)