diff options
Diffstat (limited to 'source/dialogs/window.c')
-rw-r--r-- | source/dialogs/window.c | 1580 |
1 files changed, 802 insertions, 778 deletions
diff --git a/source/dialogs/window.c b/source/dialogs/window.c index 527fa43a..a132fcc7 100644 --- a/source/dialogs/window.c +++ b/source/dialogs/window.c @@ -26,118 +26,127 @@ */ /** The log domain of this dialog. */ -#define G_LOG_DOMAIN "Dialogs.Window" +#define G_LOG_DOMAIN "Dialogs.Window" #include <config.h> #ifdef WINDOW_MODE -#include <stdlib.h> -#include <stdio.h> +#include <errno.h> #include <stdint.h> -#include <unistd.h> -#include <strings.h> +#include <stdio.h> +#include <stdlib.h> #include <string.h> -#include <errno.h> +#include <strings.h> +#include <unistd.h> #include <xcb/xcb.h> +#include <xcb/xcb_atom.h> #include <xcb/xcb_ewmh.h> #include <xcb/xcb_icccm.h> -#include <xcb/xcb_atom.h> #include <glib.h> #include "xcb-internal.h" #include "xcb.h" +#include "dialogs/window.h" +#include "helper.h" #include "rofi.h" #include "settings.h" -#include "helper.h" #include "widgets/textbox.h" -#include "dialogs/window.h" #include "timings.h" -#include "rofi-icon-fetcher.h" #include "mode-private.h" +#include "rofi-icon-fetcher.h" -#define WINLIST 32 +#define WINLIST 32 -#define CLIENTSTATE 10 -#define CLIENTWINDOWTYPE 10 +#define CLIENTSTATE 10 +#define CLIENTWINDOWTYPE 10 // Fields to match in window mode -typedef struct -{ - char *field_name; - gboolean enabled; +typedef struct { + char *field_name; + gboolean enabled; } WinModeField; -typedef enum -{ - WIN_MATCH_FIELD_TITLE, - WIN_MATCH_FIELD_CLASS, - WIN_MATCH_FIELD_ROLE, - WIN_MATCH_FIELD_NAME, - WIN_MATCH_FIELD_DESKTOP, - WIN_MATCH_NUM_FIELDS, +typedef enum { + WIN_MATCH_FIELD_TITLE, + WIN_MATCH_FIELD_CLASS, + WIN_MATCH_FIELD_ROLE, + WIN_MATCH_FIELD_NAME, + WIN_MATCH_FIELD_DESKTOP, + WIN_MATCH_NUM_FIELDS, } WinModeMatchingFields; static WinModeField matching_window_fields[WIN_MATCH_NUM_FIELDS] = { - { .field_name = "title", .enabled = TRUE, }, - { .field_name = "class", .enabled = TRUE, }, - { .field_name = "role", .enabled = TRUE, }, - { .field_name = "name", .enabled = TRUE, }, - { .field_name = "desktop", .enabled = TRUE, } -}; - -static gboolean window_matching_fields_parsed = FALSE; + { + .field_name = "title", + .enabled = TRUE, + }, + { + .field_name = "class", + .enabled = TRUE, + }, + { + .field_name = "role", + .enabled = TRUE, + }, + { + .field_name = "name", + .enabled = TRUE, + }, + { + .field_name = "desktop", + .enabled = TRUE, + }}; + +static gboolean window_matching_fields_parsed = FALSE; // a manageable window -typedef struct -{ - xcb_window_t window; - xcb_get_window_attributes_reply_t xattr; - char *title; - char *class; - char *name; - char *role; - int states; - xcb_atom_t state[CLIENTSTATE]; - int window_types; - xcb_atom_t window_type[CLIENTWINDOWTYPE]; - int active; - int demands; - long hint_flags; - uint32_t wmdesktop; - char *wmdesktopstr; - unsigned int wmdesktopstr_len; - cairo_surface_t *icon; - gboolean icon_checked; - uint32_t icon_fetch_uid; - gboolean thumbnail_checked; +typedef struct { + xcb_window_t window; + xcb_get_window_attributes_reply_t xattr; + char *title; + char *class; + char *name; + char *role; + int states; + xcb_atom_t state[CLIENTSTATE]; + int window_types; + xcb_atom_t window_type[CLIENTWINDOWTYPE]; + int active; + int demands; + long hint_flags; + uint32_t wmdesktop; + char *wmdesktopstr; + unsigned int wmdesktopstr_len; + cairo_surface_t *icon; + gboolean icon_checked; + uint32_t icon_fetch_uid; + gboolean thumbnail_checked; } client; // window lists -typedef struct -{ - xcb_window_t *array; - client **data; - int len; +typedef struct { + xcb_window_t *array; + client **data; + int len; } winlist; -typedef struct -{ - unsigned int id; - winlist *ids; - // Current window. - unsigned int index; - char *cache; - unsigned int wmdn_len; - unsigned int clf_len; - unsigned int name_len; - unsigned int title_len; - unsigned int role_len; - GRegex *window_regex; +typedef struct { + unsigned int id; + winlist *ids; + // Current window. + unsigned int index; + char *cache; + unsigned int wmdn_len; + unsigned int clf_len; + unsigned int name_len; + unsigned int title_len; + unsigned int role_len; + GRegex *window_regex; } ModeModePrivateData; winlist *cache_client = NULL; @@ -147,13 +156,12 @@ winlist *cache_client = NULL; * * @returns A new window list. */ -static winlist* winlist_new () -{ - winlist *l = g_malloc ( sizeof ( winlist ) ); - l->len = 0; - l->array = g_malloc_n ( WINLIST + 1, sizeof ( xcb_window_t ) ); - l->data = g_malloc_n ( WINLIST + 1, sizeof ( client* ) ); - return l; +static winlist *winlist_new() { + winlist *l = g_malloc(sizeof(winlist)); + l->len = 0; + l->array = g_malloc_n(WINLIST + 1, sizeof(xcb_window_t)); + l->data = g_malloc_n(WINLIST + 1, sizeof(client *)); + return l; } /** @@ -165,46 +173,44 @@ static winlist* winlist_new () * * @returns 0 if failed, 1 is successful. */ -static int winlist_append ( winlist *l, xcb_window_t w, client *d ) -{ - if ( l->len > 0 && !( l->len % WINLIST ) ) { - l->array = g_realloc ( l->array, sizeof ( xcb_window_t ) * ( l->len + WINLIST + 1 ) ); - l->data = g_realloc ( l->data, sizeof ( client* ) * ( l->len + WINLIST + 1 ) ); - } - // Make clang-check happy. - // TODO: make clang-check clear this should never be 0. - if ( l->data == NULL || l->array == NULL ) { - return 0; - } +static int winlist_append(winlist *l, xcb_window_t w, client *d) { + if (l->len > 0 && !(l->len % WINLIST)) { + l->array = + g_realloc(l->array, sizeof(xcb_window_t) * (l->len + WINLIST + 1)); + l->data = g_realloc(l->data, sizeof(client *) * (l->len + WINLIST + 1)); + } + // Make clang-check happy. + // TODO: make clang-check clear this should never be 0. + if (l->data == NULL || l->array == NULL) { + return 0; + } - l->data[l->len] = d; - l->array[l->len++] = w; - return l->len - 1; + l->data[l->len] = d; + l->array[l->len++] = w; + return l->len - 1; } -static void client_free ( client *c ) -{ - if ( c == NULL ) { +static void client_free(client *c) { + if (c == NULL) { return; } - if ( c->icon ) { - cairo_surface_destroy ( c->icon ); + if (c->icon) { + cairo_surface_destroy(c->icon); } - g_free ( c->title ); - g_free ( c->class ); - g_free ( c->name ); - g_free ( c->role ); - g_free ( c->wmdesktopstr ); + g_free(c->title); + g_free(c->class); + g_free(c->name); + g_free(c->role); + g_free(c->wmdesktopstr); } -static void winlist_empty ( winlist *l ) -{ - while ( l->len > 0 ) { - client *c = l->data[--l->len]; - if ( c != NULL ) { - client_free ( c ); - g_free ( c ); - } +static void winlist_empty(winlist *l) { + while (l->len > 0) { + client *c = l->data[--l->len]; + if (c != NULL) { + client_free(c); + g_free(c); } + } } /** @@ -212,14 +218,13 @@ static void winlist_empty ( winlist *l ) * * Free the winlist. */ -static void winlist_free ( winlist *l ) -{ - if ( l != NULL ) { - winlist_empty ( l ); - g_free ( l->array ); - g_free ( l->data ); - g_free ( l ); - } +static void winlist_free(winlist *l) { + if (l != NULL) { + winlist_empty(l); + g_free(l->array); + g_free(l->data); + g_free(l); + } } /** @@ -230,37 +235,34 @@ static void winlist_free ( winlist *l ) * * @returns -1 if failed, index is successful. */ -static int winlist_find ( winlist *l, xcb_window_t w ) -{ -// iterate backwards. Theory is: windows most often accessed will be -// nearer the end. Testing with kcachegrind seems to support this... - int i; - - for ( i = ( l->len - 1 ); i >= 0; i-- ) { - if ( l->array[i] == w ) { - return i; - } +static int winlist_find(winlist *l, xcb_window_t w) { + // iterate backwards. Theory is: windows most often accessed will be + // nearer the end. Testing with kcachegrind seems to support this... + int i; + + for (i = (l->len - 1); i >= 0; i--) { + if (l->array[i] == w) { + return i; } + } - return -1; + return -1; } /** * Create empty X11 cache for windows and windows attributes. */ -static void x11_cache_create ( void ) -{ - if ( cache_client == NULL ) { - cache_client = winlist_new (); - } +static void x11_cache_create(void) { + if (cache_client == NULL) { + cache_client = winlist_new(); + } } /** * Free the cache. */ -static void x11_cache_free ( void ) -{ - winlist_free ( cache_client ); - cache_client = NULL; +static void x11_cache_free(void) { + winlist_free(cache_client); + cache_client = NULL; } /** @@ -272,591 +274,618 @@ static void x11_cache_free ( void ) * * @returns a XWindowAttributes */ -static xcb_get_window_attributes_reply_t * window_get_attributes ( xcb_window_t w ) -{ - xcb_get_window_attributes_cookie_t c = xcb_get_window_attributes ( xcb->connection, w ); - xcb_get_window_attributes_reply_t *r = xcb_get_window_attributes_reply ( xcb->connection, c, NULL ); - if ( r ) { - return r; - } - return NULL; +static xcb_get_window_attributes_reply_t * +window_get_attributes(xcb_window_t w) { + xcb_get_window_attributes_cookie_t c = + xcb_get_window_attributes(xcb->connection, w); + xcb_get_window_attributes_reply_t *r = + xcb_get_window_attributes_reply(xcb->connection, c, NULL); + if (r) { + return r; + } + return NULL; } // _NET_WM_STATE_* -static int client_has_state ( client *c, xcb_atom_t state ) -{ - for ( int i = 0; i < c->states; i++ ) { - if ( c->state[i] == state ) { - return 1; - } +static int client_has_state(client *c, xcb_atom_t state) { + for (int i = 0; i < c->states; i++) { + if (c->state[i] == state) { + return 1; } + } - return 0; + return 0; } -static int client_has_window_type ( client *c, xcb_atom_t type ) -{ - for ( int i = 0; i < c->window_types; i++ ) { - if ( c->window_type[i] == type ) { - return 1; - } +static int client_has_window_type(client *c, xcb_atom_t type) { + for (int i = 0; i < c->window_types; i++) { + if (c->window_type[i] == type) { + return 1; } + } - return 0; + return 0; } -static client* window_client ( ModeModePrivateData *pd, xcb_window_t win ) -{ - if ( win == XCB_WINDOW_NONE ) { - return NULL; - } +static client *window_client(ModeModePrivateData *pd, xcb_window_t win) { + if (win == XCB_WINDOW_NONE) { + return NULL; + } - int idx = winlist_find ( cache_client, win ); + int idx = winlist_find(cache_client, win); - if ( idx >= 0 ) { - return cache_client->data[idx]; - } + if (idx >= 0) { + return cache_client->data[idx]; + } - // if this fails, we're up that creek - xcb_get_window_attributes_reply_t *attr = window_get_attributes ( win ); + // if this fails, we're up that creek + xcb_get_window_attributes_reply_t *attr = window_get_attributes(win); - if ( !attr ) { - return NULL; - } - client *c = g_malloc0 ( sizeof ( client ) ); - c->window = win; - - // copy xattr so we don't have to care when stuff is freed - memmove ( &c->xattr, attr, sizeof ( xcb_get_window_attributes_reply_t ) ); - - xcb_get_property_cookie_t cky = xcb_ewmh_get_wm_state ( &xcb->ewmh, win ); - xcb_ewmh_get_atoms_reply_t states; - if ( xcb_ewmh_get_wm_state_reply ( &xcb->ewmh, cky, &states, NULL ) ) { - c->states = MIN ( CLIENTSTATE, states.atoms_len ); - memcpy ( c->state, states.atoms, MIN ( CLIENTSTATE, states.atoms_len ) * sizeof ( xcb_atom_t ) ); - xcb_ewmh_get_atoms_reply_wipe ( &states ); - } - cky = xcb_ewmh_get_wm_window_type ( &xcb->ewmh, win ); - if ( xcb_ewmh_get_wm_window_type_reply ( &xcb->ewmh, cky, &states, NULL ) ) { - c->window_types = MIN ( CLIENTWINDOWTYPE, states.atoms_len ); - memcpy ( c->window_type, states.atoms, MIN ( CLIENTWINDOWTYPE, states.atoms_len ) * sizeof ( xcb_atom_t ) ); - xcb_ewmh_get_atoms_reply_wipe ( &states ); - } + if (!attr) { + return NULL; + } + client *c = g_malloc0(sizeof(client)); + c->window = win; + + // copy xattr so we don't have to care when stuff is freed + memmove(&c->xattr, attr, sizeof(xcb_get_window_attributes_reply_t)); + + xcb_get_property_cookie_t cky = xcb_ewmh_get_wm_state(&xcb->ewmh, win); + xcb_ewmh_get_atoms_reply_t states; + if (xcb_ewmh_get_wm_state_reply(&xcb->ewmh, cky, &states, NULL)) { + c->states = MIN(CLIENTSTATE, states.atoms_len); + memcpy(c->state, states.atoms, + MIN(CLIENTSTATE, states.atoms_len) * sizeof(xcb_atom_t)); + xcb_ewmh_get_atoms_reply_wipe(&states); + } + cky = xcb_ewmh_get_wm_window_type(&xcb->ewmh, win); + if (xcb_ewmh_get_wm_window_type_reply(&xcb->ewmh, cky, &states, NULL)) { + c->window_types = MIN(CLIENTWINDOWTYPE, states.atoms_len); + memcpy(c->window_type, states.atoms, + MIN(CLIENTWINDOWTYPE, states.atoms_len) * sizeof(xcb_atom_t)); + xcb_ewmh_get_atoms_reply_wipe(&states); + } - char *tmp_title = window_get_text_prop ( c->window, xcb->ewmh._NET_WM_NAME ); - if ( tmp_title == NULL ) { - tmp_title = window_get_text_prop ( c->window, XCB_ATOM_WM_NAME ); - } - c->title = g_markup_escape_text ( tmp_title, -1 ); - pd->title_len = MAX ( c->title ? g_utf8_strlen ( c->title, -1 ) : 0, pd->title_len ); - g_free ( tmp_title ); - - char *tmp_role = window_get_text_prop ( c->window, netatoms[WM_WINDOW_ROLE] ); - c->role = g_markup_escape_text ( tmp_role ? tmp_role : "", -1 ); - pd->role_len = MAX ( c->role ? g_utf8_strlen ( c->role, -1 ) : 0, pd->role_len ); - g_free ( tmp_role ); - - cky = xcb_icccm_get_wm_class ( xcb->connection, c->window ); - xcb_icccm_get_wm_class_reply_t wcr; - if ( xcb_icccm_get_wm_class_reply ( xcb->connection, cky, &wcr, NULL ) ) { - c->class = g_markup_escape_text ( wcr.class_name, -1 ); - c->name = g_markup_escape_text ( wcr.instance_name, -1 ); - pd->name_len = MAX ( c->name ? g_utf8_strlen ( c->name, -1 ) : 0, pd->name_len ); - xcb_icccm_get_wm_class_reply_wipe ( &wcr ); - } + char *tmp_title = window_get_text_prop(c->window, xcb->ewmh._NET_WM_NAME); + if (tmp_title == NULL) { + tmp_title = window_get_text_prop(c->window, XCB_ATOM_WM_NAME); + } + c->title = g_markup_escape_text(tmp_title, -1); + pd->title_len = + MAX(c->title ? g_utf8_strlen(c->title, -1) : 0, pd->title_len); + g_free(tmp_title); + + char *tmp_role = window_get_text_prop(c->window, netatoms[WM_WINDOW_ROLE]); + c->role = g_markup_escape_text(tmp_role ? tmp_role : "", -1); + pd->role_len = MAX(c->role ? g_utf8_strlen(c->role, -1) : 0, pd->role_len); + g_free(tmp_role); + + cky = xcb_icccm_get_wm_class(xcb->connection, c->window); + xcb_icccm_get_wm_class_reply_t wcr; + if (xcb_icccm_get_wm_class_reply(xcb->connection, cky, &wcr, NULL)) { + c->class = g_markup_escape_text(wcr.class_name, -1); + c->name = g_markup_escape_text(wcr.instance_name, -1); + pd->name_len = MAX(c->name ? g_utf8_strlen(c->name, -1) : 0, pd->name_len); + xcb_icccm_get_wm_class_reply_wipe(&wcr); + } - xcb_get_property_cookie_t cc = xcb_icccm_get_wm_hints ( xcb->connection, c->window ); - xcb_icccm_wm_hints_t r; - if ( xcb_icccm_get_wm_hints_reply ( xcb->connection, cc, &r, NULL ) ) { - c->hint_flags = r.flags; - } + xcb_get_property_cookie_t cc = + xcb_icccm_get_wm_hints(xcb->connection, c->window); + xcb_icccm_wm_hints_t r; + if (xcb_icccm_get_wm_hints_reply(xcb->connection, cc, &r, NULL)) { + c->hint_flags = r.flags; + } - winlist_append ( cache_client, c->window, c ); - g_free ( attr ); - return c; + winlist_append(cache_client, c->window, c); + g_free(attr); + return c; } -static int window_match ( const Mode *sw, rofi_int_matcher **tokens, unsigned int index ) -{ - ModeModePrivateData *rmpd = (ModeModePrivateData *) mode_get_private_data ( sw ); - int match = 1; - const winlist *ids = ( winlist * ) rmpd->ids; - // Want to pull directly out of cache, X calls are not thread safe. - int idx = winlist_find ( cache_client, ids->array[index] ); - g_assert ( idx >= 0 ); - client *c = cache_client->data[idx]; - - if ( tokens ) { - for ( int j = 0; match && tokens != NULL && tokens[j] != NULL; j++ ) { - int test = 0; - // Dirty hack. Normally helper_token_match does _all_ the matching, - // Now we want it to match only one item at the time. - // If hack not in place it would not match queries spanning multiple fields. - // e.g. when searching 'title element' and 'class element' - rofi_int_matcher *ftokens[2] = { tokens[j], NULL }; - if ( c->title != NULL && c->title[0] != '\0' && matching_window_fields[WIN_MATCH_FIELD_TITLE].enabled ) { - test = helper_token_match ( ftokens, c->title ); - } - - if ( test == tokens[j]->invert && c->class != NULL && c->class[0] != '\0' && matching_window_fields[WIN_MATCH_FIELD_CLASS].enabled ) { - test = helper_token_match ( ftokens, c->class ); - } - - if ( test == tokens[j]->invert && c->role != NULL && c->role[0] != '\0' && matching_window_fields[WIN_MATCH_FIELD_ROLE].enabled ) { - test = helper_token_match ( ftokens, c->role ); - } - - if ( test == tokens[j]->invert && c->name != NULL && c->name[0] != '\0' && matching_window_fields[WIN_MATCH_FIELD_NAME].enabled ) { - test = helper_token_match ( ftokens, c->name ); - } - if ( test == tokens[j]->invert && c->wmdesktopstr != NULL && c->wmdesktopstr[0] != '\0' && matching_window_fields[WIN_MATCH_FIELD_DESKTOP].enabled ) { - test = helper_token_match ( ftokens, c->wmdesktopstr ); - } - - if ( test == 0 ) { - match = 0; - } - } +static int window_match(const Mode *sw, rofi_int_matcher **tokens, + unsigned int index) { + ModeModePrivateData *rmpd = (ModeModePrivateData *)mode_get_private_data(sw); + int match = 1; + const winlist *ids = (winlist *)rmpd->ids; + // Want to pull directly out of cache, X calls are not thread safe. + int idx = winlist_find(cache_client, ids->array[index]); + g_assert(idx >= 0); + client *c = cache_client->data[idx]; + + if (tokens) { + for (int j = 0; match && tokens != NULL && tokens[j] != NULL; j++) { + int test = 0; + // Dirty hack. Normally helper_token_match does _all_ the matching, + // Now we want it to match only one item at the time. + // If hack not in place it would not match queries spanning multiple + // fields. e.g. when searching 'title element' and 'class element' + rofi_int_matcher *ftokens[2] = {tokens[j], NULL}; + if (c->title != NULL && c->title[0] != '\0' && + matching_window_fields[WIN_MATCH_FIELD_TITLE].enabled) { + test = helper_token_match(ftokens, c->title); + } + + if (test == tokens[j]->invert && c->class != NULL && + c->class[0] != '\0' && + matching_window_fields[WIN_MATCH_FIELD_CLASS].enabled) { + test = helper_token_match(ftokens, c->class); + } + + if (test == tokens[j]->invert && c->role != NULL && c->role[0] != '\0' && + matching_window_fields[WIN_MATCH_FIELD_ROLE].enabled) { + test = helper_token_match(ftokens, c->role); + } + + if (test == tokens[j]->invert && c->name != NULL && c->name[0] != '\0' && + matching_window_fields[WIN_MATCH_FIELD_NAME].enabled) { + test = helper_token_match(ftokens, c->name); + } + if (test == tokens[j]->invert && c->wmdesktopstr != NULL && + c->wmdesktopstr[0] != '\0' && + matching_window_fields[WIN_MATCH_FIELD_DESKTOP].enabled) { + test = helper_token_match(ftokens, c->wmdesktopstr); + } + + if (test == 0) { + match = 0; + } } + } - return match; + return match; } -static void window_mode_parse_fields () -{ - window_matching_fields_parsed = TRUE; - char *savept = NULL; - // Make a copy, as strtok will modify it. - char *switcher_str = g_strdup ( config.window_match_fields ); - const char * const sep = ",#"; - // Split token on ','. This modifies switcher_str. - for ( unsigned int i = 0; i < WIN_MATCH_NUM_FIELDS; i++ ) { - matching_window_fields[i].enabled = FALSE; +static void window_mode_parse_fields() { + window_matching_fields_parsed = TRUE; + char *savept = NULL; + // Make a copy, as strtok will modify it. + char *switcher_str = g_strdup(config.window_match_fields); + const char *const sep = ",#"; + // Split token on ','. This modifies switcher_str. + for (unsigned int i = 0; i < WIN_MATCH_NUM_FIELDS; i++) { + matching_window_fields[i].enabled = FALSE; + } + for (char *token = strtok_r(switcher_str, sep, &savept); token != NULL; + token = strtok_r(NULL, sep, &savept)) { + if (strcmp(token, "all") == 0) { + for (unsigned int i = 0; i < WIN_MATCH_NUM_FIELDS; i++) { + matching_window_fields[i].enabled = TRUE; + } + break; } - for ( char *token = strtok_r ( switcher_str, sep, &savept ); token != NULL; - token = strtok_r ( NULL, sep, &savept ) ) { - if ( strcmp ( token, "all" ) == 0 ) { - for ( unsigned int i = 0; i < WIN_MATCH_NUM_FIELDS; i++ ) { - matching_window_fields[i].enabled = TRUE; - } - break; - } - else { - gboolean matched = FALSE; - for ( unsigned int i = 0; i < WIN_MATCH_NUM_FIELDS; i++ ) { - const char * field_name = matching_window_fields[i].field_name; - if ( strcmp ( token, field_name ) == 0 ) { - matching_window_fields[i].enabled = TRUE; - matched = TRUE; - } - } - if ( !matched ) { - g_warning ( "Invalid window field name :%s", token ); - } - } + gboolean matched = FALSE; + for (unsigned int i = 0; i < WIN_MATCH_NUM_FIELDS; i++) { + const char *field_name = matching_window_fields[i].field_name; + if (strcmp(token, field_name) == 0) { + matching_window_fields[i].enabled = TRUE; + matched = TRUE; + } } - // Free string that was modified by strtok_r - g_free ( switcher_str ); + if (!matched) { + g_warning("Invalid window field name :%s", token); + } + } + // Free string that was modified by strtok_r + g_free(switcher_str); } -static unsigned int window_mode_get_num_entries ( const Mode *sw ) -{ - const ModeModePrivateData *pd = (const ModeModePrivateData *) mode_get_private_data ( sw ); +static unsigned int window_mode_get_num_entries(const Mode *sw) { + const ModeModePrivateData *pd = + (const ModeModePrivateData *)mode_get_private_data(sw); - return pd->ids ? pd->ids->len : 0; + return pd->ids ? pd->ids->len : 0; } /** * Small helper function to find the right entry in the ewmh reply. * Is there a call for this? */ const char *invalid_desktop_name = "n/a"; -static const char * _window_name_list_entry ( const char *str, uint32_t length, int entry ) -{ - uint32_t offset = 0; - int index = 0; - while ( index < entry && offset < length ) { - if ( str[offset] == 0 ) { - index++; - } - offset++; +static const char *_window_name_list_entry(const char *str, uint32_t length, + int entry) { + uint32_t offset = 0; + int index = 0; + while (index < entry && offset < length) { + if (str[offset] == 0) { + index++; } - if ( offset >= length ) { - return invalid_desktop_name; - } - return &str[offset]; + offset++; + } + if (offset >= length) { + return invalid_desktop_name; + } + return &str[offset]; } -static void _window_mode_load_data ( Mode *sw, unsigned int cd ) -{ - ModeModePrivateData *pd = (ModeModePrivateData *) mode_get_private_data ( sw ); - // find window list - xcb_window_t curr_win_id; - int found = 0; - - // Create cache - - x11_cache_create (); - xcb_get_property_cookie_t c = xcb_ewmh_get_active_window ( &( xcb->ewmh ), xcb->screen_nbr ); - if ( !xcb_ewmh_get_active_window_reply ( &xcb->ewmh, c, &curr_win_id, NULL ) ) { - curr_win_id = 0; - } +static void _window_mode_load_data(Mode *sw, unsigned int cd) { + ModeModePrivateData *pd = (ModeModePrivateData *)mode_get_private_data(sw); + // find window list + xcb_window_t curr_win_id; + int found = 0; + + // Create cache + + x11_cache_create(); + xcb_get_property_cookie_t c = + xcb_ewmh_get_active_window(&(xcb->ewmh), xcb->screen_nbr); + if (!xcb_ewmh_get_active_window_reply(&xcb->ewmh, c, &curr_win_id, NULL)) { + curr_win_id = 0; + } - // Get the current desktop. - unsigned int current_desktop = 0; - c = xcb_ewmh_get_current_desktop ( &xcb->ewmh, xcb->screen_nbr ); - if ( !xcb_ewmh_get_current_desktop_reply ( &xcb->ewmh, c, ¤t_desktop, NULL ) ) { - current_desktop = 0; + // Get the current desktop. + unsigned int current_desktop = 0; + c = xcb_ewmh_get_current_desktop(&xcb->ewmh, xcb->screen_nbr); + if (!xcb_ewmh_get_current_desktop_reply(&xcb->ewmh, c, ¤t_desktop, + NULL)) { + current_desktop = 0; + } + + g_debug("Get list from: %d", xcb->screen_nbr); + c = xcb_ewmh_get_client_list_stacking(&xcb->ewmh, xcb->screen_nbr); + xcb_ewmh_get_windows_reply_t clients = { + 0, + }; + if (xcb_ewmh_get_client_list_stacking_reply(&xcb->ewmh, c, &clients, NULL)) { + found = 1; + } else { + c = xcb_ewmh_get_client_list(&xcb->ewmh, xcb->screen_nbr); + if (xcb_ewmh_get_client_list_reply(&xcb->ewmh, c, &clients, NULL)) { + found = 1; } + } + if (!found) { + return; + } - g_debug ( "Get list from: %d", xcb->screen_nbr ); - c = xcb_ewmh_get_client_list_stacking ( &xcb->ewmh, xcb->screen_nbr ); - xcb_ewmh_get_windows_reply_t clients = { 0, }; - if ( xcb_ewmh_get_client_list_stacking_reply ( &xcb->ewmh, c, &clients, NULL ) ) { - found = 1; + if (clients.windows_len > 0) { + int i; + // windows we actually display. May be slightly different to + // _NET_CLIENT_LIST_STACKING if we happen to have a window destroyed while + // we're working... + pd->ids = winlist_new(); + + xcb_get_property_cookie_t c = + xcb_ewmh_get_desktop_names(&xcb->ewmh, xcb->screen_nbr); + xcb_ewmh_get_utf8_strings_reply_t names; + int has_names = FALSE; + if (xcb_ewmh_get_desktop_names_reply(&xcb->ewmh, c, &names, NULL)) { + has_names = TRUE; } - else { - c = xcb_ewmh_get_client_list ( &xcb->ewmh, xcb->screen_nbr ); - if ( xcb_ewmh_get_client_list_reply ( &xcb->ewmh, c, &clients, NULL ) ) { - found = 1; + // calc widths of fields + for (i = clients.windows_len - 1; i > -1; i--) { + client *c = window_client(pd, clients.windows[i]); + if ((c != NULL) && !c->xattr.override_redirect && + !client_has_window_type(c, xcb->ewmh._NET_WM_WINDOW_TYPE_DOCK) && + !client_has_window_type(c, xcb->ewmh._NET_WM_WINDOW_TYPE_DESKTOP) && + !client_has_state(c, xcb->ewmh._NET_WM_STATE_SKIP_PAGER) && + !client_has_state(c, xcb->ewmh._NET_WM_STATE_SKIP_TASKBAR)) { + pd->clf_len = + MAX(pd->clf_len, + (c->class != NULL) ? (g_utf8_strlen(c->class, -1)) : 0); + + if (client_has_state(c, xcb->ewmh._NET_WM_STATE_DEMANDS_ATTENTION)) { + c->demands = TRUE; + } + if ((c->hint_flags & XCB_ICCCM_WM_HINT_X_URGENCY) != 0) { + c->demands = TRUE; } - } - if ( !found ) { - return; - } - if ( clients.windows_len > 0 ) { - int i; - // windows we actually display. May be slightly different to _NET_CLIENT_LIST_STACKING - // if we happen to have a window destroyed while we're working... - pd->ids = winlist_new (); - - xcb_get_property_cookie_t c = xcb_ewmh_get_desktop_names ( &xcb->ewmh, xcb->screen_nbr ); - xcb_ewmh_get_utf8_strings_reply_t names; - int has_names = FALSE; - if ( xcb_ewmh_get_desktop_names_reply ( &xcb->ewmh, c, &names, NULL ) ) { - has_names = TRUE; + if (c->window == curr_win_id) { + c->active = TRUE; + } + // find client's desktop. + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *r; + + c->wmdesktop = 0xFFFFFFFF; + cookie = xcb_get_property(xcb->connection, 0, c->window, + xcb->ewmh._NET_WM_DESKTOP, XCB_ATOM_CARDINAL, + 0, 1); + r = xcb_get_property_reply(xcb->connection, cookie, NULL); + if (r) { + if (r->type == XCB_ATOM_CARDINAL) { + c->wmdesktop = *((uint32_t *)xcb_get_property_value(r)); + } + free(r); } - // calc widths of fields - for ( i = clients.windows_len - 1; i > -1; i-- ) { - client *c = window_client ( pd, clients.windows[i] ); - if ( ( c != NULL ) - && !c->xattr.override_redirect - && !client_has_window_type ( c, xcb->ewmh._NET_WM_WINDOW_TYPE_DOCK ) - && !client_has_window_type ( c, xcb->ewmh._NET_WM_WINDOW_TYPE_DESKTOP ) - && !client_has_state ( c, xcb->ewmh._NET_WM_STATE_SKIP_PAGER ) - && !client_has_state ( c, xcb->ewmh._NET_WM_STATE_SKIP_TASKBAR ) ) { - pd->clf_len = MAX ( pd->clf_len, ( c->class != NULL ) ? ( g_utf8_strlen ( c->class, -1 ) ) : 0 ); - - if ( client_has_state ( c, xcb->ewmh._NET_WM_STATE_DEMANDS_ATTENTION ) ) { - c->demands = TRUE; - } - if ( ( c->hint_flags & XCB_ICCCM_WM_HINT_X_URGENCY ) != 0 ) { - c->demands = TRUE; - } - - if ( c->window == curr_win_id ) { - c->active = TRUE; - } - // find client's desktop. - xcb_get_property_cookie_t cookie; - xcb_get_property_reply_t *r; - - c->wmdesktop = 0xFFFFFFFF; - cookie = - xcb_get_property ( xcb->connection, 0, c->window, xcb->ewmh._NET_WM_DESKTOP, XCB_ATOM_CARDINAL, 0, - 1 ); - r = xcb_get_property_reply ( xcb->connection, cookie, NULL ); - if ( r ) { - if ( r->type == XCB_ATOM_CARDINAL ) { - c->wmdesktop = *( (uint32_t *) xcb_get_property_value ( r ) ); - } - free ( r ); - } - if ( c->wmdesktop != 0xFFFFFFFF ) { - if ( has_names ) { - if ( ( current_window_manager & WM_PANGO_WORKSPACE_NAMES ) == WM_PANGO_WORKSPACE_NAMES ) { - char *output = NULL; - if ( pango_parse_markup ( _window_name_list_entry ( names.strings, names.strings_len, - c->wmdesktop ), -1, 0, NULL, &output, NULL, NULL ) ) { - c->wmdesktopstr = g_strdup ( _window_name_list_entry ( names.strings, names.strings_len, c->wmdesktop ) ); - c->wmdesktopstr_len = g_utf8_strlen ( output, -1 ); - pd->wmdn_len = MAX ( pd->wmdn_len, c->wmdesktopstr_len ); - g_free ( output ); - } - else { - c->wmdesktopstr = g_strdup ( "Invalid name" ); - pd->wmdn_len = MAX ( pd->wmdn_len, g_utf8_strlen ( c->wmdesktopstr, -1 ) ); - } - } - else { - c->wmdesktopstr = g_markup_escape_text ( _window_name_list_entry ( names.strings, names.strings_len, c->wmdesktop ), -1 ); - pd->wmdn_len = MAX ( pd->wmdn_len, g_utf8_strlen ( c->wmdesktopstr, -1 ) ); - } - } - else { - c->wmdesktopstr = g_strdup_printf ( "%u", (uint32_t) c->wmdesktop ); - pd->wmdn_len = MAX ( pd->wmdn_len, g_utf8_strlen ( c->wmdesktopstr, -1 ) ); - } - } - else { - c->wmdesktopstr = g_strdup ( "" ); - pd->wmdn_len = MAX ( pd->wmdn_len, g_utf8_strlen ( c->wmdesktopstr, -1 ) ); - } - if ( cd && c->wmdesktop != current_desktop ) { - continue; - } - winlist_append ( pd->ids, c->window, NULL ); + if (c->wmdesktop != 0xFFFFFFF |