Index: tasklist.c
===================================================================
RCS file: /cvs/gnome/libwnck/libwnck/tasklist.c,v
retrieving revision 1.87
diff -u -p -r1.87 tasklist.c
--- tasklist.c	3 Oct 2005 19:42:46 -0000	1.87
+++ tasklist.c	16 Oct 2005 19:27:27 -0000
@@ -2835,6 +2835,7 @@ wnck_task_drag_leave (GtkWidget         
       g_source_remove (task->button_activate);
       task->button_activate = 0;
     }
+  gtk_drag_unhighlight (widget);
 }
 
 static gboolean
@@ -2845,16 +2846,104 @@ wnck_task_drag_motion (GtkWidget        
 		       guint               time,
 		       WnckTask            *task)
 {
-  task->dnd_timestamp = time;
-  if (task->button_activate == 0 && task->type == WNCK_TASK_WINDOW)
-      task->button_activate = g_timeout_add (WNCK_ACTIVATE_TIMEOUT,
-                                             wnck_task_motion_timeout,
-                                             task);
-  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
+    {
+      task->dnd_timestamp = time;
+
+      if (task->button_activate == 0 && task->type == WNCK_TASK_WINDOW)
+          task->button_activate = g_timeout_add (WNCK_ACTIVATE_TIMEOUT,
+                                                 wnck_task_motion_timeout,
+                                                 task);
+      gdk_drag_status (context, 0, time);
+    }
+    
   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));
+}
+
+void  
+wnck_task_drag_data_received (GtkWidget          *widget,
+			    GdkDragContext     *context,
+			    gint                x,
+			    gint                y,
+			    GtkSelectionData   *data,
+			    guint               info,
+			    guint               time,
+			    WnckTask           *target_task)
+{
+    WnckTasklist *tasklist = target_task->tasklist;
+
+    if ((data->length == sizeof (gulong)) && (data->format == 8))
+     {
+       GList *l, *windows;
+       WnckWindow *window;
+       gulong *xid = (gulong *)data->data;
+       guint new_order, old_order, order;
+       WnckWindow *found_window = NULL;
+	
+       windows = wnck_screen_get_windows (tasklist->priv->screen);
+       for (l = windows; l; l = l->next)
+         {
+	    window = WNCK_WINDOW (l->data);
+	    if (wnck_window_get_xid (window) == *xid) 
+             {
+	        old_order = wnck_window_get_sort_order (window);
+                new_order = wnck_window_get_sort_order (target_task->window); 
+		if (old_order < new_order) 
+			new_order++;
+		found_window = window;
+		break;
+	     }
+         }
+
+       if (found_window) 
+         {	
+           for (l = windows; l; l = l->next)
+             {
+ 	        window = WNCK_WINDOW (l->data);
+	        order = wnck_window_get_sort_order (window);
+	        if (order >= new_order)
+		  wnck_window_set_sort_order (window, order + 1);
+	     } 
+           wnck_window_set_sort_order (found_window, new_order);
+	   
+	   if (!tasklist->priv->include_all_workspaces)
+	     {
+	        WnckWorkspace *active_space;
+	        active_space = wnck_screen_get_active_workspace (tasklist->priv->screen);
+                wnck_window_move_to_workspace (found_window, active_space);
+	     }
+
+	   gtk_widget_queue_resize (GTK_WIDGET (tasklist));
+	 }
+
+       gtk_drag_finish (context, TRUE, FALSE, time); 
+       return;
+     }   
+  gtk_drag_finish (context, FALSE, FALSE, time);
+}
+
 static gboolean
 wnck_task_button_press_event (GtkWidget	      *widget,
 			      GdkEventButton  *event,
@@ -2932,6 +3021,10 @@ 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");
@@ -2951,9 +3044,18 @@ wnck_task_create_widgets (WnckTask *task
   
   gtk_widget_set_name (task->button,
 		       "tasklist-button");
-
-  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);
+      gtk_drag_dest_set (GTK_WIDGET(task->button), GTK_DEST_DEFAULT_DROP, targets, 1, GDK_ACTION_MOVE);
+    }
+  else  
+      gtk_drag_dest_set (GTK_WIDGET(task->button), 0, NULL, 0, GDK_ACTION_DEFAULT);
+ 
   hbox = gtk_hbox_new (FALSE, 0);
 
   pixbuf = wnck_task_get_icon (task);
@@ -3010,6 +3112,20 @@ wnck_task_create_widgets (WnckTask *task
                            G_CALLBACK (wnck_task_drag_motion),
                            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_data_received",
+                               G_CALLBACK (wnck_task_drag_data_received),
+                               G_OBJECT (task),
+                               0); 
+
+    }
 
   g_signal_connect_object (G_OBJECT(task->button), "drag_leave",
                            G_CALLBACK (wnck_task_drag_leave),
Index: window.c
===================================================================
RCS file: /cvs/gnome/libwnck/libwnck/window.c,v
retrieving revision 1.61
diff -u -p -r1.61 window.c
--- window.c	19 Sep 2005 16:22:53 -0000	1.61
+++ window.c	16 Oct 2005 19:27:27 -0000
@@ -579,7 +579,7 @@ wnck_window_get_pid (WnckWindow *window)
  * @window: a #WnckWindow
  *
  * Gets the sort order of @window; used for ordering of the window in
- * the tasklist.  This is defined when the window is created.
+ * the tasklist. 
  *
  * Return value: sort order of @window, or G_MAXINT if none available
  **/
@@ -589,6 +589,24 @@ wnck_window_get_sort_order (WnckWindow *
   g_return_val_if_fail (WNCK_IS_WINDOW (window), G_MAXINT);
 
   return window->priv->sort_order;
+}
+
+/**
+ * wnck_window_set_sort_order:
+ * @window: a #WnckWindow
+ * @order: new order
+ *
+ * Sets the sort order of @window; used for ordering of the window in
+ * the tasklist. 
+ *
+ **/
+void        wnck_window_set_sort_order        (WnckWindow *window, 
+					       gint order)
+{ 
+  g_return_if_fail (WNCK_IS_WINDOW (window));
+  
+  window->priv->sort_order = order;
+  return;
 }
 
 /**
Index: window.h
===================================================================
RCS file: /cvs/gnome/libwnck/libwnck/window.h,v
retrieving revision 1.35
diff -u -p -r1.35 window.h
--- window.h	19 Jul 2005 10:18:04 -0000	1.35
+++ window.h	16 Oct 2005 19:27:27 -0000
@@ -147,6 +147,8 @@ const char* wnck_window_get_session_id  
 const char* wnck_window_get_session_id_utf8   (WnckWindow *window);
 int         wnck_window_get_pid               (WnckWindow *window);
 gint        wnck_window_get_sort_order        (WnckWindow *window);
+void        wnck_window_set_sort_order        (WnckWindow *window, 
+					       gint order);
 
 WnckWindowType wnck_window_get_window_type    (WnckWindow *window);
 void           wnck_window_set_window_type    (WnckWindow *window,
