? 81704.patch
? stamp-h1
Index: src/common.h
===================================================================
RCS file: /cvs/gnome/metacity/src/common.h,v
retrieving revision 1.34
diff -u -b -B -r1.34 common.h
--- src/common.h	21 Jun 2004 16:47:27 -0000	1.34
+++ src/common.h	20 Jun 2005 04:14:06 -0000
@@ -210,6 +210,13 @@
   MetaButtonFunction right_buttons[MAX_BUTTONS_PER_CORNER];
 };
 
+typedef enum
+{
+  META_MOVE_ASSISTANCE_NONE,
+  META_MOVE_ASSISTANCE_RESISTANCE,
+  META_MOVE_ASSISTANCE_SNAP
+} MetaMoveAssistance;
+
 /* should investigate changing these to whatever most apps use */
 #define META_ICON_WIDTH 32
 #define META_ICON_HEIGHT 32
Index: src/metacity.schemas.in
===================================================================
RCS file: /cvs/gnome/metacity/src/metacity.schemas.in,v
retrieving revision 1.42
diff -u -b -B -r1.42 metacity.schemas.in
--- src/metacity.schemas.in	5 Feb 2005 03:57:41 -0000	1.42
+++ src/metacity.schemas.in	20 Jun 2005 04:14:06 -0000
@@ -61,6 +61,20 @@
       </locale>
     </schema>
 
+     <schema>
+      <key>/schemas/apps/metacity/general/move_assistance</key>
+      <applyto>/apps/metacity/general/move_assistance</applyto>
+      <owner>metacity</owner>
+      <type>string</type>
+      <default>none</default>
+      <locale name="C">
+         <short>Type of window arrangement assistance mode</short>
+         <long>
+          none: provides no automatic window arrangement. resistance: provides resistance before aligning against edges of windows and screen. snap: make windows snap to edges of other windows and screen
+         </long>
+      </locale>
+    </schema>
+
     <schema>
       <key>/schemas/apps/metacity/general/action_double_click_titlebar</key>
       <applyto>/apps/metacity/general/action_double_click_titlebar</applyto>
Index: src/prefs.c
===================================================================
RCS file: /cvs/gnome/metacity/src/prefs.c,v
retrieving revision 1.50
diff -u -b -B -r1.50 prefs.c
--- src/prefs.c	26 Jan 2005 08:43:38 -0000	1.50
+++ src/prefs.c	20 Jun 2005 04:14:06 -0000
@@ -52,6 +52,7 @@
 #define KEY_DISABLE_WORKAROUNDS "/apps/metacity/general/disable_workarounds"
 #define KEY_BUTTON_LAYOUT "/apps/metacity/general/button_layout"
 #define KEY_REDUCED_RESOURCES "/apps/metacity/general/reduced_resources"
+#define KEY_MOVE_ASSISTANCE "/apps/metacity/general/move_assistance"
 #define KEY_GNOME_ACCESSIBILITY "/desktop/gnome/interface/accessibility"
 
 #define KEY_COMMAND_PREFIX "/apps/metacity/keybinding_commands/command_"
@@ -107,6 +108,8 @@
   }
 };
 
+static MetaMoveAssistance move_assistance = META_MOVE_ASSISTANCE_NONE;
+
 /* The screenshot commands are at the end */
 static char *commands[MAX_COMMANDS] = { NULL, };
 
@@ -129,6 +132,7 @@
 static gboolean update_auto_raise          (gboolean   value);
 static gboolean update_auto_raise_delay    (int        value);
 static gboolean update_button_layout      (const char *value);
+static gboolean update_move_assistance    (const char *value);
 static gboolean update_window_binding     (const char *name,
                                            const char *value);
 static gboolean update_screen_binding     (const char *name,
@@ -396,6 +400,12 @@
   update_button_layout (str_val);
   g_free (str_val);
   
+  str_val = gconf_client_get_string (default_client, KEY_MOVE_ASSISTANCE,
+                                     &err);
+  cleanup_error (&err);
+  update_move_assistance (str_val);
+  g_free (str_val);
+
   bool_val = gconf_client_get_bool (default_client, KEY_VISUAL_BELL,
                                     &err);
   cleanup_error (&err);
@@ -769,6 +779,22 @@
       if (update_button_layout (str))
         queue_changed (META_PREF_BUTTON_LAYOUT);
     }
+  else if (strcmp (key, KEY_MOVE_ASSISTANCE) == 0)
+  {
+      const char *str;
+      
+      if (value && value->type != GCONF_VALUE_STRING)
+        {
+          meta_warning (_("GConf key \"%s\" is set to an invalid type\n"),
+                        KEY_MOVE_ASSISTANCE);
+          goto out;
+        }
+      
+      str = value ? gconf_value_get_string (value) : NULL;
+
+      if (update_move_assistance (str))
+        queue_changed (META_PREF_MOVE_ASSISTANCE);
+    }
   else if (strcmp (key, KEY_VISUAL_BELL) == 0)
     {
       gboolean b;
@@ -1200,6 +1226,35 @@
 }
 #endif /* HAVE_GCONF */
 
+#ifdef HAVE_GCONF
+static gboolean
+update_move_assistance (const char *value)
+{
+  MetaMoveAssistance old_mode = move_assistance;
+  
+  if (value != NULL)
+    {
+      if (g_ascii_strcasecmp (value, "resistance") == 0)
+        move_assistance = META_MOVE_ASSISTANCE_RESISTANCE;
+      else if (g_ascii_strcasecmp (value, "snap") == 0)
+        move_assistance = META_MOVE_ASSISTANCE_SNAP;
+      else if (g_ascii_strcasecmp (value, "none") == 0)
+        move_assistance = META_MOVE_ASSISTANCE_NONE;
+      else
+        meta_warning (_("GConf key '%s' is set to an invalid value\n"),
+                      KEY_MOVE_ASSISTANCE);
+    }
+
+  return (old_mode != move_assistance);
+}
+#endif /* HAVE_GCONF */
+
+MetaMoveAssistance
+meta_prefs_get_move_assistance (void)
+{
+  return move_assistance;
+}
+
 const PangoFontDescription*
 meta_prefs_get_titlebar_font (void)
 {
@@ -1424,6 +1479,10 @@
 
     case META_PREF_BUTTON_LAYOUT:
       return "BUTTON_LAYOUT";
+      break;
+
+    case META_PREF_MOVE_ASSISTANCE:
+      return "MOVE_ASSISTANCE";
       break;
 
     case META_PREF_WORKSPACE_NAMES:
Index: src/prefs.h
===================================================================
RCS file: /cvs/gnome/metacity/src/prefs.h,v
retrieving revision 1.36
diff -u -b -B -r1.36 prefs.h
--- src/prefs.h	26 Jan 2005 08:43:38 -0000	1.36
+++ src/prefs.h	20 Jun 2005 04:14:06 -0000
@@ -47,6 +47,7 @@
   META_PREF_VISUAL_BELL,
   META_PREF_AUDIBLE_BELL,
   META_PREF_VISUAL_BELL_TYPE,
+  META_PREF_MOVE_ASSISTANCE,
   META_PREF_REDUCED_RESOURCES,
   META_PREF_GNOME_ACCESSIBILITY
 } MetaPreference;
@@ -83,6 +84,7 @@
 const char*                 meta_prefs_get_gconf_key_for_terminal_command (void);
 
 void                        meta_prefs_get_button_layout (MetaButtonLayout *button_layout);
+MetaMoveAssistance          meta_prefs_get_move_assistance    (void);
 MetaActionDoubleClickTitlebar meta_prefs_get_action_double_click_titlebar (void);
 
 void meta_prefs_set_num_workspaces (int n_workspaces);
Index: src/window.c
===================================================================
RCS file: /cvs/gnome/metacity/src/window.c,v
retrieving revision 1.388
diff -u -b -B -r1.388 window.c
--- src/window.c	2 Jun 2005 15:47:37 -0000	1.388
+++ src/window.c	20 Jun 2005 04:14:07 -0000
@@ -6379,7 +6379,7 @@
 {
   int dx, dy;
   int new_x, new_y;
-  int shake_threshold;
+  int drag_threshold, shake_threshold;
   
   window->display->grab_latest_motion_x = x;
   window->display->grab_latest_motion_y = y;
@@ -6403,8 +6403,8 @@
    */
 
 #define DRAG_THRESHOLD_TO_SHAKE_THRESHOLD_FACTOR 6
-  shake_threshold = meta_ui_get_drag_threshold (window->screen->ui) *
-    DRAG_THRESHOLD_TO_SHAKE_THRESHOLD_FACTOR;
+  drag_threshold = meta_ui_get_drag_threshold (window->screen->ui);
+  shake_threshold = drag_threshold * DRAG_THRESHOLD_TO_SHAKE_THRESHOLD_FACTOR;
     
   if (window->maximized && ABS (dy) >= shake_threshold)
     {
@@ -6508,7 +6508,52 @@
           new_x = meta_window_find_nearest_vertical_edge (window, new_x);
           new_y = meta_window_find_nearest_horizontal_edge (window, new_y);
         }
+      else
+      {
+      MetaMoveAssistance move_assist = meta_prefs_get_move_assistance ();
+      if (move_assist != META_MOVE_ASSISTANCE_NONE)
+        {
+#         define DRAG_THRESHOLD_TO_SNAP_THRESHOLD_FACTOR 2
+          int snap_threshold = drag_threshold * 
+              DRAG_THRESHOLD_TO_SNAP_THRESHOLD_FACTOR;
+
+          int nearest_x, nearest_y;
+          nearest_x = meta_window_find_nearest_vertical_edge (window, new_x);
+          nearest_y = meta_window_find_nearest_horizontal_edge (window, new_y);
+
+          if (move_assist == META_MOVE_ASSISTANCE_RESISTANCE) 
+            {
+              MetaRectangle old_rect;
+              meta_window_get_position (window, &old_rect.x, &old_rect.y);
       
+              if (nearest_x == old_rect.x && 
+                  ABS (new_x - nearest_x) <= snap_threshold) 
+                {
+                  /* snaped and below threshold -- don't change x */
+                    new_x = nearest_x;
+                }
+              if (nearest_y == old_rect.y &&
+                  ABS (new_y - nearest_y) <= snap_threshold)
+                {
+                  /* snaped and below threshold -- don't change y */
+                    new_y = nearest_y;
+                }
+            }
+          else if (move_assist == META_MOVE_ASSISTANCE_SNAP)
+            {
+              if (ABS (new_x - nearest_x) <= snap_threshold) 
+                {
+                  /* below threshold -- snap in */
+                  new_x = nearest_x;
+                }
+              if (ABS (new_y - nearest_y) <= snap_threshold)
+                {
+                  /* below threshold -- snap in */
+                  new_y = nearest_y;
+                }
+            }
+        }
+    }
       meta_window_move (window, TRUE, new_x, new_y);
     }
 }
