Subject: FVWM: fvwm 2.0.46: patches and bugs

From: Grant McDorman <[email-masked]>
Date: Tue, 26 Aug 1997 14:31:02 -0400 (EDT)

-----BEGIN PGP SIGNED MESSAGE-----

I have just finished installing - and patching - 2.0.46.

The patches (attached) are as follows:
   modules:
      FvwmWinList:  do not call ShutMeDown in DeadPipe, just exit (to avoid
                    FvwmWinList looping)
      FvwmAudio:    ditto
      FvwmIconBox:  ditto, may need more work if the XDeleteProperty is needed
      FvwmIconMan:  ditto
      FvwmButtons:  do not do X calls in signal handling; also, allow
                    "swallowmodule" as well as "swallow" in FvwmGoodStuff
                    compatiblity [this patch previously submitted against
                    2.0.43]

   fvwm:
     colormaps.c: If, on Sun systems, TRUECOLOR_ALWAYS_INSTALLED is defined,
                  do not install a 24-bit TrueColor colormap. (Despite what
                  the server says, it is always installed.)
     add_window.c: Instead of doing button grabs for click-to-focus using no
                  modifiers and Caps Lock, use AnyModifer
     events.c:    Button press handing: Check for user-defined button action
                  first, then allow click-to-focus/click-to-raise with any
                  modifier.
     placement.c: If a transient has no position specified, fall back to
                  random/smart placement (as per configuration) instead of
                  placing the transient at 0,0

   extras:
     FvwmTaskBar: fixes for signal handling like those above

Other "extras" programs require fixes for signal handling, including (at least)
FvwmWharf. If these programs are not fixed, they can go into a loop when fvwm
is terminated or the X server reset (i.e. logout). I would suggest these
programs be removed from the release, or at least have a very strong warning
attached, until they are fixed.

Grant McDorman <[email-masked]>
ISG Technologies, Inc.  http://www.isgtec.com
Mississauga, Ontario, Canada

*** fvwm-2.0.46/modules/FvwmWinList/FvwmWinList.c.orig	Wed Aug  6 16:19:28 1997
--- fvwm-2.0.46/modules/FvwmWinList/FvwmWinList.c	Tue Aug 26 11:56:22 1997
***************
*** 457,463 ****
   **********************************************************************/
  void DeadPipe(int nonsense)
  {
!   ShutMeDown(1);
  }
  
  /*****************************************************************************
*
--- 457,467 ----
   **********************************************************************/
  void DeadPipe(int nonsense)
  {
!     /*
!      * do not call ShutMeDown, it may make X calls which are not allowed
!      * in a signal hander.
!      */
!   exit(1);
  }
  
  /*****************************************************************************
*
*** fvwm-2.0.46/modules/FvwmAudio/FvwmAudio.c.orig	Fri Jan 17 11:10:49 1997
--- fvwm-2.0.46/modules/FvwmAudio/FvwmAudio.c	Tue Aug 26 11:48:53 1997
***************
*** 469,474 ****
--- 469,479 ----
   ***********************************************************************/
  void DeadPipe(int nonsense)
  {
+     /*
+      * In most cases, the only legal operation here is to exit. However,
+      * for this module done(0) is acceptable since all done does is
+      * to play an audio sample [see below].
+      */
  	done(0);
  }
  
*** fvwm-2.0.46/modules/FvwmIconBox/FvwmIconBox.c.orig	Thu Jan  2 15:19:31 1997
--- fvwm-2.0.46/modules/FvwmIconBox/FvwmIconBox.c	Tue Aug 26 11:51:38 1997
***************
*** 1419,1427 ****
      tmpi = tmpi->next;
      freeitem(tmpi2, 0);
    }
!   if ((local_flags & SETWMICONSIZE))
!     XDeleteProperty(dpy, Root, XA_WM_ICON_SIZE); 
!   XSync(dpy,0);
    exit(0);
  }
  
--- 1419,1431 ----
      tmpi = tmpi->next;
      freeitem(tmpi2, 0);
    }
!   /*
!    * This cannot be done in a signal handler.
!    */
! /*  if ((local_flags & SETWMICONSIZE))
!  *   XDeleteProperty(dpy, Root, XA_WM_ICON_SIZE); 
!  * XSync(dpy,0);
!  */
    exit(0);
  }
  
*** fvwm-2.0.46/modules/FvwmButtons/FvwmButtons.c.orig	Thu Jun 26 17:32:31 1997
--- fvwm-2.0.46/modules/FvwmButtons/FvwmButtons.c	Tue Aug 26 11:46:29 1997
***************
*** 27,32 ****
--- 27,33 ----
  #include <string.h>
  #include <sys/wait.h>
  #include <sys/time.h>
+ #include <sys/stat.h>
  #if defined ___AIX || defined _AIX || defined __QNX__ || defined ___AIXV3 || d
efined AIXV3 || defined _SEQUENT_
  #include <sys/select.h>
  #endif
***************
*** 78,83 ****
--- 79,85 ----
  /* ------------------------------ prototypes ------------------------------- *
/
  
  void DeadPipe(int nonsense);
+ void CleanUp(void);
  void SetButtonSize(button_info*,int,int);
  /* main */
  void Loop(void);
***************
*** 126,131 ****
--- 128,135 ----
  GC  NormalGC;
  int Width,Height;
  
+ int running = 1;
+ 
  int x= -30000,y= -30000,w= -1,h= -1,gravity = NorthWestGravity;
  int new_desk = 0;
  int ready = 0;
***************
*** 173,185 ****
  **/
  void DeadPipe(int whatever)
  {
    button_info *b,*ub=UberButton;
    int button=-1;
  
-   signal(SIGPIPE, SIG_IGN);/* Xsync may cause SIGPIPE */
- 
    XSync(Dpy,0); /* Wait for thing to settle down a bit */
    XGrabServer(Dpy); /* We don't want interference right now */
    while(NextButton(&ub,&b,&button,0))
      {
        /* delete swallowed windows */
--- 177,220 ----
  **/
  void DeadPipe(int whatever)
  {
+   struct stat buf;
+     
+   /*
+    * If a SIGPIPE arrives during this operation, just exit.
+    *  - the signal will probably because the server is shutting
+    *    down. Attempting to do any further processing is useless
+    *    and may in fact, on some platforms, put the process into
+    *    a tight loop (if SIGPIPE is ignored).
+    * 22 July 1996 GRM.
+    * 
+    * Further investigation: XSync may loop *without* causing a SIGPIPE.
+    * This may be because the connection is dead, or because of the
+    * fact that X operations in signal handlers are discouraged.
+    * 
+    * In order to cover all the bases, then, this function will now
+    * set a global flag which will cause the main loop to stop.
+    *
+    * SIGPIPE is reset to DeadPipe, as well.
+    */
+   signal(SIGPIPE, DeadPipe);
+ 
+   /*
+    * Try to check status of X connection.
+    */
+   if (fstat(XConnectionNumber(Dpy), &buf) == -1)
+       exit(0);
+   
+   running = 0;
+ }
+ 
+ void CleanUp(void)
+ {
    button_info *b,*ub=UberButton;
    int button=-1;
  
    XSync(Dpy,0); /* Wait for thing to settle down a bit */
    XGrabServer(Dpy); /* We don't want interference right now */
+ 
    while(NextButton(&ub,&b,&button,0))
      {
        /* delete swallowed windows */
***************
*** 587,593 ****
    int ex=10000,ey=10000,ex2=0,ey2=0;
  #endif
  
!   while(1)
      {
        if(My_XNextEvent(Dpy,&Event))
  	{
--- 622,628 ----
    int ex=10000,ey=10000,ex2=0,ey2=0;
  #endif
  
!   while(running)
      {
        if(My_XNextEvent(Dpy,&Event))
  	{
***************
*** 814,819 ****
--- 849,855 ----
  	  }
        }
      }
+     CleanUp();
  }
  
  /**
*** fvwm-2.0.46/modules/FvwmButtons/parse.c.orig	Thu Jun 26 17:32:33 1997
--- fvwm-2.0.46/modules/FvwmButtons/parse.c	Tue Aug 26 11:44:18 1997
***************
*** 670,675 ****
--- 670,682 ----
  	  exit(1);
  	}
        s+=7;
+       /*
+        * Swallow old 'swallowmodule' command
+        */
+       if (mystrncasecmp(s,"module",6)==0)
+       {
+           s+=6;
+       }
        b->hangon=seekright(&s);
        b->flags|=(b_Swallow|b_Hangon);
        b->swallow|=1;
*** fvwm-2.0.46/modules/FvwmIconMan/FvwmIconMan.c.orig	Wed Jul 16 21:31:21 1997
--- fvwm-2.0.46/modules/FvwmIconMan/FvwmIconMan.c	Tue Aug 26 11:53:22 1997
***************
*** 96,102 ****
  void DeadPipe (int nothing)
  {
    ConsoleDebug (CORE, "Bye Bye\n");
!   ShutMeDown (0);
  }
  
  void SendFvwmPipe (char *message,unsigned long window)
--- 96,107 ----
  void DeadPipe (int nothing)
  {
    ConsoleDebug (CORE, "Bye Bye\n");
!   /*
!    * ShutMeDown is not called because most operations, especially X
!    * calls, are not allowed in signal handlers. Currently, of course,
!    * ShutMeDown doesn't do anything significant, but it may in future.
!    */
!   exit (0);
  }
  
  void SendFvwmPipe (char *message,unsigned long window)
*** fvwm-2.0.46/fvwm/colormaps.c.orig	Fri Apr 28 08:38:32 1995
--- fvwm-2.0.46/fvwm/colormaps.c	Tue Aug 26 12:03:50 1997
***************
*** 152,159 ****
  	  if(w == tmp->w)
  	    ThisWinInstalled = True;
  	  XGetWindowAttributes(dpy,w,&attributes);
! 	  
! 	  if(last_cmap != attributes.colormap)
  	    {
  	      last_cmap = attributes.colormap;
  	      XInstallColormap(dpy,attributes.colormap);    
--- 152,168 ----
  	  if(w == tmp->w)
  	    ThisWinInstalled = True;
  	  XGetWindowAttributes(dpy,w,&attributes);
! 
!             /*
!              * On Sun X servers, don't install 24 bit TrueColor colourmaps.
!              * Despite what the server says, these colourmaps are always
!              * installed.
!              */
! 	  if(last_cmap != attributes.colormap
! #if defined(sun) && defined(TRUECOLOR_ALWAYS_INSTALLED)
!              && !(attributes.depth == 24 && attributes.visual->class == TrueCo
lor)
! #endif
!              )
  	    {
  	      last_cmap = attributes.colormap;
  	      XInstallColormap(dpy,attributes.colormap);    
***************
*** 163,169 ****
  
    if(!ThisWinInstalled)
      {
!       if(last_cmap != tmp->attr.colormap)
  	{
  	  last_cmap = tmp->attr.colormap;
  	  XInstallColormap(dpy,tmp->attr.colormap);    
--- 172,182 ----
  
    if(!ThisWinInstalled)
      {
!       if(last_cmap != tmp->attr.colormap
! #if defined(sun) && defined(TRUECOLOR_ALWAYS_INSTALLED)
!          && !(attributes.depth == 24 && attributes.visual->class == TrueColor)
! #endif
!         )
  	{
  	  last_cmap = tmp->attr.colormap;
  	  XInstallColormap(dpy,tmp->attr.colormap);    
*** fvwm-2.0.46/fvwm/add_window.c.orig	Wed Aug  6 15:35:12 1997
--- fvwm-2.0.46/fvwm/add_window.c	Tue Aug 26 11:25:56 1997
***************
*** 656,667 ****
        for(i=0;i<3;i++)
  	if(Scr.buttons2grab & (1<<i))
  	  {
! 	    XGrabButton(dpy,(i+1),0,tmp_win->frame,True,
! 			ButtonPressMask, GrabModeSync,GrabModeAsync,None,
! 			Scr.FvwmCursors[SYS]);
! 	    XGrabButton(dpy,(i+1),LockMask,tmp_win->frame,True,
  			ButtonPressMask, GrabModeSync,GrabModeAsync,None,
  			Scr.FvwmCursors[SYS]);
  	  }
      }
    BroadcastConfig(M_ADD_WINDOW,tmp_win);
--- 656,669 ----
        for(i=0;i<3;i++)
  	if(Scr.buttons2grab & (1<<i))
  	  {
!               /* accept any modifier on this button */
! 	    XGrabButton(dpy,(i+1),AnyModifier,tmp_win->frame,True,
  			ButtonPressMask, GrabModeSync,GrabModeAsync,None,
  			Scr.FvwmCursors[SYS]);
+ /*	    XGrabButton(dpy,(i+1),LockMask,tmp_win->frame,True,
+  *			ButtonPressMask, GrabModeSync,GrabModeAsync,None,
+  *			Scr.FvwmCursors[SYS]);
+  */
  	  }
      }
    BroadcastConfig(M_ADD_WINDOW,tmp_win);
*** fvwm-2.0.46/fvwm/decorations.c.orig	Mon Aug  4 16:52:51 1997
--- fvwm-2.0.46/fvwm/decorations.c	Tue Aug 26 11:29:57 1997
***************
*** 589,594 ****
--- 589,598 ----
       (!(t->functions & MWM_FUNC_CLOSE)))
      return 0;
  
+   if((function == F_CLOSE)&&(t)&&
+      (!(t->functions & MWM_FUNC_CLOSE)))
+     return 0;
+ 
    if((function == F_DESTROY)&&(t)&&
       (!(t->functions & MWM_FUNC_CLOSE)))
      return 0;
*** fvwm-2.0.46/fvwm/events.c.orig	Thu Aug  7 11:14:22 1997
--- fvwm-2.0.46/fvwm/events.c	Tue Aug 26 12:13:14 1997
***************
*** 968,1035 ****
    
    DBUG("HandleButtonPress","Routine Entered");
  
!   /* click to focus stuff goes here */
!   if((Tmp_win)&&(Tmp_win->flags & ClickToFocus)&&(Tmp_win != Scr.Ungrabbed) &&
!      ((Event.xbutton.state&
!        (ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) == 0))
    {
!     if(Tmp_win)
      {
!       SetFocus(Tmp_win->w,Tmp_win,1);
  /* #ifdef CLICKY_MODE_1 */
!       if (Scr.ClickToFocusRaises ||
!           ((Event.xany.window != Tmp_win->w)&&
!            (Event.xbutton.subwindow != Tmp_win->w)&&
!            (Event.xany.window != Tmp_win->Parent)&&
!            (Event.xbutton.subwindow != Tmp_win->Parent)))
  /* #endif */
!       {
!         RaiseWindow(Tmp_win);
!       }
        
!       KeepOnTop();
  
        /* Why is this here? Seems to cause breakage with
         * non-focusing windows! */
!       if(!(Tmp_win->flags & ICONIFIED))
!       {
!         XSync(dpy,0);
!         /* pass click event to just clicked to focus window? */
!         if (Scr.ClickToFocusPassesClick)
!           XAllowEvents(dpy,ReplayPointer,CurrentTime);
!         else /* don't pass click to just focused window */
!           XAllowEvents(dpy,AsyncPointer,CurrentTime);
!         XSync(dpy,0);
!         return;
!       }
        
      }
!   }
!   else if ((Tmp_win) && !(Tmp_win->flags & ClickToFocus) &&
!            (Event.xbutton.window == Tmp_win->frame) &&
!           Scr.MouseFocusClickRaises)
!   {
!     if (Tmp_win != Scr.LastWindowRaised &&
!         (Event.xbutton.state &
!          (ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) == 0 &&
!         GetContext(Tmp_win,&Event, &PressedW) == C_WINDOW)
      {
!       RaiseWindow(Tmp_win);
!       KeepOnTop();
      }
-     XSync(dpy,0);
-     XAllowEvents(dpy,ReplayPointer,CurrentTime);
-     XSync(dpy,0);
-     return;
    }
  
-   XSync(dpy,0);
-   XAllowEvents(dpy,ReplayPointer,CurrentTime);
-   XSync(dpy,0);
-   
-   Context = GetContext(Tmp_win,&Event, &PressedW);
-   LocalContext = Context;
-   x= PressedW;
    if(Context == C_TITLE)
      SetTitleBar(Tmp_win,(Scr.Hilite == Tmp_win),False);
    else
--- 968,1058 ----
    
    DBUG("HandleButtonPress","Routine Entered");
  
!   /*
!    * First, look for button bindings.
!    */
!   Context = GetContext(Tmp_win,&Event, &PressedW);
!   LocalContext = Context;
!   x= PressedW;
! 
!   /* we have to execute a function or pop up a menu
!    */
!   
!   modifier = (Event.xbutton.state & mods_used);
!   /* need to search for an appropriate mouse binding */
!   for (MouseEntry = Scr.AllBindings; MouseEntry != NULL;
!        MouseEntry= MouseEntry->NextBinding)
    {
!     if(((MouseEntry->Button_Key == Event.xbutton.button)||
!         (MouseEntry->Button_Key == 0))&&
!        (MouseEntry->Context & Context)&&
!        ((MouseEntry->Modifier == AnyModifier)||
!         (MouseEntry->Modifier == (modifier& (~LockMask))))&&
!        (MouseEntry->IsMouse == 1))
      {
!       /* got a match ... save it and exit loop */
!       break;
!     }
!   }
! 
!   /*
!    * do no click to focus if a mouse function was found
!    */
!   if (MouseEntry == NULL) {
!     /* click to focus stuff goes here */
!     /* any modifier is acceptable for click-to-focus */
!     if((Tmp_win)&&(Tmp_win->flags & ClickToFocus)&&(Tmp_win != Scr.Ungrabbed))
!     {
!       if(Tmp_win)
!       {
!         SetFocus(Tmp_win->w,Tmp_win,1);
  /* #ifdef CLICKY_MODE_1 */
!           if (Scr.ClickToFocusRaises ||
!               ((Event.xany.window != Tmp_win->w)&&
!                (Event.xbutton.subwindow != Tmp_win->w)&&
!                (Event.xany.window != Tmp_win->Parent)&&
!                (Event.xbutton.subwindow != Tmp_win->Parent)))
  /* #endif */
!           {
!             RaiseWindow(Tmp_win);
!           }
        
!           KeepOnTop();
  
        /* Why is this here? Seems to cause breakage with
         * non-focusing windows! */
!           if(!(Tmp_win->flags & ICONIFIED))
!           {
!             XSync(dpy,0);
!               /* pass click event to just clicked to focus window? */
!               if (Scr.ClickToFocusPassesClick)
!                 XAllowEvents(dpy,ReplayPointer,CurrentTime);
!               else /* don't pass click to just focused window */
!                 XAllowEvents(dpy,AsyncPointer,CurrentTime);
!               XSync(dpy,0);
!               return;
!           }
        
+       }
      }
!     else if ((Tmp_win) && !(Tmp_win->flags & ClickToFocus) &&
!              (Event.xbutton.window == Tmp_win->frame) &&
!              Scr.MouseFocusClickRaises)
      {
!         /* click-to-raise. Again, ignore any modifiers. */
!         if (Tmp_win != Scr.LastWindowRaised &&
!             GetContext(Tmp_win,&Event, &PressedW) == C_WINDOW)
!         {
!             RaiseWindow(Tmp_win);
!             KeepOnTop();
!         }
!         XSync(dpy,0);
!         XAllowEvents(dpy,ReplayPointer,CurrentTime);
!         XSync(dpy,0);
!         return;
      }
    }
  
    if(Context == C_TITLE)
      SetTitleBar(Tmp_win,(Scr.Hilite == Tmp_win),False);
    else
***************
*** 1037,1062 ****
    
    ButtonWindow = Tmp_win;
    
!   /* we have to execute a function or pop up a menu
!    */
!   
!   modifier = (Event.xbutton.state & mods_used);
!   /* need to search for an appropriate mouse binding */
!   for (MouseEntry = Scr.AllBindings; MouseEntry != NULL;
!        MouseEntry= MouseEntry->NextBinding)
!   {
!     if(((MouseEntry->Button_Key == Event.xbutton.button)||
!         (MouseEntry->Button_Key == 0))&&
!        (MouseEntry->Context & Context)&&
!        ((MouseEntry->Modifier == AnyModifier)||
!         (MouseEntry->Modifier == (modifier& (~LockMask))))&&
!        (MouseEntry->IsMouse == 1))
!     {
!       /* got a match, now process it */
        ExecuteFunction(MouseEntry->Action,Tmp_win, &Event,Context,-1);
!       break;
!     }
!   }
    PressedW = None;
    if(LocalContext!=C_TITLE)
      SetBorder(ButtonWindow,(Scr.Hilite == ButtonWindow),True,True,x);
--- 1060,1072 ----
    
    ButtonWindow = Tmp_win;
    
!   XSync(dpy,0);
!   XAllowEvents(dpy,ReplayPointer,CurrentTime);
!   XSync(dpy,0);
! 
!   if (MouseEntry != NULL)
        ExecuteFunction(MouseEntry->Action,Tmp_win, &Event,Context,-1);
! 
    PressedW = None;
    if(LocalContext!=C_TITLE)
      SetBorder(ButtonWindow,(Scr.Hilite == ButtonWindow),True,True,x);
*** fvwm-2.0.46/fvwm/placement.c.orig	Fri Jan 17 09:39:21 1997
--- fvwm-2.0.46/fvwm/placement.c	Tue Aug 26 14:24:49 1997
***************
*** 396,402 ****
    /* Desk has been selected, now pick a location for the window */
    /*
     *  If
!    *     o  the window is a transient, or
     * 
     *     o  a USPosition was requested
     * 
--- 396,402 ----
    /* Desk has been selected, now pick a location for the window */
    /*
     *  If
!    *     o  the window is a transient with a position, or
     * 
     *     o  a USPosition was requested
     * 
***************
*** 405,411 ****
     *   If RandomPlacement was specified,
     *       then place the window in a psuedo-random location
     */
!   if (!(tmp_win->flags & TRANSIENT) && 
        !(tmp_win->hints.flags & USPosition) &&
        ((tflag & NO_PPOSITION_FLAG)||
         !(tmp_win->hints.flags & PPosition)) &&
--- 405,411 ----
     *   If RandomPlacement was specified,
     *       then place the window in a psuedo-random location
     */
!   if (!((tmp_win->flags & TRANSIENT) && (tmp_win->hints.flags & PPosition)) &&
        !(tmp_win->hints.flags & USPosition) &&
        ((tflag & NO_PPOSITION_FLAG)||
         !(tmp_win->hints.flags & PPosition)) &&
***************
*** 415,421 ****
  	(tmp_win->wmhints->initial_state == IconicState)) )
    {
      /* Get user's window placement, unless RandomPlacement is specified */   
!     if(tflag & RANDOM_PLACE_FLAG)
      {
        if(tflag & SMART_PLACE_FLAG)
          SmartPlacement(tmp_win,tmp_win->frame_width+2*tmp_win->bw,
--- 415,421 ----
  	(tmp_win->wmhints->initial_state == IconicState)) )
    {
      /* Get user's window placement, unless RandomPlacement is specified */   
!     if(tflag & RANDOM_PLACE_FLAG || (tmp_win->flags & TRANSIENT))
      {
        if(tflag & SMART_PLACE_FLAG)
          SmartPlacement(tmp_win,tmp_win->frame_width+2*tmp_win->bw,
*** fvwm-2.0.46/extras/FvwmTaskBar/FvwmTaskBar.c.orig	Tue Sep 24 06:54:59 1996
--- fvwm-2.0.46/extras/FvwmTaskBar/FvwmTaskBar.c	Tue Aug 26 13:59:45 1997
***************
*** 78,83 ****
--- 78,90 ----
  int   Fvwm_fd[2];
  int   x_fd;
  
+ /* Signal handling */
+ int   signal_pipes[2];
+ enum e_SignalActions {
+     SIGNAL_DEAD_PIPE=1,
+     SIGNAL_ALARM=2
+ };
+ 
  /* X related things */
  Display *dpy;
  Window  Root, win;
***************
*** 181,188 ****
    Fvwm_fd[1] = atoi(argv[2]);
    fd_width = GetFdWidth();
  
    signal (SIGPIPE, DeadPipe);
!   signal (SIGALRM, Alarm);
  
    SetMessageMask(Fvwm_fd,M_ADD_WINDOW | M_CONFIGURE_WINDOW | M_DESTROY_WINDOW 
|
  		 M_WINDOW_NAME | M_ICON_NAME | M_RES_NAME | M_DEICONIFY | M_ICONIFY |
--- 188,197 ----
    Fvwm_fd[1] = atoi(argv[2]);
    fd_width = GetFdWidth();
  
+   /* set up signal and alarm pipes */
+   pipe(signal_pipes);
    signal (SIGPIPE, DeadPipe);
!   signal (SIGALRM, SigAlarm);
  
    SetMessageMask(Fvwm_fd,M_ADD_WINDOW | M_CONFIGURE_WINDOW | M_DESTROY_WINDOW 
|
  		 M_WINDOW_NAME | M_ICON_NAME | M_RES_NAME | M_DEICONIFY | M_ICONIFY |
***************
*** 281,286 ****
--- 290,311 ----
        DrawGoodies();
      }
  
+       /*
+        * signal notification handling
+        */
+     if (FD_ISSET(signal_pipes[1], &readset)) {
+         char buffer[1];
+         read(signal_pipes[1], buffer, sizeof buffer);
+         switch (buffer[0]) {
+          case SIGNAL_DEAD_PIPE:
+             ShutMeDown(1);
+             break;
+             
+          case SIGNAL_ALARM:
+             Alarm();
+         }
+     }
+ 
    }
  }
  
***************
*** 495,502 ****
   **********************************************************************/
  void DeadPipe(int nonsense)
  {
!   ConsoleMessage("received SIGPIPE signal: exiting...\n");
!   ShutMeDown(1);
  }
  
  /*****************************************************************************
*
--- 520,530 ----
   **********************************************************************/
  void DeadPipe(int nonsense)
  {
!   /*
!    * Send notification to the main loop
!    */
!   static char buffer[1] = { (char) SIGNAL_DEAD_PIPE  };
!   write(signal_pipes[0], buffer, sizeof buffer);
  }
  
  /*****************************************************************************
*
***************
*** 717,725 ****
  /*****************************************************************************
*
    Alarm - Handle a SIGALRM - used to implement timeout events
  ******************************************************************************
/
! void Alarm(int nonsense) {
  
!   switch(AlarmSet) {
  
    case SHOW_TIP:
      ShowTipWindow(1);
--- 745,763 ----
  /*****************************************************************************
*
    Alarm - Handle a SIGALRM - used to implement timeout events
  ******************************************************************************
/
! void SigAlarm(int nonsense) {
! 
!     /*
!      * send an alarm to the main loop
!      */
!   static char buffer[1] = { (char) SIGNAL_ALARM };
!   write(signal_pipes[0], buffer, sizeof buffer);
! 
!   signal (SIGALRM, SigAlarm);
! }
  
! void Alarm(void) {
! switch(AlarmSet) {
  
    case SHOW_TIP:
      ShowTipWindow(1);
***************
*** 731,737 ****
    }
  
    AlarmSet = NOT_SET;
-   signal (SIGALRM, Alarm);
  }
  
  /*****************************************************************************
*
--- 769,774 ----

---

From: Grant McDorman <[email-masked]>
Date: Wed, 27 Aug 1997 17:03:47 -0400 (EDT)

-----BEGIN PGP SIGNED MESSAGE-----

Okay, let's try this again.

The patch I sent out yesterday was flawed:
  - the colourmap patch (24 bit truecolor) didn't work
  - the patch to FvwmTaskBar was broken (I did not properly setup for
    select() on the pipe)
  - the click-to-focus patch used the wrong context if the window clicked on
    didn't have the focus

I also have two new patches:
   1) in misc.c, window raising code now handles transients of transients
      (an outstanding defect, apparently)
   2) FvwmTaskBar now gets the configuration from fvwm instead of trying to
      read fvwm's configuration file directly. This means that it will work
      for preprocessed (FvwmM4/FvwmCpp) and dynamic configuration.

A revised patch is attached. If you applied the patch I sent out yesterday,
reverse it (patch -R) or start with a clean fvwm source and then apply the
attached version.

Note that I am *not* the author of FvwmTaskBar. The fixes I am providing for it
are just to help.

On 26-Aug-97 18:31:02 Grant McDorman wrote:
> -----BEGIN PGP SIGNATURE-----
> Version: 2.6.2
> 
> iQBVAwUBNAMg5UDmya2cFZ8ZAQEiOAIAuWYub8sUblDwYN5GkyL3NoYc1wtq0gVI
> 559BZRWU6ehBzj+CWv9Ih/YitA6IVT8JVOtmobpAHxWFHeMlbIhjig==
> =ikmu
> -----END PGP SIGNATURE-----

  

  
--- 1419,1431 ----
      tmpi = tmpi->next;
      freeitem(tmpi2, 0);
    }
!   /*

  
+ int running = 1;
+ 

  
!   while(1)
      {
  
!   while(running)
      {
  
  /**

--- fvwm-2.0.46/fvwm/colormaps.c	Tue Aug 26 15:15:14 1997
  
    if(!ThisWinInstalled)
      {
  
    if(!ThisWinInstalled)
      {
!          && !(tmp->attr.depth == 24 && tmp->attr.visual->class == TrueColor)
  
+   if((function == F_CLOSE)&&(t)&&
+      (!(t->functions & MWM_FUNC_CLOSE)))
+     return 0;
+ 
    if((function == F_DESTROY)&&(t)&&
       (!(t->functions & MWM_FUNC_CLOSE)))
      return 0;
*** fvwm-2.0.46/fvwm/events.c.orig	Thu Aug  7 11:14:22 1997
--- fvwm-2.0.46/fvwm/events.c	Tue Aug 26 18:07:06 1997
***************
*** 203,211 ****
     * window where the event occured */
    if((e->type == KeyPress)&&(e->xkey.subwindow != None))
      *w = e->xkey.subwindow;
!   
!   if((e->type == ButtonPress)&&(e->xbutton.subwindow != None)&&
!      ((e->xbutton.subwindow == t->w)||(e->xbutton.subwindow == t->Parent)))
      *w = e->xbutton.subwindow;
    
    if (*w == Scr.Root)
--- 203,214 ----
     * window where the event occured */
    if((e->type == KeyPress)&&(e->xkey.subwindow != None))
      *w = e->xkey.subwindow;
! 
!     /* Q: are these subwindow checks necessary? */
!   if((e->type == ButtonPress)&&(e->xbutton.subwindow != None)
! /*    &&((e->xbutton.subwindow == t->w)||(e->xbutton.subwindow == t->Parent)||
!       (e->xbutton.subwindow == t->title_w))*/
!     )
      *w = e->xbutton.subwindow;
    
    if (*w == Scr.Root)
***************
*** 968,1035 ****

        
!       KeepOnTop();
  
        /* Why is this here? Seems to cause breakage with
         * non-focusing windows! */
!       if(!(Tmp_win->flags & ICONIFIED))
!       {
          XSync(dpy,0);
!         /* pass click event to just clicked to focus window? */
!         if (Scr.ClickToFocusPassesClick)
!           XAllowEvents(dpy,ReplayPointer,CurrentTime);
!         else /* don't pass click to just focused window */
!           XAllowEvents(dpy,AsyncPointer,CurrentTime);
          XSync(dpy,0);
          return;
-       }
-       
      }
    }
-   else if ((Tmp_win) && !(Tmp_win->flags & ClickToFocus) &&
-            (Event.xbutton.window == Tmp_win->frame) &&
-           Scr.MouseFocusClickRaises)
-   {
-     if (Tmp_win != Scr.LastWindowRaised &&
-         (Event.xbutton.state &
-          (ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) == 0 &&
-         GetContext(Tmp_win,&Event, &PressedW) == C_WINDOW)
-     {
-       RaiseWindow(Tmp_win);
-       KeepOnTop();
-     }
-     XSync(dpy,0);
-     XAllowEvents(dpy,ReplayPointer,CurrentTime);
-     XSync(dpy,0);
-     return;
-   }
  
-   XSync(dpy,0);
--- 971,1061 ----

!   /*
        
!           KeepOnTop();
  
          XSync(dpy,0);
          XSync(dpy,0);
          return;
      }
    }
  
    if(Context == C_TITLE)
    
    ButtonWindow = Tmp_win;
    
--- 1063,1075 ----
    
    ButtonWindow = Tmp_win;
    
!   XSync(dpy,0);
*** fvwm-2.0.46/fvwm/misc.c.orig	Tue Aug 26 17:02:45 1997
--- fvwm-2.0.46/fvwm/misc.c	Tue Aug 26 17:03:38 1997
***************
*** 588,608 ****

! void RaiseWindow(FvwmWindow *t)
  {
    FvwmWindow *t2;
!   int count, i;
!   Window *wins;
  
-   /* raise the target, at least */
-   count = 1;
-   Broadcast(M_RAISE_WINDOW,3,t->w,t->frame,(unsigned long)t,0,0,0,0);
-   
    for (t2 = Scr.FvwmRoot.next; t2 != NULL; t2 = t2->next)
      {
!       if(t2->flags & ONTOP)
! 	count++;
!       if((t2->flags & TRANSIENT) &&(t2->transientfor == t->w)&&
  	 (t2 != t))
  	{
  	  count++;
--- 588,606 ----

! /*
!  * Count all transients, direct or indirect, for window 't'
!  */
! static int CountTransientsFor(FvwmWindow *t)
  {
    FvwmWindow *t2;
!   Window      transientfor;
!   int         count = 0;
  
    for (t2 = Scr.FvwmRoot.next; t2 != NULL; t2 = t2->next)
      {
!       if(!(t2->flags & ONTOP) && 
!          (t2->flags & TRANSIENT) &&(t2->transientfor == t->w)&&
  	 (t2 != t))
  	{
  	  count++;
***************
*** 611,619 ****
  	  if ((t2->flags & ICONIFIED)&&(!(t2->flags & SUPPRESSICON)))
  	    {
  	      count += 2;
! 	    }	  
  	}
      }
    if ((t->flags & ICONIFIED)&&(!(t->flags & SUPPRESSICON)))
      {
        count += 2;
--- 609,702 ----
  	  if ((t2->flags & ICONIFIED)&&(!(t2->flags & SUPPRESSICON)))
  	    {
  	      count += 2;
! 	    }
!           /*
!            * Also count this transient window's own transients
!            * To avoid loops, temporarily destroy the transientfor.
!            */
!           transientfor = t2->transientfor;
!           t2->transientfor = None;
!           count += CountTransientsFor(t2);
!           t2->transientfor = transientfor;
  	}
      }
+   return count;
+ }
+ 
+ /*
+  * Fill in array with transients for window 't'.
+  */
+ static void GetTransientsFor(FvwmWindow *t, Window *wins, int *i)
+ {
+   FvwmWindow *t2;
+   Window      transientfor;
+ 
+   for (t2 = Scr.FvwmRoot.next; t2 != NULL; t2 = t2->next)
+   {
+     if((t2->flags & TRANSIENT) &&
+        (t2->transientfor == t->w) &&
+        (t2 != t) &&
+        (!(t2->flags & ONTOP)))
+     {
+       /*
+        * Put this window's own transients in first.
+        * As above, temporarily destroy the transientfor.
+        */
+       transientfor = t2->transientfor;
+       t2->transientfor = None;
+       GetTransientsFor(t2, wins, i);
+       t2->transientfor = transientfor;
+ 
+       /*
+        * Now put in the transient itself.
+        */
+       wins[(*i)++] = t2->frame;
+       if ((t2->flags & ICONIFIED)&&(!(t2->flags & SUPPRESSICON)))
+       {
+         if(!(t2->flags & NOICON_TITLE))
+           wins[(*i)++] = t2->icon_w;
+         if(!(t2->icon_pixmap_w))
+           wins[(*i)++] = t2->icon_pixmap_w;
+       }
+     }
+   }
+ }
+ 
+ /*
+  * Raise a window. Maintain transients for that window above the window
+  * (if DONT_RAISE_TRANSIENTS not defined).
+  */
+ void RaiseWindow(FvwmWindow *t)
+ {
+   FvwmWindow *t2;
+   int count, i;
+   Window *wins;
+ 
+   /*
+    * 1. Count windows that will get raised.
+    */
+ 
+   /* 1a. raise the target, at least */
+   count = 1;
+   Broadcast(M_RAISE_WINDOW,3,t->w,t->frame,(unsigned long)t,0,0,0,0);
+ 
+   /*
+    * 1b. Count on-top windows
+    */
+   for (t2 = Scr.FvwmRoot.next; t2 != NULL; t2 = t2->next)
+     {
+       if(t2->flags & ONTOP)
+ 	count++;
+     }
+ 
+   /*
+    * 1c. Count transients (direct and indirect) for this window.
+    */
+   count += CountTransientsFor(t);
+ 
+   /*
+    * 1d. Count window's icon, if this window is iconified.
+    */
    if ((t->flags & ICONIFIED)&&(!(t->flags & SUPPRESSICON)))
      {
        count += 2;
***************
*** 623,629 ****
  
    i=0;
  
!   /* ONTOP windows on top */
    for (t2 = Scr.FvwmRoot.next; t2 != NULL; t2 = t2->next)
      {
        if(t2->flags & ONTOP)
--- 706,715 ----
  
    i=0;
  
!   /*
!    * 2. Collect windows in order.
!    */
!   /* 2a. ONTOP windows on top */
    for (t2 = Scr.FvwmRoot.next; t2 != NULL; t2 = t2->next)
      {
        if(t2->flags & ONTOP)
***************
*** 634,659 ****
  	}
      }
  
!   /* now raise transients */
  #ifndef DONT_RAISE_TRANSIENTS
!   for (t2 = Scr.FvwmRoot.next; t2 != NULL; t2 = t2->next)
!   {
!     if((t2->flags & TRANSIENT) &&
!        (t2->transientfor == t->w) &&
!        (t2 != t) &&
!        (!(t2->flags & ONTOP)))
!     {
!       wins[i++] = t2->frame;
!       if ((t2->flags & ICONIFIED)&&(!(t2->flags & SUPPRESSICON)))
!       {
!         if(!(t2->flags & NOICON_TITLE))
!           wins[i++] = t2->icon_w;
!         if(!(t2->icon_pixmap_w))
!           wins[i++] = t2->icon_pixmap_w;
!       }
!     }
!   }
  #endif
    if ((t->flags & ICONIFIED)&&(!(t->flags & SUPPRESSICON)))
    {
      if(!(t->flags & NOICON_TITLE)) 
--- 720,735 ----
  	}
      }
  
!   /* 
!    * 2b. Transients.
!    */
  #ifndef DONT_RAISE_TRANSIENTS
!     GetTransientsFor(t, wins, &i);
  #endif
+     
+   /*
+    * 2c. Window itself.
+    */
    if ((t->flags & ICONIFIED)&&(!(t->flags & SUPPRESSICON)))
    {
      if(!(t->flags & NOICON_TITLE)) 
***************
*** 666,671 ****
--- 742,750 ----
    if(!(t->flags & ONTOP))
      Scr.LastWindowRaised = t;
  
+   /*
+    * Raise the topmost window in the stack
+    */
    if(i > 0)
      XRaiseWindow(dpy,wins[0]);
  
*** fvwm-2.0.46/extras/FvwmTaskBar/FvwmTaskBar.c.orig	Tue Sep 24 06:54:59 1996
--- fvwm-2.0.46/extras/FvwmTaskBar/FvwmTaskBar.c	Tue Aug 26 17:34:55 1997
***************
*** 78,83 ****
--- 78,90 ----
  int   Fvwm_fd[2];
  int   x_fd;
  
+ /* Signal handling */
+ int   signal_pipes[2];
+ enum e_SignalActions {
+     SIGNAL_DEAD_PIPE=1,
+     SIGNAL_ALARM=2
+ };
+ 
  /* X related things */
  Display *dpy;
  Window  Root, win;
***************
*** 181,188 ****

--- 188,201 ----
  
+   /* set up signal and alarm pipes */
+   pipe(signal_pipes);
    signal (SIGPIPE, DeadPipe);
!   signal (SIGALRM, SigAlarm);
! 
!   /* Parse the config file */
!   InitList(&swallowed);
!   ParseConfig(argv[3]);
  
*** 197,206 ****
  #endif
  		);
  
-   /* Parse the config file */
-   InitList(&swallowed);
-   ParseConfig(argv[3]);
- 
    /* Setup the XConnection */
    StartMeUp();
    XSetErrorHandler((XErrorHandler) ErrorHandler);
--- 210,215 ----
***************
*** 235,240 ****
--- 244,250 ----
      FD_ZERO(&readset);
      FD_SET(Fvwm_fd[1], &readset);
      FD_SET(x_fd, &readset);
+     FD_SET(signal_pipes[1], &readset);
      XPending(dpy);
      tv.tv_sec  = 0;
      tv.tv_usec = 0;
***************
*** 244,249 ****
--- 254,260 ----
          FD_ZERO(&readset);
          FD_SET(Fvwm_fd[1], &readset);
          FD_SET(x_fd, &readset);
+         FD_SET(signal_pipes[1], &readset);
          XPending(dpy);
  
          tv.tv_sec  = UpdateInterval;
***************
*** 260,265 ****
--- 271,277 ----
          FD_ZERO(&readset);
          FD_SET(Fvwm_fd[1], &readset);
          FD_SET(x_fd, &readset);
+         FD_SET(signal_pipes[1], &readset);
          XPending(dpy);
  
          tv.tv_sec  = UpdateInterval;
***************
*** 281,286 ****
--- 293,314 ----
        DrawGoodies();
      }
  
+       /*
  
***************
*** 495,502 ****
  
--- 523,533 ----
  
  /*****************************************************************************
*
***************
*** 575,589 ****
    char *str;
    FILE *ptr;
    int i, j;
!    
    ptr = fopen(file,"r");
    if (ptr == (FILE *)NULL) {
      ConsoleMessage("Couldn't read configuration file (%s)...\n", file);
      return;
    }
  
    tline = fgets(line,(sizeof line)-1,ptr);
- 
    while (tline != (char *)0) {
      while (isspace(*tline))tline++;
      if (strlen(tline)>1 && tline[0] != '#') {
--- 606,639 ----
    char *str;
    FILE *ptr;
    int i, j;
! 
! #ifndef FVWM95
!     /*
!      * transfer config to a temporary file, to avoid problems with
!      * message traffic during configuration parsing
!      */
!     ptr = tmpfile();
!   if (ptr == (FILE *)NULL) {
!     ConsoleMessage("Couldn't get temporary file\n");
!     return;
!   }
!   GetConfigLine(Fvwm_fd,&tline);
!   while (tline != (char *) 0) {
!       fputs(tline, ptr);
!       GetConfigLine(Fvwm_fd,&tline);
!   }
!   rewind(ptr);
! 
!   
! #else /* FVWM95 */
    ptr = fopen(file,"r");
    if (ptr == (FILE *)NULL) {
      ConsoleMessage("Couldn't read configuration file (%s)...\n", file);
      return;
    }
  
+ #endif
    tline = fgets(line,(sizeof line)-1,ptr);
    while (tline != (char *)0) {
      while (isspace(*tline))tline++;
      if (strlen(tline)>1 && tline[0] != '#') {
***************
*** 678,683 ****
--- 728,734 ----
        }
      tline = fgets(line,(sizeof line)-1,ptr);
    }
+   fclose(ptr);
  }

!   switch(AlarmSet) {
  
    case SHOW_TIP:
      ShowTipWindow(1);
--- 768,786 ----
  
! void Alarm(void) {
! switch(AlarmSet) {
  
    case SHOW_TIP:
      ShowTipWindow(1);
***************
*** 731,737 ****
    }
  
    AlarmSet = NOT_SET;
  
  /*****************************************************************************
*
--- 792,797 ----
*** fvwm-2.0.46/extras/FvwmTaskBar/FvwmTaskBar.h.orig	Mon Sep 23 20:00:31 1996
--- fvwm-2.0.46/extras/FvwmTaskBar/FvwmTaskBar.h	Tue Aug 26 13:56:29 1997
***************
*** 81,87 ****
  void ProcessMessage(unsigned long type,unsigned long *body);
  void SendFvwmPipe(char *message,unsigned long window);
  void DeadPipe(int nonsense);
! void Alarm(int nonsense);
  void SetAlarm(int event);
  void ClearAlarm(void);
  void CheckForTip(int x, int y);
--- 81,88 ----
  void ProcessMessage(unsigned long type,unsigned long *body);
  void SendFvwmPipe(char *message,unsigned long window);
  void DeadPipe(int nonsense);
! void SigAlarm(int nonsense);
! void Alarm(void);
  void SetAlarm(int event);
  void ClearAlarm(void);
  void CheckForTip(int x, int y);

---

From: Bruce Stephens <[email-masked]>
Date: Thu, 28 Aug 1997 10:23:15 +0100

> The patch I sent out yesterday was flawed: 

Could you check this patch (i.e., use your mailer to save it, and compare it 
with the original)?  It looks as though your mailer has folded lines, making 
it awkward for me to apply.  It's possible that it's *my* mailer that's doing 
it, of course, but I have reason to think it's not.  (Our MTA certainly 
doesn't fold lines, and MH is pretty good about not fiddling with things like 
that.)  The previous version also suffered this fault.

When I save the patch, I get a file of length 30713, which disagrees with size 
given in the text of the message.

Now I come to think of it, a likely culprit is the mailing list software.  
Perhaps MIME is a bad way of distributing patches?  What about uuencoded 
patches instead?

--
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: Kendrick Vargas <[email-masked]>
Date: Thu, 28 Aug 1997 18:49:10 -0400 (EDT)

> Perhaps MIME is a bad way of distributing patches?  What about uuencoded 

Maybe it's YOUR (hence ownership) software. I've never had a problem with
MIME encoded stuff on a mailing list. If you're getting errors in the
reported size, maybe you should check to see (with netscape) what the
message on the archive looks like. Netscape should see the nice mime
ttachment.
			-peace

--- BEGIN GEEK CODE BLOCK ------------+-----------
GAT d- s:+ !a C+(+++) UI/L/S/B++(+++) | "In the morning glad I see
P>+ L+(++) E---- W+++ N+ o? K? w++++  |  My foe outstrech'd beneath the tree."
O--- M-- V PS+++@ PE Y-- PGP+ t++ 5   |               -The Poison Tree
X++ R- tv+ b DI++ D+ G e>*  h*(!) r-  |                William Blake
y*(+) ------ END GEEK CODE BLOCK -----+