diff --git a/gdk/x11/gdkmonitor-x11.c b/gdk/x11/gdkmonitor-x11.c index 899511afcd..c05bae9a02 100644 --- a/gdk/x11/gdkmonitor-x11.c +++ b/gdk/x11/gdkmonitor-x11.c @@ -66,19 +66,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 a4b2ebc18a..bb4df059bc 100644 --- a/gdk/x11/gdkscreen-x11.c +++ b/gdk/x11/gdkscreen-x11.c @@ -234,6 +234,106 @@ get_current_desktop (GdkScreen *screen) return workspace; } +gboolean +_gdk_x11_screen_get_monitor_work_area (GdkScreen *screen, + GdkMonitor *monitor, + GdkRectangle *area) +{ + GdkX11Screen *x11_screen; + GdkAtom net_workareas; + GdkDisplay *display; + Display *xdisplay; + 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; + + x11_screen = GDK_X11_SCREEN (screen); + + net_workareas = gdk_atom_intern_static_string ("_GTK_WORKAREAS"); + if (!gdk_x11_screen_supports_net_wm_hint (screen, net_workareas)) + return FALSE; + + display = gdk_screen_get_display (screen); + xdisplay = gdk_x11_display_get_xdisplay (display); + + current_desktop = get_current_desktop (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 (screen); + xroot = XRootWindow (xdisplay, screen_number); + + gdk_x11_display_error_trap_push (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 (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->window_scale, + .y = workareas[1] / x11_screen->window_scale, + .width = workareas[2] / x11_screen->window_scale, + .height = workareas[3] / x11_screen->window_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 (GdkScreen *screen, GdkRectangle *area) diff --git a/gdk/x11/gdkscreen-x11.h b/gdk/x11/gdkscreen-x11.h index aca9b3c9e0..19edf2aa12 100644 --- a/gdk/x11/gdkscreen-x11.h +++ b/gdk/x11/gdkscreen-x11.h @@ -119,6 +119,9 @@ void _gdk_x11_screen_get_edge_monitors (GdkScreen *screen, gint *right); void _gdk_x11_screen_set_window_scale (GdkX11Screen *x11_screen, int scale); +gboolean _gdk_x11_screen_get_monitor_work_area (GdkScreen *screen, + GdkMonitor *monitor, + GdkRectangle *area); void gdk_x11_screen_get_work_area (GdkScreen *screen, GdkRectangle *area); gint gdk_x11_screen_get_width (GdkScreen *screen);