Subject: FVWM: Icon-Aware CleverPlacement

From: Anthony Martin <[email-masked]>
Date: Fri, 17 Jan 1997 01:24:51 -0800 (PST)

Since I don't normally use icons, I hadn't noticed CleverPlacement's poor
handling of icons.  I have now modified CleverPlacement to place windows
around icons properly.  It also tries to avoid StaysOnTop windows and you
can make it avoid Sticky windows if you want (compile-time option).

To use CleverPlacement in 2.0.44, put the following line in your .fvwm2rc
file:
GlobalOpts SmartPlacementIsReallySmart

The patch also fixes a bug in the placement code that causes windows to be
misplaced by one pixel if the RandomPlacement flag is set.  This fix seems
to have missed 2.0.44.

The patch is attached, but if you prefer, you can get the entire
placement.c file from:
http://www.engr.csulb.edu/~amartin/placement.c
Just replace the original placement.c and recompile.

Let me know if you have any problems.

Tony.

--- placement.c.orig	Thu Jan 16 20:50:53 1997
+++ placement.c	Fri Jan 17 00:41:01 1997
@@ -33,15 +33,24 @@
 int test_fit(FvwmWindow *t, int test_x, int test_y, int aoimin);
 void CleverPlacement(FvwmWindow *t, int *x, int *y);
 
-/* The AVOIDONTOP factor represents the amount of area that ONTOP windows
- * are counted as.  The default is 5 times as much as normal windows.  To
- * treat ONTOP windows the same as other windows, set this to 1.  To really,
- * really avoid putting windows under ONTOP windows, set this to a high value,
- * say 1000.  A value of 5 will try to avoid ONTOP windows if practical, but if
- * it saves a reasonable amount of area elsewhere, it will place one there.
+/* The following factors represent the amount of area that these types of
+ * windows are counted as.  For example, by default the area of ONTOP windows
+ * is counted 5 times as much as normal windows.  So CleverPlacement will
+ * cover 5 times as much area of another window before it will cover an ONTOP
+ * window.  To treat ONTOP windows the same as other windows, set this to 1.
+ * To really, really avoid putting windows under ONTOP windows, set this to a
+ * high value, say 1000.  A value of 5 will try to avoid ONTOP windows if
+ * practical, but if it saves a reasonable amount of area elsewhere, it will
+ * place one there.  The same rules apply for the other "AVOID" factors.
  * (for CleverPlacement)
  */
 #define AVOIDONTOP 5
+#define AVOIDSTICKY 1
+#ifdef NO_STUBBORN_PLACEMENT
+#define AVOIDICON 0     /*  Ignore Icons.  Place windows over them  */
+#else
+#define AVOIDICON 10    /*  Try hard no to place windows over icons */
+#endif
 
 void SmartPlacement(FvwmWindow *t, int width, int height, int *x, int *y)
 {
@@ -174,10 +183,23 @@
   /* Test the values of the right edges of every window */
   for(testw = Scr.FvwmRoot.next ; testw != NULL ; testw = testw->next)
   {
-    if((testw->Desk == Scr.CurrentDesk) &&
-       !(testw->flags & ICONIFIED) && (testw != t) &&
-       (y < (testw->frame_height+2*testw->bw+testw->frame_y)) &&
-       (testw->frame_y < (t->frame_height+2*t->bw+y)))
+    if((testw->Desk != Scr.CurrentDesk) || (testw == t))
+      continue;
+    if(testw->flags & ICONIFIED)
+    {
+      if((y < (testw->icon_p_height+testw->icon_w_height+testw->icon_y_loc))&&
+         (testw->icon_y_loc < (t->frame_height+2*t->bw+y)))
+      {
+        xtest = testw->icon_p_width+testw->icon_x_loc;
+        if(xtest > x)
+          xnew = MIN(xnew, xtest);
+        xtest = testw->icon_x_loc - (t->frame_width + 2 * t->bw);
+        if(xtest > x)
+          xnew = MIN(xnew, xtest);
+      }
+    }
+    else if((y < (testw->frame_height+2*testw->bw+testw->frame_y)) &&
+            (testw->frame_y < (t->frame_height+2*t->bw+y)))
     {
       xtest = testw->frame_width+2*testw->bw+testw->frame_x;
       if(xtest > x)
@@ -203,8 +225,18 @@
   /* Test the values of the bottom edge of every window */
   for(testw = Scr.FvwmRoot.next ; testw != NULL ; testw = testw->next)
   {
-    if((testw->Desk == Scr.CurrentDesk) &&
-       !(testw->flags & ICONIFIED) && (testw != t))
+    if((testw->Desk != Scr.CurrentDesk) || (testw == t))
+      continue;
+    if(testw->flags & ICONIFIED)
+    {
+      ytest = testw->icon_p_height+testw->icon_w_height+testw->icon_y_loc;
+      if(ytest > y)
+        ynew = MIN(ynew, ytest);
+      ytest = testw->icon_y_loc - (t->frame_height + 2 * t->bw);
+      if(ytest > y)
+        ynew = MIN(ynew, ytest);
+    }
+    else
     {
       ytest = testw->frame_height+2*testw->bw+testw->frame_y;
       if(ytest > y)
@@ -227,6 +259,7 @@
   int xl, xr, yt, yb; /* xleft, xright, ytop, ybottom */
   int aoi = 0;	    /* area of interference */
   int anew;
+  int avoidance_factor;
   
   x12 = x11 + t->frame_width  + 2 * t->bw;
   y12 = y11 + t->frame_height + 2 * t->bw;
@@ -237,28 +270,46 @@
     return -2;
   for(testw = Scr.FvwmRoot.next ; testw != NULL ; testw = testw->next)
   {
-    x21 = testw->frame_x;
-    y21 = testw->frame_y;
-    x22 = x21 + testw->frame_width  + 2 * testw->bw;
-    y22 = y21 + testw->frame_height + 2 * testw->bw;
-    if((testw->Desk == Scr.CurrentDesk) &&
-       !(testw->flags & ICONIFIED) && (testw != t))
+    if((testw == t) || (testw->Desk != Scr.CurrentDesk))
+       continue;
+    if((testw->flags & ICONIFIED)&&
+       (testw->icon_w))
+    {
+       if(testw->flags & ICON_UNMAPPED)
+	  continue;
+       x21 = testw->icon_x_loc;
+       y21 = testw->icon_y_loc;
+       x22 = x21 + testw->icon_p_width;
+       y22 = y21 + testw->icon_p_height + testw->icon_w_height;
+    }
+    else
     {
-      if((x11 < x22) && (x12 > x21) &&
-         (y11 < y22) && (y12 > y21))
-      {
-        /* Windows interfere */
-        xl = MAX(x11, x21);
-        xr = MIN(x12, x22);
-        yt = MAX(y11, y21);
-        yb = MIN(y12, y22);
-        anew = (xr - xl) * (yb - yt);
-        if(testw->flags & ONTOP)
-          anew *= AVOIDONTOP;
-        aoi += anew;
-        if((aoi > aoimin)&&(aoimin != -1))
-          return aoi;
-      }
+       x21 = testw->frame_x;
+       y21 = testw->frame_y;
+       x22 = x21 + testw->frame_width  + 2 * testw->bw;
+       y22 = y21 + testw->frame_height + 2 * testw->bw;
+    }
+    if((x11 < x22) && (x12 > x21) &&
+       (y11 < y22) && (y12 > y21))
+    {
+      /* Windows interfere */
+      xl = MAX(x11, x21);
+      xr = MIN(x12, x22);
+      yt = MAX(y11, y21);
+      yb = MIN(y12, y22);
+      anew = (xr - xl) * (yb - yt);
+      if(testw->flags & ICONIFIED)
+        avoidance_factor = AVOIDICON;
+      else if(testw->flags & ONTOP)
+        avoidance_factor = AVOIDONTOP;
+      else if(testw->flags & STICKY)
+        avoidance_factor = AVOIDSTICKY;
+      else
+        avoidance_factor = 1;
+      anew *= avoidance_factor;
+      aoi += anew;
+      if((aoi > aoimin)&&(aoimin != -1))
+        return aoi;
     }
   }
   return aoi;
@@ -382,8 +433,8 @@
       }
       else
       {
-        tmp_win->attr.x = xl - tmp_win->old_bw;
-        tmp_win->attr.y = yt - tmp_win->old_bw;
+        tmp_win->attr.x = xl - tmp_win->old_bw + tmp_win->bw;
+        tmp_win->attr.y = yt - tmp_win->old_bw + tmp_win->bw;
       }
       /* patches 11/93 to try to keep the window on the
        * screen */

--
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].