From: Alberts Muktupāvels Date: Sun, 12 Jan 2020 22:38:12 +0000 (+0200) Subject: x11: add support for _GTK_WORKAREAS_Dn X-Git-Tag: archive/raspbian/4.4.1+ds1-2+rpi1^2~18^2~20^2~131^2 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=248883089c6a9ac221532a8a85a5511f0bc9af77;p=gtk4.git x11: add support for _GTK_WORKAREAS_Dn If window manager supports _GTK_WORKAREAS use per-monitor work areas. https://mail.gnome.org/archives/wm-spec-list/2018-December/msg00000.html https://gitlab.freedesktop.org/xdg/xdg-specs/merge_requests/22 https://gitlab.gnome.org/GNOME/gtk/merge_requests/1300 --- diff --git a/gdk/x11/gdkmonitor-x11.c b/gdk/x11/gdkmonitor-x11.c index 34d88e98f8..2ed77b9b81 100644 --- a/gdk/x11/gdkmonitor-x11.c +++ b/gdk/x11/gdkmonitor-x11.c @@ -67,19 +67,27 @@ gdk_x11_monitor_get_workarea (GdkMonitor *monitor, gdk_monitor_get_geometry (monitor, dest); - /* The EWMH constrains workarea to be a rectangle, so it - * can't adequately deal with L-shaped monitor arrangements. - * As a workaround, we ignore the workarea for anything - * but the primary monitor. Since that is where the 'desktop - * chrome' usually lives, this works ok in practice. - */ - if (gdk_monitor_is_primary (monitor) && - !gdk_monitor_has_fullscreen_window (monitor)) + if (_gdk_x11_screen_get_monitor_work_area (screen, monitor, &workarea)) { - gdk_x11_screen_get_work_area (screen, &workarea); - if (gdk_rectangle_intersect (dest, &workarea, &workarea)) + if (!gdk_monitor_has_fullscreen_window (monitor)) *dest = workarea; } + else + { + /* The EWMH constrains workarea to be a rectangle, so it + * can't adequately deal with L-shaped monitor arrangements. + * As a workaround, we ignore the workarea for anything + * but the primary monitor. Since that is where the 'desktop + * chrome' usually lives, this works ok in practice. + */ + if (gdk_monitor_is_primary (monitor) && + !gdk_monitor_has_fullscreen_window (monitor)) + { + gdk_x11_screen_get_work_area (screen, &workarea); + if (gdk_rectangle_intersect (dest, &workarea, &workarea)) + *dest = workarea; + } + } } static void diff --git a/gdk/x11/gdkscreen-x11.c b/gdk/x11/gdkscreen-x11.c index ffba0708f7..838a6d1cf1 100644 --- a/gdk/x11/gdkscreen-x11.c +++ b/gdk/x11/gdkscreen-x11.c @@ -179,6 +179,105 @@ get_current_desktop (GdkX11Screen *screen) return workspace; } +gboolean +_gdk_x11_screen_get_monitor_work_area (GdkX11Screen *x11_screen, + GdkMonitor *monitor, + GdkRectangle *area) +{ + Display *xdisplay; + Atom net_workareas; + int current_desktop; + char *workareas_dn_name; + Atom workareas_dn; + int screen_number; + Window xroot; + int result; + Atom type; + int format; + gulong num; + gulong leftovers; + guchar *ret_workarea; + long *workareas; + GdkRectangle geometry; + int i; + + if (!gdk_x11_screen_supports_net_wm_hint (x11_screen, + g_intern_static_string ("_GTK_WORKAREAS"))) + return FALSE; + + xdisplay = gdk_x11_display_get_xdisplay (x11_screen->display); + net_workareas = XInternAtom (xdisplay, "_GTK_WORKAREAS", False); + + if (net_workareas == None) + return FALSE; + + current_desktop = get_current_desktop (x11_screen); + workareas_dn_name = g_strdup_printf ("_GTK_WORKAREAS_D%d", current_desktop); + workareas_dn = XInternAtom (xdisplay, workareas_dn_name, True); + g_free (workareas_dn_name); + + if (workareas_dn == None) + return FALSE; + + screen_number = gdk_x11_screen_get_screen_number (x11_screen); + xroot = XRootWindow (xdisplay, screen_number); + + gdk_x11_display_error_trap_push (x11_screen->display); + + ret_workarea = NULL; + result = XGetWindowProperty (xdisplay, + xroot, + workareas_dn, + 0, + G_MAXLONG, + False, + AnyPropertyType, + &type, + &format, + &num, + &leftovers, + &ret_workarea); + + gdk_x11_display_error_trap_pop_ignored (x11_screen->display); + + if (result != Success || + type == None || + format == 0 || + leftovers || + num % 4 != 0) + { + XFree (ret_workarea); + + return FALSE; + } + + workareas = (long *) ret_workarea; + + gdk_monitor_get_geometry (monitor, &geometry); + *area = geometry; + + for (i = 0; i < num / 4; i++) + { + GdkRectangle work_area; + + work_area = (GdkRectangle) { + .x = workareas[0] / x11_screen->surface_scale, + .y = workareas[1] / x11_screen->surface_scale, + .width = workareas[2] / x11_screen->surface_scale, + .height = workareas[3] / x11_screen->surface_scale, + }; + + if (gdk_rectangle_intersect (area, &work_area, &work_area)) + *area = work_area; + + workareas += 4; + } + + XFree (ret_workarea); + + return TRUE; +} + void gdk_x11_screen_get_work_area (GdkX11Screen *x11_screen, GdkRectangle *area) diff --git a/gdk/x11/gdkscreen-x11.h b/gdk/x11/gdkscreen-x11.h index aa5e063447..348a3ef323 100644 --- a/gdk/x11/gdkscreen-x11.h +++ b/gdk/x11/gdkscreen-x11.h @@ -108,6 +108,9 @@ void _gdk_x11_screen_get_edge_monitors (GdkX11Screen *screen, gint *right); void _gdk_x11_screen_set_surface_scale (GdkX11Screen *x11_screen, int scale); +gboolean _gdk_x11_screen_get_monitor_work_area (GdkX11Screen *screen, + GdkMonitor *monitor, + GdkRectangle *area); void gdk_x11_screen_get_work_area (GdkX11Screen *screen, GdkRectangle *area); gboolean gdk_x11_screen_get_setting (GdkX11Screen *screen,