From 4b2f404da151e59bed31020805ba1dba9a64f289 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sun, 21 Jun 2026 00:51:57 +0200 Subject: [PATCH] UI/Qt: Honor AppKit window drag gesture macOS can be configured to drag windows with Cmd+Ctrl+click via NSWindowShouldDragOnGesture. AppKit does not see its usual titlebar drag path for our frameless Qt windows, so handle the native mouse down in the AppKit event filter when that default is enabled. Forward the event to performWindowDragWithEvent before Qt turns it into normal widget input. This restores the system gesture without changing behavior for users who have not enabled the default. --- UI/Qt/MacWindow.mm | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/UI/Qt/MacWindow.mm b/UI/Qt/MacWindow.mm index 7b2b5b16d8..ee0d1c8e2d 100644 --- a/UI/Qt/MacWindow.mm +++ b/UI/Qt/MacWindow.mm @@ -66,6 +66,11 @@ namespace Ladybird { static NSEvent* s_latest_window_drag_event; +static bool is_window_drag_on_gesture_enabled() +{ + return [[NSUserDefaults standardUserDefaults] boolForKey:@"NSWindowShouldDragOnGesture"]; +} + static bool is_appkit_event_type(QByteArray const& event_type) { return event_type == QByteArrayLiteral("NSEvent") @@ -86,6 +91,25 @@ static bool is_window_drag_event(NSEvent* event) } } +static bool should_start_window_drag_for_gesture(NSEvent* event) +{ + if (!event || event.type != NSEventTypeLeftMouseDown) + return false; + + if (!is_window_drag_on_gesture_enabled()) + return false; + + auto modifier_flags = event.modifierFlags & NSEventModifierFlagDeviceIndependentFlagsMask; + if ((modifier_flags & (NSEventModifierFlagCommand | NSEventModifierFlagControl)) != (NSEventModifierFlagCommand | NSEventModifierFlagControl)) + return false; + + auto* window = event.window; + if (!window || !window.isMovable || (window.styleMask & NSWindowStyleMaskFullScreen)) + return false; + + return true; +} + class LadybirdAppKitEventCaptureFilter final : public QAbstractNativeEventFilter { public: virtual bool nativeEventFilter(QByteArray const& event_type, void* message, qintptr*) override @@ -94,6 +118,11 @@ public: return false; auto* event = static_cast(message); + if (should_start_window_drag_for_gesture(event)) { + [event.window performWindowDragWithEvent:event]; + return true; + } + if (!is_window_drag_event(event)) return false;