]> git.sur5r.net Git - i3/i3/commitdiff
Bugfix: Use both parts of WM_CLASS (it contains instance and class) (Thanks fallen)
authorMichael Stapelberg <michael@stapelberg.de>
Fri, 12 Feb 2010 14:56:19 +0000 (15:56 +0100)
committerMichael Stapelberg <michael@stapelberg.de>
Fri, 12 Feb 2010 14:56:19 +0000 (15:56 +0100)
Actually, WM_CLASS contains two null-terminated strings, so we cannot
use asprintf() to get its value but rather use strdup() to get both
of them. Both values are compared when a client is matched against
a wm_class/title combination (for assignments for example).

include/data.h
src/client.c
src/handlers.c
src/util.c

index 12c235544bb957a8be4cf9c1ec86e74d2a312704..971e908d3b696b41a351c728a41f16b8f2ee8551 100644 (file)
@@ -378,8 +378,10 @@ struct Client {
          * in. If set to true, legacy window names are ignored. */
         bool uses_net_wm_name;
 
-        /** Holds the WM_CLASS, useful for matching the client in commands */
-        char *window_class;
+        /** Holds the WM_CLASS (which consists of two strings, the instance
+         * and the class), useful for matching the client in commands */
+        char *window_class_instance;
+        char *window_class_class;
 
         /** Holds the client’s mark, for vim-like jumping */
         char *mark;
index b686a1ae7be3b83e497a0afec1c78d07773b113d..dd88acc1f6f73aff072d7a540b52cfb66358eed8 100644 (file)
@@ -122,7 +122,10 @@ void client_kill(xcb_connection_t *conn, Client *window) {
 bool client_matches_class_name(Client *client, char *to_class, char *to_title,
                                char *to_title_ucs, int to_title_ucs_len) {
         /* Check if the given class is part of the window class */
-        if (client->window_class == NULL || strcasestr(client->window_class, to_class) == NULL)
+        if ((client->window_class_instance == NULL ||
+             strcasestr(client->window_class_instance, to_class) == NULL) &&
+            (client->window_class_class == NULL ||
+             strcasestr(client->window_class_class, to_class) == NULL))
                 return false;
 
         /* If no title was given, we’re done */
index 6cc85f0176ad88aa265209ab3a1cc1a2c582a848..0dc0295b24f954d10d94425d570af891264b46d4 100644 (file)
@@ -534,7 +534,8 @@ int handle_unmap_notify_event(void *data, xcb_connection_t *conn, xcb_unmap_noti
         client->urgent = false;
         workspace_update_urgent_flag(client->workspace);
 
-        FREE(client->window_class);
+        FREE(client->window_class_instance);
+        FREE(client->window_class_class);
         FREE(client->name);
         free(client);
 
@@ -692,28 +693,23 @@ int handle_windowclass_change(void *data, xcb_connection_t *conn, uint8_t state,
         Client *client = table_get(&by_child, 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("WM_CLASS changed to %s\n", new_class);
-        char *old_class = client->window_class;
-        client->window_class = new_class;
-        FREE(old_class);
+        /* We cannot use asprintf here since this property contains two
+         * null-terminated strings (for compatibility reasons). Instead, we
+         * use strdup() on both strings */
+        char *new_class = xcb_get_property_value(prop);
 
-        if (!client->initialized)
-                return 1;
+        FREE(client->window_class_instance);
+        FREE(client->window_class_class);
 
-        if (strcmp(new_class, "tools") == 0 || strcmp(new_class, "Dialog") == 0) {
-                LOG("tool/dialog window, should we put it floating?\n");
-                if (client->floating == FLOATING_AUTO_OFF)
-                        toggle_floating_mode(conn, client, true);
-        }
+        client->window_class_instance = strdup(new_class);
+        if ((strlen(new_class) + 1) < xcb_get_property_value_length(prop))
+                client->window_class_class = strdup(new_class + strlen(new_class) + 1);
+        else client->window_class_class = NULL;
+        LOG("WM_CLASS changed to %s (instance), %s (class)\n",
+            client->window_class_instance, client->window_class_class);
 
-        return 1;
+        return 0;
 }
 
 /*
index 149af2dae32d43f0ac25f7f0ffe05387c1a0c846..a2b8cd67f808fef12dfd6019df1839f82affd5ea 100644 (file)
@@ -465,7 +465,8 @@ Client *get_matching_client(xcb_connection_t *conn, const char *window_classtitl
 
                 Client *client;
                 SLIST_FOREACH(client, &(ws->focus_stack), focus_clients) {
-                        LOG("Checking client with class=%s, name=%s\n", client->window_class, client->name);
+                        LOG("Checking client with class=%s / %s, name=%s\n", client->window_class_instance,
+                             client->window_class_class, client->name);
                         if (!client_matches_class_name(client, to_class, to_title, to_title_ucs, to_title_ucs_len))
                                 continue;