Index: pager.c
===================================================================
RCS file: /cvs/gnome/libwnck/libwnck/pager.c,v
retrieving revision 1.52
diff -u -p -r1.52 pager.c
--- pager.c	6 Mar 2006 18:58:22 -0000	1.52
+++ pager.c	31 Mar 2006 19:52:49 -0000
@@ -45,17 +45,10 @@ struct _WnckPagerPrivate
   GtkOrientation orientation;
   int workspace_size;
   guint screen_connections[N_SCREEN_CONNECTIONS];
-  int drag_start_x;
-  int drag_start_y;
-  int drag_start_x_workspace_relative;
-  int drag_start_y_workspace_relative;
-  WnckWindow *drag_window;
-  int drag_window_x;
-  int drag_window_y;
+
   WnckWindow *action_window;
   int action_click_x;
   int action_click_y;
-  guint dragging : 1;
 
   GdkPixbuf *bg_cache;
 
@@ -64,6 +57,8 @@ struct _WnckPagerPrivate
   guint dnd_activate;
   gint  dnd_workspace_number;
   guint dnd_time;
+  WnckWindow *dnd_window;
+  gint in_dnd : 1;
 };
 
 enum
@@ -98,13 +93,25 @@ static gboolean wnck_pager_drag_motion  
                                           gint              x,
                                           gint              y,
                                           guint             time);
+static void wnck_pager_drag_begin        (GtkWidget *widget,
+                                          GdkDragContext *drag_context);
+static void wnck_pager_drag_end          (GtkWidget *widget,
+                                          GdkDragContext *drag_context);
 static void wnck_pager_drag_motion_leave (GtkWidget        *widget,
                                           GdkDragContext   *context,
                                           guint             time);
-static gboolean wnck_pager_motion        (GtkWidget        *widget,
-                                          GdkEventMotion   *event);
-static gboolean wnck_pager_button_release (GtkWidget        *widget,
-                                           GdkEventButton   *event);
+static void wnck_pager_drag_data_received (GtkWidget          *widget,
+			  	           GdkDragContext     *context,
+				           gint                x,
+				           gint                y,
+				           GtkSelectionData   *selection_data,
+				           guint               info,
+				           guint               time_);
+static void wnck_pager_drag_data_get      (GtkWidget        *widget,
+		                           GdkDragContext   *context,
+		                           GtkSelectionData *selection_data,
+		                           guint             info,
+		                           guint             time);
 static gboolean wnck_pager_focus         (GtkWidget        *widget,
                                           GtkDirectionType  direction);
 static void workspace_name_changed_callback (WnckWorkspace *workspace,
@@ -118,15 +125,12 @@ static void wnck_pager_disconnect_screen
 
 static void wnck_pager_set_layout_hint   (WnckPager  *pager);
 
-static void wnck_pager_clear_drag (WnckPager *pager);
-
 static GdkPixbuf* wnck_pager_get_background (WnckPager *pager,
                                              int        width,
                                              int        height);
 
 static AtkObject* wnck_pager_get_accessible (GtkWidget *widget);
 
-
 static gpointer parent_class;
 
 GType
@@ -163,6 +167,10 @@ wnck_pager_get_type (void)
 static void
 wnck_pager_init (WnckPager *pager)
 {  
+  static const GtkTargetEntry targets[] = {
+   { "application/x-wm-window-id", 0, 0}
+  };
+  
   pager->priv = g_new0 (WnckPagerPrivate, 1);
 
   pager->priv->n_rows = 1;
@@ -175,7 +183,8 @@ 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_drag_source_set (GTK_WIDGET (pager), GDK_BUTTON1_MASK, targets, 1, GDK_ACTION_MOVE);
 
   GTK_WIDGET_SET_FLAGS (GTK_WIDGET (pager), GTK_CAN_FOCUS);
 }
@@ -196,12 +205,14 @@ wnck_pager_class_init (WnckPagerClass *k
   widget_class->size_allocate = wnck_pager_size_allocate;
   widget_class->expose_event = wnck_pager_expose_event;
   widget_class->button_press_event = wnck_pager_button_press;
-  widget_class->button_release_event = wnck_pager_button_release;
-  widget_class->motion_notify_event = wnck_pager_motion;
   widget_class->focus = wnck_pager_focus;
   widget_class->get_accessible = wnck_pager_get_accessible;
   widget_class->drag_leave = wnck_pager_drag_motion_leave;
+  widget_class->drag_begin = wnck_pager_drag_begin;
+  widget_class->drag_end = wnck_pager_drag_end;
   widget_class->drag_motion = wnck_pager_drag_motion;	
+  widget_class->drag_data_received = wnck_pager_drag_data_received;
+  widget_class->drag_data_get = wnck_pager_drag_data_get;
 }
 
 static void
@@ -251,7 +262,7 @@ wnck_pager_realize (GtkWidget *widget)
   attributes.visual = gtk_widget_get_visual (widget);
   attributes.colormap = gtk_widget_get_colormap (widget);
   attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK |
-    GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK;
+    GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK;
 
   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
 
@@ -271,8 +282,6 @@ wnck_pager_unrealize (GtkWidget *widget)
   
   pager = WNCK_PAGER (widget);
 
-  wnck_pager_clear_drag (pager);
-
   wnck_screen_release_workspace_layout (pager->priv->screen,
                                         pager->priv->layout_manager_token);
   
@@ -909,8 +918,8 @@ wnck_pager_draw_workspace (WnckPager    
 	  WnckWindow *win = tmp->data;
 	  GdkRectangle winrect;
 	  
-          if ((pager->priv->dragging &&
-               win == pager->priv->drag_window) ||
+	  if ((pager->priv->in_dnd &&
+               win == pager->priv->dnd_window) ||
               win == pager->priv->action_window)
 	    {
 	      tmp = tmp->next;
@@ -966,7 +975,6 @@ wnck_pager_expose_event  (GtkWidget     
   WnckWorkspace *active_space;
   GdkPixbuf *bg_pixbuf;
   gboolean first;
-  int drag_space;
   int focus_width;
   
   pager = WNCK_PAGER (widget);
@@ -1006,14 +1014,6 @@ wnck_pager_expose_event  (GtkWidget     
 			widget->allocation.height - 2 * focus_width);
     }
   
-  if (pager->priv->dragging)
-    drag_space = workspace_at_point (pager,
-                                     pager->priv->drag_window_x,
-                                     pager->priv->drag_window_y,
-                                     NULL, NULL);
-  else
-    drag_space = -1;
-  
   i = 0;
   while (i < n_spaces)
     {
@@ -1038,44 +1038,12 @@ wnck_pager_expose_event  (GtkWidget     
             }
           
 	  wnck_pager_draw_workspace (pager, i, &rect, bg_pixbuf,
-                                     drag_space == i);
+                                     pager->priv->dnd_workspace_number == i);
 	}
  
       ++i;
     }
 
-  /* Draw the drag window */  
-  if (drag_space >= 0)
-    {
-      GdkRectangle rect;
-      GdkRectangle winrect;
-      int dx, dy;
-      WnckWorkspace *active_space;
-      gboolean is_current;
-  
-      active_space = wnck_screen_get_active_workspace (pager->priv->screen);
-
-      is_current = active_space &&
-        drag_space == wnck_workspace_get_number (active_space);
-      
-      get_workspace_rect (pager, drag_space, &rect);          
-      get_window_rect (pager->priv->drag_window, &rect, &winrect);
-      
-      dx = (pager->priv->drag_window_x - rect.x) -
-        pager->priv->drag_start_x_workspace_relative;
-      dy = (pager->priv->drag_window_y - rect.y) -
-        pager->priv->drag_start_y_workspace_relative;
-      
-      winrect.x += dx;
-      winrect.y += dy;
-      
-      draw_window (widget->window,
-                   widget,
-                   pager->priv->drag_window,
-                   &winrect,
-                   is_current);
-    }
-
   if (pager->priv->action_window)
     pager->priv->action_window = NULL;
   
@@ -1130,13 +1098,7 @@ wnck_pager_button_press (GtkWidget      
 	      if (event->button == 1)
 		{
 		  /* wnck_window_activate (win); */
-		  pager->priv->drag_window = win;
-		  pager->priv->drag_start_x = event->x;
-		  pager->priv->drag_start_y = event->y;
-		  pager->priv->drag_start_x_workspace_relative =
-		    event->x - workspace_rect.x;
-		  pager->priv->drag_start_y_workspace_relative =
-		    event->y - workspace_rect.y;
+		  pager->priv->dnd_window = win;
 		}
 	      
 	      break;
@@ -1169,6 +1131,37 @@ wnck_pager_drag_motion_timeout (gpointer
   return FALSE;
 }
 
+static void
+wnck_pager_drag_begin  (GtkWidget          *widget,
+                        GdkDragContext     *context)
+{
+  WnckPager *pager;
+  GdkPixbuf *icon;
+
+  pager = WNCK_PAGER (widget);
+  pager->priv->in_dnd = TRUE;
+
+  gtk_widget_queue_draw (widget);
+
+  icon = wnck_window_get_icon (pager->priv->dnd_window);
+  gtk_drag_set_icon_pixbuf (context, icon, -2, -2);
+
+  return;
+}
+
+static void
+wnck_pager_drag_end  (GtkWidget          *widget,
+                        GdkDragContext     *context)
+{
+  WnckPager *pager;
+
+  gtk_widget_queue_draw (widget);
+
+  pager = WNCK_PAGER (widget);
+  pager->priv->in_dnd = FALSE;
+  return;
+}
+
 static gboolean 
 wnck_pager_drag_motion (GtkWidget          *widget,
                         GdkDragContext     *context,
@@ -1179,16 +1172,25 @@ 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);
+    }    
+ 
+  gtk_widget_queue_draw (widget);
   return (pager->priv->dnd_workspace_number != -1);
 }
  
@@ -1208,112 +1210,76 @@ wnck_pager_drag_motion_leave (GtkWidget 
       pager->priv->dnd_time = 0;
       pager->priv->dnd_activate = 0;
     }
+  gtk_drag_unhighlight (widget);
+  gtk_widget_queue_draw (widget);
 }
 
-static gboolean
-wnck_pager_motion (GtkWidget        *widget,
-                   GdkEventMotion   *event)
-{
-  WnckPager *pager;
-  int x, y;
-
-  pager = WNCK_PAGER (widget);
-
-  gdk_window_get_pointer (widget->window, &x, &y, NULL);
-
-  if (!pager->priv->dragging &&
-      pager->priv->drag_window != NULL &&
-      gtk_drag_check_threshold (widget,
-                                pager->priv->drag_start_x,
-                                pager->priv->drag_start_y,
-                                x, y))
-    pager->priv->dragging = TRUE;
-
-  if (pager->priv->dragging)
-    {
-      gtk_widget_queue_draw (widget);
-      pager->priv->drag_window_x = event->x;
-      pager->priv->drag_window_y = event->y;
-    }
-
-  return TRUE;
-}
-
-static gboolean
-wnck_pager_button_release (GtkWidget        *widget,
-                           GdkEventButton   *event)
+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;
-  WnckPager *pager;
-  int i;
-  gboolean handled = FALSE;
-  int viewport_x;
-  int viewport_y;
-  
-  pager = WNCK_PAGER (widget);
+  WnckWindow *win;
+  GList *windows;
+  GList *tmp;
 
-  if (event->button == 1 && pager->priv->dragging)
+  if ((selection_data->length == sizeof (gulong)) && (selection_data->format == 8))
     {
-      i = workspace_at_point (pager, event->x, event->y, NULL, NULL);
-
-      if (i >= 0)
+      if (pager->priv->dnd_workspace_number >= 0)
 	{
-	  space = wnck_screen_get_workspace (pager->priv->screen, i);
-
+	  space = wnck_screen_get_workspace (pager->priv->screen, pager->priv->dnd_workspace_number);
 	  if (space)
             {
-              if (wnck_window_get_workspace (pager->priv->drag_window) != space)
-                pager->priv->action_window = pager->priv->drag_window;
-
-              wnck_window_move_to_workspace (pager->priv->drag_window,
-                                             space);
-              if (space == wnck_screen_get_active_workspace (pager->priv->screen))
-                wnck_window_activate (pager->priv->drag_window, event->time);
-            }
-	}
-      
-      wnck_pager_clear_drag (pager);
-      handled = TRUE;
-    }
-  else if (event->button == 1)
-    {
-      i = workspace_at_point (pager, event->x, event->y, &viewport_x, &viewport_y);
-
-      if (i >= 0 && (space = wnck_screen_get_workspace (pager->priv->screen, i)))
-	  {
-	    int screen_width, screen_height;
-
-	    /* Don't switch the desktop if we're already there */
-	    if (space != wnck_screen_get_active_workspace (pager->priv->screen))
-	      wnck_workspace_activate (space, event->time);
-
-	    /* EWMH only lets us move the viewport for the active workspace,
-	     * but we just go ahead and hackily assume that the activate
-	     * just above takes effect prior to moving the viewport
-	     */
-
-	    /* Transform the pointer location to viewport origin, assuming
-	     * that we want the nearest "regular" viewport containing the
-	     * pointer.
-	     */
-	    screen_width  = wnck_screen_get_width  (pager->priv->screen);
-	    screen_height = wnck_screen_get_height (pager->priv->screen);
-	    viewport_x = (viewport_x / screen_width)  * screen_width;
-	    viewport_y = (viewport_y / screen_height) * screen_height;
-              
-	    if (wnck_workspace_get_viewport_x (space) != viewport_x ||
-		wnck_workspace_get_viewport_y (space) != viewport_y)
-	      wnck_screen_move_viewport (pager->priv->screen, viewport_x, viewport_y);
-	  }
-      
-      if (pager->priv->drag_window)
-        wnck_pager_clear_drag (pager);
-
-      handled = TRUE;
+              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 void 
+wnck_pager_drag_data_get (GtkWidget        *widget,
+                          GdkDragContext   *context,
+                          GtkSelectionData *selection_data,
+                          guint             info,
+                          guint             time)
+{
+  WnckPager *pager = WNCK_PAGER (widget);
+  gulong xid;    
+
+  if (pager->priv->dnd_window != NULL) 
+    {
+      xid = wnck_window_get_xid (pager->priv->dnd_window);
+      gtk_selection_data_set (selection_data,
+   		              selection_data->target,
+			      8, (guchar *)&xid, sizeof (gulong));
     }
-
-  return FALSE;
-}
+}			  
 
 static gboolean
 wnck_pager_focus (GtkWidget        *widget,
@@ -1496,9 +1462,6 @@ window_closed_callback            (WnckS
 {
   WnckPager *pager = WNCK_PAGER (data);
 
-  if (pager->priv->drag_window == window)
-    wnck_pager_clear_drag (pager);
-  
   gtk_widget_queue_draw (GTK_WIDGET (pager));
 }
 
@@ -1749,20 +1712,6 @@ wnck_pager_disconnect_screen (WnckPager 
     }
 
   pager->priv->screen = NULL;
-}
-
-static void
-wnck_pager_clear_drag (WnckPager *pager)
-{
-  if (pager->priv->dragging)
-    gtk_widget_queue_draw (GTK_WIDGET (pager));
-
-  pager->priv->dragging = FALSE;
-  pager->priv->drag_window = NULL;
-  pager->priv->drag_start_x = -1;
-  pager->priv->drag_start_y = -1;
-  pager->priv->drag_window_x = -1;
-  pager->priv->drag_window_y = -1;
 }
 
 static GdkPixbuf*
Index: tasklist.c
===================================================================
RCS file: /cvs/gnome/libwnck/libwnck/tasklist.c,v
retrieving revision 1.99
diff -u -p -r1.99 tasklist.c
--- tasklist.c	28 Mar 2006 21:49:20 -0000	1.99
+++ tasklist.c	31 Mar 2006 19:52:50 -0000
@@ -2944,6 +2944,33 @@ wnck_task_drag_motion (GtkWidget        
   return TRUE;
 }
 
+void  
+wnck_task_drag_begin (GtkWidget          *widget,
+		      GdkDragContext     *context,
+		      WnckTask           *task)
+{
+  GdkPixbuf *icon;
+
+  icon = wnck_window_get_icon (task->window);
+  gtk_drag_set_icon_pixbuf (context, icon, -2, -2);
+}
+
+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 +3048,9 @@ wnck_task_create_widgets (WnckTask *task
   GdkPixbuf *pixbuf;
   char *text;
   static GQuark disable_sound_quark = 0;
+  static const GtkTargetEntry targets[] = {
+    { "application/x-wm-window-id", 0, 0}
+  };
   
   if (!disable_sound_quark)
     disable_sound_quark = g_quark_from_static_string ("gnome_disable_sound_events");
@@ -3043,6 +3073,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);
@@ -3105,6 +3143,18 @@ wnck_task_create_widgets (WnckTask *task
                            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); 
+
+      g_signal_connect_object (G_OBJECT(task->button), "drag_begin",
+                               G_CALLBACK (wnck_task_drag_begin),
+                               G_OBJECT (task),
+                               0); 
+  }
+  
   switch (task->type)
     {
     case WNCK_TASK_CLASS_GROUP:
