2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
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
24 * (c) Copyright 1989, 1990, 1991, 1992, 1993 OPEN SOFTWARE FOUNDATION, INC.
32 static char rcsid[] = "$TOG: WmWinInfo.c /main/18 1999/02/04 15:17:25 mgreess $"
36 * (c) Copyright 1987, 1988, 1989, 1990 HEWLETT-PACKARD COMPANY */
45 #include "WmResNames.h"
47 #define MWM_NEED_ICONBOX
48 #include "WmIBitmap.h"
56 #define makemult(a, b) ((b==1) ? (a) : (((int)((a) / (b))) * (b)) )
59 * include extern functions
61 #include "WmWinInfo.h"
68 #include "WmIconBox.h"
72 #include "WmProperty.h"
73 #include "WmResource.h"
75 #include "WmWrkspace.h"
77 #include "WmWinList.h"
79 #include "WmPresence.h"
84 static void AdjustSlideOutGeometry (ClientData *pCD);
85 static void FixSubpanelEmbeddedClientGeometry (ClientData *pCD);
88 #ifndef NO_MESSAGE_CATALOG
89 # define LOCALE_MSG GETMESSAGE(70, 7, "[XmbTextPropertyToTextList]:\n Locale (%.100s) not supported. (Check $LANG).")
91 # define LOCALE_MSG "[XmbTextPropertyToTextList]:\n Locale (%.100s) not supported. (Check $LANG)."
98 WmWorkspaceData *pIconBoxInitialWS;
103 /*************************************<->*************************************
105 * GetClientInfo (pSD, clientWindow, manageFlags)
110 * This function is used to initialize client window data based on the
111 * contents of client window properties and the client window configuration.
116 * pSD = pointer to screen data for screen that client lives in
118 * clientWindow = window id for the client window that is to be managed
120 * manageFlags = flags that indicate wm state info
125 * Return = pointer to an initialized client data structure for the
126 * specified client window
128 *************************************<->***********************************/
131 GetClientInfo (WmScreenData *pSD, Window clientWindow, long manageFlags)
135 XSetWindowAttributes sAttributes;
139 * Allocate and initialize a client data structure:
142 if (!(pCD = (ClientData *)XtMalloc (sizeof (ClientData))))
144 /* unable to allocate space */
145 Warning (((char *)GETMESSAGE(70, 1, "Insufficient memory for client data")));
151 * Initialize the data structure:
154 pCD->client = clientWindow;
155 pCD->clientID = ++(pSD->clientCounter);
156 pCD->clientFlags = WM_INITIALIZATION;
159 pCD->pIconBox = NULL;
161 pCD->thisIconBox = NULL;
166 #endif /* PANELIST */
167 pCD->wmUnmapCount = 0;
168 pCD->transientFor = (Window)0L;
169 pCD->transientLeader = NULL;
170 pCD->transientChildren = NULL;
171 pCD->transientSiblings = NULL;
173 pCD->primaryStackPosition = 0;
175 pCD->fullModalCount = 0;
176 pCD->primaryModalCount = 0;
177 pCD->focusPriority = 0;
178 pCD->focusAutoRaiseDisabled = False;
179 pCD->focusAutoRaiseDisablePending = False;
181 pCD->clientClass = NULL;
182 pCD->clientName = NULL;
183 pCD->clientFrameWin = (Window)0L;
185 pCD->iconFrameWin = (Window)0L;
187 pCD->iconWindow = (Window)0L;
188 pCD->iconPixmap = (Pixmap)0L;
190 pCD->iconPlace = NO_ICON_PLACE;
192 pCD->clientProtocols = NULL;
193 pCD->clientProtocolCount = 0;
194 pCD->mwmMessages = NULL;
195 pCD->mwmMessagesCount = 0;
196 pCD->clientCmapCount = 0;
197 pCD->clientCmapIndex = 0;
198 pCD->clientCmapFlagsInitialized = FALSE;
199 pCD->systemMenuSpec = NULL;
201 pCD->putInAll = False;
202 pCD->pWorkspaceHints = NULL;
203 pCD->numInhabited = 0;
205 pCD->dtwmFunctions = DtWM_FUNCTION_OCCUPY_WS;
206 pCD->dtwmBehaviors = 0L;
207 pCD->paInitialProperties = NULL;
208 pCD->numInitialProperties = 0;
211 pCD->decorFlags = 0L;
212 pCD->pTitleGadgets = NULL;
213 pCD->cTitleGadgets = 0;
214 pCD->pResizeGadgets = NULL;
215 pCD->clientTitleWin = (Window)0L;
216 pCD->pclientTopShadows = NULL;
217 pCD->pclientBottomShadows = NULL;
218 pCD->pclientTitleTopShadows = NULL;
219 pCD->pclientTitleBottomShadows = NULL;
220 pCD->pclientMatteTopShadows = NULL;
221 pCD->pclientMatteBottomShadows = NULL;
222 pCD->piconTopShadows = NULL;
223 pCD->piconBottomShadows = NULL;
224 pCD->internalBevel = (wmGD.frameStyle == WmSLAB) ? 0 :
225 FRAME_INTERNAL_SHADOW_WIDTH;
227 pCD->bPseudoTransient = False;
228 #endif /* NO_OL_COMPAT */
230 pCD->maxWidth = pCD->maxWidthLimit = BIGSIZE;
231 pCD->maxHeight = pCD->maxHeightLimit = BIGSIZE;
232 pCD->maxConfig = FALSE;
234 pCD->dataType = CLIENT_DATA_TYPE;
235 pCD->window_status = 0L;
237 pCD->clientEntry.nextSibling = NULL;
238 pCD->clientEntry.prevSibling = NULL;
239 pCD->clientEntry.pCD = NULL;
241 pCD->smClientID = (String)NULL;
244 * Do special processing for client windows that are controlled by
245 * the window manager.
248 if (manageFlags & MANAGEW_WM_CLIENTS)
251 WmWorkspaceData *pWS;
253 if (manageFlags & MANAGEW_ICON_BOX)
255 pWS = pIconBoxInitialWS;
259 pWS = pSD->pActiveWS;
261 return (GetWmClientInfo (pWS, pCD, manageFlags));
263 return (GetWmClientInfo (pSD->pActiveWS, pCD, manageFlags));
269 * Register the client window to facilitate event handling:
272 XSaveContext (DISPLAY, clientWindow, wmGD.windowContextType, (caddr_t)pCD);
276 * Listen for property change events on the window so that we keep
277 * in sync with the hints.
279 sAttributes.event_mask = (PropertyChangeMask | ColormapChangeMask);
280 XChangeWindowAttributes (DISPLAY, pCD->client, CWEventMask,
284 * Get window configuration attributes. WmGetWindowAttributes sets
285 * up the global window attributes cache with the client window
289 if (!WmGetWindowAttributes (clientWindow))
292 * Cannot get window attributes. Do not manage window.
293 * (error message within WmGetWindowAttributes)
296 UnManageWindow (pCD);
299 pCD->xBorderWidth = wmGD.windowAttributes.border_width;
303 * Get the initial list of properties on this window.
304 * Save it to optimize subsequent property fetching.
306 GetInitialPropertyList (pCD);
310 * Retrieve and process WM_CLASS hints client window property info:
313 ProcessWmClass (pCD);
317 * Retrieve and process WM_TRANSIENT_FOR client window property info:
320 ProcessWmTransientFor (pCD);
323 * Get client window resource data (from resources, .mwmrc):
324 * Moved prior to GetClientWorkspaceInfo() because the
325 * ignoreWMSaveHints resource may affect that function.
328 ProcessClientResources (pCD);
331 * Retreive and process SM_CLIENT_ID client window property info
332 * and WMSAVE_HINT client window property info:
333 * must be done prior to calling GetClientWorkspaceInfo().
335 ProcessSmClientID (pCD);
336 ProcessWmSaveHint (pCD);
340 * Set client's workspace information. NOTE: this also may
341 * set the geometry, initial state, etc. For Sm-aware clients,
342 * this info will be in private DB; for older clients, it will
343 * be contained in the screen's pDtSessionItems.
345 if (!GetClientWorkspaceInfo (pCD, manageFlags))
347 XtFree ((char *)pCD);
352 * Restore client's per-workspace icon information.
354 LoadClientIconPositions(pCD);
357 * Retrieve and process _DT_WM_HINTS client window property
358 * (results are used in ProcessMwmHints)
360 ProcessDtWmHints (pCD);
364 * For Sm-aware clients, retrieve geometry and initial state
367 FindClientDBMatch(pCD, (char **)NULL);
372 * Retrieve and process M_CLIENT_DECOR client window property info:
375 ProcessMwmHints (pCD);
379 * Retrieve and process WM_HINTS client window property info:
382 ProcessWmHints (pCD, True /*first time*/);
386 * Set offset from frame of client window
389 SetClientOffset (pCD);
393 * Retrieve and process WM_NORMAL_HINTS client window property info:
397 ProcessWmNormalHints (pCD, True /*first time*/, manageFlags);
401 * Retrieve and process WM_NAME client window property info (this
402 * property contains the window title NOT the window resource name):
405 ProcessWmWindowTitle (pCD, TRUE);
409 * Retrieve and process WM_ICON_NAME client window property info:
412 ProcessWmIconTitle (pCD, TRUE);
416 * Retrieve and process the WM_PROTOCOLS property.
419 ProcessWmProtocols (pCD);
423 * If necessary retrieve and process the _MWM_MESSAGES property.
426 if (pCD->protocolFlags & PROTOCOL_MWM_MESSAGES)
428 ProcessMwmMessages (pCD);
433 * Make or find a system menu for the client.
438 MakeSystemMenu (pCD);
442 pCD->systemMenuSpec = NULL;
447 * Setup the colormap data for the client window. This includes
448 * retrieving and processing client window properties that deal with
449 * subwindow colormaps.
452 InitCColormapData (pCD);
455 /* successful return */
460 } /* END OF FUNCTION GetClientInfo */
464 /*************************************<->*************************************
466 * GetWmClientInfo (pWS, pCD, manageFlags)
471 * This function is used to initialize client window data for a window
472 * that is controlled by the window manager (e.g., the icon box). The
473 * client window may get made in the process.
478 * pWS = pointer to workspace data
480 * pCD = pointer to client window data structure
482 * manageFlags = flags that indicate wm state info
487 * Return = pointer to an initialized client data structure or NULL
488 * if the client data could not be initialized
490 *************************************<->***********************************/
492 GetWmClientInfo (WmWorkspaceData *pWS,
503 * Set up the client class and name for resource retrieval.
504 * Get client specific resource data (from resources, .mwmrc).
507 if (manageFlags & MANAGEW_ICON_BOX)
509 SetIconBoxInfo (pWS, pCD);
511 else if (manageFlags & MANAGEW_CONFIRM_BOX)
513 pCD->clientClass = WmCConfirmbox;
514 pCD->clientName = WmNconfirmbox;
515 pCD->iconImage = NULL;
516 pCD->useClientIcon = False;
517 pCD->focusAutoRaise = True;
518 pCD->internalBevel = (wmGD.frameStyle == WmSLAB) ? 0 :
519 FRAME_INTERNAL_SHADOW_WIDTH;
521 pCD->maximumClientSize.width = 0;
522 pCD->maximumClientSize.height = 0;
523 pCD->systemMenu = NULL;
528 * Set up transient for data.
531 if (manageFlags & MANAGEW_ICON_BOX)
537 * Set up WM_HINTS type information.
540 pCD->inputFocusModel = True;
541 pCD->clientState = NORMAL_STATE;
543 if (ICON_DECORATION(pCD) & ICON_IMAGE_PART)
545 if (manageFlags & MANAGEW_ICON_BOX)
547 pCD->clientFlags |= ICON_BOX;
550 if (!pCD->useClientIcon && pCD->iconImage)
553 * Make a client supplied icon image.
554 * Do not use the default icon image if iconImage is not found.
557 pCD->iconPixmap = MakeNamedIconPixmap (pCD, pCD->iconImage);
560 if (!pCD->iconPixmap)
563 * Use a built-in icon image for the window manager client.
564 * The image may differ from the default icon image, depending on
565 * the particular client (eg the iconbox).
568 if (manageFlags & MANAGEW_ICON_BOX)
571 * Make a default iconBox icon image.
574 iconBitmap = XCreateBitmapFromData (DISPLAY,
575 ROOT_FOR_CLIENT(pCD), (char *)iconBox_bits,
576 iconBox_width, iconBox_height);
578 pCD->iconPixmap = MakeIconPixmap (pCD,
579 iconBitmap, (Pixmap)0L,
580 iconBox_width, iconBox_height, 1);
588 * Allocate initial workspace ID list
591 if ((pCD->pWsList = (WsClientData *)
592 XtMalloc(pCD->pSD->numWorkspaces * sizeof(WsClientData))) == NULL)
594 Warning (((char *)GETMESSAGE(70, 2, "Insufficient memory for client data")));
597 pCD->sizeWsList = pCD->pSD->numWorkspaces;
598 for (i = 0; i < pCD->pSD->numWorkspaces; i++)
600 pCD->pWsList[i].wsID = NULL;
601 pCD->pWsList[i].iconPlace = NO_ICON_PLACE;
602 pCD->pWsList[i].iconX = 0;
603 pCD->pWsList[i].iconY = 0;
604 pCD->pWsList[i].iconFrameWin = (Window)0L;
605 pCD->pWsList[i].pIconBox = NULL;
608 * Internally managed clients must be specifically inserted
609 * into workspaces the first time by calling
610 * PutClientIntoWorkspace.
612 pCD->numInhabited = 0;
614 pCD->iconPlace = NO_ICON_PLACE;
618 pCD->windowGroup = 0L;
620 pCD->bPseudoTransient = False;
621 #endif /* NO_OL_COMPAT */
625 * Set up _MWM_HINTS data.
628 * Fix the client functions and decorations fields if they have
629 * default resource values.
633 if (manageFlags & MANAGEW_CONFIRM_BOX)
635 pCD->clientFunctions = WM_FUNC_NONE;
636 pCD->clientDecoration = WM_DECOR_BORDER;
640 if (pCD->clientFunctions & WM_FUNC_DEFAULT)
642 pCD->clientFunctions = WM_FUNC_ALL;
645 if (pCD->clientDecoration & WM_DECOR_DEFAULT)
647 pCD->clientDecoration = WM_DECOR_ALL;
650 if (manageFlags & MANAGEW_ICON_BOX)
652 pCD->clientFunctions &= ICON_BOX_FUNCTIONS;
654 pCD->dtwmFunctions &= ~DtWM_FUNCTION_OCCUPY_WS;
657 if (wmGD.useFrontPanel && pCD->pSD->iconBoxControl)
660 * If there's a front panel button for the icon
661 * box, then use it to "hide" the box on "close"
663 pCD->clientFunctions &= ~MWM_FUNC_MINIMIZE;
664 pCD->clientFunctions |= MWM_FUNC_CLOSE;
667 #endif /* PANELIST */
671 if (!(pCD->clientFunctions & MWM_FUNC_RESIZE))
673 pCD->clientDecoration &= ~MWM_DECOR_RESIZEH;
676 if (!(pCD->clientFunctions & MWM_FUNC_MINIMIZE))
678 pCD->clientDecoration &= ~MWM_DECOR_MINIMIZE;
681 if (!(pCD->clientFunctions & MWM_FUNC_MAXIMIZE))
683 pCD->clientDecoration &= ~MWM_DECOR_MAXIMIZE;
687 pCD->decor = pCD->clientDecoration;
689 if (manageFlags & MANAGEW_ICON_BOX)
691 pCD->inputMode = MWM_INPUT_MODELESS;
693 else if (manageFlags & MANAGEW_CONFIRM_BOX)
695 pCD->inputMode = MWM_INPUT_SYSTEM_MODAL;
699 * Set up WM_NORMAL_HINTS data.
702 pCD->icccVersion = ICCC_CURRENT;
703 pCD->sizeFlags = US_POSITION | US_SIZE;
706 * Any calls to create Window Manager clients should
707 * return with the values for the following fields set.
708 * If it fails, it should free any space allocated and
714 * pCD->clientHeight =
724 * pCD->oldMaxHeight =
726 * AND PROBABLY SHOULD SET
727 * pCD->client = THE_WINDOW_THE_FUNCTION_CREATES
730 pCD->windowGravity = NorthWestGravity;
733 * Create IconBox window
736 if (manageFlags & MANAGEW_ICON_BOX)
738 if (!MakeIconBox (pWS, pCD))
741 * May want a more verbose message here
744 Warning (((char *)GETMESSAGE(70, 3, "Couldn't make icon box")));
748 PutClientIntoWorkspace (pWS, pCD);
751 else if (manageFlags & MANAGEW_CONFIRM_BOX)
754 unsigned int cbWidth, cbHeight;
757 XGetGeometry (DISPLAY, pCD->client, &root,
758 &(pCD->clientX), &(pCD->clientY),
760 (unsigned int*)&(pCD->xBorderWidth), &depth);
762 pCD->clientWidth = cbWidth;
763 pCD->clientHeight = cbHeight;
764 pCD->minWidth = pCD->baseWidth = pCD->maxWidth = pCD->clientWidth;
765 pCD->minHeight = pCD->baseHeight = pCD->maxHeight = pCD->clientHeight;
766 pCD->oldMaxWidth = pCD->maxWidth;
767 pCD->oldMaxHeight = pCD->maxHeight;
770 pCD->clientFlags |= CONFIRM_BOX;
772 PutClientIntoWorkspace (ACTIVE_WS, pCD);
777 * Set offset from frame of client window (need client size information).
784 * Register the client window to facilitate event handling.
787 XSaveContext (DISPLAY, pCD->client, wmGD.windowContextType, (caddr_t)pCD);
791 * Set up WM_PROTOCOLS data.
794 pCD->clientProtocolCount = 0;
795 pCD->protocolFlags = 0;
799 * Make the system menu.
802 if (manageFlags & MANAGEW_ICON_BOX)
804 #if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
805 /** BEGIN FIX CR 6941 **/
806 MenuItem *iconBoxMenuItems, *lastItem;
808 /* This MenuSpec is not added to pSD->acceleratorMenuSpecs */
809 pCD->systemMenuSpec =
810 MAKE_MENU (PSD_FOR_CLIENT(pCD), pCD, pCD->systemMenu,
811 F_CONTEXT_WINDOW, F_CONTEXT_WINDOW|F_CONTEXT_ICON,
813 if (pCD->systemMenuSpec != (MenuSpec *) NULL)
815 pCD->systemMenuSpec = DuplicateMenuSpec(pCD->systemMenuSpec);
816 XtFree(pCD->systemMenuSpec->name);
817 pCD->systemMenuSpec->name = XtNewString("IconBoxMenu");
818 iconBoxMenuItems = GetIconBoxMenuItems (PSD_FOR_CLIENT(pCD));
820 /* Find the last menu item in the menu spec's list. */
821 for (lastItem = pCD->systemMenuSpec->menuItems;
822 lastItem->nextMenuItem != (MenuItem *) NULL;
823 lastItem = lastItem->nextMenuItem)
825 lastItem->nextMenuItem = iconBoxMenuItems;
827 /* Now recreate the menu widgets since we've appended the
828 icon box menu items */
829 DestroyMenuSpecWidgets(pCD->systemMenuSpec);
830 pCD->systemMenuSpec->menuWidget =
831 CreateMenuWidget (PSD_FOR_CLIENT(pCD), pCD, "IconBoxMenu",
832 PSD_FOR_CLIENT(pCD)->screenTopLevelW, TRUE,
833 pCD->systemMenuSpec, NULL);
835 /** END FIX CR 6941 **/
837 pCD->systemMenuSpec =
838 MAKE_MENU (PSD_FOR_CLIENT(pCD), pCD, pCD->systemMenu,
839 F_CONTEXT_WINDOW, F_CONTEXT_WINDOW|F_CONTEXT_ICON,
840 GetIconBoxMenuItems(PSD_FOR_CLIENT(pCD)),
842 #endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
848 * Setup the colormap data.
851 pCD->clientColormap = PSD_FOR_CLIENT(pCD)->workspaceColormap;
855 * Return the pointer to the client data.
861 } /* END OF FUNCTION GetWmClientInfo */
865 /*************************************<->*************************************
867 * ProcessWmClass (pCD)
872 * This function retrieves the contents of the WM_CLASS property on the
873 * cient window. The resource class and the resource name are saved in
874 * the ClientData structure (note that the space for the strings is
875 * allocated using Xmalloc).
880 * pCD - pointer to client data
889 *************************************<->***********************************/
892 ProcessWmClass (ClientData *pCD)
894 XClassHint classHint;
898 classHint.res_class = "";
899 classHint.res_name = "";
900 XGetClassHint (DISPLAY, pCD->client, &classHint);
903 if ((HasProperty (pCD, XA_WM_CLASS)) &&
904 (XGetClassHint (DISPLAY, pCD->client, &classHint)))
906 if (XGetClassHint (DISPLAY, pCD->client, &classHint))
910 /* the WM_CLASS property exists for the client window */
911 pCD->clientClass = classHint.res_class;
912 pCD->clientName = classHint.res_name;
914 /* else no WM_CLASS property; assume clientClass, clientName are NULL */
916 } /* END OF FUNCTION ProcessWmClass */
920 /*************************************<->*************************************
922 * ProcessSmClientID (pCD)
927 * This function retrieves the contents of the SM_CLIENT_ID property on the
928 * cient window. The value is saved in the ClientData structure
929 * (note that the space for the strings is allocated using Xmalloc).
934 * pCD - pointer to client data
943 *************************************<->***********************************/
946 ProcessSmClientID (ClientData *pCD)
950 unsigned long nitems, leftover;
953 if (pCD->smClientID != (String)NULL)
955 XFree(pCD->smClientID);
956 pCD->smClientID = (String)NULL;
959 if ((XGetWindowProperty(DISPLAY, pCD->client, wmGD.xa_SM_CLIENT_ID,
960 0L, (long)1000000, False, AnyPropertyType,
961 &actualType, &actualFormat, &nitems,
962 &leftover, (unsigned char **)&clientID)
964 (actualType != None) && (actualFormat == 8))
966 /* the SM_CLIENT_ID property exists for the client window */
967 pCD->smClientID = clientID;
970 } /* END OF FUNCTION ProcessSmClientID */
974 /*************************************<->*************************************
976 * ProcessWmSaveHint (pCD)
981 * This function retrieves the contents of the WMSAVE_HINT property on the
982 * cient window. The value is saved in the ClientData structure.
987 * pCD - pointer to client data
996 *************************************<->***********************************/
999 ProcessWmSaveHint (ClientData *pCD)
1003 unsigned long nitems, leftover;
1004 BITS32 *saveHintFlags = (BITS32 *)NULL;
1006 if ((XGetWindowProperty(DISPLAY, pCD->client, wmGD.xa_WMSAVE_HINT,
1007 0L, (long)1000000, False, AnyPropertyType,
1008 &actualType, &actualFormat, &nitems,
1009 &leftover, (unsigned char **)&saveHintFlags)
1011 (actualType != None) && (actualFormat == 32))
1013 /* the WMSAVE_HINT property exists for the client window */
1014 pCD->wmSaveHintFlags = (int)*saveHintFlags;
1016 else pCD->wmSaveHintFlags = 0;
1019 XFree(saveHintFlags);
1021 } /* END OF FUNCTION ProcessWmSaveHint */
1024 /*************************************<->*************************************
1026 * ProcessWmHints (pCD, firstTime)
1031 * This function retrieves the contents of the WM_HINTS property on the
1037 * pCD = pointer to client data for the window with the property
1039 * firstTime = if True this is the first time the property has been processed
1044 * pCD = initialize various WM_HINTS related fields
1050 *************************************<->***********************************/
1053 ProcessWmHints (ClientData *pCD, Boolean firstTime)
1055 register XWMHints *pXWMHints;
1056 register long flags;
1060 WmWorkspaceData *pWsTmp;
1064 int tmpIconX, tmpIconY;
1068 * If the WM_HINTS property does not exist the flags field will be
1069 * set to 0. If flags is 0 don't reference the WMHints structure
1070 * since they may be none.
1074 if (firstTime && !HasProperty (pCD, XA_WM_HINTS))
1078 pXWMHints = XGetWMHints (DISPLAY, pCD->client);
1082 flags = pXWMHints->flags;
1091 * Parse the WM_HINTS information. If this is the first time the hints
1092 * have been processed then parse all fields and set defaults where hint
1093 * fields are not set. If this is not the first time do selective
1099 #ifndef NO_OL_COMPAT
1102 unsigned int numIDs = 0;
1105 * Save the window group.
1108 if (flags & WindowGroupHint)
1110 pCD->windowGroup = pXWMHints->window_group;
1112 * Pretend this is a transient window
1114 if ((pCD->bPseudoTransient) &&
1115 (pCD->transientFor == (Window)0L))
1117 pCD->clientFlags |= CLIENT_TRANSIENT;
1120 * Treat this like a transient window. This is transient
1121 * for the window group window.
1124 if ((pCD->client != pCD->windowGroup) &&
1125 !XFindContext (DISPLAY, pCD->windowGroup,
1126 wmGD.windowContextType, (caddr_t *)&leader))
1128 pCD->transientFor = pCD->windowGroup;
1129 pCD->transientLeader = leader;
1132 * Insure it is in the same set of workspaces
1135 if (pCD->transientLeader &&
1136 GetLeaderPresence(pCD, &pIDs, &numIDs))
1138 ProcessWorkspaceHintList (pCD, pIDs, numIDs);
1145 pCD->windowGroup = 0L;
1147 #endif /* NO_OL_COMPAT */
1149 * The window manger does not do anything with the input hint. Input
1150 * always goes to the selected window.
1153 if (flags & InputHint)
1155 pCD->inputFocusModel = pXWMHints->input;
1159 pCD->inputFocusModel = True;
1164 * The default state is NORMAL_STATE. States other than iconic
1165 * (e.g., ZoomState from the R2 ICCC) indicate to the window manager
1166 * that the NORMAL_STATE is to be used.
1169 if (pCD->clientFlags & SM_CLIENT_STATE)
1171 if ((pCD->clientState == MINIMIZED_STATE) &&
1172 (!(pCD->clientFunctions & MWM_FUNC_MINIMIZE)))
1174 pCD->clientState = NORMAL_STATE;
1178 if ((flags & StateHint) && (pXWMHints->initial_state == IconicState) &&
1179 (pCD->clientFunctions & MWM_FUNC_MINIMIZE))
1181 pCD->clientState = MINIMIZED_STATE;
1186 * States other than iconic are treated as normal.
1188 pCD->clientState = NORMAL_STATE;
1193 if (!ClientInWorkspace (PSD_FOR_CLIENT(pCD)->pActiveWS, pCD))
1195 pCD->clientState |= UNSEEN_STATE;
1201 * If an icon is to be made for the client then ...
1202 * save the icon image if useClientIcon is True or there is no
1203 * user specified icon image. A client supplied image may be a
1204 * pixmap or a window (a client icon window takes precedence over
1208 if ((pCD->clientFunctions & MWM_FUNC_MINIMIZE) &&
1209 (pCD->transientLeader == NULL))
1211 if ((ICON_DECORATION(pCD) & ICON_IMAGE_PART) &&
1212 (pCD->useClientIcon || !pCD->iconImage))
1214 if ((flags & IconWindowHint) &&
1215 (pXWMHints->icon_window != pCD->client))
1218 * An icon window has been supplied that is different from
1219 * the client window. Check out the window and get it
1220 * ready to be reparented to the window manager supplied
1224 if (!SetupClientIconWindow (pCD, pXWMHints->icon_window))
1227 * Cannot use the client supplied icon window. Use
1228 * an icon image if specified or a default image.
1232 if (!pCD->iconWindow && (flags & IconPixmapHint))
1234 iconMask = (flags & IconMaskHint) ?
1235 pXWMHints->icon_mask : (Pixmap) NULL;
1237 * A client supplied icon window is NOT
1238 * available so use the client supplied icon image.
1241 if ((pCD->iconPixmap =
1242 MakeClientIconPixmap (pCD,
1243 pXWMHints->icon_pixmap, iconMask)) != None)
1246 * Indicate that a client supplied icon image is being
1250 pCD->iconFlags |= ICON_HINTS_PIXMAP;
1255 * Cannot make a client supplied image. Use a user
1256 * specified icon image if it is available or a default
1263 if ((ICON_DECORATION(pCD) & ICON_IMAGE_PART) && !pCD->iconPixmap)
1266 * Use a user supplied icon image if it is available or a
1267 * default icon image.
1273 * Try to make a user specified icon image.
1277 MakeNamedIconPixmap (pCD, pCD->iconImage);
1280 if (!pCD->iconPixmap)
1283 * The icon image was not provided or not available.
1284 * Use the default icon image.
1287 pCD->iconPixmap = MakeNamedIconPixmap (pCD, NULL);
1293 * Save the client (user?) supplied icon position:
1296 if ((flags & IconPositionHint) ||
1297 (pCD->clientFlags & (SM_ICON_X | SM_ICON_Y)))
1299 pCD->iconFlags |= ICON_HINTS_POSITION;
1300 if (wmGD.iconAutoPlace)
1304 * Initialize icon placement data in all inhabited
1307 for (iws = 0; iws< pCD->numInhabited; iws++)
1309 pWsc = &(pCD->pWsList[iws]);
1310 if (pWsTmp=GetWorkspaceData(pCD->pSD, pWsc->wsID))
1312 tmpIconX = (pCD->clientFlags & SM_ICON_X) ?
1313 pWsc->iconX : pXWMHints->icon_x;
1314 tmpIconY = (pCD->clientFlags & SM_ICON_Y) ?
1315 pWsc->iconY : pXWMHints->icon_y;
1317 FindIconPlace (pCD, &(pWsTmp->IPData),
1318 tmpIconX, tmpIconY);
1319 if (pWsc->iconPlace != NO_ICON_PLACE)
1321 CvtIconPlaceToPosition ( &(pWsTmp->IPData),
1331 for (iws = 0; iws< pCD->numInhabited; iws++)
1333 pWsc = &(pCD->pWsList[iws]);
1334 if (pWsTmp=GetWorkspaceData(pCD->pSD, pWsc->wsID))
1336 if (!(pCD->clientFlags & SM_ICON_X))
1337 pWsc->iconX = pXWMHints->icon_x;
1338 if (!(pCD->clientFlags & SM_ICON_Y))
1339 pWsc->iconY = pXWMHints->icon_y;
1345 tmpIconX = (pCD->clientFlags & SM_ICON_X) ?
1346 pCD->iconX : pXWMHints->icon_x;
1347 tmpIconY = (pCD->clientFlags & SM_ICON_Y) ?
1348 pCD->iconY : pXWMHints->icon_y;
1350 FindIconPlace (pCD, &(pCD->pSD->pActiveWS->IPData),
1351 tmpIconX, tmpIconY);
1352 if (pCD->iconPlace != NO_ICON_PLACE)
1354 CvtIconPlaceToPosition (&(pCD->pSD->pActiveWS->IPData),
1355 pCD->iconPlace, &pCD->iconX, &pCD->iconY);
1360 if (!(pCD->clientFlags & SM_ICON_X))
1361 pCD->iconX = pXWMHints->icon_x;
1362 if (!(pCD->clientFlags & SM_ICON_Y))
1363 pCD->iconY = pXWMHints->icon_y;
1369 if (wmGD.iconAutoPlace)
1373 * Initialize icon placement data in all inhabited
1376 for (iws = 0; iws< pCD->numInhabited; iws++)
1378 pWsc = &(pCD->pWsList[iws]);
1379 pWsc->iconPlace = NO_ICON_PLACE;
1384 pCD->iconPlace = NO_ICON_PLACE;
1394 * Save the window group.
1397 if (flags & WindowGroupHint)
1399 pCD->windowGroup = pXWMHints->window_group;
1403 pCD->windowGroup = 0L;
1405 #endif /* NO_OL_COMPAT */
1407 else /* not the first time the hints are processed */
1409 if (flags & IconPixmapHint)
1412 * Process an icon image change if the icon image was initially
1413 * set up with a client supplied icon image OR, if the client
1414 * now wants to supply an image.
1416 iconMask = (flags & IconMaskHint)?
1417 pXWMHints->icon_mask : (Pixmap) NULL;
1420 MakeClientIconPixmap (pCD, pXWMHints->icon_pixmap,
1424 * Made new icon image; free up the old image and display
1427 if (pCD->iconFlags & ICON_HINTS_PIXMAP)
1430 * ICON_HINTS_PIXMAP was set either initally or
1431 * below because a new pixmap was made for the client.
1432 * It is now safe to free the previous pixmap since it
1433 * is not the shared default iconPixmap
1435 if (pCD->iconPixmap)
1437 XFreePixmap (DISPLAY, pCD->iconPixmap);
1442 pCD->iconFlags |= ICON_HINTS_PIXMAP;
1445 pCD->iconPixmap = iconPixmap;
1448 * Display new icon image if the icon is showing:
1451 if (((pCD->clientState == MINIMIZED_STATE) ||
1452 ((pCD->pSD->useIconBox) && (P_ICON_BOX(pCD)))) &&
1453 ICON_FRAME_WIN(pCD))
1455 IconExposureProc (pCD, True);
1463 XFree ((char*)pXWMHints);
1467 } /* END OF FUNCTION ProcessWmHints */
1471 /*************************************<->*************************************
1473 * ProcessWmNormalHints (pCD, firstTime, manageFlags)
1478 * This function retrieves the contents of the WM_NORMAL_HINTS property on
1479 * the cient window. There are several versions of the property that must be
1480 * handled (currently R2 and CURRENT).
1485 * pCD = pointer to client data for the window with the property
1487 * firstTime = if True this is the first time the property has been processed
1489 * manageFlags = flags that indicate wm state information
1494 * pCD = client location and size fields set
1499 * If the hints are being reprocessed (!firstTime) the configuration values
1500 * will be ignored. The size constraint values will be processed but the
1501 * client configuration will not be changed even if it is not in line with
1502 * the new values. Reconfigurations subsequent to the hints changes will
1503 * be done with the new constraints.
1505 *************************************<->***********************************/
1508 ProcessWmNormalHints (ClientData *pCD, Boolean firstTime, long manageFlags)
1510 register SizeHints *pNormalHints;
1511 register long flags;
1513 unsigned long decoration;
1514 unsigned int boxdim, tmpMin;
1515 unsigned int oldWidthInc, oldHeightInc;
1516 unsigned int oldBaseWidth, oldBaseHeight;
1517 unsigned int incWidth, incHeight;
1520 * Use a custom verion of the Xlib routine to get WM_NORMAL_HINTS.
1521 * A custom version is necessary to handle the different versions
1522 * of WM_NORMAL_HINTS that may be encountered. If the WM_NORMAL_HINTS
1523 * property does not exist the flags field will be set to 0.
1526 pNormalHints = GetNormalHints (pCD);
1528 pCD->icccVersion = pNormalHints->icccVersion;
1532 * Parse the WM_NORMAL_HINTS information:
1535 if (((flags = pNormalHints->flags) == 0) && !firstTime)
1542 * Process the size only if this is the first time the hints are
1543 * being processed for the window.
1549 * Process client window size flags and information:
1552 pCD->sizeFlags = flags & (US_POSITION | US_SIZE | P_POSITION | P_SIZE);
1555 * The R2 conventions and Xlib manual indicate that the window size
1556 * and position should be taken out of the WM_NORMAL_HINTS property
1557 * if they are specified there. The current conventions indicate that
1558 * the size and position information should be gotten from the window
1559 * configuration. Mwm 1.1 always uses the current conventions.
1564 * Maintain R2 compatiblity code for CND product xnm
1566 if ((pNormalHints->icccVersion == ICCC_R2) &&
1567 (flags & (US_POSITION | P_POSITION)) &&
1568 !(manageFlags & MANAGEW_WM_RESTART))
1570 if (!(pCD->clientFlags & SM_X))
1571 pCD->clientX = pNormalHints->x;
1572 if (!(pCD->clientFlags & SM_Y))
1573 pCD->clientY = pNormalHints->y;
1577 if (!(pCD->clientFlags & SM_X))
1578 pCD->clientX = wmGD.windowAttributes.x;
1579 if (!(pCD->clientFlags & SM_Y))
1580 pCD->clientY = wmGD.windowAttributes.y;
1582 #else /* R2_COMPAT */
1583 if (!(pCD->clientFlags & SM_X))
1584 pCD->clientX = wmGD.windowAttributes.x;
1585 if (!(pCD->clientFlags & SM_Y))
1586 pCD->clientY = wmGD.windowAttributes.y;
1587 #endif /* R2_COMPAT */
1590 * Use current conventions for initial window dimensions.
1595 * Maintain R2 compatiblity code for CND product xnm
1597 if ((pNormalHints->icccVersion == ICCC_R2) &&
1598 (flags & (US_SIZE | P_SIZE)) &&
1599 !(manageFlags & MANAGEW_WM_RESTART))
1601 if (!(pCD->clientFlags & SM_WIDTH))
1602 pCD->clientWidth = pNormalHints->width;
1603 if (!(pCD->clientFlags & SM_HEIGHT))
1604 pCD->clientHeight = pNormalHints->height;
1608 if (!(pCD->clientFlags & SM_WIDTH))
1609 pCD->clientWidth = wmGD.windowAttributes.width;
1610 if (!(pCD->clientFlags & SM_HEIGHT))
1611 pCD->clientHeight = wmGD.windowAttributes.height;
1613 #else /* R2_COMPAT */
1614 if (!(pCD->clientFlags & SM_WIDTH))
1615 pCD->clientWidth = wmGD.windowAttributes.width;
1616 if (!(pCD->clientFlags & SM_HEIGHT))
1617 pCD->clientHeight = wmGD.windowAttributes.height;
1618 #endif /* R2_COMPAT */
1622 * Process the minimum size:
1625 if (flags & P_MIN_SIZE)
1628 (pNormalHints->min_width < 0) ? 0 : pNormalHints->min_width;
1630 (pNormalHints->min_height < 0) ? 0 : pNormalHints->min_height;
1631 if (pCD->minWidth > MAX_MAX_SIZE(pCD).width)
1633 pCD->minWidth = MAX_MAX_SIZE(pCD).width;
1635 if (pCD->minHeight > MAX_MAX_SIZE(pCD).height)
1637 pCD->minHeight = MAX_MAX_SIZE(pCD).height;
1648 * Process the resizing increments:
1653 oldWidthInc = (pCD->widthInc == 0) ? 1 : pCD->widthInc;
1654 oldHeightInc = (pCD->heightInc == 0) ? 1 : pCD->heightInc;
1657 if (flags & P_RESIZE_INC)
1660 (pNormalHints->width_inc < 1) ? 1 : pNormalHints->width_inc;
1662 (pNormalHints->height_inc < 1) ? 1 : pNormalHints->height_inc;
1672 * Process the base size:
1677 oldBaseWidth = pCD->baseWidth;
1678 oldBaseHeight = pCD->baseHeight;
1681 if (flags & P_BASE_SIZE)
1684 (pNormalHints->base_width < 0) ? 0 : pNormalHints->base_width;
1686 (pNormalHints->base_height < 0) ? 0 : pNormalHints->base_height;
1688 else if ((pNormalHints->icccVersion == ICCC_R2) &&
1690 (!firstTime && (flags & P_MIN_SIZE))))
1693 * In this version of the hints the minimum size was effectively
1696 pCD->baseWidth = pCD->minWidth;
1697 pCD->baseHeight = pCD->minHeight;
1701 if (flags & P_MIN_SIZE)
1703 pCD->baseWidth = pCD->minWidth;
1704 pCD->baseHeight = pCD->minHeight;
1709 pCD->baseHeight = 0;
1715 if (pCD->clientFlags & SM_WIDTH)
1717 pCD->clientWidth = ((pCD->clientWidth * pCD->widthInc) +
1720 if (pCD->clientFlags & SM_HEIGHT)
1722 pCD->clientHeight =((pCD->clientHeight * pCD->heightInc) +
1728 * Process the maximum width. NOTE: maximumClientSize.width
1729 * and maximumClientSize.height will be set to BIGSIZE if
1730 * maximumClientSize is either set to 'horizontal' or 'vertical'.
1733 pCD->oldMaxWidth = pCD->maxWidth;
1734 if (pCD->maximumClientSize.width)
1736 /* If maximumClientSize is full 'horizontal' */
1737 if (IS_MAXIMIZE_HORIZONTAL(pCD))
1739 /* go to min (full screen width, max maximum width) */
1740 pCD->maxWidth = DisplayWidth (DISPLAY, SCREEN_FOR_CLIENT(pCD)) -
1741 (2 * pCD->clientOffset.x);
1744 * Hack to set max client to the current client height, maxHeight
1745 * will be kept up to date whenever the window is reconfigured
1747 pCD->maxHeight = pCD->clientHeight;
1752 pCD->maxWidth = (pCD->maximumClientSize.width *
1753 pCD->widthInc) + pCD->baseWidth;
1758 if (flags & P_MAX_SIZE)
1760 if (pNormalHints->max_width < 0)
1762 /* go to min (full screen width, max maximum width) */
1763 pCD->maxWidth = DisplayWidth (DISPLAY, SCREEN_FOR_CLIENT(pCD)) -
1764 (2 * pCD->clientOffset.x);
1768 pCD->maxWidth = pNormalHints->max_width;
1771 /* Don't reset maxWidth if it has been set earlier */
1772 else if (!IS_MAXIMIZE_VERTICAL(pCD))
1776 /* go to min (full screen width, max maximum width) */
1777 pCD->maxWidth = DisplayWidth (DISPLAY,
1778 SCREEN_FOR_CLIENT(pCD)) -
1779 (2 * pCD->clientOffset.x);
1783 /* reset the maxHeight before further processing */
1784 pCD->maxWidth = pCD->maxWidthLimit;
1790 * If the hints changed we need to adjust the maximum
1791 * size (if not specified in the hints).
1794 ((oldBaseWidth != pCD->baseWidth) ||
1795 (oldWidthInc != pCD->widthInc)))
1797 incWidth = (pCD->maxWidth - oldBaseWidth) / oldWidthInc;
1799 (incWidth * pCD->widthInc) + pCD->baseWidth;
1803 /* reset the maxHeight before further processing */
1804 pCD->maxWidth = pCD->maxWidthLimit;
1807 if (pCD->maxWidth > MAX_MAX_SIZE(pCD).width)
1809 pCD->maxWidth = MAX_MAX_SIZE(pCD).width;
1816 * Process the maximum height.
1819 pCD->oldMaxHeight = pCD->maxHeight;
1820 if (pCD->maximumClientSize.height)
1822 /* If maximumClientSize is full 'vertical' */
1823 if (IS_MAXIMIZE_VERTICAL(pCD))
1825 /* go to min (full screen height, max maximum height) */
1826 pCD->maxHeight = DisplayHeight (DISPLAY, SCREEN_FOR_CLIENT(pCD)) -
1827 (pCD->clientOffset.x +
1828 pCD->clientOffset.y);
1830 * Hack to set max client to the current client width, maxWidth
1831 * will be kept up to date whenever the window is reconfigured
1833 pCD->maxWidth = pCD->clientWidth;
1838 pCD->maxHeight = (pCD->maximumClientSize.height *
1839 pCD->heightInc) + pCD->baseHeight;
1844 if (flags & P_MAX_SIZE)
1846 if (pNormalHints->max_height < 0)
1848 /* go to min (full screen height, max maximum height) */
1849 pCD->maxHeight = DisplayHeight (
1850 DISPLAY, SCREEN_FOR_CLIENT(pCD)) -
1851 (pCD->clientOffset.x +
1852 pCD->clientOffset.y);
1856 pCD->maxHeight = pNormalHints->max_height;
1859 /* Don't reset maxHeight if it has been set above */
1860 else if (!IS_MAXIMIZE_HORIZONTAL(pCD))
1864 /* go to min (full screen height, max maximum height) */
1865 pCD->maxHeight = DisplayHeight (DISPLAY,
1866 SCREEN_FOR_CLIENT(pCD)) -
1867 (pCD->clientOffset.x +
1868 pCD->clientOffset.y);
1872 /* reset the maxHeight before further processing */
1873 pCD->maxHeight = pCD->maxHeightLimit;
1879 * If the hints changed we need to adjust the maximum
1880 * size (if not specified in the hints).
1883 ((oldBaseHeight != pCD->baseHeight) ||
1884 (oldHeightInc != pCD->heightInc)))
1886 incHeight = (pCD->maxHeight - oldBaseHeight) / oldHeightInc;
1888 (incHeight * pCD->heightInc) + pCD->baseHeight;
1892 /* reset the maxHeight before further processing */
1893 pCD->maxHeight = pCD->maxHeightLimit;
1896 if (pCD->maxHeight > MAX_MAX_SIZE(pCD).height)
1898 pCD->maxHeight = MAX_MAX_SIZE(pCD).height;
1903 * Make sure not to exceed the maximumMaximumSize (width and height)
1906 if (pCD->maxWidth > MAX_MAX_SIZE(pCD).width)
1908 pCD->maxWidth = MAX_MAX_SIZE(pCD).width;
1911 if (pCD->maxHeight > MAX_MAX_SIZE(pCD).height)
1913 pCD->maxHeight = MAX_MAX_SIZE(pCD).height;
1917 * Get the initial aspect ratios, if available. Only use them if:
1921 * 0 <= minAspect.x / minAspect.y <= maxAspect.x / maxAspect.y
1924 if (flags & P_ASPECT)
1926 pCD->minAspect.x = pNormalHints->min_aspect.x;
1927 pCD->minAspect.y = pNormalHints->min_aspect.y;
1928 pCD->maxAspect.x = pNormalHints->max_aspect.x;
1929 pCD->maxAspect.y = pNormalHints->max_aspect.y;
1931 if (pCD->minAspect.y > 0 &&
1932 pCD->maxAspect.y > 0 &&
1933 pCD->minAspect.x > 0 &&
1934 pCD->maxAspect.x > 0 &&
1935 (pCD->minAspect.x * pCD->maxAspect.y <=
1936 pCD->maxAspect.x * pCD->minAspect.y))
1938 pCD->sizeFlags |= P_ASPECT;
1942 pCD->sizeFlags &= ~P_ASPECT;
1946 /* compute for minimum frame size */
1947 if ((decoration = pCD->decor) & MWM_DECOR_TITLE)
1949 boxdim = TitleBarHeight(pCD);
1951 ((decoration & MWM_DECOR_MENU) ? boxdim : 0) +
1952 ((decoration & MWM_DECOR_MINIMIZE) ? boxdim : 0) +
1953 ((decoration & MWM_DECOR_MAXIMIZE) ? boxdim : 0) -
1954 2*(pCD->matteWidth);
1962 * Process the window gravity (for positioning):
1965 if (flags & P_WIN_GRAVITY)
1967 pCD->windowGravity = pNormalHints->win_gravity;
1971 if (pNormalHints->icccVersion == ICCC_R2)
1973 pCD->windowGravity = wmGD.windowAttributes.win_gravity;
1977 pCD->windowGravity = NorthWestGravity;
1983 * Make sure that all the window sizing constraints are compatible:
1989 * minWidth >= tmpMin
1990 * minWidth >= max (baseWidth, widthInc) > 0
1991 * & an integral number of widthInc from baseWidth.
1992 * minHeight >= max (baseHeight, heightInc) > 0
1993 * & an integral number of heightInc from baseHeight.
1996 if (pCD->minWidth < tmpMin)
1998 if ((diff = ((tmpMin - pCD->baseWidth)%pCD->widthInc)) != 0)
2000 pCD->minWidth = tmpMin + pCD->widthInc - diff;
2004 pCD->minWidth = tmpMin;
2008 if (pCD->minWidth < pCD->baseWidth)
2010 pCD->minWidth = pCD->baseWidth;
2013 if (pCD->minWidth == 0)
2015 pCD->minWidth = pCD->widthInc;
2017 else if ((diff = ((pCD->minWidth - pCD->baseWidth)%pCD->widthInc)) != 0)
2019 pCD->minWidth += pCD->widthInc - diff;
2022 if (pCD->minHeight < pCD->baseHeight)
2024 pCD->minHeight = pCD->baseHeight;
2027 if (pCD->minHeight == 0)
2029 pCD->minHeight = pCD->heightInc;
2031 else if ((diff = ((pCD->minHeight - pCD->baseHeight) % pCD->heightInc)) !=0)
2033 pCD->minHeight += pCD->heightInc - diff;
2039 * maxWidth >= minWidth
2040 * & an integral number of widthInc from baseWidth.
2041 * maxHeight >= minHeight
2042 * & an integral number of heightInc from baseHeight.
2045 if (pCD->maxWidth < pCD->minWidth)
2047 pCD->maxWidth = pCD->minWidth;
2051 * Hack to use maxWidthLimit as the real maxWidth when maximumClientSize
2052 * set to 'vertical'.
2054 if (IS_MAXIMIZE_VERTICAL(pCD))
2056 /* go to min (full screen width, max maximum width) */
2057 pCD->maxWidthLimit = DisplayWidth (DISPLAY, SCREEN_FOR_CLIENT(pCD)) -
2058 (2 * pCD->clientOffset.x);
2062 pCD->maxWidthLimit = pCD->maxWidth;
2065 pCD->maxWidth -= ((pCD->maxWidth - pCD->baseWidth) % pCD->widthInc);
2069 pCD->oldMaxWidth = pCD->maxWidth;
2072 if (pCD->maxHeight < pCD->minHeight)
2074 pCD->maxHeight = pCD->minHeight;
2078 * Hack to use maxHeightLimit as the real maxHeight when maximumClientSize
2079 * set to 'horizontal'.
2081 if (IS_MAXIMIZE_HORIZONTAL(pCD))
2083 /* go to min (full screen height, max maximum height) */
2084 pCD->maxHeightLimit = DisplayHeight (DISPLAY, SCREEN_FOR_CLIENT(pCD)) -
2085 (pCD->clientOffset.x +
2086 pCD->clientOffset.y);
2090 pCD->maxHeightLimit = pCD->maxHeight;
2093 pCD->maxHeight -= ((pCD->maxHeight - pCD->baseHeight) % pCD->heightInc);
2097 pCD->oldMaxHeight = pCD->maxHeight;
2100 if (!firstTime && pCD->maxConfig)
2103 * If the hints changed while we were maximized then
2104 * we may need to adjust the normalized size of the window.
2107 ((oldBaseWidth != pCD->baseWidth) ||
2108 (oldBaseHeight != pCD->baseHeight) ||
2109 (oldWidthInc != pCD->widthInc) ||
2110 (oldHeightInc != pCD->heightInc)))
2112 incWidth = (pCD->clientWidth - oldBaseWidth) / oldWidthInc;
2113 incHeight = (pCD->clientHeight - oldBaseHeight) / oldHeightInc;
2115 (incWidth * pCD->widthInc) + pCD->baseWidth;
2117 (incHeight * pCD->heightInc) + pCD->baseHeight;
2122 * If using aspect ratios, make:
2124 * minWidth / maxHeight <= minAspect.x / minAspect.y
2125 * <= maxAspect.x / maxAspect.y
2126 * <= maxWidth / minHeight
2129 if (pCD->sizeFlags & P_ASPECT)
2131 if (pCD->minWidth * pCD->minAspect.y >
2132 pCD->minAspect.x * pCD->maxHeight)
2134 pCD->minAspect.x = pCD->minWidth;
2135 pCD->minAspect.y = pCD->maxHeight;
2138 if (pCD->maxAspect.x * pCD->minHeight >
2139 pCD->maxWidth * pCD->maxAspect.y)
2141 pCD->maxAspect.x = pCD->maxWidth;
2142 pCD->maxAspect.y = pCD->minHeight;
2145 FixWindowSize (pCD, (unsigned int *) &(pCD->maxWidth),
2146 (unsigned int *) &(pCD->maxHeight),
2147 (unsigned int) (pCD->widthInc),
2148 (unsigned int) (pCD->heightInc));
2152 * If this is the first time, make sure the client dimensions are within
2153 * range and that they satisfy any aspect ratio constraints:
2155 * 0 < minWidth <= clientWidth <= maxWidth
2156 * 0 < minHeight <= clientHeight <= maxHeight
2158 * minAspect.x / minAspect.y <= clientWidth / clientHeight
2159 * <= maxAspect.x / maxAspect.y
2161 * Initial max width/height are set to max of max size or normal
2162 * client size unless a maximumClientSize was specified.
2167 if (!pCD->maximumClientSize.width)
2169 if (pCD->clientWidth > pCD->pSD->maximumMaximumSize.width)
2171 pCD->clientWidth = pCD->pSD->maximumMaximumSize.width;
2175 if (!pCD->maximumClientSize.height)
2177 if (pCD->clientHeight > pCD->pSD->maximumMaximumSize.height)
2179 pCD->clientHeight = pCD->pSD->maximumMaximumSize.height;
2183 FixWindowSize (pCD, (unsigned int *) &(pCD->clientWidth),
2184 (unsigned int *) &(pCD->clientHeight),
2185 (unsigned int) (pCD->widthInc),
2186 (unsigned int) (pCD->heightInc));
2189 } /* END OF FUNCTION ProcessWmNormalHints */
2192 /*************************************<->*************************************
2194 * WmICCCMToXmString (wmNameProp)
2199 * This function uses a property (WM_NAME or WM_ICON_NAME) that was
2200 * retrieved from the window, and converts it to XmString.
2204 * wmNameProp - the text property
2208 * Return = new XmString, or NULL if the property didn't have a value.
2210 *************************************<->***********************************/
2213 WmICCCMToXmString (XTextProperty *wmNameProp)
2216 XmString xms_return;
2217 XmStringTable xmsTable;
2218 int i, nStrings = -1;
2221 if (wmNameProp->value == 0 || strlen((char *)wmNameProp->value) == 0)
2223 return (XmString)NULL;
2226 if (((status = XmCvtTextPropertyToXmStringTable(DISPLAY, wmNameProp,
2227 &xmsTable, &nStrings))
2228 != Success) || (nStrings <= 0))
2232 case XConverterNotFound:
2233 #ifndef MOTIF_ONE_DOT_ONE
2234 sprintf(msg, GETMESSAGE (70,5,
2235 "Window manager cannot convert property %.100s as clientTitle/iconTitle: XmbTextPropertyToTextList"),
2236 XGetAtomName (DISPLAY,wmNameProp->encoding));
2238 #endif /* MOTIF_ONE_DOT_ONE */
2242 sprintf(msg, GETMESSAGE (70, 6,
2243 "insufficient memory to convert property %.100s as clientTitle/iconTitle: XmbTextPropertyToTextList"),
2244 XGetAtomName(DISPLAY,wmNameProp->encoding));
2248 case XLocaleNotSupported:
2249 if ((wmNameProp->encoding == XA_STRING) ||
2250 (wmNameProp->encoding == wmGD.xa_COMPOUND_TEXT))
2252 sprintf(msg, LOCALE_MSG, setlocale(LC_ALL, NULL));
2256 /* Atom was neither STRING nor COMPOUND_TEXT */
2257 sprintf(msg, GETMESSAGE(70, 8,
2258 "Window manager received unknown property as clientTitle/iconTitle: %.100s. Property ignored."),
2259 XGetAtomName(DISPLAY, wmNameProp->encoding));
2265 /* Couldn't convert using Xm; apply a default */
2266 return XmCvtCTToXmString((char*)wmNameProp->value);
2269 xms_return = xmsTable[0];
2270 for (i = 1; i < nStrings; i++)
2272 #ifdef CONCAT_TEXTLIST
2273 xms_return = XmStringConcatAndFree(xms_return, xmsTable[i]);
2275 XmStringFree(xmsTable[i]);
2276 #endif /* CONCAT_TEXTLIST */
2278 XtFree((char *)xmsTable);
2284 /*************************************<->*************************************
2286 * ProcessWmWindowTitle (pCD, firstTime)
2291 * This function retrieves the contents of the WM_NAME property on the
2292 * cient window. A default name is set if the property does not exist.
2297 * pCD - pointer to client data structure
2298 * firstTime - false if the window is already managed and the title
2304 * pCD - clientTitle, iconTitle
2306 *************************************<->***********************************/
2309 ProcessWmWindowTitle (ClientData *pCD, Boolean firstTime)
2311 XTextProperty wmNameProp;
2312 XmString title_xms = NULL;
2314 if ((pCD->clientDecoration & MWM_DECOR_TITLE) &&
2316 (!firstTime || HasProperty (pCD, XA_WM_NAME)) &&
2318 XGetWMName(DISPLAY, pCD->client, &wmNameProp))
2320 title_xms = WmICCCMToXmString(&wmNameProp);
2321 if (wmNameProp.value)
2322 XFree ((char*)wmNameProp.value);
2327 if (!firstTime && (pCD->iconTitle == pCD->clientTitle))
2330 * The client window title is being used for the icon title so
2331 * change the icon title with the window title.
2333 pCD->iconTitle = title_xms;
2334 RedisplayIconTitle (pCD);
2337 if ((pCD->clientFlags & CLIENT_HINTS_TITLE) &&
2338 pCD->clientTitle != wmGD.clientDefaultTitle)
2340 XmStringFree (pCD->clientTitle);
2343 pCD->clientTitle = title_xms;
2344 pCD->clientFlags |= CLIENT_HINTS_TITLE;
2348 DrawWindowTitle (pCD, True);
2352 * The client frame does not have a place to put the title or the WM_NAME
2353 * property does not exist or there was some error in getting
2354 * the property information, so use a default value.
2358 if (pCD->clientName)
2360 pCD->clientTitle = XmStringCreateLocalized(pCD->clientName);
2364 pCD->clientTitle = wmGD.clientDefaultTitle;
2369 * If this is a tear-off menu, then make sure title text is not clipped
2373 if ((pCD->window_status & MWM_TEAROFF_WINDOW) ||
2374 (pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUBPANEL))
2375 #else /* PANELIST */
2376 if (pCD->window_status & MWM_TEAROFF_WINDOW)
2377 #endif /* PANELIST */
2379 unsigned int boxdim = TitleBarHeight (pCD);
2380 unsigned long decor = pCD->decor;
2381 XmFontList fontList;
2384 if (DECOUPLE_TITLE_APPEARANCE(pCD))
2385 fontList = CLIENT_TITLE_APPEARANCE(pCD).fontList;
2387 fontList = CLIENT_APPEARANCE(pCD).fontList;
2390 * Calculations derived from GetTextBox() and GetFramePartInfo()
2392 minWidth = XmStringWidth(fontList, pCD->clientTitle) +
2394 ((pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUBPANEL) ? 4 : 0) +
2395 #endif /* PANELIST */
2396 ((decor & MWM_DECOR_MENU) ? boxdim : 0) +
2397 ((decor & MWM_DECOR_MINIMIZE) ? boxdim : 0) +
2398 ((decor & MWM_DECOR_MAXIMIZE) ? boxdim : 0) +
2399 WM_TOP_TITLE_SHADOW + WM_BOTTOM_TITLE_SHADOW +
2400 WM_TOP_TITLE_PADDING + WM_BOTTOM_TITLE_PADDING;
2402 if (minWidth > pCD->minWidth)
2404 pCD->minWidth = minWidth;
2407 if ((pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUBPANEL) &&
2408 (pCD->clientWidth < pCD->minWidth))
2410 FixSubpanelEmbeddedClientGeometry (pCD);
2412 #endif /* PANELIST */
2415 } /* END OF FUNCTION ProcessWmWindowTitle */
2419 /*************************************<->*************************************
2421 * FixSubpanelEmbeddedClientGeometry ( pCD )
2426 * This function adjusts the embedded clients in a subpanel if the
2427 * geometry of the subpanel is adjusted.
2432 * pCD - pointer to client data structure
2440 * Only handles change in width right now.
2442 *************************************<->***********************************/
2445 FixSubpanelEmbeddedClientGeometry (ClientData *pCD)
2447 WmScreenData *pSD = PSD_FOR_CLIENT(pCD);
2453 * Get the widget for the subpanel
2455 wSubpanel = WmPanelistWindowToSubpanel (DISPLAY1, pCD->client);
2457 if (pSD->wPanelist && wSubpanel)
2459 WmFpEmbeddedClientData *pECD;
2463 * set new shell width to minimum width
2465 if (pCD->clientWidth < pCD->minWidth)
2468 XtSetArg (al[ac], XmNwidth, pCD->minWidth); ac++;
2469 XtSetValues (wSubpanel, al, ac);
2473 * Cause update of client geometries.
2475 /* WmPanelistSetClientGeometry (pSD->wPanelist); */
2478 * Update all affected reparented controls.
2481 for (i=0; i<pSD->numEmbeddedClients; i++)
2483 pECD = &(((WmFpEmbeddedClientData *) pSD->pECD)[i]);
2487 ClientData *pCD2 = pECD->pCD;
2489 if ((pCD2->clientWidth != pECD->width) ||
2490 (pCD2->clientHeight != pECD->height) ||
2491 (pCD2->clientX != pECD->x) ||
2492 (pCD2->clientY != pECD->y))
2494 pCD2->clientX = pECD->x;
2495 pCD2->clientY = pECD->y;
2496 pCD2->clientWidth = pECD->width;
2497 pCD2->clientHeight = pECD->height;
2499 XMoveResizeWindow (DISPLAY1, pCD2->client,
2500 pECD->x, pECD->y, pECD->width, pECD->height);
2505 } /* END OF FUNCTION FixEmbeddedClientGeometry */
2507 #endif /* PANELIST */
2510 /*************************************<->*************************************
2512 * ProcessWmIconTitle (pCD, firstTime)
2517 * This function retrieves the contents of the WM_ICON_NAME property on the
2518 * cient window. The value of the property is a string that is used for the
2519 * icon title. A default title is set if the property does not exist.
2524 * pCD - pointer to client data structure
2526 * firstTime - false if the window is already managed and the title
2534 *************************************<->***********************************/
2537 ProcessWmIconTitle (ClientData *pCD, Boolean firstTime)
2539 XTextProperty wmIconNameProp;
2540 XmString icon_xms = NULL;
2542 if ((pCD->clientFunctions & MWM_FUNC_MINIMIZE) &&
2543 (pCD->transientLeader == NULL) &&
2545 (!firstTime || HasProperty(pCD, XA_WM_ICON_NAME)) &&
2547 XGetWMIconName (DISPLAY, pCD->client, &wmIconNameProp))
2549 icon_xms = WmICCCMToXmString(&wmIconNameProp);
2550 if (wmIconNameProp.value)
2551 XFree ((char*)wmIconNameProp.value);
2556 if ((pCD->iconFlags & ICON_HINTS_TITLE) &&
2557 pCD->iconTitle != wmGD.iconDefaultTitle)
2559 XmStringFree (pCD->iconTitle);
2562 pCD->iconTitle = icon_xms;
2563 pCD->iconFlags |= ICON_HINTS_TITLE;
2567 RedisplayIconTitle (pCD);
2571 * The WM_ICON_NAME property does not exist (or there was some error
2572 * in getting * the property information), so use a default value.
2576 if (pCD->clientTitle && (pCD->clientTitle != wmGD.clientDefaultTitle))
2578 pCD->iconTitle = pCD->clientTitle;
2582 pCD->iconTitle = wmGD.iconDefaultTitle;
2586 } /* END OF FUNCTION ProcessWmIconTitle */
2590 /*************************************<->*************************************
2592 * ProcessWmTransientFor (pCD)
2597 * This function retrieves the contents of the WM_TRANSIENT_FOR property on
2603 * pCD = pointer to the client data structure for the window with the property
2608 * pCD.transientFor = if tranient then this is the associated main window
2610 * pCD.clientFlags = indicate that this is a transient window
2612 *************************************<->***********************************/
2615 ProcessWmTransientFor (ClientData *pCD)
2622 if ((HasProperty (pCD, XA_WM_TRANSIENT_FOR)) &&
2623 (XGetTransientForHint (DISPLAY, pCD->client, &window)))
2625 if (XGetTransientForHint (DISPLAY, pCD->client, &window))
2628 pCD->clientFlags |= CLIENT_TRANSIENT;
2631 * Only save the (leader) transientFor window if it is NOT the
2632 * client window and it is already managed by the window manager.
2635 if ((pCD->client != window) &&
2636 !XFindContext (DISPLAY, window, wmGD.windowContextType,
2637 (caddr_t *)&leader))
2639 pCD->transientFor = window;
2640 pCD->transientLeader = leader;
2643 else { /* else this is not a transient window */
2644 pCD->clientFlags &= ~CLIENT_TRANSIENT;
2645 pCD->transientFor = (Window)0L;
2646 pCD->transientLeader = NULL;
2650 } /* END OF FUNCTION ProcessWmTransientFor */
2654 /*************************************<->*************************************
2656 * MakeSystemMenu (pCD)
2661 * This function finds or makes a system menu for the client. A check
2662 * is made for the _MWM_MENU property and, if present, client-specific
2663 * items are added to the custom system menu. Any custom system menu
2664 * must be destroyed when the client is unmanaged (or killed).
2669 * pCD = pointer to the client data structure for the managed window
2674 * pCD.systemMenuSpec = system menu specification for the client, not added
2675 * to wmGD.acceleratorMenuSpecs
2677 *************************************<->***********************************/
2680 MakeSystemMenu (ClientData *pCD)
2682 #if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
2684 #endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
2686 pCD->mwmMenuItems = GetMwmMenuItems(pCD);
2687 pCD->systemMenuSpec =
2688 MAKE_MENU (PSD_FOR_CLIENT(pCD), pCD, pCD->systemMenu, F_CONTEXT_WINDOW,
2689 F_CONTEXT_WINDOW|F_CONTEXT_ICON, pCD->mwmMenuItems, TRUE);
2691 #ifdef NO_MESSAGE_CATALOG
2692 if (pCD->systemMenuSpec == NULL)
2695 * As the lookup has failed, let's try just one more time.
2697 Warning("Retrying - using builtin window menu\n");
2699 pCD->systemMenuSpec =
2700 MAKE_MENU(PSD_FOR_CLIENT(pCD), pCD, builtinSystemMenuName,
2702 F_CONTEXT_WINDOW|F_CONTEXT_ICON, pCD->mwmMenuItems, TRUE);
2706 #if defined(MWM_QATS_PROTOCOL)
2707 /* Added to fix CDExc23338
2708 * Not sure what the MWM_QATS_PROTOCOL is trying to accomplish here,
2709 * but this code is causing the system menu to loose it's default
2710 * actions whenever client defined actions are added. I thought
2711 * it prudent to minimize the changes. It could be that the
2712 * #if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
2714 * #if ((!defined(WSM)) && defined(MWM_QATS_PROTOCOL))
2715 * throughout the wm code, but I am loath to make such a change
2716 * without any documentation.
2719 #if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
2720 /** BEGIN FIX CR 6941 **/
2722 /* if we still don't have a menu spec, then just abort. */
2723 if (pCD->systemMenuSpec == NULL)
2726 pCD->systemMenuSpec = DuplicateMenuSpec(pCD->systemMenuSpec);
2727 XtFree(pCD->systemMenuSpec->name);
2728 pCD->systemMenuSpec->name = XtNewString("ProtocolsMenu");
2730 /* Find the last menu item in the menu spec's list. */
2731 for (lastItem = pCD->systemMenuSpec->menuItems;
2732 lastItem->nextMenuItem != (MenuItem *) NULL;
2733 lastItem = lastItem->nextMenuItem)
2735 lastItem->nextMenuItem = pCD->mwmMenuItems;
2737 /* Now recreate the menu widgets since we've appended the
2738 protocol menu items */
2739 DestroyMenuSpecWidgets(pCD->systemMenuSpec);
2740 pCD->systemMenuSpec->menuWidget =
2741 CreateMenuWidget (PSD_FOR_CLIENT(pCD), pCD, "ProtocolsMenu",
2742 PSD_FOR_CLIENT(pCD)->screenTopLevelW, TRUE,
2743 pCD->systemMenuSpec, NULL);
2744 /** END FIX CR 6941 **/
2745 #endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
2746 #endif /* defined(MWM_QATS_PROTOCOL) */
2748 } /* END OF FUNCTION MakeSystemMenu */
2752 /*************************************<->*************************************
2754 * InitCColormapData (pCD)
2759 * This function initializes colormap data for the client window that is
2760 * by the window manager in maintaining the colormap focus. This may
2761 * involve retrieving and processing properties that deal with subwindow
2767 * pCD = pointer to the client data structure for the managed window
2772 * pCD.clientColormap = client colormap to be installed when the client
2773 * window gets the colormap focus
2775 * pCD = (cmapWindows, clientCmapList, clientCmapCount, clientCmapIndex)
2777 *************************************<->***********************************/
2780 InitCColormapData (ClientData *pCD)
2783 if (wmGD.windowAttributes.colormap == None)
2785 pCD->clientColormap = WORKSPACE_COLORMAP(pCD);
2789 pCD->clientColormap = wmGD.windowAttributes.colormap;
2793 * Process subwindow colormap windows if they are specified.
2796 ProcessWmColormapWindows (pCD);
2799 } /* END OF FUNCTION InitCColormapData */
2803 /*************************************<->*************************************
2805 * CalculateGravityOffset (pCD, xoff, yoff)
2810 * This function calculates the window offsets based on the window gravity
2811 * and the window frame client offset.
2816 * pCD = pointer to client data (client window configuration fields)
2817 * xoff = pointer to xoffset
2818 * yoff = pointer to yoffset
2823 * xoff = pointer to xoffset set
2824 * yoff = pointer to yoffset set
2826 *************************************<->***********************************/
2829 CalculateGravityOffset (ClientData *pCD, int *xoff, int *yoff)
2831 int borderWidth = pCD->xBorderWidth;
2833 if (pCD->windowGravity < ForgetGravity ||
2834 pCD->windowGravity > StaticGravity)
2841 switch (pCD->windowGravity)
2843 case NorthWestGravity:
2846 *xoff = pCD->clientOffset.x;
2847 *yoff = pCD->clientOffset.y;
2853 *xoff = borderWidth;
2854 *yoff = pCD->clientOffset.y;
2858 case NorthEastGravity:
2860 *xoff = -(pCD->clientOffset.x - (2 * borderWidth));
2861 *yoff = pCD->clientOffset.y;
2867 *xoff = -(pCD->clientOffset.x - (2 * borderWidth));
2868 *yoff = borderWidth +
2869 (pCD->clientOffset.y - pCD->clientOffset.x)/2;
2873 case SouthEastGravity:
2875 *xoff = -(pCD->clientOffset.x - (2 * borderWidth));
2876 *yoff = -(pCD->clientOffset.x - (2 * borderWidth));
2882 *xoff = borderWidth;
2883 *yoff = -(pCD->clientOffset.x - (2 * borderWidth));
2887 case SouthWestGravity:
2889 *xoff = pCD->clientOffset.x;
2890 *yoff = -(pCD->clientOffset.x - (2 * borderWidth));
2896 *xoff = pCD->clientOffset.x;
2897 *yoff = borderWidth +
2898 (pCD->clientOffset.y - pCD->clientOffset.x)/2;
2910 } /* END OF FUNCTION CalculateGravityOffset */
2914 /*************************************<->*************************************
2916 * InitClientPlacement (pCD, manageFlags)
2921 * This function sets up the initial client window placement (for both
2922 * the normal and maximized state).
2927 * pCD = pointer to client data (client window configuration fields)
2929 * manageFlags = flags that indicate wm state information (e.g. whether
2930 * the window manager is starting up or restarting)
2935 * Return = True if position changed by this routine.
2936 * pCD = changes to the client window configuration fields
2938 *************************************<->***********************************/
2941 InitClientPlacement (ClientData *pCD, long manageFlags)
2943 Boolean interactivelyPlaced = False;
2944 Boolean autoPlaced = False;
2945 Boolean rval = False;
2947 int origX, origY, origWidth, origHeight;
2954 * Save initial client values
2956 origX = pCD->clientX;
2957 origY = pCD->clientY;
2958 origWidth = pCD->clientWidth;
2959 origHeight = pCD->clientHeight;
2962 * Do interactive placement if...
2963 * + the resource is turned on
2964 * + the window's coming up on the active screen
2967 * + position specified in DB or by Session Manager
2968 * + the user has specified a position
2969 * + the window is coming up iconic
2970 * + the window is transient
2971 * + we're system modal
2974 if (wmGD.interactivePlacement &&
2975 (!(pCD->clientFlags & (SM_X | SM_Y))) &&
2976 !(pCD->sizeFlags & US_POSITION) &&
2977 (pCD->clientState != MINIMIZED_STATE) &&
2978 (manageFlags == MANAGEW_NORMAL) &&
2979 !(pCD->clientFlags & CLIENT_TRANSIENT) &&
2980 (pCD->inputMode != MWM_INPUT_SYSTEM_MODAL) &&
2982 (ClientInWorkspace(PSD_FOR_CLIENT(pCD)->pActiveWS, pCD)))
2984 (PSD_FOR_CLIENT(pCD) == ACTIVE_PSD))
2988 * Interactively place the window on the screen.
2990 interactivelyPlaced = True;
2991 PlaceWindowInteractively (pCD);
2996 * Check out the configuration values to insure that they are within
3000 FixWindowConfiguration (pCD, (unsigned int *) &(pCD->clientWidth),
3001 (unsigned int *) &(pCD->clientHeight),
3002 (unsigned int) (pCD->widthInc),
3003 (unsigned int) (pCD->heightInc));
3006 * Do autoplacement of the client window if appropriate.
3009 if ((manageFlags == MANAGEW_NORMAL) && !interactivelyPlaced &&
3010 (!(pCD->clientFlags & (SM_X | SM_Y))) &&
3011 !(pCD->sizeFlags & US_POSITION) &&
3012 !(pCD->clientFlags & CLIENT_TRANSIENT) &&
3013 (pCD->inputMode != MWM_INPUT_SYSTEM_MODAL) && wmGD.clientAutoPlace)
3016 * if (PPosition is on or nonzero), then use current value for
3017 * clientX and clientY which was set to windowAttributes.x,y
3018 * by ProcessWmNormalHints(), else autoplace client.
3021 if ((pCD->sizeFlags & P_POSITION) &&
3022 ((pCD->usePPosition == USE_PPOSITION_ON) ||
3023 ((pCD->usePPosition == USE_PPOSITION_NONZERO) &&
3024 ((pCD->clientX != 0) || (pCD->clientY != 0)))))
3030 FindClientPlacement (pCD);
3036 * Do PositionIsFrame processing:
3037 * Use window gravity to allow the user to specify the window
3038 * position on the screen without having to know the dimensions
3039 * of the decoration that mwm is adding.
3042 if ((wmGD.positionIsFrame) &&
3043 !interactivelyPlaced && !autoPlaced)
3045 CalculateGravityOffset (pCD, &xoff, &yoff);
3046 if (!(pCD->clientFlags & SM_X))
3047 pCD->clientX += xoff;
3048 if (!(pCD->clientFlags & SM_Y))
3049 pCD->clientY += yoff;
3054 * Do PositionOnScreen processing:
3060 if (pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUBPANEL)
3062 if (pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUB_RESTORED)
3068 AdjustSlideOutGeometry (pCD);
3072 #endif /* PANELIST */
3074 if (((wmGD.positionOnScreen) && !interactivelyPlaced) &&
3075 (!(pCD->clientFlags & (SM_X | SM_Y))))
3077 PlaceFrameOnScreen (pCD, &pCD->clientX, &pCD->clientY,
3078 pCD->clientWidth, pCD->clientHeight);
3083 * Position the maximized frame:
3086 pCD->maxX = pCD->clientX;
3087 pCD->maxY = pCD->clientY;
3088 PlaceFrameOnScreen (pCD, &pCD->maxX, &pCD->maxY, pCD->maxWidth,
3092 if (!wmGD.iconAutoPlace)
3095 if (!(pCD->iconFlags & ICON_HINTS_POSITION))
3097 for (iwsc=0; iwsc<pCD->numInhabited; iwsc++)
3099 pCD->pWsList[iwsc].iconX = pCD->clientX;
3100 pCD->pWsList[iwsc].iconY = pCD->clientY;
3101 PlaceIconOnScreen (pCD, &pCD->pWsList[iwsc].iconX,
3102 &pCD->pWsList[iwsc].iconY);
3106 if (!(pCD->iconFlags & ICON_HINTS_POSITION))
3108 pCD->iconX = pCD->clientX;
3109 pCD->iconY = pCD->clientY;
3111 PlaceIconOnScreen (pCD, &pCD->iconX, &pCD->iconY);
3116 * if client size or position has been changed by this routine,
3117 * then indicate in return value
3119 if ((origX != pCD->clientX) || (origY != pCD->clientY) ||
3120 (origWidth != pCD->clientWidth) || (origHeight != pCD->clientHeight))
3127 } /* END OF FUNCTION InitClientPlacement */
3131 /******************************<->*************************************
3133 * void AdjustSlideOutGeometry (pCD)
3137 * Adjusts the geometry of the slide out panel
3141 * pCD = pointer to a client data of slide out
3148 * Subpanel is to appear above or below the front panel, centered
3149 * on the vertical axis of the spawning control.
3150 ******************************<->***********************************/
3152 AdjustSlideOutGeometry ( ClientData *pCD)
3154 ClientData *pCD_FP = NULL;
3155 WmPanelistObject pPanelist;
3157 pCD->slideDirection = SLIDE_NORTH; /* assume up for now */
3158 pPanelist = (WmPanelistObject) pCD->pSD->wPanelist;
3159 (void) XFindContext (DISPLAY, XtWindow(O_Shell(pPanelist)),
3160 wmGD.windowContextType, (caddr_t *)&pCD_FP);
3165 * Adjust slide up position if coming from front
3167 * (Assumes no nesting of panels !!!)
3168 * (Assumes horizontal oriented front panel!!!)
3170 if (pCD->transientLeader == pCD_FP)
3173 * Subpanel should be sort-of centered already,
3174 * adjust by width of window manager frame.
3176 pCD->clientX -= pCD->frameInfo.lowerBorderWidth;
3179 * Adjust to slide up above front panel.
3181 pCD->clientY = pCD_FP->frameInfo.y -
3182 pCD->frameInfo.lowerBorderWidth -
3183 pCD->clientHeight + 3;
3185 /* RICK -- added the (+ 3) */
3188 if (pCD->clientY < 0)
3191 * Adjust to slide down below front panel.
3193 pCD->clientY = pCD_FP->frameInfo.y +
3194 pCD_FP->frameInfo.height +
3195 pCD->frameInfo.titleBarHeight +
3196 pCD->frameInfo.upperBorderWidth - 3;
3197 pCD->slideDirection = SLIDE_SOUTH;
3198 /* RICK -- added the (- 3) */
3201 if ((pCD->clientY + pCD->clientHeight +
3202 pCD->frameInfo.lowerBorderWidth) >
3203 XDisplayHeight (DISPLAY, pCD->pSD->screen))
3206 * If the bottom of the slide-up is off the bottom
3207 * of the screen, then don't slide, just pop it up.
3209 pCD->slideDirection = SLIDE_NOT;
3212 PlaceFrameOnScreen (pCD, &pCD->clientX, &pCD->clientY,
3213 pCD->clientWidth, pCD->clientHeight);
3218 #endif /* PANELIST */
3221 /*************************************<->*************************************
3223 * PlaceFrameOnScreen (pCD, pX, pY, w, h)
3228 * This function is used to nudge a client window so that it is totally
3229 * onscreen if possible. At least the top left corner will be onscreen.
3234 * pCD - pointer to client data
3235 * pX - pointer to x-coord
3236 * pY - pointer to y-coord
3237 * w - width of window
3238 * h - height of window
3250 *************************************<->***********************************/
3253 PlaceFrameOnScreen (ClientData *pCD, int *pX, int *pY, int w, int h)
3265 clientOffsetX = pCD->clientOffset.x;
3266 clientOffsetY = pCD->clientOffset.y;
3267 frameX = *pX - clientOffsetX;
3268 frameY = *pY - clientOffsetY;
3269 frameWidth = w + (2 * clientOffsetX);
3270 frameHeight = h + clientOffsetX + clientOffsetY;
3271 screenWidth = DisplayWidth (DISPLAY, SCREEN_FOR_CLIENT(pCD));
3272 screenHeight = DisplayHeight (DISPLAY, SCREEN_FOR_CLIENT(pCD));
3274 if ((frameX + frameWidth) > screenWidth)
3276 frameX -= (frameX + frameWidth) - screenWidth;
3278 if ((frameY + frameHeight) > screenHeight)
3280 frameY -= (frameY + frameHeight) - screenHeight;
3291 *pX = frameX + clientOffsetX;
3292 *pY = frameY + clientOffsetY;
3294 } /* END OF FUNCTION PlaceFrameOnScreen */
3298 /*************************************<->*************************************
3300 * PlaceIconOnScreen (pCD, pX, pY)
3305 * This function positions an icon on-screen.
3310 * pCD - pointer to client data
3311 * pX - pointer to x-coord
3312 * pY - pointer to y-coord
3322 *************************************<->***********************************/
3325 PlaceIconOnScreen (ClientData *pCD, int *pX, int *pY)
3333 screenWidth = DisplayWidth (DISPLAY, SCREEN_FOR_CLIENT(pCD));
3334 screenHeight = DisplayHeight (DISPLAY, SCREEN_FOR_CLIENT(pCD));
3338 if ((iconX + ICON_WIDTH(pCD)) > screenWidth)
3340 iconX = screenWidth - ICON_WIDTH(pCD);
3347 if ((iconY + ICON_HEIGHT(pCD)) > screenHeight)
3349 iconY = screenHeight - ICON_HEIGHT(pCD);
3360 } /* END OF FUNCTION PlaceIconOnScreen */
3364 /*************************************<->*************************************
3366 * FixWindowConfiguration (pCD, pWidth, pHeight, widthInc, heightInc)
3371 * This function adjusts the configuration for the client window so that
3372 * it is in line with the client window's sizing constraints.
3377 * pCD = a pointer to the client window data
3378 * pWidth, pHeight = pointers to the window configuration values
3379 * widthInc, heightInc = window size increment values
3384 * pWidth, pHeight = adjusted configuration values are returned here
3387 *************************************<->***********************************/
3390 FixWindowConfiguration (ClientData *pCD, unsigned int *pWidth, unsigned int *pHeight, unsigned int widthInc, unsigned int heightInc)
3395 * Make sure we're on width/height increment boundaries.
3398 if ((int) *pWidth < pCD->minWidth)
3400 *pWidth = pCD->minWidth;
3402 else if ((delta = (*pWidth - pCD->baseWidth) % pCD->widthInc))
3407 if ((int) *pHeight < pCD->minHeight)
3409 *pHeight = pCD->minHeight;
3411 else if ((delta = (*pHeight - pCD->baseHeight) % pCD->heightInc))
3417 * Constrain size within bounds.
3420 FixWindowSize (pCD, pWidth, pHeight, widthInc, heightInc);
3422 } /* END OF FUNCTION FixWindowConfiguration */
3426 /*************************************<->*************************************
3428 * FixWindowSize (pCD, pWidth, pHeight, widthInc, heightInc)
3433 * This function adjusts the client window width and height so that
3434 * it is in line with its sizing constraints.
3439 * pCD = a pointer to the client window data
3440 * pWidth, pHeight = pointers to the window size values
3441 * widthInc, heightInc = window size increment values
3447 * pWidth, pHeight = adjusted size values.
3450 *************************************<->***********************************/
3453 FixWindowSize (ClientData *pCD, unsigned int *pWidth, unsigned int *pHeight, unsigned int widthInc, unsigned int heightInc)
3455 register int deltaW;
3456 register int deltaH;
3457 WmScreenData *pSD = pCD->pSD;
3460 * All occurances of maxHeight and maxWidth in this routing has been
3461 * hacked to use maxHeightLimit and maxWidthLimit as the real max when
3462 * maximumClientSize is set to 'horizontal' or 'vertical', since
3463 * pCD->maxHeight and pCD->maxWidth is fiddle to on reconfiguration.
3466 if ((int) *pWidth < pCD->minWidth)
3468 *pWidth = pCD->minWidth;
3470 else if (*pWidth > pCD->maxWidthLimit &&
3472 !(pCD->clientFlags & CLIENT_WM_CLIENTS))
3474 *pWidth = pCD->maxWidthLimit;
3477 if ((int) *pHeight < pCD->minHeight)
3479 *pHeight = pCD->minHeight;
3481 else if (*pHeight > pCD->maxHeightLimit &&
3483 !(pCD->clientFlags & CLIENT_WM_CLIENTS))
3485 *pHeight = pCD->maxHeightLimit;
3488 if ((pCD->sizeFlags & P_ASPECT) &&
3489 *pWidth * pCD->maxAspect.y > *pHeight * pCD->maxAspect.x)
3491 * Client aspect is too big.
3492 * Candidate height >= client height:
3493 * Try to increase the client's height without violating bounds.
3494 * If this fails, use maximum height and try to decrease its width.
3495 * Candidate height < client height:
3496 * Try to decrease the client's width without violating bounds.
3497 * If this fails, use minimum width and try to increase its height.
3500 if ((*pHeight >= pCD->clientHeight) ||
3501 (*pWidth > pCD->clientWidth))
3503 * Candidate height >= client height:
3504 * Try to increase the client's height without violating bounds.
3505 * If this fails, use maximum height and try to decrease its width.
3508 deltaH = makemult (*pWidth * pCD->maxAspect.y / pCD->maxAspect.x -
3509 *pHeight, heightInc);
3510 if (*pHeight + deltaH <= pCD->maxHeightLimit ||
3511 !pSD->limitResize ||
3512 pCD->clientFlags & CLIENT_WM_CLIENTS)
3518 *pHeight = pCD->maxHeightLimit;
3519 deltaW = makemult (*pWidth - *pHeight * pCD->maxAspect.x /
3520 pCD->maxAspect.y, widthInc);
3521 if (*pWidth - deltaW >= pCD->minWidth)
3527 *pWidth = pCD->minWidth;
3533 * Candidate height < client height and candidate width <= client width.
3534 * Try to decrease the client's width without violating bounds.
3535 * If this fails, use minimum width and try to increase its height.
3538 deltaW = makemult (*pWidth - *pHeight * pCD->maxAspect.x /
3539 pCD->maxAspect.y, widthInc);
3541 if (*pWidth - deltaW >= pCD->minWidth)
3547 *pWidth = pCD->minWidth;
3548 deltaH = makemult (*pWidth * pCD->maxAspect.y /
3549 pCD->maxAspect.x - *pHeight, heightInc);
3550 if (*pHeight + deltaH <= pCD->maxHeightLimit ||
3551 !pSD->limitResize ||
3552 pCD->clientFlags & CLIENT_WM_CLIENTS)
3558 *pHeight = pCD->maxHeightLimit;
3564 else if ((pCD->sizeFlags & P_ASPECT) &&
3565 *pHeight * pCD->minAspect.x > *pWidth * pCD->minAspect.y)
3567 * Client aspect is too small.
3568 * Candidate width >= client width:
3569 * Try to increase the client's width without violating bounds.
3570 * If this fails, use maximum width and try to decrease its height.
3571 * Candidate width < client width:
3572 * Try to decrease the client's height without violating bounds.
3573 * If this fails, use minimum height and try to increase its width.
3576 if ((*pWidth >= pCD->clientWidth) ||
3577 (*pHeight > pCD->clientHeight))
3579 * Candidate width >= client width:
3580 * Try to increase the client's width without violating bounds.
3581 * If this fails, use maximum width and try to decrease its height.
3584 deltaW = makemult (*pHeight * pCD->minAspect.x / pCD->minAspect.y -
3586 if (*pWidth + deltaW <= pCD->maxWidthLimit ||
3587 !pSD->limitResize ||
3588 pCD->clientFlags & CLIENT_WM_CLIENTS)
3594 *pWidth = pCD->maxWidthLimit;
3595 deltaH = makemult (*pHeight - *pWidth * pCD->minAspect.y /
3596 pCD->minAspect.x, heightInc);
3597 if (*pHeight - deltaH >= pCD->minHeight)
3603 *pHeight = pCD->minHeight;
3609 * Candidate width < client width and Candidate height <= client height:
3610 * Try to decrease the client's height without violating bounds.
3611 * If this fails, use minimum height and try to increase its width.
3614 deltaH = makemult (*pHeight - *pWidth * pCD->minAspect.y /
3615 pCD->minAspect.x, heightInc);
3616 if (*pHeight - deltaH >= pCD->minHeight)
3622 *pHeight = pCD->minHeight;
3623 deltaW = makemult (*pHeight * pCD->minAspect.x /
3624 pCD->minAspect.y - *pWidth, widthInc);
3625 if (*pWidth + deltaW <= pCD->maxWidthLimit ||
3626 !pSD->limitResize ||
3627 pCD->clientFlags & CLIENT_WM_CLIENTS)
3633 *pWidth = pCD->maxWidthLimit;
3638 } /* END OF FUNCTION FixWindowSize */
3642 /*************************************<->*************************************
3644 * FindClientPlacement (pCD)
3649 * This function finds a position for the client window on the screen.
3650 * Windows positions are stepped down the screen. An attempt is made
3651 * to keep windows from being clipped by the edge of the screen.
3656 * pCD = pointer to client data (client window configuration fields)
3661 * pCD = changes to the client window configuration fields
3663 *************************************<->***********************************/
3666 FindClientPlacement (ClientData *pCD)
3668 static Boolean clientPlacementInitialized = False;
3669 static int clientPlacementOffset;
3670 static int clientPlacementX;
3671 static int clientPlacementY;
3672 static int clientPlacementOrigin;
3673 static int clientPlacementXOrigin;
3675 Boolean placed = False;
3680 int borderWidth = 0;
3685 if (!clientPlacementInitialized)
3687 if (pCD->clientDecoration & WM_DECOR_RESIZEH)
3689 borderWidth = ((RESIZE_BORDER_WIDTH(pCD) > FRAME_BORDER_WIDTH(pCD))
3690 ? RESIZE_BORDER_WIDTH(pCD) : FRAME_BORDER_WIDTH(pCD));
3694 borderWidth = pCD->matteWidth;
3696 clientPlacementOffset = TitleTextHeight(pCD) + borderWidth;
3697 clientPlacementOrigin = clientPlacementOffset;
3698 clientPlacementX = clientPlacementOrigin;
3699 clientPlacementY = clientPlacementOrigin;
3700 clientPlacementXOrigin = clientPlacementX;
3701 clientPlacementInitialized = True;
3704 frameWidth = pCD->clientWidth + (2 * pCD->clientOffset.x);
3705 frameHeight = pCD->clientHeight + pCD->clientOffset.y + pCD->clientOffset.x;
3706 screenWidth = DisplayWidth (DISPLAY, SCREEN_FOR_CLIENT(pCD));
3707 screenHeight = DisplayHeight (DISPLAY, SCREEN_FOR_CLIENT(pCD));
3711 if ((clientPlacementX - pCD->clientOffset.x + frameWidth)
3720 if ((clientPlacementY - pCD->clientOffset.y + frameHeight)
3730 if (offScreenX || offScreenY)
3732 if (clientPlacementX == clientPlacementOrigin)
3735 * Placement location is already as far to the NW as it is
3741 else if (clientPlacementY == clientPlacementOrigin)
3744 * Placement location is as far to the N as it is going to go.
3745 * Use the current placement if the window is not off the
3746 * screen in the x coordinate otherwise reset the placement
3747 * back to the NW origin.
3752 clientPlacementXOrigin = clientPlacementOrigin;
3753 clientPlacementX = clientPlacementXOrigin;
3760 * If window is off the right edge of screen, just move
3761 * window in the X direction onto screen. Process similarly
3762 * for windows that are off the bottom of the screen.
3765 if (offScreenX && !offScreenY)
3767 clientPlacementX = clientPlacementOrigin;
3769 else if (offScreenY && !offScreenX)
3771 clientPlacementY = clientPlacementOrigin;
3777 * Reset the placement location back to the NW of the
3778 * current location. Go as far N as possible and step the
3779 * x coordinate to the E.
3782 clientPlacementXOrigin += clientPlacementOffset;
3783 clientPlacementX = clientPlacementXOrigin;
3784 clientPlacementY = clientPlacementOrigin;
3795 * The window has been placed, now update the placement information.
3798 pCD->clientX = clientPlacementX;
3799 pCD->clientY = clientPlacementY;
3800 clientPlacementX += clientPlacementOffset;
3802 if (clientPlacementX >= screenWidth)
3804 clientPlacementXOrigin = clientPlacementOrigin;
3805 clientPlacementX = clientPlacementXOrigin;
3807 clientPlacementY += clientPlacementOffset;
3810 * Reset Y position to top of screen so that windows start new column of
3811 * placement that is offset from the previous column. Previously, the new
3812 * column was place right over the old column, obscuring it.
3813 * NOTE: column == diagonal
3816 if (clientPlacementY >= (screenHeight / 3))
3818 clientPlacementY = clientPlacementOrigin;
3822 } /* END OF FUNCTION FindClientPlacement */
3826 /*************************************<->*************************************
3828 * WmGetWindowAttributes (window)
3833 * This function gets window attributes if necessary and saves them in the
3834 * global window attribute cache. If the window attributes are already
3835 * there then no X call is made.
3840 * window = get attributes for window with this id
3845 * wmGD.attributesWindow = set to window that matches windowAttributes
3847 * wmGD.windowAttributes = XWindowAttributes of window
3852 * The attributes in the global cache are (known) current only for a
3853 * single pass through the wm event processing loop. They (should be)
3854 * regularly cleared.
3856 *************************************<->***********************************/
3859 WmGetWindowAttributes (Window window)
3861 if (wmGD.attributesWindow != window)
3863 if (!XGetWindowAttributes (DISPLAY, window, &wmGD.windowAttributes))
3866 * Cannot get window attributes.
3869 wmGD.attributesWindow = (Window)0L;
3872 wmGD.attributesWindow = window;
3877 } /* END OF FUNCTION WmGetWindowAttributes */
3881 /*************************************<->*************************************
3883 * SetupClientIconWindow (pCD, window)
3888 * This function prepares a client supplied icon window for insertion into
3889 * a window manager icon frame.
3894 * pCD = pointer to client data
3896 * window = client supplied icon window
3901 * pCD = (iconWindow)
3903 * Return = True if the icon window can be used
3905 *************************************<->***********************************/
3908 SetupClientIconWindow (ClientData *pCD, Window window)
3914 * Check to see if the icon window can be used (i.e there is no conflict
3918 if (!XFindContext (DISPLAY, window, wmGD.windowContextType,
3921 if (window == pCD->client)
3924 * The proposed icon window is the same as the client!
3931 * The proposed icon window is already being managed.
3932 * Assume that we managed it by mistake. Unmanage the
3933 * window and use it as the icon window for this client.
3936 UnManageWindow (pcd);
3939 /* update client data */
3940 pCD->iconWindow = window;
3942 /* put in window manager's save set */
3943 XChangeSaveSet (DISPLAY, pCD->iconWindow, SetModeInsert);
3944 pCD->clientFlags |= ICON_IN_SAVE_SET;
3948 } /* END OF FUNCTION SetupClientIconWindow */
3952 /*************************************<->*************************************
3954 * ProcessMwmHints (pCD)
3959 * Process the _MWM_HINTS property on the window (if any). Setup the
3960 * applicable function and decoration masks.
3965 * pCD = pointer to client data
3970 * pCD = may be changed.
3972 *************************************<->***********************************/
3975 ProcessMwmHints (ClientData *pCD)
3977 PropMwmHints *pHints;
3981 * Fix the client functions and decorations fields if they have
3982 * default resource values.
3985 if (pCD->clientFunctions & WM_FUNC_DEFAULT)
3987 if (pCD->clientFlags & CLIENT_TRANSIENT)
3989 pCD->clientFunctions = TRANSIENT_FUNCTIONS(pCD);
3993 pCD->clientFunctions = WM_FUNC_ALL;
3996 if (pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUBPANEL)
3998 pCD->clientFunctions &= WM_FUNC_SUBPANEL_DEFAULT;
3999 pCD->dtwmFunctions &= ~DtWM_FUNCTION_OCCUPY_WS;
4001 else if (pCD->dtwmBehaviors & DtWM_BEHAVIOR_PANEL)
4003 pCD->clientFunctions &= WM_FUNC_PANEL_DEFAULT;
4004 pCD->dtwmFunctions &= ~DtWM_FUNCTION_OCCUPY_WS;
4006 #endif /* PANELIST */
4009 if (pCD->clientDecoration & WM_DECOR_DEFAULT)
4011 if (pCD->clientFlags & CLIENT_TRANSIENT)
4013 pCD->clientDecoration = TRANSIENT_DECORATION(pCD);
4017 pCD->clientDecoration = WM_DECOR_ALL;
4020 if (pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUBPANEL)
4022 pCD->clientDecoration = pCD->pSD->subpanelDecoration;
4024 else if (pCD->dtwmBehaviors & DtWM_BEHAVIOR_PANEL)
4026 pCD->clientDecoration &= WM_DECOR_PANEL_DEFAULT;
4028 #endif /* PANELIST */
4033 * Retrieve the _MWM_HINTS property if it exists.
4036 pCD->inputMode = MWM_INPUT_MODELESS;
4038 if ((pHints = GetMwmHints (pCD)) != NULL)
4040 if (pHints->flags & MWM_HINTS_FUNCTIONS)
4042 if (pHints->functions & MWM_FUNC_ALL)
4044 /* client indicating inapplicable functions */
4045 pCD->clientFunctions &= ~(pHints->functions);
4049 /* client indicating applicable functions */
4050 pCD->clientFunctions &= pHints->functions;
4053 if (!(pCD->clientFlags & GOT_DT_WM_HINTS) &&
4057 * !!! Backward compatibility heurisitic !!!
4059 * If client doesn't want any functions and
4060 * no DT_WM_HINTS specified, then remove
4061 * workspace functions.
4063 pCD->dtwmFunctions &= ~DtWM_FUNCTION_OCCUPY_WS;
4066 /* !!! check for some minimal level of functionality? !!! */
4069 if (pHints->flags & MWM_HINTS_DECORATIONS)
4071 if (pHints->decorations & MWM_DECOR_ALL)
4073 /* client indicating decorations to be removed */
4074 pCD->clientDecoration &= ~(pHints->decorations);
4078 /* client indicating decorations to be added */
4079 pCD->clientDecoration &= pHints->decorations;
4083 * Fix up decoration configuration.
4086 if (pCD->clientDecoration &
4087 (MWM_DECOR_MENU | MWM_DECOR_MINIMIZE | MWM_DECOR_MAXIMIZE))
4089 pCD->clientDecoration |= MWM_DECOR_TITLE;
4091 if (pCD->clientDecoration & MWM_DECOR_RESIZEH)
4093 pCD->clientDecoration |= MWM_DECOR_BORDER;
4097 if (pHints->flags & MWM_HINTS_INPUT_MODE)
4099 if ((pHints->inputMode == MWM_INPUT_PRIMARY_APPLICATION_MODAL) ||
4100 (pHints->inputMode == MWM_INPUT_FULL_APPLICATION_MODAL) ||
4101 ((pHints->inputMode == MWM_INPUT_SYSTEM_MODAL) &&
4102 !wmGD.systemModalActive))
4105 pCD->inputMode = pHints->inputMode;
4110 * Don't allow a system modal window to be a secondary window
4111 * (except with respect to applicable functions and frame
4112 * decorations). Also, don't allow system modal window to
4116 if (pCD->inputMode == MWM_INPUT_SYSTEM_MODAL)
4118 pCD->transientLeader = NULL;
4119 if (pCD->clientFunctions & MWM_FUNC_MINIMIZE)
4121 pCD->clientFunctions &= ~(MWM_FUNC_MINIMIZE);
4126 if (pHints->flags & MWM_HINTS_STATUS)
4128 pCD->window_status = pHints->status;
4131 XFree ((char*)pHints);
4133 #ifndef NO_OL_COMPAT
4136 ProcessOLDecoration (pCD);
4138 #endif /* NO_OL_COMPAT */
4142 * If primary window can't move between workspaces, then
4143 * secondary window shouldn't either.
4145 if (pCD->transientLeader &&
4146 !(pCD->transientLeader->dtwmFunctions & DtWM_FUNCTION_OCCUPY_WS))
4148 pCD->dtwmFunctions &= ~DtWM_FUNCTION_OCCUPY_WS;
4153 * Fix up functions based on system modal settings. System modal
4154 * windows and their descendents cannot be minimized.
4157 if (!((FindTransientTreeLeader (pCD))->clientFunctions&MWM_FUNC_MINIMIZE))
4159 pCD->clientFunctions &= ~MWM_FUNC_MINIMIZE;
4164 * Fix up decoration configuration based on applicable functions.
4167 if (!(pCD->clientFunctions & MWM_FUNC_RESIZE))
4169 pCD->clientDecoration &= ~MWM_DECOR_RESIZEH;
4172 if (!(pCD->clientFunctions & MWM_FUNC_MINIMIZE))
4174 pCD->clientDecoration &= ~MWM_DECOR_MINIMIZE;
4177 if (!(pCD->clientFunctions & MWM_FUNC_MAXIMIZE))
4179 pCD->clientDecoration &= ~MWM_DECOR_MAXIMIZE;
4182 pCD->decor = pCD->clientDecoration; /* !!! combine decor ... !!! */
4185 } /* END OF ProcessMwmHints */