diff --git a/src/Eto.Mac/Forms/ApplicationHandler.cs b/src/Eto.Mac/Forms/ApplicationHandler.cs index 36df3216d1..b2ab355771 100644 --- a/src/Eto.Mac/Forms/ApplicationHandler.cs +++ b/src/Eto.Mac/Forms/ApplicationHandler.cs @@ -3,7 +3,7 @@ using System.Runtime.CompilerServices; namespace Eto.Mac.Forms { - public class ApplicationHandler : MacObject, Application.IHandler + public class ApplicationHandler : MacObject, Application.IHandler, Application.IActivateHandler { bool _attached; bool? _activateOnStartup; @@ -371,15 +371,21 @@ internal void EnsureActivated(bool showInTaskbar, bool showActivated, Icon icon) if (!showActivated) return; - // taking activation from whatever app has it is only for callers that opted in, and has to be done - // for every window since another app can take it back at any point during a run - if (ActivateIgnoringOtherApps) - Control.ActivateIgnoringOtherApps(true); - // otherwise only ask for it as the app gets its first window, which is all macOS will grant anyway - else if (showInTaskbar && wasProhibited) + // Later shows should not take activation unless explicitly opted in. + if (ActivateIgnoringOtherApps || showInTaskbar && wasProhibited) + RequestActivation(false); + } + + void RequestActivation(bool explicitlyRequested) + { + if (MacVersion.IsAtLeast(14, 0) && !ActivateIgnoringOtherApps) Control.Activate(); + else + Control.ActivateIgnoringOtherApps(explicitlyRequested || ActivateIgnoringOtherApps); } + public void Activate() => RequestActivation(true); + public Keys CommonModifier => Keys.Application; public Keys AlternateModifier => Keys.Alt; diff --git a/src/Eto/Forms/Application.cs b/src/Eto/Forms/Application.cs index 78b4d69528..fb40e82926 100755 --- a/src/Eto/Forms/Application.cs +++ b/src/Eto/Forms/Application.cs @@ -583,6 +583,23 @@ public string BadgeLabel /// public bool IsActive => Handler.IsActive; + /// + /// Requests native application activation. + /// + /// + /// This method is supported by the native macOS backend and has no effect on other backends. + /// The operating system may delay or decline activation; use and + /// to observe the activation state. + /// Call this method on the UI thread before calling on the desired window. + /// + /// + /// + public void Activate() + { + EnsureUIThread(); + (Handler as IActivateHandler)?.Activate(); + } + /// /// Advanced. Runs an iteration of the main UI loop when you are blocking the UI thread with logic. /// @@ -830,4 +847,15 @@ public void OnThemeChanged(Application widget, EventArgs e) /// Theme Theme { get; set; } } + + /// + /// Optional handler for native application activation. + /// + public interface IActivateHandler + { + /// + /// Requests native application activation. + /// + void Activate(); + } } \ No newline at end of file