[gtk/wip/muktupavels/work-areas: 301/301] x11: add support for _GTK_WORKAREAS_Dn
- From: Alberts Muktupāvels <muktupavels src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/muktupavels/work-areas: 301/301] x11: add support for _GTK_WORKAREAS_Dn
- Date: Wed, 29 Jan 2020 12:39:35 +0000 (UTC)
commit 248883089c6a9ac221532a8a85a5511f0bc9af77
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date: Mon Jan 13 00:38:12 2020 +0200
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
gdk/x11/gdkmonitor-x11.c | 28 +++++++++-----
gdk/x11/gdkscreen-x11.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++
gdk/x11/gdkscreen-x11.h | 3 ++
3 files changed, 120 insertions(+), 10 deletions(-)
---
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,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]