Index: libwnck/pager.c
===================================================================
RCS file: /cvs/gnome/libwnck/libwnck/pager.c,v
retrieving revision 1.52
diff -u -p -r1.52 pager.c
--- libwnck/pager.c	6 Mar 2006 18:58:22 -0000	1.52
+++ libwnck/pager.c	30 Mar 2006 21:31:51 -0000
@@ -45,6 +45,8 @@ struct _WnckPagerPrivate
   GtkOrientation orientation;
   int workspace_size;
   guint screen_connections[N_SCREEN_CONNECTIONS];
+
+  guint dragging : 1;
   int drag_start_x;
   int drag_start_y;
   int drag_start_x_workspace_relative;
@@ -55,7 +57,6 @@ struct _WnckPagerPrivate
   WnckWindow *action_window;
   int action_click_x;
   int action_click_y;
-  guint dragging : 1;
 
   GdkPixbuf *bg_cache;
 
@@ -64,6 +65,8 @@ struct _WnckPagerPrivate
   guint dnd_activate;
   gint  dnd_workspace_number;
   guint dnd_time;
+  WnckWindow *dnd_window;
+  guint in_dnd : 1;
 };
 
 enum
@@ -101,6 +104,13 @@ static gboolean wnck_pager_drag_motion  
 static void wnck_pager_drag_motion_leave (GtkWidget        *widget,
                                           GdkDragContext   *context,
                                           guint             time);
+static void wnck_pager_drag_data_received (GtkWidget          *widget,
+			  	           GdkDragContext     *context,
+				           gint                x,
+				           gint                y,
+				           GtkSelectionData   *selection_data,
+				           guint               info,
+				           guint               time_);
 static gboolean wnck_pager_motion        (GtkWidget        *widget,
                                           GdkEventMotion   *event);
 static gboolean wnck_pager_button_release (GtkWidget        *widget,
@@ -163,6 +173,9 @@ wnck_pager_get_type (void)
 static void
 wnck_pager_init (WnckPager *pager)
 {  
+  static const GtkTargetEntry targets[] = {
+    { "application/x-window-id", 0, 0}
+  };
   pager->priv = g_new0 (WnckPagerPrivate, 1);
 
   pager->priv->n_rows = 1;
@@ -175,7 +188,7 @@ wnck_pager_init (WnckPager *pager)
   pager->priv->action_window = NULL;
   pager->priv->layout_manager_token = WNCK_NO_MANAGER_TOKEN;
 
-  gtk_drag_dest_set (GTK_WIDGET (pager), 0, NULL, 0, 0);
+  gtk_drag_dest_set (GTK_WIDGET (pager), GTK_DEST_DEFAULT_DROP, targets, 1, GDK_ACTION_MOVE);
 
   GTK_WIDGET_SET_FLAGS (GTK_WIDGET (pager), GTK_CAN_FOCUS);
 }
@@ -202,6 +215,7 @@ wnck_pager_class_init (WnckPagerClass *k
   widget_class->get_accessible = wnck_pager_get_accessible;
   widget_class->drag_leave = wnck_pager_drag_motion_leave;
   widget_class->drag_motion = wnck_pager_drag_motion;	
+  widget_class->drag_data_received = wnck_pager_drag_data_received;
 }
 
 static void
@@ -1179,16 +1193,24 @@ wnck_pager_drag_motion (GtkWidget       
   WnckPager *pager;
 
   pager = WNCK_PAGER (widget);
-
-  if (pager->priv->dnd_activate == 0 )
-    pager->priv->dnd_activate = g_timeout_add (WNCK_ACTIVATE_TIMEOUT,
-                                               wnck_pager_drag_motion_timeout,
-                                               pager);
-
   pager->priv->dnd_workspace_number = workspace_at_point (pager, x, y, NULL, NULL);
-  pager->priv->dnd_time = time;
-  gdk_drag_status (context, 0, time);
 
+  if (gtk_drag_dest_find_target (widget, context, NULL))
+    {
+      gtk_drag_highlight (widget);
+      gdk_drag_status (context, context->suggested_action, time);
+    }
+  else 
+    {
+      if (pager->priv->dnd_activate == 0 )   
+         pager->priv->dnd_activate = g_timeout_add (WNCK_ACTIVATE_TIMEOUT,
+                                                    wnck_pager_drag_motion_timeout,
+                                                    pager);
+
+      pager->priv->dnd_time = time;
+      gdk_drag_status (context, 0, time);
+    }    
+ 
   return (pager->priv->dnd_workspace_number != -1);
 }
  
@@ -1208,8 +1230,57 @@ wnck_pager_drag_motion_leave (GtkWidget 
       pager->priv->dnd_time = 0;
       pager->priv->dnd_activate = 0;
     }
+  gtk_drag_unhighlight (widget);
 }
 
+static void
+wnck_pager_drag_data_received (GtkWidget          *widget,
+	  	               GdkDragContext     *context,
+			       gint                x,
+			       gint                y,
+			       GtkSelectionData   *selection_data,
+			       guint               info,
+			       guint               time)
+{
+  WnckPager *pager = WNCK_PAGER (widget);
+  WnckWorkspace *space;
+  WnckWindow *win;
+  GList *windows;
+  GList *tmp;
+
+  if ((selection_data->length == sizeof (gulong)) && (selection_data->format == 8))
+    {
+      if (pager->priv->dnd_workspace_number >= 0)
+	{
+	  space = wnck_screen_get_workspace (pager->priv->screen, pager->priv->dnd_workspace_number);
+	  if (space)
+            {
+              gulong *xid = (gulong *)selection_data->data;
+	      
+	       windows = wnck_screen_get_windows_stacked (pager->priv->screen);
+	       win = NULL;
+	       
+              for (tmp = windows; tmp != NULL; tmp = tmp->next)
+                {
+                  win = WNCK_WINDOW (tmp->data);
+                  if (wnck_window_get_xid (win) == *xid)
+                    break;
+                }
+      
+              if (win)
+                {
+                  wnck_window_move_to_workspace (win, space);
+                  if (space == wnck_screen_get_active_workspace (pager->priv->screen))
+                     wnck_window_activate (win, time);
+    	           gtk_drag_finish (context, TRUE, FALSE, time);
+         	   return;
+                }	  
+          } 
+       }
+    }    
+  gtk_drag_finish (context, FALSE, FALSE, time);
+}			       
+
 static gboolean
 wnck_pager_motion (GtkWidget        *widget,
                    GdkEventMotion   *event)
@@ -1236,6 +1307,30 @@ wnck_pager_motion (GtkWidget        *wid
       pager->priv->drag_window_y = event->y;
     }
 
+  if (pager->priv->dragging &&
+      (event->x < widget->allocation.x || 
+       event->x > widget->allocation.x + widget->allocation.width ||
+       event->y < widget->allocation.y ||
+       event->y > widget->allocation.y + widget->allocation.height))
+    {
+        static const GtkTargetEntry targets[] = {
+	   { "application/x-window-id", 0, 0}
+	};
+	GdkDragContext *context;
+	GtkTargetList *target_list = gtk_target_list_new (NULL, 0);
+
+	gtk_target_list_add_table (target_list, targets, 1);
+
+	context = gtk_drag_begin (widget, target_list,
+				  GDK_ACTION_MOVE,
+				  1, (GdkEvent *)event);
+
+	gtk_target_list_unref (target_list);
+	pager->priv->dnd_window = pager->priv->drag_window;
+	pager->priv->in_dnd = TRUE;
+	wnck_pager_clear_drag (pager);
+    }
+
   return TRUE;
 }
 
@@ -1246,13 +1341,16 @@ wnck_pager_button_release (GtkWidget    
   WnckWorkspace *space;
   WnckPager *pager;
   int i;
-  gboolean handled = FALSE;
   int viewport_x;
   int viewport_y;
   
   pager = WNCK_PAGER (widget);
 
-  if (event->button == 1 && pager->priv->dragging)
+  if (event->button == 1 && pager->priv->in_dnd) 
+    {
+      pager->priv->in_dnd = FALSE;
+    }
+  else if (event->button == 1 && pager->priv->dragging)
     {
       i = workspace_at_point (pager, event->x, event->y, NULL, NULL);
 
@@ -1273,7 +1371,6 @@ wnck_pager_button_release (GtkWidget    
 	}
       
       wnck_pager_clear_drag (pager);
-      handled = TRUE;
     }
   else if (event->button == 1)
     {
@@ -1308,8 +1405,6 @@ wnck_pager_button_release (GtkWidget    
       
       if (pager->priv->drag_window)
         wnck_pager_clear_drag (pager);
-
-      handled = TRUE;
     }
 
   return FALSE;
Index: libwnck/tasklist.c
===================================================================
RCS file: /cvs/gnome/libwnck/libwnck/tasklist.c,v
retrieving revision 1.99
diff -u -p -r1.99 tasklist.c
--- libwnck/tasklist.c	28 Mar 2006 21:49:20 -0000	1.99
+++ libwnck/tasklist.c	30 Mar 2006 21:31:52 -0000
@@ -2944,6 +2944,22 @@ wnck_task_drag_motion (GtkWidget        
   return TRUE;
 }
 
+void  
+wnck_task_drag_data_get (GtkWidget          *widget,
+		         GdkDragContext     *context,
+		         GtkSelectionData   *selection_data,
+		         guint               info,
+		 	 guint               time,
+		         WnckTask           *task)
+{
+  gulong xid;    
+
+  xid = wnck_window_get_xid (task->window);
+  gtk_selection_data_set (selection_data,
+ 		          selection_data->target,
+			  8, (guchar *)&xid, sizeof (gulong));
+}
+
 static gboolean
 wnck_task_button_press_event (GtkWidget	      *widget,
 			      GdkEventButton  *event,
@@ -3021,6 +3037,9 @@ wnck_task_create_widgets (WnckTask *task
   GdkPixbuf *pixbuf;
   char *text;
   static GQuark disable_sound_quark = 0;
+  static const GtkTargetEntry targets[] = {
+    { "application/x-window-id", 0, 0}
+  };
   
   if (!disable_sound_quark)
     disable_sound_quark = g_quark_from_static_string ("gnome_disable_sound_events");
@@ -3043,6 +3062,14 @@ wnck_task_create_widgets (WnckTask *task
 
   gtk_drag_dest_set (GTK_WIDGET(task->button), 0, NULL, 0, 0);
 
+  if (task->type == WNCK_TASK_WINDOW)
+    {
+      gtk_drag_source_set (GTK_WIDGET (task->button),
+		           GDK_BUTTON1_MASK,
+		           targets, 1,
+		           GDK_ACTION_MOVE);
+    }
+
   hbox = gtk_hbox_new (FALSE, 0);
 
   pixbuf = wnck_task_get_icon (task);
@@ -3104,6 +3131,12 @@ wnck_task_create_widgets (WnckTask *task
                            G_CALLBACK (wnck_task_drag_leave),
                            G_OBJECT (task),
                            0);
+
+  if (task->type == WNCK_TASK_WINDOW) 
+      g_signal_connect_object (G_OBJECT(task->button), "drag_data_get",
+                               G_CALLBACK (wnck_task_drag_data_get),
+                               G_OBJECT (task),
+                               0); 
 
   switch (task->type)
     {
