diff --git a/docs/changelog.rst b/docs/changelog.rst index 5eb2c7ec7..c43df4a92 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -36,7 +36,10 @@ Changelog file is text (:pull:`752`) - kitty @ new-window: Add a new option :option:`kitty @ new-window --window-type` - to create top-level OS windows. (:iss:`770`) + to create top-level OS windows (:iss:`770`) + +- The :opt:`focus_follows_mouse` option now also works across top-level kitty OS windows + (:iss:`754`) 0.11.3 [2018-07-10] diff --git a/glfw/cocoa_window.m b/glfw/cocoa_window.m index 860b1677d..6e3874b84 100644 --- a/glfw/cocoa_window.m +++ b/glfw/cocoa_window.m @@ -739,7 +739,7 @@ - (void)updateTrackingAreas } const NSTrackingAreaOptions options = NSTrackingMouseEnteredAndExited | - NSTrackingActiveInKeyWindow | + NSTrackingActiveAlways | NSTrackingEnabledDuringMouseDrag | NSTrackingCursorUpdate | NSTrackingInVisibleRect | @@ -1083,7 +1083,7 @@ - (void)doNothing:(id)object } - (void)loadMainMenu -{ // removed by Kovid as it generated compiler warnings +{ // removed by Kovid as it generated compiler warnings } @end diff --git a/kitty/cocoa_window.m b/kitty/cocoa_window.m index 2bae366f7..5cd18090a 100644 --- a/kitty/cocoa_window.m +++ b/kitty/cocoa_window.m @@ -218,6 +218,12 @@ + (GlobalMenuTarget *) shared_instance return true; } +void +cocoa_focus_window(void *w) { + NSWindow *window = (NSWindow*)w; + [window makeKeyWindow]; +} + static PyObject* cocoa_get_lang(PyObject UNUSED *self) { NSString* locale = nil; diff --git a/kitty/data-types.h b/kitty/data-types.h index 3ebd684f5..09b793823 100644 --- a/kitty/data-types.h +++ b/kitty/data-types.h @@ -280,6 +280,7 @@ void colorprofile_push_dynamic_colors(ColorProfile*); void colorprofile_pop_dynamic_colors(ColorProfile*); void set_mouse_cursor(MouseShape); +void enter_event(); void mouse_event(int, int); void focus_in_event(); void wakeup_io_loop(bool); diff --git a/kitty/glfw.c b/kitty/glfw.c index da31ac4d8..7185a454c 100644 --- a/kitty/glfw.c +++ b/kitty/glfw.c @@ -9,6 +9,7 @@ #include #include "glfw-wrapper.h" extern bool cocoa_make_window_resizable(void *w, bool); +extern void cocoa_focus_window(void *w); extern void cocoa_create_global_menu(void); extern void cocoa_set_hide_from_tasks(void); extern void cocoa_set_titlebar_color(void *w, color_type color); @@ -138,6 +139,18 @@ key_callback(GLFWwindow *w, int key, int scancode, int action, int mods, const c global_state.callback_os_window = NULL; } +static void +cursor_enter_callback(GLFWwindow *w, int entered) { + if (!set_callback_window(w)) return; + if (entered) { + show_mouse_cursor(w); + double now = monotonic(); + global_state.callback_os_window->last_mouse_activity_at = now; + if (is_window_ready_for_callbacks()) enter_event(); + } + global_state.callback_os_window = NULL; +} + static void mouse_button_callback(GLFWwindow *w, int button, int action, int mods) { if (!set_callback_window(w)) return; @@ -489,6 +502,7 @@ create_os_window(PyObject UNUSED *self, PyObject *args) { glfwSetFramebufferSizeCallback(glfw_window, framebuffer_size_callback); glfwSetWindowContentScaleCallback(glfw_window, dpi_change_callback); glfwSetWindowRefreshCallback(glfw_window, refresh_callback); + glfwSetCursorEnterCallback(glfw_window, cursor_enter_callback); glfwSetMouseButtonCallback(glfw_window, mouse_button_callback); glfwSetScrollCallback(glfw_window, scroll_callback); glfwSetCursorPosCallback(glfw_window, cursor_pos_callback); @@ -544,8 +558,16 @@ destroy_os_window(OSWindow *w) { } void -focus_os_window(OSWindow *w) { - if (w->handle) glfwFocusWindow(w->handle); +focus_os_window(OSWindow *w, bool also_raise) { + if (w->handle) { +#ifdef __APPLE__ + if (!also_raise) cocoa_focus_window(glfwGetCocoaWindow(w->handle)); + else glfwFocusWindow(w->handle); +#else + (void)also_raise; + glfwFocusWindow(w->handle); +#endif + } } #ifdef __APPLE__ diff --git a/kitty/mouse.c b/kitty/mouse.c index 4ebb562f1..ad0126e77 100644 --- a/kitty/mouse.c +++ b/kitty/mouse.c @@ -451,6 +451,13 @@ focus_in_event() { if (w && w->render_data.screen) screen_mark_url(w->render_data.screen, 0, 0, 0, 0); } +void +enter_event() { + if (OPT(focus_follows_mouse) && !global_state.callback_os_window->is_focused) { + focus_os_window(global_state.callback_os_window, false); + } +} + void mouse_event(int button, int modifiers) { MouseShape old_cursor = mouse_cursor_shape; diff --git a/kitty/state.c b/kitty/state.c index 7afdc454f..5891be760 100644 --- a/kitty/state.c +++ b/kitty/state.c @@ -499,9 +499,10 @@ PYWRAP1(mark_os_window_for_close) { PYWRAP1(focus_os_window) { id_type os_window_id; - PA("K", &os_window_id); + int also_raise = 1; + PA("K|p", &os_window_id, &also_raise); WITH_OS_WINDOW(os_window_id) - if (!os_window->is_focused) focus_os_window(os_window); + if (!os_window->is_focused) focus_os_window(os_window, also_raise); Py_RETURN_TRUE; END_WITH_OS_WINDOW Py_RETURN_FALSE; diff --git a/kitty/state.h b/kitty/state.h index 2e4a33cc3..08f3b4e50 100644 --- a/kitty/state.h +++ b/kitty/state.h @@ -170,7 +170,7 @@ void swap_window_buffers(OSWindow *w); void make_window_context_current(OSWindow *w); void hide_mouse(OSWindow *w); void destroy_os_window(OSWindow *w); -void focus_os_window(OSWindow *w); +void focus_os_window(OSWindow *w, bool also_raise); void set_os_window_title(OSWindow *w, const char *title); OSWindow* os_window_for_kitty_window(id_type); OSWindow* add_os_window();