Updating branch refs/heads/master to 774ba3393dc6aae7d22a54422c49d805639a4d3a (commit) from 915a0f8383f30a59218e229f3af7f5d76673f83b (commit)
commit 774ba3393dc6aae7d22a54422c49d805639a4d3a Author: David Schneider <dnschn...@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 <dnschn...@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__ */ + _______________________________________________ Xfce4-commits mailing list Xfce4-commits@xfce.org https://mail.xfce.org/mailman/listinfo/xfce4-commits