Subject: Shading as an ICCCM state

From: Matthias Clasen <[email-masked]>
Date: Fri, 15 Jan 1999 02:30:34 +0100

Today I had a look at afterstep and noticed that it handles 
shaded windows different than fvwm2. It subsumes the shaded
state among iconic. This makes a lot of sense. fvwm currently
makes it normal state.

The following patch changes fvwm to do the same, and allow 
all transitions between iconified, normal and shaded.

This even avoids a bug in afterstep: If a client deiconifies
a shaded window, afterstep doesn't unshade it. We do.

--- icons.c.last	Fri Jan 15 01:50:38 1999
+++ icons.c	Fri Jan 15 01:50:07 1999
@@ -873,6 +873,10 @@
   return;
 }
 
+#ifdef WINDOWSHADE
+void UnShade(FvwmWindow *tmp_win);
+#endif
+
 /****************************************************************************
  *
  * Iconifies the selected window
@@ -886,6 +890,12 @@
 
   if(!tmp_win)
     return;
+
+#ifdef WINDOWSHADE
+  if (tmp_win->buttons & WSHADE) {
+    UnShade(tmp_win);
+  }
+#endif
 
   XGetWindowAttributes(dpy, tmp_win->w, &winattrs);
   eventMask = winattrs.your_event_mask;
--- builtins.c.last	Fri Jan 15 01:52:00 1999
+++ builtins.c	Fri Jan 15 01:50:00 1999
@@ -436,49 +436,98 @@
  *
  *  WindowShade -- shades or unshades a window ([email-masked])
  *
- *  Args: 1 -- force shade, 2 -- force unshade  No Arg: toggle
+ *  Args: > 0 -- force shade, < 0 -- force unshade  No Arg: toggle
  *
  ***********************************************************************/
+/* tmp_win should be in normal state for this to work */
+void UnShade (FvwmWindow *tmp_win) 
+{    
+  XWindowAttributes winattrs = {0};
+  unsigned long eventMask;
+
+  tmp_win->buttons &= ~WSHADE;
+
+  XGetWindowAttributes(dpy, tmp_win->w, &winattrs);
+  eventMask = winattrs.your_event_mask;
+
+  tmp_win->flags |= MAPPED;
+  XSelectInput(dpy, tmp_win->w, eventMask & ~StructureNotifyMask);
+  XMapWindow(dpy, tmp_win->w);
+  XSelectInput(dpy, tmp_win->w, eventMask);
+
+  SetupFrame(tmp_win,
+	     tmp_win->frame_x,
+	     tmp_win->frame_y,
+	     tmp_win->orig_wd,
+	     tmp_win->orig_ht,
+	     True);
+
+  SetMapStateProp(tmp_win, NormalState);
+
+  BroadcastPacket(M_DEWINDOWSHADE, 3,
+		  tmp_win->w, tmp_win->frame, (unsigned long)tmp_win);
+}
+
+
+void Shade (FvwmWindow *tmp_win)
+{
+  XWindowAttributes winattrs = {0};
+  unsigned long eventMask;
+
+  tmp_win->buttons |= WSHADE;
+  
+  SetupFrame(tmp_win,
+	     tmp_win->frame_x,
+	     tmp_win->frame_y,
+	     tmp_win->frame_width,
+	     tmp_win->title_height + tmp_win->boundary_width,
+	     False);
+
+  if (tmp_win->flags & ICONIFIED) {
+    DeIconify(tmp_win);
+  }
+    
+  XGetWindowAttributes(dpy, tmp_win->w, &winattrs);
+  eventMask = winattrs.your_event_mask;
+  
+  tmp_win->flags &= ~MAPPED;
+  XSelectInput(dpy, tmp_win->w, eventMask & ~StructureNotifyMask);
+  XUnmapWindow(dpy, tmp_win->w);
+  XSelectInput(dpy, tmp_win->w, eventMask);
+  
+  SetMapStateProp(tmp_win, IconicState);
+  
+  BroadcastPacket(M_WINDOWSHADE, 3,
+		  tmp_win->w, tmp_win->frame, (unsigned long)tmp_win);
+}
+
 void WindowShade(XEvent *eventp,Window w,FvwmWindow *tmp_win,
 		 unsigned long context, char *action, int *Module)
 {
-    int n = 0;
-
+    int val = 0;
+    
     if (DeferExecution(eventp,&w,&tmp_win,&context, SELECT,ButtonRelease))
 	return;
 
+    GetIntegerArguments(action, NULL, &val, 1);
+
     if (!(tmp_win->flags & TITLE) || (tmp_win->flags & MAXIMIZED)) {
-	XBell(dpy, 0);
-	return;
-    }
-    while (isspace(*action))++action;
-    if (isdigit(*action))
-	sscanf(action,"%d",&n);
-
-    if (((tmp_win->buttons & WSHADE)||(n==2))&&(n!=1))
-    {
-	tmp_win->buttons &= ~WSHADE;
-	SetupFrame(tmp_win,
-		   tmp_win->frame_x,
-		   tmp_win->frame_y,
-		   tmp_win->orig_wd,
-		   tmp_win->orig_ht,
-		   True);
-        BroadcastPacket(M_DEWINDOWSHADE, 3,
-                        tmp_win->w, tmp_win->frame, (unsigned long)tmp_win);
+      FunctionNotAllowed();
+      return;
     }
+
+    if (((val > 0) && (tmp_win->buttons & WSHADE)) ||
+        ((val < 0) && !(tmp_win->buttons & WSHADE)))
+      return;
+
+    if (tmp_win->buttons & WSHADE)
+      {
+	UnShade (tmp_win);
+      } 
     else
-    {
-	tmp_win->buttons |= WSHADE;
-	SetupFrame(tmp_win,
-		   tmp_win->frame_x,
-		   tmp_win->frame_y,
-		   tmp_win->frame_width,
-		   tmp_win->title_height + tmp_win->boundary_width,
-		   False);
-        BroadcastPacket(M_WINDOWSHADE, 3,
-                        tmp_win->w, tmp_win->frame, (unsigned long)tmp_win);
-    }
+      {
+	Shade (tmp_win);
+      }
 }
 #endif /* WINDOWSHADE */
 
--- events.c.last	Fri Jan 15 02:02:08 1999
+++ events.c	Fri Jan 15 01:58:50 1999
@@ -796,6 +796,11 @@
 
   HandleMapRequestKeepRaised(None);
 }
+
+#ifdef WINDOWSHADE
+void UnShade (FvwmWindow *);
+#endif
+
 void HandleMapRequestKeepRaised(Window KeepRaised)
 {
   extern long isIconicState;
@@ -848,6 +853,13 @@
 
   if(KeepRaised != None)
     XRaiseWindow(dpy,KeepRaised);
+#ifdef WINDOWSHADE
+  if (Tmp_win->buttons & WSHADE) 
+    {
+      UnShade (Tmp_win);
+    } 
+  else
+#endif
   /* If it's not merely iconified, and we have hints, use them. */
   if (!(Tmp_win->flags & ICONIFIED))
     {

-- 
Matthias Clasen, 
Tel. 0761/203-5606
Email: [email-masked]
Mathematisches Institut, Albert-Ludwigs-Universitaet Freiburg
--
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: Tim Phipps <[email-masked]>
Date: Fri, 15 Jan 1999 13:15:56 +0000

> state among iconic. This makes a lot of sense. fvwm currently

I'm not a fan of shading but I've always thought of shading as NOT
iconifying. Shaded windows look as if they are normal windows that have
been squashed flat so just the borders and title bar are visible and I
thought that was done by manipulating the parent windows of the client,
meaning that the client window was untouched and the client didn't know
anything had happened.

At the moment shading and iconifying are orthogonal.  I don't think we
should link them without good reason.

Cheers,
Tim.

---

From: Matthias Clasen <[email-masked]>
Date: Fri, 15 Jan 1999 14:42:40 +0100

> I'm not a fan of shading but I've always thought of shading as NOT

I'm not a fan of shading either, but since its there, we should try
to make it work in the most natural way. 

> meaning that the client window was untouched and the client didn't know

For me, normal state implies that the client can expect its toplevel window
to be visible to the user (depending on the stacking order of course) and
have a size according to its size hints. This is not the case for shaded 
windows: Even if they are on top of stack, the user sees nothing. In this
respect, they are more like icons. You are right that the title bar and
borders look like those of a normal window, and that is part of why I
dislike shading.

> should link them without good reason.

Orthogonal ? I'm not convinced. At the moment, the interaction between
shading and other states is a bit inconsistent, I think. Let me see:

You can shade a normal window and only the title bar appears.
You can shade an icon and the visual appearance is unchanged, but
upon deiconification, only the title bar appears.
You can't shade a maximized window. But there is actually a bug lurking
here: If you try to shade a maximized window, you get the bell, but
the maximized window forgets its original size (you can't unmaximize
it any more)

---

From: Tim Phipps <[email-masked]>
Date: Fri, 15 Jan 1999 14:38:06 +0000

> to make it work in the most natural way.

Since neither of us like it much let's leave it alone until a fan offers
an opinion.

> You can shade a normal window and only the title bar appears.

Exactly, it's the title bar and it displays the WM_NAME property, not
the
icon name.  If you made shading be iconic then clients may change the
icon name to grab attention which wouldn't work if they were shaded. 
Another thought: what would happen to windows with active icons if they
were told they were iconified when shaded?

> upon deiconification, only the title bar appears.

That's because shading works on the window and not the icon so when you
deiconify you see the shaded window.  Maybe shading the icon shouldn't
be allowed but you could say the same about some other commands that
affect the window rather than the icon (Delete, MoveToPage/Desk,
Maximize)

> the maximized window forgets its original size (you can't unmaximize

It sounds like there is a bug in shading and maximizing so if we ignore
the maximized state you can have a window in any of the four states:

Normal <-------> Iconified
  ^                  ^
  |                  |
  v                  v
Shaded <-------> Iconified and shaded

You can transition between the left and right states with Iconify,
between top and bottom with WindowShade. I think Maximize should also be
orthogonal to this giving a cube of eight states (no ASCII diagram
included).

Cheers,
Tim.

---

From: Matthias Clasen <[email-masked]>
Date: Fri, 15 Jan 1999 16:05:27 +0100

> were told they were iconified when shaded?

Changing the icon name isn't an appropriate way to "grab attention". There
is no guarantee that the icon name is visible. ICCCM 2 introduced the 
urgency flag as a way to "grab attention". There is no guarantee either
that the icon window is visible/mapped in the iconic state. Clients that
have such a window will simply not get any expose events on it and thus
will not update its contents. 
 
> orthogonal to this giving a cube of eight states (no ASCII diagram

What I don't like with this square is that there is no visual difference
between the two states on the right. The current fvwm actually has
the same problem with maximized: Maximizing an icon doesn't change its
visual appearance. 

This cube diagram of eight states may be convenient for the programmer
since it directly corresponds to three independent flags, but from
a users perspective, I would expect a window to pop up to screen size 
immediately if I say "maximize" to an icon.

I'd propose to have only four states

normal, maximized, iconified, shaded, of which the first two correspond
to ICCCM NormalState and the last two to IconicState. The commands 
Iconify, Maximize, Shade would go to the corresponding state regardless
of the current state.

You can of course write complex functions to realize this based on
your cube, like

AddToFunc MyMaximize
+ "I" Iconify off
+ "I" WindowShade off
+ "I" Maximize on

AddToFunc MyIconify
+ "I" WindowShade off
+ "I" Maximize off
+ "I" Iconify on

AddToFunc MyShade
+ "I" Maximize off
+ "I" Iconify off
+ "I" WindowShade on

AddToFunc MyNormal
+ "I" Maximize off
+ "I" Iconify off
+ "I" WindowShade off

Thus it is perhaps best to implement the cube.

Matthias

PS I just tested the MyMaximize example above an wondered:
If used from a window menu, it works as expected, but if used
from FvwmTalk, I have to pick the window three times (once for
every function). Is there a way to avoid this ? Ie pick a context
which would then be used for the whole complex function ?

---

From: Matthias Clasen <[email-masked]>
Date: Fri, 15 Jan 1999 16:14:05 +0100

> were told they were iconified when shaded?

Forgot to mention: I have actually tested this with afterstep and a test
program with an icon window. Btw. The afterstep documentation mentions
that they changed the shading implementation from shaded==normal to
shaded==iconic, because clients had problems with shaded==normal (but
it seems they had a different implementation, resizing the client window
itself, not the frame)
 
> It sounds like there is a bug in shading and maximizing 

I tried it again and can't reproduce this any more. This was a false
alarm.

---

From: Tim Phipps <[email-masked]>
Date: Fri, 15 Jan 1999 16:20:27 +0000

Matthias Clasen wrote:
> Changing the icon name isn't an appropriate way to "grab attention".

OK "grab attention" is the wrong phrase, maybe "update status" is
better.
e.g. a CD player, this could conceivable display track time etc in an
icon window when iconified and put the track time in the WM_NAME when
normal.  If shading tells the window it is iconified it may not update
the WM_NAME but draw to the (unmapped) icon window.

> the same problem with maximized: Maximizing an icon doesn't change its

Agreed, but then you can change you key bindings so that shading and
maximizing don't happen in icons (use WTSF not A|WTSFI) or make a
different window menu pop up for icons that doesn't include shade/max.

> immediately if I say "maximize" to an icon.

I disagree, from this users perspective: if I have three buttons on the
title bar to control maximize, iconify & shade; they look like binary
pushbuttons and I don't expect them to work like radio buttons i.e. push
one in and the other two pop out. This is my view only, I'm not a GUI
expert. I expect different people would like different things.

> your cube, like <snip>

Agreed, you can enforce a four state thing from an eight state cube but
you can't do the opposite.

> which would then be used for the whole complex function ?

It's a feature of the module interface. It's not just FvwmTalk, it's all
modules that get fvwm to execute functions. When fvwm executes functions
from menus, keys or buttons it sets the target window up for the
function.  When a module sends a message to fvwm to execute a function
fvwm doesn't set the target window.  If you know the window ID you can
use "WindowID xxx MyMax", if it has a unique name you can use "Next
(<name>) MyMax". I can't think of a way of getting fvwm to prompt for a
window only once, it either has a target window or it doesn't and it
doesn't learn, this is probably linked to the reason that two Next's in
a function both select the same target i.e. you can't write a function
to iconify the next four windows on the windowlist.

Cheers,
Tim.

---

From: Matthias Clasen <[email-masked]>
Date: Sat, 16 Jan 1999 22:34:06 +0100

> to iconify the next four windows on the windowlist.

You mean like so ?

AddToFunc iconify-next-4
+ I Current Iconify 
+ I Next Focus
+ I Current Iconify 
+ I Next Focus
+ I Current Iconify 
+ I Next Focus
+ I Current Iconify 
+ I Prev Focus
+ I Prev Focus
+ I Prev Focus

---

From: Matthias Clasen <[email-masked]>
Date: Sat, 16 Jan 1999 22:35:20 +0100

> window only once, it either has a target window or it doesn't and it

I always found it annoying under RedHat's fvwm setup that
when I move an xclock by selecting Move from the Root menu,
I have to click 2 times on the root window to get rid of 
the extra select cursors (I guess "Move" is a complex function
with three lines in that setup).

This can be avoided with a new command "Pick <command>",
which behaves similarly to "Function <command>", but lets
the user pick a window to operate on instead of having
every single function in the complex function select its
own. 

The implementation is truly trivial.

Matthias

--- orig/builtins.c	Sat Jan 16 12:44:08 1999
+++ builtins.c	Sat Jan 16 13:17:29 1999
@@ -4630,6 +4630,18 @@
   FreeConditionMask(&mask);
 }
 
+/* A very simple function, but handy if you want to call 
+  complex functions from root context without selecting a window
+  for every single function in it. */
+void PickFunc(XEvent *eventp,Window w,FvwmWindow *tmp_win,
+              unsigned long context, char *action,int* Module)
+{
+  if (DeferExecution(eventp,&w,&tmp_win,&context, SELECT,ButtonRelease))
+    return;
+ 
+  ExecuteFunction(action, tmp_win, eventp, C_WINDOW, *Module);
+}
+
 void WindowIdFunc(XEvent *eventp,Window junk,FvwmWindow *tmp_win,
                   unsigned long context, char *action,int* Module)
 {
--- orig/functions.c	Sat Jan 16 12:44:54 1999
+++ functions.c	Sat Jan 16 13:05:22 1999
@@ -1,4 +1,3 @@
-e
 /****************************************************************************
  * This module is all original code
  * by Rob Nation
@@ -132,6 +131,7 @@
   {"None",         NoneFunc,         F_NONE,                FUNC_NO_WINDOW},
   {"Nop",          Nop_func,         F_NOP,                 FUNC_NO_WINDOW},
   {"OpaqueMoveSize", SetOpaque,      F_OPAQUE,              FUNC_NO_WINDOW},
+  {"Pick",         PickFunc,         F_PICK,                FUNC_NO_WINDOW},
   {"PipeRead",     PipeRead,         F_READ,                FUNC_NO_WINDOW},
   {"PixmapPath",   setPixmapPath,    F_PIXMAP_PATH,         FUNC_NO_WINDOW},
   {"PopUp",        popup_func,       F_POPUP,               FUNC_NO_WINDOW},
--- orig/misc.h	Sat Jan 16 20:43:46 1999
+++ misc.h	Sat Jan 16 12:46:52 1999
@@ -463,6 +463,7 @@
 void CurrentFunc(F_CMD_ARGS);
 void DirectionFunc(F_CMD_ARGS);
 void WindowIdFunc(F_CMD_ARGS);
+void PickFunc(F_CMD_ARGS);
 void ReadFile(F_CMD_ARGS);
 void PipeRead(F_CMD_ARGS);
 void module_zapper(F_CMD_ARGS);
--- orig/parse.h	Sat Jan 16 12:45:14 1999
+++ parse.h	Sat Jan 16 12:45:28 1999
@@ -65,6 +65,7 @@
     F_NEXT,
     F_PREV,
     F_NONE,
+    F_PICK,
     F_STAYSUP,
     F_RECAPTURE,
     F_CONFIG_LIST,

---

From: Matthias Clasen <[email-masked]>
Date: Sat, 16 Jan 1999 22:37:45 +0100

> expert. I expect different people would like different things.

Following our recent discussion about interaction of maximized,
shaded and iconic states, I have tried to make them as orthogonal
as possible. This patch (against todays CVS) does:

* Treat shaded as NormalState again, unlike my last patch on this 
  topic.

* Prevents client-side resizing of maximized windows. I think it
  is ugly to see a maximized xterm grow beyond the screen when
  I change the font. User-side resizing of maximized windows is
  still allowed. 

* Fix an off-by-one error when shading windows with FvwmBorder. It
  caused one pixel line of the client window to remain visible,
  making it possible to eg pop up the fonts menu on a shaded
  xterm. If you are interested in this as a bugfix for 2.2,
  it is only one line in builtins.c:

  Change the the second-to-last instruction in the WindowShade
  function from

	SetupFrame(tmp_win,
		   tmp_win->frame_x,
		   tmp_win->frame_y,
		   tmp_win->frame_width,
		   tmp_win->title_height + tmp_win->boundary_width, 
		   False);

  to

	SetupFrame(tmp_win,
		   tmp_win->frame_x,
		   tmp_win->frame_y,
		   tmp_win->frame_width,
		   tmp_win->title_height + tmp_win->boundary_width
                     - tmp_win->bw,
		   False);

* Make resize shade-smart, ie you can now resize a shaded window.
  It will remain shaded, but unshade to the new size. 

* Enable transitions between shaded, shaded+maximized and maximized.
  This unfortunately needs another set of "saved geometry" variables in the 
  FvwmWindow struct to make sure that you can unshade a shaded+maximized
  window to its maximized size and then unmaximize it to its original 
  size.

Matthias

--- borders.c	Sat Jan 16 21:06:17 1999
+++ changed/borders.c	Sat Jan 16 20:47:45 1999
@@ -1336,6 +1334,17 @@
     tmp_win->orig_wd = w;
     tmp_win->orig_ht = h;
   }
+  else if ((tmp_win->flags & MAXIMIZED)  
+#ifdef WINDOWSHADE
+	   && !shaded
+#endif
+	   )
+    {
+      tmp_win->maximized_x = x;
+      tmp_win->maximized_y = y;
+      tmp_win->maximized_wd = w;
+      tmp_win->maximized_ht = h;
+    }
 
   if((w != tmp_win->frame_width) || (h != tmp_win->frame_height))
     Resized = True;
--- builtins.c	Sat Jan 16 21:08:05 1999
+++ changed/builtins.c	Sat Jan 16 20:47:45 1999
@@ -326,11 +326,7 @@
   if(tmp_win == NULL)
     return;
 
-  if(check_allowed_function2(F_MAXIMIZE,tmp_win) == 0
-#ifdef WINDOWSHADE
-     || (tmp_win->buttons & WSHADE)
-#endif
-     )
+  if(check_allowed_function2(F_MAXIMIZE,tmp_win) == 0)
   {
     XBell(dpy, 0);
     return;
@@ -347,14 +343,35 @@
   if (tmp_win->flags & MAXIMIZED)
   {
     tmp_win->flags &= ~MAXIMIZED;
-    SetupFrame(tmp_win, tmp_win->orig_x, tmp_win->orig_y, tmp_win->orig_wd,
-               tmp_win->orig_ht,TRUE);
+    if (tmp_win->buttons & WSHADE)
+      {
+	new_x = tmp_win->orig_x;
+	new_y = tmp_win->orig_y;
+	new_width = tmp_win->orig_wd;
+	new_height = tmp_win->title_height + tmp_win->boundary_width 
+	  - tmp_win->bw;
+      }
+    else
+      {
+	new_x = tmp_win->orig_x;
+	new_y = tmp_win->orig_y;
+	new_width = tmp_win->orig_wd;
+	new_height = tmp_win->orig_ht;
+      }
+    SetupFrame(tmp_win, new_x, new_y, new_width, new_height, TRUE);
     SetBorder(tmp_win,True,True,True,None);
   }
   else
   {
     new_width = tmp_win->frame_width;
+    if (tmp_win->buttons & WSHADE) 
+      {
+	new_height = tmp_win->orig_ht;
+      } 
+    else
+      {
     new_height = tmp_win->frame_height;
+      }
     new_x = tmp_win->frame_x;
     new_y = tmp_win->frame_y;
     if(val1 >0)
@@ -376,8 +393,16 @@
     }
     tmp_win->flags |= MAXIMIZED;
     ConstrainSize (tmp_win, &new_width, &new_height, False, 0, 0);
+    if (tmp_win->buttons & WSHADE)
+      {
+        tmp_win->maximized_x = new_x;
+        tmp_win->maximized_y = new_y; 
+        tmp_win->maximized_wd = new_width; 
+        tmp_win->maximized_ht = new_height;
+        new_height = tmp_win->frame_height;
+      } 
     SetupFrame(tmp_win,new_x,new_y,new_width,new_height,TRUE);
-    SetBorder(tmp_win,Scr.Hilite == tmp_win,True,True,None);
+    /*   SetBorder(tmp_win,Scr.Hilite == tmp_win,True,True,None);*/
   }
 }
 
@@ -393,11 +418,12 @@
 		 unsigned long context, char *action, int *Module)
 {
     int n = 0;
+    int new_x, new_y, new_width, new_height;

-    if (!(tmp_win->flags & TITLE) || (tmp_win->flags & MAXIMIZED)) {
+    if (!(tmp_win->flags & TITLE)) {
 	XBell(dpy, 0);
 	return;
     }
@@ -408,12 +434,21 @@
     if (((tmp_win->buttons & WSHADE)||(n==2))&&(n!=1))
     {
 	tmp_win->buttons &= ~WSHADE;
-	SetupFrame(tmp_win,
-		   tmp_win->frame_x,
-		   tmp_win->frame_y,
-		   tmp_win->orig_wd,
-		   tmp_win->orig_ht,
-		   True);
+	if (tmp_win->flags & MAXIMIZED) 
+	  {
+	    new_x = tmp_win->maximized_x;
+	    new_y = tmp_win->maximized_y;
+	    new_width = tmp_win->maximized_wd;
+	    new_height = tmp_win->maximized_ht;
+	  }
+	else
+	  {
+	    new_x = tmp_win->frame_x;
+	    new_y = tmp_win->frame_y;
+	    new_width = tmp_win->orig_wd;
+	    new_height = tmp_win->orig_ht;
+	  }
+	SetupFrame(tmp_win, new_x, new_y, new_width, new_height, True);
         BroadcastPacket(M_DEWINDOWSHADE, 3,
                         tmp_win->w, tmp_win->frame, (unsigned long)tmp_win);
     }
@@ -424,7 +459,8 @@
 		   tmp_win->frame_x,
 		   tmp_win->frame_y,
 		   tmp_win->frame_width,
-		   tmp_win->title_height + tmp_win->boundary_width,
+		   tmp_win->title_height + tmp_win->boundary_width 
+		   - tmp_win->bw,
 		   False);
         BroadcastPacket(M_WINDOWSHADE, 3,
                         tmp_win->w, tmp_win->frame, (unsigned long)tmp_win);
--- events.c	Sat Jan 16 21:09:08 1999
+++ changed/events.c	Sat Jan 16 20:50:12 1999
@@ -1476,7 +1476,18 @@
   ConstrainSize(Tmp_win, &width, &height, False, 0, 0);
 DB(("HandleConfigureRequest: after ConstrainSize: width=%d, height=%d",width,height));
 DB(("HandleConfigureRequest: calling SetupFrame"));
+ if (Tmp_win->buttons & WSHADE) 
+   {
+     Tmp_win->orig_x = x;
+     Tmp_win->orig_y = y;
+     Tmp_win->orig_wd = width;
+     Tmp_win->orig_ht = height;
+     SetupFrame (Tmp_win, x, y, width, Tmp_win->frame_height,sendEvent);
+   } 
+ else if (!(Tmp_win->flags & MAXIMIZED))
+   {
   SetupFrame (Tmp_win, x, y, width, height,sendEvent);
+   }
 DB(("HandleConfigureRequest: calling KeepOnTop"));
   KeepOnTop();
 DB(("HandleConfigureRequest: finished 2"));
--- fvwm.h	Sat Jan 16 21:09:14 1999
+++ changed/fvwm.h	Sat Jan 16 20:47:49 1999
@@ -258,10 +258,10 @@
 #endif
     char *icon_bitmap_file;
 
-    int orig_x;                 /* unmaximized x coordinate */
-    int orig_y;                 /* unmaximized y coordinate */
-    int orig_wd;                /* unmaximized window width */
-    int orig_ht;                /* unmaximized window height */
+    int orig_x;                 
+    int orig_y;                 
+    int orig_wd;                
+    int orig_ht;                
 
     int xdiff,ydiff;            /* used to restore window position on exit*/
     int *mwm_hints;
@@ -275,6 +275,11 @@
     Pixel BackPixel;
     unsigned long buttons;
     icon_boxes *IconBoxes;              /* zero or more iconboxes */
+
+    int maximized_x;                 
+    int maximized_y;                 
+    int maximized_wd;                
+    int maximized_ht;                
 } FvwmWindow;
 
 /* Window mask for Circulate and Direction functions */
--- resize.c	Sat Jan 16 21:09:32 1999
+++ changed/resize.c	Sat Jan 16 20:52:21 1999
@@ -71,11 +71,7 @@
 		 &JunkX, &JunkY, &JunkX, &JunkY, &button_mask);
   button_mask &= Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask;
 
-  if(check_allowed_function2(F_RESIZE,tmp_win) == 0
-#ifdef WINDOWSHADE
-     || (tmp_win->buttons & WSHADE)
-#endif
-     )
+  if(check_allowed_function2(F_RESIZE,tmp_win) == 0)
     {
       XBell(dpy, 0);
       return;
@@ -84,13 +80,6 @@
 
   tmp_win->flags &= ~MAXIMIZED;
 
-  /* Already checked this in functions.c, but its here too incase
-   * there's a resize on initial placement. */
-  if(check_allowed_function2(F_RESIZE,tmp_win) == 0)
-    {
-      XBell(dpy, 0);
-      return;
-    }
   /* can't resize icons */
   if(tmp_win->flags & ICONIFIED)
     return;
@@ -107,8 +96,19 @@
       /* size will be less or equal to requested */
       ConstrainSize (tmp_win, &drag->width, &drag->height, False, xmotion,
 		     ymotion);
+      if (tmp_win->buttons & WSHADE) 
+	{
+	  tmp_win->orig_wd = drag->width;
+	  tmp_win->orig_ht = drag->height;
+	  SetupFrame (tmp_win, tmp_win->frame_x, tmp_win->frame_y,
+		      drag->width, tmp_win->frame_height,FALSE);
+	} 
+      else 
+	{
       SetupFrame (tmp_win, tmp_win->frame_x,
 		  tmp_win->frame_y ,drag->width, drag->height,FALSE);
+	}
+      SetBorder(tmp_win,True,True,True,None);
 
       ResizeWindow = None;
       return;
@@ -129,9 +129,19 @@
   flags = Scr.flags;
   Scr.flags &= ~(EdgeWrapX|EdgeWrapY);
 
+  if (tmp_win->buttons & WSHADE) 
+    {
+      drag->x = tmp_win->frame_x;
+      drag->y = tmp_win->frame_y;
+      drag->width = tmp_win->orig_wd;
+      drag->height = tmp_win->orig_ht;
+    } 
+  else 
+    {
   XGetGeometry(dpy, (Drawable) ResizeWindow, &JunkRoot,
 	       &drag->x, &drag->y, (unsigned int *)&drag->width,
 	       (unsigned int *)&drag->height, &JunkBW,&JunkDepth);
+    }
 
   drag->x += tmp_win->bw;
   drag->y += tmp_win->bw;
@@ -297,9 +307,22 @@
       /* size will be >= to requested */
       ConstrainSize (tmp_win, &drag->width, &drag->height, True, xmotion,
 		     ymotion);
+      if (tmp_win->buttons & WSHADE) 
+	{
+	  tmp_win->orig_x = drag->x - tmp_win->bw;
+	  tmp_win->orig_y = drag->y - tmp_win->bw;
+	  tmp_win->orig_wd = drag->width;
+	  tmp_win->orig_ht = drag->height;
+	  SetupFrame (tmp_win, tmp_win->orig_x, tmp_win->orig_y,
+		      drag->width, tmp_win->frame_height, FALSE);
+	} 
+      else 
+	{
       SetupFrame (tmp_win, drag->x - tmp_win->bw,
 		  drag->y - tmp_win->bw, drag->width, drag->height,FALSE);
     }
+      SetBorder(tmp_win,True,True,True,None);
+    }
   UninstallRootColormap();
   ResizeWindow = None;
   MyXUngrabServer(dpy);
@@ -602,9 +625,11 @@
      */
     *widthp = dwidth + 2*tmp_win->boundary_width;
     *heightp = dheight + tmp_win->title_height + 2*tmp_win->boundary_width;
+#if 0
 #ifdef WINDOWSHADE
     if (tmp_win->buttons & WSHADE)
       *heightp = tmp_win->title_height + tmp_win->boundary_width;
+#endif
 #endif
 
 DB(("ConstrainSize: final width=%d, final height=%d",*widthp,*heightp));

---

From: Tim Phipps <[email-masked]>
Date: Mon, 18 Jan 1999 10:52:07 +0000

Matthias Clasen wrote:
> <working example of what I thought was imposible>

Err, yes.  I didn't think you could do that.  I remember trying

+ I Next Iconify
+ I Next Iconify

and giving up.

Cheers,
Tim.
--
Visit the official FVWM web page at <URL:http://fvwm.math.uh.edu/>.
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].