gboolean create);
static void gtk_drag_source_site_destroy (gpointer data);
+static GtkDragSourceInfo *gtk_drag_get_source_info (GdkDragContext *context,
+ gboolean create);
+
+extern GdkDragContext *gdk_quartz_drag_source_context (); /* gdk/quartz/gdkdnd-quartz.c */
+
struct _GtkDragSourceSite
{
GdkModifierType start_button_mask;
struct _GtkDragSourceInfo
{
+ GtkWidget *source_widget;
GtkWidget *widget;
GtkTargetList *target_list; /* Targets for drag data */
GdkDragAction possible_actions; /* Actions allowed by source */
GdkDragContext *context; /* drag context */
-
+ NSEvent *nsevent; /* what started it */
gint hot_x, hot_y; /* Hot spot for drag */
GdkPixbuf *icon_pixbuf;
+ gboolean success;
+ gboolean delete;
};
struct _GtkDragDestSite
selection_data.target,
&target_info))
{
- g_signal_emit_by_name (info->widget, "drag_data_get",
+ g_signal_emit_by_name (info->widget, "drag-data-get",
info->context,
&selection_data,
target_info,
if (!(site->flags & GTK_DEST_DEFAULT_DROP) ||
selection_data->length >= 0)
g_signal_emit_by_name (widget,
- "drag_data_received",
+ "drag-data-received",
context, info->drop_x, info->drop_y,
selection_data,
target_info, time);
else
{
g_signal_emit_by_name (widget,
- "drag_data_received",
+ "drag-data-received",
context, info->drop_x, info->drop_y,
selection_data,
0, time);
}
}
-
-GtkWidget *
-gtk_drag_get_source_widget (GdkDragContext *context)
-{
- return NULL;
-}
-
void
gtk_drag_finish (GdkDragContext *context,
gboolean success,
gboolean del,
guint32 time)
{
+ GtkDragSourceInfo *info;
+ GdkDragContext* source_context = gdk_quartz_drag_source_context ();
+
+ if (source_context)
+ {
+ info = gtk_drag_get_source_info (source_context, FALSE);
+ if (info)
+ {
+ info->success = success;
+ info->delete = del;
+ }
+ }
}
static void
g_object_set_qdata (G_OBJECT (context), dest_info_quark, NULL);
}
+GtkWidget *
+gtk_drag_get_source_widget (GdkDragContext *context)
+{
+ GtkDragSourceInfo *info;
+ GdkDragContext* real_source_context = gdk_quartz_drag_source_context();
+
+ if (!real_source_context)
+ return NULL;
+
+ info = gtk_drag_get_source_info (real_source_context, FALSE);
+ if (!info)
+ return NULL;
+
+ return info->source_widget;
+}
+
/*************************************************************
* gtk_drag_highlight_expose:
* Callback for expose_event for highlighted widgets.
{
gint x, y, width, height;
- if (GTK_WIDGET_DRAWABLE (widget))
+ if (gtk_widget_is_drawable (widget))
{
cairo_t *cr;
- if (GTK_WIDGET_NO_WINDOW (widget))
+ if (!gtk_widget_get_has_window (widget))
{
x = widget->allocation.x;
y = widget->allocation.y;
{
g_return_if_fail (GTK_IS_WIDGET (widget));
- g_signal_connect_after (widget, "expose_event",
+ g_signal_connect_after (widget, "expose-event",
G_CALLBACK (gtk_drag_highlight_expose),
NULL);
{
GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
- if (GTK_WIDGET_TOPLEVEL (toplevel) && toplevel->window)
+ if (gtk_widget_is_toplevel (toplevel) && toplevel->window)
return [gdk_quartz_window_get_nsview (toplevel->window) window];
else
return NULL;
if (site->target_list)
{
NSWindow *nswindow = get_toplevel_nswindow (widget);
- NSArray *types;
+ NSSet *types;
NSAutoreleasePool *pool;
if (!nswindow)
pool = [[NSAutoreleasePool alloc] init];
types = _gtk_quartz_target_list_to_pasteboard_types (site->target_list);
- [nswindow registerForDraggedTypes:types];
+ [nswindow registerForDraggedTypes:[types allObjects]];
+
+ [types release];
[pool release];
}
}
old_site = g_object_get_data (G_OBJECT (widget), "gtk-drag-dest");
- gtk_drag_dest_unset (widget);
-
site = g_new (GtkDragDestSite, 1);
site->flags = flags;
site->have_drag = FALSE;
else
site->track_motion = FALSE;
+ gtk_drag_dest_unset (widget);
+
if (GTK_WIDGET_REALIZED (widget))
gtk_drag_dest_realized (widget, site);
g_signal_connect (widget, "realize",
G_CALLBACK (gtk_drag_dest_realized), site);
- g_signal_connect (widget, "hierarchy_changed",
+ g_signal_connect (widget, "hierarchy-changed",
G_CALLBACK (gtk_drag_dest_hierarchy_changed), site);
g_object_set_data_full (G_OBJECT (widget), I_("gtk-drag-dest"),
gint x_offset = 0;
gint y_offset = 0;
- if (data->found || !GTK_WIDGET_MAPPED (widget) || !GTK_WIDGET_SENSITIVE (widget))
+ if (data->found || !gtk_widget_get_mapped (widget) || !gtk_widget_get_sensitive (widget))
return;
/* Note that in the following code, we only count the
allocation_to_window_x = widget->allocation.x;
allocation_to_window_y = widget->allocation.y;
- if (!GTK_WIDGET_NO_WINDOW (widget))
+ if (gtk_widget_get_has_window (widget))
{
/* The allocation is relative to the parent window for
* window widgets, not to widget->window.
new_data.toplevel = FALSE;
/* need to reference children temporarily in case the
- * ::drag_motion/::drag_drop callbacks change the widget heirarchy.
+ * ::drag-motion/::drag-drop callbacks change the widget hierarchy.
*/
gtk_container_forall (GTK_CONTAINER (widget), prepend_and_ref_widget, &children);
for (tmp_list = children; tmp_list; tmp_list = tmp_list->next)
{
- if (!new_data.found && GTK_WIDGET_DRAWABLE (tmp_list->data))
+ if (!new_data.found && gtk_widget_is_drawable (tmp_list->data))
gtk_drag_find_widget (tmp_list->data, &new_data);
g_object_unref (tmp_list->data);
}
}
/* If not, and this widget is registered as a drop site, check to
- * emit "drag_motion" to check if we are actually in
+ * emit "drag-motion" to check if we are actually in
* a drop site.
*/
if (!data->found &&
data->x - x_offset - allocation_to_window_x,
data->y - y_offset - allocation_to_window_y,
data->time);
- /* If so, send a "drag_leave" to the last widget */
+ /* If so, send a "drag-leave" to the last widget */
if (data->found)
{
if (data->info->widget && data->info->widget != widget)
if (!(site->flags & GTK_DEST_DEFAULT_MOTION) || site->have_drag ||
site->track_motion)
- g_signal_emit_by_name (widget, "drag_leave", context, time);
+ g_signal_emit_by_name (widget, "drag-leave", context, time);
site->have_drag = FALSE;
}
}
}
- g_signal_emit_by_name (widget, "drag_motion",
+ g_signal_emit_by_name (widget, "drag-motion",
context, x, y, time, &retval);
return (site->flags & GTK_DEST_DEFAULT_MOTION) ? TRUE : retval;
gtk_drag_get_data (widget, context, target, time);
}
- g_signal_emit_by_name (widget, "drag_drop",
+ g_signal_emit_by_name (widget, "drag-drop",
context, x, y, time, &retval);
return (site->flags & GTK_DEST_DEFAULT_DROP) ? TRUE : retval;
return GDK_NONE;
}
+static gboolean
+gtk_drag_begin_idle (gpointer arg)
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ GdkDragContext* context = (GdkDragContext*) arg;
+ GtkDragSourceInfo* info = gtk_drag_get_source_info (context, FALSE);
+ NSWindow *nswindow;
+ NSPasteboard *pasteboard;
+ GtkDragSourceOwner *owner;
+ NSPoint point;
+ NSSet *types;
+ NSImage *drag_image;
+
+ g_assert (info != NULL);
+
+ pasteboard = [NSPasteboard pasteboardWithName:NSDragPboard];
+ owner = [[GtkDragSourceOwner alloc] initWithInfo:info];
+
+ types = _gtk_quartz_target_list_to_pasteboard_types (info->target_list);
+
+ [pasteboard declareTypes:[types allObjects] owner:owner];
+
+ [owner release];
+ [types release];
+
+ if ((nswindow = get_toplevel_nswindow (info->source_widget)) == NULL)
+ return FALSE;
+
+ /* Ref the context. It's unreffed when the drag has been aborted */
+ g_object_ref (info->context);
+
+ /* FIXME: If the event isn't a mouse event, use the global cursor position instead */
+ point = [info->nsevent locationInWindow];
+
+ drag_image = _gtk_quartz_create_image_from_pixbuf (info->icon_pixbuf);
+
+ [nswindow dragImage:drag_image
+ at:point
+ offset:NSMakeSize(0, 0)
+ event:info->nsevent
+ pasteboard:pasteboard
+ source:nswindow
+ slideBack:YES];
+
+ [info->nsevent release];
+ [drag_image release];
+
+ [pool release];
+
+ return FALSE;
+}
+
static GdkDragContext *
gtk_drag_begin_internal (GtkWidget *widget,
GtkDragSourceSite *site,
GtkDragSourceInfo *info;
GdkDragContext *context;
NSWindow *nswindow;
- NSPasteboard *pasteboard;
- GtkDragSourceOwner *owner;
- NSEvent *nsevent;
- NSPoint point;
context = gdk_drag_begin (NULL, NULL);
context->is_source = TRUE;
info = gtk_drag_get_source_info (context, TRUE);
+ info->source_widget = g_object_ref (widget);
info->widget = g_object_ref (widget);
info->target_list = target_list;
gtk_target_list_ref (target_list);
info->possible_actions = actions;
- g_signal_emit_by_name (widget, "drag_begin", info->context);
+ g_signal_emit_by_name (widget, "drag-begin", info->context);
/* Ensure that we have an icon before we start the drag; the
* application may have set one in ::drag_begin, or it may
GdkPixbuf *pixbuf;
pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, 1, 1);
- gdk_pixbuf_fill (pixbuf, 0xffffff);
-
- gtk_drag_set_icon_pixbuf (context,
- pixbuf,
+ gdk_pixbuf_fill (pixbuf, 0xffffff);
+
+ gtk_drag_set_icon_pixbuf (context,
+ pixbuf,
0, 0);
- g_object_unref (pixbuf);
+ g_object_unref (pixbuf);
}
break;
case GTK_IMAGE_PIXBUF:
}
}
- gdk_pointer_ungrab (0);
-
- pasteboard = [NSPasteboard pasteboardWithName:NSDragPboard];
- owner = [[GtkDragSourceOwner alloc] initWithInfo:info];
-
- [pasteboard declareTypes:_gtk_quartz_target_list_to_pasteboard_types (target_list) owner:owner];
-
- /* Ref the context. It's unreffed when the drag has been aborted */
- g_object_ref (info->context);
-
nswindow = get_toplevel_nswindow (widget);
+ info->nsevent = [nswindow currentEvent];
+ [info->nsevent retain];
- /* FIXME: If the event isn't a mouse event, use the global cursor position instead */
- nsevent = [nswindow currentEvent];
- point = [nsevent locationInWindow];
+ /* drag will begin in an idle handler to avoid nested run loops */
- [nswindow dragImage:_gtk_quartz_create_image_from_pixbuf (info->icon_pixbuf)
- at:point
- offset:NSMakeSize(0, 0)
- event:nsevent
- pasteboard:pasteboard
- source:nswindow
- slideBack:YES];
+ g_idle_add_full (G_PRIORITY_HIGH_IDLE, gtk_drag_begin_idle, context, NULL);
- return info->context;
+ gdk_pointer_ungrab (0);
+
+ return context;
}
GdkDragContext *
site->icon_type = GTK_IMAGE_EMPTY;
- g_signal_connect (widget, "button_press_event",
+ g_signal_connect (widget, "button-press-event",
G_CALLBACK (gtk_drag_source_event_cb),
site);
- g_signal_connect (widget, "button_release_event",
+ g_signal_connect (widget, "button-release-event",
G_CALLBACK (gtk_drag_source_event_cb),
site);
- g_signal_connect (widget, "motion_notify_event",
+ g_signal_connect (widget, "motion-notify-event",
G_CALLBACK (gtk_drag_source_event_cb),
site);
*
* Changes the icon for a widget to a given widget. GTK+
* will not destroy the icon, so if you don't want
- * it to persist, you should connect to the "drag_end"
+ * it to persist, you should connect to the "drag-end"
* signal and destroy it yourself.
**/
void
gint hot_x,
gint hot_y)
{
- g_warning ("gtk_drag_set_icon_pixmap is not supported on Mac OS X");
+ GdkPixbuf *pixbuf;
+
+ g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
+ g_return_if_fail (context->is_source);
+ g_return_if_fail (GDK_IS_COLORMAP (colormap));
+ g_return_if_fail (GDK_IS_PIXMAP (pixmap));
+
+ pixbuf = gdk_pixbuf_get_from_drawable (NULL, pixmap, colormap,
+ 0, 0, /* src */
+ 0, 0, /* dst */
+ -1, -1);
+
+ gtk_drag_set_icon_pixbuf (context, pixbuf, hot_x, hot_y);
+ g_object_unref (pixbuf);
}
/**
if (info->icon_pixbuf)
g_object_unref (info->icon_pixbuf);
- g_signal_emit_by_name (info->widget, "drag_end",
+ g_signal_emit_by_name (info->widget, "drag-end",
info->context);
+ if (info->source_widget)
+ g_object_unref (info->source_widget);
+
if (info->widget)
g_object_unref (info->widget);
static void
gtk_drag_drop_finished (GtkDragSourceInfo *info)
{
+ if (info->success && info->delete)
+ g_signal_emit_by_name (info->source_widget, "drag-data-delete",
+ info->context);
+
/* Workaround for the fact that the NS API blocks until the drag is
* over. This way the context is still valid when returning from
* drag_begin, even if it will still be quite useless. See bug #501588.