diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 71b6e5b20..717f2dd9d 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -23,6 +23,9 @@ version 0.7.0 [future] - Take the mouse wheel multiplier option in to account when generating fake key scroll events +- macOS: Fix closing top-level window does not transfer focus to other + top-level windows. + - kitty icat: Workaround for bug in ImageMagick that would cause some images to fail to display at certain sizes. diff --git a/kitty/glfw.c b/kitty/glfw.c index 27f0b096c..f13ab4648 100644 --- a/kitty/glfw.c +++ b/kitty/glfw.c @@ -143,6 +143,14 @@ scroll_callback(GLFWwindow *w, double xoffset, double yoffset) { global_state.callback_os_window = NULL; } +static inline void +push_focus_history(OSWindow *w) { + if (w->id != global_state.os_window_focus_history[1]) { + global_state.os_window_focus_history[0] = global_state.os_window_focus_history[1]; + global_state.os_window_focus_history[1] = w->id; + } +} + static void window_focus_callback(GLFWwindow *w, int focused) { if (!set_callback_window(w)) return; @@ -150,6 +158,7 @@ window_focus_callback(GLFWwindow *w, int focused) { if (focused) { show_mouse_cursor(w); focus_in_event(); + push_focus_history(global_state.callback_os_window); } double now = monotonic(); global_state.callback_os_window->last_mouse_activity_at = now; @@ -380,6 +389,7 @@ show_window(PyObject UNUSED *self, PyObject *args) { bool first_show = !w->shown_once; glfwShowWindow(w->handle); w->shown_once = true; + push_focus_history(w); if (first_show) { double before_x = global_state.logical_dpi_x, before_y = global_state.logical_dpi_y; set_dpi_from_os_window(w); @@ -402,6 +412,17 @@ destroy_os_window(OSWindow *w) { if (current_os_window_ctx == w->handle) current_os_window_ctx = NULL; } w->handle = NULL; +#ifdef __APPLE__ + // On macOS when closing a window, any other existing windows belonging to the same application do not + // automatically get focus, so we do it manually. + for (size_t i = 0; i < global_state.num_os_windows; i++) { + OSWindow *c = global_state.os_windows + i; + if (c->id != w->id && c->handle && c->shown_once && (c->id == global_state.os_window_focus_history[0] || c->id == global_state.os_window_focus_history[1])) { + glfwFocusWindow(c->handle); + break; + } + } +#endif } // Global functions {{{ diff --git a/kitty/state.h b/kitty/state.h index 6c93ca75f..8b1e97d5a 100644 --- a/kitty/state.h +++ b/kitty/state.h @@ -128,6 +128,7 @@ typedef struct { bool is_wayland; bool debug_gl; bool has_pending_resizes; + id_type os_window_focus_history[2]; } GlobalState; extern GlobalState global_state;