Blame


1 e573cb09 2020-09-27 op /*
2 e573cb09 2020-09-27 op * Copyright (c) 2020 Omar Polo <op@omarpolo.com>
3 e573cb09 2020-09-27 op *
4 e573cb09 2020-09-27 op * Permission to use, copy, modify, and distribute this software for any
5 e573cb09 2020-09-27 op * purpose with or without fee is hereby granted, provided that the above
6 e573cb09 2020-09-27 op * copyright notice and this permission notice appear in all copies.
7 e573cb09 2020-09-27 op *
8 e573cb09 2020-09-27 op * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 e573cb09 2020-09-27 op * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 e573cb09 2020-09-27 op * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 e573cb09 2020-09-27 op * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 e573cb09 2020-09-27 op * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 e573cb09 2020-09-27 op * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 e573cb09 2020-09-27 op * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 e573cb09 2020-09-27 op */
16 e573cb09 2020-09-27 op
17 e573cb09 2020-09-27 op #include "star-platinum.h"
18 e573cb09 2020-09-27 op
19 e573cb09 2020-09-27 op #include <err.h>
20 e573cb09 2020-09-27 op #include <stdio.h>
21 e573cb09 2020-09-27 op #include <string.h>
22 e573cb09 2020-09-27 op #include <unistd.h>
23 e573cb09 2020-09-27 op
24 e573cb09 2020-09-27 op #include <X11/XKBlib.h>
25 e573cb09 2020-09-27 op #include <X11/Xutil.h>
26 e573cb09 2020-09-27 op
27 e573cb09 2020-09-27 op #ifndef __OpenBSD__
28 e573cb09 2020-09-27 op # define pledge(a, b) 0
29 e573cb09 2020-09-27 op #endif
30 e573cb09 2020-09-27 op
31 e573cb09 2020-09-27 op extern FILE *yyin;
32 e573cb09 2020-09-27 op char *fname;
33 e573cb09 2020-09-27 op
34 e573cb09 2020-09-27 op extern int yylineno;
35 e573cb09 2020-09-27 op int yyparse(void);
36 e573cb09 2020-09-27 op
37 e573cb09 2020-09-27 op struct group *config;
38 e573cb09 2020-09-27 op int goterror = 0;
39 e573cb09 2020-09-27 op
40 e573cb09 2020-09-27 op Display *d;
41 e573cb09 2020-09-27 op
42 e573cb09 2020-09-27 op int ignored_modifiers[] = {
43 e573cb09 2020-09-27 op 0, /* no modifiers */
44 e573cb09 2020-09-27 op LockMask, /* caps lock */
45 e573cb09 2020-09-27 op Mod2Mask, /* num lock */
46 e573cb09 2020-09-27 op Mod3Mask, /* scroll lock */
47 e573cb09 2020-09-27 op Mod5Mask, /* ? */
48 e573cb09 2020-09-27 op };
49 e573cb09 2020-09-27 op
50 e573cb09 2020-09-27 op #define IGNORE_MODIFIERS (LockMask | Mod2Mask | Mod3Mask | Mod5Mask)
51 e573cb09 2020-09-27 op
52 e573cb09 2020-09-27 op void
53 e573cb09 2020-09-27 op yyerror(const char *e)
54 e573cb09 2020-09-27 op {
55 e573cb09 2020-09-27 op goterror = 1;
56 e573cb09 2020-09-27 op fprintf(stderr, "%s:%d %s\n", fname, yylineno, e);
57 e573cb09 2020-09-27 op }
58 e573cb09 2020-09-27 op
59 e573cb09 2020-09-27 op char *
60 e573cb09 2020-09-27 op find_config()
61 e573cb09 2020-09-27 op {
62 e573cb09 2020-09-27 op char *home, *xdg, *t;
63 e573cb09 2020-09-27 op int free_xdg = 0;
64 e573cb09 2020-09-27 op
65 e573cb09 2020-09-27 op home = getenv("HOME");
66 e573cb09 2020-09-27 op xdg = getenv("XDG_CONFIG_HOME");
67 e573cb09 2020-09-27 op
68 e573cb09 2020-09-27 op if (home == NULL && xdg == NULL)
69 e573cb09 2020-09-27 op return NULL;
70 e573cb09 2020-09-27 op
71 e573cb09 2020-09-27 op /* file in home directory >>>>>> XDG shit */
72 e573cb09 2020-09-27 op if (home != NULL) {
73 e573cb09 2020-09-27 op if (asprintf(&t, "%s/.star-platinum.conf", home) == -1)
74 e573cb09 2020-09-27 op return NULL;
75 e573cb09 2020-09-27 op if (access(t, R_OK) == 0)
76 e573cb09 2020-09-27 op return t;
77 e573cb09 2020-09-27 op
78 e573cb09 2020-09-27 op free(t);
79 e573cb09 2020-09-27 op /* continue to search */
80 e573cb09 2020-09-27 op }
81 e573cb09 2020-09-27 op
82 e573cb09 2020-09-27 op /* sanitize XDG_CONFIG_HOME */
83 e573cb09 2020-09-27 op if (xdg == NULL) {
84 e573cb09 2020-09-27 op free_xdg = 1;
85 e573cb09 2020-09-27 op if (asprintf(&xdg, "%s/.config", home) == -1)
86 e573cb09 2020-09-27 op return NULL;
87 e573cb09 2020-09-27 op }
88 e573cb09 2020-09-27 op
89 e573cb09 2020-09-27 op if (asprintf(&t, "%s/star-platinum.conf", xdg) == -1)
90 e573cb09 2020-09-27 op goto err;
91 e573cb09 2020-09-27 op
92 e573cb09 2020-09-27 op if (access(t, R_OK) == 0)
93 e573cb09 2020-09-27 op return t;
94 e573cb09 2020-09-27 op free(t);
95 e573cb09 2020-09-27 op
96 e573cb09 2020-09-27 op err:
97 e573cb09 2020-09-27 op if (free_xdg)
98 e573cb09 2020-09-27 op free(xdg);
99 e573cb09 2020-09-27 op
100 e573cb09 2020-09-27 op return NULL;
101 e573cb09 2020-09-27 op }
102 e573cb09 2020-09-27 op
103 e573cb09 2020-09-27 op int
104 e573cb09 2020-09-27 op main(int argc, char **argv)
105 e573cb09 2020-09-27 op {
106 e573cb09 2020-09-27 op int status = 0, dump_config = 0, conftest = 0, ch;
107 e573cb09 2020-09-27 op struct group *g;
108 e573cb09 2020-09-27 op struct rule *r;
109 e573cb09 2020-09-27 op XEvent e;
110 e573cb09 2020-09-27 op Window root;
111 e573cb09 2020-09-27 op
112 e573cb09 2020-09-27 op fname = NULL;
113 e573cb09 2020-09-27 op while ((ch = getopt(argc, argv, "c:dn")) != -1) {
114 e573cb09 2020-09-27 op switch (ch) {
115 e573cb09 2020-09-27 op case 'c':
116 e573cb09 2020-09-27 op free(fname);
117 e573cb09 2020-09-27 op if ((fname = strdup(optarg)) == NULL)
118 e573cb09 2020-09-27 op err(1, "strdup");
119 e573cb09 2020-09-27 op break;
120 e573cb09 2020-09-27 op
121 e573cb09 2020-09-27 op case 'd':
122 e573cb09 2020-09-27 op dump_config = 1;
123 e573cb09 2020-09-27 op break;
124 e573cb09 2020-09-27 op
125 e573cb09 2020-09-27 op case 'n':
126 e573cb09 2020-09-27 op conftest = 1;
127 e573cb09 2020-09-27 op break;
128 e573cb09 2020-09-27 op
129 e573cb09 2020-09-27 op default:
130 e573cb09 2020-09-27 op fprintf(stderr, "USAGE: %s [-dn] [-c conf]\n", *argv);
131 e573cb09 2020-09-27 op return 1;
132 e573cb09 2020-09-27 op }
133 e573cb09 2020-09-27 op }
134 e573cb09 2020-09-27 op
135 e573cb09 2020-09-27 op if (fname == NULL) {
136 e573cb09 2020-09-27 op if ((fname = find_config()) == NULL)
137 e573cb09 2020-09-27 op errx(1, "can't find a configuration file");
138 e573cb09 2020-09-27 op }
139 e573cb09 2020-09-27 op
140 e573cb09 2020-09-27 op if ((yyin = fopen(fname, "r")) == NULL)
141 e573cb09 2020-09-27 op err(1, "cannot open %s", fname);
142 e573cb09 2020-09-27 op yyparse();
143 e573cb09 2020-09-27 op fclose(yyin);
144 e573cb09 2020-09-27 op
145 e573cb09 2020-09-27 op free(fname);
146 e573cb09 2020-09-27 op fname = NULL;
147 e573cb09 2020-09-27 op
148 e573cb09 2020-09-27 op if (goterror)
149 e573cb09 2020-09-27 op return 1;
150 e573cb09 2020-09-27 op
151 e573cb09 2020-09-27 op if (dump_config)
152 e573cb09 2020-09-27 op printgroup(config);
153 e573cb09 2020-09-27 op
154 e573cb09 2020-09-27 op if (conftest) {
155 e573cb09 2020-09-27 op recfree_group(config);
156 e573cb09 2020-09-27 op return 0;
157 e573cb09 2020-09-27 op }
158 e573cb09 2020-09-27 op
159 e573cb09 2020-09-27 op if ((d = XOpenDisplay(NULL)) == NULL) {
160 e573cb09 2020-09-27 op recfree_group(config);
161 e573cb09 2020-09-27 op return 1;
162 e573cb09 2020-09-27 op }
163 e573cb09 2020-09-27 op
164 fe0dcf4e 2020-09-29 op XSetErrorHandler(&error_handler);
165 fe0dcf4e 2020-09-29 op
166 e573cb09 2020-09-27 op root = DefaultRootWindow(d);
167 e573cb09 2020-09-27 op
168 e573cb09 2020-09-27 op /* grab all the keys */
169 e573cb09 2020-09-27 op for (g = config; g != NULL; g = g->next)
170 e573cb09 2020-09-27 op for (r = g->rules; r != NULL; r = r->next)
171 e573cb09 2020-09-27 op grabkey(r->key);
172 e573cb09 2020-09-27 op
173 e573cb09 2020-09-27 op XSelectInput(d, root, KeyPressMask);
174 e573cb09 2020-09-27 op XFlush(d);
175 e573cb09 2020-09-27 op
176 e573cb09 2020-09-27 op pledge("stdio", "");
177 e573cb09 2020-09-27 op
178 e573cb09 2020-09-27 op while (1) {
179 e573cb09 2020-09-27 op XNextEvent(d, &e);
180 e573cb09 2020-09-27 op switch (e.type) {
181 e573cb09 2020-09-27 op case KeyRelease:
182 e573cb09 2020-09-27 op case KeyPress:
183 e573cb09 2020-09-27 op process_event(config, (XKeyEvent*)&e);
184 e573cb09 2020-09-27 op break;
185 e573cb09 2020-09-27 op
186 e573cb09 2020-09-27 op default:
187 e573cb09 2020-09-27 op printf("Unknown event %d\n", e.type);
188 e573cb09 2020-09-27 op break;
189 e573cb09 2020-09-27 op }
190 e573cb09 2020-09-27 op }
191 e573cb09 2020-09-27 op
192 e573cb09 2020-09-27 op XCloseDisplay(d);
193 e573cb09 2020-09-27 op recfree_group(config);
194 e573cb09 2020-09-27 op return status;
195 e573cb09 2020-09-27 op }
196 e573cb09 2020-09-27 op
197 e573cb09 2020-09-27 op
198 e573cb09 2020-09-27 op /* xlib */
199 e573cb09 2020-09-27 op
200 fe0dcf4e 2020-09-29 op int
201 fe0dcf4e 2020-09-29 op error_handler(Display *d, XErrorEvent *e)
202 fe0dcf4e 2020-09-29 op {
203 fe0dcf4e 2020-09-29 op fprintf(stderr, "Xlib error %d\n", e->type);
204 fe0dcf4e 2020-09-29 op return 1;
205 fe0dcf4e 2020-09-29 op }
206 fe0dcf4e 2020-09-29 op
207 e573cb09 2020-09-27 op /* TODO: it should grab ALL POSSIBLE COMBINATIONS of `ignored_modifiers`! */
208 e573cb09 2020-09-27 op void
209 e573cb09 2020-09-27 op grabkey(struct key k)
210 e573cb09 2020-09-27 op {
211 e573cb09 2020-09-27 op static size_t len = sizeof(ignored_modifiers)/sizeof(int);
212 e573cb09 2020-09-27 op size_t i;
213 e573cb09 2020-09-27 op Window root;
214 e573cb09 2020-09-27 op
215 e573cb09 2020-09-27 op root = DefaultRootWindow(d);
216 e573cb09 2020-09-27 op
217 e573cb09 2020-09-27 op /* printf("Grabbing "); printkey(k); printf("\n"); */
218 e573cb09 2020-09-27 op for (i = 0; i < len; ++i) {
219 e573cb09 2020-09-27 op XGrabKey(d, XKeysymToKeycode(d, k.key),
220 e573cb09 2020-09-27 op k.modifier | ignored_modifiers[i],
221 e573cb09 2020-09-27 op root, False, GrabModeAsync, GrabModeAsync);
222 e573cb09 2020-09-27 op }
223 e573cb09 2020-09-27 op }
224 e573cb09 2020-09-27 op
225 e573cb09 2020-09-27 op KeySym
226 e573cb09 2020-09-27 op keycode_to_keysym(unsigned int kc)
227 e573cb09 2020-09-27 op {
228 e573cb09 2020-09-27 op /* group 0 (?). shift level is 0 because we don't want it*/
229 e573cb09 2020-09-27 op return XkbKeycodeToKeysym(d, kc, 0, 0);
230 e573cb09 2020-09-27 op }
231 e573cb09 2020-09-27 op
232 e573cb09 2020-09-27 op Window
233 e573cb09 2020-09-27 op focused_window()
234 e573cb09 2020-09-27 op {
235 e573cb09 2020-09-27 op Window w;
236 e573cb09 2020-09-27 op int revert_to;
237 e573cb09 2020-09-27 op
238 e573cb09 2020-09-27 op /* one can use (at least) three way to obtain the current
239 e573cb09 2020-09-27 op * focused window using xlib:
240 e573cb09 2020-09-27 op *
241 e573cb09 2020-09-27 op * - XQueryTree : you traverse tre tree until you find the
242 e573cb09 2020-09-27 op * window
243 e573cb09 2020-09-27 op *
244 e573cb09 2020-09-27 op * - looking at _NET_ACTIVE_WINDOW in the root window, but
245 e573cb09 2020-09-27 op * depedns on the window manager to set it
246 e573cb09 2020-09-27 op *
247 e573cb09 2020-09-27 op * - using XGetInputFocus
248 e573cb09 2020-09-27 op *
249 e573cb09 2020-09-27 op * I don't know the pro/cons of these, but XGetInputFocus
250 e573cb09 2020-09-27 op * seems the easiest.
251 e573cb09 2020-09-27 op */
252 e573cb09 2020-09-27 op XGetInputFocus(d, &w, &revert_to);
253 e573cb09 2020-09-27 op return w;
254 e573cb09 2020-09-27 op }
255 e573cb09 2020-09-27 op
256 e573cb09 2020-09-27 op void
257 e573cb09 2020-09-27 op send_fake(Window w, struct key k, int pressed)
258 e573cb09 2020-09-27 op {
259 e573cb09 2020-09-27 op XKeyEvent e;
260 e573cb09 2020-09-27 op
261 e573cb09 2020-09-27 op e.type = pressed ? KeyPress : KeyRelease;
262 e573cb09 2020-09-27 op
263 e573cb09 2020-09-27 op e.display = d;
264 e573cb09 2020-09-27 op e.window = w;
265 e573cb09 2020-09-27 op e.root = DefaultRootWindow(d);
266 e573cb09 2020-09-27 op e.subwindow = None;
267 e573cb09 2020-09-27 op e.time = CurrentTime;
268 e573cb09 2020-09-27 op
269 e573cb09 2020-09-27 op /* TODO: fix these */
270 e573cb09 2020-09-27 op e.x = 1;
271 e573cb09 2020-09-27 op e.y = 1;
272 e573cb09 2020-09-27 op e.x_root = 1;
273 e573cb09 2020-09-27 op e.y_root = 1;
274 e573cb09 2020-09-27 op
275 e573cb09 2020-09-27 op e.same_screen = True;
276 e573cb09 2020-09-27 op e.keycode = XKeysymToKeycode(d, k.key);
277 e573cb09 2020-09-27 op e.state = k.modifier;
278 e573cb09 2020-09-27 op
279 e573cb09 2020-09-27 op XSendEvent(d, w, True, KeyPressMask, (XEvent*)&e);
280 e573cb09 2020-09-27 op XFlush(d);
281 e573cb09 2020-09-27 op }
282 e573cb09 2020-09-27 op
283 e573cb09 2020-09-27 op int
284 e573cb09 2020-09-27 op window_match_class(Window w, const char *class)
285 e573cb09 2020-09-27 op {
286 e573cb09 2020-09-27 op XClassHint ch;
287 e573cb09 2020-09-27 op int matched;
288 e573cb09 2020-09-27 op
289 e573cb09 2020-09-27 op if (!XGetClassHint(d, w, &ch)) {
290 e573cb09 2020-09-27 op fprintf(stderr, "XGetClassHint failed\n");
291 e573cb09 2020-09-27 op return 0;
292 e573cb09 2020-09-27 op }
293 e573cb09 2020-09-27 op
294 e573cb09 2020-09-27 op matched = !strcmp(ch.res_class, class);
295 e573cb09 2020-09-27 op
296 e573cb09 2020-09-27 op XFree(ch.res_name);
297 e573cb09 2020-09-27 op XFree(ch.res_class);
298 e573cb09 2020-09-27 op
299 e573cb09 2020-09-27 op return matched;
300 e573cb09 2020-09-27 op }
301 e573cb09 2020-09-27 op
302 e573cb09 2020-09-27 op
303 e573cb09 2020-09-27 op /* action */
304 e573cb09 2020-09-27 op
305 e573cb09 2020-09-27 op void
306 e573cb09 2020-09-27 op do_action(struct action a, Window focused, int pressed)
307 e573cb09 2020-09-27 op {
308 e573cb09 2020-09-27 op switch (a.type) {
309 e573cb09 2020-09-27 op case AFAKE:
310 e573cb09 2020-09-27 op send_fake(focused, a.send_key, pressed);
311 e573cb09 2020-09-27 op break;
312 e573cb09 2020-09-27 op
313 e573cb09 2020-09-27 op case ASPECIAL:
314 e573cb09 2020-09-27 op switch (a.special) {
315 e573cb09 2020-09-27 op case ATOGGLE:
316 e573cb09 2020-09-27 op case AACTIVATE:
317 e573cb09 2020-09-27 op case ADEACTIVATE:
318 e573cb09 2020-09-27 op printf("TODO\n");
319 e573cb09 2020-09-27 op break;
320 e573cb09 2020-09-27 op
321 e573cb09 2020-09-27 op case AIGNORE:
322 e573cb09 2020-09-27 op break;
323 e573cb09 2020-09-27 op
324 e573cb09 2020-09-27 op default:
325 e573cb09 2020-09-27 op /* unreachable */
326 e573cb09 2020-09-27 op abort();
327 e573cb09 2020-09-27 op }
328 e573cb09 2020-09-27 op break;
329 e573cb09 2020-09-27 op
330 e573cb09 2020-09-27 op default:
331 e573cb09 2020-09-27 op /* unreachable */
332 e573cb09 2020-09-27 op abort();
333 e573cb09 2020-09-27 op }
334 e573cb09 2020-09-27 op }
335 e573cb09 2020-09-27 op
336 e573cb09 2020-09-27 op
337 e573cb09 2020-09-27 op /* match */
338 e573cb09 2020-09-27 op
339 e573cb09 2020-09-27 op struct match *
340 e573cb09 2020-09-27 op new_match(int prop, char *s)
341 e573cb09 2020-09-27 op {
342 e573cb09 2020-09-27 op struct match *m;
343 e573cb09 2020-09-27 op
344 e573cb09 2020-09-27 op if ((m = calloc(1, sizeof(*m))) == NULL)
345 e573cb09 2020-09-27 op err(1, "calloc");
346 e573cb09 2020-09-27 op m->prop = prop;
347 e573cb09 2020-09-27 op m->str = s;
348 e573cb09 2020-09-27 op return m;
349 e573cb09 2020-09-27 op }
350 e573cb09 2020-09-27 op
351 e573cb09 2020-09-27 op void
352 e573cb09 2020-09-27 op recfree_match(struct match *m)
353 e573cb09 2020-09-27 op {
354 e573cb09 2020-09-27 op struct match *mt;
355 e573cb09 2020-09-27 op
356 e573cb09 2020-09-27 op if (m == NULL)
357 e573cb09 2020-09-27 op return;
358 e573cb09 2020-09-27 op
359 e573cb09 2020-09-27 op mt = m->next;
360 e573cb09 2020-09-27 op free(m->str);
361 e573cb09 2020-09-27 op free(m);
362 e573cb09 2020-09-27 op recfree_match(mt);
363 e573cb09 2020-09-27 op }
364 e573cb09 2020-09-27 op
365 e573cb09 2020-09-27 op int
366 e573cb09 2020-09-27 op match_window(struct match *m, Window w)
367 e573cb09 2020-09-27 op {
368 e573cb09 2020-09-27 op switch (m->prop) {
369 9f53ba9b 2020-09-29 op case MANY:
370 9f53ba9b 2020-09-29 op return 1;
371 9f53ba9b 2020-09-29 op
372 e573cb09 2020-09-27 op case MCLASS:
373 e573cb09 2020-09-27 op return window_match_class(w, m->str);
374 e573cb09 2020-09-27 op break;
375 e573cb09 2020-09-27 op
376 e573cb09 2020-09-27 op default:
377 e573cb09 2020-09-27 op /* unreachable */
378 e573cb09 2020-09-27 op abort();
379 e573cb09 2020-09-27 op }
380 e573cb09 2020-09-27 op }
381 e573cb09 2020-09-27 op
382 e573cb09 2020-09-27 op
383 e573cb09 2020-09-27 op /* rule */
384 e573cb09 2020-09-27 op
385 e573cb09 2020-09-27 op struct rule *
386 e573cb09 2020-09-27 op new_rule(struct key k, struct action a)
387 e573cb09 2020-09-27 op {
388 e573cb09 2020-09-27 op struct rule *r;
389 e573cb09 2020-09-27 op
390 e573cb09 2020-09-27 op if ((r = calloc(1, sizeof(*r))) == NULL)
391 e573cb09 2020-09-27 op err(1, "calloc");
392 e573cb09 2020-09-27 op memcpy(&r->key, &k, sizeof(k));
393 e573cb09 2020-09-27 op memcpy(&r->action, &a, sizeof(a));
394 e573cb09 2020-09-27 op return r;
395 e573cb09 2020-09-27 op }
396 e573cb09 2020-09-27 op
397 e573cb09 2020-09-27 op void
398 e573cb09 2020-09-27 op recfree_rule(struct rule *r)
399 e573cb09 2020-09-27 op {
400 e573cb09 2020-09-27 op struct rule *rt;
401 e573cb09 2020-09-27 op
402 e573cb09 2020-09-27 op if (r == NULL)
403 e573cb09 2020-09-27 op return;
404 e573cb09 2020-09-27 op
405 e573cb09 2020-09-27 op rt = r->next;
406 e573cb09 2020-09-27 op free(r);
407 e573cb09 2020-09-27 op recfree_rule(rt);
408 e573cb09 2020-09-27 op }
409 e573cb09 2020-09-27 op
410 e573cb09 2020-09-27 op int
411 e573cb09 2020-09-27 op rule_matched(struct rule *r, struct key k)
412 e573cb09 2020-09-27 op {
413 e573cb09 2020-09-27 op unsigned int m;
414 e573cb09 2020-09-27 op
415 e573cb09 2020-09-27 op m = k.modifier;
416 e573cb09 2020-09-27 op m &= ~IGNORE_MODIFIERS; /* clear ignored modifiers */
417 e573cb09 2020-09-27 op
418 e573cb09 2020-09-27 op return r->key.modifier == m
419 e573cb09 2020-09-27 op && r->key.key == k.key;
420 e573cb09 2020-09-27 op }
421 e573cb09 2020-09-27 op
422 e573cb09 2020-09-27 op
423 e573cb09 2020-09-27 op /* group */
424 e573cb09 2020-09-27 op
425 e573cb09 2020-09-27 op struct group *
426 e573cb09 2020-09-27 op new_group(struct match *matches, struct rule *rules)
427 e573cb09 2020-09-27 op {
428 e573cb09 2020-09-27 op struct group *g;
429 e573cb09 2020-09-27 op
430 e573cb09 2020-09-27 op if ((g = calloc(1, sizeof(*g))) == NULL)
431 e573cb09 2020-09-27 op err(1, "calloc");
432 e573cb09 2020-09-27 op g->matches = matches;
433 e573cb09 2020-09-27 op g->rules = rules;
434 e573cb09 2020-09-27 op return g;
435 e573cb09 2020-09-27 op }
436 e573cb09 2020-09-27 op
437 e573cb09 2020-09-27 op void
438 e573cb09 2020-09-27 op recfree_group(struct group *g)
439 e573cb09 2020-09-27 op {
440 e573cb09 2020-09-27 op struct group *gt;
441 e573cb09 2020-09-27 op
442 e573cb09 2020-09-27 op if (g == NULL)
443 e573cb09 2020-09-27 op return;
444 e573cb09 2020-09-27 op
445 e573cb09 2020-09-27 op gt = g->next;
446 e573cb09 2020-09-27 op recfree_match(g->matches);
447 e573cb09 2020-09-27 op recfree_rule(g->rules);
448 e573cb09 2020-09-27 op free(g);
449 e573cb09 2020-09-27 op recfree_group(gt);
450 e573cb09 2020-09-27 op }
451 e573cb09 2020-09-27 op
452 e573cb09 2020-09-27 op void
453 e573cb09 2020-09-27 op process_event(struct group *g, XKeyEvent *e)
454 e573cb09 2020-09-27 op {
455 e573cb09 2020-09-27 op Window focused;
456 e573cb09 2020-09-27 op struct rule *r;
457 e573cb09 2020-09-27 op struct key pressed = {
458 e573cb09 2020-09-27 op .modifier = e->state,
459 e573cb09 2020-09-27 op .key = keycode_to_keysym(e->keycode),
460 e573cb09 2020-09-27 op };
461 e573cb09 2020-09-27 op
462 e573cb09 2020-09-27 op focused = focused_window();
463 e573cb09 2020-09-27 op
464 e573cb09 2020-09-27 op for (; g != NULL; g = g->next) {
465 e573cb09 2020-09-27 op if (!group_match(g, focused))
466 e573cb09 2020-09-27 op continue;
467 e573cb09 2020-09-27 op
468 e573cb09 2020-09-27 op for (r = g->rules; r != NULL; r = r->next) {
469 e573cb09 2020-09-27 op if (rule_matched(r, pressed)) {
470 e573cb09 2020-09-27 op do_action(r->action, focused, e->type == KeyPress);
471 e573cb09 2020-09-27 op return;
472 e573cb09 2020-09-27 op }
473 e573cb09 2020-09-27 op }
474 e573cb09 2020-09-27 op }
475 e573cb09 2020-09-27 op
476 e573cb09 2020-09-27 op send_fake(focused, pressed, e->type == KeyPress);
477 e573cb09 2020-09-27 op }
478 e573cb09 2020-09-27 op
479 e573cb09 2020-09-27 op int
480 e573cb09 2020-09-27 op group_match(struct group *g, Window w)
481 e573cb09 2020-09-27 op {
482 e573cb09 2020-09-27 op struct match *m;
483 e573cb09 2020-09-27 op
484 e573cb09 2020-09-27 op for (m = g->matches; m != NULL; m = m->next)
485 e573cb09 2020-09-27 op if (match_window(m, w))
486 e573cb09 2020-09-27 op return 1;
487 e573cb09 2020-09-27 op return 0;
488 e573cb09 2020-09-27 op }
489 e573cb09 2020-09-27 op
490 e573cb09 2020-09-27 op
491 e573cb09 2020-09-27 op /* debug/dump stuff */
492 e573cb09 2020-09-27 op
493 e573cb09 2020-09-27 op void
494 e573cb09 2020-09-27 op printkey(struct key k)
495 e573cb09 2020-09-27 op {
496 e573cb09 2020-09-27 op if (k.modifier & ControlMask)
497 e573cb09 2020-09-27 op printf("C-");
498 e573cb09 2020-09-27 op if (k.modifier & ShiftMask)
499 e573cb09 2020-09-27 op printf("S-");
500 e573cb09 2020-09-27 op if (k.modifier & Mod1Mask)
501 e573cb09 2020-09-27 op printf("M-");
502 e573cb09 2020-09-27 op if (k.modifier & Mod4Mask)
503 e573cb09 2020-09-27 op printf("s-");
504 e573cb09 2020-09-27 op
505 e573cb09 2020-09-27 op printf("%s", XKeysymToString(k.key));
506 e573cb09 2020-09-27 op }
507 e573cb09 2020-09-27 op
508 e573cb09 2020-09-27 op void
509 e573cb09 2020-09-27 op printaction(struct action a)
510 e573cb09 2020-09-27 op {
511 e573cb09 2020-09-27 op if (a.type == ASPECIAL) {
512 e573cb09 2020-09-27 op switch (a.special) {
513 e573cb09 2020-09-27 op case ATOGGLE: printf("toggle"); break;
514 e573cb09 2020-09-27 op case AACTIVATE: printf("activate"); break;
515 e573cb09 2020-09-27 op case ADEACTIVATE: printf("deactivate"); break;
516 e573cb09 2020-09-27 op case AIGNORE: printf("ignore"); break;
517 e573cb09 2020-09-27 op }
518 e573cb09 2020-09-27 op } else {
519 e573cb09 2020-09-27 op printf("send key ");
520 e573cb09 2020-09-27 op printkey(a.send_key);
521 e573cb09 2020-09-27 op }
522 e573cb09 2020-09-27 op }
523 e573cb09 2020-09-27 op
524 e573cb09 2020-09-27 op void
525 e573cb09 2020-09-27 op printmatch(struct match *m)
526 e573cb09 2020-09-27 op {
527 e573cb09 2020-09-27 op if (m == NULL) {
528 e573cb09 2020-09-27 op printf("(null)");
529 e573cb09 2020-09-27 op return;
530 e573cb09 2020-09-27 op }
531 e573cb09 2020-09-27 op printf("match ");
532 e573cb09 2020-09-27 op switch (m->prop) {
533 e573cb09 2020-09-27 op case MCLASS:
534 e573cb09 2020-09-27 op printf("class");
535 e573cb09 2020-09-27 op break;
536 e573cb09 2020-09-27 op default:
537 e573cb09 2020-09-27 op abort();
538 e573cb09 2020-09-27 op }
539 e573cb09 2020-09-27 op printf(" %s", m->str);
540 e573cb09 2020-09-27 op
541 e573cb09 2020-09-27 op if (m->next == NULL)
542 e573cb09 2020-09-27 op printf("\n");
543 e573cb09 2020-09-27 op else {
544 e573cb09 2020-09-27 op printf(" ; ");
545 e573cb09 2020-09-27 op printmatch(m->next);
546 e573cb09 2020-09-27 op }
547 e573cb09 2020-09-27 op }
548 e573cb09 2020-09-27 op
549 e573cb09 2020-09-27 op void
550 e573cb09 2020-09-27 op printrule(struct rule *r)
551 e573cb09 2020-09-27 op {
552 e573cb09 2020-09-27 op if (r == NULL) {
553 e573cb09 2020-09-27 op printf("(null)");
554 e573cb09 2020-09-27 op return;
555 e573cb09 2020-09-27 op }
556 e573cb09 2020-09-27 op printf("on ");
557 e573cb09 2020-09-27 op printkey(r->key);
558 e573cb09 2020-09-27 op printf(" do ");
559 e573cb09 2020-09-27 op printaction(r->action);
560 e573cb09 2020-09-27 op printf("\n");
561 e573cb09 2020-09-27 op
562 e573cb09 2020-09-27 op if (r->next != NULL)
563 e573cb09 2020-09-27 op printrule(r->next);
564 e573cb09 2020-09-27 op }
565 e573cb09 2020-09-27 op
566 e573cb09 2020-09-27 op void
567 e573cb09 2020-09-27 op printgroup(struct group *g)
568 e573cb09 2020-09-27 op {
569 e573cb09 2020-09-27 op if (g == NULL) {
570 e573cb09 2020-09-27 op printf("(null)");
571 e573cb09 2020-09-27 op return;
572 e573cb09 2020-09-27 op }
573 e573cb09 2020-09-27 op printmatch(g->matches);
574 e573cb09 2020-09-27 op printf("\n");
575 e573cb09 2020-09-27 op printrule(g->rules);
576 e573cb09 2020-09-27 op printf("\n\n");
577 e573cb09 2020-09-27 op
578 e573cb09 2020-09-27 op if (g->next != NULL)
579 e573cb09 2020-09-27 op printgroup(g->next);
580 e573cb09 2020-09-27 op }