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