From: Zhiyi Zhang Subject: [PATCH 2/2] winex11.drv: Use _GTK_WORKAREAS to get work areas if it is available. Message-Id: Date: Tue, 30 Jun 2020 17:56:53 +0800 _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 --- 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