commit c21d6eaf97dbcc03bbf6bd90096349dba8e1b071 from: Omar Polo date: Thu Oct 08 08:59:12 2020 UTC grabkey only on the targeted windows now we grabkey() only on the window that matches what the user requested. That is, given match class 'Firefox' on "C-n" do "" we only bind C-n on windows that match the class Firefox, and not on the root window as we did before. In order to do this, we traverse the tree during startup and grabkey on matching windows, than we subscribe also to SubstructureNotify so that when a window gets mapped we receive an event. There are still some downsides to this. Firefox uses also '/usr/local/lib/firefox/firefox' as class name on my machine, and sometimes it seems like we don’t grab the key at the first try (maybe Firefox changes the class after the window gets mapped?) commit - c85d4bf338efd6371825dfe51680c62ee65be408 commit + c21d6eaf97dbcc03bbf6bd90096349dba8e1b071 blob - 1bfeb83ff93c564131f3b33e7cced7fa172bd3c6 blob + 03c56368be172e377ef948d27abdff49bfa924d4 --- star-platinum.c +++ star-platinum.c @@ -119,8 +119,6 @@ int main(int argc, char **argv) { int status = 0, dump_config = 0, conftest = 0, ch; - struct group *g; - struct rule *r; XEvent e; Window root; @@ -182,12 +180,9 @@ main(int argc, char **argv) root = DefaultRootWindow(d); - /* grab all the keys */ - for (g = config; g != NULL; g = g->next) - for (r = g->rules; r != NULL; r = r->next) - grabkey(r->key, root); + grabkey_matching_windows(); - XSelectInput(d, root, KeyPressMask); + XSelectInput(d, root, SubstructureNotifyMask | KeyPressMask); XFlush(d); pledge("stdio proc exec", NULL); @@ -200,6 +195,20 @@ main(int argc, char **argv) process_event(config, (XKeyEvent*)&e); break; + case MapNotify: { + XMapEvent *ev = (XMapEvent*)&e; + grab_matching_keys(ev->window); + break; + } + + case UnmapNotify: + case ConfigureNotify: + case CreateNotify: + case DestroyNotify: + case ClientMessage: + /* ignored */ + break; + default: printf("Unknown event %d\n", e.type); break; @@ -233,7 +242,42 @@ grabkey(struct key k, Window w) XGrabKey(d, XKeysymToKeycode(d, k.key), k.modifier | ignored_modifiers[i], w, False, GrabModeAsync, GrabModeAsync); + } +} + +void +grab_matching_keys(Window w) +{ + XClassHint ch; + struct group *g; + struct rule *r; + + if (!XGetClassHint(d, w, &ch)) + return; + + for (g = config; g != NULL; g = g->next) { + if (!group_match(g, w)) + continue; + + for (r = g->rules; r != NULL; r = r->next) + grabkey(r->key, w); } +} + +int +grabkey_matching_windows() +{ + Window root, parent, *children; + unsigned int len, i; + + root = DefaultRootWindow(d); + if (!XQueryTree(d, root, &root, &parent, &children, &len)) + return 0; + + for (i = 0; i < len; ++i) + grab_matching_keys(children[i]); + + return 1; } KeySym blob - 96277b5de8bfaf10a929c1180880cf9968434770 blob + b92ba21cc0b1deba1173fa6d36119ab63c25a0af --- star-platinum.h +++ star-platinum.h @@ -91,6 +91,8 @@ int group_match(struct group*, Window); /* xlib-related */ int error_handler(Display*, XErrorEvent*); void grabkey(struct key, Window); +void grab_matching_keys(Window); +int grabkey_matching_windows(); KeySym keycode_to_keysym(unsigned int); Window focused_window(); void send_fake(Window, struct key, XKeyEvent*);