Use C++ linker
[oweals/cde.git] / cde / programs / dtwm / WmCEvent.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* 
24  * (c) Copyright 1989, 1990, 1991, 1992, 1993, 1994 OPEN SOFTWARE FOUNDATION, INC. 
25  * ALL RIGHTS RESERVED 
26 */ 
27 /* 
28  * Motif Release 1.2.4
29 */ 
30 #ifdef REV_INFO
31 #ifndef lint
32 static char rcsid[] = "$XConsortium: WmCEvent.c /main/10 1996/08/09 15:05:39 rswiston $"
33 #endif
34 #endif
35 /*
36  * (c) Copyright 1987, 1988, 1989, 1990 HEWLETT-PACKARD COMPANY */
37
38 /*
39  * Included Files:
40  */
41
42 #include "WmGlobal.h"
43 #include "WmICCC.h"
44
45 #include <X11/Xatom.h>
46
47 /*
48  * include extern functions
49  */
50 #include "WmCEvent.h"
51 #include "WmCDecor.h"
52 #include "WmColormap.h"
53 #include "WmEvent.h"
54 #include "WmFeedback.h"
55 #include "WmFunction.h"
56 #include "WmIDecor.h"
57 #include "WmKeyFocus.h"
58 #ifdef PANELIST
59 #include "WmPanelP.h"
60 #endif /* PANELIST */
61 #include "WmManage.h"
62 #include "WmMenu.h"
63 #include "WmProperty.h"
64 #include "WmProtocol.h"
65 #include "WmWinConf.h"
66 #include "WmWinInfo.h"
67 #include "WmWinList.h"
68 #include "WmWinState.h"
69 #ifdef WSM
70 #include "WmWrkspace.h"
71 #endif /* WSM */
72
73
74 /*
75  * Global Variables:
76  */
77
78 extern unsigned int buttonModifierMasks[];
79
80 \f
81 /*************************************<->*************************************
82  *
83  *  SetupCButtonBindings (window, buttonSpecs)
84  *
85  *
86  *  Description:
87  *  -----------
88  *  This function sets up the event handling necessary to support user
89  *  specified button bindings for window manager functions that apply to
90  *  the client window.
91  *
92  *
93  *  Inputs:
94  *  ------
95  *  window = grab window id
96  *
97  *  buttonSpecs = list of button bindings for window manager functions
98  *
99  *************************************<->***********************************/
100
101 void SetupCButtonBindings (Window window, ButtonSpec *buttonSpecs)
102 {
103     ButtonSpec *buttonSpec;
104     unsigned int eventMask;
105     unsigned int grabState;
106
107
108     /*
109      * If the context of the button binding includes "window" do button
110      * grabs to get the button events that invoke window manger functions.
111      * !!! don't do redundant grabs !!!
112      */
113
114     buttonSpec = buttonSpecs;
115     while (buttonSpec)
116     {
117         if ((buttonSpec->context & F_CONTEXT_WINDOW) &&
118             (buttonSpec->subContext & F_SUBCONTEXT_W_CLIENT))
119         {
120             eventMask = ButtonMotionMask | ButtonReleaseMask;
121
122             if (buttonSpec->eventType == ButtonRelease)
123             {
124                 /*
125                  * Don't include the button down in the grab state.
126                  */
127
128                 grabState = buttonSpec->state &
129                                 ~(buttonModifierMasks[buttonSpec->button]);
130             }
131             else
132             {
133                 grabState = buttonSpec->state;
134             }
135
136             WmGrabButton (DISPLAY, buttonSpec->button, grabState,
137                 window, False, eventMask, GrabModeSync,
138                 GrabModeAsync, None, None);
139         }
140         /*
141          * If the window context is not "window" a general grab is not
142          * necessary.
143          */
144
145         buttonSpec = buttonSpec->nextButtonSpec;
146     }
147
148 } /* END OF FUNCTION SetupCButtonBindings */
149
150
151 \f
152 /*************************************<->*************************************
153  *
154  *  WmDispatchClientEvent (event)
155  *
156  *
157  *  Description:
158  *  -----------
159  *  This function detects and dispatches events that are reported to a client
160  *  frame or icon window that are not widget-related (i.e. they would not be
161  *  dispatched by the Xtk intrinsics).
162  *
163  *
164  *  Inputs:
165  *  ------
166  *  event = This is an X event that has been retrieved by XtNextEvent.
167  *
168  *
169  *  Outputs:
170  *  -------
171  *  RETURN = If True the event should be dispatched by the toolkit,
172  *      otherwise the event should not be dispatched.
173  *
174  *************************************<->***********************************/
175
176 Boolean WmDispatchClientEvent (XEvent *event)
177 {
178     ClientData * pCD = NULL;
179 #ifndef IBM_169380
180     ClientData **cmap_window_data = NULL;
181 #endif
182     Boolean dispatchEvent = False;
183
184     /*
185      * Detect and dispatch non-widget events that have been reported to
186      * an icon or a client window frame.
187      */
188
189 #ifndef IBM_169380
190     if ((XFindContext (DISPLAY, event->xany.window, wmGD.windowContextType,
191             (caddr_t *)&pCD)) &&
192         (XFindContext (DISPLAY, event->xany.window, wmGD.cmapWindowContextType,
193             (caddr_t *)&cmap_window_data)))
194 #else
195     if (XFindContext (DISPLAY, event->xany.window, wmGD.windowContextType,
196             (caddr_t *)&pCD))
197 #endif
198     {
199         /*
200          *  Set active screen if we're not sure. 
201          */
202         if (wmGD.queryScreen)
203             DetermineActiveScreen (event);
204
205         /*
206          * Handle events on windows that are made by mwm for
207          * non-client-specific functions.  Also handle "leftover"
208          * events on windows that used to be managed by mwm
209          * (e.g. ConfigureRequest events).
210          */
211
212         return (HandleEventsOnSpecialWindows (event));
213     }
214
215 #ifndef IBM_169380
216     if (cmap_window_data)
217     /*
218      * Event is on a subwindow that is specified in one or more toplevel
219      * window's WM_COLORMAP_WINDOWS property.  (Most likely this is a
220      * ColormapNotify event.)  It could have more than one pCD associated
221      * with it, so we have to choose one.  If one of the pCD's currently has
222      * the Colormap Focus, then let's use that one.  Otherwise, just use
223      * the 1st one.
224      */
225     {
226         int j;
227         for (j = 0; cmap_window_data[j]; j++)
228         {
229             if (ACTIVE_PSD->colormapFocus == cmap_window_data[j])
230             {
231                 pCD = cmap_window_data[j];
232                 break;
233             }
234         }
235         /*
236          * None of the pCD's in the list have Colormap Focus.  So, just
237          * set pCD to the 1st one in the list.
238          */
239         if (!pCD)
240             pCD = cmap_window_data[0];
241     }
242 #endif
243
244     /*
245      *  Set active screen if this is not a FocusOut event.
246      *  We don't need to set it on focus out AND we use
247      *  (SCREEN_FOR_CLIENT(pCD) != ACTIVE_SCREEN) in
248      *  in HandleCFocusOut to determine if a new colormap needs
249      *  to be installed.
250      */
251
252     if (!(event->type == FocusOut))
253     {
254         SetActiveScreen (PSD_FOR_CLIENT(pCD));
255     }
256 #ifdef WSM
257     /* Get workspace specific client data */
258     SetClientWsIndex (pCD);
259 #endif /* WSM */
260
261     /*
262      * Handle events on top-level client windows.
263      */
264
265     if (event->xany.window == pCD->client)
266     {
267         return (HandleEventsOnClientWindow (pCD, event));
268     }
269
270     /*
271      * Handle events on windows created by mwm (for icons and client window
272      * frames) and on non-top-level client windows (e.g., colormap
273      * windows).
274      */
275
276     switch (event->type)
277     {
278         case ButtonPress:
279         {
280             dispatchEvent = HandleCButtonPress (pCD, (XButtonEvent *)event);
281             break;
282         }
283
284         case ButtonRelease:
285         {
286             if (wmGD.menuActive)
287             {
288                 dispatchEvent = True; /* have the toolkit dispatch the event */
289             }
290             else
291             {
292                 HandleCButtonRelease (pCD, (XButtonEvent *)event);
293             }
294             break;
295         }
296
297         case KeyPress:
298         {
299             dispatchEvent = HandleCKeyPress (pCD, (XKeyEvent *)event);
300             break;
301         }
302
303         case MotionNotify:
304         {
305             HandleCMotionNotify (pCD, (XMotionEvent *)event);
306             break;
307         }
308
309         case Expose:
310         {
311             /* 
312              * If multiple expose events, wait for last one.
313              */
314
315             if (event->xexpose.count == 0) 
316             {
317                 if (event->xexpose.window == ICON_FRAME_WIN(pCD))
318                 {
319                     IconExposureProc (pCD, True);
320                     if (P_ICON_BOX(pCD))
321                     {
322                         dispatchEvent = True;
323                     }
324                 }
325                 else if (event->xexpose.window == 
326                              pCD->pSD->activeIconTextWin)
327                 {
328                     PaintActiveIconText (pCD, FALSE);
329                 }
330                 else if (!(pCD->clientFlags & CLIENT_DESTROYED))
331                 {
332                     if ((event->xexpose.window == pCD->clientFrameWin) ||
333                          (event->xexpose.window == pCD->clientTitleWin))
334                     {
335                         FrameExposureProc (pCD);
336                     }
337                     if (event->xexpose.window == pCD->clientBaseWin)
338                     {
339                         BaseWinExposureProc (pCD);
340                     }
341                 }
342 #ifdef PANELIST
343                 else if (pCD->clientFlags & FRONT_PANEL_BOX)
344                 {
345                 /*
346                  *
347                  *  Then this client is the shell for the 
348                  *  front panel and we want the toolkit to repaint
349                  *  it.
350                  *
351                  */
352                     dispatchEvent = True;
353                 }
354 #endif /* PANELIST */
355             }
356             break;
357         }
358
359         case EnterNotify:
360         {
361             HandleCEnterNotify (pCD, (XEnterWindowEvent *)event);
362             break;
363         }
364
365         case LeaveNotify:
366         {
367             HandleCLeaveNotify (pCD, (XLeaveWindowEvent *)event);
368             break;
369         }
370
371         case FocusIn:
372         {
373             dispatchEvent = HandleCFocusIn (pCD, (XFocusChangeEvent *)event);
374             break;
375         }
376
377         case FocusOut:
378         {
379             dispatchEvent = HandleCFocusOut (pCD, (XFocusChangeEvent *)event);
380             break;
381         }
382
383         case DestroyNotify:
384         {
385             if (((XDestroyWindowEvent *)event)->window == pCD->client)
386             {
387                 pCD->clientFlags |= CLIENT_DESTROYED;
388                 UnManageWindow (pCD);
389             }
390             break;
391         }
392
393         case UnmapNotify:
394         {
395             /*
396              * This event is generated when a managed  client window is 
397              * unmapped by the client or when the window manager unmaps the
398              * client window; check the wmMapCount to determine if this is
399              * the result of a window manager unmap. If this is a client
400              * unmap then the window is to be withdrawn from window manager
401              * control.
402              */
403
404             if (((XUnmapEvent *)event)->window == pCD->client)
405             {
406                 if (pCD->wmUnmapCount)
407                 {
408                     pCD->wmUnmapCount--;
409                 }
410                 else
411                 {
412                     UnManageWindow (pCD);
413                 }
414             }
415             break;
416         }
417
418         case MapRequest:
419         {
420             /*
421              * This is a request to change the state of the client window from
422              * iconic (minimized) to normal.
423              */
424 #ifdef WSM
425             if (!ClientInWorkspace (ACTIVE_WS, pCD))
426             {
427                 if (pCD->absentMapBehavior == AMAP_BEHAVIOR_IGNORE)
428                 {
429                     SetClientState (pCD, NORMAL_STATE|UNSEEN_STATE, 
430                                     GetTimestamp ());
431                 }
432                 else
433                 {
434                     HonorAbsentMapBehavior(pCD);
435                     SetClientState (pCD, NORMAL_STATE, GetTimestamp ());
436                 }
437             }
438             else
439             {
440                 SetClientState (pCD, NORMAL_STATE, GetTimestamp ());
441             }
442 #else /* WSM */
443             SetClientState (pCD, NORMAL_STATE, GetTimestamp ());
444 #endif /* WSM */
445             break;
446         }
447
448         case ConfigureRequest:
449         {
450             HandleCConfigureRequest (pCD, (XConfigureRequestEvent *)event);
451             break;
452         }
453
454         case ColormapNotify:
455         {
456             /*
457              * Process changes to client window colormaps:
458              */
459
460             HandleCColormapNotify (pCD, (XColormapEvent *)event);
461             break;
462         }
463
464         case ClientMessage:
465         {
466             /*
467              * Handle client message events.
468              */
469
470             HandleClientMessage (pCD, (XClientMessageEvent *)event);
471             break;
472         }
473         case ReparentNotify:
474         {
475             if ((((XReparentEvent *)event)->window == pCD->client) &&
476                 (((XReparentEvent *)event)->parent != pCD->clientBaseWin))
477             {
478                 /*
479                  * The window was reparented away from the frame.
480                  * Unmanage to clean up the now empty frame.
481                  *
482                  * Note: We get here when the reparent is done while
483                  * the client is unmapped (e.g. iconified). Otherwise
484                  * the reparent will generate an UnmapNotify which
485                  * will also cause us to unmanage the client.
486                  */
487                 UnManageWindow (pCD);
488               }
489             break;
490         }
491     } /* end of event.type switch */
492
493
494     return (dispatchEvent);
495
496
497 } /* END OF FUNCTION WmDispatchClientEvent */
498
499
500 \f
501 /*************************************<->*************************************
502  *
503  *  HandleEventsOnSpecialWindows (pEvent)
504  *
505  *
506  *  Description:
507  *  -----------
508  *  Handles events on special window manager windows and "leftover" events
509  *  from destroyed client window frames.
510  *
511  *
512  *  Inputs:
513  *  ------
514  *  pEvent = pointer to an XEvent structure
515  *
516  * 
517  *  Outputs:
518  *  -------
519  *  RETURN = If True the event should be dispatched by the toolkit,
520  *      otherwise the event should not be dispatched.
521  *
522  *************************************<->***********************************/
523
524 Boolean HandleEventsOnSpecialWindows (XEvent *pEvent)
525 {
526     Boolean dispatchEvent = True;
527 #ifdef WSM
528     WmScreenData *pSD;
529 #endif /* WSM */
530
531
532     /*
533      * The window is not a root window or a client frame window.  Check for
534      * a special window manager window.  Have the toolkit dispatch the event
535      * if the event is not on a special window.
536      */
537
538     if (pEvent->xany.window == ACTIVE_ROOT)
539     {
540         if (pEvent->type == FocusIn)
541         {
542             SetKeyboardFocus ((ClientData *) NULL, REFRESH_LAST_FOCUS);
543         }
544     }
545     else if (pEvent->xany.window == ACTIVE_PSD->feedbackWin)
546     {
547         if (pEvent->type == Expose)
548         {
549             if (pEvent->xexpose.count == 0)
550             {
551                 PaintFeedbackWindow(ACTIVE_PSD);
552             }
553         }
554         dispatchEvent = False; /* don't have the toolkit dispatch the event */
555     }
556     else if (pEvent->xany.window == ACTIVE_PSD->inputScreenWindow)
557     {
558         if (pEvent->type == ButtonPress)
559         {
560             F_Beep (NULL, (ClientData *) NULL, (XEvent *) NULL);
561         }
562         else if ((wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_POINTER) &&
563                  (pEvent->type == EnterNotify))
564         {
565             HandleWsEnterNotify ((XEnterWindowEvent *)pEvent);
566         }
567         dispatchEvent = False; /* don't have the toolkit dispatch the event */
568     }
569 #ifdef  WSM
570     else if (!XFindContext (DISPLAY, pEvent->xany.window,
571                     wmGD.mwmWindowContextType, (caddr_t *)&pSD))
572     {
573         if ((pEvent->type == PropertyNotify) &&
574             (pEvent->xproperty.atom == wmGD.xa_DT_WM_REQUEST) &&
575             (pEvent->xproperty.state == PropertyNewValue))
576         {
577             HandleDtWmRequest (pSD, pEvent);
578         }
579         if (pEvent->type == ClientMessage)
580         {
581             HandleDtWmClientMessage ((XClientMessageEvent *)pEvent);
582         }
583     }
584 #endif /* WSM */
585     else
586     {
587         /*
588          * Events may come in for a client frame base window that no
589          * longer exists (the client window was just unmanaged but the
590          * the client did some action before the un-reparenting was
591          * actually done).  Confirm that this is the case and then
592          * handle the request as if it came in as a root window event.
593          */
594
595         switch (pEvent->type)
596         {
597             case ConfigureRequest:
598             {
599                 if (GetParentWindow (pEvent->xconfigurerequest.window) ==
600                     ACTIVE_ROOT)
601                 {
602                     /*
603                      * This is an event for a client base window that
604                      * no longer exists.  Handle the event as if it is a
605                      * root window event.
606                      */
607
608                     dispatchEvent =  WmDispatchWsEvent (pEvent);
609                 }
610                 break;
611             }
612
613             case MapRequest:
614             {
615                 if (GetParentWindow (pEvent->xmaprequest.window) ==
616                     ACTIVE_ROOT)
617                 {
618                     /*
619                      * This is an event for a client base window that
620                      * no longer exists.  Handle the event as if it is a
621                      * root window event.
622                      */
623
624                     dispatchEvent = WmDispatchWsEvent (pEvent);
625                 }
626                 break;
627             }
628         }
629     }
630
631     return (dispatchEvent);
632
633 } /* END OF FUNCTION HandleEventsOnSpecialWindows */
634
635
636 \f
637 /*************************************<->*************************************
638  *
639  *  HandleEventsOnClientWindow (pCD, pEvent)
640  *
641  *
642  *  Description:
643  *  -----------
644  *  Handles events on a client top-level window.
645  *
646  *
647  *  Inputs:
648  *  ------
649  *  pCD = pointer to client data
650  *
651  *  pEvent = pointer to an XEvent structure
652  *
653  * 
654  *  Outputs:
655  *  -------
656  *  RETURN = If True the event should be dispatched by the toolkit,
657  *      otherwise the event should not be dispatched.
658  *
659  *************************************<->***********************************/
660
661 Boolean HandleEventsOnClientWindow (ClientData *pCD, XEvent *pEvent)
662 {
663     Boolean doXtDispatchEvent = True;
664
665 #ifndef NO_SHAPE
666     if (pEvent->type == (wmGD.shapeEventBase+ShapeNotify))
667     {
668         HandleCShapeNotify (pCD, (XShapeEvent *)pEvent);
669     }
670     else
671 #endif /* NO_SHAPE */
672     switch (pEvent->type)
673     {
674         case ColormapNotify:
675         {
676             /*
677              * Process changes to top-level client window colormaps:
678              */
679
680             HandleCColormapNotify (pCD, (XColormapEvent *)pEvent);
681             doXtDispatchEvent = False;
682             break;
683         }
684
685         case PropertyNotify:
686         {
687             /*
688              * Process property changes on managed client windows:
689              */
690                 
691             HandleCPropertyNotify (pCD, (XPropertyEvent *)pEvent);
692             doXtDispatchEvent = False;
693             break;
694         }
695
696         case ClientMessage:
697         {
698             /*
699              * Handle client message events.
700              */
701
702             HandleClientMessage (pCD, (XClientMessageEvent *)pEvent);
703             break;
704         }
705
706     }
707
708     return (doXtDispatchEvent);
709
710
711 } /* END OF FUNCTION HandleEventsOnClientWindow */
712
713
714 \f
715 /*************************************<->*************************************
716  *
717  *  HandleCPropertyNotify (pCD, propertyEvent)
718  *
719  *
720  *  Description:
721  *  -----------
722  *  This function handles propertyNotify events (indicating window property
723  *  changes) that are reported to the client window.
724  *
725  *
726  *  Inputs:
727  *  ------
728  *  pCD = pointer to the client data for the client window that got the event
729  *
730  *  propertyEvent = propertyNotify event that was received
731  *
732  *************************************<->***********************************/
733
734 void HandleCPropertyNotify (ClientData *pCD, XPropertyEvent *propertyEvent)
735 {
736
737     switch (propertyEvent->atom)
738     {
739         case XA_WM_HINTS:
740         {
741             ProcessWmHints (pCD, FALSE /*not first time*/);
742             break;
743         }
744         
745         case XA_WM_NORMAL_HINTS:
746         {
747             ProcessWmNormalHints (pCD, FALSE /*not first time*/, 0);
748             break;
749         }
750         
751         case XA_WM_NAME:
752         {
753             ProcessWmWindowTitle (pCD, FALSE /*not first time*/);
754             break;
755         }
756         
757         case XA_WM_ICON_NAME:
758         {
759             ProcessWmIconTitle (pCD, FALSE /*not first time*/);
760             break;
761         }
762         
763         case XA_WM_CLASS:
764         {
765
766             break;
767         }
768         
769         case XA_WM_COMMAND:
770         {
771             if (pCD->clientFlags & CLIENT_TERMINATING)
772             {
773                 DeleteClientWmTimers (pCD);
774                 XKillClient (DISPLAY, pCD->client);
775             }
776             break;
777         }
778
779         case XA_WM_TRANSIENT_FOR:
780         {
781             /*
782              * here we handle the special case of dialogs that are
783              * mapped before the windows they are transient for are
784              * mapped.  Xm handles this case by waiting for the
785              * transient_for window to appear before setting the
786              * WM_TRANSIENT_FOR property on the dialog.  Mwm has to
787              * notice this property change and re-organize things
788              * so the dialog is treated as a transient window.
789              *
790              * Note that we also handle the case of the WM_TRANSIENT_FOR
791              * property being removed. 
792              */
793             DeleteClientFromList (pCD->pSD->pActiveWS, pCD);
794             ProcessWmTransientFor(pCD);
795             AddClientToList(pCD->pSD->pActiveWS, pCD, True);
796             if (pCD->transientLeader != NULL)
797                 StackTransientWindow(pCD);
798             break;
799         }
800         
801         default:
802         {
803             if (propertyEvent->atom == wmGD.xa_WM_PROTOCOLS)
804             {
805                 ProcessWmProtocols (pCD);
806             }
807 #ifdef WSM
808             else if (propertyEvent->atom == wmGD.xa_DT_WORKSPACE_HINTS)
809             {
810                 (void) ProcessWorkspaceHints (pCD);
811             }
812 #endif /* WSM */
813             else if (propertyEvent->atom == wmGD.xa_MWM_MESSAGES)
814             {
815                 if (pCD->protocolFlags & PROTOCOL_MWM_MESSAGES)
816                 {
817                     ProcessMwmMessages (pCD);
818                 }
819             }
820             else if (propertyEvent->atom == wmGD.xa_SM_CLIENT_ID)
821             {
822                 ProcessSmClientID(pCD);
823             }
824             else if (propertyEvent->atom == wmGD.xa_WMSAVE_HINT)
825             {
826                 ProcessWmSaveHint(pCD);
827             }
828             else if (propertyEvent->atom == wmGD.xa_WM_COLORMAP_WINDOWS)
829             {
830                 if (propertyEvent->state == PropertyNewValue)
831                 {
832                     ProcessWmColormapWindows (pCD);
833                 }
834                 else
835                 {
836                     /* property was deleted */
837                     ResetColormapData (pCD, NULL, 0);
838                 }
839
840                 if ((ACTIVE_PSD->colormapFocus == pCD) &&
841                     ((pCD->clientState == NORMAL_STATE) ||
842                      (pCD->clientState == MAXIMIZED_STATE)))
843                 {
844                     /*
845                      * The client window has the colormap focus, install the
846                      * colormap.
847                      */
848 #ifndef OLD_COLORMAP /* colormap */
849                     /*
850                      * We just changed the colormaps list,
851                      * so we need to re-run the whole thing.
852                      */
853                     pCD->clientCmapFlagsInitialized = 0;
854                     ProcessColormapList (ACTIVE_PSD, pCD);
855 #else /* OSF original */
856                     WmInstallColormap (ACTIVE_PSD, pCD->clientColormap);
857 #endif
858                 }
859             }
860             break;
861         }
862     }
863
864 } /* END OF FUNCTION HandleCPropertyNotify */
865
866
867 \f
868 /*************************************<->*************************************
869  *
870  *  HandleCButtonPress (pCD, buttonEvent)
871  *
872  *
873  *  Description:
874  *  -----------
875  *  This function does window management actions associated with a button
876  *  press event on the client window (including frame) or icon.
877  *
878  *
879  *  Inputs:
880  *  ------
881  *  pCD = pointer to client data (identifies client window)
882  *
883  *  buttonEvent = ButtonPress event on client window
884  *
885  *
886  *  Outputs:
887  *  -------
888  *  RETURN = True if the event should be dispatched by XtDispatchEvent
889  *
890  *************************************<->***********************************/
891
892 Boolean HandleCButtonPress (ClientData *pCD, XButtonEvent *buttonEvent)
893 {
894     Boolean dispatchEvent = False;
895     Boolean replayEvent = True;
896     Context context;
897     int partContext;
898     Context subContext;
899     static Time baseWinTime = 0;
900     static unsigned int baseWinButton = 0;
901
902     wmGD.passButtonsCheck = True;
903
904     /*
905      * Find out the event context and process the event accordingly.
906      * If the event is due to a key focus selection grab or an application
907      * modal grab then handle the grab (only these types of grabs are
908      * done on the client window frame base window)..
909      */
910
911     if (wmGD.menuActive)
912     {
913         dispatchEvent = True;   /* have the toolkit dispatch the event */
914     }
915     else
916     {
917         IdentifyEventContext (buttonEvent, pCD, &context, &partContext);
918         subContext = (1L << partContext);
919
920         if (buttonEvent->window == pCD->clientBaseWin)
921         {
922             /* save time of event caught by base window grab */
923             baseWinTime = buttonEvent->time;
924             baseWinButton = buttonEvent->button;
925         }
926  
927         /*
928          * If this event was caught by the base window grab and
929          * replayed, then don't reprocess if caught by the frame
930          * window. (Replayed events have the same time.)
931          */
932         if (!((buttonEvent->window == pCD->clientFrameWin) &&
933               (buttonEvent->button == baseWinButton) &&
934               (buttonEvent->time == baseWinTime)))
935         {
936
937 #ifndef MOTIF_ONE_DOT_ONE
938             /*
939              * Motif 1.2, ignore replayed events UNPOST_AND_REPLAY events
940              * generated from the menu system (time stamps are exactly
941              * the same for the replayed event)
942              */
943
944             if (wmGD.clickData.time == buttonEvent->time)
945             {
946                 dispatchEvent = False;
947             }
948             else
949             {
950                 ProcessClickBPress (buttonEvent, pCD, context, subContext);
951             }
952 #else
953             ProcessClickBPress (buttonEvent, pCD, context, subContext);
954 #endif
955
956             if (CheckForButtonAction (buttonEvent, context, subContext, pCD) 
957                 && pCD)
958             {
959                 /*
960                  * Button bindings have been processed, now check for bindings
961                  * that associated with the built-in semantics of the window
962                  * frame decorations.
963                  */
964
965                 CheckButtonPressBuiltin (buttonEvent, context, subContext,
966                     partContext, pCD);
967
968                 /*
969                  * For case where button action causes lower, but
970                  * builtin causes focus - disable auto raise until
971                  * we receive focusIn or focusOut.
972                  */
973                 pCD->focusAutoRaiseDisablePending = False;
974             }
975             else
976             {
977                /*
978                 * Else skip built-in processing due to execution of a function
979                 * that does on-going event processing or that has changed the
980                 * client state (e.g., f.move or f.minimize).
981                 */
982
983                 replayEvent = False;
984             }
985         }
986     }
987
988     if (buttonEvent->window == pCD->clientBaseWin)
989     {
990         ProcessButtonGrabOnClient (pCD, buttonEvent, replayEvent);
991     }
992
993     return (dispatchEvent);
994
995
996 } /* END OF FUNCTION HandleCButtonPress */
997
998
999 \f
1000 /*************************************<->*************************************
1001  *
1002  *  ProcessButtonGrabOnClient (pCD, buttonEvent, replayEvent)
1003  *
1004  *
1005  *  Description:
1006  *  -----------
1007  *  This function handles an activated button grab on the client window
1008  *  frame base window.
1009  *
1010  *
1011  *  Inputs:
1012  *  ------
1013  *  pCD = pointer to client data of window associated with the grab
1014  *
1015  *  buttonEvent = ButtonPress event on client window
1016  *
1017  *  replayEvent = True if event should be replayed
1018  *
1019  *************************************<->***********************************/
1020
1021 void ProcessButtonGrabOnClient (ClientData *pCD, XButtonEvent *buttonEvent, Boolean replayEvent)
1022 {
1023     ButtonSpec *buttonSpec;
1024     Boolean passButton;
1025
1026
1027
1028     if ((buttonEvent->button == SELECT_BUTTON) && 
1029         ((buttonEvent->state == 0) ||
1030          (NOLOCKMOD(buttonEvent->state) == 0)))
1031     {
1032         passButton = wmGD.passSelectButton;
1033     }
1034     else
1035     {
1036         passButton = wmGD.passButtons;
1037     }
1038
1039     if (IS_APP_MODALIZED(pCD) || !passButton)
1040     {
1041         replayEvent = False;
1042     }
1043     else if (replayEvent)
1044     {
1045         /*
1046          * Replay the event as long as there is not another button binding
1047          * for the button release.
1048          */
1049
1050         buttonSpec = ACTIVE_PSD->buttonSpecs;
1051         while (buttonSpec)
1052         {
1053             if ((buttonSpec->eventType == ButtonRelease) &&
1054                 ((buttonEvent->state == buttonSpec->state) ||
1055                  (NOLOCKMOD(buttonEvent->state) == buttonSpec->state)) &&
1056                 (buttonEvent->button == buttonSpec->button))
1057             {
1058                 replayEvent = False;
1059                 break;
1060             }
1061
1062             buttonSpec = buttonSpec->nextButtonSpec;
1063         }
1064     }
1065
1066     if (replayEvent && wmGD.passButtonsCheck)
1067     {
1068         XAllowEvents (DISPLAY, ReplayPointer, CurrentTime);
1069     }
1070     else
1071     {
1072         if (IS_APP_MODALIZED(pCD))
1073         {
1074             /*
1075              * The grab is done on a window that has an application modal
1076              * secondary window.  Beep to indicate no client processing of
1077              * the event.
1078              */
1079
1080             F_Beep (NULL, pCD, (XEvent *) NULL);
1081         }
1082
1083         XAllowEvents (DISPLAY, AsyncPointer, CurrentTime);
1084     }
1085     XAllowEvents (DISPLAY, AsyncKeyboard, CurrentTime);
1086
1087 } /* END OF FUNCTION ProcessButtonGrabOnClient */
1088
1089
1090 \f
1091 /*************************************<->*************************************
1092  *
1093  *  CheckButtonPressBuiltin (buttonEvent, context, subContext, partContext, pCD)
1094  *
1095  *
1096  *  Description:
1097  *  -----------
1098  *  This function checks to see if a built-in window manager function
1099  *  has been selected.  If yes, then the function is done.
1100  *
1101  *
1102  *  Inputs:
1103  *  ------
1104  *  buttonEvent = pointer to button event
1105  *
1106  *  context = button event context (root, icon, window)
1107  *
1108  *  subContext = button event subcontext (title, system button, ...)
1109  *
1110  *  partContext = part context within a window manager component
1111  *
1112  *************************************<->***********************************/
1113
1114 void CheckButtonPressBuiltin (XButtonEvent *buttonEvent, Context context, Context subContext, int partContext, ClientData *pCD)
1115 {
1116     /*
1117      * All builtin button bindings are based on button 1 with no
1118      * modifiers. (Ignore locking modifiers)
1119      */
1120
1121     if (((buttonEvent->button != SELECT_BUTTON)  && 
1122          (buttonEvent->button != DMANIP_BUTTON)) || 
1123            NOLOCKMOD(buttonEvent->state))
1124     {
1125         return;
1126     }
1127
1128
1129     /*
1130      * Process the builtin button bindings based on the window manager
1131      * component that was selected.
1132      */
1133
1134     if (context & F_CONTEXT_ICON)
1135     {
1136         HandleIconButtonPress (pCD, buttonEvent);
1137     }
1138     else if (context & F_CONTEXT_ICONBOX)
1139     {
1140         HandleIconBoxButtonPress (pCD, buttonEvent, subContext);
1141     }
1142     else if (context & F_CONTEXT_WINDOW)
1143     {
1144         /*
1145          * A client window frame component was selected.
1146          */
1147
1148         /*
1149          * If the keyboard focus policy is explicit then all window frame
1150          * components set the keyboard input focus when selected.
1151          */
1152
1153         if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)
1154         {
1155             /* If we've just done f.lower, disable focusAutoRaise. */
1156             if (pCD && pCD->focusAutoRaiseDisablePending)
1157               pCD->focusAutoRaiseDisabled = True;
1158
1159             Do_Focus_Key (pCD, buttonEvent->time,
1160                 (long)((partContext == FRAME_CLIENT) ? CLIENT_AREA_FOCUS : 0));
1161         }
1162
1163
1164         /*
1165          * Process the builtin button bindings based on the client window
1166          * frame component that was selected.
1167          */
1168
1169         if ((buttonEvent->button == SELECT_BUTTON) && 
1170             (subContext == F_SUBCONTEXT_W_SYSTEM))
1171         {
1172             int flags = 0;
1173
1174             /*
1175              * System menu button component:
1176              * SELECT_BUTTON Press - post the system menu.
1177              * SELECT_BUTTON double-click - close the window.
1178              */
1179
1180             PushGadgetIn (pCD, partContext);
1181
1182             if ((wmGD.clickData.doubleClickContext == F_SUBCONTEXT_W_SYSTEM) &&
1183                 wmGD.systemButtonClick2 &&
1184                 (pCD->clientFunctions & MWM_FUNC_CLOSE))
1185             {
1186                 /*
1187                  * Close the client window.  Don't do any of the other
1188                  * system menu button actions.
1189                  */
1190
1191                 wmGD.clickData.clickPending = False;
1192                 wmGD.clickData.doubleClickPending = False;
1193                 F_Kill (NULL, pCD, (XEvent *) buttonEvent);
1194                 return;
1195             }
1196
1197             if (pCD->clientState == NORMAL_STATE)
1198             {
1199                 context = F_CONTEXT_NORMAL;
1200             }
1201             else if (pCD->clientState == MAXIMIZED_STATE)
1202             {
1203                 context = F_CONTEXT_MAXIMIZE;
1204             }
1205             else
1206             {
1207                 context = F_CONTEXT_ICON;
1208             }
1209
1210             /*
1211              * Set up for "sticky" menu processing if specified.
1212              */
1213             if (wmGD.systemButtonClick)
1214             {
1215                 wmGD.checkHotspot = True;
1216                 flags |= POST_STICKY;
1217             }
1218
1219             pCD->grabContext = context;
1220
1221             PostMenu (pCD->systemMenuSpec, pCD, 0, 0, SELECT_BUTTON, 
1222                       context, flags, (XEvent *)buttonEvent);
1223
1224         }
1225         else if (subContext == F_SUBCONTEXT_W_TITLE)
1226         {
1227             /*
1228              * Title component:
1229              * SELECT_BUTTON  or DMANIP_BUTTON Press - 
1230              *               start looking for a move.
1231              */
1232
1233             PushGadgetIn (pCD, partContext);
1234
1235 /*
1236  * Fix for 5075 - Check to make sure that MWM_FUNC_MOVE is set in the
1237  *                clientFunctions.  This is necessary because the title
1238  *                bar is added based on a number of decorations even if
1239  *                the resources or the user has specifically requested
1240  *                that "move" not be one of them.
1241  */
1242             if (pCD->clientFunctions & MWM_FUNC_MOVE)
1243             {
1244               wmGD.preMove = True;
1245               wmGD.preMoveX = buttonEvent->x_root;
1246               wmGD.preMoveY = buttonEvent->y_root;
1247               wmGD.configButton = buttonEvent->button;
1248               wmGD.configAction = MOVE_CLIENT;
1249             }
1250 /*
1251  * End fix 5075
1252  */
1253
1254         }
1255         else if (subContext & F_SUBCONTEXT_W_RBORDER)
1256         {
1257             /*
1258              * Resize border handle components:
1259              * SELECT_BUTTON or DMANIP_BUTTON Press - 
1260              *              start looking for a resize.
1261              */
1262
1263             wmGD.preMove = True;
1264             wmGD.preMoveX = buttonEvent->x_root;
1265             wmGD.preMoveY = buttonEvent->y_root;
1266             wmGD.configButton = buttonEvent->button;
1267             wmGD.configAction = RESIZE_CLIENT;
1268             wmGD.configPart = partContext;
1269             wmGD.configSet = True;
1270         }
1271         else if ((buttonEvent->button == SELECT_BUTTON) &&
1272             (subContext & (F_SUBCONTEXT_W_MINIMIZE|F_SUBCONTEXT_W_MAXIMIZE)))
1273         {
1274             /*
1275              * Minimize and maximize button components:
1276              * SELECT_BUTTON Press - start of a click.
1277              */
1278
1279             PushGadgetIn (pCD, partContext);
1280         }
1281            
1282         /*
1283          * Other components: no action
1284          */
1285     }
1286
1287 } /* END OF FUNCTION CheckButtonPressBuiltin */
1288
1289
1290 \f
1291 /*************************************<->*************************************
1292  *
1293  *  HandleIconButtonPress (pCD, buttonEvent)
1294  *
1295  *
1296  *  Description:
1297  *  -----------
1298  *  This function handles builtin functions in the icon context.
1299  *
1300  *
1301  *  Inputs:
1302  *  ------
1303  *  pCD = pointer to client data of the icon that received the button event
1304  *
1305  *  buttonEvent = pointer to the button event that occurred
1306  *
1307  *************************************<->***********************************/
1308
1309 void HandleIconButtonPress (ClientData *pCD, XButtonEvent *buttonEvent)
1310 {
1311     int newState;
1312
1313     /*
1314      * Do icon component button press actions:
1315      * Button 1 press - set the keyboard input focus if policy is explicit
1316      * Button 1 double-click - normalize the icon
1317      */
1318
1319     if (wmGD.clickData.doubleClickContext == F_SUBCONTEXT_I_ALL)
1320     {
1321         /*
1322          * A double-click was done, normalize the icon.
1323          */
1324
1325         if (pCD->maxConfig)
1326         {
1327             newState = MAXIMIZED_STATE;
1328         }
1329         else
1330         {
1331             newState = NORMAL_STATE;
1332         }
1333
1334         SetClientState (pCD, newState, buttonEvent->time);
1335         wmGD.clickData.clickPending = False;
1336         wmGD.clickData.doubleClickPending = False;
1337     }
1338     else
1339     {
1340         /*
1341          * This is a regular button press (it may be the start of a 
1342          * double-click).  Set the focus and top the icon if appropriate.
1343          */
1344
1345         if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)
1346         {
1347             Do_Focus_Key (pCD, buttonEvent->time, ALWAYS_SET_FOCUS);
1348         }
1349
1350
1351         /*
1352          * Indicate that a move may be starting; wait for button motion
1353          * events before moving the icon.
1354          */
1355
1356         wmGD.preMove = True;
1357         wmGD.preMoveX = buttonEvent->x_root;
1358         wmGD.preMoveY = buttonEvent->y_root;
1359         wmGD.configButton = buttonEvent->button;
1360         wmGD.configAction = MOVE_CLIENT;
1361     }
1362
1363
1364 } /* END OF FUNCTION HandleIconButtonPress */
1365
1366
1367 \f
1368 /*************************************<->*************************************
1369  *
1370  *  HandleIconBoxButtonPress (pCD, buttonEvent, subContext)
1371  *
1372  *
1373  *  Description:
1374  *  -----------
1375  *  This function handles builtin functions in the iconbox context.
1376  *
1377  *
1378  *  Inputs:
1379  *  ------
1380  *  pCD = pointer to client data of the icon that received the button event
1381  *
1382  *  buttonEvent = pointer to the button event that occurred
1383  *
1384  *  subContext = context id of event location inside icon box
1385  *
1386  *************************************<->***********************************/
1387
1388 void HandleIconBoxButtonPress (ClientData *pCD, XButtonEvent *buttonEvent, Context subContext)
1389 {
1390
1391     /*
1392      * Do iconbox icon component button press actions:
1393      * Button 1 press - select the icon
1394      * Button 1 double-click - normalize the icon or raise the window
1395      */
1396
1397     if ((wmGD.clickData.doubleClickContext == F_SUBCONTEXT_IB_IICON) ||
1398        (wmGD.clickData.doubleClickContext == F_SUBCONTEXT_IB_WICON))
1399     {
1400         F_Restore_And_Raise ((String)NULL, pCD, (XEvent *)NULL);
1401     }
1402     else if ((subContext == F_SUBCONTEXT_IB_IICON) ||
1403              (subContext == F_SUBCONTEXT_IB_WICON))
1404     {
1405         /*
1406          * Indicate that a move may be starting; wait for button motion
1407          * events before moving the icon.
1408          */
1409
1410         wmGD.preMove = True;
1411         wmGD.preMoveX = buttonEvent->x_root;
1412         wmGD.preMoveY = buttonEvent->y_root;
1413         wmGD.configButton = buttonEvent->button;
1414         wmGD.configAction = MOVE_CLIENT;
1415     }
1416
1417     /*
1418      * Do icon box icon actions:
1419      * Button 1 press - select the icon in the icon box
1420      */
1421
1422     /*
1423      * XmProcessTraversal will move the selection cursor to the
1424      * widget that was "boinked" with the mouse
1425      */
1426
1427     if ((P_ICON_BOX(pCD)->pCD_iconBox == wmGD.keyboardFocus) ||
1428         (P_ICON_BOX(pCD)->pCD_iconBox == wmGD.nextKeyboardFocus))
1429     {
1430         XmProcessTraversal (XtWindowToWidget(DISPLAY, ICON_FRAME_WIN(pCD)), 
1431                             XmTRAVERSE_CURRENT);
1432     }
1433
1434
1435 } /* END OF FUNCTION HandleIconBoxButtonPress */
1436
1437
1438 \f
1439 /*************************************<->*************************************
1440  *
1441  *  HandleCButtonRelease (pCD, buttonEvent)
1442  *
1443  *
1444  *  Description:
1445  *  -----------
1446  *  This function does window management actions associated with a button
1447  *  release event on the client window (including frame) or icon.
1448  *
1449  *
1450  *  Inputs:
1451  *  ------
1452  *  pCD = pointer to client data for the window/icon that got the event
1453  *
1454  *  buttonEvent = pointer to the button event that occurred
1455  *
1456  *  Comments:
1457  *  ---------
1458  *  Skip builtin processing if move or resize button actions were started
1459  *  due to button-up bindings.
1460  *
1461  *************************************<->***********************************/
1462
1463 void HandleCButtonRelease (ClientData *pCD, XButtonEvent *buttonEvent)
1464 {
1465     Context context;
1466     Context subContext;
1467     int partContext;
1468
1469
1470     /*
1471      * Find out whether the event was on the client window frame or the icon
1472      * and process the event accordingly.
1473      */
1474
1475     IdentifyEventContext (buttonEvent, pCD, &context, &partContext);
1476     subContext = (1L << partContext);
1477
1478     ProcessClickBRelease (buttonEvent, pCD, context, subContext);
1479
1480     if (CheckForButtonAction (buttonEvent, context, subContext, pCD) && pCD)
1481     {
1482         /*
1483          * Button bindings have been processed, now check for bindings
1484          * that associated with the built-in semantics of the window
1485          * frame decorations.
1486          */
1487
1488         CheckButtonReleaseBuiltin (buttonEvent, context, subContext, pCD);
1489     }
1490     /*
1491      * Else skip built-in processing due to execution of a function that
1492      * does on-going event processing or that has changed the client state
1493      * (e.g., f.move or f.minimize).
1494      */
1495
1496
1497     /* clear preMove state */
1498     wmGD.preMove = False;
1499
1500
1501 } /* END OF FUNCTION HandleCButtonRelease */
1502
1503
1504 \f
1505 /*************************************<->*************************************
1506  *
1507  *  HandleCKeyPress (pCD, keyEvent)
1508  *
1509  *
1510  *  Description:
1511  *  -----------
1512  *  This function does window management actions associated with a key
1513  *  press event on the client window (including frame) or icon.
1514  *
1515  *
1516  *  Inputs:
1517  *  ------
1518  *  pCD = pointer to client data for the window/icon that got the event
1519  *
1520  *  keyEvent = pointer to the key event that occurred
1521  *
1522  *
1523  *  Outputs:
1524  *  -------
1525  *  RETURN = True if the event should be dispatched by XtDispatchEvent
1526  *
1527  *************************************<->***********************************/
1528
1529 Boolean HandleCKeyPress (ClientData *pCD, XKeyEvent *keyEvent)
1530 {
1531     Boolean dispatchEvent = False;
1532     Boolean checkKeyEvent = True;
1533
1534
1535     if (wmGD.menuActive)
1536     {
1537         /*
1538          * The active menu accelerators have been checked and keyEvent was
1539          * not one of them.  We will check for an iconbox icon widget key and
1540          * for pass keys mode and then have the toolkit dispatch the event, 
1541          * without rechecking the client accelerator list.
1542          */
1543
1544         dispatchEvent = True;
1545         checkKeyEvent = False;
1546     }
1547
1548     /*
1549      * If pass keys is active then only check for getting out of the pass
1550      * keys mode if the event is on the client frame or icon frame window.
1551      * Unfreeze the keyboard and replay the key if pass keys is active.
1552      */
1553
1554     if (((keyEvent->window == ICON_FRAME_WIN(pCD)) ||
1555          (keyEvent->window == pCD->pSD->activeIconTextWin)) &&
1556         P_ICON_BOX(pCD))
1557     {
1558         /*
1559          * This is a non-grabbed key that is intended for the icon widget
1560          * in the iconbox.
1561          */
1562
1563         dispatchEvent = True; /* have the toolkit dispatch the event */
1564         checkKeyEvent = False;
1565         if (keyEvent->window == pCD->pSD->activeIconTextWin)
1566         {
1567             /*
1568              * The event is really for the icon, not the active
1569              * label, so ... correct the window id 
1570              */
1571
1572             keyEvent->window = ICON_FRAME_WIN(pCD);
1573         }
1574     }
1575     else if (wmGD.passKeysActive)
1576     {
1577         if (wmGD.passKeysKeySpec &&
1578             ((wmGD.passKeysKeySpec->state == keyEvent->state) ||
1579              (wmGD.passKeysKeySpec->state == NOLOCKMOD(keyEvent->state))) &&
1580             (wmGD.passKeysKeySpec->keycode == keyEvent->keycode))
1581         {
1582             /*
1583              * Get out of the pass keys mode.
1584              */
1585
1586             F_Pass_Key (NULL, (ClientData *) NULL, (XEvent *) NULL);
1587             XAllowEvents (DISPLAY, AsyncKeyboard, CurrentTime);
1588         }
1589         else
1590         {
1591             XAllowEvents (DISPLAY, ReplayKeyboard, CurrentTime);
1592         }
1593         checkKeyEvent = False;
1594     }
1595     else
1596     {
1597         XAllowEvents (DISPLAY, AsyncKeyboard, CurrentTime);
1598     }
1599
1600
1601     /*
1602      * Check for a "general" key binding that has been set only for the
1603      * icon context.  These key bindings are set with the keyBinding
1604      * resource or as accelerators in icon context menus.
1605      */
1606
1607     if (checkKeyEvent && (keyEvent->window == ICON_FRAME_WIN(pCD)))
1608     {
1609         if ((checkKeyEvent = HandleKeyPress (keyEvent, 
1610                                              ACTIVE_PSD->keySpecs, True,
1611                                              F_CONTEXT_ICON, False,
1612                                              (ClientData *)NULL))
1613             && ACTIVE_PSD->acceleratorMenuCount)
1614         {
1615             int n;
1616
1617             for (n = 0; ((keyEvent->keycode != 0) &&
1618                          (n < ACTIVE_PSD->acceleratorMenuCount)); n++)
1619             {
1620                 if (!HandleKeyPress (keyEvent,
1621                            ACTIVE_PSD->acceleratorMenuSpecs[n]->accelKeySpecs,
1622                            True, F_CONTEXT_ICON, True,(ClientData *)NULL))
1623                 {
1624                     checkKeyEvent = False;
1625                     break;
1626                 }
1627             }
1628         }
1629     }
1630
1631     /*
1632      * Check for a key binding that has been set as an accelerator in the
1633      * system menu.  We only do the first accelerator found.
1634      */
1635
1636     if (checkKeyEvent && pCD->systemMenuSpec &&
1637         (pCD->systemMenuSpec->accelKeySpecs))
1638     {
1639         HandleKeyPress (keyEvent, pCD->systemMenuSpec->accelKeySpecs,
1640                         FALSE, 0, TRUE,(ClientData *)NULL );
1641     }
1642
1643     return (dispatchEvent);
1644
1645 } /* END OF FUNCTION HandleCKeyPress */
1646
1647
1648 \f
1649 /*************************************<->*************************************
1650  *
1651  *  CheckButtonReleaseBuiltin (buttonEvent, context, subContext, pCD)
1652  *
1653  *
1654  *  Description:
1655  *  -----------
1656  *  This function checks to see if a built-in window manager function
1657  *  has been activated as a result of a button release. If yes, then the
1658  *  associated function is done.
1659  *
1660  *
1661  *  Inputs:
1662  *  ------
1663  *  buttonEvent = pointer to a button release event
1664  *
1665  *  context = button event context (root, icon, window)
1666  *
1667  *  subContext = button event subcontext (title, system button, ...)
1668  *
1669  *  pCD = pointer to client data for the window/icon that got the event
1670  *
1671  *************************************<->***********************************/
1672
1673 void CheckButtonReleaseBuiltin (XButtonEvent *buttonEvent, Context context, Context subContext, ClientData *pCD)
1674 {
1675     /*
1676      * All builtin button buindings are based on button 1 with no modifiers.
1677      * (Ignore locking modifiers).
1678      *
1679      * Test the event for a ``button up'' transition on buttons we are
1680      * interested in.
1681      */
1682
1683     if (!((buttonEvent->button == SELECT_BUTTON) &&
1684           (NOLOCKMOD(buttonEvent->state) == SELECT_BUTTON_MASK)) &&
1685         !((buttonEvent->button == DMANIP_BUTTON) &&
1686           (NOLOCKMOD(buttonEvent->state) == DMANIP_BUTTON_MASK)))
1687     {
1688         return;
1689     }
1690
1691
1692     /*
1693      * Process the builtin button bindings based on the window manager
1694      * component that was selected.
1695      */
1696
1697     if ((buttonEvent->button == SELECT_BUTTON) &&
1698         (context & F_CONTEXT_ICON))
1699     {
1700         /*
1701          * Do the icon component button release actions:
1702          * SELECT_BUTTON click - post the system menu if specified.
1703          */
1704
1705         if (wmGD.iconClick &&
1706             (wmGD.clickData.clickContext == F_SUBCONTEXT_I_ALL))
1707         {
1708             wmGD.checkHotspot = True;
1709
1710             /*
1711              * Post the system menu with traversal on (Button 1 should be
1712              * used to manipulate the menu).
1713              */
1714             pCD->grabContext = F_CONTEXT_ICON;
1715             PostMenu (pCD->systemMenuSpec, pCD, 0, 0, NoButton, 
1716                       F_CONTEXT_ICON, POST_STICKY, (XEvent *)buttonEvent);
1717         }
1718     }
1719 /* post menu from icon in iconbox */
1720     else if ((buttonEvent->button == SELECT_BUTTON) &&
1721              (context & F_CONTEXT_ICONBOX))
1722     {
1723         if ((wmGD.iconClick)  &&
1724             (((pCD->clientState == MINIMIZED_STATE)  &&
1725               (wmGD.clickData.clickContext == F_SUBCONTEXT_IB_IICON)) ||
1726              (wmGD.clickData.clickContext == F_SUBCONTEXT_IB_WICON))  )
1727         {
1728             wmGD.checkHotspot = True;
1729             
1730             /*
1731              * Post the system menu with traversal on (Button 1 should be
1732              * used to manipulate the menu.
1733              */
1734             if ((wmGD.clickData.clickContext == F_SUBCONTEXT_IB_IICON) &&
1735                 (pCD->clientState == MINIMIZED_STATE))
1736             {
1737                 pCD->grabContext = F_SUBCONTEXT_IB_IICON;
1738                 PostMenu (pCD->systemMenuSpec, pCD, 0, 0, NoButton,
1739                           F_SUBCONTEXT_IB_IICON, POST_STICKY, (XEvent *)buttonEvent);
1740             }
1741             else
1742             {
1743                 pCD->grabContext = F_SUBCONTEXT_IB_WICON;
1744                 PostMenu (pCD->systemMenuSpec, pCD, 0, 0, NoButton,
1745                           F_SUBCONTEXT_IB_WICON, POST_STICKY, (XEvent *)buttonEvent);
1746             }
1747         }
1748     }
1749 /* end of post menu from icon in iconbox */
1750     else if (context & F_CONTEXT_WINDOW)
1751     {
1752         /*
1753          * The button release is on a client window frame component.
1754          */
1755
1756         if ((buttonEvent->button == SELECT_BUTTON) &&
1757             (subContext == F_SUBCONTEXT_W_MINIMIZE))
1758         {
1759             /*
1760              * Minimize button:
1761              * Button 1 click - minimize the window.
1762              */
1763
1764             if (wmGD.clickData.clickContext == F_SUBCONTEXT_W_MINIMIZE)
1765             {
1766                 SetClientState (pCD, MINIMIZED_STATE, buttonEvent->time);
1767             }
1768         }
1769         else if ((buttonEvent->button == SELECT_BUTTON) &&
1770                  (subContext == F_SUBCONTEXT_W_MAXIMIZE))
1771         {
1772             /*
1773              * Maximize button:
1774              * Button 1 click - maximize the window.
1775              */
1776
1777             if (wmGD.clickData.clickContext == F_SUBCONTEXT_W_MAXIMIZE)
1778             {
1779                 if (pCD->clientState == NORMAL_STATE)
1780                 {
1781                     SetClientState (pCD, MAXIMIZED_STATE, buttonEvent->time);
1782                 }
1783                 else
1784                 {
1785                     SetClientState (pCD, NORMAL_STATE, buttonEvent->time);
1786                 }
1787             }
1788         }
1789     }
1790
1791
1792     /*
1793      * Clear the pre-configuration info that supports the move threshold.
1794      */
1795
1796     wmGD.preMove = False;
1797
1798
1799 } /* END OF FUNCTION CheckButtonReleaseBuiltin */
1800
1801
1802 \f
1803 /*************************************<->*************************************
1804  *
1805  *  HandleCMotionNotify (pCD, motionEvent)
1806  *
1807  *
1808  *  Description:
1809  *  -----------
1810  *  This function does window management actions associated with a motion
1811  *  notify event on the client window (including frame) or icon.
1812  *
1813  *
1814  *  Inputs:
1815  *  ------
1816  *  pCD = pointer to the client data for the window/icon that got the motion
1817  *
1818  *  motionEvent = pointer to the motion event
1819  *
1820  *************************************<->***********************************/
1821
1822 void HandleCMotionNotify (ClientData *pCD, XMotionEvent *motionEvent)
1823 {
1824     int diffX;
1825     int diffY;
1826
1827
1828     /*
1829      * Do pre-move processing (to support the move threshold) if appropriate:
1830      */
1831
1832     if (wmGD.preMove)
1833     {
1834         diffX = motionEvent->x_root - wmGD.preMoveX;
1835         if (diffX < 0) diffX = -diffX;
1836         diffY = motionEvent->y_root - wmGD.preMoveY;
1837         if (diffY < 0) diffY = -diffY;
1838
1839
1840         if ((diffX >= wmGD.moveThreshold) || (diffY >= wmGD.moveThreshold)) 
1841         {
1842             /*
1843              * The move threshold has been exceded; start the config action.
1844              */
1845
1846             wmGD.clickData.clickPending = False;
1847             wmGD.clickData.doubleClickPending = False;
1848             wmGD.preMove = False;
1849
1850             if (wmGD.configAction == MOVE_CLIENT)
1851             {
1852                 HandleClientFrameMove (pCD, (XEvent *) motionEvent);
1853             }
1854             else if (wmGD.configAction == RESIZE_CLIENT)
1855             {
1856                 HandleClientFrameResize (pCD, (XEvent *) motionEvent);
1857             }
1858         }
1859     }
1860
1861 } /* END OF FUNCTION HandleCMotionNotify */
1862
1863
1864 \f
1865 /*************************************<->*************************************
1866  *
1867  *  HandleCEnterNotify (pCD, enterEvent)
1868  *
1869  *
1870  *  Description:
1871  *  -----------
1872  *  This function does window management actions associated with an enter
1873  *  window event on the client window.
1874  *
1875  *
1876  *  Inputs:
1877  *  ------
1878  *  pCD = pointer to the client data for the window/icon that was entered
1879  *
1880  *  enterEvent = pointer to the enter event
1881  *
1882  *************************************<->***********************************/
1883
1884 void HandleCEnterNotify (ClientData *pCD, XEnterWindowEvent *enterEvent)
1885 {
1886     XEvent          report;
1887     Boolean         MatchFound;
1888     Window          enterWindow;
1889
1890     /*
1891      * If a client is being configured don't change the keyboard input
1892      * focus.  The input focus is "fixed" after the configuration has been
1893      * completed.
1894      */
1895
1896     if (pCD->clientState == MINIMIZED_STATE)
1897     {
1898         enterWindow = ICON_FRAME_WIN(pCD);
1899     }
1900     else
1901     {
1902         enterWindow = pCD->clientFrameWin;
1903     }
1904
1905     MatchFound = XCheckTypedWindowEvent(DISPLAY, enterWindow,
1906                                     LeaveNotify, &report);
1907
1908     /*
1909      * NOTE: Handle focus change for when user clicks button in the
1910      * process of moving focus the matching event will be NotifyGrab.
1911      *
1912      * IF (((no_match) ||
1913      *      (another window has focus and button grabbed)) &&
1914      *     pointer_mode)
1915      */
1916
1917     if ((enterEvent->detail != NotifyInferior) &&
1918         (((!MatchFound || (report.xcrossing.detail == NotifyInferior)) &&
1919           ((enterEvent->mode == NotifyNormal) ||
1920            (enterEvent->mode == NotifyUngrab)) &&
1921           !wmGD.menuActive) ||
1922
1923          (wmGD.keyboardFocus &&
1924           (wmGD.keyboardFocus->clientFrameWin != enterWindow) &&
1925           (enterEvent->mode == NotifyGrab))) &&
1926
1927         ((wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_POINTER) ||
1928          (wmGD.colormapFocusPolicy == CMAP_FOCUS_POINTER)))
1929     {
1930         /* 
1931          * Make sure that EnterNotify is applicable; don't do anything if
1932          * the window is minimized (not currently visible) or the event is
1933          * associated with an icon in the icon box.
1934          */
1935
1936         if (!(((enterEvent->window == pCD->clientFrameWin) &&
1937               (pCD->clientState == MINIMIZED_STATE)) ||
1938              (((enterEvent->window == ICON_FRAME_WIN(pCD)) && 
1939                P_ICON_BOX(pCD)) ||
1940               (enterEvent->window == pCD->pSD->activeIconTextWin))))
1941
1942         {
1943             if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_POINTER)
1944             {
1945                 /*
1946                  * Set the focus only if the window does not currently have
1947                  * or if another window is in the process of getting the
1948                  * focus (this check avoids redundant focus setting).
1949                  */
1950
1951                 if ((pCD != wmGD.keyboardFocus) ||
1952                     (pCD != wmGD.nextKeyboardFocus))
1953                 {
1954
1955                     Do_Focus_Key (pCD, enterEvent->time, ALWAYS_SET_FOCUS);
1956
1957                     /* Does the event need to be replayed for modalized windows ? */
1958                     if ( wmGD.replayEnterEvent )
1959                         /* Yes, save the event. */
1960                         memcpy( &wmGD.savedEnterEvent, enterEvent, 
1961                                 sizeof( XEnterWindowEvent ) );
1962
1963
1964 /*
1965  * The original code counted on getting a focus out event as a result
1966  * of setting the input focus in Do_Focus_key.  That would cause
1967  * SetkeyboardFocus to get called.  Unfortunately, you cannot depend on
1968  * getting a focus out.  You may have already had focus yourself.
1969  *
1970  * This bug can be produced by:
1971  *      * bring up a menu and leave it posted
1972  *      * move to a different window and click
1973  *      * the menu comes unposted, the new window has input focus, but no
1974  *        client active decorations are changed.
1975  */
1976 #ifdef SGI_FOCUS_PATCH
1977                     SetKeyboardFocus (pCD, REFRESH_LAST_FOCUS);
1978 #endif
1979                 }
1980             }
1981             if (wmGD.colormapFocusPolicy == CMAP_FOCUS_POINTER)
1982             {
1983                 SetColormapFocus (ACTIVE_PSD, pCD);
1984             }
1985         }
1986     }
1987
1988 } /* END OF FUNCTION HandleCEnterNotify */
1989
1990
1991
1992 \f
1993 /*************************************<->*************************************
1994  *
1995  *  HandleCLeaveNotify (pCD, leaveEvent)
1996  *
1997  *
1998  *  Description:
1999  *  -----------
2000  *  This function does window management actions associated with an leave
2001  *  window event on the client window.
2002  *
2003  *
2004  *  Inputs:
2005  *  ------
2006  *  pCD = pointer to the client data for the window/icon that was leaveed
2007  *
2008  *  leaveEvent = pointer to the leave event
2009  *
2010  *************************************<->***********************************/
2011
2012 void HandleCLeaveNotify (ClientData *pCD, XLeaveWindowEvent *leaveEvent)
2013 {
2014     XEvent          report;
2015     Window          leaveWindow;
2016
2017     if (pCD->clientState == MINIMIZED_STATE)
2018     {
2019         leaveWindow = ICON_FRAME_WIN(pCD);
2020     }
2021     else
2022     {
2023         leaveWindow = pCD->clientFrameWin;
2024     }
2025
2026     /*
2027      * Don't remove enterEvents when user double clicks on an icon in
2028      * an iconbox.  Otherwise the window that gets normalized will get
2029      * matching enter events and not get the focus.
2030      */
2031     if (P_ICON_BOX(pCD) &&
2032         (P_ICON_BOX(pCD)->pCD_iconBox != wmGD.keyboardFocus) &&
2033         (P_ICON_BOX(pCD)->pCD_iconBox != wmGD.nextKeyboardFocus))
2034     {
2035         XCheckTypedWindowEvent(DISPLAY, leaveWindow, EnterNotify, &report);
2036     }
2037
2038 } /* END OF FUNCTION HandleCLeaveNotify */
2039
2040
2041
2042 \f
2043 /*************************************<->*************************************
2044  *
2045  *  HandleCFocusIn (pCD, focusChangeEvent)
2046  *
2047  *
2048  *  Description:
2049  *  -----------
2050  *  This function does window management actions associated with a focus
2051  *  in event.
2052  *
2053  *
2054  *  Inputs:
2055  *  ------
2056  *  pCD = pointer to the client data for the window/icon that was entered
2057  *
2058  *  enterEvent = pointer to the focus in event
2059  *
2060  *
2061  *  Outputs:
2062  *  -------
2063  *  RETURN = True if event is to be dispatched by the toolkit
2064  *
2065  *************************************<->***********************************/
2066
2067 Boolean HandleCFocusIn (ClientData *pCD, XFocusChangeEvent *focusChangeEvent)
2068 {
2069     Boolean setupNextFocus;
2070     Boolean doXtDispatchEvent = False;
2071
2072     /*
2073      * Ignore the event if it is for a window that is no longer viewable.
2074      * This is the case for a client window FocusIn event that is being
2075      * processed for a window that has been minimized.
2076      */
2077
2078     if ((focusChangeEvent->window == ICON_FRAME_WIN(pCD)) && 
2079         P_ICON_BOX(pCD))
2080     {
2081         doXtDispatchEvent = True;
2082     }
2083     else if (((focusChangeEvent->mode == NotifyNormal) ||
2084              (focusChangeEvent->mode == NotifyWhileGrabbed)) &&
2085             !((focusChangeEvent->window == pCD->clientBaseWin) &&
2086               (pCD->clientState == MINIMIZED_STATE)) &&
2087             !((focusChangeEvent->window == ICON_FRAME_WIN(pCD)) &&
2088               (pCD->clientState != MINIMIZED_STATE)))
2089     {
2090         setupNextFocus = (wmGD.keyboardFocus == wmGD.nextKeyboardFocus);
2091
2092         if (wmGD.keyboardFocus != pCD)
2093         {
2094             if ((focusChangeEvent->detail == NotifyNonlinear) ||
2095                 (focusChangeEvent->detail == NotifyNonlinearVirtual))
2096             {
2097                 SetKeyboardFocus (pCD, REFRESH_LAST_FOCUS);
2098                 if (setupNextFocus)
2099                 {
2100                     wmGD.nextKeyboardFocus = wmGD.keyboardFocus;
2101                 }
2102             }
2103             /* Re: CR 4896                                                  */
2104             /* this part added to try and fix the %#$!@!!&* focus bug.      */
2105             /* this seems to solve most of the problem.  This still leaves  */
2106             /* times when clicking on an icon toggles the focus back to the */
2107             /* the previous focus window.                                   */
2108             /* Another patch was added to WmEvent.c to fix that problem.    */
2109             else
2110             {
2111                 SetKeyboardFocus (pCD, REFRESH_LAST_FOCUS);
2112                 if (setupNextFocus) wmGD.nextKeyboardFocus = wmGD.keyboardFocus;
2113             }
2114         }
2115         else if ((focusChangeEvent->detail == NotifyInferior) &&
2116                  (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT))
2117         {
2118             /*
2119              * The client window was withdrawn (unmapped or destroyed).
2120              * Reset the focus.
2121              * !!! pointer focus !!!
2122              */
2123
2124             if (wmGD.autoKeyFocus)
2125             {
2126                 /* !!! fix this up to handle transient windows !!! */
2127                 AutoResetKeyFocus (wmGD.keyboardFocus, GetTimestamp ());
2128             }
2129             else
2130             {
2131                 Do_Focus_Key ((ClientData *) NULL, GetTimestamp (), 
2132                         ALWAYS_SET_FOCUS);
2133             }
2134         }
2135     }
2136
2137     pCD->focusAutoRaiseDisabled = False;
2138
2139     return (doXtDispatchEvent);
2140
2141 } /* END OF FUNCTION HandleCFocusIn */
2142
2143
2144 \f
2145 /*************************************<->*************************************
2146  *
2147  *  HandleCFocusOut (pCD, focusChangeEvent)
2148  *
2149  *
2150  *  Description:
2151  *  -----------
2152  *  This function does window management actions associated with a focus
2153  *  out event that applies to a client window.
2154  *
2155  *
2156  *  Inputs:
2157  *  ------
2158  *  pCD = pointer to the client data for the window/icon that was entered
2159  *
2160  *  enterEvent = pointer to the focus out event
2161  *
2162  *
2163  *  Outputs:
2164  *  -------
2165  *  RETURN = True if event is to be dispatched by the toolkit
2166  *
2167  *************************************<->***********************************/
2168
2169 Boolean HandleCFocusOut (ClientData *pCD, XFocusChangeEvent *focusChangeEvent)
2170 {
2171     Boolean doXtDispatchEvent = False;
2172     long focusFlags = REFRESH_LAST_FOCUS ;
2173
2174     pCD->focusAutoRaiseDisabled = False;
2175
2176     /*
2177      * Ignore the event if it is for a window that is no longer viewable.
2178      * This is the case for a client window FocusOut event that is being
2179      * processed for a window that has been minimized. Also, ignore focus
2180      * out events for clients that aren't on the current screen.
2181      */
2182
2183     if (((focusChangeEvent->window == ICON_FRAME_WIN(pCD)) && 
2184          P_ICON_BOX(pCD)) ||
2185         (SCREEN_FOR_CLIENT(pCD) != ACTIVE_SCREEN))
2186     {
2187         doXtDispatchEvent = True;
2188     }
2189     else if ((wmGD.keyboardFocus == pCD) &&
2190              (focusChangeEvent->mode == NotifyNormal) &&
2191              ((focusChangeEvent->detail == NotifyNonlinear) ||
2192               (focusChangeEvent->detail == NotifyNonlinearVirtual)) &&
2193              !((focusChangeEvent->window == pCD->clientBaseWin) &&
2194                (pCD->clientState == MINIMIZED_STATE)) &&
2195              !((focusChangeEvent->window == ICON_FRAME_WIN(pCD)) &&
2196                (pCD->clientState != MINIMIZED_STATE)))
2197     {
2198         /*
2199          * The keyboard focus was shifted to another window, maybe on
2200          * another screen.  Clear the focus indication and reset focus
2201          * handling for the client window.
2202          */
2203
2204         /*
2205          * use SCREEN_SWITCH_FOCUS in SetKeyboardFocus to
2206          * not call SetColormapFocus if we are moveing
2207          * to another screen
2208          */
2209         if (SCREEN_FOR_CLIENT(pCD) != ACTIVE_SCREEN)
2210         {
2211             focusFlags |= SCREEN_SWITCH_FOCUS;
2212         }
2213         SetKeyboardFocus ((ClientData *) NULL, focusFlags);
2214         if (wmGD.nextKeyboardFocus == pCD)
2215         {
2216             wmGD.nextKeyboardFocus = NULL;
2217         }
2218     }
2219
2220     return (doXtDispatchEvent);
2221
2222 } /* END OF FUNCTION HandleCFocusOut */
2223
2224
2225 \f
2226 /*************************************<->*************************************
2227  *
2228  *  HandleCConfigureRequest (pCD, configureRequest)
2229  *
2230  *
2231  *  Description:
2232  *  -----------
2233  *  This functions handles ConfigureRequest events that are for client windows.
2234  *
2235  *
2236  *  Inputs:
2237  *  ------
2238  *  pCD = pointer to client data
2239  *
2240  *  configureRequest = a pointer to a ConfigureRequest event
2241  *
2242  *************************************<->***********************************/
2243
2244 void HandleCConfigureRequest (ClientData *pCD, XConfigureRequestEvent *configureRequest)
2245 {
2246     unsigned int mask = configureRequest->value_mask;
2247     int stackMode = configureRequest->detail;
2248     unsigned int changeMask;
2249     ClientData *pcdLeader;
2250     ClientData *pcdSibling;
2251     ClientListEntry *pStackEntry;
2252
2253
2254     /*
2255      * Call ProcessNewConfiguration to handle window moving and resizing.
2256      * Send ConfigureNotify event (based on ICCCM conventions).
2257      * Then process the request for stacking.
2258      */
2259
2260     if ((configureRequest->window == pCD->client) &&
2261         (mask & (CWX | CWY | CWWidth | CWHeight | CWBorderWidth)))
2262     {
2263         if (pCD->maxConfig) {
2264             ProcessNewConfiguration (pCD,
2265                 (mask & CWX) ? configureRequest->x : pCD->maxX,
2266                 (mask & CWY) ? configureRequest->y : pCD->maxY,
2267                 (unsigned int) ((mask & CWWidth) ? 
2268                     configureRequest->width : pCD->maxWidth),
2269                 (unsigned int) ((mask & CWHeight) ? 
2270                     configureRequest->height : pCD->maxHeight),
2271                 True /*client request*/);
2272         }
2273         else {
2274             int xOff, yOff;
2275
2276             /* CDExc21094 - ProcessNewConfiguration() offsets the */
2277             /* x and y positions passed in; in order to keep them */
2278             /* the same, we offset them in the opposite direction. */
2279             if (wmGD.positionIsFrame)
2280             {
2281                 xOff = pCD->clientOffset.x;
2282                 yOff = pCD->clientOffset.y;
2283             }
2284             else
2285             {
2286                 xOff = yOff = 0;
2287             }
2288
2289             ProcessNewConfiguration (pCD,
2290                 (mask & CWX) ? configureRequest->x : pCD->clientX - xOff,
2291                 (mask & CWY) ? configureRequest->y : pCD->clientY - yOff,
2292                 (unsigned int) ((mask & CWWidth) ? 
2293                     configureRequest->width : pCD->clientWidth),
2294                 (unsigned int) ((mask & CWHeight) ? 
2295                     configureRequest->height : pCD->clientHeight),
2296                 True /*client request*/);
2297         }
2298     }
2299
2300     if (mask & CWStackMode)
2301     {
2302         changeMask = mask & (CWSibling | CWStackMode);
2303         if (changeMask & CWSibling)
2304         {
2305             if (XFindContext (DISPLAY, configureRequest->above,
2306                     wmGD.windowContextType, (caddr_t *)&pcdSibling))
2307             {
2308                 changeMask &= ~CWSibling;
2309             }
2310             else
2311             {
2312                 /*
2313                  * For client requests only primary windows can be
2314                  * restacked relative to one another.
2315                  */
2316
2317                 pcdLeader = FindTransientTreeLeader (pCD);
2318                 pcdSibling = FindTransientTreeLeader (pcdSibling);
2319                 if (pcdLeader == pcdSibling)
2320                 {
2321                     changeMask &= ~CWSibling;
2322                 }
2323                 else
2324                 {
2325                     pStackEntry = &pcdSibling->clientEntry;
2326                     if ((stackMode == Above) || (stackMode == TopIf))
2327                     {
2328                         /* lower the window to just above the sibling */
2329                         Do_Lower (pcdLeader, pStackEntry, STACK_NORMAL);
2330                     }
2331                     else if ((stackMode == Below) || (stackMode == BottomIf))
2332                     {
2333                         /* raise the window to just below the sibling */
2334                         Do_Raise (pcdLeader, pStackEntry, STACK_NORMAL);
2335                     }
2336                     else if (stackMode == Opposite)
2337                     {
2338                         F_Raise_Lower (NULL, pCD, (XEvent *)configureRequest);
2339                     }
2340                 }
2341             }
2342         }
2343
2344         if (!(changeMask & CWSibling))
2345         {
2346             if ((stackMode == Above) || (stackMode == TopIf))
2347             {
2348                 Do_Raise (pCD, (ClientListEntry *) NULL, STACK_NORMAL);
2349             }
2350             else if ((stackMode == Below) || (stackMode == BottomIf))
2351             {
2352                 Do_Lower (pCD, (ClientListEntry *) NULL, STACK_NORMAL);
2353             }
2354             else if (stackMode == Opposite)
2355             {
2356                 F_Raise_Lower (NULL, pCD, (XEvent *) configureRequest);
2357             }
2358         }
2359
2360         /* !!! should a synthetic ConfigureNotify be sent? !!! */
2361         if ((configureRequest->window == pCD->client) &&
2362             !(mask & (CWX | CWY | CWWidth | CWHeight | CWBorderWidth)))
2363         {
2364             SendConfigureNotify (pCD);
2365         }
2366     }
2367
2368
2369 } /* END OF FUNCTION HandleCConfigureRequest */
2370
2371
2372 \f
2373 /*************************************<->*************************************
2374  *
2375  *  HandleCColormapNotify (pCD, colorEvent)
2376  *
2377  *
2378  *  Description:
2379  *  -----------
2380  *  This function does window management actions associated with a colormap
2381  *  notify event on the client window.
2382  *
2383  *
2384  *  Inputs:
2385  *  ------
2386  *  pCD = pointer to client data
2387  *
2388  *  colorEvent = a ColormapNotify event
2389  *
2390  *************************************<->***********************************/
2391
2392 void HandleCColormapNotify (ClientData *pCD, XColormapEvent *colorEvent)
2393 {
2394     int i;
2395 #ifndef IBM_169380
2396     ClientData  **cmap_window_data;
2397 #endif
2398     Boolean newClientColormap = False;
2399
2400
2401     /*
2402      * The colormap of the top-level client window or one of its subwindows
2403      * has been changed.
2404      */
2405
2406
2407     if (colorEvent->new)
2408     {
2409         /*
2410          * The colormap has been changed.
2411          */
2412
2413         /*
2414          * !!! when the server ColormapNotify problem is fixed !!!
2415          * !!! use the colormap id from the event              !!!
2416          */
2417         if (WmGetWindowAttributes (colorEvent->window))
2418         {
2419             colorEvent->colormap = wmGD.windowAttributes.colormap;
2420         }
2421         else
2422         {
2423             return;
2424         }
2425         /*
2426          * !!! remove the above code when the problem is fixed  !!!
2427          */
2428
2429         /*
2430          * Identify the colormap that the window manager has associated
2431          * with the window.
2432          */
2433
2434 #ifndef IBM_169380
2435         if ((pCD->clientCmapCount == 0) && (colorEvent->window == pCD->client))
2436 #endif
2437         if (pCD->clientCmapCount == 0)
2438         {
2439             /* no subwindow colormaps; change top-level window colormap */
2440 #ifdef  IBM_169380
2441             if (colorEvent->window == pCD->client)
2442             {
2443 #endif
2444                 if (colorEvent->colormap == None)
2445                 {
2446                     /* use the workspace colormap */
2447                     pCD->clientColormap = 
2448                         ACTIVE_PSD->workspaceColormap;
2449                 }
2450                 else
2451                 {
2452                     pCD->clientColormap = colorEvent->colormap;
2453                 }
2454                 newClientColormap = True;
2455 #ifdef  IBM_169380
2456             }
2457 #endif
2458         }
2459
2460 #ifndef IBM_169380
2461         if (!XFindContext (DISPLAY, colorEvent->window,
2462             wmGD.cmapWindowContextType, (caddr_t *)&cmap_window_data))
2463         {
2464             /*
2465              * The WM_COLORMAP_WINDOWS property of a toplevel window may
2466              * specify colorEvent->window.  If so, we must update the
2467              * colormap information it holds in clientCmapList.
2468              */
2469             ClientData  *any_pCD;
2470             int         j;
2471
2472             for (j = 0; cmap_window_data[j] != NULL; j++)
2473             {
2474                 any_pCD = cmap_window_data[j];
2475                 for (i = 0; i < any_pCD->clientCmapCount; i++)
2476                 {
2477                     if (any_pCD->cmapWindows[i] == colorEvent->window)
2478                     {
2479                         if (colorEvent->colormap == None)
2480                         {
2481                             /* use the workspace colormap */
2482                             any_pCD->clientCmapList[i] =
2483                                 ACTIVE_PSD->workspaceColormap;
2484                         }
2485                         else
2486                         {
2487                             any_pCD->clientCmapList[i] = colorEvent->colormap;
2488                         }
2489                         if (i == any_pCD->clientCmapIndex)
2490                         {
2491                             any_pCD->clientColormap =
2492                                 any_pCD->clientCmapList[i];
2493                             if (any_pCD == pCD)
2494                             {
2495                                 newClientColormap = True;
2496                             }
2497                         }
2498                         break;
2499                     }
2500                 }
2501             }
2502         }
2503 #else
2504         else
2505         {
2506             /* there are subwindow colormaps */
2507             for (i = 0; i < pCD->clientCmapCount; i++)
2508             {
2509                 if (pCD->cmapWindows[i] == colorEvent->window)
2510                 {
2511                     if (colorEvent->colormap == None)
2512                     {
2513                         /* use the workspace colormap */
2514                         pCD->clientCmapList[i] = 
2515                             ACTIVE_PSD->workspaceColormap;
2516                     }
2517                     else
2518                     {
2519                         pCD->clientCmapList[i] = colorEvent->colormap;
2520                     }
2521                     if (i == pCD->clientCmapIndex)
2522                     {
2523                         newClientColormap = True;
2524                         pCD->clientColormap = pCD->clientCmapList[i];
2525                     }
2526                     break;
2527                 }
2528             }
2529         }
2530 #endif  /* IBM_169380 */
2531
2532         if ((ACTIVE_PSD->colormapFocus == pCD) && newClientColormap &&
2533             ((pCD->clientState == NORMAL_STATE) ||
2534             (pCD->clientState == MAXIMIZED_STATE)))
2535         {
2536             /*
2537              * The client window has the colormap focus, install the
2538              * colormap.
2539              */
2540
2541             WmInstallColormap (ACTIVE_PSD, pCD->clientColormap);
2542         }
2543     }
2544
2545
2546 } /* END OF FUNCTION HandleCColormapNotify */
2547
2548
2549 \f
2550 /*************************************<->*************************************
2551  *
2552  *  HandleClientMessage (pCD, clientEvent)
2553  *
2554  *
2555  *  Description:
2556  *  -----------
2557  *  This function handles client message events that are sent to the root
2558  *  window.  The window manager action that is taken depends on the
2559  *  message_type of the event.
2560  *
2561  *
2562  *  Inputs:
2563  *  ------
2564  *  pCD = pointer to client data
2565  *
2566  *  clientEvent = pointer to a client message event on the root window
2567  * 
2568  *************************************<->***********************************/
2569
2570 void HandleClientMessage (ClientData *pCD, XClientMessageEvent *clientEvent)
2571 {
2572     unsigned int newState;
2573
2574     /*
2575      * Process the client message event based on the message_type.
2576      */
2577
2578     if (clientEvent->message_type == wmGD.xa_WM_CHANGE_STATE)
2579     {
2580         if ((clientEvent->data.l[0] == IconicState) &&
2581             (pCD->clientFunctions & MWM_FUNC_MINIMIZE))
2582         {
2583             newState = MINIMIZED_STATE;
2584         }
2585         else if (clientEvent->data.l[0] == NormalState)
2586         {
2587             newState = NORMAL_STATE;
2588         }
2589 #ifdef WSM
2590         if (!ClientInWorkspace (ACTIVE_WS, pCD))
2591         {
2592             newState |= UNSEEN_STATE;
2593         }
2594 #endif /* WSM */
2595
2596         SetClientState (pCD, newState, GetTimestamp ());
2597
2598     }
2599
2600 } /* END OF FUNCTION HandleClientMessage */
2601
2602
2603 #ifndef NO_SHAPE
2604 \f
2605 /*************************************<->*************************************
2606  *
2607  *  HandleCShapeNotify (pCD, shapeEvent)
2608  *
2609  *
2610  *  Description:
2611  *  -----------
2612  *  Handle a shape notify event on a client window. Keeps track of
2613  *  the shaped state of the client window and calls
2614  *  SetFrameShape() to reshape the frame accordingly.
2615  *
2616  *  Inputs:
2617  *  ------
2618  *  shapeEvent = pointer to a shape notify in event on the client window.
2619  *
2620  *************************************<->***********************************/
2621 void
2622 HandleCShapeNotify (ClientData *pCD,  XShapeEvent *shapeEvent)
2623 {
2624     if (pCD)
2625     {
2626         if (shapeEvent->kind != ShapeBounding)
2627         {
2628             return;
2629         }
2630         
2631         pCD->wShaped = shapeEvent->shaped;
2632         SetFrameShape (pCD);
2633     }
2634 } /* END OF FUNCTION HandleCShapeNotify */
2635 #endif /* NO_SHAPE */
2636
2637 \f
2638 /*************************************<->*************************************
2639  *
2640  *  GetParentWindow (window)
2641  *
2642  *
2643  *  Description:
2644  *  -----------
2645  *  This function identifies the parent window of the specified window.
2646  *
2647  *
2648  *  Inputs:
2649  *  ------
2650  *  window = find the parent of this window
2651  * 
2652  *  Outputs:
2653  *  -------
2654  *  Return = return the window id of the parent of the specified window
2655  * 
2656  *************************************<->***********************************/
2657
2658 Window GetParentWindow (Window window)
2659 {
2660     Window root;
2661     Window parent;
2662     Window *children;
2663     unsigned int nchildren;
2664
2665
2666     if (XQueryTree (DISPLAY, window, &root, &parent, &children, &nchildren))
2667     {
2668         if (nchildren)
2669         {
2670             XFree ((char *)children);
2671         }
2672     }
2673     else
2674     {
2675         parent = (Window)0L;
2676     }
2677
2678     return (parent);
2679
2680
2681 } /* END OF FUNCTION GetParentWindow */
2682
2683 \f
2684 /*************************************<->*************************************
2685  *
2686  *  DetermineActiveScreen (pEvent)
2687  *
2688  *
2689  *  Description:
2690  *  -----------
2691  *  This function determines the currently active screen
2692  *
2693  *
2694  *  Inputs:
2695  *  ------
2696  *  pEvent = pointer to an event structure
2697  * 
2698  *  Outputs:
2699  *  -------
2700  *  ACTIVE_PSD =  set to point to the screen data for the currently
2701  *                active scree;
2702  *  wmGD.queryScreen =  set to False if we're sure about the ACTIVE_PSD
2703  *                      setting
2704  * 
2705  *************************************<->***********************************/
2706
2707 void DetermineActiveScreen (XEvent *pEvent)
2708 {
2709     WmScreenData *pSD;
2710
2711     switch (pEvent->type)
2712     {
2713         case NoExpose:
2714         case GraphicsExpose:
2715                 break;          /* ignore these events */
2716
2717         default:
2718                 /*
2719                  * Get the screen that the event occurred on.
2720                  */
2721                 pSD = GetScreenForWindow (pEvent->xany.window);
2722
2723                 if (pSD) 
2724                 {
2725                     /*
2726                      * Set the ACTIVE_PSD to the event's screen to
2727                      * make sure the event gets handled correctly.
2728                      */
2729                     SetActiveScreen (pSD);
2730                 }
2731                 break;
2732     }
2733
2734 } /* END OF FUNCTION DetermineActiveScreen */
2735
2736 \f
2737 /*************************************<->*************************************
2738  *
2739  *  GetScreenForWindow (win)
2740  *
2741  *
2742  *  Description:
2743  *  -----------
2744  *  This function determines the screen for a window
2745  *
2746  *
2747  *  Inputs:
2748  *  ------
2749  *  win = window id
2750  * 
2751  *  Outputs:
2752  *  -------
2753  *  value of function = pointer to screen data (pSD) or NULL on failure
2754  * 
2755  *************************************<->***********************************/
2756
2757 WmScreenData * GetScreenForWindow (win)
2758     Window win;
2759
2760 {
2761     XWindowAttributes attribs;
2762     WmScreenData *pSD = NULL;
2763
2764
2765     /*
2766      * Get the screen that the event occurred on.
2767      */
2768     if (XGetWindowAttributes (DISPLAY, win, &attribs))
2769     {
2770         if (!XFindContext (DISPLAY, attribs.root, wmGD.screenContextType, 
2771                             (caddr_t *)&pSD))
2772         {
2773             if (pSD && !pSD->screenTopLevelW)
2774             {
2775                 pSD = NULL;
2776             }
2777         }
2778     }
2779
2780     return (pSD);
2781
2782 } /* END OF FUNCTION GetScreenForWindow */