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, 1994 OPEN SOFTWARE FOUNDATION, INC.
32 static char rcsid[] = "$TOG: WmManage.c /main/11 1998/01/12 16:45:48 cshi $"
36 * (c) Copyright 1987, 1988, 1989, 1990, 1992, 1993 HEWLETT-PACKARD COMPANY
46 * include extern functions
50 #include "WmColormap.h"
53 #include "WmFunction.h"
54 #include "WmGraphics.h"
56 #include "WmIconBox.h"
58 #include "WmKeyFocus.h"
60 #include "WmPanelP.h" /* typedef needed in WmManage.h */
61 #include <Dt/Message.h>
66 #include "WmProperty.h"
67 #include "WmProtocol.h"
68 #include "WmWinInfo.h"
69 #include "WmWinList.h"
70 #include "WmWinState.h"
72 #include "WmPresence.h"
73 #include "WmWrkspace.h"
80 * Function Declarations:
85 Boolean IsEmbeddedClient (
87 WmFpEmbeddedClientData **ppECD);
88 Boolean ManageEmbeddedClient (
90 WmFpEmbeddedClientData *pECD,
92 Boolean IsPushRecallClient (
94 WmFpPushRecallClientData **ppPRCD);
95 static void HandleSubstructEvents(
99 Boolean UpdateEmbeddedClientsProperty(
101 static void ForceSubpanelWMState(Window win);
102 static void ReManageWindow (ClientData *pCD);
103 static void CheckPushRecallClient (ClientData *pCD);
105 #endif /* PANELIST */
114 /*************************************<->*************************************
116 * AdoptInitialClients (pSD)
120 * pSD = pointer to screen data
125 * This function is called to find client windows that were mapped prior to
126 * starting (or restarting) the window manager. These windows are included
127 * in the set of windows managed by the window manager.
129 *************************************<->***********************************/
131 void AdoptInitialClients (WmScreenData *pSD)
137 int nAncillaries, iAnc;
138 Window *pAncillaryWindows, *pWin1;
139 WmWorkspaceData *pWS0;
141 unsigned int nclients;
142 ClientData *pcd = NULL;
143 PropWMState *wmStateProp;
144 Boolean manageOnRestart;
150 * Generate list of ancillary windows (not to be managed)
152 nAncillaries = 2 + pSD->numWorkspaces;
153 pAncillaryWindows = (Window *) XtMalloc (sizeof(Window)*(nAncillaries));
154 if (!pAncillaryWindows)
156 Warning (((char *)GETMESSAGE(46, 1, "Insufficient memory to adopt initial clients")));
157 ExitWM (WM_ERROR_EXIT_VALUE);
160 pWin1 = pAncillaryWindows;
161 for (iAnc = 0; iAnc < pSD->numWorkspaces; iAnc++)
163 *pWin1 = XtWindow((pWS0)->workspaceTopLevelW);
167 *pWin1++ = XtWindow (pSD->screenTopLevelW);
168 *pWin1 = pSD->activeIconTextWin;
173 * Look for mapped top-level windows and start managing them:
176 if (XQueryTree (DISPLAY, pSD->rootWindow, &root, &parent, &clients,
179 #ifndef DONT_FILTER_ICON_WINDOWS
181 * Filter out icon windows so they don't get managed as a client
182 * window. Icon windows will be process in SetupClientIconWindow().
186 for (i = 0; i < nclients; i++) {
188 if ((tmphint = XGetWMHints (DISPLAY, clients[i])) != NULL) {
189 if (tmphint->flags & IconWindowHint) {
190 for (j = 0; j < nclients; j++) {
191 if (clients[j] == tmphint->icon_window) {
197 XFree ((char *) tmphint);
203 for (i = 0; i < nclients; i++)
205 /* determine if the client window should be managed by wm */
207 if (InWindowList (clients[i], pAncillaryWindows, nAncillaries))
209 /* don't manage ancillary window manager windows */
213 if ((clients[i] == XtWindow (pSD->screenTopLevelW)) ||
214 (clients[i] == XtWindow (pSD->pActiveWS->workspaceTopLevelW)) ||
215 (clients[i] == pSD->activeIconTextWin))
217 /* don't manage ancillary window manager windows */
221 if (!XFindContext (DISPLAY, clients[i], wmGD.windowContextType,
224 /* don't manage a window we've already established a
225 context for (e.g. icon windows) */
228 if (!WmGetWindowAttributes (clients[i]))
230 /* can't access the window; ignore it */
233 /* window attributes are put into the global cache */
236 * Get the window WM_STATE property value to determine the
237 * initial window state if the wm is being restarted.
240 manageFlags = MANAGEW_WM_STARTUP;
241 manageOnRestart = True;
243 if (wmGD.wmRestarted)
245 manageFlags |= MANAGEW_WM_RESTART;
246 if ((wmStateProp = GetWMState (clients[i])) != NULL)
248 if (wmStateProp->state == IconicState)
250 manageFlags |= MANAGEW_WM_RESTART_ICON;
252 else if (wmStateProp->state != NormalState)
254 manageOnRestart = False;
256 XFree ((char *)wmStateProp);
260 manageOnRestart = False;
265 * Don't manage any override_redirect windows (mapped or not).
266 * Manage an unmapped window if it has a WM_STATE property
267 * and it is not Withdrawn.
268 * Manage any window that is mapped.
271 if ((wmGD.windowAttributes.override_redirect != True) &&
272 ((wmGD.wmRestarted && manageOnRestart) ||
273 (wmGD.windowAttributes.map_state != IsUnmapped)))
275 ManageWindow (pSD, clients[i], manageFlags);
281 XFree ((char *)clients);
286 if (pAncillaryWindows)
288 XtFree ((char *) pAncillaryWindows);
292 } /* END OF FUNCTION AdoptInitialClients */
296 /*************************************<->*************************************
298 * ManageWindow (pSD, clientWindow, manageFlags)
303 * This is the highlevel function that is used to include a window in
304 * the set of windows that are managed by the window manager. The window
305 * gets reparented and decorated, gets an icon, is setup for window
306 * management event handling, etc. Client windows that are controlled
307 * by the window manager (e.g., the icon box) are also managed with
313 * clientWindow = window of the client that we should manage
315 * manageFlags = additional control information
320 * pCD = initialized client data
322 *************************************<->***********************************/
325 ManageWindow (WmScreenData *pSD, Window clientWindow, long manageFlags)
330 Boolean sendConfigNotify;
332 WmWorkspaceData *pwsi;
335 WmFpEmbeddedClientData *pECD;
336 #endif /* PANELIST */
339 * Get client information including window attributes and window
340 * property values. Use this information to determine how the window
344 if (!(pCD = GetClientInfo (pSD, clientWindow, manageFlags)))
346 /* error getting client info; do not manage the client window */
353 * Handle case of transients that derive from embedded clients.
355 if (wmGD.dtSD && (wmGD.dtSD == pCD->pSD))
357 if (pCD->transientLeader && pCD->transientLeader->pECD)
359 WmPanelistObject pPanelist;
360 ClientData *pCDfp = NULL;
362 pPanelist = (WmPanelistObject) pCD->pSD->wPanelist;
363 (void) XFindContext (DISPLAY, XtWindow(O_Shell (pPanelist)),
364 wmGD.windowContextType, (caddr_t *)&pCDfp);
366 pCD->transientLeader = pCDfp;
370 if (IsEmbeddedClient (pCD, &pECD))
373 * This client is embedded in the front panel
376 if (ManageEmbeddedClient(pCD, pECD, manageFlags))
379 * ...then we've embedded it in the front
380 * panel--no further processing required.
383 if (smAckState == SM_START_ACK)
385 SendClientMsg( wmGD.dtSmWindow,
386 (long) wmGD.xa_DT_SM_WM_PROTOCOL,
387 (long) wmGD.xa_DT_WM_WINDOW_ACK,
388 CurrentTime, NULL, 0);
396 * Handle case of transients that derive from embedded clients.
400 if (pCD->transientLeader && pCD->transientLeader->pAccessPanel)
402 pCD->transientLeader =
403 pCD->transientLeader->pAccessPanel->pCD_accessPanel;
406 #endif /* PANELIST */
408 if (pCD->inputMode == MWM_INPUT_SYSTEM_MODAL)
411 * Put system modal windows in all workspaces to
412 * avoid the race condition of the window coming up
413 * just as the user switches workspaces.
415 pCD->dtwmFunctions |= DtWM_FUNCTION_OCCUPY_WS;
416 F_AddToAllWorkspaces(0, pCD, 0);
417 pCD->dtwmFunctions &= ~DtWM_FUNCTION_OCCUPY_WS;
420 if (manageFlags & MANAGEW_WM_RESTART)
422 if (manageFlags & MANAGEW_WM_RESTART_ICON)
424 pCD->clientState = MINIMIZED_STATE;
428 pCD->clientState = NORMAL_STATE;
434 * Setup the initial placement of the client window. Do interactive
435 * placement if configured.
438 sendConfigNotify = InitClientPlacement (pCD, manageFlags);
442 * Make a window frame for the client window and reparent the client
446 if (!FrameWindow (pCD))
449 * Error in framing the window; clean up the wm resources made
450 * up to this point for the client window. Do not manage the
454 UnManageWindow (pCD);
459 * Send config notify if the client's been moved/resized
461 if (sendConfigNotify)
463 SendConfigureNotify (pCD);
467 * Send client offset message if:
469 * 1. The client is interested.
470 * 2. The position we report to the user is not the client's real
472 * 3. There is a client offset to report.
474 if ((pCD->protocolFlags & PROTOCOL_MWM_OFFSET) &&
475 (wmGD.positionIsFrame) &&
476 ((pCD->clientOffset.x != 0) ||
477 (pCD->clientOffset.y != 0)))
479 SendClientOffsetMessage (pCD);
483 * Make an icon for the client window if it is not a valid transient
488 if ((pCD->clientFunctions & MWM_FUNC_MINIMIZE) &&
489 (pCD->transientLeader == NULL))
493 * Only make one icon frame for root icons.
494 * Make one per workspace for icon box icons.
496 for (i = 0; i < pCD->numInhabited; i++)
498 if (pwsi = GetWorkspaceData(pCD->pSD, pCD->pWsList[i].wsID))
501 if ((pCD->pSD->useIconBox &&
502 !(manageFlags & MANAGEW_WM_CLIENTS) &&
503 !(pCD->clientFlags & FRONT_PANEL_BOX)) || (i == 0))
506 * Make icon inside an icon box for non-root case
508 if (!MakeIcon (pwsi, pCD))
511 * Error in making an icon for the client window;
512 * clean up the wm resources; do not manage the
516 UnManageWindow (pCD);
521 XSaveContext (DISPLAY, pCD->pWsList[i].iconFrameWin,
522 wmGD.windowContextType, (caddr_t)pCD);
524 if (pCD->iconWindow && pCD->pWsList[i].iconFrameWin)
526 XGrabButton (DISPLAY, AnyButton, AnyModifier,
527 pCD->pWsList[i].iconFrameWin, True,
528 ButtonPressMask|ButtonReleaseMask|
530 GrabModeAsync, GrabModeAsync, None,
531 wmGD.workspaceCursor);
538 * Make root icons for a client
540 if ((pCD->clientFunctions & MWM_FUNC_MINIMIZE) &&
541 (pCD->transientLeader == NULL))
544 (!MakeIcon (pwsi, pCD)))
547 * Error in making an icon for the client
548 * window; clean up the wm resources; do
549 * not manage the client window.
552 UnManageWindow (pCD);
557 /* copy root icon frame reference to other
560 pCD->pWsList[i].iconFrameWin =
561 pCD->pWsList[0].iconFrameWin;
569 if ((pCD->clientFunctions & MWM_FUNC_MINIMIZE) &&
570 (pCD->transientLeader == NULL) &&
571 !MakeIcon (pCD->pSD->pActiveWS, pCD))
574 * Error in making an icon for the client window; clean up the wm
575 * resources; do not manage the client window.
578 UnManageWindow (pCD);
585 * Register window contexts to facilitate event handling:
588 XSaveContext (DISPLAY, pCD->clientFrameWin, wmGD.windowContextType,
591 XSaveContext (DISPLAY, pCD->clientBaseWin, wmGD.windowContextType,
594 if (DECOUPLE_TITLE_APPEARANCE(pCD) && pCD->clientTitleWin)
597 * handle exposures on title bar if it has its own appearance
599 XSaveContext (DISPLAY, pCD->clientTitleWin, wmGD.windowContextType,
603 if (pCD->iconFrameWin)
605 XSaveContext (DISPLAY, pCD->iconFrameWin, wmGD.windowContextType,
610 if (pCD->clientCmapCount > 0)
612 for (i = 0; i < pCD->clientCmapCount; i++)
614 if (pCD->cmapWindows[i] != pCD->client)
617 AddColormapWindowReference(pCD, pCD->cmapWindows[i]);
619 XSaveContext (DISPLAY, pCD->cmapWindows[i],
620 wmGD.windowContextType, (caddr_t)pCD);
626 pCD->clientFlags |= CLIENT_CONTEXT_SAVED;
630 * Setup button binding handling for actions that apply to the client
634 if (BUTTON_SPECS(pCD))
636 SetupCButtonBindings (pCD->clientBaseWin, BUTTON_SPECS(pCD));
640 if (pCD->iconWindow && pCD->iconFrameWin)
642 XGrabButton (DISPLAY, AnyButton, AnyModifier, pCD->iconFrameWin, True,
643 ButtonPressMask | ButtonReleaseMask | ButtonMotionMask,
644 GrabModeAsync, GrabModeAsync, None, wmGD.workspaceCursor);
649 * Setup key binding handling for system menu accelerators.
652 if (pCD->systemMenuSpec &&
653 (pCD->systemMenuSpec->accelKeySpecs))
655 SetupKeyBindings (pCD->systemMenuSpec->accelKeySpecs,
656 pCD->clientFrameWin, GrabModeSync, F_CONTEXT_ALL);
658 for (i = 0; i < pCD->numInhabited; i++)
660 if (!pCD->pWsList[i].pIconBox && pCD->pWsList[i].iconFrameWin)
662 SetupKeyBindings (pCD->systemMenuSpec->accelKeySpecs,
663 pCD->pWsList[i].iconFrameWin, GrabModeSync,
668 if (!pCD->pIconBox && pCD->iconFrameWin)
670 SetupKeyBindings (pCD->systemMenuSpec->accelKeySpecs,
671 pCD->iconFrameWin, GrabModeSync, F_CONTEXT_ALL);
677 for (i = 0; i < pCD->numInhabited; i++)
679 if (!pCD->pWsList[i].pIconBox && pCD->pWsList[i].iconFrameWin)
681 if (!pCD->pIconBox && pCD->iconFrameWin)
684 static int iconKeySpec = 1;
685 static int iconAccelSpec = 1;
687 if ((iconKeySpec != 0) && KEY_SPECS(pCD))
690 iconKeySpec = SetupKeyBindings (KEY_SPECS(pCD),
691 pCD->pWsList[i].iconFrameWin,
692 GrabModeSync, F_CONTEXT_ICON);
694 iconKeySpec = SetupKeyBindings (KEY_SPECS(pCD), pCD->iconFrameWin,
695 GrabModeSync, F_CONTEXT_ICON);
699 if ((iconAccelSpec != 0) && ACCELERATOR_MENU_COUNT(pCD))
704 for (n= 0; n < pSD->acceleratorMenuCount; n++)
707 iconAccelSpec += SetupKeyBindings (
708 ACCELERATOR_MENU_SPECS(pCD)[n]->accelKeySpecs,
709 pCD->pWsList[i].iconFrameWin, GrabModeSync,
712 iconAccelSpec += SetupKeyBindings (
713 ACCELERATOR_MENU_SPECS(pCD)[n]->accelKeySpecs,
714 pCD->iconFrameWin, GrabModeSync,
726 * Setup keyboard focus handling if policy is "explicit".
729 if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)
731 DoExplicitSelectGrab (pCD->clientBaseWin);
735 UpdateWorkspacePresenceProperty(pCD);
740 * Make sure the client window has been reparented ...
743 if (!(manageFlags & MANAGEW_WM_CLIENTS))
745 XSync (DISPLAY, False);
747 if (pCD->clientFlags & CLIENT_DESTROYED)
749 UnManageWindow (pCD);
755 * Setup the initial display state for the client window:
758 initialState = pCD->clientState;
760 if (!ClientInWorkspace (pSD->pActiveWS, pCD))
762 initialState |= UNSEEN_STATE;
765 pCD->clientState = WITHDRAWN_STATE;
766 pCD->clientFlags &= ~WM_INITIALIZATION;
770 * Add to stacking list using the client's zero'th workspace
771 * instead of the current one because it may not be in
774 AddClientToList (GetWorkspaceData (pSD, pCD->pWsList[0].wsID),
775 pCD, True /*on top*/);
777 AddClientToList (pSD->pActiveWS, pCD, True /*on top*/);
779 SetClientState (pCD, initialState, GetTimestamp());
782 * Set the keyboard input focus to the newly managed window if appropriate:
783 * - focus is automatically set only if the focus policy is explicit
784 * - if there is a system modal window active then set the focus only
785 * if the new window is in the system modal heirarchy
786 * - focus is automatically set if startupKeyFocus is selected or
787 * the new window is a system modal window or the current focus window
788 * has the new window as an application modal subordinate
789 * - don't automatically set the focus if the window is minimized or
790 * is a window that generally doesn't take input
793 if ((wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT) &&
794 ((pCD->inputMode == MWM_INPUT_SYSTEM_MODAL) ||
795 ((!wmGD.systemModalActive ||
796 (wmGD.systemModalClient == FindTransientTreeLeader (pCD))) &&
797 (wmGD.startupKeyFocus ||
798 (wmGD.keyboardFocus && (IS_APP_MODALIZED(wmGD.keyboardFocus)))) &&
800 (MANAGEW_WM_STARTUP | MANAGEW_WM_RESTART | MANAGEW_WM_CLIENTS)) &&
801 (pCD->clientState != MINIMIZED_STATE) &&
803 !(pCD->clientState & UNSEEN_STATE) &&
805 (pCD->inputFocusModel ||
806 (pCD->protocolFlags & PROTOCOL_WM_TAKE_FOCUS)))))
808 Do_Focus_Key (pCD, GetTimestamp() , ALWAYS_SET_FOCUS);
810 else if ((pCD->inputMode == MWM_INPUT_SYSTEM_MODAL) ||
811 (wmGD.keyboardFocus && IS_APP_MODALIZED(wmGD.keyboardFocus)))
813 Do_Focus_Key ((ClientData *)NULL, GetTimestamp() , ALWAYS_SET_FOCUS);
817 if (smAckState == SM_START_ACK)
819 SendClientMsg( wmGD.dtSmWindow, (long) wmGD.xa_DT_SM_WM_PROTOCOL,
820 (long) wmGD.xa_DT_WM_WINDOW_ACK,
821 CurrentTime, NULL, 0);
825 * Free the initial property list. This will force
826 * reads of properties that change after the initial
827 * management (see HasProperty() function.)
829 DiscardInitialPropertyList (pCD);
833 CheckPushRecallClient (pCD);
834 #endif /* PANELIST */
836 } /* END OF FUNCTION ManageWindow */
840 /*************************************<->*************************************
842 * UnManageWindow (pCD)
847 * This function removes a top-level client window and it's transients
848 * from the set of windows that is managed by the window manager.
853 * pCD - pointer to client data of window to unmanage
855 *************************************<->***********************************/
857 void UnManageWindow (ClientData *pCD)
862 WmFpEmbeddedClientData *pECD;
864 pECD = (WmFpEmbeddedClientData *) pCD->pECD;
866 XtRemoveEventHandler(XtWindowToWidget (DISPLAY1, pECD->winParent),
867 (SubstructureRedirectMask | SubstructureNotifyMask),
869 (XtEventHandler)HandleSubstructEvents,
873 UpdateEmbeddedClientsProperty (pCD->pSD);
878 WmFpPushRecallClientData *pPRCD;
881 pPRCD = (WmFpPushRecallClientData *) pCD->pSD->pPRCD;
884 j < pCD->pSD->numPushRecallClients;
888 * Clean out all slots used by this client.
890 if ((!strcmp ((char *)pCD->clientName,
891 (char *)(pPRCD->pchResName))) &&
899 #endif /* PANELIST */
901 * Withdraw all the transient children of this window.
904 if (pCD->transientChildren != NULL)
906 WithdrawTransientChildren (pCD);
911 * If this is a transient window, then delete it from the leader's
912 * list of transients.
915 if (pCD->transientLeader)
917 DeleteTransient (pCD);
919 /* If this was a modal dialog box, then replay the event. */
920 if ( wmGD.replayEnterEvent )
922 XPutBackEvent( DISPLAY, (XEvent*)&wmGD.savedEnterEvent );
923 /* Reset event flag to false */
924 wmGD.replayEnterEvent = False;
930 * Withdraw this window
933 WithdrawWindow (pCD);
935 } /* END OF FUNCTION UnManageWindow */
939 /*************************************<->*************************************
941 * WithdrawTransientChildren (pCD)
946 * This function withdraws all transient children of the specified window.
951 * pCD = pointer to client data of the leader of the transient tree.
953 *************************************<->***********************************/
955 void WithdrawTransientChildren (ClientData *pCD)
961 pcdNext = pCD->transientChildren;
964 if (pcdNext->transientChildren)
966 WithdrawTransientChildren (pcdNext);
969 pcdNext = pcdThis->transientSiblings;
970 DeleteTransient(pcdThis);
971 WithdrawWindow (pcdThis);
974 } /* END OF FUNCTION WithdrawTransientChildren */
978 /*************************************<->*************************************
980 * WithdrawWindow (pCD)
985 * This function removes a top-level client window from the set of windows
986 * that is managed by the window manager. All window manager resources
987 * associtated with the client window are freed up (possibly cached for
988 * reuse). Any custom system menu is destroyed.
993 * pCD - pointer to client data of window to withdraw
995 *************************************<->***********************************/
997 void WithdrawWindow (ClientData *pCD)
1006 * Put the client window into a withdrawn state:
1008 * - remove the icon/client window from the screen
1009 * - make sure the input focus no longer is associted with the window
1010 * - free the icon placement (if necessary)
1013 SetClientWsIndex (pCD);
1016 if (!(pCD->clientFlags & WM_INITIALIZATION))
1018 if (!pCD->transientLeader)
1020 DeleteClientFromList (pCD->pSD->pActiveWS, pCD);
1022 ResetWithdrawnFocii (pCD);
1023 if (pCD->clientState & MINIMIZED_STATE)
1026 if (wmGD.iconAutoPlace && (!(P_ICON_BOX(pCD))))
1028 WmWorkspaceData *pWsTmp;
1033 * Clean up icon placement data in all inhabited
1036 for (j = 0; j< pCD->numInhabited; j++)
1038 pWsc = &(pCD->pWsList[j]);
1040 if (pWsc->iconPlace != NO_ICON_PLACE)
1042 if (pWsTmp=GetWorkspaceData(pCD->pSD, pWsc->wsID))
1044 pWsTmp->IPData.placeList[pWsc->iconPlace].pCD
1051 if (wmGD.iconAutoPlace && (!(P_ICON_BOX(pCD))))
1053 if (ICON_PLACE(pCD) != NO_ICON_PLACE)
1055 pCD->pSD->pActiveWS->IPData.placeList[ICON_PLACE(pCD)].pCD
1060 if (ICON_FRAME_WIN(pCD))
1062 XUnmapWindow (DISPLAY, ICON_FRAME_WIN(pCD));
1066 else if ((pCD->clientState == NORMAL_STATE) ||
1067 (pCD->clientState == MAXIMIZED_STATE))
1069 XUnmapWindow (DISPLAY, pCD->clientFrameWin);
1075 * Clean up the workspace presence dialog if it's
1076 * connected to this client.
1078 if ((pCD->pSD->presence.shellW) &&
1079 (pCD->pSD->presence.pCDforClient == pCD))
1081 if (pCD->pSD->presence.onScreen)
1083 HidePresenceBox (pCD->pSD, True);
1085 pCD->pSD->presence.pCDforClient = NULL;
1090 * Check to see if the window is being unmanaged because the window
1094 if (!(pCD->clientFlags & CLIENT_DESTROYED))
1098 if (XCheckTypedWindowEvent (DISPLAY, pCD->clientBaseWin, DestroyNotify,
1101 pCD->clientFlags |= CLIENT_DESTROYED;
1107 * Reparent the client window back to root if the window has been
1108 * reparented by the window manager. Remove the window from the
1109 * window managers save-set if necessary.
1112 if ((pCD->clientFlags & CLIENT_REPARENTED) &&
1113 !(pCD->clientFlags & CLIENT_DESTROYED))
1116 SetWMState (pCD->client, WithdrawnSTATE,
1117 pCD->pWsList[0].iconFrameWin);
1119 SetWMState (pCD->client, WithdrawnSTATE, ICON_FRAME_WIN(pCD));
1131 if(wmGD.positionIsFrame)
1133 CalculateGravityOffset (pCD, &xoff, &yoff);
1134 x = pCD->clientX - xoff;
1135 y = pCD->clientY - yoff;
1144 XUnmapWindow (DISPLAY, pCD->client);
1145 XReparentWindow (DISPLAY, pCD->client, ROOT_FOR_CLIENT(pCD), x, y);
1147 /* give the window back it's X border */
1148 xwc.border_width = pCD->xBorderWidth;
1149 XConfigureWindow(DISPLAY, pCD->client, CWBorderWidth, &xwc);
1151 if (pCD->iconWindow && (pCD->clientFlags & ICON_REPARENTED))
1153 XUnmapWindow (DISPLAY, pCD->iconWindow);
1155 XReparentWindow (DISPLAY, pCD->iconWindow, ROOT_FOR_CLIENT(pCD),
1156 pCD->pWsList[0].iconX, pCD->pWsList[0].iconY);
1158 XReparentWindow (DISPLAY, pCD->iconWindow, ROOT_FOR_CLIENT(pCD),
1159 ICON_X(pCD), ICON_Y(pCD));
1165 if ((pCD->clientFlags & CLIENT_IN_SAVE_SET) &&
1166 !(pCD->clientFlags & CLIENT_DESTROYED))
1168 XRemoveFromSaveSet (DISPLAY, pCD->client);
1170 if (pCD->iconWindow && (pCD->clientFlags & ICON_IN_SAVE_SET))
1172 XRemoveFromSaveSet (DISPLAY, pCD->iconWindow);
1177 * Free a custom system menu if one was created.
1180 FreeCustomMenuSpec (pCD->systemMenuSpec);
1183 * Free the client window frame:
1186 if (pCD->clientFrameWin)
1188 FreeClientFrame (pCD);
1193 * Free the icon associated with the client window:
1196 if ((pCD->iconFlags & ICON_HINTS_PIXMAP) && pCD->iconPixmap)
1198 XFreePixmap (DISPLAY, pCD->iconPixmap);
1202 if ((pCD->numInhabited > 0) && ICON_FRAME_WIN(pCD))
1204 if (ICON_FRAME_WIN(pCD))
1212 * Free up the client protocol list:
1215 if (pCD->clientProtocols)
1217 XtFree ((char *)pCD->clientProtocols);
1222 * Free up the mwm messages list:
1225 if (pCD->mwmMessages)
1227 XtFree ((char *)pCD->mwmMessages);
1232 * Delete client window manager timers:
1235 DeleteClientWmTimers (pCD);
1239 * Free up window context associations.
1241 DeleteClientContext (pCD);
1246 * Count backward for efficiency --
1247 * removes from end of list.
1249 for (i = pCD->numInhabited - 1; i >= 0; i--)
1251 TakeClientOutOfWorkspace (
1252 GetWorkspaceData(pCD->pSD, pCD->pWsList[i].wsID),
1258 * Free up window manager resources:
1261 if (!(pCD->clientFlags & CLIENT_WM_CLIENTS))
1263 if (pCD->clientName)
1265 XFree ((char *) (pCD->clientName));
1267 if (pCD->clientClass)
1269 XFree ((char *) (pCD->clientClass));
1273 if ((pCD->clientFlags & CLIENT_HINTS_TITLE) && pCD->clientTitle)
1275 XmStringFree (pCD->clientTitle);
1278 if ((pCD->iconFlags & ICON_HINTS_TITLE) && pCD->iconTitle)
1280 XmStringFree (pCD->iconTitle);
1283 if (pCD->clientCmapCount > 0)
1285 for (i = 0; i < pCD->clientCmapCount; i++)
1287 if (pCD->cmapWindows[i] != pCD->client)
1290 RemoveColormapWindowReference(pCD, pCD->cmapWindows[i]);
1292 XDeleteContext (DISPLAY, pCD->cmapWindows[i],
1293 wmGD.windowContextType);
1297 XtFree ((char *) (pCD->cmapWindows));
1298 XtFree ((char *) (pCD->clientCmapList));
1299 #ifndef OLD_COLORMAP /* colormap */
1300 XtFree ((char *) (pCD->clientCmapFlags));
1306 * Insure list of initial properties has been freed.
1308 DiscardInitialPropertyList (pCD);
1311 * free up list of workspace specific data
1315 XtFree ((char *) (pCD->pWsList));
1319 * free up workspace hints
1321 if (pCD->pWorkspaceHints)
1323 XtFree ((char *)pCD->pWorkspaceHints);
1327 if (pCD->smClientID)
1328 XFree (pCD->smClientID);
1331 * Clean up references to this data before we free it.
1333 if (wmGD.menuClient == pCD) {
1334 wmGD.menuClient = NULL;
1337 if (wmGD.gadgetClient == pCD) {
1338 wmGD.gadgetClient = NULL;
1339 wmGD.gadgetDepressed = 0;
1342 if (wmGD.clickData.pCD == pCD) {
1343 wmGD.clickData.pCD = NULL;
1346 if (wmGD.nextKeyboardFocus == pCD)
1347 wmGD.nextKeyboardFocus = NULL;
1348 if (wmGD.keyboardFocus == pCD)
1349 wmGD.keyboardFocus = NULL;
1352 * Fix for 5325 - Delete reference by dirty stack
1354 ClearDirtyStackEntry(pCD);
1356 XtFree ((char *)pCD);
1359 } /* END OF FUNCTION WithdrawWindow */
1363 /*************************************<->*************************************
1365 * DeleteClientContext (pCD)
1370 * This function deletes the client from the X context manager
1375 * pCD - pointer to client data
1383 *************************************<->***********************************/
1385 void DeleteClientContext (ClientData *pCD)
1388 * Free up window context associations. The context for the client
1389 * window is always set if there is a client data structure.
1392 XDeleteContext (DISPLAY, pCD->client, wmGD.windowContextType);
1393 if (pCD->clientFlags & CLIENT_CONTEXT_SAVED)
1395 XDeleteContext (DISPLAY, pCD->clientFrameWin, wmGD.windowContextType);
1396 XDeleteContext (DISPLAY, pCD->clientBaseWin, wmGD.windowContextType);
1397 if (DECOUPLE_TITLE_APPEARANCE(pCD))
1399 XDeleteContext (DISPLAY, pCD->clientTitleWin,
1400 wmGD.windowContextType);
1402 if (ICON_FRAME_WIN(pCD))
1407 for (k=0; k < pCD->numInhabited; k++)
1409 XDeleteContext (DISPLAY, pCD->pWsList[k].iconFrameWin,
1410 wmGD.windowContextType);
1413 XDeleteContext (DISPLAY, pCD->iconFrameWin,
1414 wmGD.windowContextType);
1417 pCD->clientFlags &= ~CLIENT_CONTEXT_SAVED;
1420 } /* END OF FUNCTION DeleteClientContext */
1424 /*************************************<->*************************************
1426 * ResetWitdrawnFocii (pCD)
1431 * This function resets the various types of focus if they are set to a
1432 * window being withdrawn.
1438 * pCD - pointer to client data
1446 *************************************<->***********************************/
1448 void ResetWithdrawnFocii (ClientData *pCD)
1450 if ((wmGD.keyboardFocus == pCD) ||
1451 /* BEGIN fix for CDExc21090 */
1452 ((wmGD.keyboardFocus == (ClientData *)NULL) &&
1453 (wmGD.nextKeyboardFocus == pCD) &&
1454 (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)))
1455 /* END fix for CDExc21090 */
1457 if (wmGD.autoKeyFocus &&
1458 (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT))
1460 /* local hack: if we've already received a map for a new
1461 ** focus window, be sure to use wmGD.nextKeyboardFocus; otherwise
1462 ** AutoResetKeyFocus chooses an essentially arbitrary window to
1465 if (wmGD.nextKeyboardFocus == pCD)
1466 AutoResetKeyFocus (pCD, GetTimestamp());
1468 Do_Focus_Key ((ClientData *)wmGD.nextKeyboardFocus,
1469 GetTimestamp(), ALWAYS_SET_FOCUS);
1474 * Set the focus to the default state if the focus is not in
1475 * the process of being set (i.e. a FocusIn event will be
1476 * comming along shortly.
1479 if (wmGD.nextKeyboardFocus == wmGD.keyboardFocus)
1481 Do_Focus_Key ((ClientData *)NULL, GetTimestamp(),
1482 ALWAYS_SET_FOCUS | WORKSPACE_IF_NULL);
1485 SetKeyboardFocus ((ClientData *)NULL, 0);
1488 if (((pCD->inputMode == MWM_INPUT_PRIMARY_APPLICATION_MODAL) ||
1489 (pCD->inputMode == MWM_INPUT_FULL_APPLICATION_MODAL)) &&
1490 (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_POINTER))
1493 * Repair the focus if an application modal dialog went
1494 * away. We may not see an enter event and have the focus
1495 * set to the wrong place.
1500 if (wmGD.nextKeyboardFocus == pCD)
1502 wmGD.nextKeyboardFocus = NULL;
1505 if (ACTIVE_PSD->colormapFocus == pCD)
1507 SetColormapFocus (ACTIVE_PSD, (ClientData *)NULL);
1510 } /* END OF FUNCTION ResetWithdrawnFocii */
1514 /*************************************<->*************************************
1516 * FreeClientFrame (pCD)
1521 * This function frees up frame windows and associated resources.
1526 * pCD - pointer to client data
1528 *************************************<->***********************************/
1530 void FreeClientFrame (ClientData *pCD)
1532 if (pCD->pclientTopShadows) {
1533 FreeRList (pCD->pclientTopShadows);
1534 pCD->pclientTopShadows = NULL;
1536 if (pCD->pclientBottomShadows) {
1537 FreeRList (pCD->pclientBottomShadows);
1538 pCD->pclientBottomShadows = NULL;
1540 if (pCD->pclientTitleTopShadows) {
1541 FreeRList (pCD->pclientTitleTopShadows);
1542 pCD->pclientTitleTopShadows = NULL;
1544 if (pCD->pclientTitleBottomShadows) {
1545 FreeRList (pCD->pclientTitleBottomShadows);
1546 pCD->pclientTitleBottomShadows = NULL;
1548 if (pCD->pclientMatteTopShadows) {
1549 FreeRList (pCD->pclientMatteTopShadows);
1550 pCD->pclientMatteTopShadows = NULL;
1552 if (pCD->pclientMatteBottomShadows) {
1553 FreeRList (pCD->pclientMatteBottomShadows);
1554 pCD->pclientMatteBottomShadows = NULL;
1556 if (pCD->pTitleGadgets) {
1557 XtFree ((char *)pCD->pTitleGadgets);
1558 pCD->pTitleGadgets = NULL;
1559 pCD->cTitleGadgets = 0;
1561 if (pCD->pResizeGadgets) {
1562 XtFree ((char *)pCD->pResizeGadgets);
1563 pCD->pResizeGadgets = NULL;
1566 /* destroy frame window & all children */
1567 XDestroyWindow (DISPLAY, pCD->clientFrameWin);
1569 } /* END OF FUNCTION FreeClientFrame */
1573 /*************************************<->*************************************
1580 * This function frees up icon windows and associated resources.
1585 * pCD - pointer to client data
1587 *************************************<->***********************************/
1589 void FreeIcon (ClientData *pCD)
1592 WmWorkspaceData *pWsTmp;
1596 if (pCD->piconTopShadows) {
1597 FreeRList (pCD->piconTopShadows);
1598 pCD->piconTopShadows = NULL;
1600 if (pCD->piconBottomShadows) {
1601 FreeRList (pCD->piconBottomShadows);
1602 pCD->piconBottomShadows = NULL;
1606 * destroy frame window & all children
1610 if ((pCD->pSD->useIconBox) && pCD->pWsList[0].pIconBox)
1613 * We're using icon boxes and it's in at least one ...
1614 * Delete from all workspaces we live in
1616 for (i = 0; i< pCD->numInhabited; i++)
1618 if (pWsTmp = GetWorkspaceData(pCD->pSD, pCD->pWsList[i].wsID))
1620 DeleteIconFromBox (pWsTmp->pIconBox, pCD);
1626 /* only one window, so destroying its first reference will
1627 * clean it up adequately
1629 if (pCD->pWsList[0].iconFrameWin)
1631 XDestroyWindow (DISPLAY, pCD->pWsList[0].iconFrameWin);
1635 if (pCD->pSD->useIconBox && P_ICON_BOX(pCD))
1637 DeleteIconFromBox (pCD->pSD->pActiveWS->pIconBox, pCD);
1641 XDestroyWindow (DISPLAY, pCD->iconFrameWin);
1645 } /* END OF FUNCTION FreeIcon */
1650 /*************************************<->*************************************
1652 * WithdrawDialog (dialogboxW)
1657 * This function removes a DialogBox widget "client" from the set of windows
1658 * that are managed by the window manager.
1663 * dialogboxW = DialogBox widget to withdraw.
1667 * Does not maintain the WM_STATE property on the dialog "client".
1669 *************************************<->***********************************/
1671 void WithdrawDialog (Widget dialogboxW)
1676 ClientData *pCD = NULL;
1679 * Get the dialog shell window client data.
1682 if (XFindContext (DISPLAY, XtWindow (XtParent (dialogboxW)),
1683 wmGD.windowContextType, (caddr_t *)&pCD))
1686 XtUnmanageChild (dialogboxW);
1687 DeleteClientFromList (ACTIVE_WS, pCD);
1689 /* TakeClientOutOfWorkspace (ACTIVE_WS, pCD); */
1692 * Count backward for efficiency --
1693 * removes from end of list.
1695 for (i = pCD->numInhabited - 1; i >= 0; i--)
1697 TakeClientOutOfWorkspace (
1698 GetWorkspaceData(pCD->pSD, pCD->pWsList[i].wsID),
1702 ResetWithdrawnFocii (pCD);
1703 XUnmapWindow (DISPLAY, pCD->clientFrameWin);
1705 } /* END OF FUNCTION WithdrawDialog */
1709 /*************************************<->*************************************
1711 * ReManageDialog (pSD, dialogboxW)
1716 * This function remanages a DialogBox "client" that was unmanaged via
1717 * WithdrawDialog ().
1722 * pSD = pointer to screen data
1723 * dialogboxW = DialogBox widget to remanage.
1728 * Does not maintain the WM_STATE property on the dialog "client".
1730 *************************************<->***********************************/
1732 void ReManageDialog (WmScreenData *pSD, Widget dialogboxW)
1734 ClientData *pCD = NULL;
1737 * Get the dialog shell window client data.
1740 if (XFindContext (DISPLAY, XtWindow (XtParent (dialogboxW)),
1741 wmGD.windowContextType, (caddr_t *)&pCD))
1745 * The order is important here:
1750 * Put system modal windows in all workspaces to
1751 * avoid the race condition of the window coming up
1752 * just as the user switches workspaces OR when
1753 * the window is up and a user switces workspaces
1754 * with a key binding. We may want to eventually short
1755 * circuit F_Functions any time there is a modal
1756 * window up, but for now, we will just make sure
1757 * the modal window appears in all workspaces
1760 pCD->dtwmFunctions |= DtWM_FUNCTION_OCCUPY_WS;
1761 F_AddToAllWorkspaces(0, pCD, 0);
1762 pCD->dtwmFunctions &= ~DtWM_FUNCTION_OCCUPY_WS;
1765 if (pSD->clientList)
1767 StackWindow (pSD->pActiveWS, &pCD->clientEntry,
1768 TRUE, (ClientListEntry *) NULL);
1770 AddClientToList (pSD->pActiveWS, pCD, True /*on top*/);
1771 XMapWindow (DISPLAY, pCD->clientFrameWin);
1772 XtManageChild (dialogboxW);
1774 if ((wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT))
1776 Do_Focus_Key (pCD, GetTimestamp() , ALWAYS_SET_FOCUS);
1780 } /* END OF FUNCTION ReManageDialog */
1784 /*************************************<->*************************************
1786 * RegisterEmbeddedClients (wPanelist, pECD, count)
1791 * This function registers a list of clients to be embedded in the
1792 * front panel subsystem.
1797 * wPanelist = front panel object (widget)
1798 * pECD = pointer to list of data for clients to embed
1799 * count = number of elements in the list
1805 *************************************<->***********************************/
1808 RegisterEmbeddedClients (
1810 WmFpEmbeddedClientList pECD,
1816 for (i= 0; i < wmGD.numScreens; i++)
1818 pSD = &(wmGD.Screens[i]);
1822 if (pSD->wPanelist == wPanelist)
1827 if (i < wmGD.numScreens)
1829 pSD->pECD = (struct _WmFpEmbeddedClientData *) pECD;
1830 pSD->numEmbeddedClients = count;
1835 fprintf (stderr, "Couldn't match wPanelist to screen data\n");
1839 } /* END OF FUNCTION RegisterEmbeddedClients */
1842 #define LTT_INCREMENT 16
1843 /*************************************<->*************************************
1845 * ListTransientSubtree (pCD, ppWins, pSize, pCount)
1850 * This function returns the list of windows in a transient window
1856 * pCD - pointer to client data of a window.
1857 * ppWins - address of a pointer to a list of windows
1858 * (this must be in the heap -- XtMalloc).
1859 * pSize - address of variable with size of list
1860 * pCount - address of variable with number of windows in list
1864 * *ppWins - may point to a new area of memory if list grows
1865 * *pSize - if list has to grow, this may be bigger
1866 * *pCount - number of windows in the list
1870 * The list should be freed when done with XtFree().
1872 *************************************<->***********************************/
1875 ListTransientSubtree (
1884 if (*pCount == *pSize)
1886 *pSize += LTT_INCREMENT;
1887 *ppWins = (Window *)
1888 XtRealloc ((char *) *ppWins, (*pSize * sizeof(Window)));
1891 * Add this window to the list
1893 (*ppWins)[*pCount] = pCD->client;
1899 if (pCD->transientSiblings)
1900 ListTransientSubtree (pCD->transientSiblings, ppWins, pSize, pCount);
1905 if (pCD->transientChildren)
1906 ListTransientSubtree (pCD->transientChildren, ppWins, pSize, pCount);
1909 } /* END OF FUNCTION ListTransientSubtree */
1913 /*************************************<->*************************************
1915 * ListTransientTree (pCD)
1920 * This function returns the list of windows in a transient window
1926 * pCD - pointer to client data of a primary window.
1934 * The list should be freed when done with XtFree().
1936 *************************************<->***********************************/
1947 * Initial allocation
1949 iSize = LTT_INCREMENT;
1950 pWins = (Window *) XtMalloc (iSize * sizeof(Window));
1954 * Add this window to the list
1956 ListTransientSubtree (pCD, &pWins, &iSize, &count);
1959 * Add terminator to end of window list
1963 iSize += LTT_INCREMENT;
1965 XtRealloc ((char *)pWins, (iSize * sizeof(Window)));
1967 pWins[count++] = None;
1970 * Return the list of windows found
1974 } /* END OF FUNCTION ListTransientTree */
1977 /*************************************<->*************************************
1979 * ReManageWindow (pCD)
1984 * This function unmanages and remanages a window and it's associated
1990 * pCD - pointer to client data of a primary window.
1998 * The pointer pCD is invalid after calling this function -- a
1999 * side-effect of unmanaging the client before remanaging it.
2001 *************************************<->***********************************/
2007 long manageFlags = MANAGEW_NORMAL;
2012 * Get the list of windows in the transient window tree.
2014 pWins = ListTransientTree (pCD);
2019 * Unmanage this window and associated transients
2021 UnManageWindow (pCD);
2023 /*** pCD is no longer a valid pointer!!! ***/
2026 * Remanage this window and its secondaries
2031 ManageWindow (pSD, *pW, manageFlags);
2035 XtFree ((char *) pWins);
2037 } /* END OF FUNCTION ReManageWindow */
2041 /*************************************<->*************************************
2043 * ScanForEmbeddedClients (pSD)
2048 * This function scans the managed windows and identifies those that
2049 * should be embedded clients in the front panel
2054 * pSD - pointer to screen data.
2059 *************************************<->***********************************/
2062 ScanForEmbeddedClients (
2066 ClientListEntry *pCLE;
2067 WmFpEmbeddedClientData *pECD;
2069 long manageFlags = 0L;
2073 * Search through all the windows we're managing right now to
2074 * see if any should be embedded in a front/sub panel.
2076 pCLE = pSD->clientList;
2079 while (pCLE != NULL)
2082 * See if this is an previously unrecognized embedded client
2086 if ((pCD->pECD == NULL ) && IsEmbeddedClient (pCD, &pECD))
2089 * Remanage this window and associated transients
2091 ReManageWindow (pCD);
2093 * At this point pCD is no longer valid and the
2094 * pSD->clientList has been changed.
2100 * Test for exit condition
2102 if (pCLE == pSD->lastClient)
2105 * Gone all the way through the list without finding
2106 * anything -- time to quit
2113 * Remanaging a client restructures the client list.
2114 * Start over at the beginning.
2117 pCLE = pSD->clientList;
2122 * Move to next client.
2124 pCLE = pCLE->nextSibling;
2128 } /* END OF FUNCTION ScanForEmbeddedClients */
2131 /*************************************<->*************************************
2133 * IsEmbeddedClient (pCD, ppECD)
2138 * This function tests a a client to see if it should be embedded
2139 * in the front panel.
2144 * pCD = ptr to Client Data
2145 * ppECD = ptr to returned embedded client data ptr
2150 * *ppECD = ptr to embedded client data
2152 *************************************<->***********************************/
2156 IsEmbeddedClient (ClientData *pCD, WmFpEmbeddedClientData **ppECD)
2161 Boolean bFoundMatch = False;
2162 WmFpEmbeddedClientData *pECD;
2165 pECD = (WmFpEmbeddedClientData *) pSD->pECD;
2167 for (i = 0; i < pSD->numEmbeddedClients && !bFoundMatch; i++, pECD++)
2170 * It's an embedded client if
2171 * the resource name matches a slot and
2172 * it's not a subpanel and
2173 * the slot isn't already filled.
2175 if ((!strcmp ((char *)pCD->clientName,
2176 (char *)(pECD->pchResName))) &&
2177 (!(pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUBPANEL)) &&
2184 return (bFoundMatch);
2186 } /* END OF FUNCTION IsEmbeddedClient */
2189 /******************************<->*************************************
2191 * ManageEmbeddedClient (pCD, pECD, manageFlags)
2196 * This is the function that is used to setup a client window
2197 * in the front panel.
2201 * pCD = initialized client data, including window of client that
2202 * we want to manage.
2203 * pECD = ptr to embedded client entry for this client
2205 * manageFlags = additional control information
2209 * Returns False if normal client processing needs to be done.
2211 * Returns True if this client has been embedded directly in the
2212 * front panel and is NOT to be managed as a normal top level
2213 * window--no further processing required.
2214 ******************************<->***********************************/
2217 ManageEmbeddedClient (
2219 WmFpEmbeddedClientData *pECD,
2225 XWindowChanges windowChanges;
2227 WmFpPushRecallClientData *pPRCD;
2235 * Add to all workspaces
2237 pCD->dtwmFunctions |= DtWM_FUNCTION_OCCUPY_WS;
2239 F_AddToAllWorkspaces(0, pCD, 0);
2241 pCD->dtwmFunctions &= ~DtWM_FUNCTION_OCCUPY_WS;
2244 * Set client list entries
2245 * (in a list by itself)
2247 pCD->clientEntry.type = NORMAL_STATE;
2248 pCD->clientEntry.pCD = pCD;
2249 pCD->clientEntry.nextSibling = NULL;
2250 pCD->clientEntry.prevSibling = NULL;
2252 pCD->iconEntry.type = MINIMIZED_STATE;
2253 pCD->iconEntry.pCD = pCD;
2254 pCD->iconEntry.nextSibling = NULL;
2255 pCD->iconEntry.prevSibling = NULL;
2258 * Save context for event processing.
2262 XSaveContext (DISPLAY, pCD->client, wmGD.windowContextType,
2265 if (!(pCD->clientFlags & CLIENT_WM_CLIENTS))
2267 XChangeSaveSet (DISPLAY, pCD->client, SetModeInsert);
2268 XChangeSaveSet (DISPLAY1, pCD->client, SetModeInsert);
2269 pCD->clientFlags |= CLIENT_IN_SAVE_SET;
2271 if (!(manageFlags & MANAGEW_WM_CLIENTS))
2273 XSync (DISPLAY1, False);
2275 if (pCD->clientFlags & CLIENT_DESTROYED)
2277 UnManageWindow (pCD);
2282 XtAddEventHandler(XtWindowToWidget (DISPLAY1, pECD->winParent),
2283 (SubstructureRedirectMask | SubstructureNotifyMask),
2285 (XtEventHandler)HandleSubstructEvents,
2289 * Fill in more client data
2291 pCD->clientX = pECD->x;
2292 pCD->clientY = pECD->y;
2293 pCD->clientWidth = pECD->width;
2294 pCD->clientHeight = pECD->height;
2296 pCD->clientFrameWin = 0;
2297 pCD->clientBaseWin = pECD->winParent;
2300 pCD->pECD = (void *) pECD;
2303 SetClientWsIndex(pCD);
2305 SetClientWMState (pCD, NormalState, NORMAL_STATE);
2308 * Set state on subpanel in case it never gets mapped
2309 * to prevent session manager from finding an embedded
2310 * client on its own.
2312 ForceSubpanelWMState (pECD->winParent);
2314 XReparentWindow (DISPLAY1, pCD->client,
2317 pCD->clientFlags |= CLIENT_REPARENTED;
2319 windowChanges.width = pECD->width;
2320 windowChanges.height = pECD->height;
2321 windowChanges.border_width = 0;
2322 mask = (CWWidth | CWHeight | CWBorderWidth);
2324 XConfigureWindow (DISPLAY1, pCD->client, mask, &windowChanges);
2326 XMapWindow (DISPLAY1, pCD->client);
2327 if (pCD->iconWindow)
2329 XUnmapWindow (DISPLAY, pCD->iconWindow);
2332 UpdateEmbeddedClientsProperty (pCD->pSD);
2334 SendConfigureNotify (pCD);
2336 if (IsPushRecallClient (pCD, &pPRCD))
2339 * There should only be one instance of this
2340 * client started from a front panel button.
2343 pCD->pPRCD = (void *) pPRCD;
2348 return(True); /* successful embedation */
2350 } /* END OF FUNCTION ManageEmbeddedClient */
2353 /******************************<->*************************************
2355 * ReparentEmbeddedClient (pECD, newControl, newWin, x, y, width, height)
2363 * pECD = ptr to embedded client entry for this client
2364 * newControl = widget for new "parent" widget
2365 * newWin = window ID of window that this embedded client will be
2366 * a parent of. This is needed in case the control is a
2368 * x = x-coord position within newWin where UL corner of the embedded
2370 * y = y-coord as described above.
2371 * width = desired width of embedded client in this new location
2372 * height = desired height as above.
2377 * Returns False if embedded client was is not moved to the new
2380 * Returns True if this client has been reparented to the new
2382 ******************************<->***********************************/
2385 ReparentEmbeddedClient (
2386 WmFpEmbeddedClientData *pECD,
2398 XWindowChanges windowChanges;
2400 WmFpPushRecallClientData *pPRCD;
2404 * If we have bogus data or if we're asked
2405 * to reparent to our current parent, then just
2408 if ((pECD == NULL) ||
2409 (pECD->pCD == NULL) ||
2410 (pECD->winParent == newWin))
2417 * Need event handler on new parent window?
2419 if (newWin != pECD->winParent)
2421 XtRemoveEventHandler(XtWindowToWidget (DISPLAY1, pECD->winParent),
2422 (SubstructureRedirectMask | SubstructureNotifyMask),
2424 (XtEventHandler)HandleSubstructEvents,
2427 XtAddEventHandler(XtWindowToWidget (DISPLAY1, newWin),
2428 (SubstructureRedirectMask | SubstructureNotifyMask),
2430 (XtEventHandler)HandleSubstructEvents,
2435 * Update embedding and client data
2437 pECD->wControl = newControl;
2438 pECD->winParent = newWin;
2439 pCD->clientX = pECD->x = x;
2440 pCD->clientY = pECD->y = y;
2441 pCD->clientWidth = pECD->width = width;
2442 pCD->clientHeight = pECD->height = height;
2443 pCD->clientBaseWin = pECD->winParent;
2446 * Set state on subpanel in case it never gets mapped
2447 * to prevent session manager from finding an embedded
2448 * client on its own.
2450 ForceSubpanelWMState (pECD->winParent);
2453 * Do the actual reparent
2455 XReparentWindow (DISPLAY1, pCD->client,
2460 * Configure the embedded client
2462 windowChanges.width = pECD->width;
2463 windowChanges.height = pECD->height;
2464 windowChanges.border_width = 0;
2465 mask = (CWWidth | CWHeight | CWBorderWidth);
2467 XConfigureWindow (DISPLAY1, pCD->client, mask, &windowChanges);
2469 XMapWindow (DISPLAY1, pCD->client);
2471 UpdateEmbeddedClientsProperty (pCD->pSD);
2473 SendConfigureNotify (pCD);
2475 return(True); /* successful reparent */
2477 } /* END OF FUNCTION ReparentEmbeddedClient */
2480 /*************************************<->*************************************
2482 * ForceSubpanelWMState (win)
2487 * This function forces a WM_STATE property on a subpanel window
2488 * so that the session manager doesn't save multiple copies
2489 * of embedded clients for subpanels that never get mapped.
2494 * win = window ID of a subpanel window (not necessarily the top level!)
2500 *************************************<->***********************************/
2503 ForceSubpanelWMState (Window win)
2505 ClientData *pCD = NULL;
2506 Window root, parent;
2507 Window *children = NULL;
2508 unsigned int numChildren;
2509 PropWMState *wmStateProp;
2510 Boolean bDone = False;
2514 if (!XQueryTree (DISPLAY, win, &root, &parent,
2515 &children, &numChildren))
2520 if (!XFindContext(DISPLAY, win, wmGD.windowContextType,
2524 * Only continue if we're not already managing this subpanel.
2528 else if (parent == root)
2530 if (wmStateProp = GetWMState (win))
2533 * Already has a WM_STATE.
2535 XFree ((char *)wmStateProp);
2540 * Add a dummy WM_STATE to foil the session manager
2543 SetWMState (win, WITHDRAWN_STATE, 0);
2549 /* continue ascent up to root */
2553 XFree ((char *) children);
2556 } /* END OF FUNCTION ForceSubpanelWMState */
2559 /*************************************<->*************************************
2561 * RegisterPushRecallClients (wPanelist, pPRCD, count)
2566 * This function registers a list of push_recallclients for the
2567 * front panel subsystem.
2572 * wPanelist = front panel object (widget)
2573 * pPRCD = pointer to list of data for clients
2574 * count = number of elements in the list
2580 *************************************<->***********************************/
2583 RegisterPushRecallClients (
2585 WmFpPushRecallClientList pPRCD,
2591 for (i= 0; i < wmGD.numScreens; i++)
2593 pSD = &(wmGD.Screens[i]);
2597 if (pSD->wPanelist == wPanelist)
2602 if (i < wmGD.numScreens)
2604 pSD->pPRCD = (struct _WmFpPushRecallClientData *) pPRCD;
2605 pSD->numPushRecallClients = count;
2610 fprintf (stderr, "Couldn't match wPanelist to screen data\n");
2614 for (i = 0; i < pSD->numPushRecallClients ; i++, pPRCD++)
2617 * Initialize data in each slot
2619 pPRCD->tvTimeout.tv_sec = 0;
2622 } /* END OF FUNCTION RegisterPushRecallClients */
2625 /*************************************<->*************************************
2627 * IsPushRecallClient (pCD, ppPRCD)
2632 * This function tests a a client to see if it should be embedded
2633 * in the front panel.
2638 * pCD = ptr to Client Data
2639 * ppPRCD = ptr to returned embedded client data ptr
2644 * *ppPRCD = ptr to embedded client data
2646 *************************************<->***********************************/
2650 IsPushRecallClient (ClientData *pCD, WmFpPushRecallClientData **ppPRCD)
2655 Boolean bFoundMatch = False;
2656 WmFpPushRecallClientData *pPRCD;
2659 pPRCD = (WmFpPushRecallClientData *) pSD->pPRCD;
2661 for (i = 0; i < pSD->numPushRecallClients && !bFoundMatch; i++, pPRCD++)
2664 * It's a push_recall client if the resource name matches
2665 * a slot and the slot isn't already filled.
2667 if ((!strcmp ((char *)pCD->clientName,
2668 (char *)(pPRCD->pchResName))) &&
2675 return (bFoundMatch);
2677 } /* END OF FUNCTION IsPushRecallClient */
2680 /*************************************<->*************************************
2682 * ScanForPushRecallClients (pSD)
2687 * This function scans the managed windows and identifies those that
2688 * should be push recall clients of the front panel
2693 * pSD - pointer to screen data.
2698 *************************************<->***********************************/
2701 ScanForPushRecallClients (
2705 ClientListEntry *pCLE;
2706 WmFpPushRecallClientData *pPRCD;
2709 * Search through all the windows we're managing right now
2711 pCLE = pSD->clientList;
2713 while (pCLE != NULL)
2716 * See if this is an previously unrecognized push recall client
2720 if ((pCD->pPRCD == NULL ) && IsPushRecallClient (pCD, &pPRCD))
2722 CheckPushRecallClient (pCD);
2726 * Test for exit condition
2728 if (pCLE == pSD->lastClient)
2731 * Gone all the way through the list without finding
2732 * anything -- time to quit
2739 * Move to next client.
2741 pCLE = pCLE->nextSibling;
2745 } /* END OF FUNCTION ScanForPushRecallClients */
2748 /******************************<->*************************************
2750 * static void CheckPushRecallClient (pCD)
2755 * Checks a client against the list of push recall clients to see
2756 * if there are any matches. All matches are marked.
2760 * pCD - pointer to the Client Data structure
2768 ******************************<->***********************************/
2770 CheckPushRecallClient(
2773 WmFpPushRecallClientData *pPRCD;
2775 while (IsPushRecallClient (pCD, &pPRCD))
2778 * There should only be one instance of this
2779 * client started from a front panel button.
2782 pPRCD->tvTimeout.tv_sec = 0;
2784 pCD->pPRCD = (void *) pPRCD;
2789 /******************************<->*************************************
2791 * static void HandleSubstructEvents (Widget w, caddr_t pCD, XEvent *event)
2796 * Causes death of embedded clients to run through UnManageWindow()
2797 * for proper cleanup.
2799 * Note there is one of these event handlers instantiated for
2800 * each live client window in the front panel. Hence, for each
2801 * live client window death, each of the event handlers gets called
2802 * once. We need to ensure that we've got the right pCD before
2803 * calling UnManageWindow() on it.
2809 * pCD - pointer to the Client Data structure
2810 * event - we only care about UnMapNotify
2817 * This routine is called LOTS of times, for all types of events.
2819 ******************************<->***********************************/
2821 HandleSubstructEvents(
2826 struct _ClientData *pCD = (struct _ClientData *)ptr;
2828 switch (event->type)
2832 if (pCD->client == event->xunmap.window)
2834 UnManageWindow (pCD);
2839 } /* END OF FUNCTION HandleSubstructEvents */
2842 /*******************************<->*************************************
2844 * UpdateEmbeddedClientsProperty (pSD)
2851 * pSD - pointer to the screen data
2855 * True if successful, False otherwise.
2859 * The _DT_WORKSPACE_EMBEDDED_CLIENTS property on the
2860 * root window for the screen will be updated to reflect the
2861 * current contents of the front panel
2864 ******************************<->***********************************/
2866 UpdateEmbeddedClientsProperty(
2869 unsigned int numClients = 0;
2870 Window *pClients = NULL;
2871 Boolean rval = True;
2873 WmFpEmbeddedClientData *pECD;
2875 pECD = (WmFpEmbeddedClientData *) pSD->pECD;
2877 for (i = 0; i < pSD->numEmbeddedClients; i++, pECD++)
2885 pClients = (Window *) XtMalloc (sizeof(Window));
2889 pClients = (Window *) XtRealloc ((char *)pClients,
2890 (numClients * (sizeof(Window))));
2896 ((char *)GETMESSAGE(4, 17, "Insufficient memory to write _DT_WORKSPACE_EMBEDDED_CLIENTS."))
2903 pClients[numClients-1] = pECD->pCD->client;
2908 SetEmbeddedClientsProperty (pSD->rootWindow, pClients,
2911 if (pClients != NULL)
2913 XtFree ((char *)pClients);
2917 } /* END OF FUNCTION UpdateEmbeddedClientsProperty */
2921 /*******************************<->*************************************
2923 * UnParentControls (pSD, unmap)
2930 * pSD - pointer to the screen data
2931 * unmap - if True, then unmap the windows after reparenting to root
2939 * Reparents clients embedded in the front panel back to the
2942 ******************************<->***********************************/
2950 WmFpEmbeddedClientData *pECD;
2952 if (pSD && pSD->managed)
2954 pECD = (WmFpEmbeddedClientData *) pSD->pECD;
2955 for (i = 0; i < pSD->numEmbeddedClients; i++, pECD++)
2961 if ((pCD->clientFlags & CLIENT_IN_SAVE_SET) &&
2962 !(pCD->clientFlags & CLIENT_DESTROYED))
2964 XRemoveFromSaveSet (DISPLAY, pCD->client);
2965 XRemoveFromSaveSet (DISPLAY1, pCD->client);
2968 XReparentWindow (DISPLAY,
2975 XUnmapWindow (DISPLAY, pCD->client);
2976 if (pCD->iconWindow)
2978 if (pCD->clientFlags & ICON_IN_SAVE_SET)
2980 XRemoveFromSaveSet (DISPLAY, pCD->iconWindow);
2981 pCD->clientFlags &= ~ICON_IN_SAVE_SET;
2983 XUnmapWindow (DISPLAY, pCD->iconWindow);
2990 } /* END OF FUNCTION UnParentControl */
2994 /*************************************<->*************************************
2996 * RegisterIconBoxControl (wPanelist)
3001 * This function registers the icon box control in a front panel
3006 * wPanelist = front panel object (widget)
3011 *************************************<->***********************************/
3014 RegisterIconBoxControl (Widget wPanelist)
3019 for (i= 0; i < wmGD.numScreens; i++)
3021 pSD = &(wmGD.Screens[i]);
3025 if (pSD->wPanelist == wPanelist)
3030 if (i < wmGD.numScreens)
3032 pSD->iconBoxControl = True;
3033 pSD->useIconBox = True;
3038 fprintf (stderr, "Couldn't match wPanelist to screen data\n");
3042 } /* END OF FUNCTION RegisterIconBoxControl */
3044 #endif /* PANELIST */