Subject: FVWM: window attraction patch

From: AJ Weber <[email-masked]>
Date: Thu, 15 Oct 1998 09:12:40 -0700

This patch provides a window attraction mechanism similar to KDE's window snap.
When moving a window if it is with SnapAttraction pixels of another window
it will position itself flush with the other window.  It is my favorite
aspect of KDE's wm so I added here (since I like everything else about
fvwm better).

SnapAttraction is a builtin with one argument.  Defaults to 0.  (KDE defaults
to 10).

diff -c -r ../fvwm-2.0.46/./fvwm/builtins.c ./fvwm/builtins.c
*** ../fvwm-2.0.46/./fvwm/builtins.c	Tue Aug 19 16:41:27 1997
--- ./fvwm/builtins.c	Wed Oct 14 11:39:38 1998
***************
*** 1253,1258 ****
--- 1253,1274 ----
    Scr.ClickTime = val1;
  }
  
+ void SetSnapAttraction(XEvent *eventp,Window w,FvwmWindow *tmp_win,
+               unsigned long context, char *action,int* Module)
+ {
+   int val1;
+   int val1_unit,n;
+ 
+   n = GetOneArgument(action, &val1, &val1_unit);
+   if(n != 1)
+   {
+     fvwm_msg(ERR,"SetSnapAttraction","SnapAttraction requires 1 argument");
+     return;
+   }
+ 
+   Scr.SnapAttraction = val1;
+ }
+ 
  void SetXOR(XEvent *eventp,Window w,FvwmWindow *tmp_win,
              unsigned long context, char *action,int* Module)
  {
diff -c -r ../fvwm-2.0.46/./fvwm/functions.c ./fvwm/functions.c
*** ../fvwm-2.0.46/./fvwm/functions.c	Mon Aug 11 13:09:29 1997
--- ./fvwm/functions.c	Wed Oct 14 11:58:13 1998
***************
*** 126,131 ****
--- 126,132 ----
    {"Send_WindowList",send_list_func, F_SEND_WINDOW_LIST,    FUNC_NO_WINDOW},
    {"SendToModule", SendStrToModule,  F_SEND_STRING,         FUNC_NO_WINDOW},
    {"set_mask",     set_mask_function,F_SET_MASK,            FUNC_NO_WINDOW},
+   {"SnapAttraction",SetSnapAttraction,F_SNAP_ATT,           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 -c -r ../fvwm-2.0.46/./fvwm/fvwm.c ./fvwm/fvwm.c
*** ../fvwm-2.0.46/./fvwm/fvwm.c	Mon Aug  4 13:53:32 1997
--- ./fvwm/fvwm.c	Wed Oct 14 11:44:09 1998
***************
*** 1223,1228 ****
--- 1223,1229 ----
  
    Scr.EdgeScrollX = Scr.EdgeScrollY = 100;
    Scr.ScrollResistance = Scr.MoveResistance = 0;
+   Scr.SnapAttraction = 0;
    Scr.OpaqueSize = 5;
    Scr.ClickTime = 150;
    Scr.ColormapFocus = COLORMAP_FOLLOWS_MOUSE;
diff -c -r ../fvwm-2.0.46/./fvwm/misc.h ./fvwm/misc.h
*** ../fvwm-2.0.46/./fvwm/misc.h	Mon Aug 11 13:10:19 1997
--- ./fvwm/misc.h	Wed Oct 14 11:42:30 1998
***************
*** 516,521 ****
--- 516,523 ----
  	       unsigned long context, char *action,int* Module);
  void SetClick(XEvent *eventp,Window w,FvwmWindow *tmp_win,
  	       unsigned long context, char *action,int* Module);
+ void SetSnapAttraction(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 -c -r ../fvwm-2.0.46/./fvwm/move.c ./fvwm/move.c
*** ../fvwm-2.0.46/./fvwm/move.c	Mon Aug 11 13:53:16 1997
--- ./fvwm/move.c	Wed Oct 14 11:45:33 1998
***************
*** 109,114 ****
--- 109,119 ----
  	      int Height, int *FinalX, int *FinalY,Bool opaque_move,
  	      Bool AddWindow)
  {
+ 	Window root, parent, *children;
+ 	FvwmWindow *tmp;
+ 	unsigned int nchildren;
+ 	int i,j;
+ 	int nyt,nxl,dist,closestLeft,closestRight,closestBottom,closestTop;
    Bool finished = False;
    Bool done;
    int xl,yt,delta_x,delta_y,paged;
***************
*** 180,185 ****
--- 185,267 ----
  	  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)
+ 		{
+ 			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;
+ 
  	  /* Resist moving windows over the edge of the screen! */
  	  if(((xl + Width) >= Scr.MyDisplayWidth)&&
  	     ((xl + Width) < Scr.MyDisplayWidth+Scr.MoveResistance))
***************
*** 208,213 ****
--- 290,372 ----
  	  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)
+ 		{
+ 			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;
+ 
  	  /* Resist moving windows over the edge of the screen! */
  	  if(((xl + Width) >= Scr.MyDisplayWidth)&&
  	     ((xl + Width) < Scr.MyDisplayWidth+Scr.MoveResistance))
***************
*** 219,225 ****
  	    yt = Scr.MyDisplayHeight - Height - tmp_win->bw;
  	  if((yt <= 0)&&(yt > -Scr.MoveResistance))
  	    yt = 0;
- 
  	/* check Paging request once and only once after outline redrawn */
  	/* redraw after paging if needed - mab */
  	paged=0;
--- 378,383 ----
diff -c -r ../fvwm-2.0.46/./fvwm/parse.h ./fvwm/parse.h
*** ../fvwm-2.0.46/./fvwm/parse.h	Mon Aug 11 13:10:39 1997
--- ./fvwm/parse.h	Wed Oct 14 11:41:16 1998
***************
*** 75,80 ****
--- 75,81 ----
  #define F_EXEC_SETUP            57
  #define F_CURSOR_STYLE          58
  #define F_CURRENT               59
+ #define F_SNAP_ATT              60
  
  /* Functions which require a target window */
  #define F_RESIZE		100
diff -c -r ../fvwm-2.0.46/./fvwm/screen.h ./fvwm/screen.h
*** ../fvwm-2.0.46/./fvwm/screen.h	Mon Aug  4 13:55:30 1997
--- ./fvwm/screen.h	Wed Oct 14 11:48:25 1998
***************
*** 311,316 ****
--- 311,317 ----
    int ClickTime;               /*Max button-click delay for Function built-in*/
    int ScrollResistance;        /* resistance to scrolling in desktop */
    int MoveResistance;          /* res to moving windows over viewport edge */
+   int SnapAttraction;          /* attractiveness of window edges */
    int OpaqueSize;
    int CurrentDesk;             /* The current desktop number */
    int ColormapFocus;           /* colormap focus style */
Only in .: patchfile
--
Visit the official FVWM web page at <URL:http://www.hpc.uh.edu/fvwm/>.
To unsubscribe from the list, send "unsubscribe fvwm" in the body of a
message to [email-masked].
To report problems, send mail to [email-masked].

---

From: Pat Rogan <[email-masked]>
Date: Thu, 15 Oct 1998 12:36:34 -0400

That would be a GREAT feature -- iff you can use as a Style parameter,
thereby being able to selectively enable/disbale on a per Style basis.

For instance, maybe i only want my Gimp pallets to snap to other
windows.

Alternatively, you might want to selectively turn off the ability for
other windows to snap to you:

Maybe sticky windows should not be snapped to. Also windows that are
always-on-top or always-on-bottom.  

Wharf, Fwvmbuttons, the pager maybe should not be snapped to.

I say let the user decide these things by adding the appropriate
variables.

~p@

-- 

Patrick Rogan
-----------------------------------
Systems Engineer

Lycos, Inc.
1 Oxford Centre
301 Grant Street, Suite 525
Pittsburgh, PA   15219-1408
--
Visit the official FVWM web page at <URL:http://www.hpc.uh.edu/fvwm/>.
To unsubscribe from the list, send "unsubscribe fvwm" in the body of a
message to [email-masked].
To report problems, send mail to [email-masked].

---

From: AJ Weber <[email-masked]>
Date: Thu, 15 Oct 1998 09:44:08 -0700

> I say let the user decide these things by adding the appropriate

Yeah, the current patch is just a global effect.  However, I have been 
trying to work out exactly where to go with this.  The Style this is
probably easy enough, but I was thinking along the lines of window groups.
If it were easy to associate groups of windows (either by direct interaction
on instances, or by type ala Styles) one could move groups of windows.

So in your gimp example you could move your gimp group all at once w/o 
interfereing with other windows.