macos: Send dragging events directly to the display
authorArjan Molenaar <gaphor@gmail.com>
Sat, 21 Jan 2023 13:54:12 +0000 (14:54 +0100)
committerArjan Molenaar <gaphor@gmail.com>
Sat, 21 Jan 2023 13:54:12 +0000 (14:54 +0100)
Instead of adding events to the application event queue, dispatch
them directly to the right display. We know this when the event is
to be dispatched.

This is the same as used for the `sendEvent` method in `GdkMacosWindow`.

To achieve this I factored out the generic NSEvent to GdkEvent translation.
We can send an event directly, when we receive it in the GdkMacosWindow
directly from the OS.

gdk/macos/GdkMacosWindow.c
gdk/macos/gdkmacosdisplay-private.h
gdk/macos/gdkmacosdisplay-translate.c
gdk/macos/gdkmacoseventsource-private.h
gdk/macos/gdkmacoseventsource.c

index 79a25c04d3bdb78b2a069f09428e6d1193641f49..0636018c9388aa97624132ad7c2ad6e4690271ef 100644 (file)
@@ -146,7 +146,7 @@ typedef NSString *CALayerContentsGravity;
        *
        * TODO: Can we improve grab breaking to fix this?
        */
-      _gdk_macos_display_send_button_event ([self gdkDisplay], event);
+      _gdk_macos_display_send_event ([self gdkDisplay], event);
 
       _gdk_macos_display_break_all_grabs (GDK_MACOS_DISPLAY (display), time);
 
@@ -698,23 +698,23 @@ typedef NSString *CALayerContentsGravity;
 - (void)draggingSession:(NSDraggingSession *)session movedToPoint:(NSPoint)screenPoint
 {
   NSInteger sequence_number = [session draggingSequenceNumber];
-  GdkDisplay *display = gdk_surface_get_display (GDK_SURFACE (gdk_surface));
+  GdkMacosDisplay *display = GDK_MACOS_DISPLAY (gdk_surface_get_display (GDK_SURFACE (gdk_surface)));
   GdkDrag *drag = _gdk_macos_display_find_drag (GDK_MACOS_DISPLAY (display), sequence_number);
   int x, y;
 
-  _gdk_macos_event_source_queue_event ([NSApp currentEvent]);
+  _gdk_macos_display_send_event (display, [NSApp currentEvent]);
 
-  _gdk_macos_display_from_display_coords (GDK_MACOS_DISPLAY (display), screenPoint.x, screenPoint.y, &x, &y);
+  _gdk_macos_display_from_display_coords (display, screenPoint.x, screenPoint.y, &x, &y);
   _gdk_macos_drag_surface_move (GDK_MACOS_DRAG (drag), x, y);
 }
 
 - (void)draggingSession:(NSDraggingSession *)session endedAtPoint:(NSPoint)screenPoint operation:(NSDragOperation)operation
 {
   NSInteger sequence_number = [session draggingSequenceNumber];
-  GdkDisplay *display = gdk_surface_get_display (GDK_SURFACE (gdk_surface));
-  GdkDrag *drag = _gdk_macos_display_find_drag (GDK_MACOS_DISPLAY (display), sequence_number);
+  GdkMacosDisplay *display = GDK_MACOS_DISPLAY (gdk_surface_get_display (GDK_SURFACE (gdk_surface)));
+  GdkDrag *drag = _gdk_macos_display_find_drag (display, sequence_number);
 
-  _gdk_macos_event_source_queue_event ([NSApp currentEvent]);
+  _gdk_macos_display_send_event (display, [NSApp currentEvent]);
   gdk_drag_set_selected_action (drag, _gdk_macos_drag_ns_operation_to_action (operation));
 
   if (gdk_drag_get_selected_action (drag) != 0)
@@ -722,7 +722,7 @@ typedef NSString *CALayerContentsGravity;
   else
     gdk_drag_cancel (drag, GDK_DRAG_CANCEL_NO_TARGET);
 
-  _gdk_macos_display_set_drag (GDK_MACOS_DISPLAY (display), [session draggingSequenceNumber], NULL);
+  _gdk_macos_display_set_drag (display, [session draggingSequenceNumber], NULL);
 }
 
 // end
index 122d004cec6ee7f9d769b9858755edd724574ced..9fc910ec2e58eb77e7b9f384e8bef7ea212d3ea8 100644 (file)
@@ -155,7 +155,7 @@ void             _gdk_macos_display_surface_became_key             (GdkMacosDisp
                                                                     GdkMacosSurface *surface);
 void             _gdk_macos_display_clear_sorting                  (GdkMacosDisplay *self);
 const GList     *_gdk_macos_display_get_surfaces                   (GdkMacosDisplay *self);
-void             _gdk_macos_display_send_button_event              (GdkMacosDisplay *self,
+void             _gdk_macos_display_send_event                     (GdkMacosDisplay *self,
                                                                     NSEvent         *nsevent);
 void             _gdk_macos_display_warp_pointer                   (GdkMacosDisplay *self,
                                                                     int              x,
index b06dc83dbe8c999e9fe07ea560dc278a6c05ec6a..f6d4a23991badeefab2582b41075fb7c2ea66a6a 100644 (file)
@@ -723,6 +723,85 @@ fill_scroll_event (GdkMacosDisplay *self,
   return g_steal_pointer (&ret);
 }
 
+
+static GdkEvent *
+fill_event (GdkMacosDisplay *self,
+            GdkMacosWindow  *window,
+            NSEvent         *nsevent,
+            int              x,
+            int              y)
+{
+  GdkMacosSurface *surface = [window gdkSurface];
+  NSEventType event_type = [nsevent type];
+  GdkEvent *ret = NULL;
+
+  switch ((int)event_type)
+    {
+    case NSEventTypeLeftMouseDown:
+    case NSEventTypeRightMouseDown:
+    case NSEventTypeOtherMouseDown:
+    case NSEventTypeLeftMouseUp:
+    case NSEventTypeRightMouseUp:
+    case NSEventTypeOtherMouseUp:
+      ret = fill_button_event (self, surface, nsevent, x, y);
+      break;
+
+    case NSEventTypeLeftMouseDragged:
+    case NSEventTypeRightMouseDragged:
+    case NSEventTypeOtherMouseDragged:
+    case NSEventTypeMouseMoved:
+      ret = fill_motion_event (self, surface, nsevent, x, y);
+      break;
+
+    case NSEventTypeMagnify:
+    case NSEventTypeRotate:
+      ret = fill_pinch_event (self, surface, nsevent, x, y);
+      break;
+
+    case NSEventTypeMouseExited:
+    case NSEventTypeMouseEntered:
+      {
+        GdkSeat *seat = gdk_display_get_default_seat (GDK_DISPLAY (self));
+        GdkDevice *pointer = gdk_seat_get_pointer (seat);
+        GdkDeviceGrabInfo *grab = _gdk_display_get_last_device_grab (GDK_DISPLAY (self), pointer);
+
+        if ([(GdkMacosWindow *)window isInManualResizeOrMove])
+          {
+            ret = GDK_MACOS_EVENT_DROP;
+          }
+        else if (grab == NULL)
+          {
+            if (event_type == NSEventTypeMouseExited)
+              [[NSCursor arrowCursor] set];
+
+            ret = synthesize_crossing_event (self, surface, nsevent, x, y);
+          }
+      }
+
+      break;
+
+    case NSEventTypeKeyDown:
+    case NSEventTypeKeyUp:
+    case NSEventTypeFlagsChanged: {
+      GdkEventType type = _gdk_macos_keymap_get_event_type (nsevent);
+
+      if (type)
+        ret = fill_key_event (self, surface, nsevent, type);
+
+      break;
+    }
+
+    case NSEventTypeScrollWheel:
+      ret = fill_scroll_event (self, surface, nsevent, x, y);
+      break;
+
+    default:
+      break;
+    }
+
+  return ret;
+}
+
 static gboolean
 is_mouse_button_press_event (NSEventType type)
 {
@@ -1083,7 +1162,6 @@ _gdk_macos_display_translate (GdkMacosDisplay *self,
   GdkMacosWindow *window;
   NSEventType event_type;
   NSWindow *event_window;
-  GdkEvent *ret = NULL;
   int x;
   int y;
 
@@ -1191,79 +1269,15 @@ _gdk_macos_display_translate (GdkMacosDisplay *self,
           _gdk_macos_display_clear_sorting (self);
         }
     }
-
-  switch ((int)event_type)
-    {
-    case NSEventTypeLeftMouseDown:
-    case NSEventTypeRightMouseDown:
-    case NSEventTypeOtherMouseDown:
-    case NSEventTypeLeftMouseUp:
-    case NSEventTypeRightMouseUp:
-    case NSEventTypeOtherMouseUp:
-      ret = fill_button_event (self, surface, nsevent, x, y);
-      break;
-
-    case NSEventTypeLeftMouseDragged:
-    case NSEventTypeRightMouseDragged:
-    case NSEventTypeOtherMouseDragged:
-    case NSEventTypeMouseMoved:
-      ret = fill_motion_event (self, surface, nsevent, x, y);
-      break;
-
-    case NSEventTypeMagnify:
-    case NSEventTypeRotate:
-      ret = fill_pinch_event (self, surface, nsevent, x, y);
-      break;
-
-    case NSEventTypeMouseExited:
-    case NSEventTypeMouseEntered:
-      {
-        GdkSeat *seat = gdk_display_get_default_seat (GDK_DISPLAY (self));
-        GdkDevice *pointer = gdk_seat_get_pointer (seat);
-        GdkDeviceGrabInfo *grab = _gdk_display_get_last_device_grab (GDK_DISPLAY (self), pointer);
-
-        if ([(GdkMacosWindow *)window isInManualResizeOrMove])
-          {
-            ret = GDK_MACOS_EVENT_DROP;
-          }
-        else if (grab == NULL)
-          {
-            if (event_type == NSEventTypeMouseExited)
-              [[NSCursor arrowCursor] set];
-
-            ret = synthesize_crossing_event (self, surface, nsevent, x, y);
-          }
-      }
-
-      break;
-
-    case NSEventTypeKeyDown:
-    case NSEventTypeKeyUp:
-    case NSEventTypeFlagsChanged: {
-      GdkEventType type = _gdk_macos_keymap_get_event_type (nsevent);
-
-      if (type)
-        ret = fill_key_event (self, surface, nsevent, type);
-
-      break;
-    }
-
-    case NSEventTypeScrollWheel:
-      ret = fill_scroll_event (self, surface, nsevent, x, y);
-      break;
-
-    default:
-      break;
-    }
-
-  return ret;
+  return fill_event (self, window, nsevent, x, y);
 }
 
 void
-_gdk_macos_display_send_button_event (GdkMacosDisplay *self,
-                                      NSEvent         *nsevent)
+_gdk_macos_display_send_event (GdkMacosDisplay *self,
+                               NSEvent         *nsevent)
 {
   GdkMacosSurface *surface;
+  GdkMacosWindow *window;
   GdkEvent *event;
   int x;
   int y;
@@ -1272,7 +1286,8 @@ _gdk_macos_display_send_button_event (GdkMacosDisplay *self,
   g_return_if_fail (nsevent != NULL);
 
   if ((surface = find_surface_for_ns_event (self, nsevent, &x, &y)) &&
-      (event = fill_button_event (self, surface, nsevent, x, y)))
+      (window = (GdkMacosWindow *)_gdk_macos_surface_get_native (surface)) &&
+      (event = fill_event (self, window, nsevent, x, y)))
     _gdk_windowing_got_event (GDK_DISPLAY (self),
                               _gdk_event_queue_append (GDK_DISPLAY (self), event),
                               event,
index 66579546d240ffe9e68d9d1a33f95941b9a941d1..09853a18ac3ae08ceaf33ec7898200d655cf8f25 100644 (file)
@@ -34,7 +34,6 @@ typedef enum
 GSource  *_gdk_macos_event_source_new           (GdkMacosDisplay *display);
 NSEvent  *_gdk_macos_event_source_get_pending   (void);
 gboolean  _gdk_macos_event_source_check_pending (void);
-void      _gdk_macos_event_source_queue_event   (NSEvent *event);
 
 G_END_DECLS
 
index 6c4a962ae063ce575c84822af9262fabf8e41415..121efc679bcc6993b622b6ef51c6272b60815ef1 100644 (file)
@@ -653,7 +653,7 @@ _gdk_macos_event_source_get_pending (void)
   return event;
 }
 
-void
+static void
 _gdk_macos_event_source_queue_event (NSEvent *event)
 {
   /* Just used to wake us up; if an event and a FD arrived at the same