diff --git a/cde/programs/dtwm/WmCEvent.c b/cde/programs/dtwm/WmCEvent.c index 2dab730dc..d6a5d7abf 100644 --- a/cde/programs/dtwm/WmCEvent.c +++ b/cde/programs/dtwm/WmCEvent.c @@ -80,6 +80,17 @@ static void AcceptPrematureClientMessage (XClientMessageEvent *clientEvent) sizeof(XClientMessageEvent)); } +static void HandleVisibilityNotify (ClientData *pCD, + XVisibilityEvent *visibilityEvent) +{ + if (pCD == pCD->pSD->topClient && + visibilityEvent->state != VisibilityUnobscured) + Do_Raise (pCD, NULL, STACK_NORMAL); + else if (pCD == pCD->pSD->bottomClient && + visibilityEvent->state != VisibilityFullyObscured) + Do_Lower (pCD, NULL, STACK_NORMAL); +} + /*************************************<->************************************* @@ -699,6 +710,12 @@ Boolean HandleEventsOnClientWindow (ClientData *pCD, XEvent *pEvent) break; } + case VisibilityNotify: + { + HandleVisibilityNotify (pCD, (XVisibilityEvent *)pEvent); + doXtDispatchEvent = False; + break; + } } return (doXtDispatchEvent); diff --git a/cde/programs/dtwm/WmEwmh.c b/cde/programs/dtwm/WmEwmh.c index cddc87a02..61180175b 100644 --- a/cde/programs/dtwm/WmEwmh.c +++ b/cde/programs/dtwm/WmEwmh.c @@ -27,11 +27,40 @@ #include "WmGlobal.h" #include "WmEvent.h" +#include "WmFunction.h" #include "WmMultiHead.h" #include "WmProperty.h" #include "WmWinState.h" #include "WmWrkspace.h" +static void ProcessNetWmStateAbove (ClientData *pCD, long action); +static void ProcessNetWmStateBelow (ClientData *pCD, long action); + +static void ProcessNetWmStateMaximized (ClientData *pCD, long action) +{ + int newState; + + switch (action) + { + case _NET_WM_STATE_REMOVE: + if (pCD->clientState != MAXIMIZED_STATE) return; + newState = NORMAL_STATE; + break; + case _NET_WM_STATE_ADD: + if (pCD->clientState == MAXIMIZED_STATE) return; + newState = MAXIMIZED_STATE; + break; + case _NET_WM_STATE_TOGGLE: + newState = pCD->clientState == MAXIMIZED_STATE ? + NORMAL_STATE : MAXIMIZED_STATE; + break; + default: + return; + } + + SetClientState (pCD, newState, GetTimestamp ()); +} + static void ProcessNetWmStateFullscreen (ClientData *pCD, long action) { Boolean fullscreen = pCD->fullscreen; @@ -62,29 +91,50 @@ static void ProcessNetWmStateFullscreen (ClientData *pCD, long action) } } -static void ProcessNetWmStateMaximized (ClientData *pCD, long action) +static void ProcessNetWmStateAbove (ClientData *pCD, long action) { - int newState; + if (action == _NET_WM_STATE_TOGGLE) + action = pCD == pCD->pSD->topClient ? _NET_WM_STATE_REMOVE : + _NET_WM_STATE_ADD; switch (action) { case _NET_WM_STATE_REMOVE: - if (pCD->clientState != MAXIMIZED_STATE) return; - newState = NORMAL_STATE; + if (pCD->pSD->topClient == pCD) pCD->pSD->topClient = NULL; break; case _NET_WM_STATE_ADD: - if (pCD->clientState == MAXIMIZED_STATE) return; - newState = MAXIMIZED_STATE; - break; - case _NET_WM_STATE_TOGGLE: - newState = pCD->clientState == MAXIMIZED_STATE ? - NORMAL_STATE : MAXIMIZED_STATE; + pCD->pSD->topClient = pCD; + ProcessNetWmStateBelow (pCD, _NET_WM_STATE_REMOVE); + Do_Raise (pCD, NULL, STACK_NORMAL); break; default: return; } - SetClientState (pCD, newState, GetTimestamp ()); + UpdateNetWmState (pCD->client, &wmGD.xa__NET_WM_STATE_ABOVE, 1, action); +} + +static void ProcessNetWmStateBelow (ClientData *pCD, long action) +{ + if (action == _NET_WM_STATE_TOGGLE) + action = pCD == pCD->pSD->bottomClient ? _NET_WM_STATE_REMOVE : + _NET_WM_STATE_ADD; + + switch (action) + { + case _NET_WM_STATE_REMOVE: + if (pCD->pSD->bottomClient == pCD) pCD->pSD->bottomClient = NULL; + break; + case _NET_WM_STATE_ADD: + pCD->pSD->bottomClient = pCD; + ProcessNetWmStateAbove (pCD, _NET_WM_STATE_REMOVE); + Do_Lower (pCD, NULL, STACK_NORMAL); + break; + default: + return; + } + + UpdateNetWmState (pCD->client, &wmGD.xa__NET_WM_STATE_BELOW, 1, action); } /** @@ -145,6 +195,12 @@ void ProcessNetWmState (ClientData *pCD, long action, else if (firstProperty == wmGD.xa__NET_WM_STATE_FULLSCREEN || secondProperty == wmGD.xa__NET_WM_STATE_FULLSCREEN) ProcessNetWmStateFullscreen (pCD, action); + else if (firstProperty == wmGD.xa__NET_WM_STATE_ABOVE || + secondProperty == wmGD.xa__NET_WM_STATE_ABOVE) + ProcessNetWmStateAbove (pCD, action); + else if (firstProperty == wmGD.xa__NET_WM_STATE_BELOW || + secondProperty == wmGD.xa__NET_WM_STATE_BELOW) + ProcessNetWmStateBelow (pCD, action); if (!ClientInWorkspace (ACTIVE_WS, pCD)) SetClientState (pCD, pCD->clientState | UNSEEN_STATE, GetTimestamp ()); @@ -167,9 +223,11 @@ void SetupWmEwmh (void) XA__NET_WM_VISIBLE_ICON_NAME, XA__NET_WM_FULLSCREEN_MONITORS, XA__NET_WM_STATE, - XA__NET_WM_STATE_FULLSCREEN, XA__NET_WM_STATE_MAXIMIZED_VERT, - XA__NET_WM_STATE_MAXIMIZED_HORZ + XA__NET_WM_STATE_MAXIMIZED_HORZ, + XA__NET_WM_STATE_FULLSCREEN, + XA__NET_WM_STATE_ABOVE, + XA__NET_WM_STATE_BELOW }; static char *atom_names[] = { @@ -182,9 +240,11 @@ void SetupWmEwmh (void) _XA__NET_WM_VISIBLE_ICON_NAME, _XA__NET_WM_FULLSCREEN_MONITORS, _XA__NET_WM_STATE, - _XA__NET_WM_STATE_FULLSCREEN, _XA__NET_WM_STATE_MAXIMIZED_VERT, - _XA__NET_WM_STATE_MAXIMIZED_HORZ + _XA__NET_WM_STATE_MAXIMIZED_HORZ, + _XA__NET_WM_STATE_FULLSCREEN, + _XA__NET_WM_STATE_ABOVE, + _XA__NET_WM_STATE_BELOW }; Atom atoms[XtNumber(atom_names) + 1]; @@ -198,11 +258,13 @@ void SetupWmEwmh (void) wmGD.xa__NET_WM_VISIBLE_ICON_NAME = atoms[XA__NET_WM_VISIBLE_ICON_NAME]; wmGD.xa__NET_WM_FULLSCREEN_MONITORS = atoms[XA__NET_WM_FULLSCREEN_MONITORS]; wmGD.xa__NET_WM_STATE = atoms[XA__NET_WM_STATE]; - wmGD.xa__NET_WM_STATE_FULLSCREEN = atoms[XA__NET_WM_STATE_FULLSCREEN]; wmGD.xa__NET_WM_STATE_MAXIMIZED_VERT = atoms[XA__NET_WM_STATE_MAXIMIZED_VERT]; wmGD.xa__NET_WM_STATE_MAXIMIZED_HORZ = atoms[XA__NET_WM_STATE_MAXIMIZED_HORZ]; + wmGD.xa__NET_WM_STATE_FULLSCREEN = atoms[XA__NET_WM_STATE_FULLSCREEN]; + wmGD.xa__NET_WM_STATE_ABOVE = atoms[XA__NET_WM_STATE_ABOVE]; + wmGD.xa__NET_WM_STATE_BELOW = atoms[XA__NET_WM_STATE_BELOW]; for (scr = 0; scr < wmGD.numScreens; ++scr) { @@ -230,6 +292,6 @@ void SetupWmEwmh (void) XChangeProperty(DISPLAY, wmGD.Screens[scr].rootWindow, atoms[XA__NET_SUPPORTED], XA_ATOM, 32, PropModeReplace, (unsigned char *)&atoms[XA__NET_SUPPORTING_WM_CHECK], - 10); + 12); } } diff --git a/cde/programs/dtwm/WmGlobal.h b/cde/programs/dtwm/WmGlobal.h index 1a499d00b..5dcc6bd97 100644 --- a/cde/programs/dtwm/WmGlobal.h +++ b/cde/programs/dtwm/WmGlobal.h @@ -134,9 +134,11 @@ extern Pixel FPselectcolor; #define _XA__NET_WM_VISIBLE_ICON_NAME "_NET_WM_VISIBLE_ICON_NAME" #define _XA__NET_WM_FULLSCREEN_MONITORS "_NET_WM_FULLSCREEN_MONITORS" #define _XA__NET_WM_STATE "_NET_WM_STATE" -#define _XA__NET_WM_STATE_FULLSCREEN "_NET_WM_STATE_FULLSCREEN" #define _XA__NET_WM_STATE_MAXIMIZED_VERT "_NET_WM_STATE_MAXIMIZED_VERT" #define _XA__NET_WM_STATE_MAXIMIZED_HORZ "_NET_WM_STATE_MAXIMIZED_HORZ" +#define _XA__NET_WM_STATE_FULLSCREEN "_NET_WM_STATE_FULLSCREEN" +#define _XA__NET_WM_STATE_ABOVE "_NET_WM_STATE_ABOVE" +#define _XA__NET_WM_STATE_BELOW "_NET_WM_STATE_BELOW" /* window manager exit value on fatal errors: */ #define WM_ERROR_EXIT_VALUE 1 @@ -1325,6 +1327,9 @@ typedef struct _WmScreenData DtSvcHandle hWsm; /* WORKSPACEMGR message handle */ Boolean bMarqueeSelectionInitialized; + /* top and bottom clients */ + struct _ClientData *topClient; + struct _ClientData *bottomClient; } WmScreenData; typedef struct _WmScreenData *PtrScreenData; @@ -1984,9 +1989,11 @@ typedef struct _WmGlobalData Atom xa__NET_WM_VISIBLE_ICON_NAME; Atom xa__NET_WM_FULLSCREEN_MONITORS; Atom xa__NET_WM_STATE; - Atom xa__NET_WM_STATE_FULLSCREEN; Atom xa__NET_WM_STATE_MAXIMIZED_VERT; Atom xa__NET_WM_STATE_MAXIMIZED_HORZ; + Atom xa__NET_WM_STATE_FULLSCREEN; + Atom xa__NET_WM_STATE_ABOVE; + Atom xa__NET_WM_STATE_BELOW; /* atoms used for workspace management: */ diff --git a/cde/programs/dtwm/WmInitWs.c b/cde/programs/dtwm/WmInitWs.c index 17974de8c..4cdd01c85 100644 --- a/cde/programs/dtwm/WmInitWs.c +++ b/cde/programs/dtwm/WmInitWs.c @@ -1272,6 +1272,9 @@ InitWmScreen (WmScreenData *pSD, int sNum) pSD->iconBoxControl = False; pSD->displayResolutionType = _DtGetDisplayResolution(DISPLAY, sNum); + pSD->topClient = NULL; + pSD->bottomClient = NULL; + /* * We've got display resolution type--now, let's get color * characteristics. diff --git a/cde/programs/dtwm/WmManage.c b/cde/programs/dtwm/WmManage.c index eabade922..cfdd6d87e 100644 --- a/cde/programs/dtwm/WmManage.c +++ b/cde/programs/dtwm/WmManage.c @@ -921,6 +921,8 @@ void WithdrawWindow (ClientData *pCD) int i; XWindowChanges xwc; + if (pCD->pSD->topClient == pCD) pCD->pSD->topClient = NULL; + if (pCD->pSD->bottomClient == pCD) pCD->pSD->bottomClient = NULL; /* * Put the client window into a withdrawn state: diff --git a/cde/programs/dtwm/WmWinInfo.c b/cde/programs/dtwm/WmWinInfo.c index 1bbb96371..c931c9fc6 100644 --- a/cde/programs/dtwm/WmWinInfo.c +++ b/cde/programs/dtwm/WmWinInfo.c @@ -250,7 +250,8 @@ GetClientInfo (WmScreenData *pSD, Window clientWindow, long manageFlags) * Listen for property change events on the window so that we keep * in sync with the hints. */ - sAttributes.event_mask = (PropertyChangeMask | ColormapChangeMask); + sAttributes.event_mask = (PropertyChangeMask | ColormapChangeMask | + VisibilityChangeMask); XChangeWindowAttributes (DISPLAY, pCD->client, CWEventMask, &sAttributes);