diff -u orig/libwnck-2.27.5/libwnck/tasklist.c libwnck-2.27.5/libwnck/tasklist.c
--- orig/libwnck-2.27.5/libwnck/tasklist.c	2009-04-19 19:40:32.000000000 +0200
+++ libwnck-2.27.5/libwnck/tasklist.c	2009-08-09 01:28:41.000000000 +0200
@@ -109,7 +109,8 @@
 {
   WNCK_TASK_CLASS_GROUP,
   WNCK_TASK_WINDOW,
-  WNCK_TASK_STARTUP_SEQUENCE
+  WNCK_TASK_STARTUP_SEQUENCE,
+  WNCK_TASK_MULTISELECT
 } WnckTaskType;
 
 struct _WnckTask
@@ -191,6 +192,9 @@
   GList *windows;
   GList *windows_without_class_group;
 
+  GList *selects;
+  WnckTask *selects_task;
+
   /* Not handled by update_lists */
   GList *startup_sequences;
   
@@ -252,6 +256,8 @@
 						 WnckWindow      *window);
 static WnckTask *wnck_task_new_from_class_group (WnckTasklist    *tasklist,
 						 WnckClassGroup  *class_group);
+static WnckTask *wnck_task_new_multiselect      (WnckTasklist    *tasklist,
+                                                 WnckClassGroup  *class_group);
 #ifdef HAVE_STARTUP_NOTIFICATION
 static WnckTask *wnck_task_new_from_startup_sequence (WnckTasklist      *tasklist,
                                                       SnStartupSequence *sequence);
@@ -310,6 +316,7 @@
 static gboolean wnck_tasklist_scroll_cb     (WnckTasklist   *tasklist,
                                              GdkEventScroll *event,
                                              gpointer        user_data);
+static void     wnck_tasklist_free_selected_windows (WnckTasklist *tasklist);
 static void     wnck_tasklist_free_tasks    (WnckTasklist   *tasklist);
 static void     wnck_tasklist_update_lists  (WnckTasklist   *tasklist);
 static int      wnck_tasklist_layout        (GtkAllocation  *allocation,
@@ -684,6 +691,9 @@
   tasklist->priv->windows = NULL;
   tasklist->priv->windows_without_class_group = NULL;
 
+  tasklist->priv->selects = NULL;
+  tasklist->priv->selects_task = NULL;
+
   tasklist->priv->startup_sequences = NULL;
 
   tasklist->priv->skipped_windows = NULL;
@@ -877,6 +887,8 @@
       tasklist->priv->skipped_windows = NULL;
     }
 
+  wnck_tasklist_free_selected_windows (tasklist);
+
   g_hash_table_destroy (tasklist->priv->class_group_hash);
   tasklist->priv->class_group_hash = NULL;
 
@@ -2248,6 +2260,35 @@
 }
 
 static void
+wnck_tasklist_unselect_windows (WnckTasklist *tasklist) 
+{
+  GList *tmp;
+  tmp = tasklist->priv->selects;
+  while (tmp != NULL)
+    {
+      WnckTask *task = WNCK_TASK (tmp->data);
+      tmp = tmp->next;
+      task->really_toggling = TRUE;
+      if (GTK_IS_TOGGLE_BUTTON (task->button))
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (task->button),
+                                      FALSE);
+      task->really_toggling = FALSE;
+    }
+  tasklist->priv->selects = NULL;
+}
+
+static void
+wnck_tasklist_free_selected_windows (WnckTasklist *tasklist)
+{
+  tasklist->priv->selects_task = NULL;
+
+  if (tasklist->priv->selects)
+    g_list_free (tasklist->priv->selects);
+  
+  tasklist->priv->selects = NULL;
+}
+
+static void
 wnck_tasklist_update_lists (WnckTasklist *tasklist)
 {
   GList *windows;
@@ -2257,6 +2298,7 @@
   WnckTask *win_task;
   WnckTask *class_group_task;
 
+  wnck_tasklist_free_selected_windows (tasklist);
   wnck_tasklist_free_tasks (tasklist);
 
   /* wnck_tasklist_update_lists() will be called on realize */
@@ -2494,6 +2536,8 @@
         break;
     }
 
+  wnck_tasklist_unselect_windows (tasklist);  
+  wnck_tasklist_free_selected_windows (tasklist);
   wnck_tasklist_change_active_task (tasklist, active_task);
 }
 
@@ -2918,9 +2962,10 @@
   GtkWidget *image;
   GList *l, *list;
   
-  g_return_if_fail (task->type == WNCK_TASK_CLASS_GROUP);
+  g_return_if_fail (task->type == WNCK_TASK_CLASS_GROUP || 
+                    task->type == WNCK_TASK_MULTISELECT);
 
-  if (task->class_group == NULL)
+  if (task->class_group == NULL && task->type == WNCK_TASK_CLASS_GROUP)
     return;
   
   if (task->menu == NULL)
@@ -3109,6 +3154,8 @@
       break;
     case WNCK_TASK_STARTUP_SEQUENCE:
       break;
+    case WNCK_TASK_MULTISELECT:
+      break;
     }
 }
 
@@ -3136,6 +3183,8 @@
                                                 icon_text, include_state);
       break;
 
+    case WNCK_TASK_MULTISELECT:
+      break;
     case WNCK_TASK_STARTUP_SEQUENCE:
 #ifdef HAVE_STARTUP_NOTIFICATION
       name = sn_startup_sequence_get_description (task->startup_sequence);
@@ -3261,6 +3310,8 @@
       pixbuf =  wnck_task_scale_icon (wnck_window_get_mini_icon (task->window),
 				      state & WNCK_WINDOW_STATE_MINIMIZED);
       break;
+    case WNCK_TASK_MULTISELECT:
+      break;
     case WNCK_TASK_STARTUP_SEQUENCE:
 #ifdef HAVE_STARTUP_NOTIFICATION
       if (task->tasklist->priv->icon_loader != NULL)
@@ -3332,6 +3383,8 @@
       task->start_needs_attention = _wnck_window_or_transient_get_needs_attention_time (task->window);
       break;
 
+    case WNCK_TASK_MULTISELECT:
+      break;
     case WNCK_TASK_STARTUP_SEQUENCE:
       break;
     }
@@ -3661,12 +3714,127 @@
     gtk_drag_finish (context, TRUE, FALSE, time);
 }
 
+static GList *
+wnck_task_add_task_windows (GList    *list,
+                            WnckTask *task)
+{
+  GList *tmp;
+
+  if (task->type == WNCK_TASK_WINDOW &&
+      task->window &&
+      g_list_index (list, task) == -1)
+        list = g_list_prepend (list, task);
+    
+  if (task->type == WNCK_TASK_CLASS_GROUP && task->windows)
+    {
+      tmp = task->windows;
+      while (tmp != NULL)
+        {
+          WnckTask *wt = WNCK_TASK (tmp->data);          
+          tmp = tmp->next;
+          list = wnck_task_add_task_windows (list, wt);
+        }
+    }
+  return list;
+}
+
+static GList *
+wnck_task_get_selected_tasks (WnckTasklist *tasklist)
+{
+  GList *tasks;
+  GList *tmp;
+
+  tasks = NULL;
+
+  tmp = tasklist->priv->selects;
+  while (tmp != NULL)
+    {
+      WnckTask *wt = WNCK_TASK (tmp->data);          
+      tmp = tmp->next;
+      tasks = wnck_task_add_task_windows (tasks, wt);
+    }
+
+  if (tasklist->priv->active_task)
+    tasks = wnck_task_add_task_windows (tasks, tasklist->priv->active_task);
+
+  return tasks;
+}
+
+static void
+wnck_task_toggle_selected (WnckTasklist *tasklist,
+                           WnckTask     *task,
+                           gboolean     remove)
+{
+  if (tasklist->priv->active_task == task)
+    return;
+
+  if (task->type == WNCK_TASK_STARTUP_SEQUENCE)
+    return;
+
+  if (!task->tasklist->priv->selects_task) 
+      task->tasklist->priv->selects_task = wnck_task_new_multiselect (
+                  task->tasklist, task->class_group);
+
+  if (g_list_index (task->tasklist->priv->selects, task) == -1)
+    {
+      task->really_toggling = TRUE;
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (task->button),
+                                    TRUE);
+      task->really_toggling = FALSE;
+
+      task->tasklist->priv->selects = g_list_append (
+                  task->tasklist->priv->selects, task);
+    }
+  else if (remove)
+    {
+      task->really_toggling = TRUE;
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (task->button),
+                                    FALSE);
+      task->really_toggling = FALSE;
+
+      task->tasklist->priv->selects = g_list_remove (
+                  task->tasklist->priv->selects, task);
+    }
+}
+
 static gboolean
 wnck_task_button_press_event (GtkWidget	      *widget,
 			      GdkEventButton  *event,
 			      gpointer         data)
 {
   WnckTask *task = WNCK_TASK (data);
+  WnckTasklist *tasklist;  
+  GList *selected_windows;
+  int size;
+  
+  tasklist = task->tasklist;
+
+  /* Handles task multiselection */
+  if (event->button == 3 && task->type != WNCK_TASK_STARTUP_SEQUENCE)
+    {
+      if (event->state & GDK_CONTROL_MASK)
+        wnck_task_toggle_selected (tasklist, task, FALSE);
+
+      selected_windows = wnck_task_get_selected_tasks (tasklist);
+
+      size = g_list_length (selected_windows);
+
+      /* Only show the menu if we're clicking a selected window or if 
+       * we're holding down the control key on another task */
+      if (size > 1 && 
+          (event->state & GDK_CONTROL_MASK || 
+          gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (task->button))))
+        {
+          tasklist->priv->selects_task->windows = selected_windows;
+          tasklist->priv->selects_task->button = task->button;
+
+          wnck_task_popup_menu (tasklist->priv->selects_task,
+                                TRUE);
+          return TRUE;
+        }
+      else
+        wnck_tasklist_unselect_windows (tasklist);
+    }
 
   switch (task->type)
     {
@@ -3674,13 +3842,26 @@
       if (event->button == 2)
         wnck_tasklist_activate_next_in_class_group (task, event->time);
       else
-        wnck_task_popup_menu (task,
-                              event->button == 3);
+        {
+          if (event->state & GDK_CONTROL_MASK)
+            {
+              wnck_task_toggle_selected (tasklist, task, TRUE);
+              return TRUE;
+            }
+
+          wnck_task_popup_menu (task,
+                                event->button == 3);
+        }
       return TRUE;
 
     case WNCK_TASK_WINDOW:
       if (event->button == 1)
         {
+          if (event->state & GDK_CONTROL_MASK)
+            {
+              wnck_task_toggle_selected (tasklist, task, TRUE);
+              return TRUE;
+            }
           /* is_most_recently_activated == is_active for click &
 	   * sloppy focus methods.  We use the former here because
 	   * 'mouse' focus provides a special case.  In that case, no
@@ -3725,6 +3906,8 @@
       break;
     case WNCK_TASK_STARTUP_SEQUENCE:
       break;
+    case WNCK_TASK_MULTISELECT:
+      break;
     }
 
   return FALSE;
@@ -4066,6 +4249,8 @@
 
     case WNCK_TASK_STARTUP_SEQUENCE:
       break;
+    case WNCK_TASK_MULTISELECT:
+      break;
     }
 
   return FALSE;
@@ -4125,6 +4310,8 @@
     case WNCK_TASK_STARTUP_SEQUENCE:
       pos1 = G_MAXINT; /* startup sequences are sorted at the end. */
       break;           /* Changing this will break scrolling.      */
+    case WNCK_TASK_MULTISELECT:
+      break;
     }
 
   switch (task2->type)
@@ -4141,6 +4328,8 @@
     case WNCK_TASK_STARTUP_SEQUENCE:
       pos2 = G_MAXINT;
       break;
+    case WNCK_TASK_MULTISELECT:
+      break;
     }
       
   if (pos1 < pos2)
@@ -4223,6 +4412,22 @@
   return task;
 }
 
+static WnckTask *
+wnck_task_new_multiselect (WnckTasklist   *tasklist,
+			   WnckClassGroup *class_group)
+{
+  WnckTask *task;
+
+  task = g_object_new (WNCK_TYPE_TASK, NULL);
+
+  task->type = WNCK_TASK_MULTISELECT;
+  task->window = NULL;
+  task->class_group = NULL;
+  task->tasklist = tasklist;
+
+  return task;
+}
+
 #ifdef HAVE_STARTUP_NOTIFICATION
 static WnckTask*
 wnck_task_new_from_startup_sequence (WnckTasklist      *tasklist,
