From 0b6b8e8380b8026ba834436f4ae4de47ff07feda Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Fri, 12 Feb 2010 12:12:25 +0100 Subject: [PATCH] Bugfix: Use both parts of WM_CLASS (it contains instance and class) (Thanks fallen) 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 | 6 ++++-- src/client.c | 5 ++++- src/handlers.c | 34 +++++++++++++++------------------- src/util.c | 3 ++- 4 files changed, 25 insertions(+), 23 deletions(-) diff --git a/include/data.h b/include/data.h index 8c846537..47343d19 100644 --- a/include/data.h +++ b/include/data.h @@ -382,8 +382,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; diff --git a/src/client.c b/src/client.c index c3113391..3b747f54 100644 --- a/src/client.c +++ b/src/client.c @@ -124,7 +124,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 */ diff --git a/src/handlers.c b/src/handlers.c index 6e54b04b..0f550835 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -539,7 +539,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); @@ -696,28 +697,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"); - DLOG("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) { - DLOG("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; } /* diff --git a/src/util.c b/src/util.c index ba4bd6dd..1cdc758a 100644 --- a/src/util.c +++ b/src/util.c @@ -448,7 +448,8 @@ Client *get_matching_client(xcb_connection_t *conn, const char *window_classtitl Client *client; SLIST_FOREACH(client, &(ws->focus_stack), focus_clients) { - DLOG("Checking client with class=%s, name=%s\n", client->window_class, client->name); + DLOG("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; -- 2.39.5