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

@ -199,6 +199,7 @@ gdk_screen_make_display_name
gdk_screen_get_n_monitors
gdk_screen_get_primary_monitor
gdk_screen_get_monitor_geometry
gdk_screen_get_monitor_workarea
gdk_screen_get_monitor_at_point
gdk_screen_get_monitor_at_window
gdk_screen_get_monitor_height_mm

View File

@ -321,6 +321,7 @@ gdk_broadway_screen_class_init (GdkBroadwayScreenClass *klass)
screen_class->get_monitor_height_mm = gdk_broadway_screen_get_monitor_height_mm;
screen_class->get_monitor_plug_name = gdk_broadway_screen_get_monitor_plug_name;
screen_class->get_monitor_geometry = gdk_broadway_screen_get_monitor_geometry;
screen_class->get_monitor_workarea = gdk_broadway_screen_get_monitor_geometry;
screen_class->is_composited = gdk_broadway_screen_is_composited;
screen_class->make_display_name = gdk_broadway_screen_make_display_name;
screen_class->get_active_window = gdk_broadway_screen_get_active_window;

View File

@ -271,6 +271,7 @@ gdk_screen_get_height_mm
gdk_screen_get_monitor_at_point
gdk_screen_get_monitor_at_window
gdk_screen_get_monitor_geometry
gdk_screen_get_monitor_workarea
gdk_screen_get_monitor_height_mm
gdk_screen_get_monitor_plug_name
gdk_screen_get_monitor_width_mm

View File

@ -750,12 +750,16 @@ gdk_screen_get_monitor_plug_name (GdkScreen *screen,
/**
* gdk_screen_get_monitor_geometry:
* @screen: a #GdkScreen
* @monitor_num: the monitor number, between 0 and gdk_screen_get_n_monitors (screen)
* @dest: (out) (allow-none): a #GdkRectangle to be filled with the monitor geometry
* @monitor_num: the monitor number
* @dest: (out) (allow-none): a #GdkRectangle to be filled with
* the monitor geometry
*
* Retrieves the #GdkRectangle representing the size and position of
* the individual monitor within the entire screen area.
*
* Monitor numbers start at 0. To obtain the number of monitors of
* @screen, use gdk_screen_get_n_monitors().
*
* Note that the size of the entire screen area can be retrieved via
* gdk_screen_get_width() and gdk_screen_get_height().
*
@ -769,6 +773,33 @@ gdk_screen_get_monitor_geometry (GdkScreen *screen,
GDK_SCREEN_GET_CLASS(screen)->get_monitor_geometry (screen, monitor_num, dest);
}
/**
* gdk_screen_get_monitor_workarea:
* @screen: a #GdkScreen
* @monitor_num: the monitor number
* @dest: (out) (allow-none): a #GdkRectangle to be filled with
* the monitor workarea
*
* Retrieves the #GdkRectangle representing the size and position of
* the "work area" on a monitor within the entire screen area.
*
* The work area should be considered when positioning menus and
* similar popups, to avoid placing them below panels, docks or other
* desktop components.
*
* Monitor numbers start at 0. To obtain the number of monitors of
* @screen, use gdk_screen_get_n_monitors().
*
* Since: 3.4
*/
void
gdk_screen_get_monitor_workarea (GdkScreen *screen,
gint monitor_num,
GdkRectangle *dest)
{
GDK_SCREEN_GET_CLASS(screen)->get_monitor_workarea (screen, monitor_num, dest);
}
/**
* gdk_screen_list_visuals:
* @screen: the relevant #GdkScreen.

View File

@ -57,11 +57,15 @@ GList * gdk_screen_list_visuals (GdkScreen *screen);
GList * gdk_screen_get_toplevel_windows (GdkScreen *screen);
gchar * gdk_screen_make_display_name (GdkScreen *screen);
gint gdk_screen_get_n_monitors (GdkScreen *screen);
gint gdk_screen_get_primary_monitor (GdkScreen *screen);
void gdk_screen_get_monitor_geometry (GdkScreen *screen,
gint monitor_num,
GdkRectangle *dest);
gint gdk_screen_get_n_monitors (GdkScreen *screen);
gint gdk_screen_get_primary_monitor (GdkScreen *screen);
void gdk_screen_get_monitor_geometry (GdkScreen *screen,
gint monitor_num,
GdkRectangle *dest);
void gdk_screen_get_monitor_workarea (GdkScreen *screen,
gint monitor_num,
GdkRectangle *area);
gint gdk_screen_get_monitor_at_point (GdkScreen *screen,
gint x,
gint y);

View File

@ -62,6 +62,9 @@ struct _GdkScreenClass
void (* get_monitor_geometry) (GdkScreen *screen,
gint monitor_num,
GdkRectangle *dest);
void (* get_monitor_workarea) (GdkScreen *screen,
gint monitor_num,
GdkRectangle *dest);
GList * (* list_visuals) (GdkScreen *screen);
GdkVisual * (* get_system_visual) (GdkScreen *screen);
GdkVisual * (* get_rgba_visual) (GdkScreen *screen);

View File

@ -462,6 +462,7 @@ gdk_quartz_screen_class_init (GdkQuartzScreenClass *klass)
screen_class->get_monitor_height_mm = gdk_quartz_screen_get_monitor_height_mm;
screen_class->get_monitor_plug_name = gdk_quartz_screen_get_monitor_plug_name;
screen_class->get_monitor_geometry = gdk_quartz_screen_get_monitor_geometry;
screen_class->get_monitor_workarea = gdk_quartz_screen_get_monitor_geometry;
screen_class->is_composited = gdk_quartz_screen_is_composited;
screen_class->make_display_name = gdk_quartz_screen_make_display_name;
screen_class->get_active_window = gdk_quartz_screen_get_active_window;

View File

@ -502,6 +502,7 @@ _gdk_screen_wayland_class_init (GdkScreenWaylandClass *klass)
screen_class->get_monitor_height_mm = gdk_wayland_screen_get_monitor_height_mm;
screen_class->get_monitor_plug_name = gdk_wayland_screen_get_monitor_plug_name;
screen_class->get_monitor_geometry = gdk_wayland_screen_get_monitor_geometry;
screen_class->get_monitor_workarea = gdk_wayland_screen_get_monitor_geometry;
screen_class->get_system_visual = gdk_wayland_screen_get_system_visual;
screen_class->get_rgba_visual = gdk_wayland_screen_get_rgba_visual;
screen_class->is_composited = gdk_wayland_screen_is_composited;

View File

@ -222,6 +222,7 @@ gdk_win32_screen_class_init (GdkWin32ScreenClass *klass)
screen_class->get_monitor_height_mm = gdk_win32_screen_get_monitor_height_mm;
screen_class->get_monitor_plug_name = gdk_win32_screen_get_monitor_plug_name;
screen_class->get_monitor_geometry = gdk_win32_screen_get_monitor_geometry;
screen_class->get_monitor_workarea = gdk_win32_screen_get_monitor_geometry;
screen_class->get_system_visual = _gdk_win32_screen_get_system_visual;
screen_class->get_rgba_visual = gdk_win32_screen_get_rgba_visual;
screen_class->is_composited = gdk_win32_screen_is_composited;
@ -238,4 +239,4 @@ gdk_win32_screen_class_init (GdkWin32ScreenClass *klass)
screen_class->query_depths = _gdk_win32_screen_query_depths;
screen_class->query_visual_types = _gdk_win32_screen_query_visual_types;
screen_class->list_visuals = _gdk_win32_screen_list_visuals;
}
}

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;