Spelling fixes
[oweals/cde.git] / cde / programs / dtwm / WmWinInfo.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, 1993 OPEN SOFTWARE FOUNDATION, INC. 
25  * ALL RIGHTS RESERVED 
26 */ 
27 /* 
28  * Motif Release 1.2.3
29 */ 
30 #ifdef REV_INFO
31 #ifndef lint
32 static char rcsid[] = "$TOG: WmWinInfo.c /main/18 1999/02/04 15:17:25 mgreess $"
33 #endif
34 #endif
35 /*
36  * (c) Copyright 1987, 1988, 1989, 1990 HEWLETT-PACKARD COMPANY */
37
38
39 /*
40  * Included Files:
41  */
42
43 #include "WmGlobal.h"
44 #include "WmICCC.h"
45 #include "WmResNames.h"
46
47 #define MWM_NEED_ICONBOX
48 #include "WmIBitmap.h"
49
50 #include <Xm/Xm.h>
51 #include <locale.h>
52 #ifdef PANELIST
53 #include "WmPanelP.h"
54 #endif /* PANELIST */
55
56 #define makemult(a, b) ((b==1) ? (a) : (((int)((a) / (b))) * (b)) )
57
58 /*
59  * include extern functions
60  */
61 #include "WmWinInfo.h"
62 #include "WmCDInfo.h"
63 #include "WmCDecor.h"
64 #include "WmCPlace.h"
65 #include "WmError.h"
66 #include "WmIDecor.h"
67 #include "WmIPlace.h"
68 #include "WmIconBox.h"
69 #include "WmImage.h"
70 #include "WmManage.h"
71 #include "WmMenu.h"
72 #include "WmOL.h"
73 #include "WmProperty.h" 
74 #include "WmResource.h"
75 #ifdef WSM
76 #include "WmWrkspace.h"
77 #endif /* WSM */
78 #include "WmWinList.h"
79 #ifdef WSM
80 #include "WmPresence.h"
81 #endif /* WSM */
82 #include "WmXSMP.h"
83 #include "WmMultiHead.h"
84
85 #ifdef PANELIST
86 static void AdjustSlideOutGeometry (ClientData *pCD);
87 static void FixSubpanelEmbeddedClientGeometry (ClientData *pCD);
88 #endif /* PANELIST */
89
90 #ifndef NO_MESSAGE_CATALOG
91 # define LOCALE_MSG GETMESSAGE(70, 7, "[XmbTextPropertyToTextList]:\n     Locale (%.100s) not supported. (Check $LANG).")
92 #else
93 # define LOCALE_MSG "[XmbTextPropertyToTextList]:\n     Locale (%.100s) not supported. (Check $LANG)."
94 #endif
95
96 /*
97  * Global Variables:
98  */
99 #ifdef WSM
100 WmWorkspaceData *pIconBoxInitialWS;
101 #endif /* WSM */
102
103
104 \f
105 /*************************************<->*************************************
106  *
107  *  GetClientInfo (pSD, clientWindow, manageFlags)
108  *
109  *
110  *  Description:
111  *  -----------
112  *  This function is used to initialize client window data based on the
113  *  contents of client window properties and the client window configuration.
114  *
115  *
116  *  Inputs:
117  *  ------
118  *  pSD = pointer to screen data for screen that client lives in
119  *
120  *  clientWindow = window id for the client window that is to be managed
121  *
122  *  manageFlags = flags that indicate wm state info
123  *
124  * 
125  *  Outputs:
126  *  -------
127  *  Return = pointer to an initialized client data structure for the
128  *           specified client window
129  *
130  *************************************<->***********************************/
131
132 ClientData * 
133 GetClientInfo (WmScreenData *pSD, Window clientWindow, long manageFlags)
134
135 {
136     ClientData *pCD;
137     XSetWindowAttributes sAttributes;
138
139
140     /*
141      * Allocate and initialize a client data structure:
142      */
143
144     if (!(pCD = (ClientData *)XtMalloc (sizeof (ClientData))))
145     {
146         /* unable to allocate space */
147         Warning (((char *)GETMESSAGE(70, 1, "Insufficient memory for client data")));
148         return (NULL);
149     }
150
151     
152     /*
153      * Initialize the data structure:
154      */
155
156     pCD->client = clientWindow;
157     pCD->clientID = ++(pSD->clientCounter);
158     pCD->clientFlags = WM_INITIALIZATION;
159     pCD->iconFlags = 0;
160 #ifndef WSM
161     pCD->pIconBox = NULL;
162 #endif /* WSM */
163     pCD->thisIconBox = NULL;
164 #ifdef PANELIST
165     pCD->pECD = NULL;
166     pCD->pPRCD = NULL;
167     pCD->pSOR = NULL;
168 #endif /* PANELIST */
169     pCD->wmUnmapCount = 0;
170     pCD->transientFor = (Window)0L;
171     pCD->transientLeader = NULL;
172     pCD->transientChildren = NULL;
173     pCD->transientSiblings = NULL;
174 #ifdef WSM
175     pCD->primaryStackPosition = 0;
176 #endif /* WSM */
177     pCD->fullModalCount = 0;
178     pCD->primaryModalCount = 0;
179     pCD->focusPriority = 0;
180     pCD->focusAutoRaiseDisabled = False;
181     pCD->focusAutoRaiseDisablePending = False;
182
183     pCD->clientClass = NULL;
184     pCD->clientName = NULL;
185     pCD->clientFrameWin = (Window)0L;
186 #ifndef WSM
187     pCD->iconFrameWin = (Window)0L;
188 #endif /* WSM */
189     pCD->iconWindow = (Window)0L;
190     pCD->iconPixmap = (Pixmap)0L;
191 #ifndef WSM
192     pCD->iconPlace = NO_ICON_PLACE;
193 #endif /* WSM */
194     pCD->clientProtocols = NULL;
195     pCD->clientProtocolCount = 0;
196     pCD->mwmMessages = NULL;
197     pCD->mwmMessagesCount = 0;
198     pCD->clientCmapCount = 0;
199     pCD->clientCmapIndex = 0;
200     pCD->clientCmapFlagsInitialized = FALSE;
201     pCD->systemMenuSpec = NULL;
202 #ifdef WSM
203     pCD->putInAll = False;
204     pCD->pWorkspaceHints = NULL;
205     pCD->numInhabited = 0;
206     pCD->pWsList = NULL;
207     pCD->dtwmFunctions = DtWM_FUNCTION_OCCUPY_WS;
208     pCD->dtwmBehaviors = 0L;
209     pCD->paInitialProperties = NULL;
210     pCD->numInitialProperties = 0;
211 #endif /* WSM */
212
213     pCD->decorFlags = 0L;
214     pCD->pTitleGadgets = NULL;
215     pCD->cTitleGadgets = 0;
216     pCD->pResizeGadgets = NULL;
217     pCD->clientTitleWin = (Window)0L;
218     pCD->pclientTopShadows = NULL;
219     pCD->pclientBottomShadows = NULL;
220     pCD->pclientTitleTopShadows = NULL;
221     pCD->pclientTitleBottomShadows = NULL;
222     pCD->pclientMatteTopShadows = NULL;
223     pCD->pclientMatteBottomShadows = NULL;
224     pCD->piconTopShadows = NULL;
225     pCD->piconBottomShadows = NULL;
226     pCD->internalBevel = (wmGD.frameStyle == WmSLAB) ? 0 : 
227                                                 FRAME_INTERNAL_SHADOW_WIDTH;
228 #ifndef NO_OL_COMPAT
229     pCD->bPseudoTransient = False;
230 #endif /* NO_OL_COMPAT */
231
232     pCD->maxWidth = pCD->maxWidthLimit = BIGSIZE;
233     pCD->maxHeight = pCD->maxHeightLimit = BIGSIZE;
234     pCD->maxConfig = FALSE;
235     pCD->pSD = pSD;
236     pCD->dataType = CLIENT_DATA_TYPE;
237     pCD->window_status = 0L;
238
239     pCD->clientEntry.nextSibling = NULL;
240     pCD->clientEntry.prevSibling = NULL;
241     pCD->clientEntry.pCD = NULL;
242
243     pCD->smClientID = (String)NULL;
244
245      /*
246      * Do special processing for client windows that are controlled by
247      * the window manager.
248      */
249
250     if (manageFlags & MANAGEW_WM_CLIENTS)
251     {
252 #ifdef WSM
253         WmWorkspaceData *pWS;
254
255         if (manageFlags & MANAGEW_ICON_BOX)
256         {
257             pWS = pIconBoxInitialWS;
258         }
259         else 
260         {
261             pWS = pSD->pActiveWS;
262         }
263         return (GetWmClientInfo (pWS, pCD, manageFlags));
264 #else /* WSM */
265         return (GetWmClientInfo (pSD->pActiveWS, pCD, manageFlags));
266 #endif /* WSM */
267     }
268
269
270     /*
271      * Register the client window to facilitate event handling:
272      */
273
274     XSaveContext (DISPLAY, clientWindow, wmGD.windowContextType, (caddr_t)pCD);
275
276
277     /*
278      * Listen for property change events on the window so that we keep 
279      * in sync with the hints.
280      */
281     sAttributes.event_mask = (PropertyChangeMask | ColormapChangeMask);    
282     XChangeWindowAttributes (DISPLAY, pCD->client, CWEventMask,
283         &sAttributes);
284
285     /*
286      * Get window configuration attributes.  WmGetWindowAttributes sets
287      * up the global window attributes cache with the client window 
288      * attributes.
289      */
290
291     if (!WmGetWindowAttributes (clientWindow))
292     {
293         /*
294          * Cannot get window attributes. Do not manage window.
295          * (error message within WmGetWindowAttributes)
296          */
297
298         UnManageWindow (pCD);
299         return (NULL);
300     }
301     pCD->xBorderWidth = wmGD.windowAttributes.border_width;
302
303 #ifdef WSM
304     /*
305      * Get the initial list of properties on this window. 
306      * Save it to optimize subsequent property fetching.
307      */
308     GetInitialPropertyList (pCD);
309 #endif /* WSM */
310
311     /*
312      * Retrieve and process WM_CLASS hints client window property info:
313      */
314
315     ProcessWmClass (pCD);
316
317
318     /*
319      * Retrieve and process WM_TRANSIENT_FOR client window property info:
320      */
321
322     ProcessWmTransientFor (pCD);
323
324     /*
325      * Get client window resource data (from resources, .mwmrc):
326      *  Moved prior to GetClientWorkspaceInfo() because the
327      *  ignoreWMSaveHints resource may affect that function.
328      */
329
330     ProcessClientResources (pCD);
331
332     /*
333      * Retreive and process SM_CLIENT_ID client window property info
334      * and WMSAVE_HINT client window property info:
335      * must be done prior to calling GetClientWorkspaceInfo().
336      */
337     ProcessSmClientID (pCD);
338     ProcessWmSaveHint (pCD);
339
340 #ifdef WSM
341     /*
342      *  Set client's workspace information.  NOTE: this also may
343      *  set the geometry, initial state, etc.  For Sm-aware clients,
344      *  this info will be in private DB; for older clients, it will
345      *  be contained in the screen's pDtSessionItems.
346      */
347     if (!GetClientWorkspaceInfo (pCD, manageFlags))
348     {
349         XtFree ((char *)pCD);
350         return (NULL);
351     }
352
353     /*
354      *  Restore client's per-workspace icon information.
355      */
356     LoadClientIconPositions(pCD);
357
358     /*
359      * Retrieve and process _DT_WM_HINTS client window property
360      * (results are used in ProcessMwmHints)
361      */
362     ProcessDtWmHints (pCD);
363 #else
364
365     /*
366      * For Sm-aware clients, retrieve geometry and initial state
367      * from private DB.
368      */
369     FindClientDBMatch(pCD, (char **)NULL);
370
371 #endif /* WSM */
372
373     /*
374      * Retrieve and process M_CLIENT_DECOR client window property info:
375      */
376
377     ProcessMwmHints (pCD);
378
379
380     /*
381      * Retrieve and process WM_HINTS client window property info:
382      */
383
384     ProcessWmHints (pCD, True /*first time*/);
385
386
387     /*
388      * Set offset from frame of client window
389      */
390
391     SetClientOffset (pCD);
392
393
394     /*
395      * Retrieve and process WM_NORMAL_HINTS client window property info:
396      * 
397      */
398
399     ProcessWmNormalHints (pCD, True /*first time*/, manageFlags);
400
401
402     /*
403      * Retrieve and process WM_NAME client window property info (this
404      * property contains the window title NOT the window resource name):
405      */
406
407     ProcessWmWindowTitle (pCD, TRUE);
408
409
410     /*
411      * Retrieve and process WM_ICON_NAME client window property info:
412      */
413
414     ProcessWmIconTitle (pCD, TRUE);
415
416
417     /*
418      * Retrieve and process the WM_PROTOCOLS property.
419      */
420
421     ProcessWmProtocols (pCD);
422
423
424     /*
425      * If necessary retrieve and process the _MWM_MESSAGES property.
426      */
427
428     if (pCD->protocolFlags & PROTOCOL_MWM_MESSAGES)
429     {
430         ProcessMwmMessages (pCD);
431     }
432
433
434     /*
435      * Make or find a system menu for the client.
436      */
437
438     if (pCD->systemMenu)
439     {
440         MakeSystemMenu (pCD);
441     }
442     else
443     {
444         pCD->systemMenuSpec = NULL;
445     }
446
447
448     /*
449      * Setup the colormap data for the client window.  This includes
450      * retrieving and processing client window properties that deal with
451      * subwindow colormaps.
452      */
453
454     InitCColormapData (pCD);
455
456
457     /* successful return */
458
459     return (pCD);
460
461
462 } /* END OF FUNCTION GetClientInfo */
463
464
465 \f
466 /*************************************<->*************************************
467  *
468  *  GetWmClientInfo (pWS, pCD, manageFlags)
469  *
470  *
471  *  Description:
472  *  -----------
473  *  This function is used to initialize client window data for a window
474  *  that is controlled by the window manager (e.g., the icon box).  The 
475  *  client window may get made in the process.
476  *
477  *
478  *  Inputs:
479  *  ------
480  *  pWS = pointer to workspace data
481  *
482  *  pCD = pointer to client window data structure
483  *
484  *  manageFlags = flags that indicate wm state info
485  *
486  * 
487  *  Outputs:
488  *  -------
489  *  Return = pointer to an initialized client data structure or NULL
490  *           if the client data could not be initialized
491  *
492  *************************************<->***********************************/
493 ClientData * 
494 GetWmClientInfo (WmWorkspaceData *pWS,
495                               ClientData * pCD,
496                               long manageFlags)
497
498 {
499     Pixmap      iconBitmap;
500 #ifdef WSM
501 int i;
502 #endif /* WSM */
503
504     /*
505      * Set up the client class and name for resource retrieval.
506      * Get client specific resource data (from resources, .mwmrc).
507      */
508
509     if (manageFlags & MANAGEW_ICON_BOX)
510     {
511         SetIconBoxInfo (pWS, pCD);
512     }
513     else if (manageFlags & MANAGEW_CONFIRM_BOX)
514     {
515         pCD->clientClass = WmCConfirmbox;
516         pCD->clientName = WmNconfirmbox;
517         pCD->iconImage = NULL;
518         pCD->useClientIcon = False;
519         pCD->focusAutoRaise = True;
520         pCD->internalBevel = (wmGD.frameStyle == WmSLAB) ? 0 : 
521                                                 FRAME_INTERNAL_SHADOW_WIDTH;
522         pCD->matteWidth = 0;
523         pCD->maximumClientSize.width = 0;
524         pCD->maximumClientSize.height = 0;
525         pCD->systemMenu = NULL;
526     }
527
528
529     /*
530      * Set up transient for data.
531      */
532
533     if (manageFlags & MANAGEW_ICON_BOX)
534     {
535     }
536
537
538     /*
539      * Set up WM_HINTS type information.
540      */
541
542     pCD->inputFocusModel = True;
543     pCD->clientState = NORMAL_STATE;
544     
545     if (ICON_DECORATION(pCD) & ICON_IMAGE_PART)
546     {
547         if (manageFlags & MANAGEW_ICON_BOX)
548         {
549             pCD->clientFlags |= ICON_BOX;
550         }
551         
552         if (!pCD->useClientIcon && pCD->iconImage)
553         {
554             /*
555              * Make a client supplied icon image.
556              * Do not use the default icon image if iconImage is not found.
557              */
558
559             pCD->iconPixmap = MakeNamedIconPixmap (pCD, pCD->iconImage);
560         }
561
562         if (!pCD->iconPixmap)
563         {
564             /*
565              * Use a built-in icon image for the window manager client.
566              * The image may differ from the default icon image, depending on
567              * the particular client (eg the iconbox).
568              */
569
570             if (manageFlags & MANAGEW_ICON_BOX)
571             {
572                 /*
573                  * Make a default iconBox icon image.
574                  */
575
576                 iconBitmap = XCreateBitmapFromData (DISPLAY, 
577                                 ROOT_FOR_CLIENT(pCD), (char *)iconBox_bits, 
578                                 iconBox_width, iconBox_height);
579
580                 pCD->iconPixmap = MakeIconPixmap (pCD, 
581                                 iconBitmap, (Pixmap)0L,
582                                 iconBox_width, iconBox_height, 1);
583
584             }
585         }
586     }
587
588 #ifdef WSM
589     /* 
590      * Allocate initial workspace ID list 
591      * fill with NULL IDs
592      */
593     if ((pCD->pWsList = (WsClientData *) 
594             XtMalloc(pCD->pSD->numWorkspaces * sizeof(WsClientData))) == NULL)
595     {
596         Warning (((char *)GETMESSAGE(70, 2, "Insufficient memory for client data")));
597         return (NULL);
598     }
599     pCD->sizeWsList = pCD->pSD->numWorkspaces;
600     for (i = 0; i < pCD->pSD->numWorkspaces; i++)
601     {
602         pCD->pWsList[i].wsID = 0L;
603         pCD->pWsList[i].iconPlace = NO_ICON_PLACE;
604         pCD->pWsList[i].iconX = 0;
605         pCD->pWsList[i].iconY = 0;
606         pCD->pWsList[i].iconFrameWin = (Window)0L;
607         pCD->pWsList[i].pIconBox = NULL;
608     }
609     /* 
610      * Internally managed clients must be specifically inserted
611      * into workspaces the first time by calling
612      * PutClientIntoWorkspace.
613      */
614     pCD->numInhabited = 0;
615 #else /* WSM */
616     pCD->iconPlace = NO_ICON_PLACE;
617     pCD->iconX = 0;
618     pCD->iconY = 0;
619 #endif /* WSM */
620     pCD->windowGroup = 0L;
621 #ifndef NO_OL_COMPAT
622     pCD->bPseudoTransient = False;
623 #endif /* NO_OL_COMPAT */
624
625
626     /*
627      * Set up _MWM_HINTS data.
628      */
629     /*
630      * Fix the client functions and decorations fields if they have
631      * default resource values.
632      */
633
634
635     if (manageFlags & MANAGEW_CONFIRM_BOX)
636     {
637         pCD->clientFunctions = WM_FUNC_NONE;
638         pCD->clientDecoration = WM_DECOR_BORDER;
639     }
640     else
641     {
642         if (pCD->clientFunctions & WM_FUNC_DEFAULT)
643         {
644             pCD->clientFunctions = WM_FUNC_ALL;
645         }
646
647         if (pCD->clientDecoration & WM_DECOR_DEFAULT)
648         {
649             pCD->clientDecoration = WM_DECOR_ALL;
650         }
651
652         if (manageFlags & MANAGEW_ICON_BOX)
653         {
654             pCD->clientFunctions &= ICON_BOX_FUNCTIONS;
655 #ifdef WSM
656             pCD->dtwmFunctions &= ~DtWM_FUNCTION_OCCUPY_WS;
657 #endif /* WSM */
658 #ifdef PANELIST
659             if (wmGD.useFrontPanel && pCD->pSD->iconBoxControl) 
660             { 
661                 /*
662                  * If there's a front panel button for the icon
663                  * box, then use it to "hide" the box on "close"
664                  */
665                 pCD->clientFunctions &= ~MWM_FUNC_MINIMIZE;
666                 pCD->clientFunctions |= MWM_FUNC_CLOSE;
667             }
668 #else /* PANELIST */
669 #endif /* PANELIST */
670         }
671
672
673         if (!(pCD->clientFunctions & MWM_FUNC_RESIZE))
674         {
675             pCD->clientDecoration &= ~MWM_DECOR_RESIZEH;
676         }
677
678         if (!(pCD->clientFunctions & MWM_FUNC_MINIMIZE))
679         {
680             pCD->clientDecoration &= ~MWM_DECOR_MINIMIZE;
681         }
682
683         if (!(pCD->clientFunctions & MWM_FUNC_MAXIMIZE))
684         {
685             pCD->clientDecoration &= ~MWM_DECOR_MAXIMIZE;
686         }
687     }
688
689     pCD->decor = pCD->clientDecoration;
690
691     if (manageFlags & MANAGEW_ICON_BOX)
692     {
693         pCD->inputMode = MWM_INPUT_MODELESS;
694     }
695     else if (manageFlags & MANAGEW_CONFIRM_BOX)
696     {
697         pCD->inputMode = MWM_INPUT_SYSTEM_MODAL;
698     }
699
700     /*
701      * Set up WM_NORMAL_HINTS data.
702      */
703
704     pCD->icccVersion = ICCC_CURRENT;
705     pCD->sizeFlags = US_POSITION | US_SIZE;
706
707     /* 
708      * Any calls to create Window Manager clients should
709      * return with the values for the following fields set.
710      *  If it fails, it should free any space allocated and
711      *  set pCD = NULL
712      * 
713      *  pCD->clientX =
714      *  pCD->clientY =
715      *  pCD->clientWidth =
716      *  pCD->clientHeight =
717      *  pCD->minWidth =
718      *  pCD->minHeight =
719      *  pCD->widthInc =
720      *  pCD->heightInc =
721      *  pCD->baseWidth =
722      *  pCD->baseHeight =
723      *  pCD->maxWidth =
724      *  pCD->maxHeight =
725      *  pCD->oldMaxWidth =
726      *  pCD->oldMaxHeight =
727      *
728      *        AND PROBABLY SHOULD SET
729      *         pCD->client = THE_WINDOW_THE_FUNCTION_CREATES
730      */
731
732     pCD->windowGravity = NorthWestGravity;
733
734     /* 
735      * Create IconBox window 
736      */
737     
738     if (manageFlags & MANAGEW_ICON_BOX)
739     {
740         if (!MakeIconBox (pWS, pCD))
741         {
742             /*
743              *  May want a more verbose message here 
744              */
745
746             Warning (((char *)GETMESSAGE(70, 3, "Couldn't make icon box")));
747             return (NULL);
748         }
749 #ifdef WSM
750         PutClientIntoWorkspace (pWS, pCD);
751 #endif /* WSM */
752     }
753     else if (manageFlags & MANAGEW_CONFIRM_BOX)
754     {
755         Window       root;
756         unsigned int cbWidth, cbHeight;
757         unsigned int depth;
758
759         XGetGeometry (DISPLAY, pCD->client, &root,
760                       &(pCD->clientX), &(pCD->clientY),
761                       &cbWidth, &cbHeight, 
762                       (unsigned int*)&(pCD->xBorderWidth), &depth);
763
764         pCD->clientWidth = cbWidth;
765         pCD->clientHeight = cbHeight;
766         pCD->minWidth = pCD->baseWidth = pCD->maxWidth = pCD->clientWidth;
767         pCD->minHeight = pCD->baseHeight = pCD->maxHeight = pCD->clientHeight;
768         pCD->oldMaxWidth = pCD->maxWidth;
769         pCD->oldMaxHeight = pCD->maxHeight;
770         pCD->widthInc = 1;
771         pCD->heightInc = 1;
772         pCD->clientFlags |= CONFIRM_BOX;
773 #ifdef WSM
774         PutClientIntoWorkspace (ACTIVE_WS, pCD);
775 #endif /* WSM */
776     }
777
778     /*
779      * Set offset from frame of client window (need client size information).
780      */
781
782     SetFrameInfo (pCD);
783
784
785     /*
786      * Register the client window to facilitate event handling.
787      */
788
789     XSaveContext (DISPLAY, pCD->client, wmGD.windowContextType, (caddr_t)pCD);
790
791
792     /*
793      * Set up WM_PROTOCOLS data.
794      */
795
796     pCD->clientProtocolCount = 0;
797     pCD->protocolFlags = 0;
798
799
800     /*
801      * Make the system menu.
802      */
803
804     if (manageFlags & MANAGEW_ICON_BOX)
805     {
806 #if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
807         /** BEGIN FIX CR 6941 **/
808         MenuItem *iconBoxMenuItems, *lastItem;
809
810         /* This MenuSpec is not added to pSD->acceleratorMenuSpecs */
811         pCD->systemMenuSpec = 
812             MAKE_MENU (PSD_FOR_CLIENT(pCD), pCD, pCD->systemMenu,
813                       F_CONTEXT_WINDOW, F_CONTEXT_WINDOW|F_CONTEXT_ICON,
814                       NULL, TRUE);
815         if (pCD->systemMenuSpec != (MenuSpec *) NULL)
816         {
817             pCD->systemMenuSpec = DuplicateMenuSpec(pCD->systemMenuSpec);
818             XtFree(pCD->systemMenuSpec->name);
819             pCD->systemMenuSpec->name = XtNewString("IconBoxMenu");
820             iconBoxMenuItems = GetIconBoxMenuItems (PSD_FOR_CLIENT(pCD));
821             
822             /* Find the last menu item in the menu spec's list. */
823             for (lastItem = pCD->systemMenuSpec->menuItems;
824                  lastItem->nextMenuItem != (MenuItem *) NULL;
825                  lastItem = lastItem->nextMenuItem)
826               /*EMPTY*/;
827             lastItem->nextMenuItem = iconBoxMenuItems;
828             
829             /* Now recreate the menu widgets since we've appended the
830                icon box menu items */
831             DestroyMenuSpecWidgets(pCD->systemMenuSpec);
832             pCD->systemMenuSpec->menuWidget =
833               CreateMenuWidget (PSD_FOR_CLIENT(pCD), pCD, "IconBoxMenu",
834                                 PSD_FOR_CLIENT(pCD)->screenTopLevelW, TRUE,
835                                 pCD->systemMenuSpec, NULL);
836         }
837         /** END FIX CR 6941 **/
838 #else
839         pCD->systemMenuSpec = 
840             MAKE_MENU (PSD_FOR_CLIENT(pCD), pCD, pCD->systemMenu,
841                        F_CONTEXT_WINDOW, F_CONTEXT_WINDOW|F_CONTEXT_ICON,
842                        GetIconBoxMenuItems(PSD_FOR_CLIENT(pCD)),
843                        TRUE);
844 #endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
845     }
846
847
848
849     /*
850      * Setup the colormap data.
851      */
852
853     pCD->clientColormap = PSD_FOR_CLIENT(pCD)->workspaceColormap;
854
855
856     /*
857      * Return the pointer to the client data.
858      */
859
860     return (pCD);
861
862
863 } /* END OF FUNCTION GetWmClientInfo */
864
865
866 \f
867 /*************************************<->*************************************
868  *
869  *  ProcessWmClass (pCD)
870  *
871  *
872  *  Description:
873  *  -----------
874  *  This function retrieves the contents of the WM_CLASS property on the
875  *  cient window.  The resource class and the resource name are saved in
876  *  the ClientData structure (note that the space for the strings is
877  *  allocated using Xmalloc).
878  *
879  *
880  *  Inputs:
881  *  ------
882  *  pCD         - pointer to client data
883  *
884  * 
885  *  Outputs:
886  *  -------
887  *
888  *  Comments:
889  *  --------
890  * 
891  *************************************<->***********************************/
892
893 void 
894 ProcessWmClass (ClientData *pCD)
895 {
896     XClassHint classHint;
897
898
899 #ifdef PORT_OLDXLIB
900     classHint.res_class = "";
901     classHint.res_name = "";
902     XGetClassHint (DISPLAY, pCD->client, &classHint);
903 #else
904 #ifdef WSM
905     if ((HasProperty (pCD, XA_WM_CLASS)) &&
906         (XGetClassHint (DISPLAY, pCD->client, &classHint)))
907 #else /* WSM */
908     if (XGetClassHint (DISPLAY, pCD->client, &classHint))
909 #endif /* WSM */
910 #endif
911     {
912         /* the WM_CLASS property exists for the client window */
913         pCD->clientClass = classHint.res_class;
914         pCD->clientName = classHint.res_name;
915     }
916     /* else no WM_CLASS property; assume clientClass, clientName are NULL */
917
918 } /* END OF FUNCTION ProcessWmClass */
919
920
921 \f
922 /*************************************<->*************************************
923  *
924  *  ProcessSmClientID (pCD)
925  *
926  *
927  *  Description:
928  *  -----------
929  *  This function retrieves the contents of the SM_CLIENT_ID property on the
930  *  cient window.  The value is saved in the ClientData structure
931  *  (note that the space for the strings is allocated using Xmalloc).
932  *
933  *
934  *  Inputs:
935  *  ------
936  *  pCD         - pointer to client data
937  *
938  * 
939  *  Outputs:
940  *  -------
941  *
942  *  Comments:
943  *  --------
944  * 
945  *************************************<->***********************************/
946
947 void 
948 ProcessSmClientID (ClientData *pCD)
949 {
950     Atom actualType;
951     int actualFormat;
952     unsigned long nitems, leftover;
953     char *clientID;
954
955     if (pCD->smClientID != (String)NULL)
956     {
957         XFree(pCD->smClientID);
958         pCD->smClientID = (String)NULL;
959     }
960
961     if ((XGetWindowProperty(DISPLAY, pCD->client, wmGD.xa_SM_CLIENT_ID,
962                             0L, (long)1000000, False, AnyPropertyType,
963                             &actualType, &actualFormat, &nitems,
964                             &leftover, (unsigned char **)&clientID)
965          == Success) &&
966         (actualType != None) && (actualFormat == 8))
967     {
968         /* the SM_CLIENT_ID property exists for the client window */
969         pCD->smClientID = clientID;
970     }
971
972 } /* END OF FUNCTION ProcessSmClientID */
973
974
975 \f
976 /*************************************<->*************************************
977  *
978  *  ProcessWmSaveHint (pCD)
979  *
980  *
981  *  Description:
982  *  -----------
983  *  This function retrieves the contents of the WMSAVE_HINT property on the
984  *  cient window.  The value is saved in the ClientData structure.
985  *
986  *
987  *  Inputs:
988  *  ------
989  *  pCD         - pointer to client data
990  *
991  * 
992  *  Outputs:
993  *  -------
994  *
995  *  Comments:
996  *  --------
997  * 
998  *************************************<->***********************************/
999
1000 void 
1001 ProcessWmSaveHint (ClientData *pCD)
1002 {
1003     Atom actualType;
1004     int actualFormat;
1005     unsigned long nitems, leftover;
1006     BITS32 *saveHintFlags = (BITS32 *)NULL;
1007
1008     if ((XGetWindowProperty(DISPLAY, pCD->client, wmGD.xa_WMSAVE_HINT,
1009                             0L, (long)1000000, False, AnyPropertyType,
1010                             &actualType, &actualFormat, &nitems,
1011                             &leftover, (unsigned char **)&saveHintFlags)
1012          == Success) &&
1013         (actualType != None) && (actualFormat == 32))
1014     {
1015         /* the WMSAVE_HINT property exists for the client window */
1016         pCD->wmSaveHintFlags = (int)*saveHintFlags;
1017     }
1018     else pCD->wmSaveHintFlags = 0;
1019
1020     if (saveHintFlags)
1021         XFree(saveHintFlags);
1022
1023 } /* END OF FUNCTION ProcessWmSaveHint */
1024
1025 \f
1026 /*************************************<->*************************************
1027  *
1028  *  ProcessWmHints (pCD, firstTime)
1029  *
1030  *
1031  *  Description:
1032  *  -----------
1033  *  This function retrieves the contents of the WM_HINTS property on the
1034  *  cient window.
1035  *
1036  *
1037  *  Inputs:
1038  *  ------
1039  *  pCD = pointer to client data for the window with the property
1040  *
1041  *  firstTime = if True this is the first time the property has been processed
1042  *
1043  * 
1044  *  Outputs:
1045  *  -------
1046  *  pCD = initialize various WM_HINTS related fields
1047  *
1048  *
1049  *  Comments:
1050  *  --------
1051  * 
1052  *************************************<->***********************************/
1053
1054 void 
1055 ProcessWmHints (ClientData *pCD, Boolean firstTime)
1056 {
1057     register XWMHints *pXWMHints;
1058     register long flags;
1059     Pixmap iconPixmap;
1060     Pixmap iconMask;
1061 #ifdef WSM
1062     WmWorkspaceData *pWsTmp;
1063     WsClientData *pWsc;
1064     int iws;
1065 #endif /* WSM */
1066     int tmpIconX, tmpIconY;
1067
1068
1069     /*
1070      * If the WM_HINTS property does not exist the flags field will be
1071      * set to 0.  If flags is 0 don't reference the WMHints structure
1072      * since they may be none.
1073      */
1074
1075 #ifdef WSM
1076     if (firstTime && !HasProperty (pCD, XA_WM_HINTS))
1077         pXWMHints = NULL;
1078     else
1079 #endif /* WSM */
1080     pXWMHints = XGetWMHints (DISPLAY, pCD->client);
1081
1082     if (pXWMHints)
1083     {
1084         flags = pXWMHints->flags;
1085     }
1086     else
1087     {
1088         flags = 0;
1089     }
1090
1091
1092     /*
1093      * Parse the WM_HINTS information.  If this is the first time the hints
1094      * have been processed then parse all fields and set defaults where hint
1095      * fields are not set.  If this is not the first time do selective
1096      * parsing.
1097      */
1098
1099     if (firstTime)
1100     {
1101 #ifndef NO_OL_COMPAT
1102         ClientData *leader;
1103         Atom *pIDs;
1104         unsigned int numIDs = 0;
1105
1106         /*
1107          * Save the window group.
1108          */
1109
1110         if (flags & WindowGroupHint)
1111         {
1112             pCD->windowGroup = pXWMHints->window_group;
1113             /*
1114              * Pretend this is a transient window 
1115              */
1116             if ((pCD->bPseudoTransient) && 
1117                 (pCD->transientFor == (Window)0L))
1118             {
1119                 pCD->clientFlags |= CLIENT_TRANSIENT;
1120
1121                 /*
1122                  * Treat this like a transient window. This is transient
1123                  * for the window group window.
1124                  */
1125
1126                 if ((pCD->client != pCD->windowGroup) &&
1127                     !XFindContext (DISPLAY, pCD->windowGroup, 
1128                         wmGD.windowContextType, (caddr_t *)&leader))
1129                 {
1130                     pCD->transientFor = pCD->windowGroup;
1131                     pCD->transientLeader = leader;
1132
1133                     /*
1134                      * Insure it is in the same set of workspaces
1135                      * as the leader.
1136                      */
1137                     if (pCD->transientLeader && 
1138                         GetLeaderPresence(pCD, &pIDs, &numIDs))
1139                     {
1140                         ProcessWorkspaceHintList (pCD, pIDs, numIDs);
1141                     }
1142                 }
1143             }
1144         }
1145         else
1146         {
1147             pCD->windowGroup = 0L;
1148         }
1149 #endif /* NO_OL_COMPAT */
1150         /*
1151          * The window manger does not do anything with the input hint.  Input
1152          * always goes to the selected window.
1153          */
1154
1155         if (flags & InputHint)
1156         {
1157             pCD->inputFocusModel = pXWMHints->input;
1158         }
1159         else
1160         {
1161             pCD->inputFocusModel = True;
1162         }
1163
1164
1165         /*
1166          *  The default state is NORMAL_STATE.  States other than iconic
1167          *  (e.g., ZoomState from the R2 ICCC) indicate to the window manager
1168          *  that the NORMAL_STATE is to be used.
1169          */
1170
1171         if (pCD->clientFlags & SM_CLIENT_STATE)
1172         {
1173              if ((pCD->clientState == MINIMIZED_STATE) &&
1174                 (!(pCD->clientFunctions & MWM_FUNC_MINIMIZE)))
1175              {
1176                  pCD->clientState = NORMAL_STATE;
1177              }
1178         }
1179         else
1180         if ((flags & StateHint) && (pXWMHints->initial_state == IconicState) &&
1181             (pCD->clientFunctions & MWM_FUNC_MINIMIZE))
1182         {
1183             pCD->clientState = MINIMIZED_STATE;
1184         }
1185         else
1186         {
1187             /*
1188              * States other than iconic are treated as normal.
1189              */
1190             pCD->clientState = NORMAL_STATE;
1191         }
1192
1193
1194 #ifdef WSM
1195         if (!ClientInWorkspace (PSD_FOR_CLIENT(pCD)->pActiveWS, pCD))
1196         {
1197             pCD->clientState |= UNSEEN_STATE;
1198         }
1199 #endif /* WSM */
1200
1201
1202         /*
1203          * If an icon is to be made for the client then ...
1204          * save the icon image if useClientIcon is True or there is no
1205          * user specified icon image.  A client supplied image may be a
1206          * pixmap or a window (a client icon window takes precedence over
1207          * a pixmap).
1208          */
1209
1210         if ((pCD->clientFunctions & MWM_FUNC_MINIMIZE) &&
1211             (pCD->transientLeader == NULL))
1212         {
1213             if ((ICON_DECORATION(pCD) & ICON_IMAGE_PART) &&
1214                 (pCD->useClientIcon || !pCD->iconImage))
1215             {
1216                 if ((flags & IconWindowHint) &&
1217                     (pXWMHints->icon_window != pCD->client))
1218                 {
1219                     /* 
1220                      * An icon window has been supplied that is different from
1221                      * the client window.  Check out the window and get it 
1222                      * ready to be reparented to the window manager supplied
1223                      * icon frame.
1224                      */
1225
1226                     if (!SetupClientIconWindow (pCD, pXWMHints->icon_window))
1227                     {
1228                         /*
1229                          * Cannot use the client supplied icon window.  Use
1230                          * an icon image if specified or a default image.
1231                          */
1232                     }
1233                 }
1234                 if (!pCD->iconWindow && (flags & IconPixmapHint))
1235                 {
1236                     iconMask = (flags & IconMaskHint) ?
1237                                 pXWMHints->icon_mask : (Pixmap) NULL;
1238                     /*
1239                      * A client supplied icon window is NOT 
1240                      * available so use the client supplied icon image.
1241                      */
1242
1243                     if ((pCD->iconPixmap = 
1244                             MakeClientIconPixmap (pCD,
1245                               pXWMHints->icon_pixmap, iconMask)) != None)
1246                     {
1247                         /*
1248                          * Indicate that a client supplied icon image is being
1249                          * used.
1250                          */
1251
1252                         pCD->iconFlags |= ICON_HINTS_PIXMAP;
1253                     }
1254                     else
1255                     {
1256                         /*
1257                          * Cannot make a client supplied image.  Use a user
1258                          * specified icon image if it is available or a default
1259                          * icon image.
1260                          */
1261                     }
1262                 }
1263             }
1264
1265             if ((ICON_DECORATION(pCD) & ICON_IMAGE_PART) && !pCD->iconPixmap)
1266             {
1267                 /*
1268                  * Use a user supplied icon image if it is available or a
1269                  * default icon image.
1270                  */
1271
1272                 if (pCD->iconImage)
1273                 {
1274                     /*
1275                      * Try to make a user specified icon image.
1276                      */
1277
1278                     pCD->iconPixmap = 
1279                         MakeNamedIconPixmap (pCD, pCD->iconImage);
1280                 }
1281
1282                 if (!pCD->iconPixmap)
1283                 {
1284                     /*
1285                      * The icon image was not provided or not available.
1286                      * Use the default icon image.
1287                      */
1288
1289                     pCD->iconPixmap = MakeNamedIconPixmap (pCD, NULL);
1290                 }
1291             }
1292     
1293
1294             /*
1295              * Save the client (user?) supplied icon position:
1296              */
1297
1298             if ((flags & IconPositionHint) ||
1299                 (pCD->clientFlags & (SM_ICON_X | SM_ICON_Y)))
1300             {
1301                 pCD->iconFlags |= ICON_HINTS_POSITION;
1302                 if (wmGD.iconAutoPlace)
1303 #ifdef WSM
1304                 {
1305                     /* 
1306                      * Initialize icon placement data in all inhabited
1307                      * workspaces
1308                      */
1309                     for (iws = 0; iws< pCD->numInhabited; iws++)
1310                     {
1311                         pWsc = &(pCD->pWsList[iws]);
1312                         if ((pWsTmp=GetWorkspaceData(pCD->pSD, pWsc->wsID)))
1313                         {
1314                             tmpIconX = (pCD->clientFlags & SM_ICON_X) ?
1315                               pWsc->iconX : pXWMHints->icon_x;
1316                             tmpIconY = (pCD->clientFlags & SM_ICON_Y) ?
1317                               pWsc->iconY : pXWMHints->icon_y;
1318                             pWsc->iconPlace =
1319                                 FindIconPlace (pCD, &(pWsTmp->IPData),
1320                                                tmpIconX, tmpIconY);
1321                             if (pWsc->iconPlace != NO_ICON_PLACE)
1322                             {
1323                                 CvtIconPlaceToPosition ( &(pWsTmp->IPData),
1324                                     pWsc->iconPlace,
1325                                     &pWsc->iconX,
1326                                     &pWsc->iconY);
1327                             }
1328                         }
1329                     }
1330                 }
1331                 else
1332                 {
1333                     for (iws = 0; iws< pCD->numInhabited; iws++)
1334                     {
1335                         pWsc = &(pCD->pWsList[iws]);
1336                         if ((pWsTmp=GetWorkspaceData(pCD->pSD, pWsc->wsID)))
1337                         {
1338                             if (!(pCD->clientFlags & SM_ICON_X))
1339                                 pWsc->iconX = pXWMHints->icon_x;
1340                             if (!(pCD->clientFlags & SM_ICON_Y))
1341                                 pWsc->iconY = pXWMHints->icon_y;
1342                         }
1343                     }
1344                 }
1345 #else /* WSM */
1346                 {
1347                     tmpIconX = (pCD->clientFlags & SM_ICON_X) ?
1348                       pCD->iconX : pXWMHints->icon_x;
1349                     tmpIconY = (pCD->clientFlags & SM_ICON_Y) ?
1350                       pCD->iconY : pXWMHints->icon_y;
1351                     pCD->iconPlace = 
1352                         FindIconPlace (pCD, &(pCD->pSD->pActiveWS->IPData),
1353                                        tmpIconX, tmpIconY);
1354                     if (pCD->iconPlace != NO_ICON_PLACE)
1355                     {
1356                         CvtIconPlaceToPosition (&(pCD->pSD->pActiveWS->IPData),
1357                             pCD->iconPlace, &pCD->iconX, &pCD->iconY);
1358                     }
1359                 }
1360                 else
1361                 {
1362                     if (!(pCD->clientFlags & SM_ICON_X))
1363                         pCD->iconX = pXWMHints->icon_x;
1364                     if (!(pCD->clientFlags & SM_ICON_Y))
1365                         pCD->iconY = pXWMHints->icon_y;
1366                 }
1367 #endif /* WSM */
1368             }
1369             else
1370             {
1371                 if (wmGD.iconAutoPlace)
1372                 {
1373 #ifdef WSM
1374                     /* 
1375                      * Initialize icon placement data in all inhabited
1376                      * workspaces
1377                      */
1378                     for (iws = 0; iws< pCD->numInhabited; iws++)
1379                     {
1380                         pWsc = &(pCD->pWsList[iws]);
1381                         pWsc->iconPlace = NO_ICON_PLACE;
1382                         pWsc->iconX = 0;
1383                         pWsc->iconY = 0;
1384                     }
1385 #else /* WSM */
1386                     pCD->iconPlace = NO_ICON_PLACE;
1387                     pCD->iconX = 0;
1388                     pCD->iconY = 0;
1389 #endif /* WSM */
1390                 }
1391             }
1392         }
1393
1394 #ifdef NO_OL_COMPAT
1395         /*
1396          * Save the window group.
1397          */
1398
1399         if (flags & WindowGroupHint)
1400         {
1401             pCD->windowGroup = pXWMHints->window_group;
1402         }
1403         else
1404         {
1405             pCD->windowGroup = 0L;
1406         }
1407 #endif /* NO_OL_COMPAT */
1408     }
1409     else /* not the first time the hints are processed */
1410     {
1411         if (flags & IconPixmapHint)
1412         {
1413             /*
1414              * Process an icon image change if the icon image was initially
1415              * set up with a client supplied icon image OR, if the client
1416              * now wants to supply an image.
1417              */
1418             iconMask = (flags & IconMaskHint)?
1419                        pXWMHints->icon_mask : (Pixmap) NULL;
1420
1421             if ((iconPixmap = 
1422                  MakeClientIconPixmap (pCD, pXWMHints->icon_pixmap, 
1423                                              iconMask)) != None)
1424             {
1425                 /*
1426                  * Made new icon image; free up the old image and display
1427                  * the new image.
1428                  */
1429                 if (pCD->iconFlags & ICON_HINTS_PIXMAP)
1430                 {
1431                     /*
1432                      * ICON_HINTS_PIXMAP was set either initally or
1433                      * below because a new pixmap was made for the client.
1434                      * It is now safe to free the previous pixmap since it
1435                      * is not the shared default iconPixmap
1436                      */
1437                     if (pCD->iconPixmap)
1438                     {
1439                         XFreePixmap (DISPLAY, pCD->iconPixmap);
1440                     }
1441                 }
1442                 else
1443                 {
1444                     pCD->iconFlags |= ICON_HINTS_PIXMAP;
1445                 }
1446                 
1447                 pCD->iconPixmap = iconPixmap;
1448                 
1449                 /*
1450                  * Display new icon image if the icon is showing:
1451                  */
1452                 
1453                 if (((pCD->clientState == MINIMIZED_STATE) ||
1454                      ((pCD->pSD->useIconBox) && (P_ICON_BOX(pCD)))) &&
1455                     ICON_FRAME_WIN(pCD))
1456                 {
1457                     IconExposureProc (pCD, True);
1458                 }
1459             }
1460         }
1461     }
1462
1463     if (pXWMHints)
1464     {
1465         XFree ((char*)pXWMHints);
1466     }
1467
1468
1469 } /* END OF FUNCTION ProcessWmHints */
1470
1471
1472 \f
1473 /*************************************<->*************************************
1474  *
1475  *  ProcessWmNormalHints (pCD, firstTime, manageFlags)
1476  *
1477  *
1478  *  Description:
1479  *  -----------
1480  *  This function retrieves the contents of the WM_NORMAL_HINTS property on
1481  *   the cient window.  There are several versions of the property that must be
1482  *  handled (currently R2 and CURRENT).
1483  *
1484  *
1485  *  Inputs:
1486  *  ------
1487  *  pCD = pointer to client data for the window with the property
1488  *
1489  *  firstTime = if True this is the first time the property has been processed
1490  *
1491  *  manageFlags = flags that indicate wm state information
1492  *
1493  * 
1494  *  Outputs:
1495  *  -------
1496  *  pCD = client location and size fields set
1497  *
1498  *
1499  *  Comments:
1500  *  --------
1501  *  If the hints are being reprocessed (!firstTime) the configuration values
1502  *  will be ignored.  The size constraint values will be processed but the
1503  *  client configuration will not be changed even if it is not in line with
1504  *  the new values.  Reconfigurations subsequent to the hints changes will
1505  *  be done with the new constraints.
1506  *
1507  *************************************<->***********************************/
1508
1509 void 
1510 ProcessWmNormalHints (ClientData *pCD, Boolean firstTime, long manageFlags)
1511 {
1512     register SizeHints *pNormalHints;
1513     register long       flags;
1514     int                 diff;
1515     unsigned long       decoration;
1516     unsigned int        boxdim, tmpMin;
1517     unsigned int        oldWidthInc, oldHeightInc;
1518     unsigned int        oldBaseWidth, oldBaseHeight;
1519     unsigned int        incWidth, incHeight;
1520
1521     /*
1522      * Use a custom verion of the Xlib routine to get WM_NORMAL_HINTS.
1523      * A custom version is necessary to handle the different versions
1524      * of WM_NORMAL_HINTS that may be encountered.  If the WM_NORMAL_HINTS
1525      * property does not exist the flags field will be set to 0.
1526      */
1527
1528     pNormalHints = GetNormalHints (pCD);
1529
1530     pCD->icccVersion = pNormalHints->icccVersion;
1531
1532
1533     /*
1534      * Parse the WM_NORMAL_HINTS information:
1535      */
1536
1537     if (((flags = pNormalHints->flags) == 0) && !firstTime)
1538     {
1539         return;
1540     }
1541
1542
1543     /*
1544      * Process the size only if this is the first time the hints are
1545      * being processed for the window.
1546      */
1547
1548     if (firstTime)
1549     {
1550         /*
1551          * Process client window size flags and information:
1552          */
1553
1554         pCD->sizeFlags = flags & (US_POSITION | US_SIZE | P_POSITION | P_SIZE);
1555
1556         /*
1557          * The R2 conventions and Xlib manual indicate that the window size
1558          * and position should be taken out of the WM_NORMAL_HINTS property
1559          * if they are specified there.  The current conventions indicate that
1560          * the size and position information should be gotten from the window
1561          * configuration. Mwm 1.1 always uses the current conventions.
1562          */
1563
1564 #ifdef R2_COMPAT
1565     /* 
1566      * Maintain R2 compatiblity code for CND product xnm
1567      */
1568         if ((pNormalHints->icccVersion == ICCC_R2) &&
1569             (flags & (US_POSITION | P_POSITION)) &&
1570             !(manageFlags & MANAGEW_WM_RESTART))
1571         {
1572             if (!(pCD->clientFlags & SM_X))
1573                 pCD->clientX = pNormalHints->x;
1574             if (!(pCD->clientFlags & SM_Y))
1575                 pCD->clientY = pNormalHints->y;
1576         }
1577         else
1578         {
1579             if (!(pCD->clientFlags & SM_X))
1580                 pCD->clientX = wmGD.windowAttributes.x;
1581             if (!(pCD->clientFlags & SM_Y))
1582                 pCD->clientY = wmGD.windowAttributes.y;
1583         }
1584 #else /* R2_COMPAT */
1585         if (!(pCD->clientFlags & SM_X))
1586             pCD->clientX = wmGD.windowAttributes.x;
1587         if (!(pCD->clientFlags & SM_Y))
1588             pCD->clientY = wmGD.windowAttributes.y;
1589 #endif  /* R2_COMPAT */
1590
1591         /*
1592          * Use current conventions for initial window dimensions.
1593          */
1594
1595 #ifdef R2_COMPAT
1596     /* 
1597      * Maintain R2 compatiblity code for CND product xnm
1598      */
1599         if ((pNormalHints->icccVersion == ICCC_R2) &&
1600             (flags & (US_SIZE | P_SIZE)) &&
1601             !(manageFlags & MANAGEW_WM_RESTART))
1602         {
1603             if (!(pCD->clientFlags & SM_WIDTH))
1604                 pCD->clientWidth = pNormalHints->width;
1605             if (!(pCD->clientFlags & SM_HEIGHT))
1606                 pCD->clientHeight = pNormalHints->height;
1607         }
1608         else
1609         {
1610             if (!(pCD->clientFlags & SM_WIDTH))
1611                 pCD->clientWidth = wmGD.windowAttributes.width;
1612             if (!(pCD->clientFlags & SM_HEIGHT))
1613                 pCD->clientHeight = wmGD.windowAttributes.height;
1614         }
1615 #else /* R2_COMPAT */
1616         if (!(pCD->clientFlags & SM_WIDTH))
1617             pCD->clientWidth = wmGD.windowAttributes.width;
1618         if (!(pCD->clientFlags & SM_HEIGHT))
1619             pCD->clientHeight = wmGD.windowAttributes.height;
1620 #endif /* R2_COMPAT */
1621     }
1622
1623     /*
1624      * Process the minimum size:
1625      */
1626
1627     if (flags & P_MIN_SIZE)
1628     {
1629         pCD->minWidth =
1630                  (pNormalHints->min_width < 0) ? 0 : pNormalHints->min_width;
1631         pCD->minHeight =
1632                  (pNormalHints->min_height < 0) ? 0 : pNormalHints->min_height;
1633         if (pCD->minWidth > MAX_MAX_SIZE(pCD).width)
1634         {
1635             pCD->minWidth = MAX_MAX_SIZE(pCD).width;
1636         }
1637         if (pCD->minHeight > MAX_MAX_SIZE(pCD).height)
1638         {
1639             pCD->minHeight = MAX_MAX_SIZE(pCD).height;
1640         }
1641     }
1642     else if (firstTime)
1643     {
1644         pCD->minWidth = 0;
1645         pCD->minHeight = 0;
1646     }
1647
1648
1649     /*
1650      * Process the resizing increments:
1651      */
1652
1653     if (!firstTime)
1654     {
1655         oldWidthInc = (pCD->widthInc == 0) ? 1 : pCD->widthInc;
1656         oldHeightInc = (pCD->heightInc == 0) ? 1 : pCD->heightInc;
1657     }
1658
1659     if (flags & P_RESIZE_INC)
1660     {
1661         pCD->widthInc =
1662                  (pNormalHints->width_inc < 1) ? 1 : pNormalHints->width_inc;
1663         pCD->heightInc =
1664                  (pNormalHints->height_inc < 1) ? 1 : pNormalHints->height_inc;
1665     }
1666     else if (firstTime)
1667     {
1668         pCD->widthInc = 1;
1669         pCD->heightInc = 1;
1670     }
1671
1672
1673     /*
1674      * Process the base size:
1675      */
1676
1677     if (!firstTime)
1678     {
1679         oldBaseWidth = pCD->baseWidth;
1680         oldBaseHeight = pCD->baseHeight;
1681     }
1682
1683     if (flags & P_BASE_SIZE)
1684     {
1685         pCD->baseWidth =
1686                 (pNormalHints->base_width < 0) ? 0 : pNormalHints->base_width;
1687         pCD->baseHeight =
1688                 (pNormalHints->base_height < 0) ? 0 : pNormalHints->base_height;
1689     }
1690     else if ((pNormalHints->icccVersion == ICCC_R2) &&
1691              ((firstTime) ||
1692               (!firstTime && (flags & P_MIN_SIZE))))
1693     {
1694         /*
1695          * In this version of the hints the minimum size was effectively
1696          * the base size.
1697          */
1698         pCD->baseWidth = pCD->minWidth;
1699         pCD->baseHeight = pCD->minHeight;
1700     }
1701     else if (firstTime)
1702     {
1703         if (flags & P_MIN_SIZE)
1704         {
1705             pCD->baseWidth = pCD->minWidth;
1706             pCD->baseHeight = pCD->minHeight;
1707         }
1708         else
1709         {
1710             pCD->baseWidth = 0;
1711             pCD->baseHeight = 0;
1712         }
1713     }
1714
1715     if (firstTime)
1716     {
1717         if (pCD->clientFlags & SM_WIDTH)
1718         {
1719             pCD->clientWidth = ((pCD->clientWidth * pCD->widthInc) +
1720                                 pCD->baseWidth);
1721         }
1722         if (pCD->clientFlags & SM_HEIGHT)
1723         {
1724             pCD->clientHeight =((pCD->clientHeight * pCD->heightInc) +
1725                                 pCD->baseHeight);
1726         }
1727     }
1728
1729     /*
1730      * Process the maximum width.  NOTE: maximumClientSize.width
1731      * and maximumClientSize.height will be set to BIGSIZE if
1732      * maximumClientSize is either set to 'horizontal' or 'vertical'.
1733      */
1734
1735     pCD->oldMaxWidth = pCD->maxWidth;
1736     if (pCD->maximumClientSize.width)
1737     {
1738         /* If maximumClientSize is full 'horizontal' */
1739         if (IS_MAXIMIZE_HORIZONTAL(pCD))
1740         {
1741             /* go to min (full screen width, max maximum width) */
1742             pCD->maxWidth = DisplayWidth (DISPLAY, SCREEN_FOR_CLIENT(pCD)) -
1743                                           (2 * pCD->clientOffset.x);
1744
1745             /*
1746              * Hack to set max client to the current client height, maxHeight
1747              * will be kept up to date whenever the window is reconfigured
1748              */
1749             pCD->maxHeight = pCD->clientHeight;
1750
1751         }
1752         else
1753         {
1754             pCD->maxWidth = (pCD->maximumClientSize.width * 
1755                              pCD->widthInc) + pCD->baseWidth;
1756         }
1757     }
1758     else
1759     {
1760         if (flags & P_MAX_SIZE)
1761         {
1762             if (pNormalHints->max_width < 0)
1763             {
1764                 /* go to min (full screen width, max maximum width) */
1765                 pCD->maxWidth = DisplayWidth (DISPLAY, SCREEN_FOR_CLIENT(pCD)) -
1766                                           (2 * pCD->clientOffset.x);
1767             }
1768             else
1769             {
1770                 pCD->maxWidth = pNormalHints->max_width;
1771             }
1772         }
1773         /* Don't reset maxWidth if it has been set earlier */
1774         else if (!IS_MAXIMIZE_VERTICAL(pCD))
1775         {
1776             if (firstTime)
1777             {
1778                 /* go to min (full screen width, max maximum width) */
1779                 pCD->maxWidth = DisplayWidth (DISPLAY,
1780                                               SCREEN_FOR_CLIENT(pCD)) -
1781                                                 (2 * pCD->clientOffset.x);
1782             }
1783             else
1784             {
1785                 /* reset the maxHeight before further processing */
1786                 pCD->maxWidth = pCD->maxWidthLimit;
1787             }
1788         }
1789         else
1790         {
1791             /* 
1792              * If the hints changed we need to adjust the maximum
1793              * size (if not specified in the hints).
1794              */
1795             if (!firstTime &&
1796                 ((oldBaseWidth != pCD->baseWidth) ||
1797                  (oldWidthInc != pCD->widthInc)))
1798             {
1799                 incWidth = (pCD->maxWidth - oldBaseWidth) / oldWidthInc;
1800                 pCD->maxWidth =  
1801                     (incWidth * pCD->widthInc) + pCD->baseWidth;
1802             }
1803             else
1804             {
1805                 /* reset the maxHeight before further processing */
1806                 pCD->maxWidth = pCD->maxWidthLimit;
1807             }
1808         }
1809         if (pCD->maxWidth > MAX_MAX_SIZE(pCD).width)
1810         {
1811             pCD->maxWidth = MAX_MAX_SIZE(pCD).width;
1812         }
1813     }
1814
1815
1816
1817     /*
1818      * Process the maximum height.
1819      */
1820
1821     pCD->oldMaxHeight = pCD->maxHeight;
1822     if (pCD->maximumClientSize.height)
1823     {
1824         /* If maximumClientSize is full 'vertical' */
1825         if (IS_MAXIMIZE_VERTICAL(pCD))
1826         {
1827             /* go to min (full screen height, max maximum height) */
1828             pCD->maxHeight = DisplayHeight (DISPLAY, SCREEN_FOR_CLIENT(pCD)) -
1829                              (pCD->clientOffset.x +
1830                               pCD->clientOffset.y);
1831             /*
1832              * Hack to set max client to the current client width, maxWidth
1833              * will be kept up to date whenever the window is reconfigured
1834              */
1835             pCD->maxWidth = pCD->clientWidth;
1836
1837         }
1838         else
1839         {
1840             pCD->maxHeight = (pCD->maximumClientSize.height *
1841                               pCD->heightInc) + pCD->baseHeight;
1842         }
1843     }
1844     else
1845     {
1846         if (flags & P_MAX_SIZE)
1847         {
1848             if (pNormalHints->max_height < 0)
1849             {
1850                 /* go to min (full screen height, max maximum height) */
1851                 pCD->maxHeight = DisplayHeight (
1852                                  DISPLAY, SCREEN_FOR_CLIENT(pCD)) -
1853                                  (pCD->clientOffset.x +
1854                                   pCD->clientOffset.y);
1855             }
1856             else
1857             {
1858                 pCD->maxHeight = pNormalHints->max_height;
1859             }
1860         }
1861         /* Don't reset maxHeight if it has been set above */
1862         else if (!IS_MAXIMIZE_HORIZONTAL(pCD))
1863         {
1864             if (firstTime)
1865             {
1866                 /* go to min (full screen height, max maximum height) */
1867                 pCD->maxHeight = DisplayHeight (DISPLAY,
1868                                                 SCREEN_FOR_CLIENT(pCD)) -
1869                                                   (pCD->clientOffset.x +
1870                                                    pCD->clientOffset.y);
1871             }
1872             else
1873             {
1874                 /* reset the maxHeight before further processing */
1875                 pCD->maxHeight = pCD->maxHeightLimit;
1876             }
1877         }
1878         else
1879         {
1880             /* 
1881              * If the hints changed we need to adjust the maximum
1882              * size (if not specified in the hints).
1883              */
1884             if (!firstTime &&
1885                 ((oldBaseHeight != pCD->baseHeight) ||
1886                  (oldHeightInc != pCD->heightInc)))
1887             {
1888                 incHeight = (pCD->maxHeight - oldBaseHeight) / oldHeightInc;
1889                 pCD->maxHeight =  
1890                     (incHeight * pCD->heightInc) + pCD->baseHeight;
1891             }
1892             else
1893             {
1894                 /* reset the maxHeight before further processing */
1895                 pCD->maxHeight = pCD->maxHeightLimit;
1896             }
1897         }
1898         if (pCD->maxHeight > MAX_MAX_SIZE(pCD).height)
1899         {
1900             pCD->maxHeight = MAX_MAX_SIZE(pCD).height;
1901         }
1902     }
1903
1904     /*
1905      * Make sure not to exceed the maximumMaximumSize (width and height)
1906      */
1907
1908     if (pCD->maxWidth > MAX_MAX_SIZE(pCD).width)
1909     {
1910         pCD->maxWidth = MAX_MAX_SIZE(pCD).width;
1911     }
1912
1913     if (pCD->maxHeight > MAX_MAX_SIZE(pCD).height)
1914     {
1915         pCD->maxHeight = MAX_MAX_SIZE(pCD).height;
1916     }
1917
1918     /*
1919      * Get the initial aspect ratios, if available.  Only use them if:
1920      *
1921      *   minAspect.y > 0
1922      *   maxAspect.y > 0
1923      *   0 <= minAspect.x / minAspect.y <= maxAspect.x / maxAspect.y 
1924      */
1925
1926     if (flags & P_ASPECT)
1927     {
1928         pCD->minAspect.x = pNormalHints->min_aspect.x;
1929         pCD->minAspect.y = pNormalHints->min_aspect.y;
1930         pCD->maxAspect.x = pNormalHints->max_aspect.x;
1931         pCD->maxAspect.y = pNormalHints->max_aspect.y;
1932
1933         if (pCD->minAspect.y > 0 &&
1934             pCD->maxAspect.y > 0 &&
1935             pCD->minAspect.x > 0 &&
1936             pCD->maxAspect.x > 0 &&
1937             (pCD->minAspect.x * pCD->maxAspect.y <=
1938             pCD->maxAspect.x * pCD->minAspect.y))
1939         {
1940             pCD->sizeFlags |= P_ASPECT;
1941         }
1942         else
1943         {
1944             pCD->sizeFlags &= ~P_ASPECT;
1945         }
1946     }
1947
1948     /* compute for minimum frame size */
1949     if ((decoration = pCD->decor) & MWM_DECOR_TITLE)
1950     {
1951         boxdim = TitleBarHeight(pCD);
1952         tmpMin = boxdim +
1953                  ((decoration & MWM_DECOR_MENU) ? boxdim : 0) +
1954                  ((decoration & MWM_DECOR_MINIMIZE) ? boxdim : 0) +
1955                  ((decoration & MWM_DECOR_MAXIMIZE) ? boxdim : 0) -
1956                  2*(pCD->matteWidth);
1957     }
1958     else {
1959         tmpMin = 0;
1960     }
1961
1962
1963     /*
1964      * Process the window gravity (for positioning):
1965      */
1966
1967     if (flags & P_WIN_GRAVITY)
1968     {
1969         pCD->windowGravity = pNormalHints->win_gravity;
1970     }
1971     else
1972     {
1973         if (pNormalHints->icccVersion == ICCC_R2)
1974         {
1975             pCD->windowGravity = wmGD.windowAttributes.win_gravity;
1976         }
1977         else
1978         {
1979             pCD->windowGravity = NorthWestGravity;
1980         }
1981     }
1982
1983
1984     /*
1985      * Make sure that all the window sizing constraints are compatible:
1986      */
1987
1988     /*
1989      * Make:
1990      *
1991      *   minWidth >= tmpMin
1992      *   minWidth >= max (baseWidth, widthInc) > 0
1993      *     & an integral number of widthInc from baseWidth.
1994      *   minHeight >= max (baseHeight, heightInc) > 0
1995      *     & an integral number of heightInc from baseHeight.
1996      */
1997
1998     if (pCD->minWidth < tmpMin)
1999     {
2000         if ((diff = ((tmpMin - pCD->baseWidth)%pCD->widthInc)) != 0)
2001         {
2002             pCD->minWidth = tmpMin + pCD->widthInc - diff;
2003         }
2004         else
2005         {
2006             pCD->minWidth = tmpMin;
2007         }
2008     }
2009
2010     if (pCD->minWidth < pCD->baseWidth)
2011     {
2012         pCD->minWidth = pCD->baseWidth;
2013     }
2014
2015     if (pCD->minWidth == 0)
2016     {
2017         pCD->minWidth = pCD->widthInc;
2018     }
2019     else if ((diff = ((pCD->minWidth - pCD->baseWidth)%pCD->widthInc)) != 0)
2020     {
2021         pCD->minWidth += pCD->widthInc - diff;
2022     }
2023
2024     if (pCD->minHeight < pCD->baseHeight)
2025     {
2026         pCD->minHeight = pCD->baseHeight;
2027     }
2028
2029     if (pCD->minHeight == 0)
2030     {
2031         pCD->minHeight = pCD->heightInc;
2032     }
2033     else if ((diff = ((pCD->minHeight - pCD->baseHeight) % pCD->heightInc)) !=0)
2034     {
2035         pCD->minHeight += pCD->heightInc - diff;
2036     }
2037
2038     /*
2039      * Make:
2040      *
2041      *   maxWidth >= minWidth 
2042      *     & an integral number of widthInc from baseWidth.
2043      *   maxHeight >= minHeight
2044      *     & an integral number of heightInc from baseHeight.
2045      */
2046
2047     if (pCD->maxWidth < pCD->minWidth)
2048     {
2049         pCD->maxWidth = pCD->minWidth;
2050     }
2051
2052     /*
2053      * Hack to use maxWidthLimit as the real maxWidth when maximumClientSize
2054      * set to 'vertical'.
2055      */
2056     if (IS_MAXIMIZE_VERTICAL(pCD))
2057     {
2058         /* go to min (full screen width, max maximum width) */
2059         pCD->maxWidthLimit = DisplayWidth (DISPLAY, SCREEN_FOR_CLIENT(pCD)) -
2060                             (2 * pCD->clientOffset.x);
2061     }
2062     else
2063     {
2064         pCD->maxWidthLimit = pCD->maxWidth;
2065     }
2066
2067     pCD->maxWidth -= ((pCD->maxWidth - pCD->baseWidth) % pCD->widthInc);
2068
2069     if (firstTime)
2070     {
2071         pCD->oldMaxWidth = pCD->maxWidth;
2072     }
2073
2074     if (pCD->maxHeight < pCD->minHeight)
2075     {
2076         pCD->maxHeight = pCD->minHeight;
2077     }
2078
2079     /*
2080      * Hack to use maxHeightLimit as the real maxHeight when maximumClientSize
2081      * set to 'horizontal'.
2082      */
2083     if (IS_MAXIMIZE_HORIZONTAL(pCD))
2084     {
2085         /* go to min (full screen height, max maximum height) */
2086         pCD->maxHeightLimit = DisplayHeight (DISPLAY, SCREEN_FOR_CLIENT(pCD)) -
2087                              (pCD->clientOffset.x +
2088                               pCD->clientOffset.y);
2089     }
2090     else
2091     {
2092         pCD->maxHeightLimit = pCD->maxHeight;
2093     }
2094
2095     pCD->maxHeight -= ((pCD->maxHeight - pCD->baseHeight) % pCD->heightInc);
2096
2097     if (firstTime)
2098     {
2099         pCD->oldMaxHeight = pCD->maxHeight;
2100     }
2101
2102     if (!firstTime && pCD->maxConfig)
2103     {
2104         /* 
2105          * If the hints changed while we were maximized then 
2106          * we may need to adjust the normalized size of the window.
2107          */
2108         if (!firstTime &&
2109             ((oldBaseWidth != pCD->baseWidth) ||
2110              (oldBaseHeight != pCD->baseHeight) ||
2111              (oldWidthInc != pCD->widthInc) ||
2112              (oldHeightInc != pCD->heightInc)))
2113         {
2114             incWidth = (pCD->clientWidth - oldBaseWidth) / oldWidthInc;
2115             incHeight = (pCD->clientHeight - oldBaseHeight) / oldHeightInc;
2116             pCD->clientWidth =  
2117                 (incWidth * pCD->widthInc) + pCD->baseWidth;
2118             pCD->clientHeight =  
2119                 (incHeight * pCD->heightInc) + pCD->baseHeight;
2120         }
2121     }
2122
2123     /*
2124      * If using aspect ratios, make:
2125      *
2126      *  minWidth / maxHeight <= minAspect.x / minAspect.y 
2127      *                       <= maxAspect.x / maxAspect.y
2128      *                       <= maxWidth / minHeight
2129      */
2130
2131     if (pCD->sizeFlags & P_ASPECT)
2132     {
2133         if (pCD->minWidth * pCD->minAspect.y >
2134             pCD->minAspect.x * pCD->maxHeight)
2135         {
2136             pCD->minAspect.x = pCD->minWidth;
2137             pCD->minAspect.y = pCD->maxHeight;
2138         }
2139
2140         if (pCD->maxAspect.x * pCD->minHeight >
2141             pCD->maxWidth * pCD->maxAspect.y)
2142         {
2143             pCD->maxAspect.x = pCD->maxWidth;
2144             pCD->maxAspect.y = pCD->minHeight;
2145         }
2146
2147         FixWindowSize (pCD, (unsigned int *) &(pCD->maxWidth),
2148                             (unsigned int *) &(pCD->maxHeight),
2149                             (unsigned int) (pCD->widthInc), 
2150                             (unsigned int) (pCD->heightInc));
2151     }
2152
2153     /*
2154      * If this is the first time, make sure the client dimensions are within 
2155      * range and that they satisfy any aspect ratio constraints:
2156      *
2157      *  0 < minWidth  <= clientWidth  <= maxWidth
2158      *  0 < minHeight <= clientHeight <= maxHeight
2159      *
2160      *  minAspect.x / minAspect.y <= clientWidth / clientHeight
2161      *                            <= maxAspect.x / maxAspect.y
2162      *
2163      * Initial max width/height are set to max of max size or normal
2164      * client size unless a maximumClientSize was specified.
2165      */
2166
2167     if (firstTime)
2168     {
2169         if (!pCD->maximumClientSize.width)
2170         {
2171             if (pCD->clientWidth > pCD->pSD->maximumMaximumSize.width)
2172             {
2173                 pCD->clientWidth = pCD->pSD->maximumMaximumSize.width;
2174             }
2175         }
2176
2177         if (!pCD->maximumClientSize.height)
2178         {
2179             if (pCD->clientHeight > pCD->pSD->maximumMaximumSize.height)
2180             {
2181                 pCD->clientHeight = pCD->pSD->maximumMaximumSize.height;
2182             }
2183         }
2184
2185         FixWindowSize (pCD, (unsigned int *) &(pCD->clientWidth), 
2186                             (unsigned int *) &(pCD->clientHeight),
2187                             (unsigned int) (pCD->widthInc), 
2188                             (unsigned int) (pCD->heightInc));
2189     }
2190
2191 } /* END OF FUNCTION ProcessWmNormalHints */
2192
2193 \f
2194 /*************************************<->*************************************
2195  *
2196  *  WmICCCMToXmString (wmNameProp)
2197  *
2198  *
2199  *  Description:
2200  *  -----------
2201  *  This function uses a property (WM_NAME or WM_ICON_NAME) that was
2202  *  retrieved from the window, and converts it to XmString.
2203  *
2204  *  Inputs:
2205  *  ------
2206  *  wmNameProp  - the text property
2207  * 
2208  *  Outputs:
2209  *  -------
2210  *  Return = new XmString, or NULL if the property didn't have a value.
2211  * 
2212  *************************************<->***********************************/
2213
2214 static XmString
2215 WmICCCMToXmString (XTextProperty *wmNameProp)
2216 {
2217   int status;
2218   XmString xms_return;
2219   XmStringTable xmsTable;
2220   int i, nStrings = -1;
2221   char msg[200];
2222
2223   if (wmNameProp->value == 0 || strlen((char *)wmNameProp->value) == 0)
2224     {
2225       return (XmString)NULL;
2226     }
2227
2228   if (((status = XmCvtTextPropertyToXmStringTable(DISPLAY, wmNameProp,
2229                                                   &xmsTable, &nStrings))
2230        != Success) || (nStrings <= 0))
2231   {
2232       switch (status)
2233       {
2234       case XConverterNotFound:
2235 #ifndef MOTIF_ONE_DOT_ONE
2236           sprintf(msg, GETMESSAGE (70,5,
2237                     "Window manager cannot convert property %.100s as clientTitle/iconTitle: XmbTextPropertyToTextList"), 
2238                   XGetAtomName (DISPLAY,wmNameProp->encoding));
2239           Warning(msg);
2240 #endif /* MOTIF_ONE_DOT_ONE */
2241           break;
2242
2243       case XNoMemory:
2244           sprintf(msg, GETMESSAGE (70, 6, 
2245                     "insufficient memory to convert property %.100s as clientTitle/iconTitle: XmbTextPropertyToTextList"),
2246                   XGetAtomName(DISPLAY,wmNameProp->encoding));
2247           Warning(msg);
2248           break;
2249
2250       case XLocaleNotSupported:
2251           if ((wmNameProp->encoding == XA_STRING) ||
2252               (wmNameProp->encoding == wmGD.xa_COMPOUND_TEXT))
2253           {
2254               sprintf(msg, LOCALE_MSG, setlocale(LC_ALL, NULL));
2255           }
2256           else
2257           {
2258               /* Atom was neither STRING nor COMPOUND_TEXT */
2259               sprintf(msg, GETMESSAGE(70, 8, 
2260                         "Window manager received unknown property as clientTitle/iconTitle: %.100s. Property ignored."),
2261                       XGetAtomName(DISPLAY, wmNameProp->encoding));
2262           }
2263           Warning(msg);
2264           break;
2265       }
2266
2267       /* Couldn't convert using Xm; apply a default */
2268       return XmCvtCTToXmString((char*)wmNameProp->value);
2269   }
2270
2271   xms_return = xmsTable[0];
2272   for (i = 1; i < nStrings; i++)
2273   {
2274 #ifdef CONCAT_TEXTLIST
2275       xms_return = XmStringConcatAndFree(xms_return, xmsTable[i]);
2276 #else
2277       XmStringFree(xmsTable[i]);
2278 #endif /* CONCAT_TEXTLIST */
2279   }
2280   XtFree((char *)xmsTable);
2281
2282   return xms_return;
2283 }
2284
2285 \f
2286 /*************************************<->*************************************
2287  *
2288  *  ProcessWmWindowTitle (pCD, firstTime)
2289  *
2290  *
2291  *  Description:
2292  *  -----------
2293  *  This function retrieves the contents of the WM_NAME property on the
2294  *  cient window.  A default name is set if the property does not exist.
2295  *
2296  *
2297  *  Inputs:
2298  *  ------
2299  *  pCD         - pointer to client data structure
2300  *  firstTime   - false if the window is already managed and the title
2301  *                is being changed.
2302  *
2303  * 
2304  *  Outputs:
2305  *  -------
2306  *  pCD         - clientTitle, iconTitle
2307  * 
2308  *************************************<->***********************************/
2309
2310 void 
2311 ProcessWmWindowTitle (ClientData *pCD, Boolean firstTime)
2312 {
2313     XTextProperty wmNameProp;
2314     XmString title_xms = NULL;
2315
2316     if ((pCD->clientDecoration & MWM_DECOR_TITLE) &&
2317 #ifdef WSM
2318         (!firstTime || HasProperty (pCD, XA_WM_NAME)) &&
2319 #endif /* WSM */
2320         XGetWMName(DISPLAY, pCD->client, &wmNameProp))
2321     {
2322       title_xms = WmICCCMToXmString(&wmNameProp);
2323       if (wmNameProp.value)
2324         XFree ((char*)wmNameProp.value);
2325     }
2326
2327     if (title_xms)
2328     {
2329       if (!firstTime && (pCD->iconTitle == pCD->clientTitle))
2330       {
2331         /*
2332          * The client window title is being used for the icon title so
2333          * change the icon title with the window title.
2334          */
2335         pCD->iconTitle = title_xms;
2336         RedisplayIconTitle (pCD);
2337       }
2338
2339       if ((pCD->clientFlags & CLIENT_HINTS_TITLE) &&
2340           pCD->clientTitle != wmGD.clientDefaultTitle)
2341       {
2342         XmStringFree (pCD->clientTitle);
2343       }
2344
2345       pCD->clientTitle = title_xms;
2346       pCD->clientFlags |= CLIENT_HINTS_TITLE;
2347
2348       if (!firstTime)
2349       {
2350         DrawWindowTitle (pCD, True);
2351       }
2352     }
2353     /*
2354      * The client frame does not have a place to put the title or the WM_NAME
2355      * property does not exist or there was some error in getting
2356      * the property information, so use a default value.
2357      */
2358     else if (firstTime)
2359     {
2360         if (pCD->clientName)
2361         {
2362             pCD->clientTitle = XmStringCreateLocalized(pCD->clientName);
2363         }
2364         else
2365         {
2366             pCD->clientTitle = wmGD.clientDefaultTitle;
2367         }
2368     }
2369
2370     /*
2371      * If this is a tear-off menu, then make sure title text is not clipped
2372      */
2373
2374 #ifdef PANELIST
2375     if ((pCD->window_status & MWM_TEAROFF_WINDOW) ||
2376         (pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUBPANEL))
2377 #else /* PANELIST */
2378     if (pCD->window_status & MWM_TEAROFF_WINDOW)
2379 #endif /* PANELIST */
2380     {
2381         unsigned int boxdim = TitleBarHeight (pCD);
2382         unsigned long decor = pCD->decor;
2383         XmFontList  fontList;
2384         int minWidth;
2385
2386         if (DECOUPLE_TITLE_APPEARANCE(pCD))
2387             fontList = CLIENT_TITLE_APPEARANCE(pCD).fontList;
2388         else
2389             fontList = CLIENT_APPEARANCE(pCD).fontList;
2390
2391         /*
2392          * Calculations derived from GetTextBox() and GetFramePartInfo()
2393          */
2394         minWidth = XmStringWidth(fontList, pCD->clientTitle) +
2395 #ifdef PANELIST
2396             ((pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUBPANEL) ? 4 : 0) +
2397 #endif /* PANELIST */
2398                             ((decor & MWM_DECOR_MENU) ? boxdim : 0) +
2399                             ((decor & MWM_DECOR_MINIMIZE) ? boxdim : 0) +
2400                             ((decor & MWM_DECOR_MAXIMIZE) ? boxdim : 0) +
2401                               WM_TOP_TITLE_SHADOW + WM_BOTTOM_TITLE_SHADOW +
2402                                 WM_TOP_TITLE_PADDING + WM_BOTTOM_TITLE_PADDING;
2403
2404         if (minWidth > pCD->minWidth)
2405         {
2406             pCD->minWidth = minWidth;
2407         }
2408 #ifdef PANELIST
2409         if ((pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUBPANEL) &&
2410             (pCD->clientWidth < pCD->minWidth))
2411         {
2412             FixSubpanelEmbeddedClientGeometry (pCD);
2413         }
2414 #endif /* PANELIST */
2415     }
2416
2417 } /* END OF FUNCTION ProcessWmWindowTitle */
2418
2419 #ifdef PANELIST
2420 \f
2421 /*************************************<->*************************************
2422  *
2423  *  FixSubpanelEmbeddedClientGeometry ( pCD )
2424  *
2425  *
2426  *  Description:
2427  *  -----------
2428  *  This function adjusts the embedded clients in a subpanel if the 
2429  *  geometry of the subpanel is adjusted.
2430  *
2431  *
2432  *  Inputs:
2433  *  ------
2434  *  pCD         - pointer to client data structure
2435  *
2436  * 
2437  *  Outputs:
2438  *  -------
2439  *
2440  *  Comment:
2441  *  -------
2442  *  Only handles change in width right now.
2443  *
2444  *************************************<->***********************************/
2445
2446 static void 
2447 FixSubpanelEmbeddedClientGeometry (ClientData *pCD)
2448 {
2449     WmScreenData *pSD = PSD_FOR_CLIENT(pCD);
2450     Widget wSubpanel;
2451     Arg    al[5];
2452     int    ac;
2453
2454     /*
2455      * Get the widget for the subpanel
2456      */
2457     wSubpanel = WmPanelistWindowToSubpanel (DISPLAY1, pCD->client);
2458
2459     if (pSD->wPanelist && wSubpanel)
2460     {
2461         WmFpEmbeddedClientData  *pECD; 
2462         int i;
2463
2464         /*
2465          * set new shell width to minimum width
2466          */
2467         if (pCD->clientWidth < pCD->minWidth)
2468         {
2469             ac = 0;
2470             XtSetArg (al[ac], XmNwidth, pCD->minWidth); ac++;
2471             XtSetValues (wSubpanel, al, ac);
2472         }
2473
2474         /*
2475          * Cause update of client geometries.
2476          */
2477 /*      WmPanelistSetClientGeometry (pSD->wPanelist);   */
2478
2479         /*
2480          * Update all affected reparented controls.
2481          */
2482
2483         for (i=0; i<pSD->numEmbeddedClients; i++)
2484         {
2485             pECD =  &(((WmFpEmbeddedClientData *) pSD->pECD)[i]);
2486
2487             if (pECD->pCD)
2488             {
2489                 ClientData *pCD2 = pECD->pCD;
2490
2491                 if ((pCD2->clientWidth !=  pECD->width) ||
2492                     (pCD2->clientHeight != pECD->height) ||
2493                     (pCD2->clientX != pECD->x) ||
2494                     (pCD2->clientY != pECD->y))
2495                 {
2496                     pCD2->clientX = pECD->x;
2497                     pCD2->clientY = pECD->y;
2498                     pCD2->clientWidth = pECD->width;
2499                     pCD2->clientHeight = pECD->height;
2500
2501                     XMoveResizeWindow (DISPLAY1, pCD2->client, 
2502                         pECD->x, pECD->y, pECD->width, pECD->height);
2503                 }
2504             }
2505         }
2506     }
2507 } /* END OF FUNCTION FixEmbeddedClientGeometry */
2508
2509 #endif /* PANELIST */
2510
2511 \f
2512 /*************************************<->*************************************
2513  *
2514  *  ProcessWmIconTitle (pCD, firstTime)
2515  *
2516  *
2517  *  Description:
2518  *  -----------
2519  *  This function retrieves the contents of the WM_ICON_NAME property on the
2520  *  cient window.  The value of the property is a string that is used for the
2521  *  icon title.  A default title is set if the property does not exist.
2522  *
2523  *
2524  *  Inputs:
2525  *  ------
2526  *  pCD         - pointer to client data structure
2527  *
2528  *  firstTime   - false if the window is already managed and the title
2529  *                is being changed.
2530  *
2531  * 
2532  *  Outputs:
2533  *  -------
2534  *  pCD         - iconTitle
2535  * 
2536  *************************************<->***********************************/
2537
2538 void 
2539 ProcessWmIconTitle (ClientData *pCD, Boolean firstTime)
2540 {
2541   XTextProperty wmIconNameProp;
2542   XmString icon_xms = NULL;
2543
2544   if ((pCD->clientFunctions & MWM_FUNC_MINIMIZE) &&
2545       (pCD->transientLeader == NULL) &&
2546 #ifdef WSM
2547       (!firstTime || HasProperty(pCD, XA_WM_ICON_NAME)) &&
2548 #endif /* WSM */
2549       XGetWMIconName (DISPLAY, pCD->client, &wmIconNameProp))
2550   {
2551     icon_xms = WmICCCMToXmString(&wmIconNameProp);
2552     if (wmIconNameProp.value)
2553       XFree ((char*)wmIconNameProp.value);
2554   }
2555
2556   if (icon_xms)
2557   {
2558     if ((pCD->iconFlags & ICON_HINTS_TITLE) &&
2559         pCD->iconTitle != wmGD.iconDefaultTitle)
2560     {
2561       XmStringFree (pCD->iconTitle);
2562     }
2563
2564     pCD->iconTitle = icon_xms;
2565     pCD->iconFlags |= ICON_HINTS_TITLE;
2566
2567     if (!firstTime)
2568     {
2569       RedisplayIconTitle (pCD);
2570     }
2571   }
2572   /*
2573    * The WM_ICON_NAME property does not exist (or there was some error
2574    * in getting * the property information), so use a default value.
2575    */
2576   else if (firstTime)
2577   {
2578     if (pCD->clientTitle && (pCD->clientTitle != wmGD.clientDefaultTitle))
2579     {
2580       pCD->iconTitle = pCD->clientTitle;
2581     }
2582     else
2583     {
2584       pCD->iconTitle = wmGD.iconDefaultTitle;
2585     }
2586   }
2587
2588 } /* END OF FUNCTION ProcessWmIconTitle */
2589
2590
2591 \f
2592 /*************************************<->*************************************
2593  *
2594  *  ProcessWmTransientFor (pCD)
2595  *
2596  *
2597  *  Description:
2598  *  -----------
2599  *  This function retrieves the contents of the WM_TRANSIENT_FOR property on
2600  *  the cient window.
2601  *
2602  *
2603  *  Inputs:
2604  *  ------
2605  *  pCD = pointer to the client data structure for the window with the property
2606  *
2607  * 
2608  *  Outputs:
2609  *  -------
2610  *  pCD.transientFor = if tranient then this is the associated main window
2611  *
2612  *  pCD.clientFlags = indicate that this is a transient window
2613  * 
2614  *************************************<->***********************************/
2615
2616 void 
2617 ProcessWmTransientFor (ClientData *pCD)
2618 {
2619     Window window;
2620     ClientData *leader;
2621
2622
2623 #ifdef WSM
2624     if ((HasProperty (pCD, XA_WM_TRANSIENT_FOR)) &&
2625         (XGetTransientForHint (DISPLAY, pCD->client, &window)))
2626 #else /* WSM */
2627     if (XGetTransientForHint (DISPLAY, pCD->client, &window))
2628 #endif /* WSM */
2629     {
2630         pCD->clientFlags |= CLIENT_TRANSIENT;
2631
2632         /*
2633          * Only save the (leader) transientFor window if it is NOT the
2634          * client window and it is already managed by the window manager.
2635          */
2636
2637         if ((pCD->client != window) &&
2638             !XFindContext (DISPLAY, window, wmGD.windowContextType,
2639                 (caddr_t *)&leader))
2640         {
2641             pCD->transientFor = window;
2642             pCD->transientLeader = leader;
2643         }
2644     }
2645     else {    /* else this is not a transient window */
2646         pCD->clientFlags &= ~CLIENT_TRANSIENT;
2647         pCD->transientFor = (Window)0L;
2648         pCD->transientLeader = NULL;
2649     }
2650
2651
2652 } /* END OF FUNCTION ProcessWmTransientFor */
2653
2654
2655 \f
2656 /*************************************<->*************************************
2657  *
2658  *  MakeSystemMenu (pCD)
2659  *
2660  *
2661  *  Description:
2662  *  -----------
2663  *  This function finds or makes a system menu for the client.  A check
2664  *  is made for the _MWM_MENU property and, if present, client-specific
2665  *  items are added to the custom system menu.  Any custom system menu
2666  *  must be destroyed when the client is unmanaged (or killed).
2667  *
2668  *
2669  *  Inputs:
2670  *  ------
2671  *  pCD = pointer to the client data structure for the managed window
2672  *
2673  * 
2674  *  Outputs:
2675  *  -------
2676  *  pCD.systemMenuSpec = system menu specification for the client, not added
2677  *                       to wmGD.acceleratorMenuSpecs 
2678  *
2679  *************************************<->***********************************/
2680
2681 void 
2682 MakeSystemMenu (ClientData *pCD)
2683 {
2684 #if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
2685     MenuItem *lastItem;
2686 #endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
2687
2688     pCD->mwmMenuItems = GetMwmMenuItems(pCD);
2689     pCD->systemMenuSpec = 
2690        MAKE_MENU (PSD_FOR_CLIENT(pCD), pCD, pCD->systemMenu, F_CONTEXT_WINDOW,
2691                  F_CONTEXT_WINDOW|F_CONTEXT_ICON, pCD->mwmMenuItems, TRUE);
2692
2693 #ifdef NO_MESSAGE_CATALOG
2694     if (pCD->systemMenuSpec == NULL)
2695     {
2696         /*
2697          * As the lookup has failed, let's try just one more time.
2698          */
2699         Warning("Retrying - using builtin window menu\n");
2700
2701         pCD->systemMenuSpec =
2702           MAKE_MENU(PSD_FOR_CLIENT(pCD), pCD, builtinSystemMenuName,
2703                     F_CONTEXT_WINDOW,
2704                     F_CONTEXT_WINDOW|F_CONTEXT_ICON, pCD->mwmMenuItems, TRUE);
2705     }
2706 #endif
2707
2708 #if defined(MWM_QATS_PROTOCOL)
2709     /* Added to fix CDExc23338
2710      * Not sure what the MWM_QATS_PROTOCOL is trying to accomplish here,
2711      * but this code is causing the system menu to loose it's default
2712      * actions whenever client defined actions are added.  I thought
2713      * it prudent to minimize the changes.  It could be that the
2714      * #if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
2715      * should be
2716      * #if ((!defined(WSM)) && defined(MWM_QATS_PROTOCOL))
2717      * throughout the wm code, but I am loath to make such a change
2718      * without any documentation.
2719      */
2720
2721 #if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
2722     /** BEGIN FIX CR 6941 **/
2723
2724     /* if we still don't have a menu spec, then just abort. */
2725     if (pCD->systemMenuSpec == NULL)
2726       return;
2727
2728     pCD->systemMenuSpec = DuplicateMenuSpec(pCD->systemMenuSpec);
2729     XtFree(pCD->systemMenuSpec->name);
2730     pCD->systemMenuSpec->name = XtNewString("ProtocolsMenu");
2731
2732     /* Find the last menu item in the menu spec's list. */
2733     for (lastItem = pCD->systemMenuSpec->menuItems;
2734          lastItem->nextMenuItem != (MenuItem *) NULL;
2735          lastItem = lastItem->nextMenuItem)
2736       /*EMPTY*/;
2737     lastItem->nextMenuItem = pCD->mwmMenuItems;
2738
2739     /* Now recreate the menu widgets since we've appended the 
2740        protocol menu items */
2741     DestroyMenuSpecWidgets(pCD->systemMenuSpec);
2742     pCD->systemMenuSpec->menuWidget =
2743       CreateMenuWidget (PSD_FOR_CLIENT(pCD), pCD, "ProtocolsMenu",
2744                         PSD_FOR_CLIENT(pCD)->screenTopLevelW, TRUE,
2745                         pCD->systemMenuSpec, NULL);
2746     /** END FIX CR 6941 **/
2747 #endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
2748 #endif /* defined(MWM_QATS_PROTOCOL) */
2749
2750 } /* END OF FUNCTION MakeSystemMenu */
2751
2752
2753 \f
2754 /*************************************<->*************************************
2755  *
2756  *  InitCColormapData (pCD)
2757  *
2758  *
2759  *  Description:
2760  *  -----------
2761  *  This function initializes colormap data for the client window that is
2762  *  by the window manager in maintaining the colormap focus.  This may
2763  *  involve retrieving and processing properties that deal with subwindow
2764  *  colormaps.
2765  *
2766  *
2767  *  Inputs:
2768  *  ------
2769  *  pCD = pointer to the client data structure for the managed window
2770  *
2771  * 
2772  *  Outputs:
2773  *  -------
2774  *  pCD.clientColormap = client colormap to be installed when the client
2775  *                       window gets the colormap focus
2776  *
2777  *  pCD = (cmapWindows, clientCmapList, clientCmapCount, clientCmapIndex)
2778  *
2779  *************************************<->***********************************/
2780
2781 void 
2782 InitCColormapData (ClientData *pCD)
2783 {
2784
2785     if (wmGD.windowAttributes.colormap == None)
2786     {
2787         pCD->clientColormap = WORKSPACE_COLORMAP(pCD);
2788     }
2789     else
2790     {
2791         pCD->clientColormap = wmGD.windowAttributes.colormap;
2792     }
2793
2794     /*
2795      * Process subwindow colormap windows if they are specified.
2796      */
2797
2798     ProcessWmColormapWindows (pCD);
2799     
2800
2801 } /* END OF FUNCTION InitCColormapData */
2802
2803
2804 \f
2805 /*************************************<->*************************************
2806  *
2807  *  CalculateGravityOffset (pCD, xoff, yoff)
2808  *
2809  *
2810  *  Description:
2811  *  -----------
2812  *  This function calculates the window offsets based on the window gravity
2813  *  and the window frame client offset.
2814  *
2815  *
2816  *  Inputs:
2817  *  ------
2818  *  pCD = pointer to client data (client window configuration fields)
2819  *  xoff = pointer to xoffset
2820  *  yoff = pointer to yoffset
2821  *
2822  * 
2823  *  Outputs:
2824  *  -------
2825  *  xoff = pointer to xoffset set
2826  *  yoff = pointer to yoffset set
2827  * 
2828  *************************************<->***********************************/
2829
2830 void
2831 CalculateGravityOffset (ClientData *pCD, int *xoff, int *yoff)
2832 {
2833     int borderWidth = pCD->xBorderWidth;
2834
2835     if (pCD->windowGravity < ForgetGravity ||
2836         pCD->windowGravity > StaticGravity)
2837     {
2838         *xoff = 0;
2839         *yoff = 0;
2840     }
2841     else
2842     {
2843         switch (pCD->windowGravity)
2844         {
2845             case NorthWestGravity:
2846             default:
2847             {
2848                 *xoff = pCD->clientOffset.x;
2849                 *yoff = pCD->clientOffset.y;
2850                 break;
2851             }
2852
2853             case NorthGravity:
2854             {
2855                 *xoff = borderWidth;
2856                 *yoff = pCD->clientOffset.y;
2857                 break;
2858             }
2859                 
2860             case NorthEastGravity:
2861             {
2862                 *xoff = -(pCD->clientOffset.x - (2 * borderWidth));
2863                 *yoff = pCD->clientOffset.y;
2864                 break;
2865             }
2866
2867             case EastGravity:
2868             {
2869                 *xoff = -(pCD->clientOffset.x - (2 * borderWidth));
2870                 *yoff = borderWidth +
2871                                 (pCD->clientOffset.y - pCD->clientOffset.x)/2;
2872                 break;
2873             }
2874
2875             case SouthEastGravity:
2876             {
2877                 *xoff = -(pCD->clientOffset.x - (2 * borderWidth));
2878                 *yoff = -(pCD->clientOffset.x - (2 * borderWidth));
2879                 break;
2880             }
2881
2882             case SouthGravity:
2883             {
2884                 *xoff = borderWidth;
2885                 *yoff = -(pCD->clientOffset.x - (2 * borderWidth));
2886                 break;
2887             }
2888
2889             case SouthWestGravity:
2890             {
2891                 *xoff = pCD->clientOffset.x;
2892                 *yoff = -(pCD->clientOffset.x - (2 * borderWidth));
2893                 break;
2894             }
2895
2896             case WestGravity:
2897             {
2898                 *xoff = pCD->clientOffset.x;
2899                 *yoff = borderWidth +
2900                                 (pCD->clientOffset.y - pCD->clientOffset.x)/2;
2901                 break;
2902             }
2903
2904             case CenterGravity:
2905             {
2906                 *xoff = 0;
2907                 *yoff = 0;
2908                 break;
2909             }
2910         }
2911     }
2912 } /* END OF FUNCTION CalculateGravityOffset */
2913
2914
2915 \f
2916 /*************************************<->*************************************
2917  *
2918  *  InitClientPlacement (pCD, manageFlags)
2919  *
2920  *
2921  *  Description:
2922  *  -----------
2923  *  This function sets up the initial client window placement (for both
2924  *  the normal and maximized state).
2925  *
2926  *
2927  *  Inputs:
2928  *  ------
2929  *  pCD = pointer to client data (client window configuration fields)
2930  *
2931  *  manageFlags = flags that indicate wm state information (e.g. whether
2932  *                the window manager is starting up or restarting)
2933  *
2934  * 
2935  *  Outputs:
2936  *  -------
2937  *  Return = True if position changed by this routine.
2938  *  pCD = changes to the client window configuration fields
2939  * 
2940  *************************************<->***********************************/
2941
2942 Boolean 
2943 InitClientPlacement (ClientData *pCD, long manageFlags)
2944 {
2945     Boolean interactivelyPlaced = False;
2946     Boolean autoPlaced = False;
2947     Boolean rval = False;
2948     int xoff, yoff;
2949     int origX, origY, origWidth, origHeight;
2950 #ifdef WSM
2951     int iwsc;
2952 #endif /* WSM */
2953
2954
2955     /*
2956      * Save initial client values
2957      */
2958     origX = pCD->clientX;
2959     origY = pCD->clientY;
2960     origWidth = pCD->clientWidth;
2961     origHeight = pCD->clientHeight;
2962
2963     /*
2964      * Do interactive placement if...
2965      *     + the resource is turned on 
2966      *     + the window's coming up on the active screen
2967      *
2968      * Don't do it if...
2969      *     + position specified in DB or by Session Manager
2970      *     + the user has specified a position
2971      *     + the window is coming up iconic 
2972      *     + the window is transient
2973      *     + we're system modal
2974      */
2975
2976     if (wmGD.interactivePlacement && 
2977         (!(pCD->clientFlags & (SM_X | SM_Y))) &&
2978         !(pCD->sizeFlags & US_POSITION) &&
2979         (pCD->clientState != MINIMIZED_STATE) &&
2980         (manageFlags == MANAGEW_NORMAL) &&
2981         !(pCD->clientFlags & CLIENT_TRANSIENT) &&
2982         (pCD->inputMode != MWM_INPUT_SYSTEM_MODAL) &&
2983 #ifdef WSM
2984         (ClientInWorkspace(PSD_FOR_CLIENT(pCD)->pActiveWS, pCD)))
2985 #else /* WSM */
2986         (PSD_FOR_CLIENT(pCD) == ACTIVE_PSD))
2987 #endif /* WSM */
2988     {
2989         /*
2990          * Interactively place the window on the screen.
2991          */
2992         interactivelyPlaced = True;
2993         PlaceWindowInteractively (pCD);
2994     }
2995
2996
2997     /*
2998      * Check out the configuration values to insure that they are within
2999      * the constraints.
3000      */
3001
3002     FixWindowConfiguration (pCD, (unsigned int *) &(pCD->clientWidth), 
3003                                  (unsigned int *) &(pCD->clientHeight),
3004                                  (unsigned int) (pCD->widthInc), 
3005                                  (unsigned int) (pCD->heightInc));
3006
3007     /*
3008      * Do autoplacement of the client window if appropriate.
3009      */
3010
3011     if ((manageFlags == MANAGEW_NORMAL) && !interactivelyPlaced &&
3012         (!(pCD->clientFlags & (SM_X | SM_Y))) &&
3013         !(pCD->sizeFlags & US_POSITION) &&
3014         !(pCD->clientFlags & CLIENT_TRANSIENT) &&
3015         (pCD->inputMode != MWM_INPUT_SYSTEM_MODAL) && wmGD.clientAutoPlace)
3016     {
3017         /*
3018          * if (PPosition is on or nonzero), then use current value for
3019          * clientX and clientY which was set to windowAttributes.x,y
3020          * by ProcessWmNormalHints(), else autoplace client.
3021          */
3022
3023         if ((pCD->sizeFlags & P_POSITION) &&
3024             ((pCD->usePPosition == USE_PPOSITION_ON) ||
3025              ((pCD->usePPosition == USE_PPOSITION_NONZERO) &&
3026               ((pCD->clientX != 0) || (pCD->clientY != 0)))))
3027         {
3028             /* do nothing */
3029         }
3030         else
3031         {
3032             FindClientPlacement (pCD);
3033             autoPlaced = True;
3034         }
3035     }
3036
3037     /*
3038      * Do PositionIsFrame processing:
3039      * Use window gravity to allow the user to specify the window 
3040      * position on the screen  without having to know the dimensions 
3041      * of the decoration that mwm is adding.
3042      */
3043
3044     if ((wmGD.positionIsFrame) &&
3045         !interactivelyPlaced && !autoPlaced)
3046     {
3047         CalculateGravityOffset (pCD, &xoff, &yoff);
3048         if (!(pCD->clientFlags & SM_X))
3049             pCD->clientX += xoff;
3050         if (!(pCD->clientFlags & SM_Y))
3051             pCD->clientY += yoff;
3052     }
3053
3054
3055     /*
3056      * Do PositionOnScreen processing:
3057      */
3058
3059
3060 #ifdef WSM
3061 #ifdef PANELIST
3062     if (pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUBPANEL)
3063     {
3064         if (pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUB_RESTORED)
3065         {
3066             SetFrameInfo (pCD);   
3067         }
3068         else
3069         {
3070             AdjustSlideOutGeometry (pCD);
3071         }
3072     }
3073     else
3074 #endif /* PANELIST */
3075 #endif /* WSM */
3076     if (((wmGD.positionOnScreen) && !interactivelyPlaced) &&
3077         (!(pCD->clientFlags & (SM_X | SM_Y))))
3078     {
3079         PlaceFrameOnScreen (pCD, &pCD->clientX, &pCD->clientY,
3080             pCD->clientWidth, pCD->clientHeight);
3081     }
3082
3083
3084     /*
3085      * Position the maximized frame:
3086      */
3087
3088     pCD->maxX = pCD->clientX;
3089     pCD->maxY = pCD->clientY;
3090     PlaceFrameOnScreen (pCD, &pCD->maxX, &pCD->maxY, pCD->maxWidth,
3091         pCD->maxHeight);
3092
3093
3094     if (!wmGD.iconAutoPlace)
3095     {
3096 #ifdef WSM
3097         if (!(pCD->iconFlags & ICON_HINTS_POSITION))
3098         {
3099             for (iwsc=0; iwsc<pCD->numInhabited; iwsc++)
3100             {
3101                 pCD->pWsList[iwsc].iconX = pCD->clientX;
3102                 pCD->pWsList[iwsc].iconY = pCD->clientY;
3103                 PlaceIconOnScreen (pCD, &pCD->pWsList[iwsc].iconX, 
3104                                         &pCD->pWsList[iwsc].iconY);
3105             }
3106         }
3107 #else /* WSM */
3108         if (!(pCD->iconFlags & ICON_HINTS_POSITION))
3109         {
3110             pCD->iconX = pCD->clientX;
3111             pCD->iconY = pCD->clientY;
3112         }
3113         PlaceIconOnScreen (pCD, &pCD->iconX, &pCD->iconY);
3114 #endif /* WSM */
3115     }
3116
3117     /* 
3118      * if client size or position has been changed by this routine,
3119      * then indicate in return value
3120      */
3121     if ((origX != pCD->clientX) || (origY != pCD->clientY) ||
3122         (origWidth != pCD->clientWidth) || (origHeight != pCD->clientHeight))
3123     {
3124         rval = True;
3125     }
3126
3127     return (rval);
3128
3129 } /* END OF FUNCTION InitClientPlacement */
3130
3131 #ifdef PANELIST
3132 \f
3133 /******************************<->*************************************
3134  *
3135  * void AdjustSlideOutGeometry (pCD)
3136  *
3137  *  Description:
3138  *  -----------
3139  *  Adjusts the geometry of the slide out panel
3140  *
3141  *  Inputs:
3142  *  ------
3143  *  pCD = pointer to a client data of slide out
3144  * 
3145  *  Outputs:
3146  *  -------
3147  *
3148  *  Comments:
3149  *  --------
3150  *  Subpanel is to appear above or below the front panel, centered
3151  *  on the vertical axis of the spawning control.
3152  ******************************<->***********************************/
3153 static void 
3154 AdjustSlideOutGeometry ( ClientData *pCD)
3155 {
3156     ClientData  *pCD_FP = NULL;
3157     WmPanelistObject  pPanelist;
3158
3159     pCD->slideDirection = SLIDE_NORTH;  /* assume up for now */
3160     pPanelist = (WmPanelistObject) pCD->pSD->wPanelist;
3161     (void) XFindContext (DISPLAY, XtWindow(O_Shell(pPanelist)),
3162                   wmGD.windowContextType, (caddr_t *)&pCD_FP);
3163
3164     if (pCD_FP)
3165     {
3166         /*
3167         * Adjust slide up position if coming from front
3168         * panel. 
3169         * (Assumes no nesting of panels !!!)
3170         * (Assumes horizontal oriented front panel!!!)
3171         */
3172         if (pCD->transientLeader == pCD_FP)
3173         {
3174             /* 
3175              * Subpanel should be sort-of centered already,
3176              * adjust by width of window manager frame.
3177              */
3178             pCD->clientX -= pCD->frameInfo.lowerBorderWidth;
3179
3180             /* 
3181              * Adjust to slide up above front panel.
3182              */
3183             pCD->clientY = pCD_FP->frameInfo.y - 
3184                          pCD->frameInfo.lowerBorderWidth -
3185                          pCD->clientHeight + 3;
3186
3187 /*  RICK -- added the (+ 3)  */
3188
3189
3190             if (pCD->clientY < 0)
3191             {
3192                 /*
3193                  * Adjust to slide down below front panel.
3194                  */
3195                 pCD->clientY = pCD_FP->frameInfo.y +
3196                              pCD_FP->frameInfo.height +
3197                              pCD->frameInfo.titleBarHeight +
3198                              pCD->frameInfo.upperBorderWidth - 3;
3199                 pCD->slideDirection = SLIDE_SOUTH;
3200 /*  RICK -- added the (- 3)  */
3201             }
3202
3203             if ((pCD->clientY + pCD->clientHeight +
3204                    pCD->frameInfo.lowerBorderWidth) > 
3205                 XDisplayHeight (DISPLAY, pCD->pSD->screen))
3206             {
3207                /*
3208                 * If the bottom of the slide-up is off the bottom
3209                 * of the screen, then don't slide, just pop it up.
3210                 */
3211                pCD->slideDirection = SLIDE_NOT;
3212             }
3213
3214             PlaceFrameOnScreen (pCD, &pCD->clientX, &pCD->clientY,
3215                     pCD->clientWidth, pCD->clientHeight);
3216         }
3217         SetFrameInfo (pCD);
3218     }
3219 }
3220 #endif  /* PANELIST */
3221
3222 \f
3223 /*************************************<->*************************************
3224  *
3225  *  PlaceFrameOnScreen (pCD, pX, pY, w, h)
3226  *
3227  *
3228  *  Description:
3229  *  -----------
3230  *  This function is used to nudge a client window so that it is totally
3231  *  onscreen if possible.  At least the top left corner will be onscreen.
3232  *
3233  *
3234  *  Inputs:
3235  *  ------
3236  *  pCD         - pointer to client data
3237  *  pX          - pointer to x-coord
3238  *  pY          - pointer to y-coord
3239  *  w           - width of window
3240  *  h           - height of window
3241  *
3242  * 
3243  *  Outputs:
3244  *  -------
3245  *  *pX         - new x-coord
3246  *  *pY         - new y-coord
3247  *
3248  *
3249  *  Comments:
3250  *  --------
3251  * 
3252  *************************************<->***********************************/
3253
3254 void 
3255 PlaceFrameOnScreen (ClientData *pCD, int *pX, int *pY, int w, int h)
3256 {
3257     int clientOffsetX;
3258     int clientOffsetY;
3259     int frameX;
3260     int frameY;
3261     int frameWidth;
3262     int frameHeight;
3263     int screenHeight;
3264     int screenWidth;
3265
3266
3267     clientOffsetX = pCD->clientOffset.x;
3268     clientOffsetY = pCD->clientOffset.y;
3269     frameX = *pX - clientOffsetX;
3270     frameY = *pY - clientOffsetY;
3271     frameWidth = w + (2 * clientOffsetX);
3272     frameHeight = h + clientOffsetX + clientOffsetY;
3273     screenWidth = DisplayWidth (DISPLAY, SCREEN_FOR_CLIENT(pCD));
3274     screenHeight = DisplayHeight (DISPLAY, SCREEN_FOR_CLIENT(pCD));
3275
3276     if ((frameX + frameWidth) > screenWidth)
3277     {
3278         frameX -= (frameX + frameWidth) - screenWidth;
3279     }
3280     if ((frameY + frameHeight) > screenHeight)
3281     {
3282         frameY -= (frameY + frameHeight) - screenHeight;
3283     }
3284     if (frameX < 0)
3285     {
3286         frameX = 0;
3287     }
3288     if (frameY < 0)
3289     {
3290         frameY = 0;
3291     }
3292
3293     *pX = frameX + clientOffsetX;
3294     *pY = frameY + clientOffsetY;
3295
3296 } /* END OF FUNCTION PlaceFrameOnScreen */
3297
3298
3299 \f
3300 /*************************************<->*************************************
3301  *
3302  *  PlaceIconOnScreen (pCD, pX, pY)
3303  *
3304  *
3305  *  Description:
3306  *  -----------
3307  *  This function positions an icon on-screen.
3308  *
3309  *
3310  *  Inputs:
3311  *  ------
3312  *  pCD         - pointer to client data
3313  *  pX          - pointer to x-coord
3314  *  pY          - pointer to y-coord
3315  * 
3316  *  Outputs:
3317  *  -------
3318  *  *pX         - new x-coord
3319  *  *pY         - new y-coord
3320  *
3321  *  Comments:
3322  *  --------
3323  * 
3324  *************************************<->***********************************/
3325
3326 void 
3327 PlaceIconOnScreen (ClientData *pCD, int *pX, int *pY)
3328 {
3329     int screenWidth;
3330     int screenHeight;
3331     int iconX;
3332     int iconY;
3333
3334
3335     screenWidth = DisplayWidth (DISPLAY, SCREEN_FOR_CLIENT(pCD));
3336     screenHeight = DisplayHeight (DISPLAY, SCREEN_FOR_CLIENT(pCD));
3337     iconX = *pX;
3338     iconY = *pY;
3339
3340     if ((iconX + ICON_WIDTH(pCD)) > screenWidth)
3341     {
3342         iconX = screenWidth - ICON_WIDTH(pCD);
3343     }
3344     else if (iconX < 0)
3345     {
3346         iconX = 0;
3347     }
3348
3349     if ((iconY + ICON_HEIGHT(pCD)) > screenHeight)
3350     {
3351         iconY = screenHeight - ICON_HEIGHT(pCD);
3352     }
3353     else if (iconY < 0)
3354     {
3355         iconY = 0;
3356     }
3357
3358     *pX = iconX;
3359     *pY = iconY;
3360
3361
3362 } /* END OF FUNCTION PlaceIconOnScreen */
3363
3364
3365 \f
3366 /*************************************<->*************************************
3367  *
3368  *  FixWindowConfiguration (pCD, pWidth, pHeight, widthInc, heightInc)
3369  *
3370  *
3371  *  Description:
3372  *  -----------
3373  *  This function adjusts the configuration for the client window so that
3374  *  it is in line with the client window's sizing constraints.
3375  *
3376  *
3377  *  Inputs:
3378  *  ------
3379  *  pCD = a pointer to the client window data
3380  *  pWidth, pHeight = pointers to the window configuration values
3381  *  widthInc, heightInc = window size increment values
3382  *
3383  * 
3384  *  Outputs:
3385  *  -------
3386  *  pWidth, pHeight = adjusted configuration values are returned here
3387  *
3388  * 
3389  *************************************<->***********************************/
3390
3391 void 
3392 FixWindowConfiguration (ClientData *pCD, unsigned int *pWidth, unsigned int *pHeight, unsigned int widthInc, unsigned int heightInc)
3393 {
3394     register int  delta;
3395
3396     /*
3397      * Make sure we're on width/height increment boundaries.
3398      */
3399
3400     if ((int) *pWidth < pCD->minWidth)
3401     {
3402         *pWidth = pCD->minWidth;
3403     }
3404     else if ((delta = (*pWidth - pCD->baseWidth) % pCD->widthInc))
3405     {
3406         *pWidth -= delta;
3407     }
3408
3409     if ((int) *pHeight < pCD->minHeight)
3410     {
3411         *pHeight = pCD->minHeight;
3412     }
3413     else if ((delta = (*pHeight - pCD->baseHeight) % pCD->heightInc))
3414     {
3415         *pHeight -= delta;
3416     }
3417
3418     /*
3419      * Constrain size within bounds.
3420      */
3421
3422     FixWindowSize (pCD, pWidth, pHeight, widthInc, heightInc);
3423
3424 } /* END OF FUNCTION FixWindowConfiguration */
3425
3426
3427 \f
3428 /*************************************<->*************************************
3429  *
3430  *  FixWindowSize (pCD, pWidth, pHeight, widthInc, heightInc)
3431  *
3432  *
3433  *  Description:
3434  *  -----------
3435  *  This function adjusts the client window width and height so that
3436  *  it is in line with its sizing constraints.
3437  *
3438  *
3439  *  Inputs:
3440  *  ------
3441  *  pCD = a pointer to the client window data
3442  *  pWidth, pHeight = pointers to the window size values
3443  *  widthInc, heightInc = window size increment values
3444  *  pWS->limitResize 
3445  *
3446  * 
3447  *  Outputs:
3448  *  -------
3449  *  pWidth, pHeight = adjusted size values.
3450  *
3451  * 
3452  *************************************<->***********************************/
3453
3454 void 
3455 FixWindowSize (ClientData *pCD, unsigned int *pWidth, unsigned int *pHeight, unsigned int widthInc, unsigned int heightInc)
3456 {
3457     register int  deltaW;
3458     register int  deltaH;
3459     WmScreenData *pSD = pCD->pSD;
3460
3461     /*
3462      * All occurrences of maxHeight and maxWidth in this routing has been
3463      * hacked to use maxHeightLimit and maxWidthLimit as the real max when
3464      * maximumClientSize is set to 'horizontal' or 'vertical', since
3465      * pCD->maxHeight and pCD->maxWidth is fiddle to on reconfiguration.
3466      */
3467
3468     if ((int) *pWidth < pCD->minWidth)
3469     {
3470         *pWidth = pCD->minWidth;
3471     }
3472     else if (*pWidth > pCD->maxWidthLimit &&
3473              pSD->limitResize && 
3474              !(pCD->clientFlags & CLIENT_WM_CLIENTS))
3475     {
3476         *pWidth = pCD->maxWidthLimit;
3477     }
3478
3479     if ((int) *pHeight < pCD->minHeight)
3480     {
3481         *pHeight = pCD->minHeight;
3482     }
3483     else if (*pHeight > pCD->maxHeightLimit &&
3484              pSD->limitResize && 
3485              !(pCD->clientFlags & CLIENT_WM_CLIENTS))
3486     {
3487         *pHeight = pCD->maxHeightLimit;
3488     }
3489
3490     if ((pCD->sizeFlags & P_ASPECT) &&
3491         *pWidth * pCD->maxAspect.y > *pHeight * pCD->maxAspect.x)
3492     /* 
3493      * Client aspect is too big.
3494      * Candidate height >= client height:
3495      *   Try to increase the client's height without violating bounds.
3496      *   If this fails, use maximum height and try to decrease its width.
3497      * Candidate height < client height:
3498      *   Try to decrease the client's width without violating bounds.
3499      *   If this fails, use minimum width and try to increase its height.
3500      */
3501     {
3502         if ((*pHeight >= pCD->clientHeight) ||
3503             (*pWidth > pCD->clientWidth))
3504         /* 
3505          * Candidate height >= client height:
3506          *   Try to increase the client's height without violating bounds.
3507          *   If this fails, use maximum height and try to decrease its width.
3508          */
3509         {
3510             deltaH = makemult (*pWidth * pCD->maxAspect.y / pCD->maxAspect.x -
3511                                *pHeight, heightInc);
3512             if (*pHeight + deltaH <= pCD->maxHeightLimit ||
3513                 !pSD->limitResize ||
3514                 pCD->clientFlags & CLIENT_WM_CLIENTS)
3515             {
3516                 *pHeight += deltaH;
3517             }
3518             else 
3519             {
3520                 *pHeight = pCD->maxHeightLimit;
3521                 deltaW = makemult (*pWidth - *pHeight * pCD->maxAspect.x / 
3522                                    pCD->maxAspect.y, widthInc);
3523                 if (*pWidth - deltaW >= pCD->minWidth)
3524                 {
3525                     *pWidth -= deltaW;
3526                 }  
3527                 else
3528                 {
3529                     *pWidth = pCD->minWidth;
3530                 }
3531             }
3532         }
3533         else
3534         /*
3535          * Candidate height < client height and candidate width <= client width.
3536          *   Try to decrease the client's width without violating bounds.
3537          *   If this fails, use minimum width and try to increase its height.
3538          */
3539         {
3540             deltaW = makemult (*pWidth - *pHeight * pCD->maxAspect.x / 
3541                                pCD->maxAspect.y, widthInc);
3542
3543             if (*pWidth - deltaW >= pCD->minWidth)
3544             {
3545                 *pWidth -= deltaW;
3546             }  
3547             else
3548             {
3549                 *pWidth = pCD->minWidth;
3550                 deltaH = makemult (*pWidth * pCD->maxAspect.y / 
3551                                    pCD->maxAspect.x - *pHeight, heightInc);
3552                 if (*pHeight + deltaH <= pCD->maxHeightLimit ||
3553                      !pSD->limitResize ||
3554                      pCD->clientFlags & CLIENT_WM_CLIENTS)
3555                 {
3556                     *pHeight += deltaH;
3557                 }
3558                 else
3559                 {
3560                     *pHeight = pCD->maxHeightLimit;
3561                 }
3562             }
3563         }
3564     }
3565
3566     else if ((pCD->sizeFlags & P_ASPECT) &&
3567              *pHeight * pCD->minAspect.x > *pWidth * pCD->minAspect.y)
3568     /* 
3569      * Client aspect is too small.
3570      * Candidate width >= client width:
3571      *   Try to increase the client's width without violating bounds.
3572      *   If this fails, use maximum width and try to decrease its height.
3573      * Candidate width < client width:
3574      *   Try to decrease the client's height without violating bounds.
3575      *   If this fails, use minimum height and try to increase its width.
3576      */
3577     {
3578         if ((*pWidth >= pCD->clientWidth) ||
3579             (*pHeight > pCD->clientHeight))
3580         /*
3581          * Candidate width >= client width:
3582          *   Try to increase the client's width without violating bounds.
3583          *   If this fails, use maximum width and try to decrease its height.
3584          */
3585         {
3586             deltaW = makemult (*pHeight * pCD->minAspect.x / pCD->minAspect.y -
3587                                *pWidth, widthInc);
3588             if (*pWidth + deltaW <= pCD->maxWidthLimit ||
3589                 !pSD->limitResize ||
3590                 pCD->clientFlags & CLIENT_WM_CLIENTS)
3591             {
3592                 *pWidth += deltaW;
3593             }
3594             else
3595             {
3596                 *pWidth = pCD->maxWidthLimit;
3597                 deltaH = makemult (*pHeight - *pWidth * pCD->minAspect.y / 
3598                                    pCD->minAspect.x, heightInc); 
3599                 if (*pHeight - deltaH >= pCD->minHeight)
3600                 {
3601                     *pHeight -= deltaH;
3602                 }
3603                 else
3604                 {
3605                     *pHeight = pCD->minHeight;
3606                 }
3607             }
3608         }
3609         else
3610         /*
3611          * Candidate width < client width and Candidate height <= client height:
3612          *   Try to decrease the client's height without violating bounds.
3613          *   If this fails, use minimum height and try to increase its width.
3614          */
3615         {
3616             deltaH = makemult (*pHeight - *pWidth * pCD->minAspect.y / 
3617                                pCD->minAspect.x, heightInc); 
3618             if (*pHeight - deltaH >= pCD->minHeight)
3619             {
3620                 *pHeight -= deltaH;
3621             }
3622             else
3623             {
3624                 *pHeight = pCD->minHeight;
3625                 deltaW = makemult (*pHeight * pCD->minAspect.x / 
3626                                    pCD->minAspect.y - *pWidth, widthInc);
3627                 if (*pWidth + deltaW <= pCD->maxWidthLimit ||
3628                      !pSD->limitResize ||
3629                      pCD->clientFlags & CLIENT_WM_CLIENTS)
3630                 {
3631                     *pWidth += deltaW;
3632                 }
3633                 else
3634                 {
3635                     *pWidth = pCD->maxWidthLimit;
3636                 }
3637             }
3638         }
3639     }
3640 } /* END OF FUNCTION FixWindowSize */
3641
3642
3643 \f
3644 /*************************************<->*************************************
3645  *
3646  *  FindClientPlacement (pCD)
3647  *
3648  *
3649  *  Description:
3650  *  -----------
3651  *  This function finds a position for the client window on the screen.
3652  *  Windows positions are stepped down the screen.  An attempt is made
3653  *  to keep windows from being clipped by the edge of the screen.
3654  *
3655  *
3656  *  Inputs:
3657  *  ------
3658  *  pCD = pointer to client data (client window configuration fields)
3659  *
3660  * 
3661  *  Outputs:
3662  *  -------
3663  *  pCD = changes to the client window configuration fields
3664  * 
3665  *************************************<->***********************************/
3666
3667 void 
3668 FindClientPlacement (ClientData *pCD)
3669 {
3670     static Boolean clientPlacementInitialized = False;
3671     static int clientPlacementOffset;
3672     static int clientPlacementX;
3673     static int clientPlacementY;
3674     static int clientPlacementOrigin;
3675     static int clientPlacementXOrigin;
3676
3677     Boolean placed = False;
3678     int frameWidth;
3679     int frameHeight;
3680     int screenX;
3681     int screenY;
3682     int screenWidth;
3683     int screenHeight;
3684     int borderWidth = 0;
3685     Boolean offScreenX;
3686     Boolean offScreenY;
3687     WmHeadInfo_t *WmHI = NULL;
3688
3689
3690     if (!clientPlacementInitialized)
3691     {
3692         if (pCD->clientDecoration & WM_DECOR_RESIZEH)
3693         {
3694             borderWidth = ((RESIZE_BORDER_WIDTH(pCD) > FRAME_BORDER_WIDTH(pCD))
3695                           ? RESIZE_BORDER_WIDTH(pCD) : FRAME_BORDER_WIDTH(pCD));
3696         }
3697         else
3698         {
3699             borderWidth = pCD->matteWidth;
3700         }
3701         clientPlacementOffset = TitleTextHeight(pCD) + borderWidth;
3702         clientPlacementOrigin = clientPlacementOffset;
3703         clientPlacementX = clientPlacementOrigin;
3704         clientPlacementY = clientPlacementOrigin;
3705         clientPlacementXOrigin = clientPlacementX;
3706         clientPlacementInitialized = True;
3707     }
3708
3709     frameWidth = pCD->clientWidth + (2 * pCD->clientOffset.x);
3710     frameHeight = pCD->clientHeight + pCD->clientOffset.y + pCD->clientOffset.x;
3711
3712     if (WmHI = GetHeadInfo(wmGD.keyboardFocus)) {
3713         /* Use Head metrics for placeable area */
3714         screenX = WmHI->x_org;
3715         screenY = WmHI->y_org;
3716         screenWidth = WmHI->width;
3717         screenHeight = WmHI->height;
3718
3719         free(WmHI);
3720     } else {
3721         /* Use X Screen metrics for placeable area */
3722         screenX = 0;
3723         screenY = 0;
3724         screenWidth = DisplayWidth (DISPLAY, SCREEN_FOR_CLIENT(pCD));
3725         screenHeight = DisplayHeight (DISPLAY, SCREEN_FOR_CLIENT(pCD));
3726     }
3727
3728     while (!placed)
3729     {
3730         if ((clientPlacementX - pCD->clientOffset.x + frameWidth)
3731             > screenWidth)
3732         {
3733             offScreenX = True;
3734         }
3735         else
3736         {
3737             offScreenX = False;
3738         }
3739         if ((clientPlacementY - pCD->clientOffset.y + frameHeight)
3740             > screenHeight)
3741         {
3742             offScreenY = True;
3743         }
3744         else
3745         {
3746             offScreenY = False;
3747         }
3748
3749         if (offScreenX || offScreenY)
3750         {
3751             if (clientPlacementX == clientPlacementOrigin)
3752             {
3753                 /*
3754                  * Placement location is already as far to the NW as it is
3755                  * going to go.
3756                  */
3757
3758                 placed = True;
3759             }
3760             else if (clientPlacementY == clientPlacementOrigin)
3761             {
3762                 /*
3763                  * Placement location is as far to the N as it is going to go.
3764                  * Use the current placement if the window is not off the
3765                  * screen in the x coordinate otherwise reset the placement
3766                  * back to the NW origin.
3767                  */
3768
3769                 if (offScreenX)
3770                 {
3771                     clientPlacementXOrigin = clientPlacementOrigin;
3772                     clientPlacementX = clientPlacementXOrigin;
3773                 }
3774                 placed = True;
3775             }
3776             else
3777             {
3778                 /*
3779                  * If window is off the right edge of screen, just move
3780                  * window in the X direction onto screen.  Process similarly
3781                  * for windows that are off the bottom of the screen.
3782                  */
3783
3784                 if (offScreenX && !offScreenY)
3785                 {
3786                     clientPlacementX = clientPlacementOrigin;
3787                 }
3788                 else if (offScreenY && !offScreenX)
3789                 {
3790                     clientPlacementY = clientPlacementOrigin;
3791                 }
3792                 else
3793                 {
3794
3795                 /*
3796                  * Reset the placement location back to the NW of the
3797                  * current location.  Go as far N as possible and step the
3798                  * x coordinate to the E.
3799                  */
3800
3801                     clientPlacementXOrigin += clientPlacementOffset;
3802                     clientPlacementX = clientPlacementXOrigin;
3803                     clientPlacementY = clientPlacementOrigin;
3804                 }
3805             }
3806         }
3807         else
3808         {
3809             placed = True;
3810         }
3811     }
3812
3813     /*
3814      * The window has been placed, now update the placement information.
3815      */
3816
3817     pCD->clientX = clientPlacementX + screenX;
3818     pCD->clientY = clientPlacementY + screenY;
3819     clientPlacementX += clientPlacementOffset;
3820
3821     if (clientPlacementX >= screenWidth)
3822     {
3823         clientPlacementXOrigin = clientPlacementOrigin;
3824         clientPlacementX = clientPlacementXOrigin;
3825     }
3826     clientPlacementY += clientPlacementOffset;
3827
3828     /*
3829      * Reset Y position to top of screen so that windows start new column of
3830      * placement that is offset from the previous column.  Previously, the new
3831      * column was place right over the old column, obscuring it.
3832      * NOTE: column == diagonal
3833      */
3834
3835     if (clientPlacementY >= (screenHeight / 3))
3836     {
3837         clientPlacementY = clientPlacementOrigin;
3838     }
3839
3840
3841 } /* END OF FUNCTION FindClientPlacement */
3842
3843
3844 \f
3845 /*************************************<->*************************************
3846  *
3847  *  WmGetWindowAttributes (window)
3848  *
3849  *
3850  *  Description:
3851  *  -----------
3852  *  This function gets window attributes if necessary and saves them in the
3853  *  global window attribute cache.  If the window attributes are already
3854  *  there then no X call is made.
3855  *
3856  *
3857  *  Inputs:
3858  *  ------
3859  *  window = get attributes for window with this id
3860  *
3861  * 
3862  *  Outputs:
3863  *  -------
3864  *  wmGD.attributesWindow = set to window that matches windowAttributes
3865  *
3866  *  wmGD.windowAttributes = XWindowAttributes of window
3867  *
3868  *
3869  *  Comments:
3870  *  --------
3871  *  The attributes in the global cache are (known) current only for a
3872  *  single pass through the wm event processing loop.  They (should be)
3873  *  regularly cleared.
3874  * 
3875  *************************************<->***********************************/
3876
3877 Boolean 
3878 WmGetWindowAttributes (Window window)
3879 {
3880     if (wmGD.attributesWindow != window)
3881     {
3882         if (!XGetWindowAttributes (DISPLAY, window, &wmGD.windowAttributes))
3883         {
3884             /*
3885              * Cannot get window attributes.
3886              */
3887
3888             wmGD.attributesWindow = (Window)0L;
3889             return (False);
3890         }
3891         wmGD.attributesWindow = window;
3892     }
3893
3894     return (True);
3895
3896 } /* END OF FUNCTION WmGetWindowAttributes */
3897
3898
3899 \f
3900 /*************************************<->*************************************
3901  *
3902  *  SetupClientIconWindow (pCD, window)
3903  *
3904  *
3905  *  Description:
3906  *  -----------
3907  *  This function prepares a client supplied icon window for insertion into
3908  *  a window manager icon frame.
3909  *
3910  *
3911  *  Inputs:
3912  *  ------
3913  *  pCD = pointer to client data
3914  *
3915  *  window = client supplied icon window
3916  *
3917  * 
3918  *  Outputs:
3919  *  -------
3920  *  pCD = (iconWindow)
3921  *
3922  *  Return = True if the icon window can be used
3923  *
3924  *************************************<->***********************************/
3925
3926 Boolean 
3927 SetupClientIconWindow (ClientData *pCD, Window window)
3928 {
3929     ClientData *pcd;
3930
3931
3932     /*
3933      * Check to see if the icon window can be used (i.e there is no conflict
3934      * of interest.
3935      */
3936
3937     if (!XFindContext (DISPLAY, window, wmGD.windowContextType,
3938              (caddr_t *)&pcd))
3939     {
3940         if (window == pCD->client)
3941         {
3942             /*
3943              * The proposed icon window is the same as the client!
3944              */
3945
3946             return (False);
3947         }
3948
3949         /*
3950          * The proposed icon window is already being managed. 
3951          * Assume that we managed it by mistake. Unmanage the 
3952          * window and use it as the icon window for this client.
3953          */
3954
3955          UnManageWindow (pcd);
3956     }
3957
3958     /* update client data */
3959     pCD->iconWindow = window;
3960
3961     /* put in window manager's save set */
3962     XChangeSaveSet (DISPLAY, pCD->iconWindow, SetModeInsert);
3963     pCD->clientFlags  |=  ICON_IN_SAVE_SET;
3964
3965     return (True);
3966
3967 } /* END OF FUNCTION SetupClientIconWindow */
3968
3969
3970 \f
3971 /*************************************<->*************************************
3972  *
3973  *  ProcessMwmHints (pCD)
3974  *
3975  *
3976  *  Description:
3977  *  -----------
3978  *  Process the _MWM_HINTS property on the window (if any).  Setup the
3979  *  applicable function and decoration masks.
3980  *
3981  *
3982  *  Inputs:
3983  *  ------
3984  *  pCD = pointer to client data
3985  *
3986  * 
3987  *  Outputs:
3988  *  -------
3989  *  pCD = may be changed.
3990  *
3991  *************************************<->***********************************/
3992
3993 void 
3994 ProcessMwmHints (ClientData *pCD)
3995 {
3996     PropMwmHints *pHints;
3997
3998
3999     /*
4000      * Fix the client functions and decorations fields if they have
4001      * default resource values.
4002      */
4003
4004     if (pCD->clientFunctions & WM_FUNC_DEFAULT)
4005     {
4006         if (pCD->clientFlags & CLIENT_TRANSIENT)
4007         {
4008             pCD->clientFunctions = TRANSIENT_FUNCTIONS(pCD);
4009         }
4010         else
4011         {
4012             pCD->clientFunctions = WM_FUNC_ALL;
4013         }
4014 #ifdef PANELIST
4015         if (pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUBPANEL)
4016         {
4017             pCD->clientFunctions &= WM_FUNC_SUBPANEL_DEFAULT;   
4018             pCD->dtwmFunctions &= ~DtWM_FUNCTION_OCCUPY_WS;
4019         }
4020         else if (pCD->dtwmBehaviors & DtWM_BEHAVIOR_PANEL)
4021         {
4022             pCD->clientFunctions &= WM_FUNC_PANEL_DEFAULT;   
4023             pCD->dtwmFunctions &= ~DtWM_FUNCTION_OCCUPY_WS;
4024         }
4025 #endif /* PANELIST */
4026     }
4027
4028     if (pCD->clientDecoration & WM_DECOR_DEFAULT)
4029     {
4030         if (pCD->clientFlags & CLIENT_TRANSIENT)
4031         {
4032             pCD->clientDecoration = TRANSIENT_DECORATION(pCD);
4033         }
4034         else
4035         {
4036             pCD->clientDecoration = WM_DECOR_ALL;
4037         }
4038 #ifdef PANELIST
4039         if (pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUBPANEL)
4040         {
4041             pCD->clientDecoration = pCD->pSD->subpanelDecoration;
4042         }
4043         else if (pCD->dtwmBehaviors & DtWM_BEHAVIOR_PANEL)
4044         {
4045             pCD->clientDecoration &= WM_DECOR_PANEL_DEFAULT;   
4046         }
4047 #endif /* PANELIST */
4048     }
4049
4050
4051     /*
4052      * Retrieve the _MWM_HINTS property if it exists.
4053      */
4054
4055     pCD->inputMode = MWM_INPUT_MODELESS;
4056
4057     if ((pHints = GetMwmHints (pCD)) != NULL)
4058     {
4059         if (pHints->flags & MWM_HINTS_FUNCTIONS)
4060         {
4061             if (pHints->functions & MWM_FUNC_ALL)
4062             {
4063                 /* client indicating inapplicable functions */
4064                 pCD->clientFunctions &= ~(pHints->functions);
4065             }
4066             else
4067             {
4068                 /* client indicating applicable functions */
4069                 pCD->clientFunctions &= pHints->functions;
4070             }
4071 #if 0
4072             if (!(pCD->clientFlags & GOT_DT_WM_HINTS) &&
4073                 !pHints->functions)
4074             {
4075                 /*
4076                  * !!! Backward compatibility heurisitic !!!
4077                  * 
4078                  * If client doesn't want any functions and
4079                  * no DT_WM_HINTS specified, then remove 
4080                  * workspace functions.
4081                  */
4082                 pCD->dtwmFunctions &= ~DtWM_FUNCTION_OCCUPY_WS;
4083             }
4084 #endif 
4085             /* !!! check for some minimal level of functionality? !!! */
4086         }
4087
4088         if (pHints->flags & MWM_HINTS_DECORATIONS)
4089         {
4090             if (pHints->decorations & MWM_DECOR_ALL)
4091             {
4092                 /* client indicating decorations to be removed */
4093                 pCD->clientDecoration &= ~(pHints->decorations);
4094             }
4095             else
4096             {
4097                 /* client indicating decorations to be added */
4098                 pCD->clientDecoration &= pHints->decorations;
4099             }
4100
4101             /*
4102              * Fix up decoration configuration.
4103              */
4104
4105             if (pCD->clientDecoration &
4106                   (MWM_DECOR_MENU | MWM_DECOR_MINIMIZE | MWM_DECOR_MAXIMIZE))
4107             {
4108                 pCD->clientDecoration |= MWM_DECOR_TITLE;
4109             }
4110             if (pCD->clientDecoration & MWM_DECOR_RESIZEH)
4111             {
4112                 pCD->clientDecoration |= MWM_DECOR_BORDER;
4113             }
4114         }
4115
4116         if (pHints->flags & MWM_HINTS_INPUT_MODE)
4117         {
4118             if ((pHints->inputMode == MWM_INPUT_PRIMARY_APPLICATION_MODAL) ||
4119                 (pHints->inputMode == MWM_INPUT_FULL_APPLICATION_MODAL) ||
4120                 ((pHints->inputMode == MWM_INPUT_SYSTEM_MODAL) &&
4121                  !wmGD.systemModalActive))
4122                 
4123             {
4124                 pCD->inputMode = pHints->inputMode;
4125
4126             }
4127
4128             /*
4129              * Don't allow a system modal window to be a secondary window
4130              * (except with respect to applicable functions and frame
4131              * decorations). Also, don't allow system modal window to
4132              * be minimized.
4133              */
4134
4135             if (pCD->inputMode == MWM_INPUT_SYSTEM_MODAL)
4136             {
4137                 pCD->transientLeader = NULL;
4138                 if (pCD->clientFunctions & MWM_FUNC_MINIMIZE)
4139                 {
4140                     pCD->clientFunctions &= ~(MWM_FUNC_MINIMIZE);
4141                 }
4142             }
4143         }
4144
4145         if (pHints->flags & MWM_HINTS_STATUS)
4146         {
4147             pCD->window_status = pHints->status;
4148         }
4149
4150         XFree ((char*)pHints);
4151     }
4152 #ifndef NO_OL_COMPAT
4153     else
4154     {
4155         ProcessOLDecoration (pCD);
4156     }
4157 #endif /* NO_OL_COMPAT */
4158
4159 #ifdef WSM
4160     /* 
4161      * If primary window can't move between workspaces, then
4162      * secondary window shouldn't either.
4163      */
4164     if (pCD->transientLeader &&
4165         !(pCD->transientLeader->dtwmFunctions & DtWM_FUNCTION_OCCUPY_WS))
4166     {
4167         pCD->dtwmFunctions &= ~DtWM_FUNCTION_OCCUPY_WS;
4168     }
4169 #endif /* WSM */
4170
4171     /*
4172      * Fix up functions based on system modal settings.  System modal
4173      * windows and their descendents cannot be minimized.
4174      */
4175
4176     if (!((FindTransientTreeLeader (pCD))->clientFunctions&MWM_FUNC_MINIMIZE))
4177     {
4178         pCD->clientFunctions &= ~MWM_FUNC_MINIMIZE;
4179     }
4180
4181
4182     /*
4183      * Fix up decoration configuration based on applicable functions.
4184      */
4185
4186     if (!(pCD->clientFunctions & MWM_FUNC_RESIZE))
4187     {
4188         pCD->clientDecoration &= ~MWM_DECOR_RESIZEH;
4189     }
4190
4191     if (!(pCD->clientFunctions & MWM_FUNC_MINIMIZE))
4192     {
4193         pCD->clientDecoration &= ~MWM_DECOR_MINIMIZE;
4194     }
4195
4196     if (!(pCD->clientFunctions & MWM_FUNC_MAXIMIZE))
4197     {
4198         pCD->clientDecoration &= ~MWM_DECOR_MAXIMIZE;
4199     }
4200     
4201     pCD->decor = pCD->clientDecoration;  /* !!! combine decor ... !!! */
4202
4203
4204 } /* END OF ProcessMwmHints */