Subject: Re: Patch: Window group support

From: Matthias Clasen <[email-masked]>
Date: Sat, 9 Jan 1999 00:51:41 +0100

Oops, that was a thinko. It is certainly not a good idea to 
execute functions which may change the window list while looping
over that list. Here is a corrected version of AllFunc. And
yes, the new conditions are available for all functions which
take conditions.

Matthias

--- builtins.c.orig	Fri Jan  1 21:50:51 1999
+++ builtins.c	Fri Jan  8 23:49:49 1999
@@ -39,6 +39,17 @@
 #endif
 };
 
+/* This is enabled during operation on multiple windows at one
+  (the "All" command), since it is annoying to get 5 beeps from
+  5 windows not allowing to be iconized. 
+*/
+static int fail_silently = 0;
+
+void FunctionNotAllowed(void)
+{
+   if (!fail_silently) XBell(dpy, 0);
+}
+
 /***********************************************************************
  *
  *  Procedure:
@@ -332,7 +343,7 @@
 #endif
      )
   {
-    XBell(dpy, 0);
+    FunctionNotAllowed();
     return;
   }
   n = GetTwoArguments(action, &val1, &val2, &val1_unit, &val2_unit);
@@ -398,8 +409,8 @@
 	return;
 
     if (!(tmp_win->flags & TITLE) || (tmp_win->flags & MAXIMIZED)) {
-	XBell(dpy, 0);
-	return;
+      FunctionNotAllowed();
+      return;
     }
     while (isspace(*action))++action;
     if (isdigit(*action))
@@ -691,20 +702,53 @@
 
   GetIntegerArguments(action, NULL, &val, 1);
 
-  if (tmp_win->flags & ICONIFIED)
+  /* Moved the check to cover both cases. We want to disallow
+     deiconification of artificial group leader icons. */
+  if(check_allowed_function2(F_ICONIFY,tmp_win)==0) 
+    {
+      FunctionNotAllowed();
+      return;
+    }
+  else
+    {
+      if (tmp_win->flags & ICONIFIED)
+	{
+	  if(val <=0)
+	    DeIconify(tmp_win);
+	}
+      else
+	{
+	  if(val >=0)
+	    Iconify(tmp_win,eventp->xbutton.x_root-5,eventp->xbutton.y_root-5);
+	}
+    }
+}
+
+void iconify_group_function(XEvent *eventp,Window w,FvwmWindow *tmp_win,
+		            unsigned long context,char *action, int *Module)
+
+{
+  int val = 0;
+
+  if (DeferExecution(eventp,&w,&tmp_win,&context, SELECT, ButtonRelease))
+    return;
+
+  GetIntegerArguments(action, NULL, &val, 1);
+
+  if (tmp_win->tmpflags.GroupIconified)
   {
     if(val <=0)
-      DeIconify(tmp_win);
+      DeIconifyGroup(tmp_win);
   }
   else
   {
-    if(check_allowed_function2(F_ICONIFY,tmp_win) == 0)
+    if(check_allowed_function2(F_ICONIFY_GROUP,tmp_win) == 0)
     {
-      XBell(dpy, 0);
+      FunctionNotAllowed();
       return;
     }
     if(val >=0)
-      Iconify(tmp_win,eventp->xbutton.x_root-5,eventp->xbutton.y_root-5);
+      IconifyGroup(tmp_win,eventp->xbutton.x_root-5,eventp->xbutton.y_root-5);
   }
 }
 
@@ -745,7 +789,7 @@
 
   if(check_allowed_function2(F_DESTROY,tmp_win) == 0)
   {
-    XBell(dpy, 0);
+    FunctionNotAllowed();
     return;
   }
 
@@ -765,7 +809,7 @@
 
   if(check_allowed_function2(F_DELETE,tmp_win) == 0)
   {
-    XBell(dpy, 0);
+    FunctionNotAllowed();
     return;
   }
 
@@ -775,7 +819,7 @@
     return;
   }
   else
-    XBell (dpy, 0);
+    FunctionNotAllowed();
   XSync(dpy,0);
 }
 
@@ -787,7 +831,7 @@
 
   if(check_allowed_function2(F_CLOSE,tmp_win) == 0)
   {
-    XBell(dpy, 0);
+    FunctionNotAllowed();
     return;
   }
 
@@ -4123,6 +4167,11 @@
   mask->useCirculateHitIcon = 0;
   mask->onFlags = 0;
   mask->offFlags = 0;
+  mask->leader = None;
+  mask->needsGroup = 0;
+  mask->needsNotGroup = 0;
+  mask->needsLeader = 0;
+  mask->needsNotLeader = 0;
 }
 
 /**********************************************************************
@@ -4144,7 +4193,15 @@
 
   while (condition)
   {
-    if (StrEquals(condition,"Iconic"))
+    if (StrEquals(condition,"Group"))
+      mask->needsGroup = 1;
+    else if (StrEquals(condition,"!Group"))
+      mask->needsNotGroup = 1;
+    else if (StrEquals(condition,"Leader"))
+      mask->needsLeader = 1;
+    else if (StrEquals(condition,"!Leader"))
+      mask->needsNotLeader = 1;
+    else if (StrEquals(condition,"Iconic"))
       mask->onFlags |= ICONIFIED;
     else if(StrEquals(condition,"!Iconic"))
       mask->offFlags |= ICONIFIED;
@@ -4196,6 +4253,21 @@
 	mask->needsName = 1;
     }
 
+    if (mask->needsGroup || mask->needsNotGroup ||
+        mask->needsLeader || mask->needsNotLeader) 
+      {
+	if ((Scr.Focus != NULL) &&
+	    (Scr.Focus->wmhints != NULL) &&
+	    (Scr.Focus->wmhints->flags & WindowGroupHint))
+	  {
+	    mask->leader = Scr.Focus->wmhints->window_group;
+	    if (mask->leader == Scr.Root) 
+	      {
+		mask->leader = None;
+	      }
+	  }
+      }
+    
     if (prev_condition)
       free(prev_condition);
 
@@ -4218,6 +4290,7 @@
   Bool fMatchesClass;
   Bool fMatchesResource;
   Bool fMatches;
+  Window fleader;
 
   if ((mask->onFlags & fw->flags) != mask->onFlags)
     return 0;
@@ -4263,6 +4336,28 @@
   if (mask->needsNotName && fMatches)
     return 0;
 
+  fleader = None;
+  if (fw->wmhints && (fw->wmhints->flags & WindowGroupHint))
+    {
+      fleader = fw->wmhints->window_group;
+      if (fleader == Scr.Root) 
+	{
+	  fleader = None;
+	}
+    }
+
+  if (mask->needsLeader && (mask->leader != fw->w))
+    return 0;
+
+  if (mask->needsNotLeader && (mask->leader == fw->w) && (fw->w != None))
+    return 0;
+
+  if (mask->needsGroup && (mask->leader != fleader))
+    return 0;
+
+  if (mask->needsNotGroup && (mask->leader == fleader) && (fleader != None))
+    return 0;
+      
   return 1;
 }
 
@@ -4403,6 +4498,49 @@
   }
 }
 
+void AllFunc(XEvent *eventp, Window junk, FvwmWindow *tmp_win,
+              unsigned long context, char *action,int* Module)
+{
+  FvwmWindow *t, **g;
+  char *restofline;
+  WindowConditionMask mask;
+  char *flags;
+  int num, i;
+
+  flags = CreateFlagString(action, &restofline);
+  DefaultConditionMask(&mask);
+  CreateConditionMask(flags, &mask);
+  mask.useCirculateHit = 1;
+  mask.useCirculateHitIcon = 1;
+
+  num = 0;
+  for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) 
+    {
+       num++;
+    }
+
+  g = (FvwmWindow **) malloc (num * sizeof(FvwmWindow *));
+ 
+  num = 0;
+  for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) 
+    {
+      if (MatchesConditionMask(t, &mask)) 
+	{
+          g[num++] = t;
+        }
+    }
+  
+  fail_silently = 1;
+  for (i = 0; i < num; i++)
+    {
+       ExecuteFunction(restofline,g[i],eventp,C_WINDOW,*Module);
+    }
+  fail_silently = 0;
+
+  free (g);
+  FreeConditionMask(&mask);
+}
+	       
 static void GetDirectionReference(FvwmWindow *w, int *x, int *y)
 {
   if ((w->flags & ICONIFIED) != 0)

-- 
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: Dan Espen <[email-masked]>
Date: Sat, 09 Jan 1999 17:19:39 -0500

> yes, the new conditions are available for all functions which

I don't think I've seen any discussion about whether this patch
is 2.2 material.  My impression is that its a large enough change
that it is definitely not 2.2 material.

--
Dan Espen
444 Hoes Lane  Room RRC 1C-214           E-mail: [email-masked]
Piscataway, NJ 08854                     Phone: (732) 699-5570
--
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: Sun, 10 Jan 1999 00:07:55 +0100

> that it is definitely not 2.2 material.

No, it won't get into 2.2.

Bye

Dominik

--
Dominik Vogt, [email-masked]
Reply-To: [email-masked]