[PATCH 2/2] winex11.drv: Use _GTK_WORKAREAS to get work areas if it is available.

Zhiyi Zhang zzhang at codeweavers.com
Tue Jun 30 04:56:53 CDT 2020


_NET_WORKAREA reports a single rectangle as intersected work areas of
all monitors. So work areas on non-primary monitors may be incorrect.
For example, a dock only shown on the primary monitor reduces the work
areas on non-primary monitors.

There were attempts to extend _NET_WORKAREA to support work areas of
multiple monitors but they were rejected as EWMH is no longer being
maintained and _GTK_WORKAREAS was introduced instead.

Fix Office 2010 missing title bar on non-primary monitors on GNOME.

Signed-off-by: Zhiyi Zhang <zzhang at codeweavers.com>
---
For the merge request to extend _NET_WORKAREA, see https://gitlab.freedesktop.org/xdg/xdg-specs/-/merge_requests/22

 dlls/winex11.drv/display.c     | 29 ++++++++++++++++++++++++++++-
 dlls/winex11.drv/x11drv.h      |  1 +
 dlls/winex11.drv/x11drv_main.c |  1 +
 3 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/dlls/winex11.drv/display.c b/dlls/winex11.drv/display.c
index 625e8be4f47..262127367db 100644
--- a/dlls/winex11.drv/display.c
+++ b/dlls/winex11.drv/display.c
@@ -263,10 +263,37 @@ RECT get_work_area(RECT *monitor_rect)
 {
     Atom type;
     int format;
-    unsigned long count, remaining;
+    unsigned long count, remaining, i;
     long *work_area;
     RECT work_rect;
 
+    /* Try _GTK_WORKAREAS first as _NET_WORKAREA may be incorrect on multi-monitor systems */
+    if (!XGetWindowProperty(gdi_display, DefaultRootWindow(gdi_display),
+                            x11drv_atom(_GTK_WORKAREAS_D0), 0, ~0, False, XA_CARDINAL, &type,
+                            &format, &count, &remaining, (unsigned char **)&work_area))
+    {
+        if (type == XA_CARDINAL && format == 32 && count >= 4)
+        {
+            for (i = 0; i + 3 < count; i += 4)
+            {
+                work_rect.left = work_area[i * 4];
+                work_rect.top = work_area[i * 4 + 1];
+                work_rect.right = work_rect.left + work_area[i * 4 + 2];
+                work_rect.bottom = work_rect.top + work_area[i * 4 + 3];
+
+                if (IntersectRect(&work_rect, &work_rect, monitor_rect))
+                {
+                    TRACE("work_rect:%s.\n", wine_dbgstr_rect(&work_rect));
+                    XFree(work_area);
+                    return work_rect;
+                }
+            }
+        }
+        XFree(work_area);
+    }
+
+    WARN("_GTK_WORKAREAS is not supported, fallback to _NET_WORKAREA. "
+         "Work areas may be incorrect on multi-monitor systems.\n");
     if (!XGetWindowProperty(gdi_display, DefaultRootWindow(gdi_display), x11drv_atom(_NET_WORKAREA),
                             0, ~0, False, XA_CARDINAL, &type, &format, &count, &remaining,
                             (unsigned char **)&work_area))
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index bfc9aee027c..1efdac7064c 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -464,6 +464,7 @@ enum x11drv_atoms
     XATOM__NET_WM_WINDOW_TYPE_NORMAL,
     XATOM__NET_WM_WINDOW_TYPE_UTILITY,
     XATOM__NET_WORKAREA,
+    XATOM__GTK_WORKAREAS_D0,
     XATOM__XEMBED,
     XATOM__XEMBED_INFO,
     XATOM_XdndAware,
diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c
index e6e61e801e1..9ec4c7a98f6 100644
--- a/dlls/winex11.drv/x11drv_main.c
+++ b/dlls/winex11.drv/x11drv_main.c
@@ -177,6 +177,7 @@ static const char * const atom_names[NB_XATOMS - FIRST_XATOM] =
     "_NET_WM_WINDOW_TYPE_NORMAL",
     "_NET_WM_WINDOW_TYPE_UTILITY",
     "_NET_WORKAREA",
+    "_GTK_WORKAREAS_D0",
     "_XEMBED",
     "_XEMBED_INFO",
     "XdndAware",
-- 
2.25.1



More information about the wine-devel mailing list