From 55a2f2c55c92112aa34716f859a85ff2a05b24c4 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 21 Jul 2025 14:55:12 +0530 Subject: [PATCH] Cocoa: fix quick access terminal hide focus restore Apple now makes kitty the front most application before sending the service notification. So instead watch for front most application change events from the shared workspace and restore focus to the last non-self application. --- docs/changelog.rst | 3 +++ glfw/cocoa_init.m | 14 ++++++++++++++ glfw/cocoa_platform.h | 2 +- glfw/cocoa_window.m | 7 +------ 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 5e348338f..c4db86a70 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -115,6 +115,9 @@ Detailed list of changes - Wayland: Fix incorrect window size calculation when transitioning from fullscreen to non-fullscreen with client side decorations (:iss:`8826`) +- macOS: Fix hiding quick access terminal window not restoring focus to + previously active application (:disc:`8840`) + 0.42.2 [2025-07-16] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/glfw/cocoa_init.m b/glfw/cocoa_init.m index 5762b01a2..d40e7210a 100644 --- a/glfw/cocoa_init.m +++ b/glfw/cocoa_init.m @@ -301,6 +301,14 @@ static NSDictionary *global_shortcuts = nil; @implementation GLFWApplicationDelegate +- (void)applicationDidActivate:(NSNotification *)notification { + NSRunningApplication *app = notification.userInfo[NSWorkspaceApplicationKey]; + if (app && app.processIdentifier != getpid()) { + _glfw.ns.previous_front_most_application = app.processIdentifier; + debug_rendering("Front most application changed to: %s pid: %d\n", app.bundleIdentifier.UTF8String, app.processIdentifier) + } +} + - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender { (void)sender; @@ -452,6 +460,7 @@ static GLFWapplicationwillfinishlaunchingfun finish_launching_callback = NULL; CGDirectDisplayID displayID = [(NSNumber*)displayIDAsID unsignedIntValue]; _glfwDispatchRenderFrame(displayID); } + @end @@ -816,6 +825,11 @@ int _glfwPlatformInit(bool *supports_window_occlusion) } [NSApp setDelegate:_glfw.ns.delegate]; + [[[NSWorkspace sharedWorkspace] notificationCenter] + addObserver:_glfw.ns.delegate + selector:@selector(applicationDidActivate:) + name:NSWorkspaceDidActivateApplicationNotification + object:nil]; static struct { unsigned short virtual_key_code; NSEventModifierFlags input_source_switch_modifiers; diff --git a/glfw/cocoa_platform.h b/glfw/cocoa_platform.h index 2adf33600..9c4a79f0b 100644 --- a/glfw/cocoa_platform.h +++ b/glfw/cocoa_platform.h @@ -125,7 +125,6 @@ typedef struct _GLFWwindowNS id delegate; id view; id layer; - pid_t previous_front_most_application; bool maximized; bool retina; @@ -189,6 +188,7 @@ typedef struct _GLFWlibraryNS double restoreCursorPosX, restoreCursorPosY; // The window whose disabled cursor mode is active _GLFWwindow* disabledCursorWindow; + pid_t previous_front_most_application; struct { CFBundleRef bundle; diff --git a/glfw/cocoa_window.m b/glfw/cocoa_window.m index d9d8f30b5..0cbc95acc 100644 --- a/glfw/cocoa_window.m +++ b/glfw/cocoa_window.m @@ -2228,20 +2228,15 @@ void _glfwPlatformMaximizeWindow(_GLFWwindow* window) void _glfwPlatformShowWindow(_GLFWwindow* window) { - NSRunningApplication *app = [[NSWorkspace sharedWorkspace] frontmostApplication]; - window->ns.previous_front_most_application = 0; - if (app && app.processIdentifier != getpid()) window->ns.previous_front_most_application = app.processIdentifier; if (window->ns.layer_shell.is_active && window->ns.layer_shell.config.type == GLFW_LAYER_SHELL_BACKGROUND) { [window->ns.object orderBack:nil]; } else [window->ns.object orderFront:nil]; - debug("Previously active application pid: %d bundle identifier: %s\n", - window->ns.previous_front_most_application, app ? app.bundleIdentifier.UTF8String : ""); } void _glfwPlatformHideWindow(_GLFWwindow* window) { [window->ns.object orderOut:nil]; - pid_t prev_app_pid = window->ns.previous_front_most_application; window->ns.previous_front_most_application = 0; + pid_t prev_app_pid = _glfw.ns.previous_front_most_application; _glfw.ns.previous_front_most_application = 0; NSRunningApplication *app; if (window->ns.layer_shell.is_active && prev_app_pid > 0 && (app = [NSRunningApplication runningApplicationWithProcessIdentifier:prev_app_pid])) { unsigned num_visible = 0;