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 libraries 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 hierarchy
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 * coming 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;
2071 * Search through all the windows we're managing right now to
2072 * see if any should be embedded in a front/sub panel.
2074 pCLE = pSD->clientList;
2077 while (pCLE != NULL)
2080 * See if this is an previously unrecognized embedded client
2084 if ((pCD->pECD == NULL ) && IsEmbeddedClient (pCD, &pECD))
2087 * Remanage this window and associated transients
2089 ReManageWindow (pCD);
2091 * At this point pCD is no longer valid and the
2092 * pSD->clientList has been changed.
2098 * Test for exit condition
2100 if (pCLE == pSD->lastClient)
2103 * Gone all the way through the list without finding
2104 * anything -- time to quit
2111 * Remanaging a client restructures the client list.
2112 * Start over at the beginning.
2115 pCLE = pSD->clientList;
2120 * Move to next client.
2122 pCLE = pCLE->nextSibling;
2126 } /* END OF FUNCTION ScanForEmbeddedClients */
2129 /*************************************<->*************************************
2131 * IsEmbeddedClient (pCD, ppECD)
2136 * This function tests a a client to see if it should be embedded
2137 * in the front panel.
2142 * pCD = ptr to Client Data
2143 * ppECD = ptr to returned embedded client data ptr
2148 * *ppECD = ptr to embedded client data
2150 *************************************<->***********************************/
2154 IsEmbeddedClient (ClientData *pCD, WmFpEmbeddedClientData **ppECD)
2159 Boolean bFoundMatch = False;
2160 WmFpEmbeddedClientData *pECD;
2163 pECD = (WmFpEmbeddedClientData *) pSD->pECD;
2165 for (i = 0; i < pSD->numEmbeddedClients && !bFoundMatch; i++, pECD++)
2168 * It's an embedded client if
2169 * the resource name matches a slot and
2170 * it's not a subpanel and
2171 * the slot isn't already filled.
2173 if ((!strcmp ((char *)pCD->clientName,
2174 (char *)(pECD->pchResName))) &&
2175 (!(pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUBPANEL)) &&
2182 return (bFoundMatch);
2184 } /* END OF FUNCTION IsEmbeddedClient */
2187 /******************************<->*************************************
2189 * ManageEmbeddedClient (pCD, pECD, manageFlags)
2194 * This is the function that is used to setup a client window
2195 * in the front panel.
2199 * pCD = initialized client data, including window of client that
2200 * we want to manage.
2201 * pECD = ptr to embedded client entry for this client
2203 * manageFlags = additional control information
2207 * Returns False if normal client processing needs to be done.
2209 * Returns True if this client has been embedded directly in the
2210 * front panel and is NOT to be managed as a normal top level
2211 * window--no further processing required.
2212 ******************************<->***********************************/
2215 ManageEmbeddedClient (
2217 WmFpEmbeddedClientData *pECD,
2221 XWindowChanges windowChanges;
2223 WmFpPushRecallClientData *pPRCD;
2231 * Add to all workspaces
2233 pCD->dtwmFunctions |= DtWM_FUNCTION_OCCUPY_WS;
2235 F_AddToAllWorkspaces(0, pCD, 0);
2237 pCD->dtwmFunctions &= ~DtWM_FUNCTION_OCCUPY_WS;
2240 * Set client list entries
2241 * (in a list by itself)
2243 pCD->clientEntry.type = NORMAL_STATE;
2244 pCD->clientEntry.pCD = pCD;
2245 pCD->clientEntry.nextSibling = NULL;
2246 pCD->clientEntry.prevSibling = NULL;
2248 pCD->iconEntry.type = MINIMIZED_STATE;
2249 pCD->iconEntry.pCD = pCD;
2250 pCD->iconEntry.nextSibling = NULL;
2251 pCD->iconEntry.prevSibling = NULL;
2254 * Save context for event processing.
2258 XSaveContext (DISPLAY, pCD->client, wmGD.windowContextType,
2261 if (!(pCD->clientFlags & CLIENT_WM_CLIENTS))
2263 XChangeSaveSet (DISPLAY, pCD->client, SetModeInsert);
2264 XChangeSaveSet (DISPLAY1, pCD->client, SetModeInsert);
2265 pCD->clientFlags |= CLIENT_IN_SAVE_SET;
2267 if (!(manageFlags & MANAGEW_WM_CLIENTS))
2269 XSync (DISPLAY1, False);
2271 if (pCD->clientFlags & CLIENT_DESTROYED)
2273 UnManageWindow (pCD);
2278 XtAddEventHandler(XtWindowToWidget (DISPLAY1, pECD->winParent),
2279 (SubstructureRedirectMask | SubstructureNotifyMask),
2281 (XtEventHandler)HandleSubstructEvents,
2285 * Fill in more client data
2287 pCD->clientX = pECD->x;
2288 pCD->clientY = pECD->y;
2289 pCD->clientWidth = pECD->width;
2290 pCD->clientHeight = pECD->height;
2292 pCD->clientFrameWin = 0;
2293 pCD->clientBaseWin = pECD->winParent;
2296 pCD->pECD = (void *) pECD;
2299 SetClientWsIndex(pCD);
2301 SetClientWMState (pCD, NormalState, NORMAL_STATE);
2304 * Set state on subpanel in case it never gets mapped
2305 * to prevent session manager from finding an embedded
2306 * client on its own.
2308 ForceSubpanelWMState (pECD->winParent);
2310 XReparentWindow (DISPLAY1, pCD->client,
2313 pCD->clientFlags |= CLIENT_REPARENTED;
2315 windowChanges.width = pECD->width;
2316 windowChanges.height = pECD->height;
2317 windowChanges.border_width = 0;
2318 mask = (CWWidth | CWHeight | CWBorderWidth);
2320 XConfigureWindow (DISPLAY1, pCD->client, mask, &windowChanges);
2322 XMapWindow (DISPLAY1, pCD->client);
2323 if (pCD->iconWindow)
2325 XUnmapWindow (DISPLAY, pCD->iconWindow);
2328 UpdateEmbeddedClientsProperty (pCD->pSD);
2330 SendConfigureNotify (pCD);
2332 if (IsPushRecallClient (pCD, &pPRCD))
2335 * There should only be one instance of this
2336 * client started from a front panel button.
2339 pCD->pPRCD = (void *) pPRCD;
2344 return(True); /* successful embedation */
2346 } /* END OF FUNCTION ManageEmbeddedClient */
2349 /******************************<->*************************************
2351 * ReparentEmbeddedClient (pECD, newControl, newWin, x, y, width, height)
2359 * pECD = ptr to embedded client entry for this client
2360 * newControl = widget for new "parent" widget
2361 * newWin = window ID of window that this embedded client will be
2362 * a parent of. This is needed in case the control is a
2364 * x = x-coord position within newWin where UL corner of the embedded
2366 * y = y-coord as described above.
2367 * width = desired width of embedded client in this new location
2368 * height = desired height as above.
2373 * Returns False if embedded client was is not moved to the new
2376 * Returns True if this client has been reparented to the new
2378 ******************************<->***********************************/
2381 ReparentEmbeddedClient (
2382 WmFpEmbeddedClientData *pECD,
2392 XWindowChanges windowChanges;
2397 * If we have bogus data or if we're asked
2398 * to reparent to our current parent, then just
2401 if ((pECD == NULL) ||
2402 (pECD->pCD == NULL) ||
2403 (pECD->winParent == newWin))
2410 * Need event handler on new parent window?
2412 if (newWin != pECD->winParent)
2414 XtRemoveEventHandler(XtWindowToWidget (DISPLAY1, pECD->winParent),
2415 (SubstructureRedirectMask | SubstructureNotifyMask),
2417 (XtEventHandler)HandleSubstructEvents,
2420 XtAddEventHandler(XtWindowToWidget (DISPLAY1, newWin),
2421 (SubstructureRedirectMask | SubstructureNotifyMask),
2423 (XtEventHandler)HandleSubstructEvents,
2428 * Update embedding and client data
2430 pECD->wControl = newControl;
2431 pECD->winParent = newWin;
2432 pCD->clientX = pECD->x = x;
2433 pCD->clientY = pECD->y = y;
2434 pCD->clientWidth = pECD->width = width;
2435 pCD->clientHeight = pECD->height = height;
2436 pCD->clientBaseWin = pECD->winParent;
2439 * Set state on subpanel in case it never gets mapped
2440 * to prevent session manager from finding an embedded
2441 * client on its own.
2443 ForceSubpanelWMState (pECD->winParent);
2446 * Do the actual reparent
2448 XReparentWindow (DISPLAY1, pCD->client,
2453 * Configure the embedded client
2455 windowChanges.width = pECD->width;
2456 windowChanges.height = pECD->height;
2457 windowChanges.border_width = 0;
2458 mask = (CWWidth | CWHeight | CWBorderWidth);
2460 XConfigureWindow (DISPLAY1, pCD->client, mask, &windowChanges);
2462 XMapWindow (DISPLAY1, pCD->client);
2464 UpdateEmbeddedClientsProperty (pCD->pSD);
2466 SendConfigureNotify (pCD);
2468 return(True); /* successful reparent */
2470 } /* END OF FUNCTION ReparentEmbeddedClient */
2473 /*************************************<->*************************************
2475 * ForceSubpanelWMState (win)
2480 * This function forces a WM_STATE property on a subpanel window
2481 * so that the session manager doesn't save multiple copies
2482 * of embedded clients for subpanels that never get mapped.
2487 * win = window ID of a subpanel window (not necessarily the top level!)
2493 *************************************<->***********************************/
2496 ForceSubpanelWMState (Window win)
2498 ClientData *pCD = NULL;
2499 Window root, parent;
2500 Window *children = NULL;
2501 unsigned int numChildren;
2502 PropWMState *wmStateProp;
2503 Boolean bDone = False;
2507 if (!XQueryTree (DISPLAY, win, &root, &parent,
2508 &children, &numChildren))
2513 if (!XFindContext(DISPLAY, win, wmGD.windowContextType,
2517 * Only continue if we're not already managing this subpanel.
2521 else if (parent == root)
2523 if ((wmStateProp = GetWMState (win)))
2526 * Already has a WM_STATE.
2528 XFree ((char *)wmStateProp);
2533 * Add a dummy WM_STATE to foil the session manager
2536 SetWMState (win, WITHDRAWN_STATE, 0);
2542 /* continue ascent up to root */
2546 XFree ((char *) children);
2549 } /* END OF FUNCTION ForceSubpanelWMState */
2552 /*************************************<->*************************************
2554 * RegisterPushRecallClients (wPanelist, pPRCD, count)
2559 * This function registers a list of push_recallclients for the
2560 * front panel subsystem.
2565 * wPanelist = front panel object (widget)
2566 * pPRCD = pointer to list of data for clients
2567 * count = number of elements in the list
2573 *************************************<->***********************************/
2576 RegisterPushRecallClients (
2578 WmFpPushRecallClientList pPRCD,
2584 for (i= 0; i < wmGD.numScreens; i++)
2586 pSD = &(wmGD.Screens[i]);
2590 if (pSD->wPanelist == wPanelist)
2595 if (i < wmGD.numScreens)
2597 pSD->pPRCD = (struct _WmFpPushRecallClientData *) pPRCD;
2598 pSD->numPushRecallClients = count;
2603 fprintf (stderr, "Couldn't match wPanelist to screen data\n");
2607 for (i = 0; i < pSD->numPushRecallClients ; i++, pPRCD++)
2610 * Initialize data in each slot
2612 pPRCD->tvTimeout.tv_sec = 0;
2615 } /* END OF FUNCTION RegisterPushRecallClients */
2618 /*************************************<->*************************************
2620 * IsPushRecallClient (pCD, ppPRCD)
2625 * This function tests a a client to see if it should be embedded
2626 * in the front panel.
2631 * pCD = ptr to Client Data
2632 * ppPRCD = ptr to returned embedded client data ptr
2637 * *ppPRCD = ptr to embedded client data
2639 *************************************<->***********************************/
2643 IsPushRecallClient (ClientData *pCD, WmFpPushRecallClientData **ppPRCD)
2648 Boolean bFoundMatch = False;
2649 WmFpPushRecallClientData *pPRCD;
2652 pPRCD = (WmFpPushRecallClientData *) pSD->pPRCD;
2654 for (i = 0; i < pSD->numPushRecallClients && !bFoundMatch; i++, pPRCD++)
2657 * It's a push_recall client if the resource name matches
2658 * a slot and the slot isn't already filled.
2660 if ((!strcmp ((char *)pCD->clientName,
2661 (char *)(pPRCD->pchResName))) &&
2668 return (bFoundMatch);
2670 } /* END OF FUNCTION IsPushRecallClient */
2673 /*************************************<->*************************************
2675 * ScanForPushRecallClients (pSD)
2680 * This function scans the managed windows and identifies those that
2681 * should be push recall clients of the front panel
2686 * pSD - pointer to screen data.
2691 *************************************<->***********************************/
2694 ScanForPushRecallClients (
2698 ClientListEntry *pCLE;
2699 WmFpPushRecallClientData *pPRCD;
2702 * Search through all the windows we're managing right now
2704 pCLE = pSD->clientList;
2706 while (pCLE != NULL)
2709 * See if this is an previously unrecognized push recall client
2713 if ((pCD->pPRCD == NULL ) && IsPushRecallClient (pCD, &pPRCD))
2715 CheckPushRecallClient (pCD);
2719 * Test for exit condition
2721 if (pCLE == pSD->lastClient)
2724 * Gone all the way through the list without finding
2725 * anything -- time to quit
2732 * Move to next client.
2734 pCLE = pCLE->nextSibling;
2738 } /* END OF FUNCTION ScanForPushRecallClients */
2741 /******************************<->*************************************
2743 * static void CheckPushRecallClient (pCD)
2748 * Checks a client against the list of push recall clients to see
2749 * if there are any matches. All matches are marked.
2753 * pCD - pointer to the Client Data structure
2761 ******************************<->***********************************/
2763 CheckPushRecallClient(
2766 WmFpPushRecallClientData *pPRCD;
2768 while (IsPushRecallClient (pCD, &pPRCD))
2771 * There should only be one instance of this
2772 * client started from a front panel button.
2775 pPRCD->tvTimeout.tv_sec = 0;
2777 pCD->pPRCD = (void *) pPRCD;
2782 /******************************<->*************************************
2784 * static void HandleSubstructEvents (Widget w, caddr_t pCD, XEvent *event)
2789 * Causes death of embedded clients to run through UnManageWindow()
2790 * for proper cleanup.
2792 * Note there is one of these event handlers instantiated for
2793 * each live client window in the front panel. Hence, for each
2794 * live client window death, each of the event handlers gets called
2795 * once. We need to ensure that we've got the right pCD before
2796 * calling UnManageWindow() on it.
2802 * pCD - pointer to the Client Data structure
2803 * event - we only care about UnMapNotify
2810 * This routine is called LOTS of times, for all types of events.
2812 ******************************<->***********************************/
2814 HandleSubstructEvents(
2819 struct _ClientData *pCD = (struct _ClientData *)ptr;
2821 switch (event->type)
2825 if (pCD->client == event->xunmap.window)
2827 UnManageWindow (pCD);
2832 } /* END OF FUNCTION HandleSubstructEvents */
2835 /*******************************<->*************************************
2837 * UpdateEmbeddedClientsProperty (pSD)
2844 * pSD - pointer to the screen data
2848 * True if successful, False otherwise.
2852 * The _DT_WORKSPACE_EMBEDDED_CLIENTS property on the
2853 * root window for the screen will be updated to reflect the
2854 * current contents of the front panel
2857 ******************************<->***********************************/
2859 UpdateEmbeddedClientsProperty(
2862 unsigned int numClients = 0;
2863 Window *pClients = NULL;
2864 Boolean rval = True;
2866 WmFpEmbeddedClientData *pECD;
2868 pECD = (WmFpEmbeddedClientData *) pSD->pECD;
2870 for (i = 0; i < pSD->numEmbeddedClients; i++, pECD++)
2878 pClients = (Window *) XtMalloc (sizeof(Window));
2882 pClients = (Window *) XtRealloc ((char *)pClients,
2883 (numClients * (sizeof(Window))));
2889 ((char *)GETMESSAGE(4, 17, "Insufficient memory to write _DT_WORKSPACE_EMBEDDED_CLIENTS."))
2896 pClients[numClients-1] = pECD->pCD->client;
2901 SetEmbeddedClientsProperty (pSD->rootWindow, pClients,
2904 if (pClients != NULL)
2906 XtFree ((char *)pClients);
2910 } /* END OF FUNCTION UpdateEmbeddedClientsProperty */
2914 /*******************************<->*************************************
2916 * UnParentControls (pSD, unmap)
2923 * pSD - pointer to the screen data
2924 * unmap - if True, then unmap the windows after reparenting to root
2932 * Reparents clients embedded in the front panel back to the
2935 ******************************<->***********************************/
2943 WmFpEmbeddedClientData *pECD;
2945 if (pSD && pSD->managed)
2947 pECD = (WmFpEmbeddedClientData *) pSD->pECD;
2948 for (i = 0; i < pSD->numEmbeddedClients; i++, pECD++)
2954 if ((pCD->clientFlags & CLIENT_IN_SAVE_SET) &&
2955 !(pCD->clientFlags & CLIENT_DESTROYED))
2957 XRemoveFromSaveSet (DISPLAY, pCD->client);
2958 XRemoveFromSaveSet (DISPLAY1, pCD->client);
2961 XReparentWindow (DISPLAY,
2968 XUnmapWindow (DISPLAY, pCD->client);
2969 if (pCD->iconWindow)
2971 if (pCD->clientFlags & ICON_IN_SAVE_SET)
2973 XRemoveFromSaveSet (DISPLAY, pCD->iconWindow);
2974 pCD->clientFlags &= ~ICON_IN_SAVE_SET;
2976 XUnmapWindow (DISPLAY, pCD->iconWindow);
2983 } /* END OF FUNCTION UnParentControl */
2987 /*************************************<->*************************************
2989 * RegisterIconBoxControl (wPanelist)
2994 * This function registers the icon box control in a front panel
2999 * wPanelist = front panel object (widget)
3004 *************************************<->***********************************/
3007 RegisterIconBoxControl (Widget wPanelist)
3012 for (i= 0; i < wmGD.numScreens; i++)
3014 pSD = &(wmGD.Screens[i]);
3018 if (pSD->wPanelist == wPanelist)
3023 if (i < wmGD.numScreens)
3025 pSD->iconBoxControl = True;
3026 pSD->useIconBox = True;
3031 fprintf (stderr, "Couldn't match wPanelist to screen data\n");
3035 } /* END OF FUNCTION RegisterIconBoxControl */
3037 #endif /* PANELIST */