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