[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