diff -X /usr/src/metacity/.diffignore -rudp metacity-svn-shakeloose-07/src/core/core.c metacity-svn-shakeloose-07-unimaxmouse-07/src/core/core.c
--- metacity-svn-shakeloose-07/src/core/core.c	2008-01-28 19:01:40.000000000 +0100
+++ metacity-svn-shakeloose-07-unimaxmouse-07/src/core/core.c	2008-01-28 19:22:12.000000000 +0100
@@ -317,15 +317,24 @@ meta_core_minimize (Display *xdisplay,
 
 void
 meta_core_maximize (Display *xdisplay,
-                    Window   frame_xwindow)
+                    Window   frame_xwindow,
+                    gint     button)
 {
+  MetaMaximizeFlags direction;
+
   MetaWindow *window = get_window (xdisplay, frame_xwindow);
 
   if (meta_prefs_get_raise_on_click ())
     meta_window_raise (window);
 
-  meta_window_maximize (window, 
-                        META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL);
+  if (button == 2)
+    direction = META_MAXIMIZE_VERTICAL;
+  else if (button == 3)
+    direction = META_MAXIMIZE_HORIZONTAL;
+  else
+    direction = META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL;
+
+  meta_window_maximize (window, direction);
 }
 
 void
@@ -347,15 +356,24 @@ meta_core_toggle_maximize (Display *xdis
 
 void
 meta_core_unmaximize (Display *xdisplay,
-                      Window   frame_xwindow)
+                      Window   frame_xwindow,
+                      gint     button)
 {
+  MetaMaximizeFlags direction;
+
   MetaWindow *window = get_window (xdisplay, frame_xwindow);
 
   if (meta_prefs_get_raise_on_click ())
     meta_window_raise (window);
 
-  meta_window_unmaximize (window,
-                          META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL);
+  if (button == 2)
+    direction = META_MAXIMIZE_VERTICAL;
+  else if (button == 3)
+    direction = META_MAXIMIZE_HORIZONTAL;
+  else
+    direction = META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL;
+
+  meta_window_unmaximize (window, direction);
 }
 
 void
diff -X /usr/src/metacity/.diffignore -rudp metacity-svn-shakeloose-07/src/core/frame.c metacity-svn-shakeloose-07-unimaxmouse-07/src/core/frame.c
--- metacity-svn-shakeloose-07/src/core/frame.c	2008-01-28 19:01:40.000000000 +0100
+++ metacity-svn-shakeloose-07-unimaxmouse-07/src/core/frame.c	2008-01-28 19:22:36.000000000 +0100
@@ -275,11 +275,16 @@ meta_frame_get_flags (MetaFrame *frame)
   if (frame->window->on_all_workspaces)
     flags |= META_FRAME_STUCK;
 
-  /* FIXME: Should we have some kind of UI for windows that are just vertically
-   * maximized or just horizontally maximized?
+  /* Use the maximized icon in the maximize button, even for
+   * unidirectionally maximized windows. Setting either flag
+   * also causes a subsequential left-click on the maximize
+   * button to unmaximize again (and not fully maximize).
+   * That is a feature - not a bug.
    */
-  if (META_WINDOW_MAXIMIZED (frame->window))
-    flags |= META_FRAME_MAXIMIZED;
+  if (frame->window->maximized_horizontally)
+    flags |= META_FRAME_MAXIMIZED_HORIZONTALLY;
+  if (frame->window->maximized_vertically)
+    flags |= META_FRAME_MAXIMIZED_VERTICALLY;
 
   if (frame->window->fullscreen)
     flags |= META_FRAME_FULLSCREEN;
diff -X /usr/src/metacity/.diffignore -rudp metacity-svn-shakeloose-07/src/include/common.h metacity-svn-shakeloose-07-unimaxmouse-07/src/include/common.h
--- metacity-svn-shakeloose-07/src/include/common.h	2008-01-28 19:01:39.000000000 +0100
+++ metacity-svn-shakeloose-07-unimaxmouse-07/src/include/common.h	2008-01-28 19:22:00.000000000 +0100
@@ -42,12 +42,13 @@ typedef enum
   META_FRAME_HAS_FOCUS                = 1 << 6,
   META_FRAME_SHADED                   = 1 << 7,
   META_FRAME_STUCK                    = 1 << 8,
-  META_FRAME_MAXIMIZED                = 1 << 9,
-  META_FRAME_ALLOWS_SHADE             = 1 << 10,
-  META_FRAME_ALLOWS_MOVE              = 1 << 11,
-  META_FRAME_FULLSCREEN               = 1 << 12,
-  META_FRAME_IS_FLASHING              = 1 << 13,
-  META_FRAME_ABOVE                    = 1 << 14
+  META_FRAME_MAXIMIZED_VERTICALLY     = 1 << 9,
+  META_FRAME_MAXIMIZED_HORIZONTALLY   = 1 << 10,
+  META_FRAME_ALLOWS_SHADE             = 1 << 11,
+  META_FRAME_ALLOWS_MOVE              = 1 << 12,
+  META_FRAME_FULLSCREEN               = 1 << 13,
+  META_FRAME_IS_FLASHING              = 1 << 14,
+  META_FRAME_ABOVE                    = 1 << 15
 } MetaFrameFlags;
 
 typedef enum
diff -X /usr/src/metacity/.diffignore -rudp metacity-svn-shakeloose-07/src/include/core.h metacity-svn-shakeloose-07-unimaxmouse-07/src/include/core.h
--- metacity-svn-shakeloose-07/src/include/core.h	2008-01-28 19:01:39.000000000 +0100
+++ metacity-svn-shakeloose-07-unimaxmouse-07/src/include/core.h	2008-01-28 19:22:24.000000000 +0100
@@ -121,9 +121,11 @@ void meta_core_minimize         (Display
 void meta_core_toggle_maximize  (Display *xdisplay,
                                  Window   frame_xwindow);
 void meta_core_unmaximize       (Display *xdisplay,
-                                 Window   frame_xwindow);
+                                 Window   frame_xwindow,
+                                 gint     button);
 void meta_core_maximize         (Display *xdisplay,
-                                 Window   frame_xwindow);
+                                 Window   frame_xwindow,
+                                 gint     button);
 void meta_core_delete           (Display *xdisplay,
                                  Window   frame_xwindow,
                                  guint32  timestamp);
diff -X /usr/src/metacity/.diffignore -rudp metacity-svn-shakeloose-07/src/ui/frames.c metacity-svn-shakeloose-07-unimaxmouse-07/src/ui/frames.c
--- metacity-svn-shakeloose-07/src/ui/frames.c	2008-01-28 19:26:14.000000000 +0100
+++ metacity-svn-shakeloose-07-unimaxmouse-07/src/ui/frames.c	2008-01-28 19:25:45.000000000 +0100
@@ -1369,18 +1369,19 @@ meta_frames_button_press_event (GtkWidge
       META_GRAB_OP_NONE)
     return FALSE; /* already up to something */  
 
-  if (event->button == 1 &&
-      (control == META_FRAME_CONTROL_MAXIMIZE ||
-       control == META_FRAME_CONTROL_UNMAXIMIZE ||
-       control == META_FRAME_CONTROL_MINIMIZE ||
-       control == META_FRAME_CONTROL_DELETE ||
-       control == META_FRAME_CONTROL_SHADE ||
-       control == META_FRAME_CONTROL_UNSHADE ||
-       control == META_FRAME_CONTROL_ABOVE ||
-       control == META_FRAME_CONTROL_UNABOVE ||
-       control == META_FRAME_CONTROL_STICK ||
-       control == META_FRAME_CONTROL_UNSTICK ||
-       control == META_FRAME_CONTROL_MENU))
+  if ((event->button == 1 &&
+       (control == META_FRAME_CONTROL_MINIMIZE ||
+        control == META_FRAME_CONTROL_DELETE ||
+        control == META_FRAME_CONTROL_SHADE ||
+        control == META_FRAME_CONTROL_UNSHADE ||
+        control == META_FRAME_CONTROL_ABOVE ||
+        control == META_FRAME_CONTROL_UNABOVE ||
+        control == META_FRAME_CONTROL_STICK ||
+        control == META_FRAME_CONTROL_UNSTICK ||
+        control == META_FRAME_CONTROL_MENU)) ||
+      (event->button >= 1 && event->button <= 3 &&
+       (control == META_FRAME_CONTROL_MAXIMIZE ||
+        control == META_FRAME_CONTROL_UNMAXIMIZE)))
     {
       MetaGrabOp op = META_GRAB_OP_NONE;
 
@@ -1642,14 +1643,14 @@ meta_frames_button_release_event    (Gtk
             meta_core_user_focus (gdk_display,
                             frame->xwindow,
                             event->time);      
-            meta_core_maximize (gdk_display, frame->xwindow);
+            meta_core_maximize (gdk_display, frame->xwindow, event->button);
           }
           meta_core_end_grab_op (gdk_display, event->time);
           break;
 
         case META_GRAB_OP_CLICKING_UNMAXIMIZE:
           if (control == META_FRAME_CONTROL_UNMAXIMIZE)
-            meta_core_unmaximize (gdk_display, frame->xwindow);
+            meta_core_unmaximize (gdk_display, frame->xwindow, event->button);
           
           meta_core_end_grab_op (gdk_display, event->time);
           break;
@@ -2501,7 +2502,7 @@ meta_frames_set_window_background (MetaF
       gtk_style_set_background (GTK_WIDGET (frames)->style,
                                 frame->window, GTK_STATE_NORMAL);
     }
- }
+}
 
 static gboolean
 meta_frames_enter_notify_event      (GtkWidget           *widget,
@@ -2659,7 +2660,10 @@ get_control (MetaFrames *frames,
 
   if (POINT_IN_RECT (x, y, fgeom.max_rect.clickable))
     {
-      if (flags & META_FRAME_MAXIMIZED)
+      /* Unmaximize if the window is maximized, even if only
+       * unidirectionally maximized.
+       */
+      if (flags & (META_FRAME_MAXIMIZED_VERTICALLY|META_FRAME_MAXIMIZED_HORIZONTALLY))
         return META_FRAME_CONTROL_UNMAXIMIZE;
       else
         return META_FRAME_CONTROL_MAXIMIZE;
diff -X /usr/src/metacity/.diffignore -rudp metacity-svn-shakeloose-07/src/ui/theme.c metacity-svn-shakeloose-07-unimaxmouse-07/src/ui/theme.c
--- metacity-svn-shakeloose-07/src/ui/theme.c	2008-01-28 19:01:40.000000000 +0100
+++ metacity-svn-shakeloose-07-unimaxmouse-07/src/ui/theme.c	2008-01-28 19:23:01.000000000 +0100
@@ -805,19 +805,17 @@ meta_frame_layout_calc_geometry (const M
       rect->visible.width = button_width;
       rect->visible.height = button_height;
 
-      if (flags & META_FRAME_MAXIMIZED)
+      g_memmove (&(rect->clickable), &(rect->visible), sizeof(rect->clickable));
+      if (flags & META_FRAME_MAXIMIZED_VERTICALLY)
         {
-          rect->clickable.x = rect->visible.x;
           rect->clickable.y = 0;
-          rect->clickable.width = rect->visible.width;
           rect->clickable.height = button_height + button_y;
-
+        }
+      if (flags & META_FRAME_MAXIMIZED_HORIZONTALLY)
+        {
           if (i == n_right - 1)
             rect->clickable.width += layout->right_titlebar_edge + layout->right_width + layout->button_border.right;
-
         }
-      else
-        g_memmove (&(rect->clickable), &(rect->visible), sizeof(rect->clickable));
 
       *(right_bg_rects[i]) = rect->visible;
       
@@ -844,7 +842,8 @@ meta_frame_layout_calc_geometry (const M
       rect->visible.width = button_width;
       rect->visible.height = button_height;
 
-      if (flags & META_FRAME_MAXIMIZED)
+      g_memmove (&(rect->clickable), &(rect->visible), sizeof(rect->clickable));
+      if (flags & META_FRAME_MAXIMIZED_HORIZONTALLY)
         {
           if (i==0)
             {
@@ -856,13 +855,12 @@ meta_frame_layout_calc_geometry (const M
               rect->clickable.x = rect->visible.x;
               rect->clickable.width = button_width;
             }
-
-            rect->clickable.y = 0;
-            rect->clickable.height = button_height + button_y;
-          }
-        else
-          g_memmove (&(rect->clickable), &(rect->visible), sizeof(rect->clickable));
-
+        }
+      if (flags & META_FRAME_MAXIMIZED_VERTICALLY)
+        {
+          rect->clickable.y = 0;
+          rect->clickable.height = button_height + button_y;
+        }
 
       x = rect->visible.x + rect->visible.width + layout->button_border.right;
 
@@ -4920,18 +4918,26 @@ theme_get_style (MetaTheme     *theme,
   if (style_set == NULL)
     return NULL;
   
-  switch (flags & (META_FRAME_MAXIMIZED | META_FRAME_SHADED))
+  switch (flags & (META_FRAME_MAXIMIZED_HORIZONTALLY |
+                   META_FRAME_MAXIMIZED_VERTICALLY | META_FRAME_SHADED))
     {
     case 0:
+    case META_FRAME_MAXIMIZED_HORIZONTALLY:
+    case META_FRAME_MAXIMIZED_VERTICALLY:
       state = META_FRAME_STATE_NORMAL;
       break;
-    case META_FRAME_MAXIMIZED:
+    case (META_FRAME_MAXIMIZED_HORIZONTALLY |
+         META_FRAME_MAXIMIZED_VERTICALLY):
       state = META_FRAME_STATE_MAXIMIZED;
       break;
     case META_FRAME_SHADED:
+    case (META_FRAME_MAXIMIZED_HORIZONTALLY | META_FRAME_SHADED):
+    case (META_FRAME_MAXIMIZED_VERTICALLY | META_FRAME_SHADED):
       state = META_FRAME_STATE_SHADED;
       break;
-    case (META_FRAME_MAXIMIZED | META_FRAME_SHADED):
+    case (META_FRAME_MAXIMIZED_HORIZONTALLY |
+          META_FRAME_MAXIMIZED_VERTICALLY |
+          META_FRAME_SHADED):
       state = META_FRAME_STATE_MAXIMIZED_AND_SHADED;
       break;
     default:
