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"
73 #include "WmProperty.h"
74 #include "WmResource.h"
76 #include "WmWrkspace.h"
78 #include "WmWinList.h"
80 #include "WmPresence.h"
85 static void AdjustSlideOutGeometry (ClientData *pCD);
86 static void FixSubpanelEmbeddedClientGeometry (ClientData *pCD);
89 #ifndef NO_MESSAGE_CATALOG
90 # define LOCALE_MSG GETMESSAGE(70, 7, "[XmbTextPropertyToTextList]:\n Locale (%.100s) not supported. (Check $LANG).")
92 # define LOCALE_MSG "[XmbTextPropertyToTextList]:\n Locale (%.100s) not supported. (Check $LANG)."
99 WmWorkspaceData *pIconBoxInitialWS;
104 /*************************************<->*************************************
106 * GetClientInfo (pSD, clientWindow, manageFlags)
111 * This function is used to initialize client window data based on the
112 * contents of client window properties and the client window configuration.
117 * pSD = pointer to screen data for screen that client lives in
119 * clientWindow = window id for the client window that is to be managed
121 * manageFlags = flags that indicate wm state info
126 * Return = pointer to an initialized client data structure for the
127 * specified client window
129 *************************************<->***********************************/
132 GetClientInfo (WmScreenData *pSD, Window clientWindow, long manageFlags)
136 XSetWindowAttributes sAttributes;
140 * Allocate and initialize a client data structure:
143 if (!(pCD = (ClientData *)XtMalloc (sizeof (ClientData))))
145 /* unable to allocate space */
146 Warning (((char *)GETMESSAGE(70, 1, "Insufficient memory for client data")));
152 * Initialize the data structure:
155 pCD->client = clientWindow;
156 pCD->clientID = ++(pSD->clientCounter);
157 pCD->clientFlags = WM_INITIALIZATION;
160 pCD->pIconBox = NULL;
162 pCD->thisIconBox = NULL;
167 #endif /* PANELIST */
168 pCD->wmUnmapCount = 0;
169 pCD->transientFor = (Window)0L;
170 pCD->transientLeader = NULL;
171 pCD->transientChildren = NULL;
172 pCD->transientSiblings = NULL;
174 pCD->primaryStackPosition = 0;
176 pCD->fullModalCount = 0;
177 pCD->primaryModalCount = 0;
178 pCD->focusPriority = 0;
179 pCD->focusAutoRaiseDisabled = False;
180 pCD->focusAutoRaiseDisablePending = False;
182 pCD->clientClass = NULL;
183 pCD->clientName = NULL;
184 pCD->clientFrameWin = (Window)0L;
186 pCD->iconFrameWin = (Window)0L;
188 pCD->iconWindow = (Window)0L;
189 pCD->iconPixmap = (Pixmap)0L;
191 pCD->iconPlace = NO_ICON_PLACE;
193 pCD->clientProtocols = NULL;
194 pCD->clientProtocolCount = 0;
195 pCD->mwmMessages = NULL;
196 pCD->mwmMessagesCount = 0;
197 pCD->clientCmapCount = 0;
198 pCD->clientCmapIndex = 0;
199 pCD->clientCmapFlagsInitialized = FALSE;
200 pCD->systemMenuSpec = NULL;
202 pCD->putInAll = False;
203 pCD->pWorkspaceHints = NULL;
204 pCD->numInhabited = 0;
206 pCD->dtwmFunctions = DtWM_FUNCTION_OCCUPY_WS;
207 pCD->dtwmBehaviors = 0L;
208 pCD->paInitialProperties = NULL;
209 pCD->numInitialProperties = 0;
212 pCD->decorFlags = 0L;
213 pCD->pTitleGadgets = NULL;
214 pCD->cTitleGadgets = 0;
215 pCD->pResizeGadgets = NULL;
216 pCD->clientTitleWin = (Window)0L;
217 pCD->pclientTopShadows = NULL;
218 pCD->pclientBottomShadows = NULL;
219 pCD->pclientTitleTopShadows = NULL;
220 pCD->pclientTitleBottomShadows = NULL;
221 pCD->pclientMatteTopShadows = NULL;
222 pCD->pclientMatteBottomShadows = NULL;
223 pCD->piconTopShadows = NULL;
224 pCD->piconBottomShadows = NULL;
225 pCD->internalBevel = (wmGD.frameStyle == WmSLAB) ? 0 :
226 FRAME_INTERNAL_SHADOW_WIDTH;
228 pCD->bPseudoTransient = False;
229 #endif /* NO_OL_COMPAT */
231 pCD->maxWidth = pCD->maxWidthLimit = BIGSIZE;
232 pCD->maxHeight = pCD->maxHeightLimit = BIGSIZE;
233 pCD->maxConfig = FALSE;
235 pCD->dataType = CLIENT_DATA_TYPE;
236 pCD->window_status = 0L;
238 pCD->clientEntry.nextSibling = NULL;
239 pCD->clientEntry.prevSibling = NULL;
240 pCD->clientEntry.pCD = NULL;
242 pCD->smClientID = (String)NULL;
245 * Do special processing for client windows that are controlled by
246 * the window manager.
249 if (manageFlags & MANAGEW_WM_CLIENTS)
252 WmWorkspaceData *pWS;
254 if (manageFlags & MANAGEW_ICON_BOX)
256 pWS = pIconBoxInitialWS;
260 pWS = pSD->pActiveWS;
262 return (GetWmClientInfo (pWS, pCD, manageFlags));
264 return (GetWmClientInfo (pSD->pActiveWS, pCD, manageFlags));
270 * Register the client window to facilitate event handling:
273 XSaveContext (DISPLAY, clientWindow, wmGD.windowContextType, (caddr_t)pCD);
277 * Listen for property change events on the window so that we keep
278 * in sync with the hints.
280 sAttributes.event_mask = (PropertyChangeMask | ColormapChangeMask);
281 XChangeWindowAttributes (DISPLAY, pCD->client, CWEventMask,
285 * Get window configuration attributes. WmGetWindowAttributes sets
286 * up the global window attributes cache with the client window
290 if (!WmGetWindowAttributes (clientWindow))
293 * Cannot get window attributes. Do not manage window.
294 * (error message within WmGetWindowAttributes)
297 UnManageWindow (pCD);
300 pCD->xBorderWidth = wmGD.windowAttributes.border_width;
304 * Get the initial list of properties on this window.
305 * Save it to optimize subsequent property fetching.
307 GetInitialPropertyList (pCD);
311 * Retrieve and process WM_CLASS hints client window property info:
314 ProcessWmClass (pCD);
318 * Retrieve and process WM_TRANSIENT_FOR client window property info:
321 ProcessWmTransientFor (pCD);
324 * Get client window resource data (from resources, .mwmrc):
325 * Moved prior to GetClientWorkspaceInfo() because the
326 * ignoreWMSaveHints resource may affect that function.
329 ProcessClientResources (pCD);
332 * Retreive and process SM_CLIENT_ID client window property info
333 * and WMSAVE_HINT client window property info:
334 * must be done prior to calling GetClientWorkspaceInfo().
336 ProcessSmClientID (pCD);
337 ProcessWmSaveHint (pCD);
341 * Set client's workspace information. NOTE: this also may
342 * set the geometry, initial state, etc. For Sm-aware clients,
343 * this info will be in private DB; for older clients, it will
344 * be contained in the screen's pDtSessionItems.
346 if (!GetClientWorkspaceInfo (pCD, manageFlags))
348 XtFree ((char *)pCD);
353 * Restore client's per-workspace icon information.
355 LoadClientIconPositions(pCD);
358 * Retrieve and process _DT_WM_HINTS client window property
359 * (results are used in ProcessMwmHints)
361 ProcessDtWmHints (pCD);
365 * For Sm-aware clients, retrieve geometry and initial state
368 FindClientDBMatch(pCD, (char **)NULL);
373 * Retrieve and process M_CLIENT_DECOR client window property info:
376 ProcessMwmHints (pCD);
380 * Retrieve and process WM_HINTS client window property info:
383 ProcessWmHints (pCD, True /*first time*/);
387 * Set offset from frame of client window
390 SetClientOffset (pCD);
394 * Retrieve and process WM_NORMAL_HINTS client window property info:
398 ProcessWmNormalHints (pCD, True /*first time*/, manageFlags);
402 * Retrieve and process WM_NAME client window property info (this
403 * property contains the window title NOT the window resource name):
406 ProcessWmWindowTitle (pCD, TRUE);
410 * Retrieve and process WM_ICON_NAME client window property info:
413 ProcessWmIconTitle (pCD, TRUE);
417 * Retrieve and process the WM_PROTOCOLS property.
420 ProcessWmProtocols (pCD);
424 * If necessary retrieve and process the _MWM_MESSAGES property.
427 if (pCD->protocolFlags & PROTOCOL_MWM_MESSAGES)
429 ProcessMwmMessages (pCD);
434 * Make or find a system menu for the client.
439 MakeSystemMenu (pCD);
443 pCD->systemMenuSpec = NULL;
448 * Setup the colormap data for the client window. This includes
449 * retrieving and processing client window properties that deal with
450 * subwindow colormaps.
453 InitCColormapData (pCD);
456 /* successful return */
461 } /* END OF FUNCTION GetClientInfo */
465 /*************************************<->*************************************
467 * GetWmClientInfo (pWS, pCD, manageFlags)
472 * This function is used to initialize client window data for a window
473 * that is controlled by the window manager (e.g., the icon box). The
474 * client window may get made in the process.
479 * pWS = pointer to workspace data
481 * pCD = pointer to client window data structure
483 * manageFlags = flags that indicate wm state info
488 * Return = pointer to an initialized client data structure or NULL
489 * if the client data could not be initialized
491 *************************************<->***********************************/
493 GetWmClientInfo (WmWorkspaceData *pWS,
504 * Set up the client class and name for resource retrieval.
505 * Get client specific resource data (from resources, .mwmrc).
508 if (manageFlags & MANAGEW_ICON_BOX)
510 SetIconBoxInfo (pWS, pCD);
512 else if (manageFlags & MANAGEW_CONFIRM_BOX)
514 pCD->clientClass = WmCConfirmbox;
515 pCD->clientName = WmNconfirmbox;
516 pCD->iconImage = NULL;
517 pCD->useClientIcon = False;
518 pCD->focusAutoRaise = True;
519 pCD->internalBevel = (wmGD.frameStyle == WmSLAB) ? 0 :
520 FRAME_INTERNAL_SHADOW_WIDTH;
522 pCD->maximumClientSize.width = 0;
523 pCD->maximumClientSize.height = 0;
524 pCD->systemMenu = NULL;
529 * Set up transient for data.
532 if (manageFlags & MANAGEW_ICON_BOX)
538 * Set up WM_HINTS type information.
541 pCD->inputFocusModel = True;
542 pCD->clientState = NORMAL_STATE;
544 if (ICON_DECORATION(pCD) & ICON_IMAGE_PART)
546 if (manageFlags & MANAGEW_ICON_BOX)
548 pCD->clientFlags |= ICON_BOX;
551 if (!pCD->useClientIcon && pCD->iconImage)
554 * Make a client supplied icon image.
555 * Do not use the default icon image if iconImage is not found.
558 pCD->iconPixmap = MakeNamedIconPixmap (pCD, pCD->iconImage);
561 if (!pCD->iconPixmap)
564 * Use a built-in icon image for the window manager client.
565 * The image may differ from the default icon image, depending on
566 * the particular client (eg the iconbox).
569 if (manageFlags & MANAGEW_ICON_BOX)
572 * Make a default iconBox icon image.
575 iconBitmap = XCreateBitmapFromData (DISPLAY,
576 ROOT_FOR_CLIENT(pCD), (char *)iconBox_bits,
577 iconBox_width, iconBox_height);
579 pCD->iconPixmap = MakeIconPixmap (pCD,
580 iconBitmap, (Pixmap)0L,
581 iconBox_width, iconBox_height, 1);
589 * Allocate initial workspace ID list
592 if ((pCD->pWsList = (WsClientData *)
593 XtMalloc(pCD->pSD->numWorkspaces * sizeof(WsClientData))) == NULL)
595 Warning (((char *)GETMESSAGE(70, 2, "Insufficient memory for client data")));
598 pCD->sizeWsList = pCD->pSD->numWorkspaces;
599 for (i = 0; i < pCD->pSD->numWorkspaces; i++)
601 pCD->pWsList[i].wsID = 0L;
602 pCD->pWsList[i].iconPlace = NO_ICON_PLACE;
603 pCD->pWsList[i].iconX = 0;
604 pCD->pWsList[i].iconY = 0;
605 pCD->pWsList[i].iconFrameWin = (Window)0L;
606 pCD->pWsList[i].pIconBox = NULL;
609 * Internally managed clients must be specifically inserted
610 * into workspaces the first time by calling
611 * PutClientIntoWorkspace.
613 pCD->numInhabited = 0;
615 pCD->iconPlace = NO_ICON_PLACE;
619 pCD->windowGroup = 0L;
621 pCD->bPseudoTransient = False;
622 #endif /* NO_OL_COMPAT */
626 * Set up _MWM_HINTS data.
629 * Fix the client functions and decorations fields if they have
630 * default resource values.
634 if (manageFlags & MANAGEW_CONFIRM_BOX)
636 pCD->clientFunctions = WM_FUNC_NONE;
637 pCD->clientDecoration = WM_DECOR_BORDER;
641 if (pCD->clientFunctions & WM_FUNC_DEFAULT)
643 pCD->clientFunctions = WM_FUNC_ALL;
646 if (pCD->clientDecoration & WM_DECOR_DEFAULT)
648 pCD->clientDecoration = WM_DECOR_ALL;
651 if (manageFlags & MANAGEW_ICON_BOX)
653 pCD->clientFunctions &= ICON_BOX_FUNCTIONS;
655 pCD->dtwmFunctions &= ~DtWM_FUNCTION_OCCUPY_WS;
658 if (wmGD.useFrontPanel && pCD->pSD->iconBoxControl)
661 * If there's a front panel button for the icon
662 * box, then use it to "hide" the box on "close"
664 pCD->clientFunctions &= ~MWM_FUNC_MINIMIZE;
665 pCD->clientFunctions |= MWM_FUNC_CLOSE;
668 #endif /* PANELIST */
672 if (!(pCD->clientFunctions & MWM_FUNC_RESIZE))
674 pCD->clientDecoration &= ~MWM_DECOR_RESIZEH;
677 if (!(pCD->clientFunctions & MWM_FUNC_MINIMIZE))
679 pCD->clientDecoration &= ~MWM_DECOR_MINIMIZE;
682 if (!(pCD->clientFunctions & MWM_FUNC_MAXIMIZE))
684 pCD->clientDecoration &= ~MWM_DECOR_MAXIMIZE;
688 pCD->decor = pCD->clientDecoration;
690 if (manageFlags & MANAGEW_ICON_BOX)
692 pCD->inputMode = MWM_INPUT_MODELESS;
694 else if (manageFlags & MANAGEW_CONFIRM_BOX)
696 pCD->inputMode = MWM_INPUT_SYSTEM_MODAL;
700 * Set up WM_NORMAL_HINTS data.
703 pCD->icccVersion = ICCC_CURRENT;
704 pCD->sizeFlags = US_POSITION | US_SIZE;
707 * Any calls to create Window Manager clients should
708 * return with the values for the following fields set.
709 * If it fails, it should free any space allocated and
715 * pCD->clientHeight =
725 * pCD->oldMaxHeight =
727 * AND PROBABLY SHOULD SET
728 * pCD->client = THE_WINDOW_THE_FUNCTION_CREATES
731 pCD->windowGravity = NorthWestGravity;
734 * Create IconBox window
737 if (manageFlags & MANAGEW_ICON_BOX)
739 if (!MakeIconBox (pWS, pCD))
742 * May want a more verbose message here
745 Warning (((char *)GETMESSAGE(70, 3, "Couldn't make icon box")));
749 PutClientIntoWorkspace (pWS, pCD);
752 else if (manageFlags & MANAGEW_CONFIRM_BOX)
755 unsigned int cbWidth, cbHeight;
758 XGetGeometry (DISPLAY, pCD->client, &root,
759 &(pCD->clientX), &(pCD->clientY),
761 (unsigned int*)&(pCD->xBorderWidth), &depth);
763 pCD->clientWidth = cbWidth;
764 pCD->clientHeight = cbHeight;
765 pCD->minWidth = pCD->baseWidth = pCD->maxWidth = pCD->clientWidth;
766 pCD->minHeight = pCD->baseHeight = pCD->maxHeight = pCD->clientHeight;
767 pCD->oldMaxWidth = pCD->maxWidth;
768 pCD->oldMaxHeight = pCD->maxHeight;
771 pCD->clientFlags |= CONFIRM_BOX;
773 PutClientIntoWorkspace (ACTIVE_WS, pCD);
778 * Set offset from frame of client window (need client size information).
785 * Register the client window to facilitate event handling.
788 XSaveContext (DISPLAY, pCD->client, wmGD.windowContextType, (caddr_t)pCD);
792 * Set up WM_PROTOCOLS data.
795 pCD->clientProtocolCount = 0;
796 pCD->protocolFlags = 0;
800 * Make the system menu.
803 if (manageFlags & MANAGEW_ICON_BOX)
805 #if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
806 /** BEGIN FIX CR 6941 **/
807 MenuItem *iconBoxMenuItems, *lastItem;
809 /* This MenuSpec is not added to pSD->acceleratorMenuSpecs */
810 pCD->systemMenuSpec =
811 MAKE_MENU (PSD_FOR_CLIENT(pCD), pCD, pCD->systemMenu,
812 F_CONTEXT_WINDOW, F_CONTEXT_WINDOW|F_CONTEXT_ICON,
814 if (pCD->systemMenuSpec != (MenuSpec *) NULL)
816 pCD->systemMenuSpec = DuplicateMenuSpec(pCD->systemMenuSpec);
817 XtFree(pCD->systemMenuSpec->name);
818 pCD->systemMenuSpec->name = XtNewString("IconBoxMenu");
819 iconBoxMenuItems = GetIconBoxMenuItems (PSD_FOR_CLIENT(pCD));
821 /* Find the last menu item in the menu spec's list. */
822 for (lastItem = pCD->systemMenuSpec->menuItems;
823 lastItem->nextMenuItem != (MenuItem *) NULL;
824 lastItem = lastItem->nextMenuItem)
826 lastItem->nextMenuItem = iconBoxMenuItems;
828 /* Now recreate the menu widgets since we've appended the
829 icon box menu items */
830 DestroyMenuSpecWidgets(pCD->systemMenuSpec);
831 pCD->systemMenuSpec->menuWidget =
832 CreateMenuWidget (PSD_FOR_CLIENT(pCD), pCD, "IconBoxMenu",
833 PSD_FOR_CLIENT(pCD)->screenTopLevelW, TRUE,
834 pCD->systemMenuSpec, NULL);
836 /** END FIX CR 6941 **/
838 pCD->systemMenuSpec =
839 MAKE_MENU (PSD_FOR_CLIENT(pCD), pCD, pCD->systemMenu,
840 F_CONTEXT_WINDOW, F_CONTEXT_WINDOW|F_CONTEXT_ICON,
841 GetIconBoxMenuItems(PSD_FOR_CLIENT(pCD)),
843 #endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
849 * Setup the colormap data.
852 pCD->clientColormap = PSD_FOR_CLIENT(pCD)->workspaceColormap;
856 * Return the pointer to the client data.
862 } /* END OF FUNCTION GetWmClientInfo */
866 /*************************************<->*************************************
868 * ProcessWmClass (pCD)
873 * This function retrieves the contents of the WM_CLASS property on the
874 * cient window. The resource class and the resource name are saved in
875 * the ClientData structure (note that the space for the strings is
876 * allocated using Xmalloc).
881 * pCD - pointer to client data
890 *************************************<->***********************************/
893 ProcessWmClass (ClientData *pCD)
895 XClassHint classHint;
899 classHint.res_class = "";
900 classHint.res_name = "";
901 XGetClassHint (DISPLAY, pCD->client, &classHint);
904 if ((HasProperty (pCD, XA_WM_CLASS)) &&
905 (XGetClassHint (DISPLAY, pCD->client, &classHint)))
907 if (XGetClassHint (DISPLAY, pCD->client, &classHint))
911 /* the WM_CLASS property exists for the client window */
912 pCD->clientClass = classHint.res_class;
913 pCD->clientName = classHint.res_name;
915 /* else no WM_CLASS property; assume clientClass, clientName are NULL */
917 } /* END OF FUNCTION ProcessWmClass */
921 /*************************************<->*************************************
923 * ProcessSmClientID (pCD)
928 * This function retrieves the contents of the SM_CLIENT_ID property on the
929 * cient window. The value is saved in the ClientData structure
930 * (note that the space for the strings is allocated using Xmalloc).
935 * pCD - pointer to client data
944 *************************************<->***********************************/
947 ProcessSmClientID (ClientData *pCD)
951 unsigned long nitems, leftover;
954 if (pCD->smClientID != (String)NULL)
956 XFree(pCD->smClientID);
957 pCD->smClientID = (String)NULL;
960 if ((XGetWindowProperty(DISPLAY, pCD->client, wmGD.xa_SM_CLIENT_ID,
961 0L, (long)1000000, False, AnyPropertyType,
962 &actualType, &actualFormat, &nitems,
963 &leftover, (unsigned char **)&clientID)
965 (actualType != None) && (actualFormat == 8))
967 /* the SM_CLIENT_ID property exists for the client window */
968 pCD->smClientID = clientID;
971 } /* END OF FUNCTION ProcessSmClientID */
975 /*************************************<->*************************************
977 * ProcessWmSaveHint (pCD)
982 * This function retrieves the contents of the WMSAVE_HINT property on the
983 * cient window. The value is saved in the ClientData structure.
988 * pCD - pointer to client data
997 *************************************<->***********************************/
1000 ProcessWmSaveHint (ClientData *pCD)
1004 unsigned long nitems, leftover;
1005 BITS32 *saveHintFlags = (BITS32 *)NULL;
1007 if ((XGetWindowProperty(DISPLAY, pCD->client, wmGD.xa_WMSAVE_HINT,
1008 0L, (long)1000000, False, AnyPropertyType,
1009 &actualType, &actualFormat, &nitems,
1010 &leftover, (unsigned char **)&saveHintFlags)
1012 (actualType != None) && (actualFormat == 32))
1014 /* the WMSAVE_HINT property exists for the client window */
1015 pCD->wmSaveHintFlags = (int)*saveHintFlags;
1017 else pCD->wmSaveHintFlags = 0;
1020 XFree(saveHintFlags);
1022 } /* END OF FUNCTION ProcessWmSaveHint */
1025 /*************************************<->*************************************
1027 * ProcessWmHints (pCD, firstTime)
1032 * This function retrieves the contents of the WM_HINTS property on the
1038 * pCD = pointer to client data for the window with the property
1040 * firstTime = if True this is the first time the property has been processed
1045 * pCD = initialize various WM_HINTS related fields
1051 *************************************<->***********************************/
1054 ProcessWmHints (ClientData *pCD, Boolean firstTime)
1056 register XWMHints *pXWMHints;
1057 register long flags;
1061 WmWorkspaceData *pWsTmp;
1065 int tmpIconX, tmpIconY;
1069 * If the WM_HINTS property does not exist the flags field will be
1070 * set to 0. If flags is 0 don't reference the WMHints structure
1071 * since they may be none.
1075 if (firstTime && !HasProperty (pCD, XA_WM_HINTS))
1079 pXWMHints = XGetWMHints (DISPLAY, pCD->client);
1083 flags = pXWMHints->flags;
1092 * Parse the WM_HINTS information. If this is the first time the hints
1093 * have been processed then parse all fields and set defaults where hint
1094 * fields are not set. If this is not the first time do selective
1100 #ifndef NO_OL_COMPAT
1103 unsigned int numIDs = 0;
1106 * Save the window group.
1109 if (flags & WindowGroupHint)
1111 pCD->windowGroup = pXWMHints->window_group;
1113 * Pretend this is a transient window
1115 if ((pCD->bPseudoTransient) &&
1116 (pCD->transientFor == (Window)0L))
1118 pCD->clientFlags |= CLIENT_TRANSIENT;
1121 * Treat this like a transient window. This is transient
1122 * for the window group window.
1125 if ((pCD->client != pCD->windowGroup) &&
1126 !XFindContext (DISPLAY, pCD->windowGroup,
1127 wmGD.windowContextType, (caddr_t *)&leader))
1129 pCD->transientFor = pCD->windowGroup;
1130 pCD->transientLeader = leader;
1133 * Insure it is in the same set of workspaces
1136 if (pCD->transientLeader &&
1137 GetLeaderPresence(pCD, &pIDs, &numIDs))
1139 ProcessWorkspaceHintList (pCD, pIDs, numIDs);
1146 pCD->windowGroup = 0L;
1148 #endif /* NO_OL_COMPAT */
1150 * The window manger does not do anything with the input hint. Input
1151 * always goes to the selected window.
1154 if (flags & InputHint)
1156 pCD->inputFocusModel = pXWMHints->input;
1160 pCD->inputFocusModel = True;
1165 * The default state is NORMAL_STATE. States other than iconic
1166 * (e.g., ZoomState from the R2 ICCC) indicate to the window manager
1167 * that the NORMAL_STATE is to be used.
1170 if (pCD->clientFlags & SM_CLIENT_STATE)
1172 if ((pCD->clientState == MINIMIZED_STATE) &&
1173 (!(pCD->clientFunctions & MWM_FUNC_MINIMIZE)))
1175 pCD->clientState = NORMAL_STATE;
1179 if ((flags & StateHint) && (pXWMHints->initial_state == IconicState) &&
1180 (pCD->clientFunctions & MWM_FUNC_MINIMIZE))
1182 pCD->clientState = MINIMIZED_STATE;
1187 * States other than iconic are treated as normal.
1189 pCD->clientState = NORMAL_STATE;
1194 if (!ClientInWorkspace (PSD_FOR_CLIENT(pCD)->pActiveWS, pCD))
1196 pCD->clientState |= UNSEEN_STATE;
1202 * If an icon is to be made for the client then ...
1203 * save the icon image if useClientIcon is True or there is no
1204 * user specified icon image. A client supplied image may be a
1205 * pixmap or a window (a client icon window takes precedence over
1209 if ((pCD->clientFunctions & MWM_FUNC_MINIMIZE) &&
1210 (pCD->transientLeader == NULL))
1212 if ((ICON_DECORATION(pCD) & ICON_IMAGE_PART) &&
1213 (pCD->useClientIcon || !pCD->iconImage))
1215 if ((flags & IconWindowHint) &&
1216 (pXWMHints->icon_window != pCD->client))
1219 * An icon window has been supplied that is different from
1220 * the client window. Check out the window and get it
1221 * ready to be reparented to the window manager supplied
1225 if (!SetupClientIconWindow (pCD, pXWMHints->icon_window))
1228 * Cannot use the client supplied icon window. Use
1229 * an icon image if specified or a default image.
1233 if (!pCD->iconWindow && (flags & IconPixmapHint))
1235 iconMask = (flags & IconMaskHint) ?
1236 pXWMHints->icon_mask : (Pixmap) NULL;
1238 * A client supplied icon window is NOT
1239 * available so use the client supplied icon image.
1242 if ((pCD->iconPixmap =
1243 MakeClientIconPixmap (pCD,
1244 pXWMHints->icon_pixmap, iconMask)) != None)
1247 * Indicate that a client supplied icon image is being
1251 pCD->iconFlags |= ICON_HINTS_PIXMAP;
1256 * Cannot make a client supplied image. Use a user
1257 * specified icon image if it is available or a default
1264 if ((ICON_DECORATION(pCD) & ICON_IMAGE_PART) && !pCD->iconPixmap)
1267 * Use a user supplied icon image if it is available or a
1268 * default icon image.
1274 * Try to make a user specified icon image.
1278 MakeNamedIconPixmap (pCD, pCD->iconImage);
1281 if (!pCD->iconPixmap)
1284 * The icon image was not provided or not available.
1285 * Use the default icon image.
1288 pCD->iconPixmap = MakeNamedIconPixmap (pCD, NULL);
1294 * Save the client (user?) supplied icon position:
1297 if ((flags & IconPositionHint) ||
1298 (pCD->clientFlags & (SM_ICON_X | SM_ICON_Y)))
1300 pCD->iconFlags |= ICON_HINTS_POSITION;
1301 if (wmGD.iconAutoPlace)
1305 * Initialize icon placement data in all inhabited
1308 for (iws = 0; iws< pCD->numInhabited; iws++)
1310 pWsc = &(pCD->pWsList[iws]);
1311 if ((pWsTmp=GetWorkspaceData(pCD->pSD, pWsc->wsID)))
1313 tmpIconX = (pCD->clientFlags & SM_ICON_X) ?
1314 pWsc->iconX : pXWMHints->icon_x;
1315 tmpIconY = (pCD->clientFlags & SM_ICON_Y) ?
1316 pWsc->iconY : pXWMHints->icon_y;
1318 FindIconPlace (pCD, &(pWsTmp->IPData),
1319 tmpIconX, tmpIconY);
1320 if (pWsc->iconPlace != NO_ICON_PLACE)
1322 CvtIconPlaceToPosition ( &(pWsTmp->IPData),
1332 for (iws = 0; iws< pCD->numInhabited; iws++)
1334 pWsc = &(pCD->pWsList[iws]);
1335 if ((pWsTmp=GetWorkspaceData(pCD->pSD, pWsc->wsID)))
1337 if (!(pCD->clientFlags & SM_ICON_X))
1338 pWsc->iconX = pXWMHints->icon_x;
1339 if (!(pCD->clientFlags & SM_ICON_Y))
1340 pWsc->iconY = pXWMHints->icon_y;
1346 tmpIconX = (pCD->clientFlags & SM_ICON_X) ?
1347 pCD->iconX : pXWMHints->icon_x;
1348 tmpIconY = (pCD->clientFlags & SM_ICON_Y) ?
1349 pCD->iconY : pXWMHints->icon_y;
1351 FindIconPlace (pCD, &(pCD->pSD->pActiveWS->IPData),
1352 tmpIconX, tmpIconY);
1353 if (pCD->iconPlace != NO_ICON_PLACE)
1355 CvtIconPlaceToPosition (&(pCD->pSD->pActiveWS->IPData),
1356 pCD->iconPlace, &pCD->iconX, &pCD->iconY);
1361 if (!(pCD->clientFlags & SM_ICON_X))
1362 pCD->iconX = pXWMHints->icon_x;
1363 if (!(pCD->clientFlags & SM_ICON_Y))
1364 pCD->iconY = pXWMHints->icon_y;
1370 if (wmGD.iconAutoPlace)
1374 * Initialize icon placement data in all inhabited
1377 for (iws = 0; iws< pCD->numInhabited; iws++)
1379 pWsc = &(pCD->pWsList[iws]);
1380 pWsc->iconPlace = NO_ICON_PLACE;
1385 pCD->iconPlace = NO_ICON_PLACE;
1395 * Save the window group.
1398 if (flags & WindowGroupHint)
1400 pCD->windowGroup = pXWMHints->window_group;
1404 pCD->windowGroup = 0L;
1406 #endif /* NO_OL_COMPAT */
1408 else /* not the first time the hints are processed */
1410 if (flags & IconPixmapHint)
1413 * Process an icon image change if the icon image was initially
1414 * set up with a client supplied icon image OR, if the client
1415 * now wants to supply an image.
1417 iconMask = (flags & IconMaskHint)?
1418 pXWMHints->icon_mask : (Pixmap) NULL;
1421 MakeClientIconPixmap (pCD, pXWMHints->icon_pixmap,
1425 * Made new icon image; free up the old image and display
1428 if (pCD->iconFlags & ICON_HINTS_PIXMAP)
1431 * ICON_HINTS_PIXMAP was set either initally or
1432 * below because a new pixmap was made for the client.
1433 * It is now safe to free the previous pixmap since it
1434 * is not the shared default iconPixmap
1436 if (pCD->iconPixmap)
1438 XFreePixmap (DISPLAY, pCD->iconPixmap);
1443 pCD->iconFlags |= ICON_HINTS_PIXMAP;
1446 pCD->iconPixmap = iconPixmap;
1449 * Display new icon image if the icon is showing:
1452 if (((pCD->clientState == MINIMIZED_STATE) ||
1453 ((pCD->pSD->useIconBox) && (P_ICON_BOX(pCD)))) &&
1454 ICON_FRAME_WIN(pCD))
1456 IconExposureProc (pCD, True);
1464 XFree ((char*)pXWMHints);
1468 } /* END OF FUNCTION ProcessWmHints */
1472 /*************************************<->*************************************
1474 * ProcessWmNormalHints (pCD, firstTime, manageFlags)
1479 * This function retrieves the contents of the WM_NORMAL_HINTS property on
1480 * the cient window. There are several versions of the property that must be
1481 * handled (currently R2 and CURRENT).
1486 * pCD = pointer to client data for the window with the property
1488 * firstTime = if True this is the first time the property has been processed
1490 * manageFlags = flags that indicate wm state information
1495 * pCD = client location and size fields set
1500 * If the hints are being reprocessed (!firstTime) the configuration values
1501 * will be ignored. The size constraint values will be processed but the
1502 * client configuration will not be changed even if it is not in line with
1503 * the new values. Reconfigurations subsequent to the hints changes will
1504 * be done with the new constraints.
1506 *************************************<->***********************************/
1509 ProcessWmNormalHints (ClientData *pCD, Boolean firstTime, long manageFlags)
1511 register SizeHints *pNormalHints;
1512 register long flags;
1514 unsigned long decoration;
1515 unsigned int boxdim, tmpMin;
1516 unsigned int oldWidthInc, oldHeightInc;
1517 unsigned int oldBaseWidth, oldBaseHeight;
1518 unsigned int incWidth, incHeight;
1521 * Use a custom verion of the Xlib routine to get WM_NORMAL_HINTS.
1522 * A custom version is necessary to handle the different versions
1523 * of WM_NORMAL_HINTS that may be encountered. If the WM_NORMAL_HINTS
1524 * property does not exist the flags field will be set to 0.
1527 pNormalHints = GetNormalHints (pCD);
1529 pCD->icccVersion = pNormalHints->icccVersion;
1533 * Parse the WM_NORMAL_HINTS information:
1536 if (((flags = pNormalHints->flags) == 0) && !firstTime)
1543 * Process the size only if this is the first time the hints are
1544 * being processed for the window.
1550 * Process client window size flags and information:
1553 pCD->sizeFlags = flags & (US_POSITION | US_SIZE | P_POSITION | P_SIZE);
1556 * The R2 conventions and Xlib manual indicate that the window size
1557 * and position should be taken out of the WM_NORMAL_HINTS property
1558 * if they are specified there. The current conventions indicate that
1559 * the size and position information should be gotten from the window
1560 * configuration. Mwm 1.1 always uses the current conventions.
1565 * Maintain R2 compatiblity code for CND product xnm
1567 if ((pNormalHints->icccVersion == ICCC_R2) &&
1568 (flags & (US_POSITION | P_POSITION)) &&
1569 !(manageFlags & MANAGEW_WM_RESTART))
1571 if (!(pCD->clientFlags & SM_X))
1572 pCD->clientX = pNormalHints->x;
1573 if (!(pCD->clientFlags & SM_Y))
1574 pCD->clientY = pNormalHints->y;
1578 if (!(pCD->clientFlags & SM_X))
1579 pCD->clientX = wmGD.windowAttributes.x;
1580 if (!(pCD->clientFlags & SM_Y))
1581 pCD->clientY = wmGD.windowAttributes.y;
1583 #else /* R2_COMPAT */
1584 if (!(pCD->clientFlags & SM_X))
1585 pCD->clientX = wmGD.windowAttributes.x;
1586 if (!(pCD->clientFlags & SM_Y))
1587 pCD->clientY = wmGD.windowAttributes.y;
1588 #endif /* R2_COMPAT */
1591 * Use current conventions for initial window dimensions.
1596 * Maintain R2 compatiblity code for CND product xnm
1598 if ((pNormalHints->icccVersion == ICCC_R2) &&
1599 (flags & (US_SIZE | P_SIZE)) &&
1600 !(manageFlags & MANAGEW_WM_RESTART))
1602 if (!(pCD->clientFlags & SM_WIDTH))
1603 pCD->clientWidth = pNormalHints->width;
1604 if (!(pCD->clientFlags & SM_HEIGHT))
1605 pCD->clientHeight = pNormalHints->height;
1609 if (!(pCD->clientFlags & SM_WIDTH))
1610 pCD->clientWidth = wmGD.windowAttributes.width;
1611 if (!(pCD->clientFlags & SM_HEIGHT))
1612 pCD->clientHeight = wmGD.windowAttributes.height;
1614 #else /* R2_COMPAT */
1615 if (!(pCD->clientFlags & SM_WIDTH))
1616 pCD->clientWidth = wmGD.windowAttributes.width;
1617 if (!(pCD->clientFlags & SM_HEIGHT))
1618 pCD->clientHeight = wmGD.windowAttributes.height;
1619 #endif /* R2_COMPAT */
1623 * Process the minimum size:
1626 if (flags & P_MIN_SIZE)
1629 (pNormalHints->min_width < 0) ? 0 : pNormalHints->min_width;
1631 (pNormalHints->min_height < 0) ? 0 : pNormalHints->min_height;
1632 if (pCD->minWidth > MAX_MAX_SIZE(pCD).width)
1634 pCD->minWidth = MAX_MAX_SIZE(pCD).width;
1636 if (pCD->minHeight > MAX_MAX_SIZE(pCD).height)
1638 pCD->minHeight = MAX_MAX_SIZE(pCD).height;
1649 * Process the resizing increments:
1654 oldWidthInc = (pCD->widthInc == 0) ? 1 : pCD->widthInc;
1655 oldHeightInc = (pCD->heightInc == 0) ? 1 : pCD->heightInc;
1658 if (flags & P_RESIZE_INC)
1661 (pNormalHints->width_inc < 1) ? 1 : pNormalHints->width_inc;
1663 (pNormalHints->height_inc < 1) ? 1 : pNormalHints->height_inc;
1673 * Process the base size:
1678 oldBaseWidth = pCD->baseWidth;
1679 oldBaseHeight = pCD->baseHeight;
1682 if (flags & P_BASE_SIZE)
1685 (pNormalHints->base_width < 0) ? 0 : pNormalHints->base_width;
1687 (pNormalHints->base_height < 0) ? 0 : pNormalHints->base_height;
1689 else if ((pNormalHints->icccVersion == ICCC_R2) &&
1691 (!firstTime && (flags & P_MIN_SIZE))))
1694 * In this version of the hints the minimum size was effectively
1697 pCD->baseWidth = pCD->minWidth;
1698 pCD->baseHeight = pCD->minHeight;
1702 if (flags & P_MIN_SIZE)
1704 pCD->baseWidth = pCD->minWidth;
1705 pCD->baseHeight = pCD->minHeight;
1710 pCD->baseHeight = 0;
1716 if (pCD->clientFlags & SM_WIDTH)
1718 pCD->clientWidth = ((pCD->clientWidth * pCD->widthInc) +
1721 if (pCD->clientFlags & SM_HEIGHT)
1723 pCD->clientHeight =((pCD->clientHeight * pCD->heightInc) +
1729 * Process the maximum width. NOTE: maximumClientSize.width
1730 * and maximumClientSize.height will be set to BIGSIZE if
1731 * maximumClientSize is either set to 'horizontal' or 'vertical'.
1734 pCD->oldMaxWidth = pCD->maxWidth;
1735 if (pCD->maximumClientSize.width)
1737 /* If maximumClientSize is full 'horizontal' */
1738 if (IS_MAXIMIZE_HORIZONTAL(pCD))
1740 /* go to min (full screen width, max maximum width) */
1741 pCD->maxWidth = DisplayWidth (DISPLAY, SCREEN_FOR_CLIENT(pCD)) -
1742 (2 * pCD->clientOffset.x);
1745 * Hack to set max client to the current client height, maxHeight
1746 * will be kept up to date whenever the window is reconfigured
1748 pCD->maxHeight = pCD->clientHeight;
1753 pCD->maxWidth = (pCD->maximumClientSize.width *
1754 pCD->widthInc) + pCD->baseWidth;
1759 if (flags & P_MAX_SIZE)
1761 if (pNormalHints->max_width < 0)
1763 /* go to min (full screen width, max maximum width) */
1764 pCD->maxWidth = DisplayWidth (DISPLAY, SCREEN_FOR_CLIENT(pCD)) -
1765 (2 * pCD->clientOffset.x);
1769 pCD->maxWidth = pNormalHints->max_width;
1772 /* Don't reset maxWidth if it has been set earlier */
1773 else if (!IS_MAXIMIZE_VERTICAL(pCD))
1777 /* go to min (full screen width, max maximum width) */
1778 pCD->maxWidth = DisplayWidth (DISPLAY,
1779 SCREEN_FOR_CLIENT(pCD)) -
1780 (2 * pCD->clientOffset.x);
1784 /* reset the maxHeight before further processing */
1785 pCD->maxWidth = pCD->maxWidthLimit;
1791 * If the hints changed we need to adjust the maximum
1792 * size (if not specified in the hints).
1795 ((oldBaseWidth != pCD->baseWidth) ||
1796 (oldWidthInc != pCD->widthInc)))
1798 incWidth = (pCD->maxWidth - oldBaseWidth) / oldWidthInc;
1800 (incWidth * pCD->widthInc) + pCD->baseWidth;
1804 /* reset the maxHeight before further processing */
1805 pCD->maxWidth = pCD->maxWidthLimit;
1808 if (pCD->maxWidth > MAX_MAX_SIZE(pCD).width)
1810 pCD->maxWidth = MAX_MAX_SIZE(pCD).width;
1817 * Process the maximum height.
1820 pCD->oldMaxHeight = pCD->maxHeight;
1821 if (pCD->maximumClientSize.height)
1823 /* If maximumClientSize is full 'vertical' */
1824 if (IS_MAXIMIZE_VERTICAL(pCD))
1826 /* go to min (full screen height, max maximum height) */
1827 pCD->maxHeight = DisplayHeight (DISPLAY, SCREEN_FOR_CLIENT(pCD)) -
1828 (pCD->clientOffset.x +
1829 pCD->clientOffset.y);
1831 * Hack to set max client to the current client width, maxWidth
1832 * will be kept up to date whenever the window is reconfigured
1834 pCD->maxWidth = pCD->clientWidth;
1839 pCD->maxHeight = (pCD->maximumClientSize.height *
1840 pCD->heightInc) + pCD->baseHeight;
1845 if (flags & P_MAX_SIZE)
1847 if (pNormalHints->max_height < 0)
1849 /* go to min (full screen height, max maximum height) */
1850 pCD->maxHeight = DisplayHeight (
1851 DISPLAY, SCREEN_FOR_CLIENT(pCD)) -
1852 (pCD->clientOffset.x +
1853 pCD->clientOffset.y);
1857 pCD->maxHeight = pNormalHints->max_height;
1860 /* Don't reset maxHeight if it has been set above */
1861 else if (!IS_MAXIMIZE_HORIZONTAL(pCD))
1865 /* go to min (full screen height, max maximum height) */
1866 pCD->maxHeight = DisplayHeight (DISPLAY,
1867 SCREEN_FOR_CLIENT(pCD)) -
1868 (pCD->clientOffset.x +
1869 pCD->clientOffset.y);
1873 /* reset the maxHeight before further processing */
1874 pCD->maxHeight = pCD->maxHeightLimit;
1880 * If the hints changed we need to adjust the maximum
1881 * size (if not specified in the hints).
1884 ((oldBaseHeight != pCD->baseHeight) ||
1885 (oldHeightInc != pCD->heightInc)))
1887 incHeight = (pCD->maxHeight - oldBaseHeight) / oldHeightInc;
1889 (incHeight * pCD->heightInc) + pCD->baseHeight;
1893 /* reset the maxHeight before further processing */
1894 pCD->maxHeight = pCD->maxHeightLimit;
1897 if (pCD->maxHeight > MAX_MAX_SIZE(pCD).height)
1899 pCD->maxHeight = MAX_MAX_SIZE(pCD).height;
1904 * Make sure not to exceed the maximumMaximumSize (width and height)
1907 if (pCD->maxWidth > MAX_MAX_SIZE(pCD).width)
1909 pCD->maxWidth = MAX_MAX_SIZE(pCD).width;
1912 if (pCD->maxHeight > MAX_MAX_SIZE(pCD).height)
1914 pCD->maxHeight = MAX_MAX_SIZE(pCD).height;
1918 * Get the initial aspect ratios, if available. Only use them if:
1922 * 0 <= minAspect.x / minAspect.y <= maxAspect.x / maxAspect.y
1925 if (flags & P_ASPECT)
1927 pCD->minAspect.x = pNormalHints->min_aspect.x;
1928 pCD->minAspect.y = pNormalHints->min_aspect.y;
1929 pCD->maxAspect.x = pNormalHints->max_aspect.x;
1930 pCD->maxAspect.y = pNormalHints->max_aspect.y;
1932 if (pCD->minAspect.y > 0 &&
1933 pCD->maxAspect.y > 0 &&
1934 pCD->minAspect.x > 0 &&
1935 pCD->maxAspect.x > 0 &&
1936 (pCD->minAspect.x * pCD->maxAspect.y <=
1937 pCD->maxAspect.x * pCD->minAspect.y))
1939 pCD->sizeFlags |= P_ASPECT;
1943 pCD->sizeFlags &= ~P_ASPECT;
1947 /* compute for minimum frame size */
1948 if ((decoration = pCD->decor) & MWM_DECOR_TITLE)
1950 boxdim = TitleBarHeight(pCD);
1952 ((decoration & MWM_DECOR_MENU) ? boxdim : 0) +
1953 ((decoration & MWM_DECOR_MINIMIZE) ? boxdim : 0) +
1954 ((decoration & MWM_DECOR_MAXIMIZE) ? boxdim : 0) -
1955 2*(pCD->matteWidth);
1963 * Process the window gravity (for positioning):
1966 if (flags & P_WIN_GRAVITY)
1968 pCD->windowGravity = pNormalHints->win_gravity;
1972 if (pNormalHints->icccVersion == ICCC_R2)
1974 pCD->windowGravity = wmGD.windowAttributes.win_gravity;
1978 pCD->windowGravity = NorthWestGravity;
1984 * Make sure that all the window sizing constraints are compatible:
1990 * minWidth >= tmpMin
1991 * minWidth >= max (baseWidth, widthInc) > 0
1992 * & an integral number of widthInc from baseWidth.
1993 * minHeight >= max (baseHeight, heightInc) > 0
1994 * & an integral number of heightInc from baseHeight.
1997 if (pCD->minWidth < tmpMin)
1999 if ((diff = ((tmpMin - pCD->baseWidth)%pCD->widthInc)) != 0)
2001 pCD->minWidth = tmpMin + pCD->widthInc - diff;
2005 pCD->minWidth = tmpMin;
2009 if (pCD->minWidth < pCD->baseWidth)
2011 pCD->minWidth = pCD->baseWidth;
2014 if (pCD->minWidth == 0)
2016 pCD->minWidth = pCD->widthInc;
2018 else if ((diff = ((pCD->minWidth - pCD->baseWidth)%pCD->widthInc)) != 0)
2020 pCD->minWidth += pCD->widthInc - diff;
2023 if (pCD->minHeight < pCD->baseHeight)
2025 pCD->minHeight = pCD->baseHeight;
2028 if (pCD->minHeight == 0)
2030 pCD->minHeight = pCD->heightInc;
2032 else if ((diff = ((pCD->minHeight - pCD->baseHeight) % pCD->heightInc)) !=0)
2034 pCD->minHeight += pCD->heightInc - diff;
2040 * maxWidth >= minWidth
2041 * & an integral number of widthInc from baseWidth.
2042 * maxHeight >= minHeight
2043 * & an integral number of heightInc from baseHeight.
2046 if (pCD->maxWidth < pCD->minWidth)
2048 pCD->maxWidth = pCD->minWidth;
2052 * Hack to use maxWidthLimit as the real maxWidth when maximumClientSize
2053 * set to 'vertical'.
2055 if (IS_MAXIMIZE_VERTICAL(pCD))
2057 /* go to min (full screen width, max maximum width) */
2058 pCD->maxWidthLimit = DisplayWidth (DISPLAY, SCREEN_FOR_CLIENT(pCD)) -
2059 (2 * pCD->clientOffset.x);
2063 pCD->maxWidthLimit = pCD->maxWidth;
2066 pCD->maxWidth -= ((pCD->maxWidth - pCD->baseWidth) % pCD->widthInc);
2070 pCD->oldMaxWidth = pCD->maxWidth;
2073 if (pCD->maxHeight < pCD->minHeight)
2075 pCD->maxHeight = pCD->minHeight;
2079 * Hack to use maxHeightLimit as the real maxHeight when maximumClientSize
2080 * set to 'horizontal'.
2082 if (IS_MAXIMIZE_HORIZONTAL(pCD))
2084 /* go to min (full screen height, max maximum height) */
2085 pCD->maxHeightLimit = DisplayHeight (DISPLAY, SCREEN_FOR_CLIENT(pCD)) -
2086 (pCD->clientOffset.x +
2087 pCD->clientOffset.y);
2091 pCD->maxHeightLimit = pCD->maxHeight;
2094 pCD->maxHeight -= ((pCD->maxHeight - pCD->baseHeight) % pCD->heightInc);
2098 pCD->oldMaxHeight = pCD->maxHeight;
2101 if (!firstTime && pCD->maxConfig)
2104 * If the hints changed while we were maximized then
2105 * we may need to adjust the normalized size of the window.
2108 ((oldBaseWidth != pCD->baseWidth) ||
2109 (oldBaseHeight != pCD->baseHeight) ||
2110 (oldWidthInc != pCD->widthInc) ||
2111 (oldHeightInc != pCD->heightInc)))
2113 incWidth = (pCD->clientWidth - oldBaseWidth) / oldWidthInc;
2114 incHeight = (pCD->clientHeight - oldBaseHeight) / oldHeightInc;
2116 (incWidth * pCD->widthInc) + pCD->baseWidth;
2118 (incHeight * pCD->heightInc) + pCD->baseHeight;
2123 * If using aspect ratios, make:
2125 * minWidth / maxHeight <= minAspect.x / minAspect.y
2126 * <= maxAspect.x / maxAspect.y
2127 * <= maxWidth / minHeight
2130 if (pCD->sizeFlags & P_ASPECT)
2132 if (pCD->minWidth * pCD->minAspect.y >
2133 pCD->minAspect.x * pCD->maxHeight)
2135 pCD->minAspect.x = pCD->minWidth;
2136 pCD->minAspect.y = pCD->maxHeight;
2139 if (pCD->maxAspect.x * pCD->minHeight >
2140 pCD->maxWidth * pCD->maxAspect.y)
2142 pCD->maxAspect.x = pCD->maxWidth;
2143 pCD->maxAspect.y = pCD->minHeight;
2146 FixWindowSize (pCD, (unsigned int *) &(pCD->maxWidth),
2147 (unsigned int *) &(pCD->maxHeight),
2148 (unsigned int) (pCD->widthInc),
2149 (unsigned int) (pCD->heightInc));
2153 * If this is the first time, make sure the client dimensions are within
2154 * range and that they satisfy any aspect ratio constraints:
2156 * 0 < minWidth <= clientWidth <= maxWidth
2157 * 0 < minHeight <= clientHeight <= maxHeight
2159 * minAspect.x / minAspect.y <= clientWidth / clientHeight
2160 * <= maxAspect.x / maxAspect.y
2162 * Initial max width/height are set to max of max size or normal
2163 * client size unless a maximumClientSize was specified.
2168 if (!pCD->maximumClientSize.width)
2170 if (pCD->clientWidth > pCD->pSD->maximumMaximumSize.width)
2172 pCD->clientWidth = pCD->pSD->maximumMaximumSize.width;
2176 if (!pCD->maximumClientSize.height)
2178 if (pCD->clientHeight > pCD->pSD->maximumMaximumSize.height)
2180 pCD->clientHeight = pCD->pSD->maximumMaximumSize.height;
2184 FixWindowSize (pCD, (unsigned int *) &(pCD->clientWidth),
2185 (unsigned int *) &(pCD->clientHeight),
2186 (unsigned int) (pCD->widthInc),
2187 (unsigned int) (pCD->heightInc));
2190 } /* END OF FUNCTION ProcessWmNormalHints */
2193 /*************************************<->*************************************
2195 * WmICCCMToXmString (wmNameProp)
2200 * This function uses a property (WM_NAME or WM_ICON_NAME) that was
2201 * retrieved from the window, and converts it to XmString.
2205 * wmNameProp - the text property
2209 * Return = new XmString, or NULL if the property didn't have a value.
2211 *************************************<->***********************************/
2214 WmICCCMToXmString (XTextProperty *wmNameProp)
2217 XmString xms_return;
2218 XmStringTable xmsTable;
2219 int i, nStrings = -1;
2222 if (wmNameProp->value == 0 || strlen((char *)wmNameProp->value) == 0)
2224 return (XmString)NULL;
2227 if (((status = XmCvtTextPropertyToXmStringTable(DISPLAY, wmNameProp,
2228 &xmsTable, &nStrings))
2229 != Success) || (nStrings <= 0))
2233 case XConverterNotFound:
2234 #ifndef MOTIF_ONE_DOT_ONE
2235 sprintf(msg, GETMESSAGE (70,5,
2236 "Window manager cannot convert property %.100s as clientTitle/iconTitle: XmbTextPropertyToTextList"),
2237 XGetAtomName (DISPLAY,wmNameProp->encoding));
2239 #endif /* MOTIF_ONE_DOT_ONE */
2243 sprintf(msg, GETMESSAGE (70, 6,
2244 "insufficient memory to convert property %.100s as clientTitle/iconTitle: XmbTextPropertyToTextList"),
2245 XGetAtomName(DISPLAY,wmNameProp->encoding));
2249 case XLocaleNotSupported:
2250 if ((wmNameProp->encoding == XA_STRING) ||
2251 (wmNameProp->encoding == wmGD.xa_COMPOUND_TEXT))
2253 sprintf(msg, LOCALE_MSG, setlocale(LC_ALL, NULL));
2257 /* Atom was neither STRING nor COMPOUND_TEXT */
2258 sprintf(msg, GETMESSAGE(70, 8,
2259 "Window manager received unknown property as clientTitle/iconTitle: %.100s. Property ignored."),
2260 XGetAtomName(DISPLAY, wmNameProp->encoding));
2266 /* Couldn't convert using Xm; apply a default */
2267 return XmCvtCTToXmString((char*)wmNameProp->value);
2270 xms_return = xmsTable[0];
2271 for (i = 1; i < nStrings; i++)
2273 #ifdef CONCAT_TEXTLIST
2274 xms_return = XmStringConcatAndFree(xms_return, xmsTable[i]);
2276 XmStringFree(xmsTable[i]);
2277 #endif /* CONCAT_TEXTLIST */
2279 XtFree((char *)xmsTable);
2285 /*************************************<->*************************************
2287 * ProcessWmWindowTitle (pCD, firstTime)
2292 * This function retrieves the contents of the WM_NAME property on the
2293 * cient window. A default name is set if the property does not exist.
2298 * pCD - pointer to client data structure
2299 * firstTime - false if the window is already managed and the title
2305 * pCD - clientTitle, iconTitle
2307 *************************************<->***********************************/
2310 ProcessWmWindowTitle (ClientData *pCD, Boolean firstTime)
2312 XTextProperty wmNameProp;
2313 XmString title_xms = NULL;
2315 if ((pCD->clientDecoration & MWM_DECOR_TITLE) &&
2317 (!firstTime || HasProperty (pCD, XA_WM_NAME)) &&
2319 XGetWMName(DISPLAY, pCD->client, &wmNameProp))
2321 title_xms = WmICCCMToXmString(&wmNameProp);
2322 if (wmNameProp.value)
2323 XFree ((char*)wmNameProp.value);
2328 if (!firstTime && (pCD->iconTitle == pCD->clientTitle))
2331 * The client window title is being used for the icon title so
2332 * change the icon title with the window title.
2334 pCD->iconTitle = title_xms;
2335 RedisplayIconTitle (pCD);
2338 if ((pCD->clientFlags & CLIENT_HINTS_TITLE) &&
2339 pCD->clientTitle != wmGD.clientDefaultTitle)
2341 XmStringFree (pCD->clientTitle);
2344 pCD->clientTitle = title_xms;
2345 pCD->clientFlags |= CLIENT_HINTS_TITLE;
2349 DrawWindowTitle (pCD, True);
2353 * The client frame does not have a place to put the title or the WM_NAME
2354 * property does not exist or there was some error in getting
2355 * the property information, so use a default value.
2359 if (pCD->clientName)
2361 pCD->clientTitle = XmStringCreateLocalized(pCD->clientName);
2365 pCD->clientTitle = wmGD.clientDefaultTitle;
2370 * If this is a tear-off menu, then make sure title text is not clipped
2374 if ((pCD->window_status & MWM_TEAROFF_WINDOW) ||
2375 (pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUBPANEL))
2376 #else /* PANELIST */
2377 if (pCD->window_status & MWM_TEAROFF_WINDOW)
2378 #endif /* PANELIST */
2380 unsigned int boxdim = TitleBarHeight (pCD);
2381 unsigned long decor = pCD->decor;
2382 XmFontList fontList;
2385 if (DECOUPLE_TITLE_APPEARANCE(pCD))
2386 fontList = CLIENT_TITLE_APPEARANCE(pCD).fontList;
2388 fontList = CLIENT_APPEARANCE(pCD).fontList;
2391 * Calculations derived from GetTextBox() and GetFramePartInfo()
2393 minWidth = XmStringWidth(fontList, pCD->clientTitle) +
2395 ((pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUBPANEL) ? 4 : 0) +
2396 #endif /* PANELIST */
2397 ((decor & MWM_DECOR_MENU) ? boxdim : 0) +
2398 ((decor & MWM_DECOR_MINIMIZE) ? boxdim : 0) +
2399 ((decor & MWM_DECOR_MAXIMIZE) ? boxdim : 0) +
2400 WM_TOP_TITLE_SHADOW + WM_BOTTOM_TITLE_SHADOW +
2401 WM_TOP_TITLE_PADDING + WM_BOTTOM_TITLE_PADDING;
2403 if (minWidth > pCD->minWidth)
2405 pCD->minWidth = minWidth;
2408 if ((pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUBPANEL) &&
2409 (pCD->clientWidth < pCD->minWidth))
2411 FixSubpanelEmbeddedClientGeometry (pCD);
2413 #endif /* PANELIST */
2416 } /* END OF FUNCTION ProcessWmWindowTitle */
2420 /*************************************<->*************************************
2422 * FixSubpanelEmbeddedClientGeometry ( pCD )
2427 * This function adjusts the embedded clients in a subpanel if the
2428 * geometry of the subpanel is adjusted.
2433 * pCD - pointer to client data structure
2441 * Only handles change in width right now.
2443 *************************************<->***********************************/
2446 FixSubpanelEmbeddedClientGeometry (ClientData *pCD)
2448 WmScreenData *pSD = PSD_FOR_CLIENT(pCD);
2454 * Get the widget for the subpanel
2456 wSubpanel = WmPanelistWindowToSubpanel (DISPLAY1, pCD->client);
2458 if (pSD->wPanelist && wSubpanel)
2460 WmFpEmbeddedClientData *pECD;
2464 * set new shell width to minimum width
2466 if (pCD->clientWidth < pCD->minWidth)
2469 XtSetArg (al[ac], XmNwidth, pCD->minWidth); ac++;
2470 XtSetValues (wSubpanel, al, ac);
2474 * Cause update of client geometries.
2476 /* WmPanelistSetClientGeometry (pSD->wPanelist); */
2479 * Update all affected reparented controls.
2482 for (i=0; i<pSD->numEmbeddedClients; i++)
2484 pECD = &(((WmFpEmbeddedClientData *) pSD->pECD)[i]);
2488 ClientData *pCD2 = pECD->pCD;
2490 if ((pCD2->clientWidth != pECD->width) ||
2491 (pCD2->clientHeight != pECD->height) ||
2492 (pCD2->clientX != pECD->x) ||
2493 (pCD2->clientY != pECD->y))
2495 pCD2->clientX = pECD->x;
2496 pCD2->clientY = pECD->y;
2497 pCD2->clientWidth = pECD->width;
2498 pCD2->clientHeight = pECD->height;
2500 XMoveResizeWindow (DISPLAY1, pCD2->client,
2501 pECD->x, pECD->y, pECD->width, pECD->height);
2506 } /* END OF FUNCTION FixEmbeddedClientGeometry */
2508 #endif /* PANELIST */
2511 /*************************************<->*************************************
2513 * ProcessWmIconTitle (pCD, firstTime)
2518 * This function retrieves the contents of the WM_ICON_NAME property on the
2519 * cient window. The value of the property is a string that is used for the
2520 * icon title. A default title is set if the property does not exist.
2525 * pCD - pointer to client data structure
2527 * firstTime - false if the window is already managed and the title
2535 *************************************<->***********************************/
2538 ProcessWmIconTitle (ClientData *pCD, Boolean firstTime)
2540 XTextProperty wmIconNameProp;
2541 XmString icon_xms = NULL;
2543 if ((pCD->clientFunctions & MWM_FUNC_MINIMIZE) &&
2544 (pCD->transientLeader == NULL) &&
2546 (!firstTime || HasProperty(pCD, XA_WM_ICON_NAME)) &&
2548 XGetWMIconName (DISPLAY, pCD->client, &wmIconNameProp))
2550 icon_xms = WmICCCMToXmString(&wmIconNameProp);
2551 if (wmIconNameProp.value)
2552 XFree ((char*)wmIconNameProp.value);
2557 if ((pCD->iconFlags & ICON_HINTS_TITLE) &&
2558 pCD->iconTitle != wmGD.iconDefaultTitle)
2560 XmStringFree (pCD->iconTitle);
2563 pCD->iconTitle = icon_xms;
2564 pCD->iconFlags |= ICON_HINTS_TITLE;
2568 RedisplayIconTitle (pCD);
2572 * The WM_ICON_NAME property does not exist (or there was some error
2573 * in getting * the property information), so use a default value.
2577 if (pCD->clientTitle && (pCD->clientTitle != wmGD.clientDefaultTitle))
2579 pCD->iconTitle = pCD->clientTitle;
2583 pCD->iconTitle = wmGD.iconDefaultTitle;
2587 } /* END OF FUNCTION ProcessWmIconTitle */
2591 /*************************************<->*************************************
2593 * ProcessWmTransientFor (pCD)
2598 * This function retrieves the contents of the WM_TRANSIENT_FOR property on
2604 * pCD = pointer to the client data structure for the window with the property
2609 * pCD.transientFor = if tranient then this is the associated main window
2611 * pCD.clientFlags = indicate that this is a transient window
2613 *************************************<->***********************************/
2616 ProcessWmTransientFor (ClientData *pCD)
2623 if ((HasProperty (pCD, XA_WM_TRANSIENT_FOR)) &&
2624 (XGetTransientForHint (DISPLAY, pCD->client, &window)))
2626 if (XGetTransientForHint (DISPLAY, pCD->client, &window))
2629 pCD->clientFlags |= CLIENT_TRANSIENT;
2632 * Only save the (leader) transientFor window if it is NOT the
2633 * client window and it is already managed by the window manager.
2636 if ((pCD->client != window) &&
2637 !XFindContext (DISPLAY, window, wmGD.windowContextType,
2638 (caddr_t *)&leader))
2640 pCD->transientFor = window;
2641 pCD->transientLeader = leader;
2644 else { /* else this is not a transient window */
2645 pCD->clientFlags &= ~CLIENT_TRANSIENT;
2646 pCD->transientFor = (Window)0L;
2647 pCD->transientLeader = NULL;
2651 } /* END OF FUNCTION ProcessWmTransientFor */
2655 /*************************************<->*************************************
2657 * MakeSystemMenu (pCD)
2662 * This function finds or makes a system menu for the client. A check
2663 * is made for the _MWM_MENU property and, if present, client-specific
2664 * items are added to the custom system menu. Any custom system menu
2665 * must be destroyed when the client is unmanaged (or killed).
2670 * pCD = pointer to the client data structure for the managed window
2675 * pCD.systemMenuSpec = system menu specification for the client, not added
2676 * to wmGD.acceleratorMenuSpecs
2678 *************************************<->***********************************/
2681 MakeSystemMenu (ClientData *pCD)
2683 #if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
2685 #endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
2687 pCD->mwmMenuItems = GetMwmMenuItems(pCD);
2688 pCD->systemMenuSpec =
2689 MAKE_MENU (PSD_FOR_CLIENT(pCD), pCD, pCD->systemMenu, F_CONTEXT_WINDOW,
2690 F_CONTEXT_WINDOW|F_CONTEXT_ICON, pCD->mwmMenuItems, TRUE);
2692 #ifdef NO_MESSAGE_CATALOG
2693 if (pCD->systemMenuSpec == NULL)
2696 * As the lookup has failed, let's try just one more time.
2698 Warning("Retrying - using builtin window menu\n");
2700 pCD->systemMenuSpec =
2701 MAKE_MENU(PSD_FOR_CLIENT(pCD), pCD, builtinSystemMenuName,
2703 F_CONTEXT_WINDOW|F_CONTEXT_ICON, pCD->mwmMenuItems, TRUE);
2707 #if defined(MWM_QATS_PROTOCOL)
2708 /* Added to fix CDExc23338
2709 * Not sure what the MWM_QATS_PROTOCOL is trying to accomplish here,
2710 * but this code is causing the system menu to loose it's default
2711 * actions whenever client defined actions are added. I thought
2712 * it prudent to minimize the changes. It could be that the
2713 * #if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
2715 * #if ((!defined(WSM)) && defined(MWM_QATS_PROTOCOL))
2716 * throughout the wm code, but I am loath to make such a change
2717 * without any documentation.
2720 #if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
2721 /** BEGIN FIX CR 6941 **/
2723 /* if we still don't have a menu spec, then just abort. */
2724 if (pCD->systemMenuSpec == NULL)
2727 pCD->systemMenuSpec = DuplicateMenuSpec(pCD->systemMenuSpec);
2728 XtFree(pCD->systemMenuSpec->name);
2729 pCD->systemMenuSpec->name = XtNewString("ProtocolsMenu");
2731 /* Find the last menu item in the menu spec's list. */
2732 for (lastItem = pCD->systemMenuSpec->menuItems;
2733 lastItem->nextMenuItem != (MenuItem *) NULL;
2734 lastItem = lastItem->nextMenuItem)
2736 lastItem->nextMenuItem = pCD->mwmMenuItems;
2738 /* Now recreate the menu widgets since we've appended the
2739 protocol menu items */
2740 DestroyMenuSpecWidgets(pCD->systemMenuSpec);
2741 pCD->systemMenuSpec->menuWidget =
2742 CreateMenuWidget (PSD_FOR_CLIENT(pCD), pCD, "ProtocolsMenu",
2743 PSD_FOR_CLIENT(pCD)->screenTopLevelW, TRUE,
2744 pCD->systemMenuSpec, NULL);
2745 /** END FIX CR 6941 **/
2746 #endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
2747 #endif /* defined(MWM_QATS_PROTOCOL) */
2749 } /* END OF FUNCTION MakeSystemMenu */
2753 /*************************************<->*************************************
2755 * InitCColormapData (pCD)
2760 * This function initializes colormap data for the client window that is
2761 * by the window manager in maintaining the colormap focus. This may
2762 * involve retrieving and processing properties that deal with subwindow
2768 * pCD = pointer to the client data structure for the managed window
2773 * pCD.clientColormap = client colormap to be installed when the client
2774 * window gets the colormap focus
2776 * pCD = (cmapWindows, clientCmapList, clientCmapCount, clientCmapIndex)
2778 *************************************<->***********************************/
2781 InitCColormapData (ClientData *pCD)
2784 if (wmGD.windowAttributes.colormap == None)
2786 pCD->clientColormap = WORKSPACE_COLORMAP(pCD);
2790 pCD->clientColormap = wmGD.windowAttributes.colormap;
2794 * Process subwindow colormap windows if they are specified.
2797 ProcessWmColormapWindows (pCD);
2800 } /* END OF FUNCTION InitCColormapData */
2804 /*************************************<->*************************************
2806 * CalculateGravityOffset (pCD, xoff, yoff)
2811 * This function calculates the window offsets based on the window gravity
2812 * and the window frame client offset.
2817 * pCD = pointer to client data (client window configuration fields)
2818 * xoff = pointer to xoffset
2819 * yoff = pointer to yoffset
2824 * xoff = pointer to xoffset set
2825 * yoff = pointer to yoffset set
2827 *************************************<->***********************************/
2830 CalculateGravityOffset (ClientData *pCD, int *xoff, int *yoff)
2832 int borderWidth = pCD->xBorderWidth;
2834 if (pCD->windowGravity < ForgetGravity ||
2835 pCD->windowGravity > StaticGravity)
2842 switch (pCD->windowGravity)
2844 case NorthWestGravity:
2847 *xoff = pCD->clientOffset.x;
2848 *yoff = pCD->clientOffset.y;
2854 *xoff = borderWidth;
2855 *yoff = pCD->clientOffset.y;
2859 case NorthEastGravity:
2861 *xoff = -(pCD->clientOffset.x - (2 * borderWidth));
2862 *yoff = pCD->clientOffset.y;
2868 *xoff = -(pCD->clientOffset.x - (2 * borderWidth));
2869 *yoff = borderWidth +
2870 (pCD->clientOffset.y - pCD->clientOffset.x)/2;
2874 case SouthEastGravity:
2876 *xoff = -(pCD->clientOffset.x - (2 * borderWidth));
2877 *yoff = -(pCD->clientOffset.x - (2 * borderWidth));
2883 *xoff = borderWidth;
2884 *yoff = -(pCD->clientOffset.x - (2 * borderWidth));
2888 case SouthWestGravity:
2890 *xoff = pCD->clientOffset.x;
2891 *yoff = -(pCD->clientOffset.x - (2 * borderWidth));
2897 *xoff = pCD->clientOffset.x;
2898 *yoff = borderWidth +
2899 (pCD->clientOffset.y - pCD->clientOffset.x)/2;
2911 } /* END OF FUNCTION CalculateGravityOffset */
2915 /*************************************<->*************************************
2917 * InitClientPlacement (pCD, manageFlags)
2922 * This function sets up the initial client window placement (for both
2923 * the normal and maximized state).
2928 * pCD = pointer to client data (client window configuration fields)
2930 * manageFlags = flags that indicate wm state information (e.g. whether
2931 * the window manager is starting up or restarting)
2936 * Return = True if position changed by this routine.
2937 * pCD = changes to the client window configuration fields
2939 *************************************<->***********************************/
2942 InitClientPlacement (ClientData *pCD, long manageFlags)
2944 Boolean interactivelyPlaced = False;
2945 Boolean autoPlaced = False;
2946 Boolean rval = False;
2948 int origX, origY, origWidth, origHeight;
2955 * Save initial client values
2957 origX = pCD->clientX;
2958 origY = pCD->clientY;
2959 origWidth = pCD->clientWidth;
2960 origHeight = pCD->clientHeight;
2963 * Do interactive placement if...
2964 * + the resource is turned on
2965 * + the window's coming up on the active screen
2968 * + position specified in DB or by Session Manager
2969 * + the user has specified a position
2970 * + the window is coming up iconic
2971 * + the window is transient
2972 * + we're system modal
2975 if (wmGD.interactivePlacement &&
2976 (!(pCD->clientFlags & (SM_X | SM_Y))) &&
2977 !(pCD->sizeFlags & US_POSITION) &&
2978 (pCD->clientState != MINIMIZED_STATE) &&
2979 (manageFlags == MANAGEW_NORMAL) &&
2980 !(pCD->clientFlags & CLIENT_TRANSIENT) &&
2981 (pCD->inputMode != MWM_INPUT_SYSTEM_MODAL) &&
2983 (ClientInWorkspace(PSD_FOR_CLIENT(pCD)->pActiveWS, pCD)))
2985 (PSD_FOR_CLIENT(pCD) == ACTIVE_PSD))
2989 * Interactively place the window on the screen.
2991 interactivelyPlaced = True;
2992 PlaceWindowInteractively (pCD);
2997 * Check out the configuration values to insure that they are within
3001 FixWindowConfiguration (pCD, (unsigned int *) &(pCD->clientWidth),
3002 (unsigned int *) &(pCD->clientHeight),
3003 (unsigned int) (pCD->widthInc),
3004 (unsigned int) (pCD->heightInc));
3007 * Do autoplacement of the client window if appropriate.
3010 if ((manageFlags == MANAGEW_NORMAL) && !interactivelyPlaced &&
3011 (!(pCD->clientFlags & (SM_X | SM_Y))) &&
3012 !(pCD->sizeFlags & US_POSITION) &&
3013 !(pCD->clientFlags & CLIENT_TRANSIENT) &&
3014 (pCD->inputMode != MWM_INPUT_SYSTEM_MODAL) && wmGD.clientAutoPlace)
3017 * if (PPosition is on or nonzero), then use current value for
3018 * clientX and clientY which was set to windowAttributes.x,y
3019 * by ProcessWmNormalHints(), else autoplace client.
3022 if ((pCD->sizeFlags & P_POSITION) &&
3023 ((pCD->usePPosition == USE_PPOSITION_ON) ||
3024 ((pCD->usePPosition == USE_PPOSITION_NONZERO) &&
3025 ((pCD->clientX != 0) || (pCD->clientY != 0)))))
3031 FindClientPlacement (pCD);
3037 * Do PositionIsFrame processing:
3038 * Use window gravity to allow the user to specify the window
3039 * position on the screen without having to know the dimensions
3040 * of the decoration that mwm is adding.
3043 if ((wmGD.positionIsFrame) &&
3044 !interactivelyPlaced && !autoPlaced)
3046 CalculateGravityOffset (pCD, &xoff, &yoff);
3047 if (!(pCD->clientFlags & SM_X))
3048 pCD->clientX += xoff;
3049 if (!(pCD->clientFlags & SM_Y))
3050 pCD->clientY += yoff;
3055 * Do PositionOnScreen processing:
3061 if (pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUBPANEL)
3063 if (pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUB_RESTORED)
3069 AdjustSlideOutGeometry (pCD);
3073 #endif /* PANELIST */
3075 if (((wmGD.positionOnScreen) && !interactivelyPlaced) &&
3076 (!(pCD->clientFlags & (SM_X | SM_Y))))
3078 PlaceFrameOnScreen (pCD, &pCD->clientX, &pCD->clientY,
3079 pCD->clientWidth, pCD->clientHeight);
3084 * Position the maximized frame:
3087 pCD->maxX = pCD->clientX;
3088 pCD->maxY = pCD->clientY;
3089 PlaceFrameOnScreen (pCD, &pCD->maxX, &pCD->maxY, pCD->maxWidth,
3093 if (!wmGD.iconAutoPlace)
3096 if (!(pCD->iconFlags & ICON_HINTS_POSITION))
3098 for (iwsc=0; iwsc<pCD->numInhabited; iwsc++)
3100 pCD->pWsList[iwsc].iconX = pCD->clientX;
3101 pCD->pWsList[iwsc].iconY = pCD->clientY;
3102 PlaceIconOnScreen (pCD, &pCD->pWsList[iwsc].iconX,
3103 &pCD->pWsList[iwsc].iconY);
3107 if (!(pCD->iconFlags & ICON_HINTS_POSITION))
3109 pCD->iconX = pCD->clientX;
3110 pCD->iconY = pCD->clientY;
3112 PlaceIconOnScreen (pCD, &pCD->iconX, &pCD->iconY);
3117 * if client size or position has been changed by this routine,
3118 * then indicate in return value
3120 if ((origX != pCD->clientX) || (origY != pCD->clientY) ||
3121 (origWidth != pCD->clientWidth) || (origHeight != pCD->clientHeight))
3128 } /* END OF FUNCTION InitClientPlacement */
3132 /******************************<->*************************************
3134 * void AdjustSlideOutGeometry (pCD)
3138 * Adjusts the geometry of the slide out panel
3142 * pCD = pointer to a client data of slide out
3149 * Subpanel is to appear above or below the front panel, centered
3150 * on the vertical axis of the spawning control.
3151 ******************************<->***********************************/
3153 AdjustSlideOutGeometry ( ClientData *pCD)
3155 ClientData *pCD_FP = NULL;
3156 WmPanelistObject pPanelist;
3158 pCD->slideDirection = SLIDE_NORTH; /* assume up for now */
3159 pPanelist = (WmPanelistObject) pCD->pSD->wPanelist;
3160 (void) XFindContext (DISPLAY, XtWindow(O_Shell(pPanelist)),
3161 wmGD.windowContextType, (caddr_t *)&pCD_FP);
3166 * Adjust slide up position if coming from front
3168 * (Assumes no nesting of panels !!!)
3169 * (Assumes horizontal oriented front panel!!!)
3171 if (pCD->transientLeader == pCD_FP)
3174 * Subpanel should be sort-of centered already,
3175 * adjust by width of window manager frame.
3177 pCD->clientX -= pCD->frameInfo.lowerBorderWidth;
3180 * Adjust to slide up above front panel.
3182 pCD->clientY = pCD_FP->frameInfo.y -
3183 pCD->frameInfo.lowerBorderWidth -
3184 pCD->clientHeight + 3;
3186 /* RICK -- added the (+ 3) */
3189 if (pCD->clientY < 0)
3192 * Adjust to slide down below front panel.
3194 pCD->clientY = pCD_FP->frameInfo.y +
3195 pCD_FP->frameInfo.height +
3196 pCD->frameInfo.titleBarHeight +
3197 pCD->frameInfo.upperBorderWidth - 3;
3198 pCD->slideDirection = SLIDE_SOUTH;
3199 /* RICK -- added the (- 3) */
3202 if ((pCD->clientY + pCD->clientHeight +
3203 pCD->frameInfo.lowerBorderWidth) >
3204 XDisplayHeight (DISPLAY, pCD->pSD->screen))
3207 * If the bottom of the slide-up is off the bottom
3208 * of the screen, then don't slide, just pop it up.
3210 pCD->slideDirection = SLIDE_NOT;
3213 PlaceFrameOnScreen (pCD, &pCD->clientX, &pCD->clientY,
3214 pCD->clientWidth, pCD->clientHeight);
3219 #endif /* PANELIST */
3222 /*************************************<->*************************************
3224 * PlaceFrameOnScreen (pCD, pX, pY, w, h)
3229 * This function is used to nudge a client window so that it is totally
3230 * onscreen if possible. At least the top left corner will be onscreen.
3235 * pCD - pointer to client data
3236 * pX - pointer to x-coord
3237 * pY - pointer to y-coord
3238 * w - width of window
3239 * h - height of window
3251 *************************************<->***********************************/
3254 PlaceFrameOnScreen (ClientData *pCD, int *pX, int *pY, int w, int h)
3266 clientOffsetX = pCD->clientOffset.x;
3267 clientOffsetY = pCD->clientOffset.y;
3268 frameX = *pX - clientOffsetX;
3269 frameY = *pY - clientOffsetY;
3270 frameWidth = w + (2 * clientOffsetX);
3271 frameHeight = h + clientOffsetX + clientOffsetY;
3272 screenWidth = DisplayWidth (DISPLAY, SCREEN_FOR_CLIENT(pCD));
3273 screenHeight = DisplayHeight (DISPLAY, SCREEN_FOR_CLIENT(pCD));
3275 if ((frameX + frameWidth) > screenWidth)
3277 frameX -= (frameX + frameWidth) - screenWidth;
3279 if ((frameY + frameHeight) > screenHeight)
3281 frameY -= (frameY + frameHeight) - screenHeight;
3292 *pX = frameX + clientOffsetX;
3293 *pY = frameY + clientOffsetY;
3295 } /* END OF FUNCTION PlaceFrameOnScreen */
3299 /*************************************<->*************************************
3301 * PlaceIconOnScreen (pCD, pX, pY)
3306 * This function positions an icon on-screen.
3311 * pCD - pointer to client data
3312 * pX - pointer to x-coord
3313 * pY - pointer to y-coord
3323 *************************************<->***********************************/
3326 PlaceIconOnScreen (ClientData *pCD, int *pX, int *pY)
3334 screenWidth = DisplayWidth (DISPLAY, SCREEN_FOR_CLIENT(pCD));
3335 screenHeight = DisplayHeight (DISPLAY, SCREEN_FOR_CLIENT(pCD));
3339 if ((iconX + ICON_WIDTH(pCD)) > screenWidth)
3341 iconX = screenWidth - ICON_WIDTH(pCD);
3348 if ((iconY + ICON_HEIGHT(pCD)) > screenHeight)
3350 iconY = screenHeight - ICON_HEIGHT(pCD);
3361 } /* END OF FUNCTION PlaceIconOnScreen */
3365 /*************************************<->*************************************
3367 * FixWindowConfiguration (pCD, pWidth, pHeight, widthInc, heightInc)
3372 * This function adjusts the configuration for the client window so that
3373 * it is in line with the client window's sizing constraints.
3378 * pCD = a pointer to the client window data
3379 * pWidth, pHeight = pointers to the window configuration values
3380 * widthInc, heightInc = window size increment values
3385 * pWidth, pHeight = adjusted configuration values are returned here
3388 *************************************<->***********************************/
3391 FixWindowConfiguration (ClientData *pCD, unsigned int *pWidth, unsigned int *pHeight, unsigned int widthInc, unsigned int heightInc)
3396 * Make sure we're on width/height increment boundaries.
3399 if ((int) *pWidth < pCD->minWidth)
3401 *pWidth = pCD->minWidth;
3403 else if ((delta = (*pWidth - pCD->baseWidth) % pCD->widthInc))
3408 if ((int) *pHeight < pCD->minHeight)
3410 *pHeight = pCD->minHeight;
3412 else if ((delta = (*pHeight - pCD->baseHeight) % pCD->heightInc))
3418 * Constrain size within bounds.
3421 FixWindowSize (pCD, pWidth, pHeight, widthInc, heightInc);
3423 } /* END OF FUNCTION FixWindowConfiguration */
3427 /*************************************<->*************************************
3429 * FixWindowSize (pCD, pWidth, pHeight, widthInc, heightInc)
3434 * This function adjusts the client window width and height so that
3435 * it is in line with its sizing constraints.
3440 * pCD = a pointer to the client window data
3441 * pWidth, pHeight = pointers to the window size values
3442 * widthInc, heightInc = window size increment values
3448 * pWidth, pHeight = adjusted size values.
3451 *************************************<->***********************************/
3454 FixWindowSize (ClientData *pCD, unsigned int *pWidth, unsigned int *pHeight, unsigned int widthInc, unsigned int heightInc)
3456 register int deltaW;
3457 register int deltaH;
3458 WmScreenData *pSD = pCD->pSD;
3461 * All occurances of maxHeight and maxWidth in this routing has been
3462 * hacked to use maxHeightLimit and maxWidthLimit as the real max when
3463 * maximumClientSize is set to 'horizontal' or 'vertical', since
3464 * pCD->maxHeight and pCD->maxWidth is fiddle to on reconfiguration.
3467 if ((int) *pWidth < pCD->minWidth)
3469 *pWidth = pCD->minWidth;
3471 else if (*pWidth > pCD->maxWidthLimit &&
3473 !(pCD->clientFlags & CLIENT_WM_CLIENTS))
3475 *pWidth = pCD->maxWidthLimit;
3478 if ((int) *pHeight < pCD->minHeight)
3480 *pHeight = pCD->minHeight;
3482 else if (*pHeight > pCD->maxHeightLimit &&
3484 !(pCD->clientFlags & CLIENT_WM_CLIENTS))
3486 *pHeight = pCD->maxHeightLimit;
3489 if ((pCD->sizeFlags & P_ASPECT) &&
3490 *pWidth * pCD->maxAspect.y > *pHeight * pCD->maxAspect.x)
3492 * Client aspect is too big.
3493 * Candidate height >= client height:
3494 * Try to increase the client's height without violating bounds.
3495 * If this fails, use maximum height and try to decrease its width.
3496 * Candidate height < client height:
3497 * Try to decrease the client's width without violating bounds.
3498 * If this fails, use minimum width and try to increase its height.
3501 if ((*pHeight >= pCD->clientHeight) ||
3502 (*pWidth > pCD->clientWidth))
3504 * Candidate height >= client height:
3505 * Try to increase the client's height without violating bounds.
3506 * If this fails, use maximum height and try to decrease its width.
3509 deltaH = makemult (*pWidth * pCD->maxAspect.y / pCD->maxAspect.x -
3510 *pHeight, heightInc);
3511 if (*pHeight + deltaH <= pCD->maxHeightLimit ||
3512 !pSD->limitResize ||
3513 pCD->clientFlags & CLIENT_WM_CLIENTS)
3519 *pHeight = pCD->maxHeightLimit;
3520 deltaW = makemult (*pWidth - *pHeight * pCD->maxAspect.x /
3521 pCD->maxAspect.y, widthInc);
3522 if (*pWidth - deltaW >= pCD->minWidth)
3528 *pWidth = pCD->minWidth;
3534 * Candidate height < client height and candidate width <= client width.
3535 * Try to decrease the client's width without violating bounds.
3536 * If this fails, use minimum width and try to increase its height.
3539 deltaW = makemult (*pWidth - *pHeight * pCD->maxAspect.x /
3540 pCD->maxAspect.y, widthInc);
3542 if (*pWidth - deltaW >= pCD->minWidth)
3548 *pWidth = pCD->minWidth;
3549 deltaH = makemult (*pWidth * pCD->maxAspect.y /
3550 pCD->maxAspect.x - *pHeight, heightInc);
3551 if (*pHeight + deltaH <= pCD->maxHeightLimit ||
3552 !pSD->limitResize ||
3553 pCD->clientFlags & CLIENT_WM_CLIENTS)
3559 *pHeight = pCD->maxHeightLimit;
3565 else if ((pCD->sizeFlags & P_ASPECT) &&
3566 *pHeight * pCD->minAspect.x > *pWidth * pCD->minAspect.y)
3568 * Client aspect is too small.
3569 * Candidate width >= client width:
3570 * Try to increase the client's width without violating bounds.
3571 * If this fails, use maximum width and try to decrease its height.
3572 * Candidate width < client width:
3573 * Try to decrease the client's height without violating bounds.
3574 * If this fails, use minimum height and try to increase its width.
3577 if ((*pWidth >= pCD->clientWidth) ||
3578 (*pHeight > pCD->clientHeight))
3580 * Candidate width >= client width:
3581 * Try to increase the client's width without violating bounds.
3582 * If this fails, use maximum width and try to decrease its height.
3585 deltaW = makemult (*pHeight * pCD->minAspect.x / pCD->minAspect.y -
3587 if (*pWidth + deltaW <= pCD->maxWidthLimit ||
3588 !pSD->limitResize ||
3589 pCD->clientFlags & CLIENT_WM_CLIENTS)
3595 *pWidth = pCD->maxWidthLimit;
3596 deltaH = makemult (*pHeight - *pWidth * pCD->minAspect.y /
3597 pCD->minAspect.x, heightInc);
3598 if (*pHeight - deltaH >= pCD->minHeight)
3604 *pHeight = pCD->minHeight;
3610 * Candidate width < client width and Candidate height <= client height:
3611 * Try to decrease the client's height without violating bounds.
3612 * If this fails, use minimum height and try to increase its width.
3615 deltaH = makemult (*pHeight - *pWidth * pCD->minAspect.y /
3616 pCD->minAspect.x, heightInc);
3617 if (*pHeight - deltaH >= pCD->minHeight)
3623 *pHeight = pCD->minHeight;
3624 deltaW = makemult (*pHeight * pCD->minAspect.x /
3625 pCD->minAspect.y - *pWidth, widthInc);
3626 if (*pWidth + deltaW <= pCD->maxWidthLimit ||
3627 !pSD->limitResize ||
3628 pCD->clientFlags & CLIENT_WM_CLIENTS)
3634 *pWidth = pCD->maxWidthLimit;
3639 } /* END OF FUNCTION FixWindowSize */
3643 /*************************************<->*************************************
3645 * FindClientPlacement (pCD)
3650 * This function finds a position for the client window on the screen.
3651 * Windows positions are stepped down the screen. An attempt is made
3652 * to keep windows from being clipped by the edge of the screen.
3657 * pCD = pointer to client data (client window configuration fields)
3662 * pCD = changes to the client window configuration fields
3664 *************************************<->***********************************/
3667 FindClientPlacement (ClientData *pCD)
3669 static Boolean clientPlacementInitialized = False;
3670 static int clientPlacementOffset;
3671 static int clientPlacementX;
3672 static int clientPlacementY;
3673 static int clientPlacementOrigin;
3674 static int clientPlacementXOrigin;
3676 Boolean placed = False;
3681 int borderWidth = 0;
3686 if (!clientPlacementInitialized)
3688 if (pCD->clientDecoration & WM_DECOR_RESIZEH)
3690 borderWidth = ((RESIZE_BORDER_WIDTH(pCD) > FRAME_BORDER_WIDTH(pCD))
3691 ? RESIZE_BORDER_WIDTH(pCD) : FRAME_BORDER_WIDTH(pCD));
3695 borderWidth = pCD->matteWidth;
3697 clientPlacementOffset = TitleTextHeight(pCD) + borderWidth;
3698 clientPlacementOrigin = clientPlacementOffset;
3699 clientPlacementX = clientPlacementOrigin;
3700 clientPlacementY = clientPlacementOrigin;
3701 clientPlacementXOrigin = clientPlacementX;
3702 clientPlacementInitialized = True;
3705 frameWidth = pCD->clientWidth + (2 * pCD->clientOffset.x);
3706 frameHeight = pCD->clientHeight + pCD->clientOffset.y + pCD->clientOffset.x;
3707 screenWidth = DisplayWidth (DISPLAY, SCREEN_FOR_CLIENT(pCD));
3708 screenHeight = DisplayHeight (DISPLAY, SCREEN_FOR_CLIENT(pCD));
3712 if ((clientPlacementX - pCD->clientOffset.x + frameWidth)
3721 if ((clientPlacementY - pCD->clientOffset.y + frameHeight)
3731 if (offScreenX || offScreenY)
3733 if (clientPlacementX == clientPlacementOrigin)
3736 * Placement location is already as far to the NW as it is
3742 else if (clientPlacementY == clientPlacementOrigin)
3745 * Placement location is as far to the N as it is going to go.
3746 * Use the current placement if the window is not off the
3747 * screen in the x coordinate otherwise reset the placement
3748 * back to the NW origin.
3753 clientPlacementXOrigin = clientPlacementOrigin;
3754 clientPlacementX = clientPlacementXOrigin;
3761 * If window is off the right edge of screen, just move
3762 * window in the X direction onto screen. Process similarly
3763 * for windows that are off the bottom of the screen.
3766 if (offScreenX && !offScreenY)
3768 clientPlacementX = clientPlacementOrigin;
3770 else if (offScreenY && !offScreenX)
3772 clientPlacementY = clientPlacementOrigin;
3778 * Reset the placement location back to the NW of the
3779 * current location. Go as far N as possible and step the
3780 * x coordinate to the E.
3783 clientPlacementXOrigin += clientPlacementOffset;
3784 clientPlacementX = clientPlacementXOrigin;
3785 clientPlacementY = clientPlacementOrigin;
3796 * The window has been placed, now update the placement information.
3799 pCD->clientX = clientPlacementX;
3800 pCD->clientY = clientPlacementY;
3801 clientPlacementX += clientPlacementOffset;
3803 if (clientPlacementX >= screenWidth)
3805 clientPlacementXOrigin = clientPlacementOrigin;
3806 clientPlacementX = clientPlacementXOrigin;
3808 clientPlacementY += clientPlacementOffset;
3811 * Reset Y position to top of screen so that windows start new column of
3812 * placement that is offset from the previous column. Previously, the new
3813 * column was place right over the old column, obscuring it.
3814 * NOTE: column == diagonal
3817 if (clientPlacementY >= (screenHeight / 3))
3819 clientPlacementY = clientPlacementOrigin;
3823 } /* END OF FUNCTION FindClientPlacement */
3827 /*************************************<->*************************************
3829 * WmGetWindowAttributes (window)
3834 * This function gets window attributes if necessary and saves them in the
3835 * global window attribute cache. If the window attributes are already
3836 * there then no X call is made.
3841 * window = get attributes for window with this id
3846 * wmGD.attributesWindow = set to window that matches windowAttributes
3848 * wmGD.windowAttributes = XWindowAttributes of window
3853 * The attributes in the global cache are (known) current only for a
3854 * single pass through the wm event processing loop. They (should be)
3855 * regularly cleared.
3857 *************************************<->***********************************/
3860 WmGetWindowAttributes (Window window)
3862 if (wmGD.attributesWindow != window)
3864 if (!XGetWindowAttributes (DISPLAY, window, &wmGD.windowAttributes))
3867 * Cannot get window attributes.
3870 wmGD.attributesWindow = (Window)0L;
3873 wmGD.attributesWindow = window;
3878 } /* END OF FUNCTION WmGetWindowAttributes */
3882 /*************************************<->*************************************
3884 * SetupClientIconWindow (pCD, window)
3889 * This function prepares a client supplied icon window for insertion into
3890 * a window manager icon frame.
3895 * pCD = pointer to client data
3897 * window = client supplied icon window
3902 * pCD = (iconWindow)
3904 * Return = True if the icon window can be used
3906 *************************************<->***********************************/
3909 SetupClientIconWindow (ClientData *pCD, Window window)
3915 * Check to see if the icon window can be used (i.e there is no conflict
3919 if (!XFindContext (DISPLAY, window, wmGD.windowContextType,
3922 if (window == pCD->client)
3925 * The proposed icon window is the same as the client!
3932 * The proposed icon window is already being managed.
3933 * Assume that we managed it by mistake. Unmanage the
3934 * window and use it as the icon window for this client.
3937 UnManageWindow (pcd);
3940 /* update client data */
3941 pCD->iconWindow = window;
3943 /* put in window manager's save set */
3944 XChangeSaveSet (DISPLAY, pCD->iconWindow, SetModeInsert);
3945 pCD->clientFlags |= ICON_IN_SAVE_SET;
3949 } /* END OF FUNCTION SetupClientIconWindow */
3953 /*************************************<->*************************************
3955 * ProcessMwmHints (pCD)
3960 * Process the _MWM_HINTS property on the window (if any). Setup the
3961 * applicable function and decoration masks.
3966 * pCD = pointer to client data
3971 * pCD = may be changed.
3973 *************************************<->***********************************/
3976 ProcessMwmHints (ClientData *pCD)
3978 PropMwmHints *pHints;
3982 * Fix the client functions and decorations fields if they have
3983 * default resource values.
3986 if (pCD->clientFunctions & WM_FUNC_DEFAULT)
3988 if (pCD->clientFlags & CLIENT_TRANSIENT)
3990 pCD->clientFunctions = TRANSIENT_FUNCTIONS(pCD);
3994 pCD->clientFunctions = WM_FUNC_ALL;
3997 if (pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUBPANEL)
3999 pCD->clientFunctions &= WM_FUNC_SUBPANEL_DEFAULT;
4000 pCD->dtwmFunctions &= ~DtWM_FUNCTION_OCCUPY_WS;
4002 else if (pCD->dtwmBehaviors & DtWM_BEHAVIOR_PANEL)
4004 pCD->clientFunctions &= WM_FUNC_PANEL_DEFAULT;
4005 pCD->dtwmFunctions &= ~DtWM_FUNCTION_OCCUPY_WS;
4007 #endif /* PANELIST */
4010 if (pCD->clientDecoration & WM_DECOR_DEFAULT)
4012 if (pCD->clientFlags & CLIENT_TRANSIENT)
4014 pCD->clientDecoration = TRANSIENT_DECORATION(pCD);
4018 pCD->clientDecoration = WM_DECOR_ALL;
4021 if (pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUBPANEL)
4023 pCD->clientDecoration = pCD->pSD->subpanelDecoration;
4025 else if (pCD->dtwmBehaviors & DtWM_BEHAVIOR_PANEL)
4027 pCD->clientDecoration &= WM_DECOR_PANEL_DEFAULT;
4029 #endif /* PANELIST */
4034 * Retrieve the _MWM_HINTS property if it exists.
4037 pCD->inputMode = MWM_INPUT_MODELESS;
4039 if ((pHints = GetMwmHints (pCD)) != NULL)
4041 if (pHints->flags & MWM_HINTS_FUNCTIONS)
4043 if (pHints->functions & MWM_FUNC_ALL)
4045 /* client indicating inapplicable functions */
4046 pCD->clientFunctions &= ~(pHints->functions);
4050 /* client indicating applicable functions */
4051 pCD->clientFunctions &= pHints->functions;
4054 if (!(pCD->clientFlags & GOT_DT_WM_HINTS) &&
4058 * !!! Backward compatibility heurisitic !!!
4060 * If client doesn't want any functions and
4061 * no DT_WM_HINTS specified, then remove
4062 * workspace functions.
4064 pCD->dtwmFunctions &= ~DtWM_FUNCTION_OCCUPY_WS;
4067 /* !!! check for some minimal level of functionality? !!! */
4070 if (pHints->flags & MWM_HINTS_DECORATIONS)
4072 if (pHints->decorations & MWM_DECOR_ALL)
4074 /* client indicating decorations to be removed */
4075 pCD->clientDecoration &= ~(pHints->decorations);
4079 /* client indicating decorations to be added */
4080 pCD->clientDecoration &= pHints->decorations;
4084 * Fix up decoration configuration.
4087 if (pCD->clientDecoration &
4088 (MWM_DECOR_MENU | MWM_DECOR_MINIMIZE | MWM_DECOR_MAXIMIZE))
4090 pCD->clientDecoration |= MWM_DECOR_TITLE;
4092 if (pCD->clientDecoration & MWM_DECOR_RESIZEH)
4094 pCD->clientDecoration |= MWM_DECOR_BORDER;
4098 if (pHints->flags & MWM_HINTS_INPUT_MODE)
4100 if ((pHints->inputMode == MWM_INPUT_PRIMARY_APPLICATION_MODAL) ||
4101 (pHints->inputMode == MWM_INPUT_FULL_APPLICATION_MODAL) ||
4102 ((pHints->inputMode == MWM_INPUT_SYSTEM_MODAL) &&
4103 !wmGD.systemModalActive))
4106 pCD->inputMode = pHints->inputMode;
4111 * Don't allow a system modal window to be a secondary window
4112 * (except with respect to applicable functions and frame
4113 * decorations). Also, don't allow system modal window to
4117 if (pCD->inputMode == MWM_INPUT_SYSTEM_MODAL)
4119 pCD->transientLeader = NULL;
4120 if (pCD->clientFunctions & MWM_FUNC_MINIMIZE)
4122 pCD->clientFunctions &= ~(MWM_FUNC_MINIMIZE);
4127 if (pHints->flags & MWM_HINTS_STATUS)
4129 pCD->window_status = pHints->status;
4132 XFree ((char*)pHints);
4134 #ifndef NO_OL_COMPAT
4137 ProcessOLDecoration (pCD);
4139 #endif /* NO_OL_COMPAT */
4143 * If primary window can't move between workspaces, then
4144 * secondary window shouldn't either.
4146 if (pCD->transientLeader &&
4147 !(pCD->transientLeader->dtwmFunctions & DtWM_FUNCTION_OCCUPY_WS))
4149 pCD->dtwmFunctions &= ~DtWM_FUNCTION_OCCUPY_WS;
4154 * Fix up functions based on system modal settings. System modal
4155 * windows and their descendents cannot be minimized.
4158 if (!((FindTransientTreeLeader (pCD))->clientFunctions&MWM_FUNC_MINIMIZE))
4160 pCD->clientFunctions &= ~MWM_FUNC_MINIMIZE;
4165 * Fix up decoration configuration based on applicable functions.
4168 if (!(pCD->clientFunctions & MWM_FUNC_RESIZE))
4170 pCD->clientDecoration &= ~MWM_DECOR_RESIZEH;
4173 if (!(pCD->clientFunctions & MWM_FUNC_MINIMIZE))
4175 pCD->clientDecoration &= ~MWM_DECOR_MINIMIZE;
4178 if (!(pCD->clientFunctions & MWM_FUNC_MAXIMIZE))
4180 pCD->clientDecoration &= ~MWM_DECOR_MAXIMIZE;
4183 pCD->decor = pCD->clientDecoration; /* !!! combine decor ... !!! */
4186 } /* END OF ProcessMwmHints */