diff -urN metacity-2.4.1/src/display.c metacity-2.4.1-ttb/src/display.c
--- metacity-2.4.1/src/display.c	2002-09-04 00:15:46.000000000 -0400
+++ metacity-2.4.1-ttb/src/display.c	2002-09-19 22:41:04.000000000 -0400
@@ -941,6 +941,91 @@
   return FALSE;
 }
 
+/* This will return a MetaMouseButtonAction based on which mouse button
+ * is pressed and which action is associated with it.
+ */
+static MetaMouseButtonAction determine_mod_mouse_button_action(XEvent *event)
+{
+    switch (event->xbutton.button)
+    {
+        case 1:
+            return meta_prefs_get_mouse_button_one_action();
+        case 2:
+            return meta_prefs_get_mouse_button_two_action();
+        case 3:
+            return meta_prefs_get_mouse_button_three_action();
+    }
+
+    /* We should never ever get here */
+    return meta_prefs_get_mouse_button_one_action();
+}
+
+/* This function handles a modified window event
+ * if the event is "move" it sets begin_move to true and returns
+ * if the event is "resize" it calls the proper function
+ * if the event is "menu" it calls the proper function
+ */
+static void handle_modified_mouse_event(XEvent *event, 
+                                        MetaWindow *window,
+                                        MetaDisplay *display,
+                                        gboolean *begin_move)
+{
+    switch (determine_mod_mouse_button_action(event)) 
+    {
+        case META_MOUSE_BUTTON_ACTION_MOVE:
+            *begin_move = TRUE;
+            return;
+        case META_MOUSE_BUTTON_ACTION_RESIZE:
+          if (window->has_resize_func)
+            {
+              gboolean north;
+              gboolean west;
+              int root_x, root_y;
+              MetaGrabOp op;
+
+              meta_window_get_position (window, &root_x, &root_y);
+
+              west = event->xbutton.x_root < (root_x + window->rect.width / 2);
+              north = event->xbutton.y_root < (root_y + window->rect.height / 2);
+
+              if (west && north)
+                op = META_GRAB_OP_RESIZING_NW;
+              else if (west)
+                op = META_GRAB_OP_RESIZING_SW;
+              else if (north)
+                op = META_GRAB_OP_RESIZING_NE;
+              else
+                op = META_GRAB_OP_RESIZING_SE;
+              
+              meta_display_begin_grab_op (display,
+                                          window->screen,
+                                          window,
+                                          op,
+                                          TRUE,
+                                          event->xbutton.button,
+                                          0,
+                                          event->xbutton.time,
+                                          event->xbutton.x_root,
+                                          event->xbutton.y_root);
+            }
+            return;
+        case META_MOUSE_BUTTON_ACTION_MENU:
+          meta_window_show_menu (window,
+                                 event->xbutton.x_root,
+                                 event->xbutton.y_root,
+                                 event->xbutton.button,
+                                 event->xbutton.time);
+            return;
+        case META_MOUSE_BUTTON_ACTION_PASSTHROUGH:
+           /* Give back event to x server */
+           XAllowEvents (display->xdisplay,
+                        ReplayPointer, event->xbutton.time);
+            return;
+        case META_MOUSE_BUTTON_ACTION_DEFAULT:
+            return;
+    }
+}
+
 static gboolean
 event_callback (XEvent   *event,
                 gpointer  data)
@@ -1113,50 +1198,19 @@
                * the click-to-focus
                */
               if (!unmodified)
-                begin_move = TRUE;
+              {
+                handle_modified_mouse_event(event, window, display, &begin_move);
+              }
             }
           else if (event->xbutton.button == 2)
             {
-              if (window->has_resize_func)
-                {
-                  gboolean north;
-                  gboolean west;
-                  int root_x, root_y;
-                  MetaGrabOp op;
-
-                  meta_window_get_position (window, &root_x, &root_y);
-
-                  west = event->xbutton.x_root < (root_x + window->rect.width / 2);
-                  north = event->xbutton.y_root < (root_y + window->rect.height / 2);
-
-                  if (west && north)
-                    op = META_GRAB_OP_RESIZING_NW;
-                  else if (west)
-                    op = META_GRAB_OP_RESIZING_SW;
-                  else if (north)
-                    op = META_GRAB_OP_RESIZING_NE;
-                  else
-                    op = META_GRAB_OP_RESIZING_SE;
-                  
-                  meta_display_begin_grab_op (display,
-                                              window->screen,
-                                              window,
-                                              op,
-                                              TRUE,
-                                              event->xbutton.button,
-                                              0,
-                                              event->xbutton.time,
-                                              event->xbutton.x_root,
-                                              event->xbutton.y_root);
-                }
+              handle_modified_mouse_event(event, window, 
+                                          display, &begin_move);
             }
           else if (event->xbutton.button == 3)
             {
-              meta_window_show_menu (window,
-                                     event->xbutton.x_root,
-                                     event->xbutton.y_root,
-                                     event->xbutton.button,
-                                     event->xbutton.time);
+              handle_modified_mouse_event(event, window, 
+                                          display, &begin_move);
             }
 
           if (begin_move && window->has_move_func)
@@ -2439,6 +2493,25 @@
   return TRUE;
 }
 
+/* This is called from prefs.c when the modified_mouse_action gconf
+ * keys are changed. This will just end all grab ops on all displays
+ * so that we don't get confused when the mouse button action changes
+ */
+void meta_display_must_end_grab_op (void)
+{
+  GSList *tmp;
+
+  tmp = all_displays;
+  while (tmp != NULL)
+    {
+      MetaDisplay *display = tmp->data;
+
+      meta_display_end_grab_op(display, meta_display_get_current_time(display));
+
+      tmp = tmp->next;
+    }
+}
+
 void
 meta_display_end_grab_op (MetaDisplay *display,
                           Time         timestamp)
diff -urN metacity-2.4.1/src/display.h metacity-2.4.1-ttb/src/display.h
--- metacity-2.4.1/src/display.h	2002-09-04 00:15:46.000000000 -0400
+++ metacity-2.4.1-ttb/src/display.h	2002-09-19 22:29:50.000000000 -0400
@@ -311,6 +311,7 @@
                                      int          root_y);
 void     meta_display_end_grab_op   (MetaDisplay *display,
                                      Time         timestamp);
+void     meta_display_must_end_grab_op (void);
 
 void     meta_display_grab_window_buttons    (MetaDisplay *display,
                                               Window       xwindow);
diff -urN metacity-2.4.1/src/metacity.schemas.in metacity-2.4.1-ttb/src/metacity.schemas.in
--- metacity-2.4.1/src/metacity.schemas.in	2002-08-21 02:47:16.000000000 -0400
+++ metacity-2.4.1-ttb/src/metacity.schemas.in	2002-09-19 14:43:11.000000000 -0400
@@ -1446,6 +1446,50 @@
     </schema>
 
 
+    <!-- modified mouse button mappings -->
+
+    <schema>
+      <key>/schemas/apps/metacity/general/modified_mouse_button_one_action</key>
+      <applyto>/apps/metacity/general/modified_mouse_button_one_action</applyto>
+      <owner>metacity</owner>
+      <type>string</type>
+      <default>move</default>
+      <locale name="C">
+        <short>Action mapped to mouse button one when clicked while holding the alt key down</short>
+        <long>
+            The possible actions are "move", "resize", "menu", "passthrough" and "default".
+        </long>
+      </locale>
+    </schema>
+
+    <schema>
+      <key>/schemas/apps/metacity/general/modified_mouse_button_two_action</key>
+      <applyto>/apps/metacity/general/modified_mouse_button_two_action</applyto>
+      <owner>metacity</owner>
+      <type>string</type>
+      <default>menu</default>
+      <locale name="C">
+        <short>Action mapped to mouse button two when clicked while holding the alt key down</short>
+        <long>
+            The possible actions are "move", "resize", "menu", "passthrough" and "default".
+        </long>
+      </locale>
+    </schema>
+
+    <schema>
+      <key>/schemas/apps/metacity/general/modified_mouse_button_three_action</key>
+      <applyto>/apps/metacity/general/modified_mouse_button_three_action</applyto>
+      <owner>metacity</owner>
+      <type>string</type>
+      <default>resize</default>
+      <locale name="C">
+        <short>Action mapped to mouse button three when clicked while holding the alt key down</short>
+        <long>
+            The possible actions are "move", "resize", "menu", "passthrough" and "default".
+        </long>
+      </locale>
+    </schema>
+
   </schemalist>  
 </gconfschemafile>
 
diff -urN metacity-2.4.1/src/prefs.c metacity-2.4.1-ttb/src/prefs.c
--- metacity-2.4.1/src/prefs.c	2002-08-21 02:47:16.000000000 -0400
+++ metacity-2.4.1-ttb/src/prefs.c	2002-09-19 22:41:53.000000000 -0400
@@ -44,6 +44,10 @@
 #define KEY_SCREEN_BINDINGS_PREFIX "/apps/metacity/global_keybindings"
 #define KEY_WINDOW_BINDINGS_PREFIX "/apps/metacity/window_keybindings"
 
+#define KEY_MOUSE_BUTTON_ONE_ACTION   "/apps/metacity/general/modified_mouse_button_one_action"
+#define KEY_MOUSE_BUTTON_TWO_ACTION "/apps/metacity/general/modified_mouse_button_two_action"
+#define KEY_MOUSE_BUTTON_THREE_ACTION   "/apps/metacity/general/modified_mouse_button_three_action"
+
 static GConfClient *default_client = NULL;
 static GList *listeners = NULL;
 static GList *changes = NULL;
@@ -53,6 +57,9 @@
 static MetaFocusMode focus_mode = META_FOCUS_MODE_CLICK;
 static char* current_theme = NULL;
 static int num_workspaces = 4;
+static MetaMouseButtonAction mouse_button_one_action   = META_MOUSE_BUTTON_ACTION_MOVE;
+static MetaMouseButtonAction mouse_button_two_action   = META_MOUSE_BUTTON_ACTION_MENU;
+static MetaMouseButtonAction mouse_button_three_action = META_MOUSE_BUTTON_ACTION_RESIZE;
 static gboolean application_based = FALSE;
 static gboolean disable_workarounds = FALSE;
 static gboolean auto_raise = FALSE;
@@ -74,6 +81,15 @@
                                            const char *value);
 static gboolean update_screen_binding     (const char *name,
                                            const char *value);
+
+#define MOUSE_ACTION_MOVE_STR        "move"
+#define MOUSE_ACTION_MENU_STR        "menu"
+#define MOUSE_ACTION_RESIZE_STR      "resize"
+#define MOUSE_ACTION_PASSTHROUGH_STR "passthrough"
+static gboolean update_mouse_button_one_action  (const char *value);
+static gboolean update_mouse_button_two_action  (const char *value);
+static gboolean update_mouse_button_three_action (const char *value);
+
 static void     init_bindings             (void);
 static gboolean update_binding            (MetaKeyPref *binding,
                                            const char  *value);
@@ -289,6 +305,23 @@
                                     &err);
   cleanup_error (&err);
   update_disable_workarounds (bool_val);
+
+  /* Added for customized mouse button actions */
+
+  str_val = gconf_client_get_string (default_client, KEY_MOUSE_BUTTON_ONE_ACTION,
+                                    &err);
+  cleanup_error(&err);
+  update_mouse_button_one_action(str_val);
+
+  str_val = gconf_client_get_string (default_client, KEY_MOUSE_BUTTON_TWO_ACTION,
+                                    &err);
+  cleanup_error(&err);
+  update_mouse_button_two_action(str_val);
+
+  str_val = gconf_client_get_string (default_client, KEY_MOUSE_BUTTON_THREE_ACTION,
+                                    &err);
+  cleanup_error(&err);
+  update_mouse_button_three_action(str_val);
   
   /* Load keybindings prefs */
   init_bindings ();
@@ -337,6 +370,57 @@
   key = gconf_entry_get_key (entry);
   value = gconf_entry_get_value (entry);
   
+  if (strcmp (key, KEY_MOUSE_BUTTON_ONE_ACTION) == 0)
+  {
+      const char *str;
+
+      if (value && value->type != GCONF_VALUE_STRING)
+        {
+          meta_warning (_("GConf key \"%s\" is set to an invalid type\n"),
+                        KEY_MOUSE_BUTTON_ONE_ACTION);
+          goto out;
+        }
+
+      str = value ? gconf_value_get_string(value) : NULL;
+
+      if (update_mouse_button_one_action(str))
+        queue_changed (META_PREF_MOUSE_BUTTON_ONE_ACTION);
+  }
+
+  if (strcmp (key, KEY_MOUSE_BUTTON_TWO_ACTION) == 0)
+  {
+      const char *str;
+
+      if (value && value->type != GCONF_VALUE_STRING)
+        {
+          meta_warning (_("GConf key \"%s\" is set to an invalid type\n"),
+                        KEY_MOUSE_BUTTON_TWO_ACTION);
+          goto out;
+        }
+
+      str = value ? gconf_value_get_string(value) : NULL;
+
+      if (update_mouse_button_two_action(str))
+        queue_changed (META_PREF_MOUSE_BUTTON_TWO_ACTION);
+  }
+
+  if (strcmp (key, KEY_MOUSE_BUTTON_THREE_ACTION) == 0)
+  {
+      const char *str;
+
+      if (value && value->type != GCONF_VALUE_STRING)
+        {
+          meta_warning (_("GConf key \"%s\" is set to an invalid type\n"),
+                        KEY_MOUSE_BUTTON_THREE_ACTION);
+          goto out;
+        }
+
+      str = value ? gconf_value_get_string(value) : NULL;
+
+      if (update_mouse_button_three_action(str))
+        queue_changed (META_PREF_MOUSE_BUTTON_THREE_ACTION);
+  }
+
   if (strcmp (key, KEY_FOCUS_MODE) == 0)
     {
       const char *str;
@@ -799,6 +883,15 @@
 
     case META_PREF_COMMANDS:
       return "COMMANDS";
+
+    case META_PREF_MOUSE_BUTTON_ONE_ACTION:
+      return "MOUSE_BUTTON_ONE_ACTION";
+
+    case META_PREF_MOUSE_BUTTON_TWO_ACTION:
+      return "MOUSE_BUTTON_TWO_ACTION";
+
+    case META_PREF_MOUSE_BUTTON_THREE_ACTION:
+      return "MOUSE_BUTTON_THREE_ACTION";
     }
 
   return "(unknown)";
@@ -1171,6 +1264,101 @@
   return auto_raise_delay;
 }
 
+static MetaMouseButtonAction parse_mouse_button_action (const char *value)
+{
+    if (!value||!*value) return META_MOUSE_BUTTON_ACTION_DEFAULT;
+
+    if (strcmp (value, MOUSE_ACTION_MOVE_STR) == 0)
+        return META_MOUSE_BUTTON_ACTION_MOVE;
+    if (strcmp (value, MOUSE_ACTION_MENU_STR) == 0)
+        return META_MOUSE_BUTTON_ACTION_MENU;
+    if (strcmp (value, MOUSE_ACTION_RESIZE_STR) == 0)
+        return META_MOUSE_BUTTON_ACTION_RESIZE;
+    if (strcmp (value, MOUSE_ACTION_PASSTHROUGH_STR) == 0)
+        return META_MOUSE_BUTTON_ACTION_PASSTHROUGH;
+
+    return META_MOUSE_BUTTON_ACTION_DEFAULT;
+}
+
+static gboolean
+update_mouse_button_one_action (const char *value)
+{
+    /* We stop all grab ops before making any changes so we don't get
+     * stuck */
+  meta_display_must_end_grab_op();
+
+  if (parse_mouse_button_action(value) != META_MOUSE_BUTTON_ACTION_DEFAULT)
+      mouse_button_one_action = parse_mouse_button_action(value);
+  else
+  {
+      /* This is the value we default to if we don't understand the
+       * action.
+       */
+      mouse_button_one_action = META_MOUSE_BUTTON_ACTION_MOVE;
+  }
+
+  return TRUE;
+}
+
+MetaMouseButtonAction 
+meta_prefs_get_mouse_button_one_action ()
+{
+  return mouse_button_one_action;
+}
+
+static gboolean
+update_mouse_button_two_action (const char *value)
+{
+    /* We stop all grab ops before making any changes so we don't get
+     * stuck */
+  meta_display_must_end_grab_op();
+
+  if (parse_mouse_button_action(value) != META_MOUSE_BUTTON_ACTION_DEFAULT)
+      mouse_button_two_action = parse_mouse_button_action(value);
+  else
+  {
+      /* This is the value we default to if we don't understand the
+       * action.
+       */
+      mouse_button_two_action = META_MOUSE_BUTTON_ACTION_RESIZE;
+  }
+  return TRUE;
+}
+
+MetaMouseButtonAction
+meta_prefs_get_mouse_button_two_action ()
+{
+  return mouse_button_two_action;
+}
+
+static gboolean
+update_mouse_button_three_action (const char *value)
+{
+    /* We stop all grab ops before making any changes so we don't get
+     * stuck */
+  meta_display_must_end_grab_op();
+
+    if (parse_mouse_button_action(value) != META_MOUSE_BUTTON_ACTION_DEFAULT)
+        mouse_button_three_action = parse_mouse_button_action(value);
+    else
+    {
+      /* This is the value we default to if we don't understand the
+       * action.
+       */
+        mouse_button_three_action = META_MOUSE_BUTTON_ACTION_MENU;
+    }
+
+  return TRUE;
+}
+
+MetaMouseButtonAction
+meta_prefs_get_mouse_button_three_action ()
+{
+  return mouse_button_three_action;
+}
+
+
+
 MetaKeyBindingAction
 meta_prefs_get_keybinding_action (const char *name)
 {
diff -urN metacity-2.4.1/src/prefs.h metacity-2.4.1-ttb/src/prefs.h
--- metacity-2.4.1/src/prefs.h	2002-08-21 02:47:16.000000000 -0400
+++ metacity-2.4.1-ttb/src/prefs.h	2002-09-19 14:40:27.000000000 -0400
@@ -38,7 +38,10 @@
   META_PREF_WINDOW_KEYBINDINGS,
   META_PREF_SCREEN_KEYBINDINGS,
   META_PREF_DISABLE_WORKAROUNDS,
-  META_PREF_COMMANDS
+  META_PREF_COMMANDS,
+  META_PREF_MOUSE_BUTTON_ONE_ACTION,
+  META_PREF_MOUSE_BUTTON_TWO_ACTION,
+  META_PREF_MOUSE_BUTTON_THREE_ACTION
 } MetaPreference;
 
 typedef void (* MetaPrefsChangedFunc) (MetaPreference pref,
@@ -62,6 +65,21 @@
 gboolean                    meta_prefs_get_auto_raise         (void);
 int                         meta_prefs_get_auto_raise_delay   (void);
 
+/* Mouse button actions */
+
+typedef enum _MetaMouseButtonAction
+{
+  META_MOUSE_BUTTON_ACTION_DEFAULT,
+  META_MOUSE_BUTTON_ACTION_MOVE,
+  META_MOUSE_BUTTON_ACTION_RESIZE,
+  META_MOUSE_BUTTON_ACTION_MENU,
+  META_MOUSE_BUTTON_ACTION_PASSTHROUGH
+} MetaMouseButtonAction;
+
+MetaMouseButtonAction      meta_prefs_get_mouse_button_one_action(void);
+MetaMouseButtonAction      meta_prefs_get_mouse_button_two_action(void);
+MetaMouseButtonAction      meta_prefs_get_mouse_button_three_action(void);
+
 const char*                 meta_prefs_get_command            (int i);
 
 char*                       meta_prefs_get_gconf_key_for_command (int i);
