Subject: Patch to allow titlebar buttons to be drawn depressed based on layer

From: Richard Curnow <[email-masked]>
Date: Mon, 10 Dec 2001 22:26:25 +0000

I've got titlebar buttons set up to force windows to the top or bottom
of the stacking order, or to let them 'float' again, like this:

Mouse 0 3    A Function "Put-on-top"
Mouse 0 5    A Function "Put-on-bottom"
Mouse 0 7    A Function "Put-at-default"

with the functions defined thus:

AddToFunc "Put-on-top" "I" Layer 0 6
+               "I" RefreshWindow
AddToFunc "Put-on-bottom" "I" Layer 0 2
+               "I" RefreshWindow
AddToFunc "Put-at-default" "I" Layer 0 4
+               "I" RefreshWindow

I wanted to make one of the buttons be drawn 'pressed in', depending on
the window's current layer (similar to MWMDecorStick and friends).  I've
attached my patch to version 2.4.3 to achieve this.  I'm not sure if
it's the best way to do it, but it seemed quite convenient.  I have the
buttons defined this way to use the new 'Layer' option to ButtonStyle
that the patch adds:

ButtonStyle 3 15 10x5@1 90x5@1 90x20@0 50x20@0 50x25@0 80x55@0 60x55@0 60x90@0 40x90@0 40x55@1 20x55@1 50x25@1 50x20@0 10x20@0 10x5@1 -- Flat
ButtonStyle 3 ActiveDown 15 10x5@0 90x5@0 90x20@1 50x20@1 50x25@1 80x55@1 60x55@1 60x90@1 40x90@1 40x55@0 20x55@0 50x25@0 50x20@1 10x20@1 10x5@0 -- Flat
ButtonStyle 3 - Layer 6

ButtonStyle 5 13 10x80@1 10x95@1 90x95@0 90x80@0 50x80@1 80x50@0 60x50@1 60x5@0 40x5@1 40x50@1 20x50@1 50x80@0 10x80@1 -- Flat
ButtonStyle 5 ActiveDown 13 10x80@0 10x95@0 90x95@1 90x80@1 50x80@0 80x50@1 60x50@0 60x5@1 40x5@0 40x50@0 20x50@0 50x80@1 10x80@0 -- Flat
ButtonStyle 5 - Layer 2

ButtonStyle 7 21 40x0@0 40x12@1 20x12@1 50x42@0 10x42@1 10x58@1 50x58@0 20x88@1 40x88@0 40x100@1 60x100@0 60x88@0 80x88@0 50x58@0 90x58@0 90x42@0 50x42@1 80x12@0 60x12@1 60x0@0 40x0@1 -- Flat
ButtonStyle 7 ActiveDown 21 40x0@1 40x12@0 20x12@0 50x42@1 10x42@0 10x58@0 50x58@1 20x88@0 40x88@1 40x100@0 60x100@1 60x88@1 80x88@1 50x58@1 90x58@1 90x42@1 50x42@0 80x12@1 60x12@0 60x0@1 40x0@0 -- Flat
ButtonStyle 7 - Layer 4

I've also attached a small PNG showing the effect.

Enjoy!

-- 
Richard.
---------------------------------+-------------------------------------
Richard P. Curnow                | C++: n., An octopus made by
Weston-super-Mare, UK            |  nailing extra legs on a cat.
http://www.rrbcurnow.freeuk.com/ |
--- screen.h.orig	Sun Dec  9 21:44:15 2001
+++ screen.h	Sun Dec  9 23:12:09 2001
@@ -187,6 +187,12 @@
   {
     unsigned has_changed : 1;
     mwm_flags mwm_decor_flags : 9;
+
+    /* Support {ButtonStyle <number> - Layer 4} construction, so button
+     * can be rendered 'pressed in' when the window is assigned to a
+     * particular layer. */
+    unsigned set_layer : 1;
+    int layer; 
   } flags;
   DecorFace state[BS_MaxButtonState];
 } TitleButton;
--- builtins.c.orig	Sun Dec  9 21:52:07 2001
+++ builtins.c	Sun Dec  9 23:15:38 2001
@@ -2299,6 +2299,46 @@
 #endif
 }
 
+static void SetLayerButtonFlag(
+  int layer, int multi, int set, FvwmDecor *decor, TitleButton *tb)
+{
+  int i;
+  int start = 0;
+  int add = 2;
+
+  if (multi)
+  {
+    if (multi == 2)
+      start = 1;
+    else if (multi == 3)
+      add = 1;
+    for (i = start; i < NUMBER_OF_BUTTONS; i += add)
+    {
+      if (set)
+      {
+        decor->buttons[i].flags.set_layer = 1;
+        decor->buttons[i].flags.layer = layer;
+      }
+      else
+      {
+        decor->buttons[i].flags.set_layer = 0;
+      }
+    }
+  }
+  else
+  {
+    if (set)
+    {
+      tb->flags.set_layer = 1;
+      tb->flags.layer = layer;
+    }
+    else
+      tb->flags.set_layer = 0;
+  }
+
+  return;
+}
+
 /*****************************************************************************
  *
  * Changes a button decoration style (changes by [email-masked])
@@ -2468,6 +2508,32 @@
 	{
 	  SetMWMButtonFlag(MWM_DECOR_STICK, multi, set, decor, tb);
 	}
+        else if (StrEquals(tok, "Layer")) 
+        {
+          int layer, got_number;
+          char *ltok;
+          text = GetNextToken(text, &ltok);
+          if (ltok)
+          {
+            got_number = (sscanf(ltok, "%d", &layer) == 1);
+            free (ltok);
+          }
+          else
+          {
+            got_number = 0;
+          }
+          if (!ltok || !got_number)
+          {
+            fvwm_msg(ERR, "ButtonStyle",
+                     "could not read integer value for layer -- line: %s",
+                     text);
+          }
+          else
+          {
+            SetLayerButtonFlag(layer, multi, set, decor, tb);
+          }
+          
+        }
 	else
 	{
 	  fvwm_msg(ERR, "ButtonStyle",
--- borders.c.orig	Sun Dec  9 22:21:11 2001
+++ borders.c	Sun Dec  9 23:16:49 2001
@@ -223,7 +223,8 @@
 static void DrawButton(
   FvwmWindow *t, Window win, int w, int h, DecorFace *df, GC ReliefGC,
   GC ShadowGC, Pixel fore_color, Pixel back_color, Bool is_lowest,
-  mwm_flags stateflags, int left1right0, XRectangle *rclip,
+  mwm_flags stateflags, int set_layer, int layer, 
+  int left1right0, XRectangle *rclip,
   Pixmap *pbutton_background_pixmap)
 {
   register DecorFaceType type = DFS_FACE_TYPE(df->style);
@@ -255,7 +256,8 @@
     if(HAS_MWM_BUTTONS(t) &&
        ((stateflags & MWM_DECOR_MAXIMIZE && IS_MAXIMIZED(t)) ||
 	(stateflags & MWM_DECOR_SHADE && IS_SHADED(t)) ||
-	(stateflags & MWM_DECOR_STICK && IS_STICKY(t))))
+	(stateflags & MWM_DECOR_STICK && IS_STICKY(t))) ||
+        (set_layer && (t->layer == layer)))
     {
       DrawLinePattern(win, ShadowGC, ReliefGC, fore_color, back_color,
         &df->u.vector, w, h);
@@ -1097,7 +1099,10 @@
 	    DrawButton(t, t->button_w[i], t->title_g.height, t->title_g.height,
 		       tsdf, cd->relief_gc, cd->shadow_gc,
 		       cd->fore_color, cd->back_color, is_lowest,
-		       TB_MWM_DECOR_FLAGS(GetDecor(t, buttons[i])), 1, NULL,
+		       TB_MWM_DECOR_FLAGS(GetDecor(t, buttons[i])), 
+                       t->decor->buttons[i].flags.set_layer,
+                       t->decor->buttons[i].flags.layer,
+                       1, NULL,
 		       pass_bg_pixmap);
 	    is_lowest = False;
 	  }
@@ -1110,7 +1115,10 @@
 	  DrawButton(t, t->button_w[i], t->title_g.height, t->title_g.height,
 		     df, cd->relief_gc, cd->shadow_gc,
 		     cd->fore_color, cd->back_color, is_lowest,
-		     TB_MWM_DECOR_FLAGS(GetDecor(t, buttons[i])), 1, NULL,
+		     TB_MWM_DECOR_FLAGS(GetDecor(t, buttons[i])),
+                     t->decor->buttons[i].flags.set_layer,
+                     t->decor->buttons[i].flags.layer,
+                     1, NULL,
 		     pass_bg_pixmap);
 	  is_lowest = False;
 	}
@@ -1284,7 +1292,9 @@
       {
 	DrawButton(
 	  t, t->title_w, t->title_g.width, t->title_g.height, df, sgc,
-	  rgc, cd->fore_color, cd->back_color, is_lowest, 0, 1, rclip,
+	  rgc, cd->fore_color, cd->back_color, is_lowest, 0,
+          0, 0,
+          1, rclip,
           pass_bg_pixmap);
 	is_lowest = False;
       }
@@ -1297,7 +1307,9 @@
       {
 	DrawButton(
 	  t, t->title_w, t->title_g.width, t->title_g.height, df, rgc,
-	  sgc, cd->fore_color, cd->back_color, is_lowest, 0, 1, rclip,
+	  sgc, cd->fore_color, cd->back_color, is_lowest, 0,
+          0, 0,
+          1, rclip,
           pass_bg_pixmap);
 	is_lowest = False;
       }
--- fvwm2.1.orig	Mon Dec 10 22:02:28 2001
+++ fvwm2.1	Mon Dec 10 22:10:42 2001
@@ -6193,6 +6193,12 @@
 sticky. When the window is sticky, the vector pattern on the
 button looks pressed in.
 
+The flag
+.BI "Layer " layer
+should be assigned to title-bar buttons which place the window in the layer
+numbered
+.IR layer .
+
 .TP
 .BI "ChangeDecor " decor
 Changes the decor of a window to