]> git.sur5r.net Git - i3/i3/commitdiff
Implement storing WM_CLASS of each client
authorMichael Stapelberg <michael+x200@stapelberg.de>
Mon, 30 Mar 2009 07:39:35 +0000 (09:39 +0200)
committerMichael Stapelberg <michael+x200@stapelberg.de>
Tue, 5 May 2009 14:53:22 +0000 (16:53 +0200)
include/data.h
include/handlers.h
src/handlers.c
src/mainx.c

index dc7fd8ff70145ae832a7c73989444aa3a8154884..a54798ba2ab9c8a98423d8c2a205e417eedbf89a 100644 (file)
@@ -249,6 +249,9 @@ struct Client {
            legacy window names are ignored. */
         bool uses_net_wm_name;
 
+        /* Holds the WM_CLASS, useful for matching the client in commands */
+        char *window_class;
+
         /* fullscreen is pretty obvious */
         bool fullscreen;
 
index b2c0de94cf843fe5180a8ca60f0beff677afd84a..c160b6007fd05f89539d036e15e8918504e77ba7 100644 (file)
@@ -85,7 +85,15 @@ int handle_windowname_change(void *data, xcb_connection_t *conn, uint8_t state,
  *
  */
 int handle_windowname_change_legacy(void *data, xcb_connection_t *conn, uint8_t state,
-                                xcb_window_t window, xcb_atom_t atom, xcb_get_property_reply_t *prop);
+                                    xcb_window_t window, xcb_atom_t atom, xcb_get_property_reply_t *prop);
+
+/**
+ * Store the window classes for jumping to them later.
+ *
+ */
+int handle_windowclass_change(void *data, xcb_connection_t *conn, uint8_t state,
+                              xcb_window_t window, xcb_atom_t atom, xcb_get_property_reply_t *prop);
+
 
 /**
  * Expose event means we should redraw our windows (= title bar)
index d2eec97811f9245b15aa30923b36ca0cfcfa0b19..0525e8cdde4d804c87d562d9666b64352dad0772 100644 (file)
@@ -744,8 +744,7 @@ int handle_windowname_change(void *data, xcb_connection_t *conn, uint8_t state,
         client->name_len = new_len;
         client->uses_net_wm_name = true;
 
-        if (old_name != NULL)
-                free(old_name);
+        FREE(old_name);
 
         /* If the client is a dock window, we don’t need to render anything */
         if (client->dock)
@@ -827,6 +826,35 @@ int handle_windowname_change_legacy(void *data, xcb_connection_t *conn, uint8_t
         return 1;
 }
 
+/*
+ * Updates the client’s WM_CLASS property
+ *
+ */
+int handle_windowclass_change(void *data, xcb_connection_t *conn, uint8_t state,
+                             xcb_window_t window, xcb_atom_t atom, xcb_get_property_reply_t *prop) {
+        LOG("window class changed\n");
+        if (prop == NULL || xcb_get_property_value_length(prop) == 0) {
+                LOG("prop == NULL\n");
+                return 1;
+        }
+        Client *client = table_get(byChild, window);
+        if (client == NULL)
+                return 1;
+        char *new_class;
+        if (asprintf(&new_class, "%.*s", xcb_get_property_value_length(prop), (char*)xcb_get_property_value(prop)) == -1) {
+                perror("Could not get window class");
+                LOG("Could not get window class\n");
+                return 1;
+        }
+
+        LOG("changed to %s\n", new_class);
+        char *old_class = client->window_class;
+        client->window_class = new_class;
+        FREE(old_class);
+
+        return 1;
+}
+
 /*
  * Expose event means we should redraw our windows (= title bar)
  *
index 38ae2511bf898422ae52d4e57b9fa46f9195490e..e89eaab02e70ff017db28b939df1888ad5649bdc 100644 (file)
@@ -105,6 +105,7 @@ void manage_window(xcb_property_handlers_t *prophs, xcb_connection_t *conn, xcb_
         if (attr && geom) {
                 reparent_window(conn, window, attr->visual, geom->root, geom->depth,
                                 geom->x, geom->y, geom->width, geom->height);
+                xcb_property_changed(prophs, XCB_PROPERTY_NEW_VALUE, window, WM_CLASS);
                 xcb_property_changed(prophs, XCB_PROPERTY_NEW_VALUE, window, WM_NAME);
                 xcb_property_changed(prophs, XCB_PROPERTY_NEW_VALUE, window, WM_NORMAL_HINTS);
                 xcb_property_changed(prophs, XCB_PROPERTY_NEW_VALUE, window, atoms[_NET_WM_NAME]);
@@ -498,6 +499,9 @@ int main(int argc, char *argv[], char *env[]) {
         /* Watch WM_NAME (= title of the window in compound text) property for legacy applications */
         xcb_watch_wm_name(&prophs, 128, handle_windowname_change_legacy, NULL);
 
+        /* Watch WM_CLASS (= class of the window) */
+        xcb_property_set_handler(&prophs, WM_CLASS, 128, handle_windowclass_change, NULL);
+
         /* Set up the atoms we support */
         check_error(conn, xcb_change_property_checked(conn, XCB_PROP_MODE_REPLACE, root, atoms[_NET_SUPPORTED],
                        ATOM, 32, 7, atoms), "Could not set _NET_SUPPORTED");