[gtk+] x11: Add EWMH workspace handling api



commit 13f6552a7ea771638240f394c495c977e33533d0
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat Aug 24 00:51:01 2013 -0400

    x11: Add EWMH workspace handling api
    
    Add a few functions that give access to the EWMH workspace
    properties.

 docs/reference/gdk/gdk3-sections.txt |    4 +
 gdk/x11/gdkscreen-x11.c              |   71 +++++++++++++++++
 gdk/x11/gdkwindow-x11.c              |  139 ++++++++++++++++++++++------------
 gdk/x11/gdkx11screen.h               |    5 +
 gdk/x11/gdkx11window.h               |    6 ++
 5 files changed, 175 insertions(+), 50 deletions(-)
---
diff --git a/docs/reference/gdk/gdk3-sections.txt b/docs/reference/gdk/gdk3-sections.txt
index 365244c..634c2c1 100644
--- a/docs/reference/gdk/gdk3-sections.txt
+++ b/docs/reference/gdk/gdk3-sections.txt
@@ -998,6 +998,8 @@ gdk_x11_screen_get_window_manager_name
 gdk_x11_screen_get_monitor_output
 gdk_x11_screen_lookup_visual
 gdk_x11_screen_supports_net_wm_hint
+gdk_x11_screen_get_number_of_desktops
+gdk_x11_screen_get_current_desktop
 gdk_x11_window_foreign_new_for_display
 gdk_x11_window_lookup_for_display
 gdk_x11_window_get_xid
@@ -1005,6 +1007,8 @@ gdk_x11_window_set_hide_titlebar_when_maximized
 gdk_x11_window_set_theme_variant
 gdk_x11_window_set_user_time
 gdk_x11_window_move_to_current_desktop
+gdk_x11_window_move_to_desktop
+gdk_x11_window_get_desktop
 gdk_x11_window_set_utf8_property
 gdk_x11_get_default_root_xwindow
 gdk_x11_get_default_screen
diff --git a/gdk/x11/gdkscreen-x11.c b/gdk/x11/gdkscreen-x11.c
index 9f2f833..c2d7c88 100644
--- a/gdk/x11/gdkscreen-x11.c
+++ b/gdk/x11/gdkscreen-x11.c
@@ -1722,3 +1722,74 @@ gdk_x11_screen_class_init (GdkX11ScreenClass *klass)
                   G_TYPE_NONE,
                   0);
 }
+
+static guint32
+get_netwm_cardinal_property (GdkScreen   *screen,
+                             const gchar *name)
+{
+  GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
+  GdkAtom atom;
+  guint32 prop = 0;
+  Atom type;
+  gint format;
+  gulong nitems;
+  gulong bytes_after;
+  guchar *data;
+
+  atom = gdk_atom_intern_static_string (name);
+
+  if (!gdk_x11_screen_supports_net_wm_hint (screen, atom))
+    return 0;
+
+  XGetWindowProperty (x11_screen->xdisplay,
+                      x11_screen->xroot_window,
+                      gdk_x11_get_xatom_by_name_for_display (GDK_SCREEN_DISPLAY (screen), name),
+                      0, G_MAXLONG,
+                      False, XA_CARDINAL, &type, &format, &nitems,
+                      &bytes_after, &data);
+  if (type == XA_CARDINAL)
+    {
+      prop = *(gulong *)data;
+      XFree (data);
+    }
+
+  return prop;
+}
+
+/**
+ * gdk_x11_screen_get_number_of_desktops:
+ * @screen: a #GdkScreen
+ *
+ * Returns the number of workspaces for @screen when running under a
+ * window manager that supports multiple workspaces, as described
+ * in the <ulink url="http://www.freedesktop.org/Standards/wm-spec";>Extended 
+ * Window Manager Hints</ulink>.
+ *
+ * Returns: the number of workspaces, or 0 if workspaces are not supported
+ *
+ * Since: 3.10
+ */
+guint32
+gdk_x11_screen_get_number_of_desktops (GdkScreen *screen)
+{
+  return get_netwm_cardinal_property (screen, "_NET_NUMBER_OF_DESKTOPS");
+}
+
+/**
+ * gdk_x11_screen_get_current_desktop:
+ * @screen: a #GdkScreen
+ *
+ * Returns the current workspace for @screen when running under a
+ * window manager that supports multiple workspaces, as described
+ * in the <ulink url="http://www.freedesktop.org/Standards/wm-spec";>Extended 
+ * Window Manager Hints</ulink>.
+ *
+ * Returns: the current workspace, or 0 if workspaces are not supported
+ *
+ * Since: 3.10
+ */
+guint32
+gdk_x11_screen_get_current_desktop (GdkScreen *screen)
+{
+  return get_netwm_cardinal_property (screen, "_NET_CURRENT_DESKTOP");
+}
diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c
index d4ce45c..4dc632f 100644
--- a/gdk/x11/gdkwindow-x11.c
+++ b/gdk/x11/gdkwindow-x11.c
@@ -2116,59 +2116,98 @@ gdk_x11_window_move_to_current_desktop (GdkWindow *window)
 static void
 move_to_current_desktop (GdkWindow *window)
 {
-  if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
-                                          gdk_atom_intern_static_string ("_NET_WM_DESKTOP")) &&
-      gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
-                                          gdk_atom_intern_static_string ("_NET_CURRENT_DESKTOP")))
-    {
-      Atom type;
-      gint format;
-      gulong nitems;
-      gulong bytes_after;
-      guchar *data;
-      gulong *current_desktop;
-      GdkDisplay *display;
-      
-      display = gdk_window_get_display (window);
+  guint32 desktop;
 
-      /* Get current desktop, then set it; this is a race, but not
-       * one that matters much in practice.
-       */
-      XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), 
-                          GDK_WINDOW_XROOTWIN (window),
-                         gdk_x11_get_xatom_by_name_for_display (display, "_NET_CURRENT_DESKTOP"),
-                          0, G_MAXLONG,
-                          False, XA_CARDINAL, &type, &format, &nitems,
-                          &bytes_after, &data);
-
-      if (type == XA_CARDINAL)
-        {
-         XClientMessageEvent xclient;
-         current_desktop = (gulong *)data;
-         
-         memset (&xclient, 0, sizeof (xclient));
-          xclient.type = ClientMessage;
-          xclient.serial = 0;
-          xclient.send_event = True;
-          xclient.window = GDK_WINDOW_XID (window);
-         xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP");
-          xclient.format = 32;
-
-          xclient.data.l[0] = *current_desktop;
-          xclient.data.l[1] = 1; /* source indication */
-          xclient.data.l[2] = 0;
-          xclient.data.l[3] = 0;
-          xclient.data.l[4] = 0;
-      
-          XSendEvent (GDK_DISPLAY_XDISPLAY (display), 
-                      GDK_WINDOW_XROOTWIN (window), 
-                      False,
-                      SubstructureRedirectMask | SubstructureNotifyMask,
-                      (XEvent *)&xclient);
+  desktop = gdk_x11_screen_get_current_desktop (GDK_WINDOW_SCREEN (window));
+  gdk_x11_window_move_to_desktop (window, desktop);
+}
 
-          XFree (current_desktop);
-        }
+static guint32
+get_netwm_cardinal_property (GdkWindow   *window,
+                             const gchar *name)
+{
+  GdkScreen *screen = GDK_WINDOW_SCREEN (window);
+  GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
+  GdkAtom atom;
+  guint32 prop = 0;
+  Atom type;
+  gint format;
+  gulong nitems;
+  gulong bytes_after;
+  guchar *data;
+
+  atom = gdk_atom_intern_static_string (name);
+
+  if (!gdk_x11_screen_supports_net_wm_hint (screen, atom))
+    return 0;
+
+  XGetWindowProperty (x11_screen->xdisplay,
+                      GDK_WINDOW_XID (window),
+                      gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window), name),
+                      0, G_MAXLONG,
+                      False, XA_CARDINAL, &type, &format, &nitems,
+                      &bytes_after, &data);
+  if (type == XA_CARDINAL)
+    {
+      prop = *(gulong *)data;
+      XFree (data);
     }
+
+  return prop;
+}
+
+guint32
+gdk_x11_window_get_desktop (GdkWindow *window)
+{
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  return get_netwm_cardinal_property (window, "_NET_WM_DESKTOP");
+}
+
+/**
+ * gdk_x11_window_move_to_desktop:
+ * @window: a #GdkWindow
+ * @desktop: the number of the workspace to move the window to
+ *
+ * Moves the window to the given workspace when running unde a
+ * window manager that supports multiple workspaces, as described
+ * in the <ulink url="http://www.freedesktop.org/Standards/wm-spec";>Extended 
+ * Window Manager Hints</ulink>.
+ *
+ * Since: 3.10
+ */
+void
+gdk_x11_window_move_to_desktop (GdkWindow *window,
+                                guint32    desktop)
+{
+  GdkAtom atom;
+  XClientMessageEvent xclient;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  atom = gdk_atom_intern_static_string ("_NET_WM_DESKTOP");
+  if (!gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window), atom))
+    return;
+
+  memset (&xclient, 0, sizeof (xclient));
+  xclient.type = ClientMessage;
+  xclient.serial = 0;
+  xclient.send_event = True;
+  xclient.window = GDK_WINDOW_XID (window);
+  xclient.message_type = gdk_x11_atom_to_xatom_for_display (GDK_WINDOW_DISPLAY (window), atom);
+  xclient.format = 32;
+
+  xclient.data.l[0] = desktop;
+  xclient.data.l[1] = 1; /* source indication */
+  xclient.data.l[2] = 0;
+  xclient.data.l[3] = 0;
+  xclient.data.l[4] = 0;
+
+  XSendEvent (GDK_WINDOW_XDISPLAY (window),
+              GDK_WINDOW_XROOTWIN (window),
+              False,
+              SubstructureRedirectMask | SubstructureNotifyMask,
+              (XEvent *)&xclient);
 }
 
 static void
diff --git a/gdk/x11/gdkx11screen.h b/gdk/x11/gdkx11screen.h
index efc7d38..8f91d64 100644
--- a/gdk/x11/gdkx11screen.h
+++ b/gdk/x11/gdkx11screen.h
@@ -104,6 +104,11 @@ GDK_AVAILABLE_IN_ALL
 XID      gdk_x11_screen_get_monitor_output   (GdkScreen *screen,
                                               gint       monitor_num);
 
+GDK_AVAILABLE_IN_3_10
+guint32  gdk_x11_screen_get_number_of_desktops (GdkScreen *screen);
+GDK_AVAILABLE_IN_3_10
+guint32  gdk_x11_screen_get_current_desktop    (GdkScreen *screen);
+
 G_END_DECLS
 
 #endif /* __GDK_X11_SCREEN_H__ */
diff --git a/gdk/x11/gdkx11window.h b/gdk/x11/gdkx11window.h
index 24bb853..8e8290c 100644
--- a/gdk/x11/gdkx11window.h
+++ b/gdk/x11/gdkx11window.h
@@ -77,6 +77,12 @@ void     gdk_x11_window_set_hide_titlebar_when_maximized (GdkWindow *window,
 GDK_AVAILABLE_IN_ALL
 void     gdk_x11_window_move_to_current_desktop (GdkWindow   *window);
 
+GDK_AVAILABLE_IN_3_10
+guint32  gdk_x11_window_get_desktop             (GdkWindow   *window);
+GDK_AVAILABLE_IN_3_10
+void     gdk_x11_window_move_to_desktop         (GdkWindow   *window,
+                                                 guint32      desktop);
+
 GDK_AVAILABLE_IN_3_8
 void     gdk_x11_window_set_frame_sync_enabled (GdkWindow *window,
                                                 gboolean   frame_sync_enabled);


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