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