diff --git a/glfw/cocoa_window.m b/glfw/cocoa_window.m index 6d6a7e58920..91d5cf101ea 100644 --- a/glfw/cocoa_window.m +++ b/glfw/cocoa_window.m @@ -308,6 +308,7 @@ CGDirectDisplayID displayIDForWindow(_GLFWwindow *w) { } static unsigned long long display_link_shutdown_timer = 0; +static NSEvent* lastMouseDownEvent = NULL; #define DISPLAY_LINK_SHUTDOWN_CHECK_INTERVAL s_to_monotonic_t(30ll) void @@ -969,6 +970,7 @@ - (BOOL)acceptsFirstMouse:(NSEvent *)event - (void)mouseDown:(NSEvent *)event { if (!window) return; + lastMouseDownEvent = event; _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS, @@ -2692,6 +2694,12 @@ GLFWAPI void glfwCocoaRequestRenderFrame(GLFWwindow *w, GLFWcocoarenderframefun return _glfwPlatformGetNativeKeyForKey(glfw_key); } +GLFWAPI void +glfwPerformCocoaWindowDrag(GLFWwindow *handle) { + _GLFWwindow* window = (_GLFWwindow*) handle; + [window->ns.object performWindowDragWithEvent:lastMouseDownEvent]; +} + ////////////////////////////////////////////////////////////////////////// ////// GLFW internal API ////// diff --git a/glfw/glfw.py b/glfw/glfw.py index bdc6bf4c48d..f3e8f775081 100755 --- a/glfw/glfw.py +++ b/glfw/glfw.py @@ -211,6 +211,7 @@ def generate_wrappers(glfw_header: str) -> None: GLFWapplicationshouldhandlereopenfun glfwSetApplicationShouldHandleReopen(GLFWapplicationshouldhandlereopenfun callback) GLFWapplicationwillfinishlaunchingfun glfwSetApplicationWillFinishLaunching(GLFWapplicationwillfinishlaunchingfun callback) uint32_t glfwGetCocoaKeyEquivalent(uint32_t glfw_key, int glfw_mods, int* cocoa_mods) + void glfwPerformCocoaWindowDrag(GLFWwindow *handle) void glfwCocoaRequestRenderFrame(GLFWwindow *w, GLFWcocoarenderframefun callback) void* glfwGetX11Display(void) int32_t glfwGetX11Window(GLFWwindow* window) diff --git a/kitty/data-types.h b/kitty/data-types.h index 54bc4f994b3..0f41174b5e6 100644 --- a/kitty/data-types.h +++ b/kitty/data-types.h @@ -321,7 +321,7 @@ void colorprofile_report_stack(ColorProfile*, unsigned int*, unsigned int*); void set_mouse_cursor(MouseShape); void enter_event(void); -void mouse_event(int, int, int); +void mouse_event(GLFWwindow*, int, int, int); void focus_in_event(void); void scroll_event(double, double, int, int); void on_key_input(GLFWkeyevent *ev); diff --git a/kitty/glfw-wrapper.c b/kitty/glfw-wrapper.c index ad47a3f4dd4..032d9a17ce2 100644 --- a/kitty/glfw-wrapper.c +++ b/kitty/glfw-wrapper.c @@ -411,6 +411,9 @@ load_glfw(const char* path) { *(void **) (&glfwGetCocoaKeyEquivalent_impl) = dlsym(handle, "glfwGetCocoaKeyEquivalent"); if (glfwGetCocoaKeyEquivalent_impl == NULL) dlerror(); // clear error indicator + *(void **) (&glfwPerformCocoaWindowDrag_impl) = dlsym(handle, "glfwPerformCocoaWindowDrag"); + if (glfwPerformCocoaWindowDrag_impl == NULL) dlerror(); // clear error indicator + *(void **) (&glfwCocoaRequestRenderFrame_impl) = dlsym(handle, "glfwCocoaRequestRenderFrame"); if (glfwCocoaRequestRenderFrame_impl == NULL) dlerror(); // clear error indicator diff --git a/kitty/glfw-wrapper.h b/kitty/glfw-wrapper.h index 74a7a7fab93..d7035a27fd7 100644 --- a/kitty/glfw-wrapper.h +++ b/kitty/glfw-wrapper.h @@ -2128,6 +2128,10 @@ typedef uint32_t (*glfwGetCocoaKeyEquivalent_func)(uint32_t, int, int*); GFW_EXTERN glfwGetCocoaKeyEquivalent_func glfwGetCocoaKeyEquivalent_impl; #define glfwGetCocoaKeyEquivalent glfwGetCocoaKeyEquivalent_impl +typedef void (*glfwPerformCocoaWindowDrag_func)(GLFWwindow*); +GFW_EXTERN glfwPerformCocoaWindowDrag_func glfwPerformCocoaWindowDrag_impl; +#define glfwPerformCocoaWindowDrag glfwPerformCocoaWindowDrag_impl + typedef void (*glfwCocoaRequestRenderFrame_func)(GLFWwindow*, GLFWcocoarenderframefun); GFW_EXTERN glfwCocoaRequestRenderFrame_func glfwCocoaRequestRenderFrame_impl; #define glfwCocoaRequestRenderFrame glfwCocoaRequestRenderFrame_impl diff --git a/kitty/glfw.c b/kitty/glfw.c index 950c1ad341f..5a8f513bcdf 100644 --- a/kitty/glfw.c +++ b/kitty/glfw.c @@ -316,7 +316,7 @@ mouse_button_callback(GLFWwindow *w, int button, int action, int mods) { global_state.callback_os_window->last_mouse_activity_at = now; if (button >= 0 && (unsigned int)button < arraysz(global_state.callback_os_window->mouse_button_pressed)) { global_state.callback_os_window->mouse_button_pressed[button] = action == GLFW_PRESS ? true : false; - if (is_window_ready_for_callbacks()) mouse_event(button, mods, action); + if (is_window_ready_for_callbacks()) mouse_event(w, button, mods, action); } request_tick_callback(); global_state.callback_os_window = NULL; @@ -331,7 +331,7 @@ cursor_pos_callback(GLFWwindow *w, double x, double y) { global_state.callback_os_window->cursor_blink_zero_time = now; global_state.callback_os_window->mouse_x = x * global_state.callback_os_window->viewport_x_ratio; global_state.callback_os_window->mouse_y = y * global_state.callback_os_window->viewport_y_ratio; - if (is_window_ready_for_callbacks()) mouse_event(-1, mods_at_last_key_or_button_event, -1); + if (is_window_ready_for_callbacks()) mouse_event(w, -1, mods_at_last_key_or_button_event, -1); request_tick_callback(); global_state.callback_os_window = NULL; } diff --git a/kitty/mouse.c b/kitty/mouse.c index 44664fef5fd..b12aee365d2 100644 --- a/kitty/mouse.c +++ b/kitty/mouse.c @@ -187,14 +187,6 @@ contains_mouse(Window *w) { return (w->visible && window_left(w) <= x && x <= window_right(w) && window_top(w) <= y && y <= window_bottom(w)); } -static inline double -distance_to_window(Window *w) { - double x = global_state.callback_os_window->mouse_x, y = global_state.callback_os_window->mouse_y; - double cx = (window_left(w) + window_right(w)) / 2.0; - double cy = (window_top(w) + window_bottom(w)) / 2.0; - return (x - cx) * (x - cx) + (y - cy) * (y - cy); -} - static bool clamp_to_window = false; static inline bool @@ -529,23 +521,6 @@ window_for_event(unsigned int *window_idx, bool *in_tab_bar) { return NULL; } -static inline Window* -closest_window_for_event(unsigned int *window_idx) { - Window *ans = NULL; - double closest_distance = UINT_MAX; - if (global_state.callback_os_window->num_tabs > 0) { - Tab *t = global_state.callback_os_window->tabs + global_state.callback_os_window->active_tab; - for (unsigned int i = 0; i < t->num_windows; i++) { - Window *w = t->windows + i; - if (w->visible) { - double d = distance_to_window(w); - if (d < closest_distance) { ans = w; closest_distance = d; *window_idx = i; } - } - } - } - return ans; -} - void focus_in_event() { // Ensure that no URL is highlighted and the mouse cursor is in default shape @@ -629,7 +604,7 @@ mouse_selection(Window *w, int code, int button) { void -mouse_event(int button, int modifiers, int action) { +mouse_event(GLFWwindow *window, int button, int modifiers, int action) { MouseShape old_cursor = mouse_cursor_shape; bool in_tab_bar; unsigned int window_idx = 0; @@ -671,13 +646,8 @@ mouse_event(int button, int modifiers, int action) { handle_event(w, button, modifiers, window_idx); } else if (button == GLFW_MOUSE_BUTTON_LEFT && global_state.callback_os_window->mouse_button_pressed[button]) { // initial click, clamp it to the closest window - w = closest_window_for_event(&window_idx); - if (w) { - clamp_to_window = true; - debug("grabbed: %d\n", w->render_data.screen->modes.mouse_tracking_mode != 0); - handle_event(w, button, modifiers, window_idx); - clamp_to_window = false; - } else debug("no window for event\n"); + debug("start window drag move\n"); + glfwPerformCocoaWindowDrag(window); } else debug("\n"); if (mouse_cursor_shape != old_cursor) { set_mouse_cursor(mouse_cursor_shape);