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