[Xfce4-commits] <xfce4-embed-plugin:master> Added window enumeration.

David Schneider noreply at xfce.org
Sun Jan 1 21:44:20 CET 2012


Updating branch refs/heads/master
         to 774ba3393dc6aae7d22a54422c49d805639a4d3a (commit)
       from 915a0f8383f30a59218e229f3af7f5d76673f83b (commit)

commit 774ba3393dc6aae7d22a54422c49d805639a4d3a
Author: David Schneider <dnschneid at gmail.com>
Date:   Thu Dec 29 01:12:34 2011 -0500

    Added window enumeration.

 panel-plugin/Makefile.am                 |    4 +-
 panel-plugin/embed.c                     |   64 ++++++++--
 panel-plugin/embed.h                     |    6 +-
 panel-plugin/ewmh.c                      |  211 ++++++++++++++++++++++++++++++
 panel-plugin/{embed-dialogs.h => ewmh.h} |   18 ++--
 5 files changed, 280 insertions(+), 23 deletions(-)

diff --git a/panel-plugin/Makefile.am b/panel-plugin/Makefile.am
index 571118c..9b6854a 100644
--- a/panel-plugin/Makefile.am
+++ b/panel-plugin/Makefile.am
@@ -17,7 +17,9 @@ xfce4_embed_plugin_SOURCES = \
 	embed.c \
 	embed.h \
 	embed-dialogs.c \
-	embed-dialogs.h
+	embed-dialogs.h \
+	ewmh.c \
+	ewmh.h
 
 xfce4_embed_plugin_CFLAGS = \
 	$(LIBXFCE4UTIL_CFLAGS) \
diff --git a/panel-plugin/embed.c b/panel-plugin/embed.c
index 6030b11..63e32d6 100644
--- a/panel-plugin/embed.c
+++ b/panel-plugin/embed.c
@@ -29,16 +29,17 @@
 #include <libxfce4panel/xfce-panel-plugin.h>
 #include <libxfce4panel/xfce-hvbox.h>
 
+#include "ewmh.h"
 #include "embed.h"
 #include "embed-dialogs.h"
 
 /* default settings */
-#define DEFAULT_PROC_NAME   NULL
-#define DEFAULT_WINDOW_NAME NULL
-#define DEFAULT_LABEL_FMT   NULL
-#define DEFAULT_POLL_DELAY  500
-#define DEFAULT_MIN_SIZE    EMBED_MIN_SIZE_MATCH_WINDOW
-#define DEFAULT_EXPAND      TRUE
+#define DEFAULT_PROC_NAME    NULL
+#define DEFAULT_WINDOW_REGEX NULL
+#define DEFAULT_LABEL_FMT    NULL
+#define DEFAULT_POLL_DELAY   500
+#define DEFAULT_MIN_SIZE     EMBED_MIN_SIZE_MATCH_WINDOW
+#define DEFAULT_EXPAND       TRUE
 
 
 
@@ -81,8 +82,8 @@ embed_save (XfcePanelPlugin *plugin, EmbedPlugin *embed)
     DBG(".");
     if (embed->proc_name)
       xfce_rc_write_entry   (rc, "proc_name",   embed->proc_name);
-    if (embed->window_name)
-      xfce_rc_write_entry   (rc, "window_name", embed->window_name);
+    if (embed->window_regex)
+      xfce_rc_write_entry   (rc, "window_regex", embed->window_regex);
     if (embed->label_fmt)
       xfce_rc_write_entry   (rc, "label_fmt",   embed->label_fmt);
     xfce_rc_write_int_entry (rc, "poll_delay",  embed->poll_delay);
@@ -115,8 +116,8 @@ embed_read (EmbedPlugin *embed)
       /* read the settings */
       embed->proc_name = g_strdup (xfce_rc_read_entry (rc,
                               "proc_name", DEFAULT_PROC_NAME));
-      embed->window_name = g_strdup (xfce_rc_read_entry (rc,
-                              "window_name", DEFAULT_WINDOW_NAME));
+      embed->window_regex = g_strdup (xfce_rc_read_entry (rc,
+                              "window_regex", DEFAULT_WINDOW_REGEX));
       embed->label_fmt = g_strdup (xfce_rc_read_entry (rc,
                               "label_fmt", DEFAULT_LABEL_FMT));
       embed->poll_delay = xfce_rc_read_int_entry (rc,
@@ -136,7 +137,7 @@ embed_read (EmbedPlugin *embed)
   DBG ("Applying default settings");
 
   embed->proc_name   = g_strdup (DEFAULT_PROC_NAME);
-  embed->window_name = g_strdup (DEFAULT_WINDOW_NAME);
+  embed->window_regex = g_strdup (DEFAULT_WINDOW_REGEX);
   embed->label_fmt   = g_strdup (DEFAULT_LABEL_FMT);
   embed->poll_delay  = DEFAULT_POLL_DELAY;
   embed->min_size    = DEFAULT_MIN_SIZE;
@@ -166,6 +167,14 @@ embed_new (XfcePanelPlugin *plugin)
   /* read the user settings */
   embed_read (embed);
 
+  /* Compile the window name regex */
+  if (embed->window_regex)
+    embed->window_regex_comp = g_regex_new (embed->window_regex,
+                                            G_REGEX_OPTIMIZE, 0, NULL);
+
+  /* Open X11 display */
+  embed->disp = XOpenDisplay(NULL);
+
   /* get the current orientation */
   orientation = xfce_panel_plugin_get_orientation (plugin);
 
@@ -214,9 +223,16 @@ embed_free (XfcePanelPlugin *plugin, EmbedPlugin *embed)
 
   /* cleanup the settings */
   g_free (embed->proc_name);
-  g_free (embed->window_name);
+  g_free (embed->window_regex);
   g_free (embed->label_fmt);
 
+  /* Close the X11 display */
+  XCloseDisplay(embed->disp);
+
+  /* Release the compiled regex */
+  if (embed->window_regex_comp)
+    g_regex_unref (embed->window_regex_comp);
+
   /* free the plugin structure */
   panel_slice_free (EmbedPlugin, embed);
 }
@@ -284,8 +300,32 @@ embed_update_label (EmbedPlugin *embed)
 static gboolean
 embed_search (EmbedPlugin *embed)
 {
+  Window *client_list;
+  gulong client_list_size;
+  gulong i;
+
   DBG (".");
+  
   /* TODO: search! */
+  if ((client_list = get_client_list(embed->disp, &client_list_size))) {
+    for (i = 0; i < client_list_size / sizeof(Window); i++) {
+      gchar *title, *class, *proc;
+      guint width, height;
+
+      
+      title = get_window_title (embed->disp, client_list[i]);
+      class = get_window_class (embed->disp, client_list[i]);
+      proc  = get_client_proc  (embed->disp, client_list[i]);
+      get_window_size (embed->disp, client_list[i], &width, &height);
+
+      DBG("%s: %s, %s, %ux%u", proc, title, class, width, height);
+
+      g_free(title);
+      g_free(class);
+      g_free(proc);
+    }
+    g_free(client_list);
+  }
 
   /* Return TRUE if we haven't found a plug yet, so that the function is called
    * again. */
diff --git a/panel-plugin/embed.h b/panel-plugin/embed.h
index 995e875..2d73d90 100644
--- a/panel-plugin/embed.h
+++ b/panel-plugin/embed.h
@@ -41,12 +41,16 @@ typedef struct
     gint             plug_height;
     gboolean         plug_is_gtkplug;
 
+    Display         *disp;
+
     guint            search_timer;
     gboolean         disable_search;
 
+    GRegex          *window_regex_comp;
+
     /* embed settings */
     gchar           *proc_name;
-    gchar           *window_name;
+    gchar           *window_regex;
     gchar           *label_fmt;
     gint             poll_delay;
     gint             min_size;
diff --git a/panel-plugin/ewmh.c b/panel-plugin/ewmh.c
new file mode 100644
index 0000000..90c91da
--- /dev/null
+++ b/panel-plugin/ewmh.c
@@ -0,0 +1,211 @@
+/*  $Id$
+ *
+ *  Copyright (c) 2011 David Schneider <dnschneid at gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include <X11/Xatom.h>
+#include <gtk/gtk.h>
+#include <libxfce4util/libxfce4util.h>
+#include <libxfce4panel/xfce-panel-plugin.h>
+
+#include "ewmh.h"
+
+/* EWMH functions adapted from wmctrl project. */
+
+#define MAX_PROPERTY_VALUE_LEN 4096
+
+
+static gchar *get_property (Display *disp, Window win, Atom xa_prop_type,
+                            gchar *prop_name, gulong *size)
+{
+    Atom xa_prop_name;
+    Atom xa_ret_type;
+    gint ret_format;
+    gulong ret_nitems;
+    gulong ret_bytes_after;
+    gulong tmp_size;
+    guchar *ret_prop;
+    gchar *ret;
+    
+    xa_prop_name = XInternAtom(disp, prop_name, False);
+    
+    /* MAX_PROPERTY_VALUE_LEN / 4 explanation (XGetWindowProperty manpage):
+     *
+     * long_length = Specifies the length in 32-bit multiples of the
+     *               data to be retrieved.
+     *
+     * NOTE:  see 
+     * http://mail.gnome.org/archives/wm-spec-list/2003-March/msg00067.html
+     * In particular:
+     *
+     * 	When the X window system was ported to 64-bit architectures, a
+     * rather peculiar design decision was made. 32-bit quantities such
+     * as Window IDs, atoms, etc, were kept as longs in the client side
+     * APIs, even when long was changed to 64 bits.
+     *
+     */
+    if (XGetWindowProperty(disp, win, xa_prop_name, 0, MAX_PROPERTY_VALUE_LEN / 4, False,
+            xa_prop_type, &xa_ret_type, &ret_format,     
+            &ret_nitems, &ret_bytes_after, &ret_prop) != Success) {
+        DBG("Cannot get %s property.\n", prop_name);
+        return NULL;
+    }
+  
+    if (xa_ret_type != xa_prop_type) {
+        DBG("Invalid type of %s property.\n", prop_name);
+        XFree(ret_prop);
+        return NULL;
+    }
+
+    /* null terminate the result to make string handling easier */
+    tmp_size = (ret_format / 8) * ret_nitems;
+    /* Correct 64 Architecture implementation of 32 bit data */
+    if(ret_format==32) tmp_size *= sizeof(glong)/4;
+    ret = g_malloc(tmp_size + 1);
+    memcpy(ret, ret_prop, tmp_size);
+    ret[tmp_size] = '\0';
+
+    if (size) {
+        *size = tmp_size;
+    }
+    
+    XFree(ret_prop);
+    return ret;
+}
+
+
+Window *get_client_list (Display *disp, gulong *size)
+{
+    Window *client_list;
+
+    if ((client_list = (Window *)get_property(disp, DefaultRootWindow(disp), 
+                    XA_WINDOW, "_NET_CLIENT_LIST", size)) == NULL) {
+        if ((client_list = (Window *)get_property(disp, DefaultRootWindow(disp), 
+                        XA_CARDINAL, "_WIN_CLIENT_LIST", size)) == NULL) {
+            DBG("Cannot get client list properties. \n"
+                  "(_NET_CLIENT_LIST or _WIN_CLIENT_LIST)\n");
+            return NULL;
+        }
+    }
+
+    return client_list;
+}
+
+
+gchar *get_client_proc (Display *disp, Window win)
+{
+    gulong *pid;
+    gchar  proc[25];
+    gchar *contents;
+    gsize  length;
+    gchar *start;
+    gchar *end;
+    gchar *procname;
+
+    if ((pid = (gulong *)get_property(disp, win, XA_CARDINAL,
+                                      "_NET_WM_PID", NULL)) == NULL)
+        return NULL;
+
+    procname = NULL;
+
+    /* First attempt the full command line */
+    g_snprintf (proc, 25, "/proc/%lu/cmdline", *pid);
+    if ((g_file_get_contents (proc, &contents, &length, NULL))) {
+        if (length) {
+            contents[length-1] = '\0';
+            start = strrchr (contents, '/');
+            start = start ? start+1 : contents;
+            procname = g_strdup (start);
+        }
+        g_free (contents);
+    }
+    if (procname == NULL) {
+        /* Otherwise, grab the potentially-truncated version from stat */
+        g_snprintf (proc, 25, "/proc/%lu/stat", *pid);
+        if (g_file_get_contents (proc, &contents, &length, NULL)) {
+            if (length) {
+                contents[length-1] = '\0';
+                start = strchr (contents, '(');
+                if (start) {
+                    end = strchr (start, ')');
+                    if (end) {
+                        *end = '\0';
+                        procname = g_strdup (start+1);
+                    }
+                }
+            }
+            g_free (contents);
+        }
+    }
+
+    g_free (pid);
+    return procname;
+}
+
+
+gchar *get_window_title (Display *disp, Window win)
+{
+    gchar *title;
+    gchar *wm_name;
+
+    wm_name = get_property(disp, win, XInternAtom(disp, "UTF8_STRING", False),
+                           "_NET_WM_NAME", NULL);
+
+    if (wm_name) {
+        if ((title = g_locale_from_utf8(wm_name, -1, NULL, NULL, NULL))) {
+            g_free(wm_name);
+            return title;
+        }
+        return wm_name;
+    } else {
+        return get_property(disp, win, XA_STRING, "WM_NAME", NULL);
+    }
+}
+
+
+gchar *get_window_class (Display *disp, Window win)
+{
+    gchar *wm_class;
+    unsigned long size;
+
+    wm_class = get_property(disp, win, XA_STRING, "WM_CLASS", &size);
+    if (wm_class) {
+        gchar *p_0 = strchr(wm_class, '\0');
+        if (wm_class + size - 1 > p_0) {
+            *(p_0) = '.';
+        }
+    }
+
+    return wm_class;
+}
+
+
+void get_window_size (Display *disp, Window win, gint *width, gint *height)
+{
+    Window root;
+    gint relx, rely;
+    guint bw, depth;
+    XGetGeometry (disp, win, &root, &relx, &rely,
+                  (guint *)width, (guint *)height, &bw, &depth);
+}
diff --git a/panel-plugin/embed-dialogs.h b/panel-plugin/ewmh.h
similarity index 70%
copy from panel-plugin/embed-dialogs.h
copy to panel-plugin/ewmh.h
index c0659f2..1198293 100644
--- a/panel-plugin/embed-dialogs.h
+++ b/panel-plugin/ewmh.h
@@ -17,18 +17,18 @@
  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
-#ifndef __EMBED_DIALOGS_H__
-#define __EMBED_DIALOGS_H__
+#ifndef __EWMH_H__
+#define __EWMH_H__
 
 G_BEGIN_DECLS
 
-void
-embed_configure    (XfcePanelPlugin *plugin,
-                     EmbedPlugin     *embed);
-
-void
-embed_about        (XfcePanelPlugin *plugin);
+Window *get_client_list  (Display *disp, gulong *size);
+gchar  *get_client_proc  (Display *disp, Window win);
+gchar  *get_window_title (Display *disp, Window win);
+gchar  *get_window_class (Display *disp, Window win);
+void    get_window_size  (Display *disp, Window win, gint *width, gint *height);
 
 G_END_DECLS
 
-#endif
+#endif /* !__EWMH_H__ */
+


More information about the Xfce4-commits mailing list