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