[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