Subject: SnapAttraction update/fix

From: [email-masked]
Date: Fri, 27 Nov 1998 13:40:31 -0800

This patch applies to 2.1.2 and fixes the off-by-1-pixel bug on SnapAttraction.

While I was at it I added icon and snap to grid functionality.  Icons may now
be snap attracted as well.  SnapAttraction now takes an optional second
argument that may be one of the following:

All     - Icons and Windows attract to other Icons or Windows
Likes   - Icons attract to Icons only and Windows attract to Windows only
Icons   - Icons attract to Icons only
Windows - Windows attract to Windows only

For example I use:

SnapAttraction 10 Likes

The manpage entry for SnapAttraction should also note that (due to SnapGrid)
there is a difference between SnapAttraction of 0 and SnapAttraction of -1.
The value -1 completely deactivates SnapAttraction, while a value of 0 will
allow windows to exactly touch of positoned as such (in other words, 0
overrides the grid on exact positioning while -1 does not).  SnapAttraction's
default is now:
SnapAttraction -1 All
which behaves like the old default used to, no attraction at all.

Also, there is a new option called SnapGrid that take two arguments; first
is the X grid size, second is the Y grid size.  The default is 
SnapGrid 1 1
which effectively is no grid at all.

----------------------------------------------------------------------------

diff -Naur fvwm-2.1.2/fvwm/builtins.c fvwm_linux/fvwm/builtins.c
--- fvwm-2.1.2/fvwm/builtins.c	Fri Nov 20 05:51:11 1998
+++ fvwm_linux/fvwm/builtins.c	Fri Nov 27 12:38:39 1998
@@ -1268,7 +1268,9 @@
 {
   int val1;
   int val1_unit,n;
+  char *token = NULL;
 
+#if 0
   n = GetOneArgument(action, &val1, &val1_unit);
   if(n != 1)
   {
@@ -1277,6 +1279,56 @@
   }
 
   Scr.SnapAttraction = val1;
+#endif
+
+  action = GetNextToken(action, &token);
+  if(token == NULL)
+  {
+    fvwm_msg(ERR,"SetSnapAttraction",
+      "SnapAttraction requires at least 1 argument");
+    return;
+  }
+
+  sscanf(token,"%d", &(Scr.SnapAttraction));
+
+  free(token);
+
+  action = GetNextToken(action, &token);
+
+  if(token == NULL)
+  {
+    return;
+  }
+  
+  if(StrEquals(token,"All"))
+    { Scr.SnapMode = 0; }
+  if(StrEquals(token,"Likes"))
+    { Scr.SnapMode = 1; }
+  if(StrEquals(token,"Icons"))
+    { Scr.SnapMode = 2; }
+  if(StrEquals(token,"Windows"))
+    { Scr.SnapMode = 3; }
+
+  free(token);
+}
+
+void SetSnapGrid(XEvent *eventp,Window w,FvwmWindow *tmp_win,
+              unsigned long context, char *action,int* Module)
+{
+  int val1, val2;
+  int val1_unit,val2_unit,n;
+
+  n = GetTwoArguments(action, &val1, &val2, &val1_unit, &val2_unit);
+  if(n != 2)
+  {
+    fvwm_msg(ERR,"SetSnapGrid","SetSnapGrid requires 2 arguments");
+    return;
+  }
+
+  Scr.SnapGridX = val1;
+  if(Scr.SnapGridX < 1) { Scr.SnapGridX = 1;}
+  Scr.SnapGridY = val2;
+  if(Scr.SnapGridY < 1) { Scr.SnapGridY = 1;}
 }
 
 void SetXOR(XEvent *eventp,Window w,FvwmWindow *tmp_win,
diff -Naur fvwm-2.1.2/fvwm/functions.c fvwm_linux/fvwm/functions.c
--- fvwm-2.1.2/fvwm/functions.c	Fri Nov 20 05:51:14 1998
+++ fvwm_linux/fvwm/functions.c	Thu Nov 26 21:24:35 1998
@@ -143,6 +143,7 @@
   {"SetMenuDelay", set_menudelay,    F_SET_MENUDELAY,	    FUNC_NO_WINDOW},
   {"SetMenustyle", SetMenuStyle,     F_SET_MENUSTYLE,       FUNC_NO_WINDOW},
   {"SnapAttraction",SetSnapAttraction,F_SNAP_ATT,           FUNC_NO_WINDOW},
+  {"SnapGrid",     SetSnapGrid,      F_SNAP_GRID,           FUNC_NO_WINDOW},
   {"Stick",        stick_function,   F_STICK,               FUNC_NEEDS_WINDOW},
   {"Style",        ProcessNewStyle,  F_STYLE,               FUNC_NO_WINDOW},
   {"Title",        Nop_func,         F_TITLE,               FUNC_TITLE},
diff -Naur fvwm-2.1.2/fvwm/fvwm.c fvwm_linux/fvwm/fvwm.c
--- fvwm-2.1.2/fvwm/fvwm.c	Fri Nov 20 05:51:14 1998
+++ fvwm_linux/fvwm/fvwm.c	Fri Nov 27 12:36:53 1998
@@ -1253,7 +1253,10 @@
 
   Scr.EdgeScrollX = Scr.EdgeScrollY = 100;
   Scr.ScrollResistance = Scr.MoveResistance = 0;
-  Scr.SnapAttraction = 0;
+  Scr.SnapAttraction = -1;
+  Scr.SnapMode = 0;
+  Scr.SnapGridX = 1;
+  Scr.SnapGridY = 1;
   Scr.OpaqueSize = 5;
   Scr.ClickTime = 150;
   Scr.ColormapFocus = COLORMAP_FOLLOWS_MOUSE;
diff -Naur fvwm-2.1.2/fvwm/misc.h fvwm_linux/fvwm/misc.h
--- fvwm-2.1.2/fvwm/misc.h	Fri Nov 20 05:51:15 1998
+++ fvwm_linux/fvwm/misc.h	Thu Nov 26 21:21:15 1998
@@ -518,6 +518,8 @@
 	       unsigned long context, char *action,int* Module);
 void SetSnapAttraction(XEvent *eventp,Window w,FvwmWindow *tmp_win,
 			unsigned long context, char *action,int* Module);
+void SetSnapGrid(XEvent *eventp,Window w,FvwmWindow *tmp_win,
+			unsigned long context, char *action,int* Module);
 void NextFunc(XEvent *eventp,Window w,FvwmWindow *tmp_win,
 	      unsigned long context, char *action,int* Module);
 void PrevFunc(XEvent *eventp,Window w,FvwmWindow *tmp_win,
diff -Naur fvwm-2.1.2/fvwm/move.c fvwm_linux/fvwm/move.c
--- fvwm-2.1.2/fvwm/move.c	Fri Nov 20 05:51:16 1998
+++ fvwm_linux/fvwm/move.c	Fri Nov 27 12:51:26 1998
@@ -243,6 +243,13 @@
   move_window_doit(eventp,w,tmp_win,context,action,Module,FALSE,TRUE);
 }
 
+typedef struct _FvwmMoveable
+{
+	int w;
+	int h;
+	int x;
+	int y;
+} FvwmMoveable;
 
 /****************************************************************************
  *
@@ -262,6 +269,7 @@
   Bool done;
   int xl,yt,delta_x,delta_y,paged;
   unsigned int button_mask = 0;
+  FvwmMoveable self, other;
   
   XQueryPointer(dpy, Scr.Root, &JunkRoot, &JunkChild,&xl, &yt,
 		&JunkX, &JunkY, &button_mask);
@@ -354,89 +362,157 @@
 	  xl = Event.xmotion.x_root + XOffset;
 	  yt = Event.xmotion.y_root + YOffset;
 	  
-	  /* resist based on window edges */
-	  tmp = Scr.FvwmRoot.next;
-	  closestTop = Scr.SnapAttraction;
-	  closestBottom = Scr.SnapAttraction;
-	  closestRight = Scr.SnapAttraction;
-	  closestLeft = Scr.SnapAttraction;
-	  nxl = xl;
-	  nyt = yt;
-	  while(tmp)
-	    {
-	      if (tmp_win != tmp && !(tmp->flags&ICONIFIED) &&
-		  (tmp_win->Desk == tmp->Desk))
+	/* START OF SNAPATTRACTION BLOCK, mirrored in MotionNotify */
+	/* resist based on window edges */
+	tmp = Scr.FvwmRoot.next;
+	closestTop = Scr.SnapAttraction;
+	closestBottom = Scr.SnapAttraction;
+	closestRight = Scr.SnapAttraction;
+	closestLeft = Scr.SnapAttraction;
+	nxl = -1;
+	nyt = -1;
+	self.x = xl;
+	self.y = yt;
+	if(tmp_win->flags&ICONIFIED)
+	{
+		self.w = Width;
+		self.h = Height;
+	}
+	else
+	{
+		self.w = Width + tmp_win->bw;
+		self.h = Height + tmp_win->bw;
+	}
+	while(Scr.SnapAttraction >= 0 && tmp)
+	{
+		if(Scr.SnapMode == 0)  /* All */
+		{
+			/* NOOP */
+		}
+		if(Scr.SnapMode == 1)  /* Likes */
 		{
-		  if(!((tmp->frame_y + tmp->frame_height) < (yt) ||
-		       (tmp->frame_y) > (yt + Height) ))
-		    {
-		      dist = abs(tmp->frame_x - (xl + Width));
-		      if(dist < closestRight)
+			if( (tmp->flags&ICONIFIED) != (tmp_win->flags&ICONIFIED) )
+				{ tmp = tmp->next; continue; }
+		}
+		if(Scr.SnapMode == 2)  /* Icons */
+		{
+			if( !(tmp->flags&ICONIFIED) || !(tmp_win->flags&ICONIFIED) )
+				{ tmp = tmp->next; continue; }
+		}
+		if(Scr.SnapMode == 3)  /* Windows */
+		{
+			if( (tmp->flags&ICONIFIED) || (tmp_win->flags&ICONIFIED) )
+				{ tmp = tmp->next; continue; }
+		}
+		if (tmp_win != tmp && (tmp_win->Desk == tmp->Desk))
+		{
+			if(tmp->flags&ICONIFIED)
 			{
-			  closestRight = dist;
-			  if(((xl + Width) >= tmp->frame_x)&&
-			     ((xl + Width) < tmp->frame_x+Scr.SnapAttraction))
-			    nxl = tmp->frame_x - Width - tmp_win->bw;
-			  if(((xl + Width) >= tmp->frame_x
-			      - Scr.SnapAttraction)&&
-			     ((xl + Width) < tmp->frame_x))
-			    nxl = tmp->frame_x - Width - tmp_win->bw;
+				if(tmp->icon_p_height > 0)
+				{
+					other.w = tmp->icon_p_width;
+					other.h = tmp->icon_p_height;
+				}
+				else
+				{
+					other.w = tmp->icon_w_width;
+					other.h = tmp->icon_w_height;
+				}
+				other.x = tmp->icon_x_loc;
+				other.y = tmp->icon_y_loc;
 			}
-		      dist = abs(tmp->frame_x + tmp->frame_width - xl);
-		      if(dist < closestLeft)
+			else
 			{
-			  closestLeft = dist;
-			  if((xl <= tmp->frame_x + tmp->frame_width)&&
-			     (xl > tmp->frame_x + tmp->frame_width
-			      - Scr.SnapAttraction))
-			    nxl = tmp->frame_x + tmp->frame_width;
-			  if((xl <= tmp->frame_x + tmp->frame_width
-			      + Scr.SnapAttraction)&&
-			     (xl > tmp->frame_x + tmp->frame_width))
-			    nxl = tmp->frame_x + tmp->frame_width;
+				other.w = tmp->frame_width + 2 * tmp->bw;
+				other.h = tmp->frame_height + 2 * tmp->bw;
+				other.x = tmp->frame_x;
+				other.y = tmp->frame_y;
 			}
-		    }
-		  if(!(   (tmp->frame_x + tmp->frame_width) < (xl) ||
-			  (tmp->frame_x) > (xl + Width) ))
-		    {
-		      dist = abs(tmp->frame_y - (yt + Height));
-		      if(dist < closestBottom)
+			if(!((other.y + other.h) < (yt) ||
+				(other.y) > (yt + self.h) ))
 			{
-			  closestBottom = dist;
-			  if(((yt + Height) >= tmp->frame_y)&&
-			     ((yt + Height) < tmp->frame_y+Scr.SnapAttraction))
-			    nyt = tmp->frame_y - Height - tmp_win->bw;
-			  if(((yt + Height) >= tmp->frame_y
-			      - Scr.SnapAttraction)&&
-			     ((yt + Height) < tmp->frame_y))
-			    nyt = tmp->frame_y - Height - tmp_win->bw;
+				dist = abs(other.x - (xl + self.w));
+				if(dist < closestRight)
+				{
+					closestRight = dist;
+					if(((xl + self.w) >= other.x)&&
+						((xl + self.w) < other.x+Scr.SnapAttraction))
+						nxl = other.x - self.w;
+
+					if(((xl + self.w) >= other.x
+						- Scr.SnapAttraction)&&
+						((xl + self.w) < other.x))
+						nxl = other.x - self.w;
+				}
+				dist = abs(other.x + other.w - xl);
+				if(dist < closestLeft)
+				{
+					closestLeft = dist;
+					if((xl <= other.x + other.w)&&
+						(xl > other.x + other.w
+						- Scr.SnapAttraction))
+						nxl = other.x + other.w;
+					if((xl <= other.x + other.w
+						+ Scr.SnapAttraction)&&
+						(xl > other.x + other.w))
+						nxl = other.x + other.w;
+				}
 			}
-		      dist = abs(tmp->frame_y + tmp->frame_height - yt);
-		      if(dist < closestTop)
+			if(!(   (other.x + other.w) < (xl) ||
+				(other.x) > (xl + self.w) ))
 			{
-			  closestTop = dist;
-			  if((yt <= tmp->frame_y + tmp->frame_height)&&
-			     (yt > tmp->frame_y + tmp->frame_height
-			      - Scr.SnapAttraction))
-			    nyt = tmp->frame_y + tmp->frame_height;
-			  if((yt <= tmp->frame_y + tmp->frame_height
-			      + Scr.SnapAttraction)&&
-			     (yt > tmp->frame_y + tmp->frame_height))
-			    nyt = tmp->frame_y + tmp->frame_height;
+				dist = abs(other.y - (yt + self.h));
+				if(dist < closestBottom)
+				{
+					closestBottom = dist;
+					if(((yt + self.h) >= other.y)&&
+						((yt + self.h) < other.y+Scr.SnapAttraction))
+						nyt = other.y - self.h;
+					if(((yt + self.h) >= other.y
+						- Scr.SnapAttraction)&&
+						((yt + self.h) < other.y))
+						nyt = other.y - self.h;
+				}
+				dist = abs(other.y + other.h - yt);
+				if(dist < closestTop)
+				{
+					closestTop = dist;
+					if((yt <= other.y + other.h)&&
+						(yt > other.y + other.h
+						- Scr.SnapAttraction))
+						nyt = other.y + other.h;
+					if((yt <= other.y + other.h
+						+ Scr.SnapAttraction)&&
+						(yt > other.y + other.h))
+						nyt = other.y + other.h;
+				}
 			}
-		    }
-#if 0
-		  if(((yt + Height) >= Scr.MyDisplayHeight)&&
-		     ((yt + Height) < Scr.MyDisplayHeight+Scr.MoveResistance))
-		    yt = Scr.MyDisplayHeight - Height - tmp_win->bw;
-		  if((yt <= 0)&&(yt > -Scr.MoveResistance))
-		    yt = 0;
-#endif
-                }
-	      tmp = tmp->next;
-	    }
-	  xl = nxl;
-	  yt = nyt;
+		}
+		tmp = tmp->next;
+	}
+	if(nxl == -1)
+	{
+		if(xl != xl  / Scr.SnapGridX * Scr.SnapGridX)
+		{
+			xl = (xl+Scr.SnapGridX/2) / Scr.SnapGridX * Scr.SnapGridX;
+		}
+	}
+	else
+	{
+		xl = nxl;
+	}
+	if(nyt == -1)
+	{
+		if(yt != yt  / Scr.SnapGridY * Scr.SnapGridY)
+		{
+			yt = (yt+Scr.SnapGridY/2) / Scr.SnapGridY * Scr.SnapGridY;
+		}
+	}
+	else
+	{
+		yt = nyt;
+	}
+	/* END OF SNAPATTRACTION BLOCK, mirrored in MotionNotify */
 	  
 	  /* Resist moving windows over the edge of the screen! */
 	  if(((xl + Width) >= Scr.MyDisplayWidth)&&
@@ -466,85 +542,157 @@
 	  xl += XOffset;
 	  yt += YOffset;
 
-         /* resist based on window edges */
-         tmp = Scr.FvwmRoot.next;
-         closestTop = Scr.SnapAttraction;
-         closestBottom = Scr.SnapAttraction;
-         closestRight = Scr.SnapAttraction;
-         closestLeft = Scr.SnapAttraction;
-         nxl = xl;
-         nyt = yt;
-         while(tmp)
-	 {
-	   if (tmp_win != tmp && !(tmp->flags&ICONIFIED) &&
-	       (tmp_win->Desk == tmp->Desk))
-	   {
-	     if(!(   (tmp->frame_y + tmp->frame_height) < (yt) ||
-		     (tmp->frame_y) > (yt + Height) ))
-	     {
-	       dist = abs(tmp->frame_x - (xl + Width));
-	       if(dist < closestRight)
-	       {
-		 closestRight = dist;
-		 if(((xl + Width) >= tmp->frame_x)&&
-		    ((xl + Width) < tmp->frame_x+Scr.SnapAttraction))
-		   nxl = tmp->frame_x - Width - tmp_win->bw;
-		 if(((xl + Width) >= tmp->frame_x-Scr.SnapAttraction)&&
-		    ((xl + Width) < tmp->frame_x))
-		   nxl = tmp->frame_x - Width - tmp_win->bw;
-	       }
-	       dist = abs(tmp->frame_x + tmp->frame_width - xl);
-	       if(dist < closestLeft)
-	       {
-		 closestLeft = dist;
-		 if((xl <= tmp->frame_x + tmp->frame_width)&&
-		    (xl > tmp->frame_x + tmp->frame_width-Scr.SnapAttraction))
-		   nxl = tmp->frame_x + tmp->frame_width;
-		 if((xl <= tmp->frame_x + tmp->frame_width +
-		     Scr.SnapAttraction)&&
-		    (xl > tmp->frame_x + tmp->frame_width))
-		   nxl = tmp->frame_x + tmp->frame_width;
-	       }
-	     }
-	     if(!((tmp->frame_x + tmp->frame_width) < (xl) ||
-		  (tmp->frame_x) > (xl + Width) ))
-	     {
-	       dist = abs(tmp->frame_y - (yt + Height));
-	       if(dist < closestBottom)
-	       {
-		 closestBottom = dist;
-		 if(((yt + Height) >= tmp->frame_y)&&
-		    ((yt + Height) < tmp->frame_y+Scr.SnapAttraction))
-		   nyt = tmp->frame_y - Height - tmp_win->bw;
-		 if(((yt + Height) >= tmp->frame_y-Scr.SnapAttraction)&&
-		    ((yt + Height) < tmp->frame_y))
-		   nyt = tmp->frame_y - Height - tmp_win->bw;
-	       }
-	       dist = abs(tmp->frame_y + tmp->frame_height - yt);
-	       if(dist < closestTop)
-	       {
-		 closestTop = dist;
-		 if((yt <= tmp->frame_y + tmp->frame_height)&&
-		    (yt > tmp->frame_y + tmp->frame_height-Scr.SnapAttraction))
-		   nyt = tmp->frame_y + tmp->frame_height;
-		 if((yt <= tmp->frame_y + tmp->frame_height +
-		     Scr.SnapAttraction)&&
-		    (yt > tmp->frame_y + tmp->frame_height))
-		   nyt = tmp->frame_y + tmp->frame_height;
-	       }
-	     }
-#if 0
-	     if(((yt + Height) >= Scr.MyDisplayHeight)&&
-		((yt + Height) < Scr.MyDisplayHeight+Scr.MoveResistance))
-	       yt = Scr.MyDisplayHeight - Height - tmp_win->bw;
-	     if((yt <= 0)&&(yt > -Scr.MoveResistance))
-	       yt = 0;
-#endif
-	   }
-	   tmp = tmp->next;
-	 }
-         xl = nxl;
-         yt = nyt;
+	/* START OF SNAPATTRACTION BLOCK, mirrored in ButtonRelease */
+	/* resist based on window edges */
+	tmp = Scr.FvwmRoot.next;
+	closestTop = Scr.SnapAttraction;
+	closestBottom = Scr.SnapAttraction;
+	closestRight = Scr.SnapAttraction;
+	closestLeft = Scr.SnapAttraction;
+	nxl = -1;
+	nyt = -1;
+	self.x = xl;
+	self.y = yt;
+	if(tmp_win->flags&ICONIFIED)
+	{
+		self.w = Width;
+		self.h = Height;
+	}
+	else
+	{
+		self.w = Width + tmp_win->bw;
+		self.h = Height + tmp_win->bw;
+	}
+	while(Scr.SnapAttraction >= 0 && tmp)
+	{
+		if(Scr.SnapMode == 0)  /* All */
+		{
+			/* NOOP */
+		}
+		if(Scr.SnapMode == 1)  /* Likes */
+		{
+			if( (tmp->flags&ICONIFIED) != (tmp_win->flags&ICONIFIED) )
+				{ tmp = tmp->next; continue; }
+		}
+		if(Scr.SnapMode == 2)  /* Icons */
+		{
+			if( !(tmp->flags&ICONIFIED) || !(tmp_win->flags&ICONIFIED) )
+				{ tmp = tmp->next; continue; }
+		}
+		if(Scr.SnapMode == 3)  /* Windows */
+		{
+			if( (tmp->flags&ICONIFIED) || (tmp_win->flags&ICONIFIED) )
+				{ tmp = tmp->next; continue; }
+		}
+		if (tmp_win != tmp && (tmp_win->Desk == tmp->Desk))
+		{
+			if(tmp->flags&ICONIFIED)
+			{
+				if(tmp->icon_p_height > 0)
+				{
+					other.w = tmp->icon_p_width;
+					other.h = tmp->icon_p_height;
+				}
+				else
+				{
+					other.w = tmp->icon_w_width;
+					other.h = tmp->icon_w_height;
+				}
+				other.x = tmp->icon_x_loc;
+				other.y = tmp->icon_y_loc;
+			}
+			else
+			{
+				other.w = tmp->frame_width + 2 * tmp->bw;
+				other.h = tmp->frame_height + 2 * tmp->bw;
+				other.x = tmp->frame_x;
+				other.y = tmp->frame_y;
+			}
+			if(!((other.y + other.h) < (yt) ||
+				(other.y) > (yt + self.h) ))
+			{
+				dist = abs(other.x - (xl + self.w));
+				if(dist < closestRight)
+				{
+					closestRight = dist;
+					if(((xl + self.w) >= other.x)&&
+						((xl + self.w) < other.x+Scr.SnapAttraction))
+						nxl = other.x - self.w;
+
+					if(((xl + self.w) >= other.x
+						- Scr.SnapAttraction)&&
+						((xl + self.w) < other.x))
+						nxl = other.x - self.w;
+				}
+				dist = abs(other.x + other.w - xl);
+				if(dist < closestLeft)
+				{
+					closestLeft = dist;
+					if((xl <= other.x + other.w)&&
+						(xl > other.x + other.w
+						- Scr.SnapAttraction))
+						nxl = other.x + other.w;
+					if((xl <= other.x + other.w
+						+ Scr.SnapAttraction)&&
+						(xl > other.x + other.w))
+						nxl = other.x + other.w;
+				}
+			}
+			if(!(   (other.x + other.w) < (xl) ||
+				(other.x) > (xl + self.w) ))
+			{
+				dist = abs(other.y - (yt + self.h));
+				if(dist < closestBottom)
+				{
+					closestBottom = dist;
+					if(((yt + self.h) >= other.y)&&
+						((yt + self.h) < other.y+Scr.SnapAttraction))
+						nyt = other.y - self.h;
+					if(((yt + self.h) >= other.y
+						- Scr.SnapAttraction)&&
+						((yt + self.h) < other.y))
+						nyt = other.y - self.h;
+				}
+				dist = abs(other.y + other.h - yt);
+				if(dist < closestTop)
+				{
+					closestTop = dist;
+					if((yt <= other.y + other.h)&&
+						(yt > other.y + other.h
+						- Scr.SnapAttraction))
+						nyt = other.y + other.h;
+					if((yt <= other.y + other.h
+						+ Scr.SnapAttraction)&&
+						(yt > other.y + other.h))
+						nyt = other.y + other.h;
+				}
+			}
+		}
+		tmp = tmp->next;
+	}
+	if(nxl == -1)
+	{
+		if(xl != xl  / Scr.SnapGridX * Scr.SnapGridX)
+		{
+			xl = (xl+Scr.SnapGridX/2) / Scr.SnapGridX * Scr.SnapGridX;
+		}
+	}
+	else
+	{
+		xl = nxl;
+	}
+	if(nyt == -1)
+	{
+		if(yt != yt  / Scr.SnapGridY * Scr.SnapGridY)
+		{
+			yt = (yt+Scr.SnapGridY/2) / Scr.SnapGridY * Scr.SnapGridY;
+		}
+	}
+	else
+	{
+		yt = nyt;
+	}
+	/* END OF SNAPATTRACTION BLOCK, mirrored in ButtonRelease */
 	 
 	 /* Resist moving windows over the edge of the screen! */
 	 if(((xl + Width) >= Scr.MyDisplayWidth)&&
diff -Naur fvwm-2.1.2/fvwm/parse.h fvwm_linux/fvwm/parse.h
--- fvwm-2.1.2/fvwm/parse.h	Fri Nov 20 05:51:16 1998
+++ fvwm_linux/fvwm/parse.h	Thu Nov 26 21:22:50 1998
@@ -84,7 +84,8 @@
     F_SET_MENUSTYLE,
     F_CHANGE_MENUSTYLE,
     F_DESTROY_MENUSTYLE,
-    F_SNAP_ATT, /* 65 */
+    F_SNAP_ATT, 
+    F_SNAP_GRID, /* 66 */
 /* Functions which require a target window */
     F_RESIZE = 100,
     F_RAISE,
diff -Naur fvwm-2.1.2/fvwm/screen.h fvwm_linux/fvwm/screen.h
--- fvwm-2.1.2/fvwm/screen.h	Fri Nov 20 05:51:17 1998
+++ fvwm_linux/fvwm/screen.h	Fri Nov 27 11:59:31 1998
@@ -305,6 +305,9 @@
   int ScrollResistance;        /* resistance to scrolling in desktop */
   int MoveResistance;          /* res to moving windows over viewport edge */
   int SnapAttraction;          /* attractiveness of window edges */
+  int SnapMode;                /* mode of snap attraction */
+  int SnapGridX;               /* snap grid X size */
+  int SnapGridY;               /* snap grid Y size */
   int OpaqueSize;
   int CurrentDesk;             /* The current desktop number */
   int ColormapFocus;           /* colormap focus style */
--
Visit the official FVWM web page at <URL:http://www.hpc.uh.edu/fvwm/>.
To unsubscribe from the list, send "unsubscribe fvwm-workers" in the
body of a message to [email-masked].
To report problems, send mail to [email-masked].

---

From: Dominik Vogt <[email-masked]>
Date: Mon, 30 Nov 1998 12:06:22 +0100

> which effectively is no grid at all.

Hmm, at the moment I don't want to add new features. Could you please post
a patch for the one-pixel-off bug only? Before the patch can be added it
has to have its manpage entry. I want the bugfix fast, but I'm not willing
to put new (and potentially buggy) stuff into CVS so close to the beta.

Bye

DOminik

---

From: [email-masked]
Date: Mon, 30 Nov 1998 11:57:01 -0800

> to put new (and potentially buggy) stuff into CVS so close to the beta.

Actually, the way I fixed the off by one is integral with the icon part.
(There is actually an off behavior in the original in which icons being moved
interact whilst sitting icons are not interacted with.  The new implementation
is fixes this too).
I tested it more thoroughly than the original so I would have to say that 
part is actually safer than the original patch anyway.  The grid part I can
yank, but it is rather trivial, which is why I sent it anyway.  If you the the
grid yanked, no problem.

So in summary the options are:
1.  No new patch at all, SnapAttraction stands pat.
2.  Full patch, grid and SnapAttraction second arg remain undocumented.
3.  Full patch with manpage patch updating new features.
4.  New patch with grid part removed.  (Since grid is unintrusive I'd rather
    not choose this option).
5.  New off-by-one-pixel fix patch.  This would be a brand new patch, without
    fixing the weird icon behavior.

---

From: Dominik Vogt <[email-masked]>
Date: Mon, 30 Nov 1998 21:07:02 +0100

>     fixing the weird icon behavior.

Version 3 is OK, but not immediately (well, it already missed 2.1.3).
However, I'd suggest to use a more intuitive term instead of 'likes'.

Bye

Dominik
-- 
Dominik Vogt, Hewlett-Packard GmbH, Dept. BVS
Herrenberger Str.130, 71034 Boeblingen, Germany
phone: 07031/14-4596, fax: 07031/14-3883, [email-masked]
--
Visit the official FVWM web page at <URL:http://www.hpc.uh.edu/fvwm/>.
To unsubscribe from the list, send "unsubscribe fvwm-workers" in the
body of a message to [email-masked].
To report problems, send mail to [email-masked].