[Xfce4-commits] <transd:master> kill gdk/gtk/libwnck dep
Brian J. Tarricone
noreply at xfce.org
Wed Apr 11 11:52:02 CEST 2012
Updating branch refs/heads/master
to 39aa5ec62816e6c0c108a72001cf8961a93e69d6 (commit)
from aa8f6ee292b47f2a7b9e473a981173bc2db74816 (commit)
commit 39aa5ec62816e6c0c108a72001cf8961a93e69d6
Author: Brian J. Tarricone <brian at tarricone.org>
Date: Wed Apr 11 02:50:28 2012 -0700
kill gdk/gtk/libwnck dep
configure.ac | 2 -
src/Makefile.am | 11 +--
src/main.c | 67 +++++++-------
src/transd.c | 272 ++++++++++++++++++++++++++++++++++++++++---------------
src/transd.h | 10 ++-
5 files changed, 242 insertions(+), 120 deletions(-)
diff --git a/configure.ac b/configure.ac
index 2b1fb45..9a650c4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -41,8 +41,6 @@ XDT_CHECK_LIBX11_REQUIRE
dnl required
XDT_CHECK_PACKAGE([LIBXFCE4UTIL], [libxfce4util-1.0], [4.2.0])
-XDT_CHECK_PACKAGE([GTK], [gtk+-3.0], [3.0.0])
-XDT_CHECK_PACKAGE([WNCK], [libwnck-3.0], [3.0.0])
dnl check for debugging support
XDT_FEATURE_DEBUG
diff --git a/src/Makefile.am b/src/Makefile.am
index 5702cb3..13f35ee 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -5,21 +5,14 @@ transd_SOURCES = \
transd.c \
transd.h
-transd_CPPFLAGS = \
- -DWNCK_I_KNOW_THIS_IS_UNSTABLE
-
transd_CFLAGS = \
-DLOCALEDIR=\"$(localedir)\" \
$(LIBXFCE4UTIL_CFLAGS) \
- $(X11_CFLAGS) \
- $(GTK_CFLAGS) \
- $(WNCK_CFLAGS)
+ $(X11_CFLAGS)
transd_LDFLAGS = \
$(X11_LDFLAGS)
transd_LDADD = \
$(LIBXFCE4UTIL_LIBS) \
- $(X11_LIBS) \
- $(GTK_LIBS) \
- $(WNCK_LIBS)
+ -lX11
diff --git a/src/main.c b/src/main.c
index 508bf49..f1a3cbe 100644
--- a/src/main.c
+++ b/src/main.c
@@ -49,55 +49,56 @@
#include <signal.h>
#endif
-#include <gtk/gtk.h>
-
-#include <libwnck/libwnck.h>
+#include <X11/Xlib.h>
+#include <glib.h>
#include "transd.h"
static Transd *__g_transd = NULL;
+static Display *__g_dpy = NULL;
+static gboolean running = FALSE;
static void
-setup_transd(Transd *transd)
-{
- gint i, nscreens;
-
- nscreens = gdk_display_get_n_screens(gdk_display_get_default());
- for(i = 0; i < nscreens; i++) {
- WnckScreen *wnck_screen = wnck_screen_get(i);
- wnck_screen_force_update(wnck_screen);
- transd_add_screen(transd, wnck_screen);
- }
-}
-
-static void
sighandler(int sig)
{
switch(sig) {
- case SIGINT:
- case SIGTERM:
- gtk_main_quit();
- break;
-
case SIGHUP:
case SIGUSR1:
transd_free(__g_transd);
- __g_transd = transd_new();
- setup_transd(__g_transd);
+ __g_transd = transd_new(__g_dpy);
break;
}
}
+static void
+x_main(Display *dpy,
+ Transd *transd)
+{
+ while (running) {
+ XEvent xev;
+ XNextEvent(dpy, &xev);
+
+ if (xev.type == MapNotify) {
+ g_debug("got map notify");
+ transd_window_mapped(transd, &xev.xmap);
+ } else if (xev.type == PropertyNotify)
+ transd_property_changed(transd, &xev.xproperty);
+ }
+}
+
int
main(int argc, char **argv)
{
gint i;
gboolean daemon_mode = TRUE;
+ const char *display_name = NULL;
for(i = 1; i < argc; i++) {
if(!strcmp(argv[i], "--debug"))
daemon_mode = FALSE;
+ else if (!strncmp(argv[1], "--display=", 10))
+ display_name = argv[1] + 10;
}
if(daemon_mode) {
@@ -135,20 +136,22 @@ main(int argc, char **argv)
}
}
- gtk_init(&argc, &argv);
-
- signal(SIGINT, sighandler);
- signal(SIGTERM, sighandler);
+ __g_dpy = XOpenDisplay(display_name);
+ if (!__g_dpy) {
+ g_printerr("Unable to open display %s\n", display_name ? display_name : ":0");
+ return EXIT_FAILURE;
+ }
+
signal(SIGHUP, sighandler);
signal(SIGUSR1, sighandler);
- __g_transd = transd_new();
-
- setup_transd(__g_transd);
+ __g_transd = transd_new(__g_dpy);
- gtk_main();
+ running = TRUE;
+ x_main(__g_dpy, __g_transd);
transd_free(__g_transd);
+ XCloseDisplay(__g_dpy);
- return 0;
+ return EXIT_SUCCESS;
}
diff --git a/src/transd.c b/src/transd.c
index 29ff1f2..fb8a75a 100644
--- a/src/transd.c
+++ b/src/transd.c
@@ -37,21 +37,20 @@
#include <X11/Xatom.h>
#include <glib.h>
-#include <gdk/gdk.h>
-#include <gdk/gdkx.h>
-#include <gtk/gtk.h>
-
#include <libxfce4util/libxfce4util.h>
#include "transd.h"
#define _XA_OPACITY "_NET_WM_WINDOW_OPACITY"
+#define _XA_WM_CLASS "WM_CLASS"
+#define _XA_WM_NAME "WM_NAME"
+#define _XA_NET_WM_NAME "_NET_WM_NAME"
#define _XA_ROLE "WM_WINDOW_ROLE"
#define TRANSD_RULES_CONFIG "transd/rules.rc"
struct _Transd
{
- GList *screens; /* (WnckScreen *) */
+ Display *dpy;
GHashTable *rules; /* (gchar *) -> (TransdClassRule *) */
};
@@ -61,6 +60,36 @@ typedef struct
GHashTable *roles; /* (gchar *) -> (gint) */
} TransdClassRule;
+
+static int (*last_x_error_handler)(Display *, XErrorEvent *) = NULL;
+static int last_x_error = 0;
+
+static int
+x_error_handler(Display *dpy,
+ XErrorEvent *xev)
+{
+ last_x_error = xev->error_code;
+ return 0;
+}
+
+static void
+trap_x_errors(void)
+{
+ g_assert(last_x_error_handler == NULL);
+ last_x_error_handler = XSetErrorHandler(x_error_handler);
+}
+
+static int
+untrap_x_errors(Display *dpy)
+{
+ int ret = last_x_error;
+ XSync(dpy, False);
+ XSetErrorHandler(last_x_error_handler);
+ last_x_error_handler = NULL;
+ last_x_error = 0;
+ return ret;
+}
+
static void
transd_class_rule_free(TransdClassRule *class_rule)
{
@@ -71,30 +100,76 @@ transd_class_rule_free(TransdClassRule *class_rule)
}
static gchar *
-transd_window_get_role(Window xid)
+get_prop(Display *dpy,
+ Window window,
+ const char *prop_name,
+ Atom prop_type,
+ size_t *len)
{
- gchar *role = NULL;
+ gchar *prop_value = NULL;
Atom actual_type;
int actual_format;
unsigned long nitems, bytes_after;
unsigned char *prop_return = NULL;
- g_return_val_if_fail(xid != None, NULL);
-
- if(Success == XGetWindowProperty(gdk_x11_get_default_xdisplay(), xid,
- XInternAtom(gdk_x11_get_default_xdisplay(), _XA_ROLE, False),
- 0L, 8192, False, XA_STRING, &actual_type,
- &actual_format, &nitems, &bytes_after,
- &prop_return))
+ g_return_val_if_fail(window != None, NULL);
+
+ trap_x_errors();
+
+ if (Success == XGetWindowProperty(dpy, window,
+ XInternAtom(dpy, prop_name, False),
+ 0L, 8192, False, prop_type, &actual_type,
+ &actual_format, &nitems, &bytes_after,
+ &prop_return))
{
- if(actual_format == 8 && actual_type == XA_STRING)
- role = g_strdup((gchar *)prop_return);
+ if (actual_format == 8 && actual_type == prop_type) {
+ prop_value = g_memdup(prop_return, nitems);
+ if (len)
+ *len = nitems;
+ }
- if(prop_return)
+ if (prop_return)
XFree(prop_return);
}
+
+ untrap_x_errors(dpy);
- return role;
+ return prop_value;
+}
+
+static gchar *
+get_string_prop(Display *dpy,
+ Window window,
+ const char *prop_name,
+ size_t *len)
+{
+ return get_prop(dpy, window, prop_name, XA_STRING, len);
+}
+
+static gchar *
+get_utf8_string_prop(Display *dpy,
+ Window window,
+ const char *prop_name,
+ size_t *len)
+{
+ return get_prop(dpy, window, prop_name, XInternAtom(dpy, "UTF8_STRING", False), len);
+}
+
+static gchar *
+get_class_name(Display *dpy,
+ Window window)
+{
+ gchar *class_name = NULL;
+ size_t len = 0;
+ gchar *wm_class = get_string_prop(dpy, window, _XA_WM_CLASS, &len);
+ if (wm_class) {
+ size_t instance_len = strlen(wm_class);
+ if (len > instance_len + 1)
+ class_name = g_strndup(wm_class + instance_len + 1, len - instance_len + 1);
+ g_free(wm_class);
+ }
+
+ return class_name;
}
static gboolean
@@ -148,7 +223,7 @@ transd_read_config(Transd *transd, const gchar *filename)
}
value = xfce_rc_read_int_entry(rcfile, entries[j], -1);
- if(value >= 0 && value <= 100) {
+ if(value <= 100) {
g_hash_table_replace(class_rule->roles, entries[j],
GINT_TO_POINTER(value+1));
DBG(" added config class '%s', role '%s' => 0x%x", groups[i],
@@ -165,40 +240,41 @@ transd_read_config(Transd *transd, const gchar *filename)
}
static void
-transd_apply_rule(Transd *transd, WnckWindow *window)
+transd_apply_rule(Transd *transd, Window window)
{
- WnckClassGroup *cgroup;
- const gchar *class_;
+ gchar *class_;
gchar *role;
gint percentage = 0;
guint32 opacity;
- Window window_xid;
TransdClassRule *class_rule;
TRACE("entering");
- g_return_if_fail(transd && WNCK_IS_WINDOW(window));
-
- cgroup = wnck_window_get_class_group(window);
- class_ = wnck_class_group_get_id(cgroup);
+ g_return_if_fail(transd && window != None);
+
+ class_ = get_class_name(transd->dpy, window);
if (!class_) {
- class_ = wnck_class_group_get_name(cgroup);
+ class_ = get_string_prop(transd->dpy, window, _XA_WM_CLASS, NULL);
if (!class_) {
- class_ = wnck_window_get_name(window);
- if (!class_)
- return;
+ class_ = get_utf8_string_prop(transd->dpy, window, _XA_NET_WM_NAME, NULL);
+ if (!class_) {
+ class_ = get_string_prop(transd->dpy, window, _XA_WM_NAME, NULL);
+ if (!class_)
+ return;
+ }
}
}
-
+ DBG("got class '%s'", class_);
+
/* percentage is actually percentage+1 since a value of 0% would be
* interpreted as "not in hash table" */
class_rule = g_hash_table_lookup(transd->rules, class_);
+ g_free(class_);
if(!class_rule)
return;
- window_xid = wnck_window_get_xid(window);
- /* WTF doesn't libwnck have this function? */
- role = transd_window_get_role(window_xid);
+ role = get_string_prop(transd->dpy, window, _XA_ROLE, NULL);
+ DBG("got role '%s'", role);
if(role)
percentage = GPOINTER_TO_INT(g_hash_table_lookup(class_rule->roles, role));
if(percentage == 0) {
@@ -211,37 +287,28 @@ transd_apply_rule(Transd *transd, WnckWindow *window)
opacity = (guint32)(((gdouble)(percentage - 1)) / 100 * 0xffffffff);
- DBG("applying opacity 0x%x to window %d, class '%s', role '%s'", opacity,
- (guint32)window_xid, class_, role);
+ DBG("applying opacity 0x%x to window %d", opacity, (guint32)window);
- gdk_error_trap_push();
- XChangeProperty(gdk_x11_get_default_xdisplay(), window_xid,
- XInternAtom(gdk_x11_get_default_xdisplay(), _XA_OPACITY, FALSE),
+ trap_x_errors();
+ XChangeProperty(transd->dpy, window,
+ XInternAtom(transd->dpy, _XA_OPACITY, FALSE),
XA_CARDINAL, 32, PropModeReplace,
(unsigned char *)&opacity, 1L);
- if (gdk_error_trap_pop())
- ; // suppress warning
+ untrap_x_errors(transd->dpy);
g_free(role);
}
-static void
-transd_wnck_screen_window_opened_cb(WnckScreen *wnck_screen,
- WnckWindow *window,
- gpointer user_data)
-{
- Transd *transd = user_data;
- transd_apply_rule(transd, window);
-}
-
Transd *
-transd_new()
+transd_new(Display *dpy)
{
Transd *transd;
gchar *config_system, *config_user;
+ unsigned int i, n_screens;
transd = g_new0(Transd, 1);
+ transd->dpy = dpy;
transd->rules = g_hash_table_new_full(g_str_hash, g_str_equal,
(GDestroyNotify)g_free,
(GDestroyNotify)transd_class_rule_free);
@@ -296,40 +363,97 @@ transd_new()
g_free(config_system);
g_free(config_user);
+
+ n_screens = ScreenCount(dpy);
+ for (i = 0; i < n_screens; ++i) {
+ Window root = RootWindow(dpy, i);
+ Window dummy;
+ Window *children = NULL;
+ unsigned int n_children = 0;
+
+ trap_x_errors();
+ XSelectInput(dpy, root, SubstructureNotifyMask);
+ XQueryTree(dpy, root, &dummy, &dummy, &children, &n_children);
+ untrap_x_errors(dpy);
+
+ for (i = 0; i < n_children; ++i) {
+ XMapEvent xev = {
+ .type = MapNotify,
+ .serial = 0,
+ .send_event = False,
+ .display = dpy,
+ .event = root,
+ .window = children[i],
+ .override_redirect = False,
+ };
+
+ transd_window_mapped(transd, &xev);
+ }
+
+ if (children)
+ XFree(children);
+ }
return transd;
}
void
-transd_add_screen(Transd *transd, WnckScreen *wnck_screen)
+transd_window_mapped(Transd *transd,
+ XMapEvent *xmap)
{
- GList *windows, *l;
-
- g_return_if_fail(transd && wnck_screen);
-
- g_signal_connect(G_OBJECT(wnck_screen), "window-opened",
- G_CALLBACK(transd_wnck_screen_window_opened_cb), transd);
- transd->screens = g_list_append(transd->screens, wnck_screen);
-
- windows = wnck_screen_get_windows(wnck_screen);
- for(l = windows; l; l = l->next)
- transd_apply_rule(transd, (WnckWindow *)l->data);
+ Window dummy;
+ Window *children = NULL;
+ unsigned int i, n_children = 0;
+
+ XPropertyEvent xprop = {
+ .type = PropertyNotify,
+ .serial = 0,
+ .send_event = False,
+ .display = transd->dpy,
+ .window = xmap->window,
+ .atom = XInternAtom(transd->dpy, _XA_WM_CLASS, False),
+ .state = PropertyNewValue,
+ };
+
+ trap_x_errors();
+ XSelectInput(transd->dpy, xmap->window, PropertyChangeMask | SubstructureNotifyMask);
+ untrap_x_errors(transd->dpy);
+ transd_property_changed(transd, &xprop);
+
+ trap_x_errors();
+ XQueryTree(transd->dpy, xmap->window, &dummy, &dummy, &children, &n_children);
+ untrap_x_errors(transd->dpy);
+ for (i = 0; i < n_children; ++i) {
+ trap_x_errors();
+ XSelectInput(transd->dpy, children[i], PropertyChangeMask | SubstructureNotifyMask);
+ untrap_x_errors(transd->dpy);
+
+ xprop.window = children[i];
+ transd_property_changed(transd, &xprop);
+ }
+ if (children)
+ XFree(children);
+
+}
+
+void
+transd_property_changed(Transd *transd,
+ XPropertyEvent *xprop)
+{
+ if (xprop->atom == XInternAtom(transd->dpy, "WM_CLASS", False) ||
+ xprop->atom == XInternAtom(transd->dpy, "WM_WINDOW_ROLE", False) ||
+ xprop->atom == XInternAtom(transd->dpy, "WM_NAME", False) ||
+ xprop->atom == XInternAtom(transd->dpy, "_NET_WM_NAME", False))
+ {
+ transd_apply_rule(transd, xprop->window);
+ }
}
void
transd_free(Transd *transd)
{
- GList *l;
-
g_return_if_fail(transd);
-
- for(l = transd->screens; l; l = l->next) {
- g_signal_handlers_disconnect_by_func(G_OBJECT(l->data),
- G_CALLBACK(transd_wnck_screen_window_opened_cb),
- transd);
- }
- g_list_free(transd->screens);
-
+
g_hash_table_destroy(transd->rules);
g_free(transd);
diff --git a/src/transd.h b/src/transd.h
index 7ecddf0..4152adf 100644
--- a/src/transd.h
+++ b/src/transd.h
@@ -18,14 +18,18 @@
#ifndef __TRANSD__H__
#define __TRANSD__H__
-#include <libwnck/libwnck.h>
+#include <X11/Xlib.h>
+#include <glib.h>
G_BEGIN_DECLS
typedef struct _Transd Transd;
-Transd *transd_new();
-void transd_add_screen(Transd *transd, WnckScreen *wnck_screen);
+Transd *transd_new(Display *dpy);
+void transd_window_mapped(Transd *transd,
+ XMapEvent *xev);
+void transd_property_changed(Transd *transd,
+ XPropertyEvent *xev);
void transd_free(Transd *transd);
G_END_DECLS
More information about the Xfce4-commits
mailing list