Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions crates/gpui/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1317,6 +1317,16 @@ impl App {
self.platform.unhide_other_apps();
}

/// Sets the label drawn on the application's dock icon, or clears it with
/// `None`.
///
/// Only macOS implements it; elsewhere the call does nothing. A
/// menu-bar-only app (`ActivationPolicy::Accessory`) has no dock icon, so
/// the label has nowhere to appear.
pub fn set_dock_badge(&self, label: Option<&str>) {
self.platform.set_dock_badge(label);
}

/// Returns the list of currently active displays.
pub fn displays(&self) -> Vec<Rc<dyn PlatformDisplay>> {
self.platform.displays()
Expand Down
5 changes: 5 additions & 0 deletions crates/gpui/src/platform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,11 @@ pub trait Platform: 'static {
fn hide_other_apps(&self);
fn unhide_other_apps(&self);

/// Sets the label drawn on the application's dock icon, or clears it.
///
/// Only macOS implements it; the default is a no-op.
fn set_dock_badge(&self, _label: Option<&str>) {}

fn displays(&self) -> Vec<Rc<dyn PlatformDisplay>>;
fn primary_display(&self) -> Option<Rc<dyn PlatformDisplay>>;
fn active_window(&self) -> Option<AnyWindowHandle>;
Expand Down
2 changes: 1 addition & 1 deletion crates/gpui_macos/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ media.workspace = true
metal.workspace = true
objc.workspace = true
objc2.workspace = true
objc2-app-kit.workspace = true
objc2-app-kit = { workspace = true, features = ["NSApplication", "NSDockTile"] }
objc2-foundation.workspace = true
objc2-user-notifications.workspace = true
parking_lot.workspace = true
Expand Down
21 changes: 21 additions & 0 deletions crates/gpui_macos/src/dock.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//! The dock icon's badge, the one label macOS draws outside the app's windows.
//!
//! The badge belongs to the dock tile, so it only exists while the app has a
//! dock icon: a menu-bar-only app (activation policy `Accessory`) has nothing
//! to draw it on and this becomes a no-op.

use objc2::MainThreadMarker;
use objc2_app_kit::NSApplication;
use objc2_foundation::NSString;

/// Sets the dock icon's badge, or clears it with `None`.
pub(crate) fn set_dock_badge(label: Option<&str>) {
let Some(mtm) = MainThreadMarker::new() else {
log::warn!("the dock badge must be set on the main thread");
return;
};
let label = label.map(NSString::from_str);
NSApplication::sharedApplication(mtm)
.dockTile()
.setBadgeLabel(label.as_deref());
}
1 change: 1 addition & 0 deletions crates/gpui_macos/src/gpui_macos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
mod dispatcher;
mod display;
mod display_link;
mod dock;
mod events;
mod keyboard;
mod pasteboard;
Expand Down
4 changes: 4 additions & 0 deletions crates/gpui_macos/src/platform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -837,6 +837,10 @@ impl Platform for MacPlatform {
}
}

fn set_dock_badge(&self, label: Option<&str>) {
crate::dock::set_dock_badge(label);
}

fn primary_display(&self) -> Option<Rc<dyn PlatformDisplay>> {
Some(Rc::new(MacDisplay::primary()))
}
Expand Down