dtwm: Cleanup some implicit definitions
[oweals/cde.git] / cde / programs / dtwm / WmWinState.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 OPEN SOFTWARE FOUNDATION, INC. 
25  * ALL RIGHTS RESERVED 
26 */ 
27 /* 
28  * Motif Release 1.2.1
29 */ 
30 #ifdef REV_INFO
31 #ifndef lint
32 static char rcsid[] = "$XConsortium: WmWinState.c /main/6 1996/06/20 09:39: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 #include "WmProtocol.h"
45 #include "WmIPC.h"
46
47
48 /*
49  * include extern functions
50  */
51
52 #include "WmCDecor.h"
53 #include "WmFunction.h"
54 #include "WmIDecor.h"
55 #include "WmIPlace.h"
56 #include "WmIconBox.h"
57 #include "WmKeyFocus.h"
58 #ifdef PANELIST
59 #include "WmPanelP.h"  /* for typedef in WmManage.h */
60 #endif /* PANELIST */
61 #include "WmManage.h"
62 #include "WmProperty.h"
63 #include "WmWinInfo.h"
64 #include "WmWinList.h"
65 #ifdef WSM
66 #include "WmWrkspace.h"
67 #endif /* WSM */
68
69
70 /*
71  * Function Declarations:
72  */
73
74 #include "WmWinState.h"
75 #ifdef PANELIST
76 static void SlideWindowOut (ClientData *pCD);
77 #endif /* PANELIST */
78 static void UnmapClients (ClientData *pCD, unsigned int event_mask);
79 static void SetupWindowStateWithEventMask (ClientData *pCD, int newState, Time setTime, unsigned int event_mask);
80
81
82
83 /*
84  * Global Variables:
85  */
86 extern int firstTime;
87
88 \f
89 /******************************<->*************************************
90  *
91  *  SetClientState (pCD, newState, setTime)
92  *
93  *
94  *  Description:
95  *  -----------
96  *  This function is used to change the state of a client window (between
97  *  withdrawn, normal, minimized, maximized).
98  *
99  *
100  *  Inputs:
101  *  ------
102  *  pCD = This is a pointer to the window data for the window that
103  *        is to have its state changed. The fields that are used
104  *        are clientState, ...
105  *
106  *  newState = This is the state that the client window is to be changed to.
107  *
108  *  setTime = timestamp for state setting operations
109  *
110  * 
111  *  Outputs:
112  *  -------
113  *  pCD.clientState = new client state
114  *
115  ******************************<->***********************************/
116
117 void SetClientState (ClientData *pCD, int newState, Time setTime)
118 {
119         SetClientStateWithEventMask(pCD, newState, setTime, (unsigned int)0);
120 } /* END OF FUNCTION SetClientState */
121
122 void SetClientStateWithEventMask (ClientData *pCD, int newState, Time setTime, unsigned int event_mask)
123 {
124     ClientData *pcdLeader;
125     int currentState;
126     WmScreenData *pSD = PSD_FOR_CLIENT(pCD);
127 #ifdef WSM
128     Boolean notShowing = (newState & UNSEEN_STATE);
129 #endif /* WSM */
130
131     currentState = pCD->clientState;
132     if (currentState == newState)
133     {
134         /* no change in state */
135         return;
136     }
137
138
139     /*
140      * Undo the old state and setup the new state.  If this is a transient
141      * window then insure that it is put in a state that is compatible
142      * with its transient leader (e.g., it cannot be minimized separately).
143      */
144
145     pcdLeader = (pCD->transientLeader) ? FindTransientTreeLeader (pCD) : pCD;
146 #ifdef WSM
147     SetClientWsIndex (pCD);
148 #endif /* WSM */
149
150     if (pCD->transientLeader)
151     {
152         if ((pcdLeader->clientState == MINIMIZED_STATE) &&
153             (newState != WITHDRAWN_STATE))
154         {
155             newState = MINIMIZED_STATE;
156 #ifdef WSM
157             if (notShowing)
158             {
159                 newState |= UNSEEN_STATE;
160             }
161 #endif /* WSM */
162         }
163         else if ((newState == MINIMIZED_STATE) &&
164                  (pcdLeader->clientState != MINIMIZED_STATE))
165         {
166             if (currentState == WITHDRAWN_STATE)
167             {
168                 newState = NORMAL_STATE;
169 #ifdef WSM
170             if (notShowing)
171             {
172                 newState |= UNSEEN_STATE;
173             }
174 #endif /* WSM */
175             }
176             else
177             {
178                 newState = currentState;
179 #ifdef WSM
180             if (notShowing)
181             {
182                 newState |= UNSEEN_STATE;
183             }
184 #endif /* WSM */
185             }
186         }
187         if (newState == currentState)
188         {
189             return;
190         }
191     }
192
193     switch (newState)
194     {
195
196 #ifdef WSM
197         case UNSEEN_STATE | WITHDRAWN_STATE:
198 #else
199         case WITHDRAWN_STATE:
200 #endif /* WSM */
201         {
202             /*
203              * Free window manager resources (frame and icon).  The
204              * WM_STATE property is set in WithdrawWindow.
205              */
206
207             UnManageWindow (pCD);
208             break;
209         }
210
211         case NORMAL_STATE:
212         case MAXIMIZED_STATE:
213         {
214             SetupWindowStateWithEventMask (pCD, newState, setTime, event_mask);
215 #ifdef WSM
216             XMapWindow (DISPLAY, pCD->client);
217             XMapWindow (DISPLAY, pCD->clientFrameWin);
218 #if defined(PANELIST)
219             WmStopWaiting();   /* in WmIPC.c */
220 #endif /* PANELIST */
221 #endif /* WSM */
222             break;
223         }
224
225         case MINIMIZED_STATE:
226         {
227             Boolean clientHasFocus;
228
229             /*
230              * Transient windows are minimized with the rest of the transient
231              * tree, including the transient leader.
232              */
233
234             if ((pCD->clientState == NORMAL_STATE) ||
235                 (pCD->clientState == MAXIMIZED_STATE))
236             {
237                 if ((wmGD.keyboardFocus == pCD) ||
238                     (pCD->transientChildren && wmGD.keyboardFocus &&
239                      (pCD == FindTransientTreeLeader (wmGD.keyboardFocus))))
240                 {
241                     clientHasFocus = True;
242                 }
243                 else
244                 {
245                     clientHasFocus = False;
246                 }
247
248                 if (clientHasFocus ||
249                   ((wmGD.nextKeyboardFocus == pCD) ||
250                    (pCD->transientChildren && wmGD.keyboardFocus &&
251                     (pCD == FindTransientTreeLeader (wmGD.nextKeyboardFocus)))))
252                 {
253                     /*
254                      * Give up the keyboard focus when minimized (including
255                      * the case in which an associated transient window has
256                      * the focus).  Immediately remove the focus indication
257                      * from the window being minimized.
258                      */
259
260                     if (wmGD.autoKeyFocus &&
261                         (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT))
262                     {
263                         AutoResetKeyFocus (pcdLeader, setTime);
264                     }
265                     else
266                     {
267                         Do_Focus_Key (NULL, setTime, 
268                                 ALWAYS_SET_FOCUS | WORKSPACE_IF_NULL);
269                     }
270
271                     if (clientHasFocus)
272                     {
273                         SetKeyboardFocus (NULL, 0);
274                     }
275                 }
276
277                 /* unmap main client and all transients */
278                 UnmapClients (pCD, event_mask);
279             }
280
281             /*
282              * Display the icon for the minimized client.
283              */
284
285             if (ICON_FRAME_WIN(pCD)) 
286             {
287 #ifdef WSM
288                 if (pCD->clientState & UNSEEN_STATE)
289                 {
290                     if (pCD->iconWindow)
291                     {
292                         XMapWindow (DISPLAY, pCD->iconWindow);
293                     }
294                     XMapWindow (DISPLAY, ICON_FRAME_WIN(pCD));
295                 }
296
297                 ShowAllIconsForMinimizedClient (pCD);
298 #else /* WSM */
299                 ShowIconForMinimizedClient (pSD->pActiveWS, pCD);
300 #endif /* WSM */
301             }
302
303             SetClientWMState (pCD, IconicState, MINIMIZED_STATE);
304
305             if ((pSD->useIconBox) && P_ICON_BOX(pCD))
306             {
307                 if ((pCD->clientFlags & ICON_BOX) && ACTIVE_ICON_TEXT_WIN)
308                 {
309                     /*
310                      * Hide active icon text window and reparent it to
311                      * root
312                      */
313                     HideActiveIconText((WmScreenData *)NULL);
314                     pSD->activeLabelParent = ACTIVE_ROOT;
315                     XReparentWindow(DISPLAY, ACTIVE_ICON_TEXT_WIN , 
316                                 ACTIVE_ROOT, 0, 0 );
317                 }
318                 if (ICON_FRAME_WIN(pCD))
319                 {
320                     /* 
321                      * force icon appearance in icon box to change 
322                      */
323                     IconExposureProc (pCD, True);
324                 }
325             }
326             break;
327         }
328
329 #ifdef WSM 
330
331         case UNSEEN_STATE | NORMAL_STATE:
332         case UNSEEN_STATE | MAXIMIZED_STATE:
333         case UNSEEN_STATE | MINIMIZED_STATE:
334         {
335             if (wmGD.keyboardFocus == pCD)
336             {
337                 /*
338                  * Give up the keyboard focus 
339                  */
340                 Do_Focus_Key ((ClientData *)NULL, 
341                         CurrentTime, ALWAYS_SET_FOCUS);
342                 SetKeyboardFocus (NULL, 0);
343             }
344
345             if (!(pCD->clientState & UNSEEN_STATE) &&
346                  (((pCD->clientState & ~UNSEEN_STATE) == NORMAL_STATE) ||
347                   ((pCD->clientState & ~UNSEEN_STATE) == MAXIMIZED_STATE)))
348             {
349                 /* unmap main client and all transients */
350                 UnmapClients (pcdLeader, event_mask);
351
352             }
353       
354             if (pCD->clientFrameWin) 
355             {
356                 if (!P_ICON_BOX(pCD))
357                 {
358                     if (ICON_FRAME_WIN(pCD))
359                     {
360                         XUnmapWindow (DISPLAY, ICON_FRAME_WIN(pCD));
361                     }
362                     if (pCD->iconWindow)
363                         XUnmapWindow (DISPLAY, pCD->iconWindow);
364                 } 
365             }
366
367             switch (newState & ~UNSEEN_STATE)
368             {
369             case MINIMIZED_STATE:
370                 SetClientWMState (pCD, IconicState, newState);
371                 break;
372
373             case NORMAL_STATE:
374             case MAXIMIZED_STATE:
375             default:
376                 SetClientWMState (pCD, NormalState, newState);
377                 break;
378             }
379         }
380         break;
381 #endif /* WSM */
382     }
383
384 } /* END OF FUNCTION SetClientStateWithEventMask */
385
386
387 \f
388 /*************************************<->*************************************
389  *
390  *  SetupWindowStateWithEventMask (pCD, newState, setTime, event_mask)
391  *
392  *
393  *  Description:
394  *  -----------
395  *  This function is used to setup a client window in the Normal or Maximized
396  *  state.
397  *
398  *
399  *  Inputs:
400  *  ------
401  *  pCD = This is a pointer to the window data for the window that
402  *        is to have its state changed.
403  *
404  *  newState = This is the state that the client window is to be changed to.
405  *
406  *  setTime = timestamp for state setting operations
407  *
408  *  event_mask = what to grab to prevent stray events going somewhere
409  * 
410  *  Outputs:
411  *  -------
412  *  pCD.clientState = new client state
413  *
414  *************************************<->***********************************/
415
416 static void SetupWindowStateWithEventMask (ClientData *pCD, int newState, 
417         Time setTime, unsigned int event_mask)
418 {
419     int currentState;
420 #ifdef WSM
421     int wsI, iplace;
422     WmWorkspaceData *pWS_i;
423 #else /* WSM */
424     WmWorkspaceData *pWS = PSD_FOR_CLIENT(pCD)->pActiveWS;
425 #endif /* WSM */
426     WmScreenData *pSD = PSD_FOR_CLIENT(pCD);
427
428     currentState = pCD->clientState;
429
430     /*
431      * A transient window is not restored or maximized if the transient leader
432      * is minimized.
433      */
434
435     if (newState == NORMAL_STATE)
436     {
437         if (pCD->maxConfig == True)
438         {
439             /*
440              * The configuration function uses maxConfig to determine
441              * what the current configuration is (and then resets
442              * maxConfig) and uses the state paramenter to determine
443              * what the new configuration is.
444              */
445
446             ConfigureNewState (pCD); 
447         }
448     }
449     else /* MAXIMIZED_STATE */
450     {
451         if (pCD->maxConfig == False)
452         {
453             ConfigureNewState (pCD); 
454         }
455     }
456
457     if (currentState == MINIMIZED_STATE)
458     {
459         Boolean clearIconFocus;
460
461         /*
462          * give up keyboard focus 
463          */
464
465         if ((wmGD.keyboardFocus == pCD) ||
466             (wmGD.nextKeyboardFocus == pCD))
467         {
468             Do_Focus_Key (NULL, setTime, ALWAYS_SET_FOCUS | WORKSPACE_IF_NULL);
469         }
470
471         if (wmGD.keyboardFocus == pCD)
472         {
473             clearIconFocus = True;
474         }
475         else
476         {
477             clearIconFocus = False;
478         }
479
480         /*
481          * The wm icon frame window and the client icon window
482          * (if it is being used) are mapped and the client window and
483          * client frame are unmapped.
484          */
485
486         if (ICON_FRAME_WIN(pCD))
487         {
488             if (pSD->useIconBox && P_ICON_BOX(pCD) && 
489                 !(pCD->clientFlags & ICON_BOX))
490             {
491                 ShowClientIconState(pCD, newState);
492             }
493             else 
494             {
495                 Boolean doGrab = False;
496                 if (event_mask)
497                 doGrab = (Success == XGrabPointer 
498                         (DISPLAY, DefaultRootWindow(DISPLAY),
499                         False, event_mask, GrabModeAsync, GrabModeAsync,
500                         None, None, CurrentTime));
501                 XUnmapWindow (DISPLAY, ICON_FRAME_WIN(pCD));
502                 if (pCD->iconWindow)
503                 {
504                     XUnmapWindow (DISPLAY, pCD->iconWindow);
505                 }
506                 if (event_mask && doGrab)
507                 {
508                         XEvent event;
509                         XMaskEvent(DISPLAY, event_mask, &event);
510                         XUngrabPointer(DISPLAY,CurrentTime);
511                 }
512 #ifdef WSM
513                 if (wmGD.iconAutoPlace) 
514                 {
515                     for (wsI = 0; wsI < pCD->numInhabited; wsI++)
516                     {
517                         iplace = pCD->pWsList[wsI].iconPlace;
518                         if (iplace != NO_ICON_PLACE)
519                         {
520                             pWS_i = GetWorkspaceData (pCD->pSD,
521                                                 pCD->pWsList[wsI].wsID);
522                             pWS_i->IPData.placeList[iplace].pCD = 
523                                     NULL;
524                         }
525                     }
526                 }
527 #else /* WSM */
528                 if ((wmGD.iconAutoPlace) && (ICON_PLACE(pCD) != NO_ICON_PLACE))
529                 {
530                     pWS->IPData.placeList[ICON_PLACE(pCD)].pCD = 
531                         NULL;
532                 }
533 #endif /* WSM */
534             }
535
536             if (clearIconFocus)
537             {
538                 ClearFocusIndication (pCD, False /*no refresh*/);
539                 wmGD.keyboardFocus = NULL;
540             }
541         }
542     }
543     if ((currentState != NORMAL_STATE) && (currentState != MAXIMIZED_STATE))
544     {
545         /*
546          * Note that maximized state is considered a NormalState in
547          * the ICCC.  SetClientWMState also sets the state in the
548          * client data.
549          */
550
551         if (currentState == MINIMIZED_STATE)
552         {
553             /*
554              * Raise the window(s) when they are deiconified.
555              */
556
557             pCD->clientState = newState;
558 #ifdef WSM
559                     wmGD.bSuspendSecondaryRestack = True;
560 #endif /* WSM */
561             F_Raise (NULL, pCD, NULL);
562 #ifdef WSM
563                     wmGD.bSuspendSecondaryRestack = False;
564 #endif /* WSM */
565         }
566
567         if ( (!(pCD->clientFlags & ICON_BOX)) || 
568              ((pCD->clientFlags & ICON_BOX) && (!(firstTime))) )
569         {
570 #ifdef PANELIST
571           if ((currentState == WITHDRAWN_STATE) && 
572               (pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUBPANEL) &&
573               !(pCD->transientChildren))
574           {
575               if (pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUB_RESTORED)
576               {
577                   pCD->dtwmBehaviors &= ~DtWM_BEHAVIOR_SUB_RESTORED;
578                   pCD->dtwmBehaviors &= ~DtWM_BEHAVIOR_SUBPANEL;
579                   XMapWindow (DISPLAY, pCD->client);
580                   XMapWindow (DISPLAY, pCD->clientFrameWin);
581               }
582               else
583               {
584                   SlideWindowOut (pCD);
585               }
586           }
587           else
588 #endif /* PANELIST */
589             MapClientWindows (pCD);
590         }
591
592
593         /*
594          * Set the WM_STATE property of the window and any associated
595          * transients, along with the clientState value.  The call
596          * is made with an indication of NORMAL_STATE to insure
597          * that transient window clientState values are setup
598          * correctly.  The top-level window clientState is set later.
599          */
600
601         SetClientWMState (pCD, NormalState, NORMAL_STATE);
602     }
603     pCD->clientState = newState;
604
605     if ((wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT) &&
606         (currentState == MINIMIZED_STATE) && wmGD.deiconifyKeyFocus)
607     {
608         ClientData *pcdFocus;
609
610         pcdFocus = FindTransientFocus (pCD);
611         if (pcdFocus)
612         {
613             Do_Focus_Key (pcdFocus, setTime, ALWAYS_SET_FOCUS);
614         }
615     }
616
617     if ( pSD->useIconBox &&  P_ICON_BOX(pCD) &&
618          (!(pCD->clientFlags & ICON_BOX)) && (ICON_FRAME_WIN(pCD)))
619     {
620         /* 
621          * force icon appearance in icon box to change 
622          */
623
624         IconExposureProc (pCD, True);
625     }
626
627 } /* END OF FUNCTION SetupWindowStateWithEventMask */
628
629
630
631 \f
632 /*************************************<->*************************************
633  *
634  *  ConfigureNewState (pcd)
635  *
636  *
637  *  Description:
638  *  -----------
639  *  Configure the window to a new state
640  *
641  *
642  *  Inputs:
643  *  ------
644  *  pcd         - pointer to client data
645  * 
646  *  Outputs:
647  *  -------
648  *
649  *
650  *  Comments:
651  *  --------
652  *  o This is only good for going between NORMAL and MAXIMIZED state.
653  * 
654  *************************************<->***********************************/
655
656 void ConfigureNewState (ClientData *pcd)
657 {
658     if (pcd->maxConfig)
659     {
660         pcd->maxConfig = FALSE;
661         RegenerateClientFrame(pcd);
662         XResizeWindow (DISPLAY, pcd->client,
663                            (unsigned int) pcd->clientWidth, 
664                            (unsigned int) pcd->clientHeight);
665     }
666     else
667     {
668         XResizeWindow (DISPLAY, pcd->client,
669                            (unsigned int) pcd->maxWidth, 
670                            (unsigned int) pcd->maxHeight);
671         pcd->maxConfig = TRUE;
672         RegenerateClientFrame(pcd);
673     }
674     SendConfigureNotify (pcd);
675
676     /*
677      * Force repaint if size doesn't change to update frame appearance.
678      */
679
680     if ((pcd->clientWidth == pcd->maxWidth) &&
681         (pcd->clientHeight == pcd->maxHeight))
682     {
683         FrameExposureProc (pcd);
684     }
685
686 } /* END OF FUNCTION ConfigureNewState */
687
688
689 \f
690 /*************************************<->*************************************
691  *
692  *  UnmapClients (pCD, event_mask)
693  *
694  *
695  *  Description:
696  *  -----------
697  *  Unmap the window(s).  The indicated client may be the head of a transient
698  *  tree - if it is unmap all windows in the transient tree.
699  *
700  *
701  *  Inputs:
702  *  ------
703  *  pCD = pointer to client data of window(s) to be unmapped
704  *  event_mask = what to grab to prevent stray events going somewhere. Our
705  *      passive grab has just been activated -- but it is dropped when the
706  *      window is unmapped and the ButtonRelease event can go to the window
707  *      now exposed. Avoid this by grabbing the ButtonRelease before the unmap
708  *      and swallowing it.
709  *      Also done for icon being unmapped.
710  *
711  *************************************<->***********************************/
712
713 static void UnmapClients (ClientData *pCD, unsigned int event_mask)
714 {
715     ClientData *pNext;
716     Boolean doGrab = False;
717
718     pNext = pCD->transientChildren;
719     while (pNext)
720     {
721         /* unmap all children first */
722         if (pNext->transientChildren)
723             UnmapClients (pNext, (unsigned int) 0);
724
725         /* then unmap all siblings at this level */
726         XUnmapWindow (DISPLAY, pNext->clientFrameWin);
727         XUnmapWindow (DISPLAY, pNext->client);
728         pNext->wmUnmapCount++;
729         pNext = pNext->transientSiblings;
730     }
731
732     if (event_mask)
733         doGrab = (Success == XGrabPointer (DISPLAY, DefaultRootWindow(DISPLAY),
734                 False, event_mask, GrabModeAsync, GrabModeAsync,
735                 None, None, CurrentTime));
736     /* unmap this primary window */
737     XUnmapWindow (DISPLAY, pCD->clientFrameWin); 
738     XUnmapWindow (DISPLAY, pCD->client);
739     if (event_mask && doGrab)
740         {
741         XEvent event;
742         XMaskEvent(DISPLAY, event_mask, &event);
743         XUngrabPointer(DISPLAY,CurrentTime);
744         }
745     pCD->wmUnmapCount++;
746
747 } /* END OF FUNCTION UnmapClients */
748
749
750 \f
751 /*************************************<->*************************************
752  *
753  *  SetClientWMState (pCD, wmState, mwmState)
754  *
755  *
756  *  Description:
757  *  -----------
758  *  Set a new window manage state for a client window or a tree of transient
759  *  client windows.
760  *
761  *  Inputs:
762  *  ------
763  *  pCD = pointer to  client data
764  *
765  *  wmState = new state for WM_STATE property
766  *
767  *  mwmState = mwm client state
768  *
769  *************************************<->***********************************/
770
771 void SetClientWMState (ClientData *pCD, int wmState, int mwmState)
772 {
773     ClientData *pNext;
774 #ifdef WSM
775     Boolean bToUnseen;
776
777     bToUnseen = (mwmState & UNSEEN_STATE) != 0;
778     mwmState &= ~UNSEEN_STATE;
779 #endif /* WSM */
780
781 #ifdef WSM
782     SetClientWsIndex (pCD);
783 #endif /* WSM */
784     pNext = pCD->transientChildren;
785     while (pNext)
786     {
787         if (pNext->transientChildren)
788         {
789             SetClientWMState (pNext, wmState, mwmState);
790         }
791
792 #ifdef WSM
793         SetClientWsIndex (pNext);
794 #endif /* WSM */
795         SetWMState (pNext->client, wmState, ICON_FRAME_WIN(pNext));
796         if (pNext->maxConfig && mwmState == NORMAL_STATE)
797         {
798             pNext->clientState = MAXIMIZED_STATE;
799         }
800 #ifdef WSM
801         else if (!pNext->maxConfig && mwmState == MAXIMIZED_STATE)
802         {
803             pNext->clientState = NORMAL_STATE;
804         }
805 #endif /* WSM */
806         else
807         {
808             pNext->clientState = mwmState;
809         }
810 #ifdef WSM
811         if (bToUnseen)
812             pNext->clientState |= UNSEEN_STATE;
813 #endif /* WSM */
814         pNext = pNext->transientSiblings;
815     }
816
817     SetWMState (pCD->client, wmState, ICON_FRAME_WIN(pCD));
818     pCD->clientState = mwmState;
819 #ifdef WSM
820     if (bToUnseen)
821         pCD->clientState |= UNSEEN_STATE;
822 #endif /* WSM */
823
824 } /* END OF FUNCTION SetClientWMState */
825
826 #ifdef PANELIST
827 \f
828 #define SLIDE_UP_PERCENTAGE     5
829 #define SLIDE_UP_DIVISOR        (100/SLIDE_UP_PERCENTAGE)
830 #define SLIDE_UP_INTERVAL       15
831
832 /******************************<->*************************************
833  *
834  * void SlideOutTimerProc (client_data, id)
835  *
836  *  Description:
837  *  -----------
838  *  An XtTimerCallbackProc to process slide up mapping of a panel
839  *
840  *  Inputs:
841  *  ------
842  *  client_data = pointer to a SlideOutRec
843  * 
844  *  Outputs:
845  *  -------
846  *  
847  *
848  *  Comments:
849  *  --------
850  ******************************<->***********************************/
851 void
852 SlideOutTimerProc ( XtPointer client_data, XtIntervalId *id)
853 {
854     SlideOutRec *pSOR = (SlideOutRec *) client_data;
855     Boolean bDone = False;
856
857     if (pSOR)
858     {
859         /*
860          * compute next increment;
861          */
862         switch (pSOR->direction)
863         {
864             case SLIDE_NORTH:
865                 if (pSOR->mapping)
866                 {
867                     pSOR->currY -= pSOR->incHeight;
868                     pSOR->currHeight += pSOR->incHeight;
869                     if ((pSOR->currY < pSOR->pCD->frameInfo.y) ||
870                         (pSOR->currHeight > pSOR->pCD->frameInfo.height))
871                     {
872                         pSOR->currY = pSOR->pCD->frameInfo.y;
873                         pSOR->currHeight = pSOR->pCD->frameInfo.height;
874                     }
875                     bDone = (pSOR->currY == pSOR->pCD->frameInfo.y);
876                 }
877                 else 
878                 {
879                     pSOR->currY += pSOR->incHeight;
880                     if (pSOR->incHeight >= pSOR->currHeight)
881                     {
882                         pSOR->currHeight = 0;
883                         bDone = True;
884                     }
885                     else
886                     {
887                         pSOR->currHeight -= pSOR->incHeight;
888                     }
889                 }
890                 break;
891
892             case SLIDE_SOUTH:
893                 if (pSOR->mapping)
894                 {
895                     pSOR->currHeight += pSOR->incHeight;
896                     if (pSOR->currHeight > pSOR->pCD->frameInfo.height)
897                     {
898                         pSOR->currHeight = pSOR->pCD->frameInfo.height;
899                     }
900                     bDone = 
901                       (pSOR->currHeight == pSOR->pCD->frameInfo.height);
902                 }
903                 else
904                 {
905                     if (pSOR->incHeight >= pSOR->currHeight)
906                     {
907                         pSOR->currHeight = 0;
908                         bDone = True;
909                     }
910                     else
911                     {
912                         pSOR->currHeight -= pSOR->incHeight;
913                     }
914                 }
915                 break;
916         }
917
918         /*
919          * do next slide-up
920          */
921         if (pSOR->currHeight > 0)
922         {
923             XMoveResizeWindow (DISPLAY, pSOR->coverWin, 
924                 pSOR->currX, pSOR->currY,
925                 pSOR->currWidth, pSOR->currHeight);
926
927             XMoveResizeWindow (DISPLAY, pSOR->pCD->clientFrameWin, 
928                 pSOR->currX, pSOR->currY, 
929                 pSOR->currWidth, pSOR->currHeight);
930         }
931         
932         /*
933          * See if we need to continue
934          */
935         if (bDone)
936         {
937             if (!pSOR->mapping)
938             {
939                 /* Time to really unmanage the slide-up */
940                 XtUnmanageChild (pSOR->wSubpanel);
941             }
942             else
943             {
944                 WmSubpanelPosted (DISPLAY1, pSOR->pCD->client);
945                 SendConfigureNotify(pSOR->pCD);
946             }
947
948             /* done! clean up */
949             XDestroyWindow (DISPLAY, pSOR->coverWin);
950             pSOR->pCD->pSOR = NULL;
951             XtFree ((char *)pSOR);
952             wmGD.iSlideUpsInProgress -= 1;
953         }
954         else
955         {
956             /* re-arm the timer */
957             XtAppAddTimeOut(wmGD.mwmAppContext, pSOR->interval,
958                             SlideOutTimerProc, (XtPointer)pSOR);
959             XSync (DISPLAY, False);
960         }
961     }
962
963 } /* END OF FUNCTION SlideOutTimerProc */
964
965
966 \f
967 /*************************************<->*************************************
968  *
969  *  SlideWindowOut (pCD)
970  *
971  *
972  *  Description:
973  *  -----------
974  *  Maps a window with a slide-out effect.
975  *
976  *
977  *  Inputs:
978  *  ------
979  *  pCD = pointer to  client data
980  *
981  *  Comment:
982  *  -------
983  *  Only supports slide-up or slide-down 
984  * 
985  *************************************<->***********************************/
986
987 static void
988 SlideWindowOut (ClientData *pCD)
989 {
990     SlideOutRec *pSOR;
991
992     if (pCD->pSOR)
993     {
994         pSOR = pCD->pSOR;
995
996         /*
997          *  Hmmm. We're already sliding this window.
998          *  If we're supposed to go in the other direction,
999          *  then turn it around.
1000          */
1001         if (pSOR->mapping == True)
1002         {
1003             /*
1004              * We're already mapping this guy, ignore this
1005              * and finish what we've already got going.
1006              */
1007             return;
1008         }
1009         else
1010         {
1011             /*
1012              * We're not mapping this guy. Reverse course!!
1013              */
1014             pSOR->mapping = True;
1015
1016             /* insure the client window is mapped */
1017             XMapWindow (DISPLAY, pCD->client);
1018
1019             /* handle the rest on the next timeout */
1020             return;
1021         }
1022     }
1023
1024     /* map the primary window */
1025     XMapWindow (DISPLAY, pCD->client);
1026     pSOR = (SlideOutRec *) XtMalloc (sizeof(SlideOutRec));
1027     if (pSOR)
1028     {
1029         /*
1030          * Compute this ahead of time so we can check against
1031          * the window size. If the window is short, we'll
1032          * just map it, avoiding a lot of processing.
1033          */
1034         pSOR->incHeight = (Dimension) (DisplayHeight(DISPLAY, 
1035                         SCREEN_FOR_CLIENT(pCD))/SLIDE_UP_DIVISOR);
1036     }
1037
1038     if ((pCD->slideDirection != SLIDE_NOT) && pSOR &&
1039         (pSOR->incHeight < pCD->frameInfo.height))
1040     {
1041         XSetWindowAttributes window_attribs;
1042         XWindowChanges window_changes;
1043         unsigned long mask;
1044
1045         /* 
1046          * Set up data for processing slide up
1047          */
1048         pSOR->pCD = pCD;
1049         pSOR->interval = SLIDE_UP_INTERVAL;
1050         pSOR->direction = pCD->slideDirection;
1051         pSOR->mapping = True;
1052         pSOR->wSubpanel = NULL;
1053         pSOR->pCD->pSOR = pSOR;
1054         
1055         switch (pSOR->direction)
1056         {
1057             case SLIDE_NORTH:
1058                 pSOR->incWidth = 0;
1059                 pSOR->currWidth = pCD->frameInfo.width;
1060                 pSOR->currHeight = pSOR->incHeight;
1061                 pSOR->currX = pCD->frameInfo.x;
1062                 pSOR->currY = pCD->frameInfo.y + 
1063                     (pCD->frameInfo.height - pSOR->currHeight);
1064                 break;
1065
1066             case SLIDE_SOUTH:
1067                 pSOR->incWidth = 0;
1068                 pSOR->currWidth = pCD->frameInfo.width;
1069                 pSOR->currHeight = pSOR->incHeight;
1070                 pSOR->currX = pCD->frameInfo.x;
1071                 pSOR->currY = pCD->frameInfo.y;
1072                 break;
1073         }
1074
1075         /*
1076          * Create screening window to hide the slide-up from button
1077          * events until it is all the way up.
1078          */
1079         mask = CWOverrideRedirect;
1080         window_attribs.override_redirect = True;
1081         pSOR->coverWin = XCreateWindow(DISPLAY,
1082                             RootWindow (DISPLAY, SCREEN_FOR_CLIENT(pCD)),
1083                             pSOR->currX, pSOR->currY, 
1084                             pSOR->currWidth, pSOR->currHeight, 0,
1085                             CopyFromParent,InputOnly,CopyFromParent,
1086                             mask, &window_attribs);
1087
1088         /* 
1089          * Put screen window above the slide-up client
1090          */
1091         mask = CWStackMode | CWSibling;
1092         window_changes.stack_mode = Above;
1093         window_changes.sibling = pCD->clientFrameWin;
1094         XConfigureWindow (DISPLAY, pSOR->coverWin, mask, &window_changes);
1095
1096         /*
1097          * Start slide-up processing
1098          */ 
1099         XMoveResizeWindow (DISPLAY, pSOR->coverWin, pSOR->currX, pSOR->currY,
1100             pSOR->currWidth, pSOR->currHeight);
1101         XMoveResizeWindow (DISPLAY, pCD->clientFrameWin, 
1102             pSOR->currX, pSOR->currY, pSOR->currWidth, pSOR->currHeight);
1103         XMapWindow (DISPLAY, pSOR->coverWin);
1104         XMapWindow (DISPLAY, pCD->clientFrameWin);
1105         XSync (DISPLAY, False);
1106
1107         XtAppAddTimeOut(wmGD.mwmAppContext, pSOR->interval,
1108                         SlideOutTimerProc, (XtPointer)pSOR);
1109         
1110         wmGD.iSlideUpsInProgress += 1;
1111
1112     }
1113     else
1114     {
1115         /*
1116          * Not sliding because no direction specified or our window
1117          * is just a little guy.
1118          */
1119         XMapWindow (DISPLAY, pCD->clientFrameWin);
1120         if (pSOR) 
1121         {
1122             XtFree ((char *) pSOR);
1123             pCD->pSOR = NULL;
1124         }
1125     }
1126
1127 } /* END OF FUNCTION SlideOutWindow */
1128
1129
1130 \f
1131 /*************************************<->*************************************
1132  *
1133  *  SlideSubpanelBackIn (pCD, wSubpanel)
1134  *
1135  *
1136  *  Description:
1137  *  -----------
1138  *  Slides a subpanel back in
1139  *
1140  *
1141  *  Inputs:
1142  *  ------
1143  *  pCD = pointer to  client data
1144  *  wSubpanel = subpanel widget to unmanage
1145  *
1146  *  Comment:
1147  *  -------
1148  * 
1149  *************************************<->***********************************/
1150
1151 void
1152 SlideSubpanelBackIn (ClientData *pCD, Widget wSubpanel)
1153 {
1154     SlideOutRec *pSOR;
1155
1156     if (pCD->pSOR)
1157     {
1158         pSOR = pCD->pSOR;
1159
1160         /*
1161          *  Hmmm. We're already sliding this window.
1162          *  If we're supposed to go in the other direction,
1163          *  then turn it around.
1164          */
1165         if (pSOR->mapping == False)
1166         {
1167             /*
1168              * We're already unmapping this guy, ignore this
1169              * and finish what we've already got going.
1170              */
1171             return;
1172         }
1173         else
1174         {
1175             /*
1176              * We're mapping this guy. Reverse course!!
1177              */
1178             pSOR->mapping = False;
1179             pSOR->wSubpanel = wSubpanel;
1180
1181             /* handle the rest on the next timeout */
1182             return;
1183         }
1184     }
1185
1186     pSOR = (SlideOutRec *) XtMalloc (sizeof(SlideOutRec));
1187     if (pSOR)
1188     {
1189         /*
1190          * Compute this ahead of time to check if our window
1191          * is short. If it is, we'll just unmap it, avoiding
1192          * a lot of extra work.
1193          */
1194         pSOR->incHeight = (Dimension) (DisplayHeight(DISPLAY, 
1195                 SCREEN_FOR_CLIENT(pCD))/SLIDE_UP_DIVISOR);
1196     }
1197
1198     if ((pCD->slideDirection != SLIDE_NOT) && pSOR &&
1199         (pSOR->incHeight < pCD->frameInfo.height))
1200     {
1201         XSetWindowAttributes window_attribs;
1202         XWindowChanges window_changes;
1203         unsigned long mask;
1204
1205         /* 
1206          * Set up data for processing slide up
1207          */
1208         pSOR->pCD = pCD;
1209         pSOR->interval = SLIDE_UP_INTERVAL;
1210         pSOR->direction = pCD->slideDirection;
1211         pSOR->mapping = False;
1212         pSOR->wSubpanel = wSubpanel;
1213         pSOR->pCD->pSOR = pSOR;
1214         
1215         pSOR->incWidth = 0;
1216         pSOR->currWidth = pCD->frameInfo.width;
1217         pSOR->currHeight = pCD->frameInfo.height;
1218         pSOR->currX = pCD->frameInfo.x;
1219         pSOR->currY = pCD->frameInfo.y;
1220
1221         switch (pSOR->direction)
1222         {
1223             case SLIDE_NORTH:
1224                 pSOR->currHeight -= pSOR->incHeight;
1225                 pSOR->currY += pSOR->incHeight;
1226                 break;
1227
1228             case SLIDE_SOUTH:
1229                 pSOR->currHeight -= pSOR->incHeight;
1230                 break;
1231         }
1232
1233         /*
1234          * Create screening window to hide the slide-up from button
1235          * events until it is all the way up.
1236          */
1237         mask = CWOverrideRedirect;
1238         window_attribs.override_redirect = True;
1239         pSOR->coverWin = XCreateWindow(DISPLAY,
1240                             RootWindow (DISPLAY, SCREEN_FOR_CLIENT(pCD)),
1241                             pSOR->currX, pSOR->currY, 
1242                             pSOR->currWidth, pSOR->currHeight, 0,
1243                             CopyFromParent,InputOnly,CopyFromParent,
1244                             mask, &window_attribs);
1245
1246         /* 
1247          * Put screen window above the slide-up client
1248          */
1249         mask = CWStackMode | CWSibling;
1250         window_changes.stack_mode = Above;
1251         window_changes.sibling = pCD->clientFrameWin;
1252         XConfigureWindow (DISPLAY, pSOR->coverWin, mask, &window_changes);
1253
1254         /*
1255          * Start slide-up processing
1256          */ 
1257         XMapWindow (DISPLAY, pSOR->coverWin);
1258
1259         if (pSOR->currHeight > 0)
1260         {
1261             XMoveResizeWindow (DISPLAY, pCD->clientFrameWin, 
1262                 pSOR->currX, pSOR->currY, 
1263                 pSOR->currWidth, pSOR->currHeight);
1264
1265             XMoveResizeWindow (DISPLAY, pSOR->coverWin, 
1266                 pSOR->currX, pSOR->currY, 
1267                 pSOR->currWidth, pSOR->currHeight);
1268
1269             XSync (DISPLAY, False);
1270         }
1271
1272         XtAppAddTimeOut(wmGD.mwmAppContext, pSOR->interval,
1273                         SlideOutTimerProc, (XtPointer)pSOR);
1274
1275         wmGD.iSlideUpsInProgress += 1;
1276
1277     }
1278     else
1279     {
1280         /*
1281          * Not sliding because no direction specified or our window
1282          * is just a little guy.
1283          */
1284         /* Just unmanage the slide-up */
1285         XtUnmanageChild (wSubpanel);
1286         if (pSOR) 
1287         {
1288             XtFree ((char *) pSOR);
1289             pCD->pSOR = NULL;
1290         }
1291     }
1292
1293 } /* END OF FUNCTION SlideOutWindow */
1294 #endif /* PANELIST */
1295
1296 \f
1297 /*************************************<->*************************************
1298  *
1299  *  MapClientWindows (pCD)
1300  *
1301  *
1302  *  Description:
1303  *  -----------
1304  *  Maps the window.  If this is a transient tree then all the windows in
1305  *  the transient tree are mapped.
1306  *
1307  *
1308  *  Inputs:
1309  *  ------
1310  *  pCD = pointer to  client data
1311  * 
1312  *************************************<->***********************************/
1313
1314 void MapClientWindows (ClientData *pCD)
1315 {
1316     ClientData *pNext;
1317
1318
1319     pNext = pCD->transientChildren;
1320     while (pNext)
1321     {
1322         /* map all transient children first */
1323         if (pNext->transientChildren)
1324         {
1325             MapClientWindows (pNext);
1326         }
1327
1328         /* then map all siblings at this level */
1329         XMapWindow (DISPLAY, pNext->client);
1330         XMapWindow (DISPLAY, pNext->clientFrameWin);
1331
1332         pNext = pNext->transientSiblings;
1333     }
1334
1335     /* map the primary window */
1336     XMapWindow (DISPLAY, pCD->client);
1337     XMapWindow (DISPLAY, pCD->clientFrameWin);
1338
1339 } /* END OF FUNCTION MapClientWindows */
1340
1341
1342 \f
1343 /*************************************<->*************************************
1344  *
1345  *  ShowIconForMinimizedClient (pWS, pCD)
1346  *
1347  *
1348  *  Description:
1349  *  -----------
1350  *  This function shows the icon for the specified client.  If the icon
1351  *  is in an icon box then the "minimized" icon is displayed.  If the icon
1352  *  is on the root window it is mapped.
1353  * 
1354  *
1355  *  Inputs:
1356  *  ------
1357  *  pWS = pointer to workspace data
1358  *  pCD = pointer to  client data
1359  *
1360  *************************************<->***********************************/
1361
1362 void ShowIconForMinimizedClient (WmWorkspaceData *pWS, ClientData *pCD)
1363 {
1364     WmScreenData *pSD = PSD_FOR_CLIENT(pCD);
1365
1366     /*
1367      * Handle auto-placement for root icons (icons not in an icon
1368      * box).
1369      */
1370     if (wmGD.iconAutoPlace && !P_ICON_BOX(pCD))
1371     {
1372         if ((ICON_PLACE(pCD) == NO_ICON_PLACE) ||
1373             ((pWS->IPData.placeList[ICON_PLACE(pCD)].pCD) &&
1374              (pWS->IPData.placeList[ICON_PLACE(pCD)].pCD != pCD)))
1375         {
1376             /*
1377              * Icon place not defined or occupied by another client,
1378              * find a free place to put the icon.
1379              */
1380
1381             if ((ICON_PLACE(pCD) = GetNextIconPlace (&pWS->IPData)) 
1382                 == NO_ICON_PLACE)
1383             {
1384                 ICON_PLACE(pCD) = 
1385                     CvtIconPositionToPlace (&pWS->IPData,
1386                                                          pCD->clientX,
1387                                                          pCD->clientY);
1388             }
1389             CvtIconPlaceToPosition (&pWS->IPData, ICON_PLACE(pCD), 
1390                                     &ICON_X(pCD), &ICON_Y(pCD));
1391
1392 #ifndef WSM
1393             XMoveWindow (DISPLAY, ICON_FRAME_WIN(pCD), 
1394                 ICON_X(pCD), ICON_Y(pCD));
1395 #endif /* WSM */
1396
1397         }
1398
1399         pWS->IPData.placeList[ICON_PLACE(pCD)].pCD = pCD;
1400     }
1401
1402 #ifdef WSM
1403     /*
1404      * If icon on root window and this workspace is active, the
1405      * make sure it's in the right place.
1406      */
1407     if ((pWS == pSD->pActiveWS) && !P_ICON_BOX(pCD))
1408     {
1409         XMoveWindow (DISPLAY, ICON_FRAME_WIN(pCD), 
1410             ICON_X(pCD), ICON_Y(pCD));
1411     }
1412 #endif /* WSM */
1413     if (pCD->iconWindow)
1414     {
1415         XMapWindow (DISPLAY, pCD->iconWindow);
1416     }
1417
1418     if ((pSD->useIconBox) && P_ICON_BOX(pCD))
1419     {
1420         ShowClientIconState (pCD, MINIMIZED_STATE );
1421     }
1422     else
1423     {
1424         XWindowChanges windowChanges;
1425
1426         /*
1427          * Map the icon on the screen at the appropriate place in the 
1428          * window stack.
1429          */
1430
1431         if (wmGD.lowerOnIconify)
1432         {
1433             if ((&pCD->iconEntry != pSD->lastClient) &&
1434                 (pSD->lastClient))
1435             {
1436                 if (pSD->lastClient->type == MINIMIZED_STATE)
1437                 {
1438                     windowChanges.sibling = 
1439                         ICON_FRAME_WIN(pSD->lastClient->pCD);
1440                 }
1441                 else
1442                 {
1443                     windowChanges.sibling =
1444                         pSD->lastClient->pCD->clientFrameWin;
1445                 }
1446                 windowChanges.stack_mode = Below;
1447                 XConfigureWindow (DISPLAY, ICON_FRAME_WIN(pCD),
1448                                   (CWSibling | CWStackMode), &windowChanges);
1449                 MoveEntryInList (pWS, &pCD->iconEntry, 
1450                     False /*on bottom*/, NULL);
1451             }
1452         }
1453         else
1454         {
1455             windowChanges.sibling = pCD->clientFrameWin;
1456             windowChanges.stack_mode = Below;
1457             XConfigureWindow (DISPLAY, ICON_FRAME_WIN(pCD),
1458                               (CWSibling | CWStackMode), &windowChanges);
1459             MoveEntryInList (pWS, &pCD->iconEntry, False /*below*/,
1460                              &pCD->clientEntry);
1461         }
1462
1463 #ifdef WSM
1464         if (pWS == pSD->pActiveWS)
1465         {
1466             XMapWindow (DISPLAY, ICON_FRAME_WIN(pCD));
1467         }
1468 #else /* WSM */
1469         XMapWindow (DISPLAY, ICON_FRAME_WIN(pCD));
1470 #endif /* WSM */
1471     }
1472
1473 } /* END OF FUNCTION ShowIconForMinimizedClient */
1474
1475 #ifdef WSM
1476 \f
1477 /*************************************<->*************************************
1478  *
1479  *  ShowAllIconsForMinimizedClient (pCD)
1480  *
1481  *
1482  *  Description:
1483  *  -----------
1484  *  This function places icons in all the workspaces for the minimized
1485  *  client. Since there is only one clientState per client (not per
1486  *  workspace), this loops over all workspace in which the client
1487  *  resides and places an icon in each.
1488  * 
1489  *
1490  *  Inputs:
1491  *  ------
1492  *  pCD = pointer to  client data
1493  *
1494  *  Comments:
1495  *  ---------
1496  *  This operates by setting up the currentWsc index for each workspace
1497  *  and calling ShowIconForMinimizedClient, which makes heavy use of
1498  *  the macros that use the currentWsc index.
1499  *
1500  *************************************<->***********************************/
1501
1502 void ShowAllIconsForMinimizedClient (ClientData *pCD)
1503 {
1504     int saveWsc = pCD->currentWsc;
1505     int tmpWsc;
1506     WmWorkspaceData *pWS;
1507
1508     for (tmpWsc = 0; tmpWsc < pCD->numInhabited; tmpWsc++)
1509     {
1510         pCD->currentWsc = tmpWsc;
1511         pWS = GetWorkspaceData (PSD_FOR_CLIENT(pCD),
1512                                     pCD->pWsList[tmpWsc].wsID);
1513         ShowIconForMinimizedClient(pWS, pCD);
1514     }
1515     
1516     pCD->currentWsc = saveWsc;
1517
1518 } /* END OF FUNCTION ShowAllIconsForMinimizedClient */
1519 #endif /* WSM */
1520 \f