Browse Source

dtwm: support _NET_WM_STATE_ABOVE and _NET_WM_STATE_BELOW.

hyousatsu 1 year ago
parent
commit
2351a19d7e

+ 17 - 0
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);

+ 78 - 16
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;
+	    pCD->pSD->topClient = pCD;
+	    ProcessNetWmStateBelow (pCD, _NET_WM_STATE_REMOVE);
+	    Do_Raise (pCD, NULL, STACK_NORMAL);
 	    break;
-	case _NET_WM_STATE_TOGGLE:
-	    newState = pCD->clientState == MAXIMIZED_STATE ?
-		NORMAL_STATE : MAXIMIZED_STATE;
+	default:
+	    return;
+    }
+
+    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;
     }
 
-    SetClientState (pCD, newState, GetTimestamp ());
+    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);
     }
 }

+ 9 - 2
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: */
 

+ 3 - 0
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.

+ 2 - 0
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:

+ 2 - 1
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);