X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkdnd.c;h=35281f065e9f474b94cb933a10619478c9ef821c;hb=fcfb638ab0260c7f320c5ffe7c50a3d669f9881b;hp=3e88358800ad2572bb52ef0943f95c003ceb5e47;hpb=1901d4ebd7572fc9e5243345e0436d18e4e52dd1;p=~andy%2Fgtk diff --git a/gtk/gtkdnd.c b/gtk/gtkdnd.c index 3e8835880..35281f065 100644 --- a/gtk/gtkdnd.c +++ b/gtk/gtkdnd.c @@ -32,11 +32,9 @@ #include "gtkimage.h" #include "gtkinvisible.h" #include "gtkmain.h" -#include "gtksignal.h" #include "gtkstock.h" #include "gtkwindow.h" -static GSList *drag_widgets = NULL; static GSList *source_widgets = NULL; typedef struct _GtkDragSourceSite GtkDragSourceSite; @@ -84,6 +82,7 @@ struct _GtkDragSourceInfo GdkDragAction possible_actions; /* Actions allowed by source */ GdkDragContext *context; /* drag context */ GtkWidget *icon_window; /* Window for drag */ + GtkWidget *fallback_icon; /* Window for drag used on other screens */ GtkWidget *ipc_widget; /* GtkInvisible for grab, message passing */ GdkCursor *cursor; /* Cursor for drag */ gint hot_x, hot_y; /* Hot spot for drag */ @@ -94,14 +93,18 @@ struct _GtkDragSourceInfo gint start_x, start_y; /* Initial position */ gint cur_x, cur_y; /* Current Position */ + GdkScreen *cur_screen; /* Current screen for pointer */ + guint32 grab_time; /* timestamp for initial grab */ GList *selections; /* selections we've claimed */ GtkDragDestInfo *proxy_dest; /* Set if this is a proxy drag */ guint drop_timeout; /* Timeout for aborting drop */ guint destroy_icon : 1; /* If true, destroy icon_window - */ + */ + guint have_grab : 1; /* Do we still have the pointer grab + */ }; struct _GtkDragDestSite @@ -180,8 +183,9 @@ static void gtk_drag_get_event_actions (GdkEvent *event, GdkDragAction actions, GdkDragAction *suggested_action, GdkDragAction *possible_actions); -static GdkCursor * gtk_drag_get_cursor (GdkDragAction action); -static GtkWidget *gtk_drag_get_ipc_widget (void); +static GdkCursor * gtk_drag_get_cursor (GdkDisplay *display, + GdkDragAction action); +static GtkWidget *gtk_drag_get_ipc_widget (GdkScreen *screen); static void gtk_drag_release_ipc_widget (GtkWidget *widget); static gboolean gtk_drag_highlight_expose (GtkWidget *widget, @@ -231,6 +235,8 @@ static void gtk_drag_drop (GtkDragSourceInfo *info, static void gtk_drag_drop_finished (GtkDragSourceInfo *info, gboolean success, guint time); +static void gtk_drag_cancel (GtkDragSourceInfo *info, + guint32 time); static gint gtk_drag_source_event_cb (GtkWidget *widget, GdkEvent *event, @@ -245,6 +251,7 @@ static gint gtk_drag_anim_timeout (gpointer data); static void gtk_drag_remove_icon (GtkDragSourceInfo *info); static void gtk_drag_source_info_destroy (GtkDragSourceInfo *info); static void gtk_drag_update (GtkDragSourceInfo *info, + GdkScreen *screen, gint x_root, gint y_root, GdkEvent *event); @@ -338,8 +345,8 @@ static const guchar action_none_mask_bits[] = { static struct { GdkDragAction action; - const char *bits; - const char *mask; + const guchar *bits; + const guchar *mask; GdkCursor *cursor; } drag_cursors[] = { { GDK_ACTION_DEFAULT, 0 }, @@ -356,6 +363,23 @@ static const gint n_drag_cursors = sizeof (drag_cursors) / sizeof (drag_cursors[ * Utility functions * *********************/ +static void +set_can_change_screen (GtkWidget *widget, + gboolean can_change_screen) +{ + can_change_screen = can_change_screen != FALSE; + + g_object_set_data (G_OBJECT (widget), "gtk-dnd-can-change-screen", + GUINT_TO_POINTER (can_change_screen)); +} + +static gboolean +get_can_change_screen (GtkWidget *widget) +{ + return g_object_get_data (G_OBJECT (widget), "gtk-dnd-can-change-screen") != NULL; + +} + /************************************************************* * gtk_drag_get_ipc_widget: * Return a invisible, off-screen, override-redirect @@ -366,20 +390,25 @@ static const gint n_drag_cursors = sizeof (drag_cursors) / sizeof (drag_cursors[ *************************************************************/ static GtkWidget * -gtk_drag_get_ipc_widget (void) +gtk_drag_get_ipc_widget (GdkScreen *screen) { GtkWidget *result; + GSList *drag_widgets = g_object_get_data (G_OBJECT (screen), + "gtk-dnd-ipc-widgets"); if (drag_widgets) { GSList *tmp = drag_widgets; result = drag_widgets->data; drag_widgets = drag_widgets->next; + g_object_set_data (G_OBJECT (screen), + "gtk-dnd-ipc-widgets", + drag_widgets); g_slist_free_1 (tmp); } else { - result = gtk_invisible_new (); + result = gtk_invisible_new_for_screen (screen); gtk_widget_show (result); } @@ -397,7 +426,13 @@ gtk_drag_get_ipc_widget (void) static void gtk_drag_release_ipc_widget (GtkWidget *widget) { + GdkScreen *screen = gtk_widget_get_screen (widget); + GSList *drag_widgets = g_object_get_data (G_OBJECT (screen), + "gtk-dnd-ipc-widgets"); drag_widgets = g_slist_prepend (drag_widgets, widget); + g_object_set_data (G_OBJECT (screen), + "gtk-dnd-ipc-widgets", + drag_widgets); } static guint32 @@ -538,34 +573,40 @@ gtk_drag_get_event_actions (GdkEvent *event, } static GdkCursor * -gtk_drag_get_cursor (GdkDragAction action) +gtk_drag_get_cursor (GdkDisplay *display, + GdkDragAction action) { gint i; for (i = 0 ; i < n_drag_cursors - 1; i++) if (drag_cursors[i].action == action) break; + if (drag_cursors[i].cursor != NULL) + { + if (display != gdk_cursor_get_display (drag_cursors[i].cursor)) + { + gdk_cursor_unref (drag_cursors[i].cursor); + drag_cursors[i].cursor = NULL; + } + } if (drag_cursors[i].cursor == NULL) { - GdkColor fg, bg; + GdkColor bg = { 0, 0xffff, 0xffff, 0xffff }; + GdkColor fg = { 0, 0x0000, 0x0000, 0x0000 }; + GdkScreen *screen = gdk_display_get_default_screen (display); + GdkWindow *window = gdk_screen_get_root_window (screen); GdkPixmap *pixmap = - gdk_bitmap_create_from_data (NULL, - drag_cursors[i].bits, - CURSOR_WIDTH, CURSOR_HEIGHT); + gdk_bitmap_create_from_data (window, (gchar *)drag_cursors[i].bits, CURSOR_WIDTH, CURSOR_HEIGHT); + GdkPixmap *mask = - gdk_bitmap_create_from_data (NULL, - drag_cursors[i].mask, - CURSOR_WIDTH, CURSOR_HEIGHT); + gdk_bitmap_create_from_data (window, (gchar *)drag_cursors[i].mask, CURSOR_WIDTH, CURSOR_HEIGHT); - gdk_color_white (gdk_colormap_get_system (), &bg); - gdk_color_black (gdk_colormap_get_system (), &fg); - drag_cursors[i].cursor = gdk_cursor_new_from_pixmap (pixmap, mask, &fg, &bg, 0, 0); - gdk_pixmap_unref (pixmap); - gdk_pixmap_unref (mask); + g_object_unref (pixmap); + g_object_unref (mask); } return drag_cursors[i].cursor; @@ -594,18 +635,19 @@ gtk_drag_get_data (GtkWidget *widget, { GtkWidget *selection_widget; - g_return_if_fail (widget != NULL); - g_return_if_fail (context != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (GDK_IS_DRAG_CONTEXT (context)); + g_return_if_fail (!context->is_source); - selection_widget = gtk_drag_get_ipc_widget (); + selection_widget = gtk_drag_get_ipc_widget (gtk_widget_get_screen (widget)); - gdk_drag_context_ref (context); - gtk_widget_ref (widget); + g_object_ref (context); + g_object_ref (widget); - gtk_signal_connect (GTK_OBJECT (selection_widget), "selection_received", - GTK_SIGNAL_FUNC (gtk_drag_selection_received), widget); + g_signal_connect (selection_widget, "selection_received", + G_CALLBACK (gtk_drag_selection_received), widget); - gtk_object_set_data (GTK_OBJECT (selection_widget), "drag-context", context); + g_object_set_data (G_OBJECT (selection_widget), "drag-context", context); gtk_selection_convert (selection_widget, gdk_drag_get_selection (context), @@ -630,6 +672,9 @@ gtk_drag_get_source_widget (GdkDragContext *context) { GSList *tmp_list; + g_return_val_if_fail (GDK_IS_DRAG_CONTEXT (context), NULL); + g_return_val_if_fail (!context->is_source, NULL); + tmp_list = source_widgets; while (tmp_list) { @@ -638,7 +683,7 @@ gtk_drag_get_source_widget (GdkDragContext *context) if (ipc_widget->window == context->source_window) { GtkDragSourceInfo *info; - info = gtk_object_get_data (GTK_OBJECT (ipc_widget), "gtk-info"); + info = g_object_get_data (G_OBJECT (ipc_widget), "gtk-info"); return info ? info->widget : NULL; } @@ -668,7 +713,8 @@ gtk_drag_finish (GdkDragContext *context, { GdkAtom target = GDK_NONE; - g_return_if_fail (context != NULL); + g_return_if_fail (GDK_IS_DRAG_CONTEXT (context)); + g_return_if_fail (!context->is_source); if (success && del) { @@ -684,14 +730,14 @@ gtk_drag_finish (GdkDragContext *context, if (target != GDK_NONE) { - GtkWidget *selection_widget = gtk_drag_get_ipc_widget (); + GtkWidget *selection_widget = gtk_drag_get_ipc_widget (gdk_drawable_get_screen (context->source_window)); - gdk_drag_context_ref (context); + g_object_ref (context); - gtk_object_set_data (GTK_OBJECT (selection_widget), "drag-context", context); - gtk_signal_connect (GTK_OBJECT (selection_widget), "selection_received", - GTK_SIGNAL_FUNC (gtk_drag_selection_received), - NULL); + g_object_set_data (G_OBJECT (selection_widget), "drag-context", context); + g_signal_connect (selection_widget, "selection_received", + G_CALLBACK (gtk_drag_selection_received), + NULL); gtk_selection_convert (selection_widget, gdk_drag_get_selection (context), @@ -733,12 +779,13 @@ gtk_drag_highlight_expose (GtkWidget *widget, { x = 0; y = 0; - gdk_window_get_size (widget->window, &width, &height); + gdk_drawable_get_size (widget->window, &width, &height); } - gtk_draw_shadow (widget->style, widget->window, - GTK_STATE_NORMAL, GTK_SHADOW_OUT, - x, y, width, height); + gtk_paint_shadow (widget->style, widget->window, + GTK_STATE_NORMAL, GTK_SHADOW_OUT, + NULL, widget, "dnd", + x, y, width, height); gdk_draw_rectangle (widget->window, widget->style->black_gc, @@ -760,9 +807,11 @@ gtk_drag_highlight_expose (GtkWidget *widget, void gtk_drag_highlight (GtkWidget *widget) { - gtk_signal_connect_after (GTK_OBJECT (widget), "expose_event", - GTK_SIGNAL_FUNC (gtk_drag_highlight_expose), - NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + g_signal_connect_after (widget, "expose_event", + G_CALLBACK (gtk_drag_highlight_expose), + NULL); gtk_widget_queue_draw (widget); } @@ -778,13 +827,13 @@ gtk_drag_highlight (GtkWidget *widget) void gtk_drag_unhighlight (GtkWidget *widget) { - g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); - gtk_signal_disconnect_by_func (GTK_OBJECT (widget), - GTK_SIGNAL_FUNC (gtk_drag_highlight_expose), - NULL); + g_signal_handlers_disconnect_by_func (widget, + gtk_drag_highlight_expose, + NULL); - gtk_widget_queue_clear (widget); + gtk_widget_queue_draw (widget); } static void @@ -796,20 +845,27 @@ gtk_drag_dest_set_internal (GtkWidget *widget, g_return_if_fail (widget != NULL); /* HACK, do this in the destroy */ - old_site = gtk_object_get_data (GTK_OBJECT (widget), "gtk-drag-dest"); + old_site = g_object_get_data (G_OBJECT (widget), "gtk-drag-dest"); if (old_site) - gtk_signal_disconnect_by_data (GTK_OBJECT (widget), old_site); + { + g_signal_handlers_disconnect_by_func (widget, + gtk_drag_dest_realized, + old_site); + g_signal_handlers_disconnect_by_func (widget, + gtk_drag_dest_hierarchy_changed, + old_site); + } if (GTK_WIDGET_REALIZED (widget)) gtk_drag_dest_realized (widget); - gtk_signal_connect (GTK_OBJECT (widget), "realize", - GTK_SIGNAL_FUNC (gtk_drag_dest_realized), site); - gtk_signal_connect (GTK_OBJECT (widget), "hierarchy_changed", - GTK_SIGNAL_FUNC (gtk_drag_dest_hierarchy_changed), site); + g_signal_connect (widget, "realize", + G_CALLBACK (gtk_drag_dest_realized), site); + g_signal_connect (widget, "hierarchy_changed", + G_CALLBACK (gtk_drag_dest_hierarchy_changed), site); - gtk_object_set_data_full (GTK_OBJECT (widget), "gtk-drag-dest", - site, gtk_drag_dest_site_destroy); + g_object_set_data_full (G_OBJECT (widget), "gtk-drag-dest", + site, gtk_drag_dest_site_destroy); } @@ -834,7 +890,7 @@ gtk_drag_dest_set (GtkWidget *widget, { GtkDragDestSite *site; - g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); site = g_new (GtkDragDestSite, 1); @@ -844,9 +900,9 @@ gtk_drag_dest_set (GtkWidget *widget, site->target_list = gtk_target_list_new (targets, n_targets); else site->target_list = NULL; - site->actions = actions; site->do_proxy = FALSE; + site->proxy_window = NULL; gtk_drag_dest_set_internal (widget, site); } @@ -872,7 +928,8 @@ gtk_drag_dest_set_proxy (GtkWidget *widget, { GtkDragDestSite *site; - g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (!proxy_window || GDK_IS_WINDOW (proxy_window)); site = g_new (GtkDragDestSite, 1); @@ -882,7 +939,7 @@ gtk_drag_dest_set_proxy (GtkWidget *widget, site->actions = 0; site->proxy_window = proxy_window; if (proxy_window) - gdk_window_ref (proxy_window); + g_object_ref (proxy_window); site->do_proxy = TRUE; site->proxy_protocol = protocol; site->proxy_coords = use_coordinates; @@ -901,9 +958,9 @@ gtk_drag_dest_set_proxy (GtkWidget *widget, void gtk_drag_dest_unset (GtkWidget *widget) { - g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); - gtk_object_set_data (GTK_OBJECT (widget), "gtk-drag-dest", NULL); + g_object_set_data (G_OBJECT (widget), "gtk-drag-dest", NULL); } /** @@ -919,8 +976,10 @@ GtkTargetList* gtk_drag_dest_get_target_list (GtkWidget *widget) { GtkDragDestSite *site; + + g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); - site = gtk_object_get_data (GTK_OBJECT (widget), "gtk-drag-dest"); + site = g_object_get_data (G_OBJECT (widget), "gtk-drag-dest"); return site ? site->target_list : NULL; } @@ -939,8 +998,10 @@ gtk_drag_dest_set_target_list (GtkWidget *widget, GtkTargetList *target_list) { GtkDragDestSite *site; + + g_return_if_fail (GTK_IS_WIDGET (widget)); - site = gtk_object_get_data (GTK_OBJECT (widget), "gtk-drag-dest"); + site = g_object_get_data (G_OBJECT (widget), "gtk-drag-dest"); if (site == NULL) { @@ -1085,6 +1146,8 @@ gtk_drag_dest_find_target (GtkWidget *widget, g_return_val_if_fail (GTK_IS_WIDGET (widget), GDK_NONE); g_return_val_if_fail (GDK_IS_DRAG_CONTEXT (context), GDK_NONE); + g_return_val_if_fail (!context->is_source, GDK_NONE); + source_widget = gtk_drag_get_source_widget (context); @@ -1129,7 +1192,7 @@ gtk_drag_selection_received (GtkWidget *widget, drop_widget = data; - context = gtk_object_get_data (GTK_OBJECT (widget), "drag-context"); + context = g_object_get_data (G_OBJECT (widget), "drag-context"); info = gtk_drag_get_dest_info (context, FALSE); if (info->proxy_data && @@ -1157,7 +1220,7 @@ gtk_drag_selection_received (GtkWidget *widget, { GtkDragDestSite *site; - site = gtk_object_get_data (GTK_OBJECT (drop_widget), "gtk-drag-dest"); + site = g_object_get_data (G_OBJECT (drop_widget), "gtk-drag-dest"); if (site && site->target_list) { @@ -1169,19 +1232,20 @@ gtk_drag_selection_received (GtkWidget *widget, { if (!(site->flags & GTK_DEST_DEFAULT_DROP) || selection_data->length >= 0) - gtk_signal_emit_by_name (GTK_OBJECT (drop_widget), - "drag_data_received", - context, info->drop_x, info->drop_y, - selection_data, - target_info, time); + g_signal_emit_by_name (drop_widget, + "drag_data_received", + context, info->drop_x, info->drop_y, + selection_data, + target_info, time); } } else { - gtk_signal_emit_by_name (GTK_OBJECT (drop_widget), - "drag_data_received", - context, info->drop_x, info->drop_y, - selection_data, 0, time); + g_signal_emit_by_name (drop_widget, + "drag_data_received", + context, info->drop_x, info->drop_y, + selection_data, + 0, time); } if (site && site->flags & GTK_DEST_DEFAULT_DROP) @@ -1193,15 +1257,15 @@ gtk_drag_selection_received (GtkWidget *widget, time); } - gtk_widget_unref (drop_widget); + g_object_unref (drop_widget); } - gtk_signal_disconnect_by_func (GTK_OBJECT (widget), - GTK_SIGNAL_FUNC (gtk_drag_selection_received), - data); + g_signal_handlers_disconnect_by_func (widget, + gtk_drag_selection_received, + data); - gtk_object_set_data (GTK_OBJECT (widget), "drag-context", NULL); - gdk_drag_context_unref (context); + g_object_set_data (G_OBJECT (widget), "drag-context", NULL); + g_object_unref (context); gtk_drag_release_ipc_widget (widget); } @@ -1229,10 +1293,12 @@ gtk_drag_find_widget (GtkWidget *widget, GtkDragFindData *data) { GtkAllocation new_allocation; + gint allocation_to_window_x = 0; + gint allocation_to_window_y = 0; gint x_offset = 0; gint y_offset = 0; - if (data->found || !GTK_WIDGET_MAPPED (widget)) + if (data->found || !GTK_WIDGET_MAPPED (widget) || !GTK_WIDGET_SENSITIVE (widget)) return; /* Note that in the following code, we only count the @@ -1253,38 +1319,36 @@ gtk_drag_find_widget (GtkWidget *widget, if (widget->parent) { - gint tx, ty, twidth, theight; + gint tx, ty; GdkWindow *window = widget->window; - /* Correct for the fact that the allocation is relative - * to the parent window for window widgets, not to widget->window. + /* Compute the offset from allocation-relative to + * window-relative coordinates. */ + allocation_to_window_x = widget->allocation.x; + allocation_to_window_y = widget->allocation.y; + if (!GTK_WIDGET_NO_WINDOW (widget)) { + /* The allocation is relative to the parent window for + * window widgets, not to widget->window. + */ gdk_window_get_position (window, &tx, &ty); - new_allocation.x -= tx; - new_allocation.y -= ty; + allocation_to_window_x -= tx; + allocation_to_window_y -= ty; } + new_allocation.x = 0 + allocation_to_window_x; + new_allocation.y = 0 + allocation_to_window_y; + while (window && window != widget->parent->window) - { - gdk_window_get_size (window, &twidth, &theight); + { + GdkRectangle window_rect = { 0, 0, 0, 0 }; + + gdk_drawable_get_size (window, &window_rect.width, &window_rect.height); - if (new_allocation.x < 0) - { - new_allocation.width += new_allocation.x; - new_allocation.x = 0; - } - if (new_allocation.y < 0) - { - new_allocation.height += new_allocation.y; - new_allocation.y = 0; - } - if (new_allocation.x + new_allocation.width > twidth) - new_allocation.width = twidth - new_allocation.x; - if (new_allocation.y + new_allocation.height > theight) - new_allocation.height = theight - new_allocation.y; + gdk_rectangle_intersect (&new_allocation, &window_rect, &new_allocation); gdk_window_get_position (window, &tx, &ty); new_allocation.x += tx; @@ -1326,7 +1390,7 @@ gtk_drag_find_widget (GtkWidget *widget, { if (!new_data.found && GTK_WIDGET_DRAWABLE (tmp_list->data)) gtk_drag_find_widget (tmp_list->data, &new_data); - gtk_widget_unref (tmp_list->data); + g_object_unref (tmp_list->data); } g_slist_free (children); @@ -1338,12 +1402,12 @@ gtk_drag_find_widget (GtkWidget *widget, * a drop site. */ if (!data->found && - gtk_object_get_data (GTK_OBJECT (widget), "gtk-drag-dest")) + g_object_get_data (G_OBJECT (widget), "gtk-drag-dest")) { data->found = data->callback (widget, data->context, - data->x - new_allocation.x - x_offset, - data->y - new_allocation.y - y_offset, + 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 (data->found) @@ -1375,7 +1439,7 @@ gtk_drag_proxy_begin (GtkWidget *widget, dest_info->proxy_source = NULL; } - ipc_widget = gtk_drag_get_ipc_widget (); + ipc_widget = gtk_drag_get_ipc_widget (gtk_widget_get_screen (widget)); context = gdk_drag_begin (ipc_widget->window, dest_info->context->targets); @@ -1395,10 +1459,10 @@ gtk_drag_proxy_begin (GtkWidget *widget, source_info->proxy_dest = dest_info; - gtk_signal_connect (GTK_OBJECT (ipc_widget), - "selection_get", - GTK_SIGNAL_FUNC (gtk_drag_selection_get), - source_info); + g_signal_connect (ipc_widget, + "selection_get", + G_CALLBACK (gtk_drag_selection_get), + source_info); dest_info->proxy_source = source_info; } @@ -1488,6 +1552,9 @@ gtk_drag_dest_site_destroy (gpointer data) { GtkDragDestSite *site = data; + if (site->proxy_window) + g_object_unref (site->proxy_window); + if (site->target_list) gtk_target_list_unref (site->target_list); @@ -1504,7 +1571,7 @@ gtk_drag_dest_leave (GtkWidget *widget, { GtkDragDestSite *site; - site = gtk_object_get_data (GTK_OBJECT (widget), "gtk-drag-dest"); + site = g_object_get_data (G_OBJECT (widget), "gtk-drag-dest"); g_return_if_fail (site != NULL); if (site->do_proxy) @@ -1526,8 +1593,8 @@ gtk_drag_dest_leave (GtkWidget *widget, gtk_drag_unhighlight (widget); if (!(site->flags & GTK_DEST_DEFAULT_MOTION) || site->have_drag) - gtk_signal_emit_by_name (GTK_OBJECT (widget), "drag_leave", - context, time); + g_signal_emit_by_name (widget, "drag_leave", + context, time); site->have_drag = FALSE; } @@ -1544,7 +1611,7 @@ gtk_drag_dest_motion (GtkWidget *widget, GdkDragAction action = 0; gboolean retval; - site = gtk_object_get_data (GTK_OBJECT (widget), "gtk-drag-dest"); + site = g_object_get_data (G_OBJECT (widget), "gtk-drag-dest"); g_return_val_if_fail (site != NULL, FALSE); if (site->do_proxy) @@ -1568,11 +1635,12 @@ gtk_drag_dest_motion (GtkWidget *widget, } else { - gdk_drag_find_window (info->proxy_source->context, - NULL, - current_event->dnd.x_root, - current_event->dnd.y_root, - &dest_window, &proto); + gdk_drag_find_window_for_screen (info->proxy_source->context, + NULL, + gdk_drawable_get_screen (current_event->dnd.window), + current_event->dnd.x_root, + current_event->dnd.y_root, + &dest_window, &proto); } gdk_drag_motion (info->proxy_source->context, @@ -1583,7 +1651,7 @@ gtk_drag_dest_motion (GtkWidget *widget, context->actions, time); if (!site->proxy_window && dest_window) - gdk_window_unref (dest_window); + g_object_unref (dest_window); selection = gdk_drag_get_selection (info->proxy_source->context); if (selection && @@ -1632,8 +1700,8 @@ gtk_drag_dest_motion (GtkWidget *widget, } } - gtk_signal_emit_by_name (GTK_OBJECT (widget), "drag_motion", - context, x, y, time, &retval); + g_signal_emit_by_name (widget, "drag_motion", + context, x, y, time, &retval); return (site->flags & GTK_DEST_DEFAULT_MOTION) ? TRUE : retval; } @@ -1648,7 +1716,7 @@ gtk_drag_dest_drop (GtkWidget *widget, GtkDragDestSite *site; GtkDragDestInfo *info; - site = gtk_object_get_data (GTK_OBJECT (widget), "gtk-drag-dest"); + site = g_object_get_data (G_OBJECT (widget), "gtk-drag-dest"); g_return_val_if_fail (site != NULL, FALSE); info = gtk_drag_get_dest_info (context, FALSE); @@ -1688,11 +1756,12 @@ gtk_drag_dest_drop (GtkWidget *widget, } else { - gdk_drag_find_window (info->proxy_source->context, - NULL, - current_event->dnd.x_root, - current_event->dnd.y_root, - &dest_window, &proto); + gdk_drag_find_window_for_screen (info->proxy_source->context, + NULL, + gdk_drawable_get_screen (current_event->dnd.window), + current_event->dnd.x_root, + current_event->dnd.y_root, + &dest_window, &proto); } gdk_drag_motion (info->proxy_source->context, @@ -1703,7 +1772,7 @@ gtk_drag_dest_drop (GtkWidget *widget, context->actions, time); if (!site->proxy_window && dest_window) - gdk_window_unref (dest_window); + g_object_unref (dest_window); selection = gdk_drag_get_selection (info->proxy_source->context); if (selection && @@ -1732,8 +1801,8 @@ gtk_drag_dest_drop (GtkWidget *widget, gtk_drag_get_data (widget, context, target, time); } - gtk_signal_emit_by_name (GTK_OBJECT (widget), "drag_drop", - context, x, y, time, &retval); + g_signal_emit_by_name (widget, "drag_drop", + context, x, y, time, &retval); return (site->flags & GTK_DEST_DEFAULT_DROP) ? TRUE : retval; } @@ -1770,7 +1839,7 @@ gtk_drag_begin (GtkWidget *widget, GdkDragContext *context; GtkWidget *ipc_widget; - g_return_val_if_fail (widget != NULL, NULL); + g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); g_return_val_if_fail (GTK_WIDGET_REALIZED (widget), NULL); g_return_val_if_fail (target_list != NULL, NULL); @@ -1786,7 +1855,7 @@ gtk_drag_begin (GtkWidget *widget, tmp_list = tmp_list->prev; } - ipc_widget = gtk_drag_get_ipc_widget (); + ipc_widget = gtk_drag_get_ipc_widget (gtk_widget_get_screen (widget)); source_widgets = g_slist_prepend (source_widgets, ipc_widget); context = gdk_drag_begin (ipc_widget->window, targets); @@ -1795,10 +1864,9 @@ gtk_drag_begin (GtkWidget *widget, info = gtk_drag_get_source_info (context, TRUE); info->ipc_widget = ipc_widget; - gtk_object_set_data (GTK_OBJECT (info->ipc_widget), "gtk-info", info); + g_object_set_data (G_OBJECT (info->ipc_widget), "gtk-info", info); info->widget = gtk_widget_ref (widget); - info->button = button; info->target_list = target_list; @@ -1816,27 +1884,25 @@ gtk_drag_begin (GtkWidget *widget, gtk_drag_get_event_actions (event, info->button, actions, &suggested_action, &possible_actions); - info->cursor = gtk_drag_get_cursor (suggested_action); + info->cursor = gtk_drag_get_cursor (gtk_widget_get_display (widget), suggested_action); /* Set cur_x, cur_y here so if the "drag_begin" signal shows * the drag icon, it will be in the right place */ if (event && event->type == GDK_MOTION_NOTIFY) { + info->cur_screen = gtk_widget_get_screen (widget); info->cur_x = event->motion.x_root; info->cur_y = event->motion.y_root; } else { - gint x, y; - gdk_window_get_pointer (GDK_ROOT_PARENT (), &x, &y, NULL); - - info->cur_x = x; - info->cur_y = y; + gdk_display_get_pointer (gtk_widget_get_display (widget), + &info->cur_screen, &info->cur_x, &info->cur_y, NULL); } - gtk_signal_emit_by_name (GTK_OBJECT (widget), "drag_begin", - info->context); + g_signal_emit_by_name (widget, "drag_begin", + info->context); if (event && event->type == GDK_MOTION_NOTIFY) gtk_drag_motion_cb (info->ipc_widget, (GdkEventMotion *)event, info); @@ -1844,16 +1910,16 @@ gtk_drag_begin (GtkWidget *widget, info->start_x = info->cur_x; info->start_y = info->cur_y; - gtk_signal_connect (GTK_OBJECT (info->ipc_widget), "button_release_event", - GTK_SIGNAL_FUNC (gtk_drag_button_release_cb), info); - gtk_signal_connect (GTK_OBJECT (info->ipc_widget), "motion_notify_event", - GTK_SIGNAL_FUNC (gtk_drag_motion_cb), info); - gtk_signal_connect (GTK_OBJECT (info->ipc_widget), "key_press_event", - GTK_SIGNAL_FUNC (gtk_drag_key_cb), info); - gtk_signal_connect (GTK_OBJECT (info->ipc_widget), "key_release_event", - GTK_SIGNAL_FUNC (gtk_drag_key_cb), info); - gtk_signal_connect (GTK_OBJECT (info->ipc_widget), "selection_get", - GTK_SIGNAL_FUNC (gtk_drag_selection_get), info); + g_signal_connect (info->ipc_widget, "button_release_event", + G_CALLBACK (gtk_drag_button_release_cb), info); + g_signal_connect (info->ipc_widget, "motion_notify_event", + G_CALLBACK (gtk_drag_motion_cb), info); + g_signal_connect (info->ipc_widget, "key_press_event", + G_CALLBACK (gtk_drag_key_cb), info); + g_signal_connect (info->ipc_widget, "key_release_event", + G_CALLBACK (gtk_drag_key_cb), info); + g_signal_connect (info->ipc_widget, "selection_get", + G_CALLBACK (gtk_drag_selection_get), info); /* We use a GTK grab here to override any grabs that the widget * we are dragging from might have held @@ -1866,19 +1932,14 @@ gtk_drag_begin (GtkWidget *widget, { if (gdk_keyboard_grab (info->ipc_widget->window, FALSE, time) != 0) { - /* FIXME: This should be cleaned up... */ - GdkEventButton ev; - - ev.time = time; - ev.type = GDK_BUTTON_RELEASE; - ev.button = info->button; - - gtk_drag_button_release_cb (widget, &ev, info); - + gtk_drag_cancel (info, time); return NULL; } } + info->have_grab = TRUE; + info->grab_time = time; + return info->context; } @@ -1903,9 +1964,9 @@ gtk_drag_source_set (GtkWidget *widget, { GtkDragSourceSite *site; - g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); - site = gtk_object_get_data (GTK_OBJECT (widget), "gtk-site-data"); + site = g_object_get_data (G_OBJECT (widget), "gtk-site-data"); gtk_widget_add_events (widget, gtk_widget_get_events (widget) | @@ -1923,16 +1984,16 @@ gtk_drag_source_set (GtkWidget *widget, site->icon_type = GTK_IMAGE_EMPTY; - gtk_signal_connect (GTK_OBJECT (widget), "button_press_event", - GTK_SIGNAL_FUNC (gtk_drag_source_event_cb), - site); - gtk_signal_connect (GTK_OBJECT (widget), "motion_notify_event", - GTK_SIGNAL_FUNC (gtk_drag_source_event_cb), - site); + g_signal_connect (widget, "button_press_event", + G_CALLBACK (gtk_drag_source_event_cb), + site); + g_signal_connect (widget, "motion_notify_event", + G_CALLBACK (gtk_drag_source_event_cb), + site); - gtk_object_set_data_full (GTK_OBJECT (widget), - "gtk-site-data", - site, gtk_drag_source_site_destroy); + g_object_set_data_full (G_OBJECT (widget), + "gtk-site-data", + site, gtk_drag_source_site_destroy); } site->start_button_mask = start_button_mask; @@ -1959,14 +2020,19 @@ gtk_drag_source_unset (GtkWidget *widget) { GtkDragSourceSite *site; - g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); - site = gtk_object_get_data (GTK_OBJECT (widget), "gtk-site-data"); + site = g_object_get_data (G_OBJECT (widget), "gtk-site-data"); if (site) { - gtk_signal_disconnect_by_data (GTK_OBJECT (widget), site); - gtk_object_set_data (GTK_OBJECT (widget), "gtk-site-data", NULL); + g_signal_handlers_disconnect_by_func (widget, + gtk_drag_source_event_cb, + site); + g_signal_handlers_disconnect_by_func (widget, + gtk_drag_source_event_cb, + site); + g_object_set_data (G_OBJECT (widget), "gtk-site-data", NULL); } } @@ -1979,12 +2045,12 @@ gtk_drag_source_unset_icon (GtkDragSourceSite *site) break; case GTK_IMAGE_PIXMAP: if (site->icon_data.pixmap.pixmap) - gdk_pixmap_unref (site->icon_data.pixmap.pixmap); + g_object_unref (site->icon_data.pixmap.pixmap); if (site->icon_mask) - gdk_pixmap_unref (site->icon_mask); + g_object_unref (site->icon_mask); break; case GTK_IMAGE_PIXBUF: - g_object_unref (G_OBJECT (site->icon_data.pixbuf.pixbuf)); + g_object_unref (site->icon_data.pixbuf.pixbuf); break; case GTK_IMAGE_STOCK: g_free (G_OBJECT (site->icon_data.stock.stock_id)); @@ -1996,7 +2062,7 @@ gtk_drag_source_unset_icon (GtkDragSourceSite *site) site->icon_type = GTK_IMAGE_EMPTY; if (site->colormap) - gdk_colormap_unref (site->colormap); + g_object_unref (site->colormap); site->colormap = NULL; } @@ -2020,18 +2086,18 @@ gtk_drag_source_set_icon (GtkWidget *widget, { GtkDragSourceSite *site; - g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); g_return_if_fail (GDK_IS_COLORMAP (colormap)); g_return_if_fail (GDK_IS_PIXMAP (pixmap)); g_return_if_fail (!mask || GDK_IS_PIXMAP (mask)); - site = gtk_object_get_data (GTK_OBJECT (widget), "gtk-site-data"); + site = g_object_get_data (G_OBJECT (widget), "gtk-site-data"); g_return_if_fail (site != NULL); - gdk_colormap_ref (colormap); - gdk_pixmap_ref (pixmap); + g_object_ref (colormap); + g_object_ref (pixmap); if (mask) - gdk_pixmap_ref (mask); + g_object_ref (mask); gtk_drag_source_unset_icon (site); @@ -2057,12 +2123,12 @@ gtk_drag_source_set_icon_pixbuf (GtkWidget *widget, { GtkDragSourceSite *site; - g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); g_return_if_fail (GDK_IS_PIXBUF (pixbuf)); - site = gtk_object_get_data (GTK_OBJECT (widget), "gtk-site-data"); + site = g_object_get_data (G_OBJECT (widget), "gtk-site-data"); g_return_if_fail (site != NULL); - gdk_pixbuf_ref (pixbuf); + g_object_ref (pixbuf); gtk_drag_source_unset_icon (site); @@ -2084,10 +2150,10 @@ gtk_drag_source_set_icon_stock (GtkWidget *widget, { GtkDragSourceSite *site; - g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); g_return_if_fail (stock_id != NULL); - site = gtk_object_get_data (GTK_OBJECT (widget), "gtk-site-data"); + site = g_object_get_data (G_OBJECT (widget), "gtk-site-data"); g_return_if_fail (site != NULL); gtk_drag_source_unset_icon (site); @@ -2095,6 +2161,89 @@ gtk_drag_source_set_icon_stock (GtkWidget *widget, site->icon_data.stock.stock_id = g_strdup (stock_id); } +static void +gtk_drag_get_icon (GtkDragSourceInfo *info, + GtkWidget **icon_window, + gint *hot_x, + gint *hot_y) +{ + if (get_can_change_screen (info->icon_window)) + gtk_window_set_screen (GTK_WINDOW (info->icon_window), + info->cur_screen); + + if (gtk_widget_get_screen (info->icon_window) != info->cur_screen) + { + if (!info->fallback_icon) + { + gint save_hot_x, save_hot_y; + gboolean save_destroy_icon; + GtkWidget *save_icon_window; + + /* HACK to get the appropriate icon + */ + save_icon_window = info->icon_window; + save_hot_x = info->hot_x; + save_hot_y = info->hot_x; + save_destroy_icon = info->destroy_icon; + + info->icon_window = NULL; + gtk_drag_set_icon_default (info->context); + info->fallback_icon = info->icon_window; + + info->icon_window = save_icon_window; + info->hot_x = save_hot_x; + info->hot_y = save_hot_y; + info->destroy_icon = save_destroy_icon; + } + + gtk_widget_hide (info->icon_window); + + *icon_window = info->fallback_icon; + gtk_window_set_screen (GTK_WINDOW (*icon_window), info->cur_screen); + + if (!default_icon_pixmap) + { + *hot_x = -2; + *hot_y = -2; + } + else + { + *hot_x = default_icon_hot_x; + *hot_y = default_icon_hot_y; + } + } + else + { + if (info->fallback_icon) + gtk_widget_hide (info->fallback_icon); + + *icon_window = info->icon_window; + *hot_x = info->hot_x; + *hot_y = info->hot_y; + } +} + +static void +gtk_drag_update_icon (GtkDragSourceInfo *info) +{ + if (info->icon_window) + { + GtkWidget *icon_window; + gint hot_x, hot_y; + + gtk_drag_get_icon (info, &icon_window, &hot_x, &hot_y); + + gtk_window_move (GTK_WINDOW (icon_window), + info->cur_x - hot_x, + info->cur_y - hot_y); + + if (GTK_WIDGET_VISIBLE (icon_window)) + gdk_window_raise (icon_window->window); + else + gtk_widget_show (icon_window); + } +} + static void gtk_drag_set_icon_window (GdkDragContext *context, GtkWidget *widget, @@ -2104,27 +2253,18 @@ gtk_drag_set_icon_window (GdkDragContext *context, { GtkDragSourceInfo *info; - g_return_if_fail (context != NULL); - g_return_if_fail (widget != NULL); - info = gtk_drag_get_source_info (context, FALSE); gtk_drag_remove_icon (info); + if (widget) + gtk_widget_ref (widget); + info->icon_window = widget; info->hot_x = hot_x; info->hot_y = hot_y; - - if (widget) - { - gtk_widget_set_uposition (widget, - info->cur_x - info->hot_x, - info->cur_y - info->hot_y); - gtk_widget_ref (widget); - gdk_window_raise (widget->window); - gtk_widget_show (widget); - } - info->destroy_icon = destroy_on_release; + + gtk_drag_update_icon (info); } /** @@ -2146,12 +2286,35 @@ gtk_drag_set_icon_widget (GdkDragContext *context, gint hot_x, gint hot_y) { - g_return_if_fail (context != NULL); - g_return_if_fail (widget != NULL); + g_return_if_fail (GDK_IS_DRAG_CONTEXT (context)); + g_return_if_fail (context->is_source); + g_return_if_fail (GTK_IS_WIDGET (widget)); gtk_drag_set_icon_window (context, widget, hot_x, hot_y, FALSE); } +static void +icon_window_realize (GtkWidget *window, + GdkPixbuf *pixbuf) +{ + GdkPixmap *pixmap; + GdkPixmap *mask; + + gdk_pixbuf_render_pixmap_and_mask_for_colormap (pixbuf, + gtk_widget_get_colormap (window), + &pixmap, &mask, 128); + + gdk_window_set_back_pixmap (window->window, pixmap, FALSE); + + if (mask) + gtk_widget_shape_combine_mask (window, mask, 0, 0); + + g_object_unref (G_OBJECT (pixmap)); + + if (mask) + g_object_unref (G_OBJECT (mask)); +} + static void set_icon_stock_pixbuf (GdkDragContext *context, const gchar *stock_id, @@ -2161,15 +2324,19 @@ set_icon_stock_pixbuf (GdkDragContext *context, { GtkWidget *window; gint width, height; - GdkPixmap *pixmap; - GdkPixmap *mask; - + GdkScreen *screen; + g_return_if_fail (context != NULL); g_return_if_fail (pixbuf != NULL || stock_id != NULL); g_return_if_fail (pixbuf == NULL || stock_id == NULL); + + screen = gdk_drawable_get_screen (context->source_window); - gtk_widget_push_colormap (gdk_rgb_get_colormap ()); + /* Push a NULL colormap to guard against gtk_widget_push_colormap() */ + gtk_widget_push_colormap (NULL); window = gtk_window_new (GTK_WINDOW_POPUP); + gtk_window_set_screen (GTK_WINDOW (window), screen); + set_can_change_screen (window, TRUE); gtk_widget_pop_colormap (); gtk_widget_set_events (window, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK); @@ -2188,27 +2355,22 @@ set_icon_stock_pixbuf (GdkDragContext *context, } } + else + g_object_ref (pixbuf); width = gdk_pixbuf_get_width (pixbuf); height = gdk_pixbuf_get_width (pixbuf); - gtk_widget_set_usize (window, - gdk_pixbuf_get_width (pixbuf), - gdk_pixbuf_get_height (pixbuf)); - gtk_widget_realize (window); - - gdk_pixbuf_render_pixmap_and_mask (pixbuf, &pixmap, &mask, 128); - - gdk_window_set_back_pixmap (window->window, pixmap, FALSE); - - if (mask) - gtk_widget_shape_combine_mask (window, mask, 0, 0); - - g_object_unref (G_OBJECT (pixmap)); - - if (mask) - g_object_unref (G_OBJECT (mask)); + gtk_widget_set_size_request (window, + gdk_pixbuf_get_width (pixbuf), + gdk_pixbuf_get_height (pixbuf)); + g_signal_connect_closure (window, "realize", + g_cclosure_new (G_CALLBACK (icon_window_realize), + pixbuf, + (GClosureNotify)g_object_unref), + FALSE); + gtk_drag_set_icon_window (context, window, hot_x, hot_y, TRUE); } @@ -2229,6 +2391,7 @@ gtk_drag_set_icon_pixbuf (GdkDragContext *context, gint hot_y) { g_return_if_fail (GDK_IS_DRAG_CONTEXT (context)); + g_return_if_fail (context->is_source); g_return_if_fail (GDK_IS_PIXBUF (pixbuf)); set_icon_stock_pixbuf (context, NULL, pixbuf, hot_x, hot_y); @@ -2251,6 +2414,7 @@ gtk_drag_set_icon_stock (GdkDragContext *context, gint hot_y) { g_return_if_fail (GDK_IS_DRAG_CONTEXT (context)); + g_return_if_fail (context->is_source); g_return_if_fail (stock_id != NULL); set_icon_stock_pixbuf (context, stock_id, NULL, hot_x, hot_y); @@ -2280,23 +2444,33 @@ gtk_drag_set_icon_pixmap (GdkDragContext *context, gint hot_y) { GtkWidget *window; + GdkScreen *screen; gint width, height; - g_return_if_fail (context != NULL); - g_return_if_fail (colormap != NULL); - g_return_if_fail (pixmap != NULL); + 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)); + g_return_if_fail (!mask || GDK_IS_PIXMAP (mask)); - gdk_window_get_size (pixmap, &width, &height); + screen = gdk_colormap_get_screen (colormap); + + g_return_if_fail (gdk_drawable_get_screen (pixmap) == screen); + g_return_if_fail (!mask || gdk_drawable_get_screen (mask) == screen); + + gdk_drawable_get_size (pixmap, &width, &height); gtk_widget_push_colormap (colormap); window = gtk_window_new (GTK_WINDOW_POPUP); + gtk_window_set_screen (GTK_WINDOW (window), screen); + set_can_change_screen (window, FALSE); gtk_widget_set_events (window, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK); gtk_widget_set_app_paintable (GTK_WIDGET (window), TRUE); gtk_widget_pop_colormap (); - gtk_widget_set_usize (window, width, height); + gtk_widget_set_size_request (window, width, height); gtk_widget_realize (window); gdk_window_set_back_pixmap (window->window, pixmap, FALSE); @@ -2318,7 +2492,8 @@ gtk_drag_set_icon_pixmap (GdkDragContext *context, void gtk_drag_set_icon_default (GdkDragContext *context) { - g_return_if_fail (context != NULL); + g_return_if_fail (GDK_IS_DRAG_CONTEXT (context)); + g_return_if_fail (context->is_source); if (!default_icon_pixmap) gtk_drag_set_icon_stock (context, GTK_STOCK_DND, -2, -2); @@ -2342,7 +2517,7 @@ gtk_drag_set_icon_default (GdkDragContext *context) * Changes the default drag icon. GTK+ retains references for the * arguments, and will release them when they are no longer needed. * This function is obsolete. The default icon should now be changed - * via the stock system by changing the stock pixbuf for %GTK_STOCK_DND. + * via the stock system by changing the stock pixbuf for #GTK_STOCK_DND. **/ void gtk_drag_set_default_icon (GdkColormap *colormap, @@ -2351,25 +2526,26 @@ gtk_drag_set_default_icon (GdkColormap *colormap, gint hot_x, gint hot_y) { - g_return_if_fail (colormap != NULL); - g_return_if_fail (pixmap != NULL); + g_return_if_fail (GDK_IS_COLORMAP (colormap)); + g_return_if_fail (GDK_IS_PIXMAP (pixmap)); + g_return_if_fail (!mask || GDK_IS_PIXMAP (mask)); if (default_icon_colormap) - gdk_colormap_unref (default_icon_colormap); + g_object_unref (default_icon_colormap); if (default_icon_pixmap) - gdk_pixmap_unref (default_icon_pixmap); + g_object_unref (default_icon_pixmap); if (default_icon_mask) - gdk_pixmap_unref (default_icon_mask); + g_object_unref (default_icon_mask); default_icon_colormap = colormap; - gdk_colormap_ref (colormap); + g_object_ref (colormap); default_icon_pixmap = pixmap; - gdk_pixmap_ref (pixmap); + g_object_ref (pixmap); default_icon_mask = mask; if (mask) - gdk_pixmap_ref (mask); + g_object_ref (mask); default_icon_hot_x = hot_x; default_icon_hot_y = hot_y; @@ -2431,9 +2607,10 @@ _gtk_drag_source_handle_event (GtkWidget *widget, } } } - else + else if (info->have_grab) { - cursor = gtk_drag_get_cursor (event->dnd.context->action); + cursor = gtk_drag_get_cursor (gtk_widget_get_display (widget), + event->dnd.context->action); if (info->cursor != cursor) { gdk_pointer_grab (widget->window, FALSE, @@ -2441,14 +2618,14 @@ _gtk_drag_source_handle_event (GtkWidget *widget, GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_RELEASE_MASK, NULL, - cursor, event->dnd.time); + cursor, info->grab_time); info->cursor = cursor; } if (info->last_event) { gtk_drag_update (info, - info->cur_x, info->cur_y, + info->cur_screen, info->cur_x, info->cur_y, info->last_event); info->last_event = NULL; } @@ -2488,7 +2665,10 @@ gtk_drag_source_check_selection (GtkDragSourceInfo *info, tmp_list = tmp_list->next; } - gtk_selection_owner_set (info->ipc_widget, selection, time); + gtk_selection_owner_set_for_display (gtk_widget_get_display (info->widget), + info->ipc_widget, + selection, + time); info->selections = g_list_prepend (info->selections, GUINT_TO_POINTER (selection)); @@ -2561,11 +2741,9 @@ gtk_drag_drop_finished (GtkDragSourceInfo *info, anim->n_steps = MAX (info->cur_x - info->start_x, info->cur_y - info->start_y) / ANIM_STEP_LENGTH; anim->n_steps = CLAMP (anim->n_steps, ANIM_MIN_STEPS, ANIM_MAX_STEPS); - if (info->icon_window) - { - gtk_widget_show (info->icon_window); - gdk_window_raise (info->icon_window->window); - } + + info->cur_screen = gtk_widget_get_screen (info->widget); + gtk_drag_update_icon (info); /* Mark the context as dead, so if the destination decides * to respond really late, we still are OK. @@ -2580,12 +2758,15 @@ static void gtk_drag_source_release_selections (GtkDragSourceInfo *info, guint32 time) { + GdkDisplay *display = gtk_widget_get_display (info->widget); GList *tmp_list = info->selections; + while (tmp_list) { GdkAtom selection = GDK_POINTER_TO_ATOM (tmp_list->data); - if (gdk_selection_owner_get (selection) == info->ipc_widget->window) - gtk_selection_owner_set (NULL, selection, time); + if (gdk_selection_owner_get_for_display (display, selection) == info->ipc_widget->window) + gtk_selection_owner_set_for_display (display, NULL, selection, time); + tmp_list = tmp_list->next; } @@ -2623,10 +2804,10 @@ gtk_drag_drop (GtkDragSourceInfo *info, selection_data.data = NULL; selection_data.length = -1; - gtk_signal_emit_by_name (GTK_OBJECT (info->widget), "drag_data_get", - info->context, &selection_data, - pair->info, - time); + g_signal_emit_by_name (info->widget, "drag_data_get", + info->context, &selection_data, + pair->info, + time); /* FIXME: Should we check for length >= 0 here? */ gtk_drag_drop_finished (info, TRUE, time); @@ -2775,9 +2956,9 @@ gtk_drag_selection_get (GtkWidget *widget, switch (sel_info) { case TARGET_DELETE: - gtk_signal_emit_by_name (GTK_OBJECT (info->widget), - "drag_data_delete", - info->context); + g_signal_emit_by_name (info->widget, + "drag_data_delete", + info->context); gtk_selection_data_set (selection_data, null_atom, 8, NULL, 0); break; case TARGET_MOTIF_SUCCESS: @@ -2808,11 +2989,11 @@ gtk_drag_selection_get (GtkWidget *widget, selection_data->target, &target_info)) { - gtk_signal_emit_by_name (GTK_OBJECT (info->widget), "drag_data_get", - info->context, - selection_data, - target_info, - time); + g_signal_emit_by_name (info->widget, "drag_data_get", + info->context, + selection_data, + target_info, + time); } } break; @@ -2842,9 +3023,16 @@ gtk_drag_anim_timeout (gpointer data) y = (anim->info->start_y * (anim->step + 1) + anim->info->cur_y * (anim->n_steps - anim->step - 1)) / anim->n_steps; if (anim->info->icon_window) - gtk_widget_set_uposition (anim->info->icon_window, - x - anim->info->hot_x, - y - anim->info->hot_y); + { + GtkWidget *icon_window; + gint hot_x, hot_y; + + gtk_drag_get_icon (anim->info, &icon_window, &hot_x, &hot_y); + + gtk_window_move (GTK_WINDOW (icon_window), + x - hot_x, + y - hot_y); + } anim->step++; @@ -2865,7 +3053,13 @@ gtk_drag_remove_icon (GtkDragSourceInfo *info) if (info->destroy_icon) gtk_widget_destroy (info->icon_window); - gtk_widget_unref (info->icon_window); + if (info->fallback_icon) + { + gtk_widget_destroy (info->fallback_icon); + info->fallback_icon = NULL; + } + + g_object_unref (info->icon_window); info->icon_window = NULL; } } @@ -2876,22 +3070,35 @@ gtk_drag_source_info_destroy (GtkDragSourceInfo *info) gtk_drag_remove_icon (info); if (!info->proxy_dest) - gtk_signal_emit_by_name (GTK_OBJECT (info->widget), "drag_end", - info->context); + g_signal_emit_by_name (info->widget, "drag_end", + info->context); if (info->widget) - gtk_widget_unref (info->widget); + g_object_unref (info->widget); + + + g_signal_handlers_disconnect_by_func (info->ipc_widget, + gtk_drag_button_release_cb, + info); + g_signal_handlers_disconnect_by_func (info->ipc_widget, + gtk_drag_motion_cb, + info); + g_signal_handlers_disconnect_by_func (info->ipc_widget, + gtk_drag_key_cb, + info); + g_signal_handlers_disconnect_by_func (info->ipc_widget, + gtk_drag_selection_get, + info); - gtk_signal_disconnect_by_data (GTK_OBJECT (info->ipc_widget), info); gtk_selection_remove_all (info->ipc_widget); - gtk_object_set_data (GTK_OBJECT (info->ipc_widget), "gtk-info", NULL); + g_object_set_data (G_OBJECT (info->ipc_widget), "gtk-info", NULL); source_widgets = g_slist_remove (source_widgets, info->ipc_widget); gtk_drag_release_ipc_widget (info->ipc_widget); gtk_target_list_unref (info->target_list); gtk_drag_clear_source_info (info->context); - gdk_drag_context_unref (info->context); + g_object_unref (info->context); if (info->drop_timeout) gtk_timeout_remove (info->drop_timeout); @@ -2912,13 +3119,13 @@ gtk_drag_source_info_destroy (GtkDragSourceInfo *info) static void gtk_drag_update (GtkDragSourceInfo *info, + GdkScreen *screen, gint x_root, gint y_root, GdkEvent *event) { GdkDragAction action; GdkDragAction possible_actions; - GdkWindow *window = NULL; GdkWindow *dest_window; GdkDragProtocol protocol; GdkAtom selection; @@ -2928,21 +3135,15 @@ gtk_drag_update (GtkDragSourceInfo *info, info->button, info->possible_actions, &action, &possible_actions); + info->cur_screen = screen; info->cur_x = x_root; info->cur_y = y_root; - if (info->icon_window) - { - gdk_window_raise (info->icon_window->window); - gtk_widget_set_uposition (info->icon_window, - info->cur_x - info->hot_x, - info->cur_y - info->hot_y); - window = info->icon_window->window; - } - - gdk_drag_find_window (info->context, - window, x_root, y_root, - &dest_window, &protocol); + gtk_drag_update_icon (info); + gdk_drag_find_window_for_screen (info->context, + info->icon_window ? info->icon_window->window : NULL, + screen, x_root, y_root, + &dest_window, &protocol); if (gdk_drag_motion (info->context, dest_window, protocol, x_root, y_root, action, @@ -2966,7 +3167,7 @@ gtk_drag_update (GtkDragSourceInfo *info, } if (dest_window) - gdk_window_unref (dest_window); + g_object_unref (dest_window); selection = gdk_drag_get_selection (info->context); if (selection) @@ -2978,28 +3179,33 @@ gtk_drag_update (GtkDragSourceInfo *info, * Called when the user finishes to drag, either by * releasing the mouse, or by pressing Esc. * arguments: - * widget: GtkInvisible widget for this drag - * info: + * info: Source info for the drag + * time: Timestamp for ending the drag * results: *************************************************************/ static void gtk_drag_end (GtkDragSourceInfo *info, guint32 time) { - GdkEvent send_event; + GdkEvent *send_event; GtkWidget *source_widget = info->widget; + GdkDisplay *display = gtk_widget_get_display (source_widget); - gdk_pointer_ungrab (time); - gdk_keyboard_ungrab (time); - + info->have_grab = FALSE; + + gdk_display_pointer_ungrab (display, time); + gdk_display_keyboard_ungrab (display, time); gtk_grab_remove (info->ipc_widget); - gtk_signal_disconnect_by_func (GTK_OBJECT (info->ipc_widget), - GTK_SIGNAL_FUNC (gtk_drag_button_release_cb), - info); - gtk_signal_disconnect_by_func (GTK_OBJECT (info->ipc_widget), - GTK_SIGNAL_FUNC (gtk_drag_motion_cb), - info); + g_signal_handlers_disconnect_by_func (info->ipc_widget, + gtk_drag_button_release_cb, + info); + g_signal_handlers_disconnect_by_func (info->ipc_widget, + gtk_drag_motion_cb, + info); + g_signal_handlers_disconnect_by_func (info->ipc_widget, + gtk_drag_key_cb, + info); /* Send on a release pair to the the original * widget to convince it to release its grab. We need to @@ -3008,20 +3214,39 @@ gtk_drag_end (GtkDragSourceInfo *info, guint32 time) * expect propagation. */ - send_event.button.type = GDK_BUTTON_RELEASE; - send_event.button.window = GDK_ROOT_PARENT (); - send_event.button.send_event = TRUE; - send_event.button.time = time; - send_event.button.x = 0; - send_event.button.y = 0; - send_event.button.axes = NULL; - send_event.button.state = 0; - send_event.button.button = info->button; - send_event.button.device = gdk_device_get_core_pointer (); - send_event.button.x_root = 0; - send_event.button.y_root = 0; + send_event = gdk_event_new (GDK_BUTTON_RELEASE); + send_event->button.window = g_object_ref (gtk_widget_get_root_window (source_widget)); + send_event->button.send_event = TRUE; + send_event->button.time = time; + send_event->button.x = 0; + send_event->button.y = 0; + send_event->button.axes = NULL; + send_event->button.state = 0; + send_event->button.button = info->button; + send_event->button.device = gdk_display_get_core_pointer (display); + send_event->button.x_root = 0; + send_event->button.y_root = 0; + + gtk_propagate_event (source_widget, send_event); + gdk_event_free (send_event); +} + +/************************************************************* + * gtk_drag_cancel: + * Called on cancellation of a drag, either by the user + * or programmatically. + * arguments: + * info: Source info for the drag + * time: Timestamp for ending the drag + * results: + *************************************************************/ - gtk_propagate_event (source_widget, &send_event); +static void +gtk_drag_cancel (GtkDragSourceInfo *info, guint32 time) +{ + gtk_drag_end (info, time); + gdk_drag_abort (info->context, time); + gtk_drag_drop_finished (info, FALSE, time); } /************************************************************* @@ -3038,16 +3263,21 @@ gtk_drag_motion_cb (GtkWidget *widget, gpointer data) { GtkDragSourceInfo *info = (GtkDragSourceInfo *)data; + GdkScreen *screen; gint x_root, y_root; if (event->is_hint) { - gdk_window_get_pointer (GDK_ROOT_PARENT(), &x_root, &y_root, NULL); + GdkDisplay *display = gtk_widget_get_display (widget); + + gdk_display_get_pointer (display, &screen, &x_root, &y_root, NULL); event->x_root = x_root; event->y_root = y_root; } + else + screen = gdk_event_get_screen ((GdkEvent *)event); - gtk_drag_update (info, event->x_root, event->y_root, (GdkEvent *)event); + gtk_drag_update (info, screen, event->x_root, event->y_root, (GdkEvent *)event); return TRUE; } @@ -3067,14 +3297,13 @@ gtk_drag_key_cb (GtkWidget *widget, { GtkDragSourceInfo *info = (GtkDragSourceInfo *)data; GdkModifierType state; + GdkWindow *root_window; if (event->type == GDK_KEY_PRESS) { if (event->keyval == GDK_Escape) { - gtk_drag_end (info, event->time); - gdk_drag_abort (info->context, event->time); - gtk_drag_drop_finished (info, FALSE, event->time); + gtk_drag_cancel (info, event->time); return TRUE; } @@ -3086,10 +3315,11 @@ gtk_drag_key_cb (GtkWidget *widget, * to query it here. We could use XGetModifierMapping, but * that would be overkill. */ - gdk_window_get_pointer (GDK_ROOT_PARENT(), NULL, NULL, &state); + root_window = gtk_widget_get_root_window (widget); + gdk_window_get_pointer (root_window, NULL, NULL, &state); event->state = state; - gtk_drag_update (info, info->cur_x, info->cur_y, (GdkEvent *)event); + gtk_drag_update (info, info->cur_screen, info->cur_x, info->cur_y, (GdkEvent *)event); return TRUE; } @@ -3112,16 +3342,14 @@ gtk_drag_button_release_cb (GtkWidget *widget, if (event->button != info->button) return FALSE; - gtk_drag_end (info, event->time); - if ((info->context->action != 0) && (info->context->dest_window != NULL)) { + gtk_drag_end (info, event->time); gtk_drag_drop (info, event->time); } else { - gdk_drag_abort (info->context, event->time); - gtk_drag_drop_finished (info, FALSE, event->time); + gtk_drag_cancel (info, event->time); } return TRUE; @@ -3154,11 +3382,11 @@ gtk_drag_abort_timeout (gpointer data) * @current_x: current X coordinate * @current_y: current Y coordinate * - * Checks to see if a mouse drag starting at (start_x, start_y) and ending - * at (current_x, current_y) has passed the GTK drag threshhold, and thus + * Checks to see if a mouse drag starting at (@start_x, @start_y) and ending + * at (@current_x, @current_y) has passed the GTK+ drag threshhold, and thus * should trigger the beginning of a drag-and-drop operation. * - * Return Value: If the drag threshold has been passed. + * Return Value: %TRUE if the drag threshold has been passed. **/ gboolean gtk_drag_check_threshold (GtkWidget *widget, @@ -3169,6 +3397,8 @@ gtk_drag_check_threshold (GtkWidget *widget, { gint drag_threshold; + g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); + g_object_get (gtk_widget_get_settings (widget), "gtk-dnd-drag-threshold", &drag_threshold, NULL);