From 717bc8a26fff74caa6128e790f59ae0c91d7e405 Mon Sep 17 00:00:00 2001 From: Roopesh Chander Date: Wed, 22 May 2019 15:26:38 +0530 Subject: macOS: Workaround for unresponsive main menu after reopen Signed-off-by: Roopesh Chander --- WireGuard/WireGuard/UI/macOS/AppDelegate.swift | 48 ++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 6 deletions(-) (limited to 'WireGuard/WireGuard') diff --git a/WireGuard/WireGuard/UI/macOS/AppDelegate.swift b/WireGuard/WireGuard/UI/macOS/AppDelegate.swift index b53deb7..c897111 100644 --- a/WireGuard/WireGuard/UI/macOS/AppDelegate.swift +++ b/WireGuard/WireGuard/UI/macOS/AppDelegate.swift @@ -13,6 +13,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { var manageTunnelsRootVC: ManageTunnelsRootViewController? var manageTunnelsWindowObject: NSWindow? + var onAppDeactivation: (() -> Void)? func applicationDidFinishLaunching(_ aNotification: Notification) { Logger.configureGlobal(tagged: "APP", withFilePath: FileManager.logFileURL?.path) @@ -24,7 +25,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { } if !isLaunchedAtLogin { - NSApp.setActivationPolicy(.regular) + setDockIconAndMainMenuVisibility(isVisible: true) } NSApp.mainMenu = MainMenu() @@ -121,9 +122,44 @@ class AppDelegate: NSObject, NSApplicationDelegate { } func applicationShouldTerminateAfterLastWindowClosed(_ application: NSApplication) -> Bool { - application.setActivationPolicy(.accessory) + setDockIconAndMainMenuVisibility(isVisible: false) return false } + + private func setDockIconAndMainMenuVisibility(isVisible: Bool, completion: (() -> Void)? = nil) { + let currentActivationPolicy = NSApp.activationPolicy() + let newActivationPolicy: NSApplication.ActivationPolicy = isVisible ? .regular : .accessory + guard currentActivationPolicy != newActivationPolicy else { + if newActivationPolicy == .regular { + NSApp.activate(ignoringOtherApps: true) + } + completion?() + return + } + if newActivationPolicy == .regular && NSApp.isActive { + // To workaround a possible AppKit bug that causes the main menu to become unresponsive, + // we should deactivate the app first and then set the activation policy. + // NSApp.deactivate() doesn't always deactivate the app, so we instead use + // setActivationPolicy(.prohibited). + onAppDeactivation = { + NSApp.setActivationPolicy(.regular) + NSApp.activate(ignoringOtherApps: true) + completion?() + } + NSApp.setActivationPolicy(.prohibited) + } else { + NSApp.setActivationPolicy(newActivationPolicy) + if newActivationPolicy == .regular { + NSApp.activate(ignoringOtherApps: true) + } + completion?() + } + } + + func applicationDidResignActive(_ notification: Notification) { + onAppDeactivation?() + onAppDeactivation = nil + } } extension AppDelegate { @@ -159,10 +195,10 @@ extension AppDelegate: StatusMenuWindowDelegate { manageTunnelsWindowObject = window tunnelsTracker?.manageTunnelsRootVC = manageTunnelsRootVC } - NSApp.setActivationPolicy(.regular) - NSApp.activate(ignoringOtherApps: true) - manageTunnelsWindowObject!.makeKeyAndOrderFront(self) - completion?(manageTunnelsWindowObject) + setDockIconAndMainMenuVisibility(isVisible: true) { [weak manageTunnelsWindowObject] in + manageTunnelsWindowObject?.makeKeyAndOrderFront(self) + completion?(manageTunnelsWindowObject) + } } } -- cgit v1.2.3-59-g8ed1b