dtwm: basic multihead(xinerama only) support
authorMatthew R. Trower <dev@blackshard.net>
Thu, 23 Jun 2016 07:25:00 +0000 (02:25 -0500)
committerJon Trulson <jon@radscan.com>
Fri, 24 Jun 2016 23:16:19 +0000 (17:16 -0600)
* maximization (also partially fixes strange Firefox behaviour)
* sane initial window placement

Firefox is stranger than most; it appears to maximize to double
X Screen width even on single head displays.  Fixed (on multihead).

cde/programs/dtwm/Imakefile
cde/programs/dtwm/WmMultiHead.c [new file with mode: 0644]
cde/programs/dtwm/WmMultiHead.h [new file with mode: 0644]
cde/programs/dtwm/WmWinInfo.c
cde/programs/dtwm/WmWinState.c

index fa10741f9fd02ce82a6156f2938ce0c770c28cd7..258127a47627e45d043fade72ca784c21c29e63f 100644 (file)
@@ -15,8 +15,8 @@ DEPEND_DEFINES = $(DEPENDDEFINES)
 DEFINES = $(MWMDEFINES) $(DTWMDEFINES) -DMULTIBYTE -DMINIMAL_DT
 
 DEPLIBS = DepDtClientLibs
-LOCAL_LIBRARIES = DtClientLibs
-SYS_LIBRARIES = DtClientSysLibs DtClientExtraLibs
+LOCAL_LIBRARIES = DtClientLibs -lDtXinerama
+SYS_LIBRARIES = DtClientSysLibs DtClientExtraLibs -lXinerama
 
 #if defined(HPArchitecture)
 EXTRA_DEFINES = -D_HPUX_SOURCE 
@@ -32,7 +32,8 @@ SRCSXM = \
         WmMenu.c        WmProperty.c    WmProtocol.c \
         WmResCvt.c      WmResParse.c    WmResource.c \
         WmSignal.c      WmWinConf.c     WmWinInfo.c \
-        WmWinList.c     WmWinState.c    version.c
+        WmWinList.c     WmWinState.c    version.c \
+        WmMultihead.c
 
 SRCSDT = \
         Button.c        Callback.c      Clock.c \
@@ -53,7 +54,8 @@ OBJSXM = \
         WmMenu.o        WmProperty.o    WmProtocol.o \
         WmResCvt.o      WmResParse.o    WmResource.o \
         WmSignal.o      WmWinConf.o     WmWinInfo.o \
-        WmWinList.o     WmWinState.o    version.o
+        WmWinList.o     WmWinState.o    version.o \
+        WmMultiHead.o
 
 OBJSDT = \
         Button.o        Callback.o      Clock.o \
diff --git a/cde/programs/dtwm/WmMultiHead.c b/cde/programs/dtwm/WmMultiHead.c
new file mode 100644 (file)
index 0000000..4de6c6b
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2016 Matthew R. Trower
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+/*
+ * Included Files:
+ */
+#include <DtXinerama.h>
+
+#include "WmMultiHead.h"
+
+/*
+ * Global Variables
+ */
+DtXineramaInfo_t *DtXI = NULL;/* Xinerama data is static for life of X server */
+
+\f
+/*************************************<->*************************************
+ *
+ *  GetHeadInfo (pcd)
+ *
+ *
+ *  Description:
+ *  -----------
+ *  Search for the head containing target client.
+ *
+ *
+ *  Inputs:
+ *  ------
+ *
+ *
+ *  Outputs:
+ *  -------
+ *  Return = head metrics on success, NULL on failure.
+ *           menuWidget, and menuButtons members.
+ *
+ *
+ *  Comments:
+ *  --------
+ *
+ *  Can fail if:
+ *
+ *  - MultiHead(eg. Xinerama) is not active
+ *  - Client does not fall within any existing head
+ *  - malloc error
+ *  - pcd is NULL
+ *
+ *************************************<->***********************************/
+WmHeadInfo_t *GetHeadInfo(const ClientData *pcd) {
+    WmHeadInfo_t *WmHI = NULL;
+
+    if (!DtXI)
+        DtXI = _DtXineramaInit(DISPLAY);
+
+    if (!pcd || !DtXI)
+        return NULL;
+
+    if (!(WmHI = (WmHeadInfo_t *)malloc(sizeof(WmHeadInfo_t)))) {
+#ifdef DEBUG
+        fprintf(stderr, "(dtwm) _GetScreenInfo: malloc failed\n");
+#endif
+
+        free(DtXI);
+        return NULL;
+    }
+
+    /*
+     * TODO
+     *
+     * DtXineramaInfo_t uses unsigned ints
+     * XineramaScreenInfo uses shorts(?)
+     * ClientData uses ints
+     * FrameToClient and friends use a mixture (!)
+     *
+     * Explicit casting would shut the compiler up, but wouldn't change the
+     * fundamental fact that we can't agree on coordinate types.
+     */
+    int idx = 0;
+    while (_DtXineramaGetScreen(DtXI, idx++,
+            &WmHI->width, &WmHI->height, &WmHI->x_org, &WmHI->y_org)) {
+
+        if (pcd->clientX >= WmHI->x_org &&
+            pcd->clientY >= WmHI->y_org &&
+            pcd->clientX <= WmHI->x_org + WmHI->width &&
+            pcd->clientY <= WmHI->y_org + WmHI->height)
+
+            return WmHI;
+    }
+
+    /* No valid screen */
+    return NULL;
+}
diff --git a/cde/programs/dtwm/WmMultiHead.h b/cde/programs/dtwm/WmMultiHead.h
new file mode 100644 (file)
index 0000000..112b03f
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2016 Matthew R. Trower
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef _WmMultiHead_h
+#define _WmMultiHead_h
+
+#include "WmGlobal.h"
+
+typedef struct _WmHeadInfo {
+    int x_org;
+    int y_org;
+    unsigned int width;
+    unsigned int height;
+} WmHeadInfo_t, *WmHeadInfoPtr_t;
+
+WmHeadInfo_t *GetHeadInfo(const ClientData *pcd);
+
+#endif _WmMultiHead_h
index 74cd77d3ce0799e46e55472585b68c96272a3122..8f0d972909814a348e0c37830c583c2340016fa6 100644 (file)
@@ -80,6 +80,7 @@ static char rcsid[] = "$TOG: WmWinInfo.c /main/18 1999/02/04 15:17:25 mgreess $"
 #include "WmPresence.h"
 #endif /* WSM */
 #include "WmXSMP.h"
+#include "WmMultiHead.h"
 
 #ifdef PANELIST
 static void AdjustSlideOutGeometry (ClientData *pCD);
@@ -3676,11 +3677,14 @@ FindClientPlacement (ClientData *pCD)
     Boolean placed = False;
     int frameWidth;
     int frameHeight;
+    int screenX;
+    int screenY;
     int screenWidth;
     int screenHeight;
     int borderWidth = 0;
     Boolean offScreenX;
     Boolean offScreenY;
+    WmHeadInfo_t *WmHI = NULL;
 
 
     if (!clientPlacementInitialized)
@@ -3704,8 +3708,22 @@ FindClientPlacement (ClientData *pCD)
 
     frameWidth = pCD->clientWidth + (2 * pCD->clientOffset.x);
     frameHeight = pCD->clientHeight + pCD->clientOffset.y + pCD->clientOffset.x;
-    screenWidth = DisplayWidth (DISPLAY, SCREEN_FOR_CLIENT(pCD));
-    screenHeight = DisplayHeight (DISPLAY, SCREEN_FOR_CLIENT(pCD));
+
+    if (WmHI = GetHeadInfo(wmGD.keyboardFocus)) {
+        /* Use Head metrics for placeable area */
+        screenX = WmHI->x_org;
+        screenY = WmHI->y_org;
+        screenWidth = WmHI->width;
+        screenHeight = WmHI->height;
+
+        free(WmHI);
+    } else {
+        /* Use X Screen metrics for placeable area */
+        screenX = 0;
+        screenY = 0;
+        screenWidth = DisplayWidth (DISPLAY, SCREEN_FOR_CLIENT(pCD));
+        screenHeight = DisplayHeight (DISPLAY, SCREEN_FOR_CLIENT(pCD));
+    }
 
     while (!placed)
     {
@@ -3796,8 +3814,8 @@ FindClientPlacement (ClientData *pCD)
      * The window has been placed, now update the placement information.
      */
 
-    pCD->clientX = clientPlacementX;
-    pCD->clientY = clientPlacementY;
+    pCD->clientX = clientPlacementX + screenX;
+    pCD->clientY = clientPlacementY + screenY;
     clientPlacementX += clientPlacementOffset;
 
     if (clientPlacementX >= screenWidth)
index 9e63a4b2de322f38d780da83c305d72763c56334..c1e289cf5e0ae0d4f3fe4cf54d77d79656e8565b 100644 (file)
@@ -50,6 +50,7 @@ static char rcsid[] = "$XConsortium: WmWinState.c /main/6 1996/06/20 09:39:39 rs
  */
 
 #include "WmCDecor.h"
+#include "WmCDInfo.h"
 #include "WmFunction.h"
 #include "WmIDecor.h"
 #include "WmIPlace.h"
@@ -71,6 +72,7 @@ static char rcsid[] = "$XConsortium: WmWinState.c /main/6 1996/06/20 09:39:39 rs
  * Function Declarations:
  */
 
+#include "WmMultiHead.h"
 #include "WmWinState.h"
 #ifdef PANELIST
 static void SlideWindowOut (ClientData *pCD);
@@ -655,6 +657,8 @@ static void SetupWindowStateWithEventMask (ClientData *pCD, int newState,
 
 void ConfigureNewState (ClientData *pcd)
 {
+    WmHeadInfo_t *WmHI = NULL;
+
     if (pcd->maxConfig)
     {
        pcd->maxConfig = FALSE;
@@ -665,6 +669,18 @@ void ConfigureNewState (ClientData *pcd)
     }
     else
     {
+    /*
+     * Update client config to reflect underlying head, if MultiHead is active
+     */
+    if (WmHI = GetHeadInfo(pcd)) {
+        FrameToClient(pcd, &WmHI->x_org, &WmHI->y_org,
+                &WmHI->width, &WmHI->height);
+        pcd->maxX = WmHI->x_org;
+        pcd->maxY = WmHI->y_org;
+        pcd->maxWidth = WmHI->width;
+        pcd->maxHeight = WmHI->height;
+    }
+
        XResizeWindow (DISPLAY, pcd->client,
                           (unsigned int) pcd->maxWidth, 
                           (unsigned int) pcd->maxHeight);