]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkdnd.c
Skip insensitive widgets. (#84061)
[~andy/gtk] / gtk / gtkdnd.c
index ca6c833bdffbe9d424feb762879f1ce2a2877653..35281f065e9f474b94cb933a10619478c9ef821c 100644 (file)
@@ -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,6 +93,7 @@ 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 */
@@ -101,9 +102,9 @@ struct _GtkDragSourceInfo
 
   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 
@@ -234,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,
@@ -248,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);
@@ -341,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 },
@@ -359,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
@@ -577,15 +598,15 @@ gtk_drag_get_cursor (GdkDisplay   *display,
       GdkWindow *window = gdk_screen_get_root_window (screen);
 
       GdkPixmap *pixmap = 
-       gdk_bitmap_create_from_data (window, 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 (window, drag_cursors[i].mask, CURSOR_WIDTH, CURSOR_HEIGHT);
+       gdk_bitmap_create_from_data (window, (gchar *)drag_cursors[i].mask, CURSOR_WIDTH, CURSOR_HEIGHT);
 
       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;
@@ -614,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),
@@ -650,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)
     {
@@ -658,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;
        }
@@ -688,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)
     {
@@ -706,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),
@@ -753,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,
@@ -780,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);
 }
@@ -798,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
@@ -816,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);
 }
                            
 
@@ -854,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);
 
@@ -892,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);
 
@@ -902,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;
@@ -921,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);
 }
 
 /**
@@ -939,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;  
 }
@@ -959,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)
     {
@@ -1105,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);
 
@@ -1149,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 && 
@@ -1177,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)
        {
@@ -1189,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)
@@ -1213,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);
 }
@@ -1254,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
@@ -1302,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);
 
@@ -1346,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);
          
@@ -1358,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,
@@ -1415,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;
 }
@@ -1527,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)
@@ -1549,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;
     }
@@ -1567,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)
@@ -1591,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, 
@@ -1606,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 && 
@@ -1655,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;
 }
@@ -1671,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);
@@ -1711,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, 
@@ -1726,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 && 
@@ -1755,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;
     }
@@ -1793,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);
 
@@ -1818,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;
@@ -1846,17 +1891,18 @@ gtk_drag_begin (GtkWidget         *widget,
    */
   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);
@@ -1864,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
@@ -1886,15 +1932,7 @@ 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;
        }
     }
@@ -1926,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) |
@@ -1946,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;
@@ -1982,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);
     }
 }
 
@@ -2002,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));
@@ -2019,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;
 }
 
@@ -2043,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);
 
@@ -2080,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);
 
@@ -2107,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);
@@ -2118,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,
@@ -2127,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);
 }
 
 /**
@@ -2169,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,
@@ -2184,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);
@@ -2217,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);
 }
 
@@ -2258,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);
@@ -2280,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);
@@ -2309,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);
@@ -2348,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);
@@ -2381,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;
@@ -2479,7 +2625,7 @@ _gtk_drag_source_handle_event (GtkWidget *widget,
            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;
              }
@@ -2595,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.
@@ -2660,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);
@@ -2812,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:
@@ -2845,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;
@@ -2879,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++;
 
@@ -2902,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;
     }
 }
@@ -2913,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);
@@ -2949,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;
@@ -2965,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, 
@@ -3003,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)
@@ -3015,15 +3179,15 @@ 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);
 
@@ -3033,15 +3197,15 @@ gtk_drag_end (GtkDragSourceInfo *info, guint32 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);
-  gtk_signal_disconnect_by_func (GTK_OBJECT (info->ipc_widget), 
-                                GTK_SIGNAL_FUNC (gtk_drag_key_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
@@ -3050,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);
 }
 
 /*************************************************************
@@ -3080,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;
 }
@@ -3117,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;
        }
@@ -3135,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;
 }
@@ -3158,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;
@@ -3215,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);