[libwnck] WnckWindow: add WM_WINDOW_ROLE support



commit 476d0246e6557149eb114b420f69e1c53283adc9
Author: Marco Trevisan (TreviÃo) <mail 3v1n0 net>
Date:   Wed Jan 9 16:27:16 2013 +0100

    WnckWindow: add WM_WINDOW_ROLE support
    
    Added both a getter and a signal to be notified of its changes
    
    https://bugzilla.gnome.org/show_bug.cgi?id=691429

 libwnck/window.c |   93 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 libwnck/window.h |    7 +++-
 2 files changed, 96 insertions(+), 4 deletions(-)
---
diff --git a/libwnck/window.c b/libwnck/window.c
index b375aa1..6756f68 100644
--- a/libwnck/window.c
+++ b/libwnck/window.c
@@ -84,6 +84,7 @@ struct _WnckWindowPrivate
   char *icon_name;
   char *session_id;
   char *session_id_utf8;
+  char *role;
   int pid;
   int workspace;
   gint sort_order;
@@ -159,10 +160,12 @@ struct _WnckWindowPrivate
   guint need_update_wmclass : 1;
   guint need_update_wmhints : 1;
   guint need_update_frame_extents : 1;
+  guint need_update_role : 1;
 
   guint need_emit_name_changed : 1;
   guint need_emit_icon_changed : 1;
   guint need_emit_class_changed : 1;
+  guint need_emit_role_changed : 1;
 };
 
 G_DEFINE_TYPE (WnckWindow, wnck_window, G_TYPE_OBJECT);
@@ -176,6 +179,7 @@ enum {
   ACTIONS_CHANGED,
   GEOMETRY_CHANGED,
   CLASS_CHANGED,
+  ROLE_CHANGED,
   LAST_SIGNAL
 };
 
@@ -193,7 +197,8 @@ static void emit_actions_changed   (WnckWindow       *window,
                                     WnckWindowActions changed_mask,
                                     WnckWindowActions new_actions);
 static void emit_geometry_changed  (WnckWindow      *window);
-static void emit_class_changed  (WnckWindow      *window);
+static void emit_class_changed     (WnckWindow      *window);
+static void emit_role_changed      (WnckWindow      *window);
 
 static void update_name      (WnckWindow *window);
 static void update_state     (WnckWindow *window);
@@ -204,8 +209,9 @@ static void update_actions   (WnckWindow *window);
 static void update_wintype   (WnckWindow *window);
 static void update_transient_for (WnckWindow *window);
 static void update_startup_id (WnckWindow *window);
-static void update_wmclass    (WnckWindow *window);
+static void update_wmclass   (WnckWindow *window);
 static void update_frame_extents (WnckWindow *window);
+static void update_role      (WnckWindow *window);
 static void unqueue_update   (WnckWindow *window);
 static void queue_update     (WnckWindow *window);
 static void force_update_now (WnckWindow *window);
@@ -306,10 +312,12 @@ wnck_window_init (WnckWindow *window)
   window->priv->need_update_wmclass = FALSE;
   window->priv->need_update_wmhints = FALSE;
   window->priv->need_update_frame_extents = FALSE;
+  window->priv->need_update_role = FALSE;
 
   window->priv->need_emit_name_changed = FALSE;
   window->priv->need_emit_icon_changed = FALSE;
   window->priv->need_emit_class_changed = FALSE;
+  window->priv->need_emit_role_changed = FALSE;
 }
 
 static void
@@ -438,6 +446,21 @@ wnck_window_class_init (WnckWindowClass *klass)
                   NULL, NULL,
                   g_cclosure_marshal_VOID__VOID,
                   G_TYPE_NONE, 0);
+
+  /**
+   * WnckWindow::role-changed:
+   * @window: the #WnckWindow which emitted the signal.
+   *
+   * Emitted when the role of @window changes.
+   */
+  signals[ROLE_CHANGED] =
+    g_signal_new ("role_changed",
+                  G_OBJECT_CLASS_TYPE (object_class),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (WnckWindowClass, role_changed),
+                  NULL, NULL,
+                  g_cclosure_marshal_VOID__VOID,
+                  G_TYPE_NONE, 0);
 }
 
 static void
@@ -601,9 +624,11 @@ _wnck_window_create (Window      xwindow,
   window->priv->need_update_wmclass = TRUE;
   window->priv->need_update_wmhints = TRUE;
   window->priv->need_update_frame_extents = TRUE;
+  window->priv->need_update_role = TRUE;
   window->priv->need_emit_name_changed = FALSE;
   window->priv->need_emit_icon_changed = FALSE;
   window->priv->need_emit_class_changed = FALSE;
+  window->priv->need_emit_role_changed = FALSE;
   force_update_now (window);
 
   return window;
@@ -916,6 +941,24 @@ wnck_window_get_session_id_utf8 (WnckWindow *window)
 }
 
 /**
+ * wnck_window_get_role:
+ * @window: a #WnckWindow.
+ *
+ * Gets the role for @window.
+ * The role uniquely identifies a window among all windows that have the same
+ * client leader window.
+ *
+ * Return value: role for @window, or %NULL if @window has no role.
+ **/
+const char*
+wnck_window_get_role (WnckWindow *window)
+{
+  g_return_val_if_fail (WNCK_IS_WINDOW (window), NULL);
+
+  return window->priv->role;
+}
+
+/**
  * wnck_window_get_pid:
  * @window: a #WnckWindow.
  *
@@ -2644,6 +2687,12 @@ _wnck_window_process_property_notify (WnckWindow *window,
       window->priv->need_update_frame_extents = TRUE;
       queue_update (window);
     }
+  else if (xevent->xproperty.atom ==
+           _wnck_atom_get ("WM_WINDOW_ROLE"))
+    {
+      window->priv->need_update_role = TRUE;
+      queue_update (window);
+    }
 }
 
 void
@@ -3236,6 +3285,33 @@ update_frame_extents (WnckWindow *window)
 }
 
 static void
+update_role (WnckWindow *window)
+{
+  char *new_role;
+
+  if (!window->priv->need_update_role)
+    return;
+
+  window->priv->need_update_role = FALSE;
+
+  new_role = _wnck_get_text_property (WNCK_SCREEN_XSCREEN (window->priv->screen),
+                                      window->priv->xwindow,
+                                      _wnck_atom_get ("WM_WINDOW_ROLE"));
+
+  if (g_strcmp0 (window->priv->role, new_role) != 0)
+    {
+      window->priv->need_emit_role_changed = TRUE;
+
+      g_free (window->priv->role);
+      window->priv->role = new_role;
+    }
+  else
+    {
+      g_free (new_role);
+    }
+}
+
+static void
 force_update_now (WnckWindow *window)
 {
   WnckWindowState old_state;
@@ -3271,6 +3347,7 @@ force_update_now (WnckWindow *window)
   update_workspace (window); /* emits signals */
   update_actions (window);
   update_frame_extents (window); /* emits signals */
+  update_role (window); /* emits signals */
 
   get_icons (window);
 
@@ -3288,6 +3365,9 @@ force_update_now (WnckWindow *window)
 
   if (window->priv->need_emit_class_changed)
     emit_class_changed (window);
+
+  if (window->priv->need_emit_role_changed)
+    emit_role_changed (window);
 }
 
 
@@ -3382,3 +3462,12 @@ emit_geometry_changed (WnckWindow *window)
                  signals[GEOMETRY_CHANGED],
                  0);
 }
+
+static void
+emit_role_changed (WnckWindow *window)
+{
+  window->priv->need_emit_role_changed = FALSE;
+  g_signal_emit (G_OBJECT (window),
+                 signals[ROLE_CHANGED],
+                 0);
+}
diff --git a/libwnck/window.h b/libwnck/window.h
index dcc43cd..2e070b8 100644
--- a/libwnck/window.h
+++ b/libwnck/window.h
@@ -279,10 +279,12 @@ struct _WnckWindowClass
   /* Changed class group/instance name */
   void (* class_changed)     (WnckWindow       *window);
 
+  /* Changed role */
+  void (* role_changed)      (WnckWindow       *window);
+
   /* Padding for future expansion */
   void (* pad1) (void);
   void (* pad2) (void);
-  void (* pad3) (void);
 };
 
 GType wnck_window_get_type (void) G_GNUC_CONST;
@@ -308,9 +310,10 @@ const char* wnck_window_get_class_instance_name (WnckWindow *window);
 
 const char* wnck_window_get_session_id        (WnckWindow *window);
 const char* wnck_window_get_session_id_utf8   (WnckWindow *window);
+const char* wnck_window_get_role              (WnckWindow *window);
 int         wnck_window_get_pid               (WnckWindow *window);
 gint        wnck_window_get_sort_order        (WnckWindow *window);
-void        wnck_window_set_sort_order        (WnckWindow *window, 
+void        wnck_window_set_sort_order        (WnckWindow *window,
 						gint order);
 
 WnckWindowType wnck_window_get_window_type    (WnckWindow *window);



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