commit 1b77a312146f8b1a89bdaa78f570ec8f2c2a18cf
parent f2cbab62d8272d385cf5381078ea43842596f773
Author: William Casarin <jb55@jb55.com>
Date: Tue, 10 Feb 2026 10:55:56 -0800
dave: use activateWithOptions and orderFrontRegardless on macOS
NSApplication::activate does not reliably bring the app to front
in Stage Manager single-window mode. Use NSRunningApplication
activateWithOptions with ActivateAllWindows and orderFrontRegardless
on the key window to force activation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat:
2 files changed, 21 insertions(+), 5 deletions(-)
diff --git a/crates/notedeck_dave/Cargo.toml b/crates/notedeck_dave/Cargo.toml
@@ -35,7 +35,7 @@ rfd = { workspace = true }
[target.'cfg(target_os = "macos")'.dependencies]
objc2 = "0.6.1"
-objc2-app-kit = { version = "0.3.1", features = ["NSApplication", "NSResponder", "NSRunningApplication"] }
+objc2-app-kit = { version = "0.3.1", features = ["NSApplication", "NSResponder", "NSRunningApplication", "NSWindow"] }
[dev-dependencies]
tokio = { version = "1", features = ["rt-multi-thread", "macros", "test-util"] }
diff --git a/crates/notedeck_dave/src/lib.rs b/crates/notedeck_dave/src/lib.rs
@@ -930,20 +930,36 @@ impl notedeck::App for Dave {
/// Bring the application to the front.
///
/// On macOS, egui's ViewportCommand::Focus focuses the window but doesn't
-/// always activate the app (bring it in front of other apps), so we also
-/// call NSApplication::activateIgnoringOtherApps.
+/// always activate the app (bring it in front of other apps). Stage Manager
+/// single-window mode is particularly aggressive, so we use both
+/// NSRunningApplication::activateWithOptions and orderFrontRegardless
+/// on the key window.
fn activate_app(ctx: &egui::Context) {
ctx.send_viewport_cmd(egui::ViewportCommand::Focus);
#[cfg(target_os = "macos")]
{
use objc2::MainThreadMarker;
- use objc2_app_kit::NSApplication;
+ use objc2_app_kit::{
+ NSApplication, NSApplicationActivationOptions, NSRunningApplication,
+ };
// Safety: UI update runs on the main thread
if let Some(mtm) = MainThreadMarker::new() {
let app = NSApplication::sharedApplication(mtm);
- unsafe { app.activate() };
+
+ // Activate via NSRunningApplication for per-process activation
+ let current = unsafe { NSRunningApplication::currentApplication() };
+ unsafe {
+ current.activateWithOptions(
+ NSApplicationActivationOptions::ActivateAllWindows,
+ );
+ };
+
+ // Also force the key window to front regardless of Stage Manager
+ if let Some(window) = app.keyWindow() {
+ unsafe { window.orderFrontRegardless() };
+ }
}
}
}