Add gdk_screen_get_monitor_workarea

The function returns the part of a monitors area that should be
used for positioning popups, menus, etc. The only non-trivial
implementation atm is in the X backend, all the other backends
just return the full monitor area. The X implementation is
currently suboptimal, since it requires roundtrips to collect
the necessary information. It should be changed to monitor
the properties for changes, when XFixes allows to monitor
individual properties.
https://bugzilla.gnome.org/show_bug.cgi?id=641999
This commit is contained in:
Matthias Clasen
2011-12-18 14:02:55 -05:00
parent 74cff292d5
commit c6df2828b7
10 changed files with 160 additions and 8 deletions

View File

@ -305,6 +305,113 @@ gdk_x11_screen_get_monitor_geometry (GdkScreen *screen,
*dest = x11_screen->monitors[monitor_num].geometry;
}
static int
get_current_desktop (GdkScreen *screen)
{
Display *display;
Window win;
Atom current_desktop, type;
int format;
unsigned long n_items, bytes_after;
unsigned char *data_return = NULL;
int workspace = 0;
display = GDK_DISPLAY_XDISPLAY (gdk_screen_get_display (screen));
win = XRootWindow (display, GDK_SCREEN_XNUMBER (screen));
current_desktop = XInternAtom (display, "_NET_CURRENT_DESKTOP", True);
XGetWindowProperty (display,
win,
current_desktop,
0, G_MAXLONG,
False, XA_CARDINAL,
&type, &format, &n_items, &bytes_after,
&data_return);
if (type == XA_CARDINAL && format == 32 && n_items > 0)
workspace = (int) data_return[0];
if (data_return)
XFree (data_return);
return workspace;
}
static void
get_work_area (GdkScreen *screen,
GdkRectangle *area)
{
Atom workarea;
Atom type;
Window win;
int format;
gulong num;
gulong leftovers;
gulong max_len = 4 * 32;
guchar *ret_workarea;
long *workareas;
int result;
int disp_screen;
int desktop;
Display *display;
display = GDK_DISPLAY_XDISPLAY (gdk_screen_get_display (screen));
disp_screen = GDK_SCREEN_XNUMBER (screen);
workarea = XInternAtom (display, "_NET_WORKAREA", True);
/* Defaults in case of error */
area->x = 0;
area->y = 0;
area->width = gdk_screen_get_width (screen);
area->height = gdk_screen_get_height (screen);
if (workarea == None)
return;
win = XRootWindow (display, disp_screen);
result = XGetWindowProperty (display,
win,
workarea,
0,
max_len,
False,
AnyPropertyType,
&type,
&format,
&num,
&leftovers,
&ret_workarea);
if (result != Success ||
type == None ||
format == 0 ||
leftovers ||
num % 4 != 0)
return;
desktop = get_current_desktop (screen);
workareas = (long *) ret_workarea;
area->x = workareas[desktop * 4];
area->y = workareas[desktop * 4 + 1];
area->width = workareas[desktop * 4 + 2];
area->height = workareas[desktop * 4 + 3];
XFree (ret_workarea);
}
static void
gdk_x11_screen_get_monitor_workarea (GdkScreen *screen,
gint monitor_num,
GdkRectangle *dest)
{
GdkRectangle workarea;
gdk_x11_screen_get_monitor_geometry (screen, monitor_num, dest);
get_work_area (screen, &workarea);
gdk_rectangle_intersect (&workarea, dest, dest);
}
static GdkVisual *
gdk_x11_screen_get_rgba_visual (GdkScreen *screen)
{
@ -1603,6 +1710,7 @@ gdk_x11_screen_class_init (GdkX11ScreenClass *klass)
screen_class->get_monitor_height_mm = gdk_x11_screen_get_monitor_height_mm;
screen_class->get_monitor_plug_name = gdk_x11_screen_get_monitor_plug_name;
screen_class->get_monitor_geometry = gdk_x11_screen_get_monitor_geometry;
screen_class->get_monitor_workarea = gdk_x11_screen_get_monitor_workarea;
screen_class->get_system_visual = _gdk_x11_screen_get_system_visual;
screen_class->get_rgba_visual = gdk_x11_screen_get_rgba_visual;
screen_class->is_composited = gdk_x11_screen_is_composited;