X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkdnd.c;h=35281f065e9f474b94cb933a10619478c9ef821c;hb=fcfb638ab0260c7f320c5ffe7c50a3d669f9881b;hp=ab7b35ef46baea72df9e3d590596b2edec818a1a;hpb=4632fb81c77ba63341e49ea6e323772df1a19a9b;p=~andy%2Fgtk diff --git a/gtk/gtkdnd.c b/gtk/gtkdnd.c index ab7b35ef4..35281f065 100644 --- a/gtk/gtkdnd.c +++ b/gtk/gtkdnd.c @@ -32,7 +32,6 @@ #include "gtkimage.h" #include "gtkinvisible.h" #include "gtkmain.h" -#include "gtksignal.h" #include "gtkstock.h" #include "gtkwindow.h" @@ -83,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 */ @@ -93,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 @@ -179,7 +183,7 @@ static void gtk_drag_get_event_actions (GdkEvent *event, GdkDragAction actions, GdkDragAction *suggested_action, GdkDragAction *possible_actions); -static GdkCursor * gtk_drag_get_cursor (GdkScreen *screen, +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); @@ -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 @@ -549,7 +573,7 @@ gtk_drag_get_event_actions (GdkEvent *event, } static GdkCursor * -gtk_drag_get_cursor (GdkScreen *screen, +gtk_drag_get_cursor (GdkDisplay *display, GdkDragAction action) { gint i; @@ -559,7 +583,7 @@ gtk_drag_get_cursor (GdkScreen *screen, break; if (drag_cursors[i].cursor != NULL) { - if (screen != gdk_cursor_get_screen (drag_cursors[i].cursor)) + if (display != gdk_cursor_get_display (drag_cursors[i].cursor)) { gdk_cursor_unref (drag_cursors[i].cursor); drag_cursors[i].cursor = NULL; @@ -568,25 +592,21 @@ gtk_drag_get_cursor (GdkScreen *screen, if (drag_cursors[i].cursor == NULL) { - GdkColormap *colormap; - 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 (gdk_screen_get_root_window (screen), - 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 (gdk_screen_get_root_window (screen), - drag_cursors[i].mask, CURSOR_WIDTH, CURSOR_HEIGHT); + gdk_bitmap_create_from_data (window, (gchar *)drag_cursors[i].mask, CURSOR_WIDTH, CURSOR_HEIGHT); - colormap = gdk_screen_get_system_colormap (screen); - gdk_color_white (colormap, &bg); - gdk_color_black (colormap, &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; @@ -615,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 (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), @@ -651,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) { @@ -659,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; } @@ -689,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) { @@ -707,12 +732,12 @@ gtk_drag_finish (GdkDragContext *context, { 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), @@ -754,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, @@ -781,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); } @@ -799,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 @@ -817,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); } @@ -855,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); @@ -865,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); } @@ -893,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); @@ -903,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; @@ -922,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); } /** @@ -940,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; } @@ -960,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) { @@ -1106,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); @@ -1150,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 && @@ -1178,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) { @@ -1190,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) @@ -1214,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); } @@ -1255,7 +1298,7 @@ gtk_drag_find_widget (GtkWidget *widget, 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 @@ -1303,7 +1346,7 @@ gtk_drag_find_widget (GtkWidget *widget, { GdkRectangle window_rect = { 0, 0, 0, 0 }; - gdk_window_get_size (window, &window_rect.width, &window_rect.height); + gdk_drawable_get_size (window, &window_rect.width, &window_rect.height); gdk_rectangle_intersect (&new_allocation, &window_rect, &new_allocation); @@ -1347,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); @@ -1359,7 +1402,7 @@ 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, @@ -1416,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; } @@ -1509,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); @@ -1525,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) @@ -1547,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; } @@ -1565,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) @@ -1589,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, @@ -1604,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 && @@ -1653,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; } @@ -1669,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); @@ -1709,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, @@ -1724,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 && @@ -1753,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; } @@ -1791,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); @@ -1816,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; @@ -1837,24 +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 (gtk_widget_get_screen (widget), 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 { - gdk_window_get_pointer (gtk_widget_get_root_window (widget), - &info->cur_x, &info->cur_y, NULL); + 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); @@ -1862,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 @@ -1884,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; } @@ -1921,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) | @@ -1941,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; @@ -1977,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); } } @@ -1997,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)); @@ -2014,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; } @@ -2038,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); @@ -2075,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); @@ -2102,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); @@ -2113,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, @@ -2122,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); } /** @@ -2164,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, @@ -2179,21 +2324,19 @@ set_icon_stock_pixbuf (GdkDragContext *context, { GtkWidget *window; gint width, height; - GdkPixmap *pixmap; - GdkPixmap *mask; GdkScreen *screen; - GdkColormap *colormap; 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); - colormap = gdk_screen_get_rgb_colormap (screen); - - gtk_widget_push_colormap (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); @@ -2212,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_for_colormap (pixbuf, colormap, &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); } @@ -2253,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); @@ -2275,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); @@ -2304,24 +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), gdk_drawable_get_screen (context->source_window)); + 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); @@ -2343,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); @@ -2376,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; @@ -2456,9 +2607,9 @@ _gtk_drag_source_handle_event (GtkWidget *widget, } } } - else + else if (info->have_grab) { - cursor = gtk_drag_get_cursor (gtk_widget_get_screen (widget), + cursor = gtk_drag_get_cursor (gtk_widget_get_display (widget), event->dnd.context->action); if (info->cursor != cursor) { @@ -2467,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; } @@ -2590,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. @@ -2655,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); @@ -2807,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: @@ -2840,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; @@ -2874,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++; @@ -2897,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; } } @@ -2908,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); @@ -2944,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; @@ -2960,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, @@ -2998,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) @@ -3010,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); + 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 @@ -3040,20 +3214,39 @@ gtk_drag_end (GtkDragSourceInfo *info, guint32 time) * expect propagation. */ - send_event.button.type = GDK_BUTTON_RELEASE; - send_event.button.window = 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_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); + 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: + *************************************************************/ + +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); } /************************************************************* @@ -3070,18 +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) { - GdkWindow *root_window = gtk_widget_get_root_window (widget); + GdkDisplay *display = gtk_widget_get_display (widget); - gdk_window_get_pointer (root_window, &x_root, &y_root, NULL); + 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; } @@ -3107,9 +3303,7 @@ gtk_drag_key_cb (GtkWidget *widget, { 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; } @@ -3125,7 +3319,7 @@ gtk_drag_key_cb (GtkWidget *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; } @@ -3148,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; @@ -3205,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);