[gtk+] Add gdk_screen_get_monitor_workarea



commit c6df2828b7ca6b65b7ab3c328ebb96bd78c087ee
Author: Matthias Clasen <mclasen redhat com>
Date:   Sun Dec 18 14:02:55 2011 -0500

    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

 docs/reference/gdk/gdk3-sections.txt |    1 +
 gdk/broadway/gdkscreen-broadway.c    |    1 +
 gdk/gdk.symbols                      |    1 +
 gdk/gdkscreen.c                      |   35 ++++++++++-
 gdk/gdkscreen.h                      |   14 +++--
 gdk/gdkscreenprivate.h               |    3 +
 gdk/quartz/gdkscreen-quartz.c        |    1 +
 gdk/wayland/gdkscreen-wayland.c      |    1 +
 gdk/win32/gdkscreen-win32.c          |    3 +-
 gdk/x11/gdkscreen-x11.c              |  108 ++++++++++++++++++++++++++++++++++
 10 files changed, 160 insertions(+), 8 deletions(-)
---
diff --git a/docs/reference/gdk/gdk3-sections.txt b/docs/reference/gdk/gdk3-sections.txt
index 6204900..ca4173b 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 77b7a88..899ba9f 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 4222d69..e6e366b 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 c1de0f6..9493e16 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 0f16a8f..a48c48b 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 42d03f2..5ce9f07 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 678a947..d104571 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 cf7ef90..310fc15 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 d7a5815..457858a 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 fc3adad..5574f63 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;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]