[gtk+/gtk-3-2] Bug 658767 - Drag and Drop NSEvent capture is racy



commit 68135b53fc9aa679d00244304fb6d67400e9b0f3
Author: John Ralls <jralls ceridwen us>
Date:   Sat Sep 24 18:19:56 2011 -0700

    Bug 658767 - Drag and Drop NSEvent capture is racy
    
    Create a synthetic NSMouseLeftDown to store in the GtkQuartzDragSourceInfo
    rather than relying on the NSWindow's latest event being the right one (or the
    right kind).

 gtk/gtkdnd-quartz.c |   56 +++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 46 insertions(+), 10 deletions(-)
---
diff --git a/gtk/gtkdnd-quartz.c b/gtk/gtkdnd-quartz.c
index 6d4e709..0653261 100644
--- a/gtk/gtkdnd-quartz.c
+++ b/gtk/gtkdnd-quartz.c
@@ -1100,6 +1100,13 @@ gtk_drag_begin_idle (gpointer arg)
 
   return FALSE;
 }
+/* Fake protocol to let us call GdkNSView gdkWindow without including
+ * gdk/GdkNSView.h (which we can't because it pulls in the internal-only
+ * gdkwindow.h).
+ */
+ protocol GdkNSView
+- (GdkWindow *)gdkWindow;
+ end
 
 static GdkDragContext *
 gtk_drag_begin_internal (GtkWidget         *widget,
@@ -1110,14 +1117,47 @@ gtk_drag_begin_internal (GtkWidget         *widget,
 			 GdkEvent          *event)
 {
   GtkDragSourceInfo *info;
-  GdkDragContext *context;
   GdkDevice *pointer;
-  NSWindow *nswindow;
-
-  context = gdk_drag_begin (gtk_widget_get_window (widget), NULL);
+  GdkWindow *window;
+  GdkDragContext *context = gdk_drag_begin (gtk_widget_get_window (widget),
+					    NULL);
+  NSWindow *nswindow = get_toplevel_nswindow (widget);
+  NSPoint point = {0, 0};
+  gdouble x, y;
+  double time = (double)g_get_real_time ();
+  NSEvent *nsevent;
+  NSTimeInterval nstime;
+
+  if (event)
+    {
+      if (gdk_event_get_coords (event, &x, &y))
+        {
+          point.x = x;
+          point.y = y;
+        }
+      time = (double)gdk_event_get_time (event);
+    }
+  nstime = [[NSDate dateWithTimeIntervalSince1970: time / 1000] timeIntervalSinceReferenceDate];
+  nsevent = [NSEvent mouseEventWithType: NSLeftMouseDown
+        	      location: point
+		      modifierFlags: 0
+	              timestamp: nstime
+		      windowNumber: [nswindow windowNumber]
+		      context: [nswindow graphicsContext]
+		      eventNumber: 0
+		      clickCount: 1
+	              pressure: 0.0 ];
+
+  window = [(id<GdkNSView>)[nswindow contentView] gdkWindow];
+  g_return_val_if_fail(nsevent != NULL, NULL);
+
+  context = gdk_drag_begin (window, NULL);
+  g_return_val_if_fail( context != NULL, NULL);
 
   info = gtk_drag_get_source_info (context, TRUE);
-  
+  info->nsevent = nsevent;
+  [info->nsevent retain];
+
   info->source_widget = g_object_ref (widget);
   info->widget = g_object_ref (widget);
   info->target_list = target_list;
@@ -1160,10 +1200,6 @@ gtk_drag_begin_internal (GtkWidget         *widget,
 	  }
     }
 
-  nswindow = get_toplevel_nswindow (widget);
-  info->nsevent = [nswindow currentEvent];
-  [info->nsevent retain];
-
   /* drag will begin in an idle handler to avoid nested run loops */
 
   g_idle_add_full (G_PRIORITY_HIGH_IDLE, gtk_drag_begin_idle, context, NULL);
@@ -1802,7 +1838,7 @@ gtk_drag_source_info_destroy (GtkDragSourceInfo *info)
   pasteboard = [NSPasteboard pasteboardWithName: NSDragPboard];
   [pasteboard declareTypes: nil owner: nil];
 
-  [pool relase];
+  [pool release];
 
   gtk_drag_clear_source_info (info->context);
   g_object_unref (info->context);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]