[gtk+/gtk-2-24-quartz: 26/27] Bug 658722: Drag and Drop sometimes stops working
- From: John Ralls <jralls src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/gtk-2-24-quartz: 26/27] Bug 658722: Drag and Drop sometimes stops working
- Date: Sun, 25 Sep 2011 21:45:41 +0000 (UTC)
commit df0aef74c8a33508bf69092864bd3443c75084e6
Author: John Ralls <jralls ceridwen us>
Date: Sat Sep 24 12:32:24 2011 -0700
Bug 658722: Drag and Drop sometimes stops working
First, rather than assuming that there's already an event
queued up if _gdk_quartz_drag_source_context isn't NULL,
assume that it just didn't get cleaned up the last time
it ran and abort it.
This naturally requires implementing gdk_quartz_drag_abort(),
so remove the code from
[GdkQuartzWindow draggedImage:endedAt:operation:] and
move it to gdkdnd_quartz.c as static void gdk_quartz_drag_end().
Implement both gdk_quartz_drag_drop() and gdk_quartz_drag_abort() by calling gdk_quartz_drag_end().
Next, try to get rid of the memory cycle between
gtk_drag_source_info.context and _gdk_quartz_drag_source_context.
Replace gtk_drag_source_clear_info() by using a
g_object_set_qdata_full() for context in gtk_drag_get_source_context,
calling gtk_drag_source_info_destroy() as the destructor. This
eliminates the need to queue a cleanup idle event. I use
g_object_run_dispose() on _gtk_quartz_drag_source_context to
force the deletion of the info stored as qdata, which in turn unrefs the info->context pointer. Ordinarily this gets fired
off from draggedImage:endedAt:operation:, meaning that the
special dragging CFRunLoop is complete and NSEvents are again flowing, so queuing a cleanup event isn't necessary. The
advantage is that it can also be run from gdk_drag_abort, so
if Gdk thinks there's a drag but CF doesn't all of the memory still gets cleaned up.
gdk/quartz/GdkQuartzWindow.c | 16 +---------------
gdk/quartz/gdkdnd-quartz.c | 38 +++++++++++++++++++++++++++++++++-----
gtk/gtkdnd-quartz.c | 30 ++++++++++++++++++++++--------
3 files changed, 56 insertions(+), 28 deletions(-)
---
diff --git a/gdk/quartz/GdkQuartzWindow.c b/gdk/quartz/GdkQuartzWindow.c
index dcd7250..20ed80e 100644
--- a/gdk/quartz/GdkQuartzWindow.c
+++ b/gdk/quartz/GdkQuartzWindow.c
@@ -560,21 +560,7 @@ update_context_from_dragging_info (id <NSDraggingInfo> sender)
- (void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation
{
- GdkEvent event;
-
- g_assert (_gdk_quartz_drag_source_context != NULL);
-
- event.dnd.type = GDK_DROP_FINISHED;
- event.dnd.window = g_object_ref ([[self contentView] gdkWindow]);
- event.dnd.send_event = FALSE;
- event.dnd.context = _gdk_quartz_drag_source_context;
-
- (*_gdk_event_func) (&event, _gdk_event_data);
-
- g_object_unref (event.dnd.window);
-
- g_object_unref (_gdk_quartz_drag_source_context);
- _gdk_quartz_drag_source_context = NULL;
+ gdk_drag_drop (_gdk_quartz_drag_source_context, (guint32)g_get_real_time());
}
@end
diff --git a/gdk/quartz/gdkdnd-quartz.c b/gdk/quartz/gdkdnd-quartz.c
index f1ad1bc..fba4a1a 100644
--- a/gdk/quartz/gdkdnd-quartz.c
+++ b/gdk/quartz/gdkdnd-quartz.c
@@ -111,11 +111,20 @@ GdkDragContext *
gdk_drag_begin (GdkWindow *window,
GList *targets)
{
- g_return_val_if_fail (_gdk_quartz_drag_source_context == NULL, NULL);
+ if (_gdk_quartz_drag_source_context != NULL)
+ {
+ /* Something is amiss with the existing drag, so log a message
+ and abort it */
+ g_warning ("Drag begun with existing context; aborting the preexisting drag");
+ gdk_drag_abort (_gdk_quartz_drag_source_context,
+ (guint32)g_get_real_time ());
+ }
+
/* Create fake context */
_gdk_quartz_drag_source_context = gdk_drag_context_new ();
_gdk_quartz_drag_source_context->is_source = TRUE;
+ _gdk_quartz_drag_source_context->source_window = window;
return _gdk_quartz_drag_source_context;
}
@@ -155,20 +164,39 @@ gdk_drag_find_window_for_screen (GdkDragContext *context,
/* FIXME: Implement */
}
+static void
+gdk_quartz_drag_end (GdkDragContext *context)
+{
+ GdkEvent event;
+
+ g_assert (context != NULL);
+ g_warning ("Gdk-quartz-drag-end\n");
+ event.dnd.type = GDK_DROP_FINISHED;
+ event.dnd.window = g_object_ref (context->source_window);
+ event.dnd.send_event = FALSE;
+ event.dnd.context = context;
+
+ (*_gdk_event_func) (&event, _gdk_event_data);
+
+ g_object_unref (event.dnd.window);
+
+ g_object_unref (_gdk_quartz_drag_source_context);
+ _gdk_quartz_drag_source_context = NULL;
+}
+
void
gdk_drag_drop (GdkDragContext *context,
guint32 time)
{
- /* FIXME: Implement */
+ g_warning ("Gdk-quartz-drag-drop, ending\n");
+ gdk_quartz_drag_end (context);
}
void
gdk_drag_abort (GdkDragContext *context,
guint32 time)
{
- g_return_if_fail (context != NULL);
-
- /* FIXME: Implement */
+ gdk_quartz_drag_end (context);
}
void
diff --git a/gtk/gtkdnd-quartz.c b/gtk/gtkdnd-quartz.c
index 22b696c..b4d8c9c 100644
--- a/gtk/gtkdnd-quartz.c
+++ b/gtk/gtkdnd-quartz.c
@@ -138,7 +138,7 @@ struct _GtkDragFindData
@interface GtkDragSourceOwner : NSObject {
- GtkDragSourceInfo *info;
+ GdkDragContext *context;
}
@end
@@ -148,13 +148,16 @@ struct _GtkDragFindData
{
guint target_info;
GtkSelectionData selection_data;
+ GtkDragSourceInfo *info;
+ g_return_if_fail (context != NULL);
+ info = gtk_drag_get_source_info (context, FALSE);
+ g_return_if_fail (info != NULL);
g_return_if_fail(info->source_widget != NULL);
g_return_if_fail(info->target_list != NULL);
selection_data.selection = GDK_NONE;
selection_data.data = NULL;
selection_data.length = -1;
selection_data.target = _gtk_quartz_pasteboard_type_to_atom (type);
- selection_data.display = gdk_display_get_default ();
if (gtk_target_list_find (info->target_list,
selection_data.target,
@@ -175,18 +178,27 @@ struct _GtkDragFindData
- (void)pasteboardChangedOwner: (NSPasteboard*)sender
{
+ GtkDragSourceInfo *info;
+ if (context != gdk_quartz_drag_source_context())
+ {
+ context = NULL;
+ return;
+ }
+ info = gtk_drag_get_source_info (context, FALSE);
+ if (!info) return;
+
info->target_list = NULL;
info->widget = NULL;
info->source_widget = NULL;
}
-- (id)initWithInfo:(GtkDragSourceInfo *)anInfo
+- (id)initWithContext:(GdkDragContext *)aContext
{
self = [super init];
if (self)
{
- info = anInfo;
+ context = aContext;
}
return self;
@@ -500,6 +512,7 @@ gtk_drag_dest_site_destroy (gpointer data)
gtk_target_list_unref (site->target_list);
g_free (site);
+ site = NULL;
}
void
@@ -1089,7 +1102,7 @@ gtk_drag_begin_idle (gpointer arg)
g_assert (info != NULL);
pasteboard = [NSPasteboard pasteboardWithName:NSDragPboard];
- owner = [[GtkDragSourceOwner alloc] initWithInfo:info];
+ owner = [[GtkDragSourceOwner alloc] initWithContext:context];
types = _gtk_quartz_target_list_to_pasteboard_types (info->target_list);
@@ -1146,11 +1159,11 @@ gtk_drag_begin_internal (GtkWidget *widget,
eventNumber: 0
clickCount: 1
pressure: 0.0 ];
+ GdkWindow *window = [[nswindow contentView] gdkWindow];
g_return_val_if_fail(nsevent != NULL, NULL);
- context = gdk_drag_begin (NULL, NULL);
+ context = gdk_drag_begin (window, NULL);
g_return_val_if_fail( context != NULL, NULL);
-
context->is_source = TRUE;
info = gtk_drag_get_source_info (context, TRUE);
@@ -1218,7 +1231,7 @@ gtk_drag_begin_internal (GtkWidget *widget,
break;
case GTK_IMAGE_EMPTY:
default:
- g_assert_not_reached();
+ g_assert_not_reached();
break;
}
}
@@ -1874,6 +1887,7 @@ gtk_drag_source_info_destroy (GtkDragSourceInfo *info)
g_object_unref (info->context);
g_free (info);
+ info = NULL;
}
static gboolean
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]