summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2011-12-18 14:02:55 -0500
committerMatthias Clasen <mclasen@redhat.com>2011-12-18 14:29:16 -0500
commitc6df2828b7ca6b65b7ab3c328ebb96bd78c087ee (patch)
tree19922b74f44281c5d4ec3733437523d6b0340e11
parent74cff292d505f8855e78ab0fc37c6ff380d447ca (diff)
downloadgtk+-c6df2828b7ca6b65b7ab3c328ebb96bd78c087ee.tar.gz
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
-rw-r--r--docs/reference/gdk/gdk3-sections.txt1
-rw-r--r--gdk/broadway/gdkscreen-broadway.c1
-rw-r--r--gdk/gdk.symbols1
-rw-r--r--gdk/gdkscreen.c35
-rw-r--r--gdk/gdkscreen.h14
-rw-r--r--gdk/gdkscreenprivate.h3
-rw-r--r--gdk/quartz/gdkscreen-quartz.c1
-rw-r--r--gdk/wayland/gdkscreen-wayland.c1
-rw-r--r--gdk/win32/gdkscreen-win32.c3
-rw-r--r--gdk/x11/gdkscreen-x11.c108
10 files changed, 160 insertions, 8 deletions
diff --git a/docs/reference/gdk/gdk3-sections.txt b/docs/reference/gdk/gdk3-sections.txt
index 6204900377..ca4173bf7a 100644
--- a/docs/reference/gdk/gdk3-sections.txt
+++ b/docs/reference/gdk/gdk3-sections.txt
@@ -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
diff --git a/gdk/broadway/gdkscreen-broadway.c b/gdk/broadway/gdkscreen-broadway.c
index 77b7a8863e..899ba9f729 100644
--- a/gdk/broadway/gdkscreen-broadway.c
+++ b/gdk/broadway/gdkscreen-broadway.c
@@ -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;
diff --git a/gdk/gdk.symbols b/gdk/gdk.symbols
index 4222d69a28..e6e366b401 100644
--- a/gdk/gdk.symbols
+++ b/gdk/gdk.symbols
@@ -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
diff --git a/gdk/gdkscreen.c b/gdk/gdkscreen.c
index c1de0f64e9..9493e168ff 100644
--- a/gdk/gdkscreen.c
+++ b/gdk/gdkscreen.c
@@ -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().
*
@@ -770,6 +774,33 @@ gdk_screen_get_monitor_geometry (GdkScreen *screen,
}
/**
+ * 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.
*
diff --git a/gdk/gdkscreen.h b/gdk/gdkscreen.h
index 0f16a8f0f6..a48c48bfe1 100644
--- a/gdk/gdkscreen.h
+++ b/gdk/gdkscreen.h
@@ -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);
diff --git a/gdk/gdkscreenprivate.h b/gdk/gdkscreenprivate.h
index 42d03f259d..5ce9f07840 100644
--- a/gdk/gdkscreenprivate.h
+++ b/gdk/gdkscreenprivate.h
@@ -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);
diff --git a/gdk/quartz/gdkscreen-quartz.c b/gdk/quartz/gdkscreen-quartz.c
index 678a947243..d104571ce6 100644
--- a/gdk/quartz/gdkscreen-quartz.c
+++ b/gdk/quartz/gdkscreen-quartz.c
@@ -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;
diff --git a/gdk/wayland/gdkscreen-wayland.c b/gdk/wayland/gdkscreen-wayland.c
index cf7ef90349..310fc15a72 100644
--- a/gdk/wayland/gdkscreen-wayland.c
+++ b/gdk/wayland/gdkscreen-wayland.c
@@ -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;
diff --git a/gdk/win32/gdkscreen-win32.c b/gdk/win32/gdkscreen-win32.c
index d7a5815bf5..457858a2e7 100644
--- a/gdk/win32/gdkscreen-win32.c
+++ b/gdk/win32/gdkscreen-win32.c
@@ -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;
-} \ No newline at end of file
+}
diff --git a/gdk/x11/gdkscreen-x11.c b/gdk/x11/gdkscreen-x11.c
index fc3adaddd2..5574f639e0 100644
--- a/gdk/x11/gdkscreen-x11.c
+++ b/gdk/x11/gdkscreen-x11.c
@@ -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;