summaryrefslogtreecommitdiff
path: root/gtk/gtkdnd-quartz.c
diff options
context:
space:
mode:
authorJohn Ralls <jralls@ceridwen.us>2011-09-24 18:19:56 -0700
committerJohn Ralls <jralls@ceridwen.us>2011-10-09 11:24:41 -0700
commit6906ab88bc9f5b9694953948c8d61f6f40718a9e (patch)
treebe3c43bdd5a69bd0d88cb1a9b4021bc737cbf491 /gtk/gtkdnd-quartz.c
parent8ad3d2b29656b3af312b752c62ff68e7059fc326 (diff)
downloadgtk+-6906ab88bc9f5b9694953948c8d61f6f40718a9e.tar.gz
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).
Diffstat (limited to 'gtk/gtkdnd-quartz.c')
-rw-r--r--gtk/gtkdnd-quartz.c56
1 files changed, 46 insertions, 10 deletions
diff --git a/gtk/gtkdnd-quartz.c b/gtk/gtkdnd-quartz.c
index 6d4e709a94..0653261c65 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);