]> Dogcows Code - chaz/openbox/blob - openbox/action.c
change how rc parsing will work. a=b will be parsed in any [section] and given to...
[chaz/openbox] / openbox / action.c
1 #include "client.h"
2 #include "stacking.h"
3 #include "frame.h"
4 #include "screen.h"
5 #include "action.h"
6 #include "dispatch.h"
7 #include "openbox.h"
8
9 #include <glib.h>
10
11 Action *action_new(void (*func)(union ActionData *data))
12 {
13 Action *a = g_new0(Action, 1);
14 a->func = func;
15
16 /* deal with pointers */
17 if (func == action_execute)
18 a->data.execute.path = NULL;
19
20 return a;
21 }
22
23 void action_free(Action *a)
24 {
25 if (a == NULL) return;
26
27 /* deal with pointers */
28 if (a->func == action_execute || a->func == action_restart)
29 g_free(a->data.execute.path);
30
31 g_free(a);
32 }
33
34 Action *action_from_string(char *name)
35 {
36 Action *a = NULL;
37 if (!g_ascii_strcasecmp(name, "execute")) {
38 a = action_new(action_execute);
39 } else if (!g_ascii_strcasecmp(name, "focus")) {
40 a = action_new(action_focus);
41 } else if (!g_ascii_strcasecmp(name, "unfocus")) {
42 a = action_new(action_unfocus);
43 } else if (!g_ascii_strcasecmp(name, "iconify")) {
44 a = action_new(action_iconify);
45 } else if (!g_ascii_strcasecmp(name, "raise")) {
46 a = action_new(action_raise);
47 } else if (!g_ascii_strcasecmp(name, "lower")) {
48 a = action_new(action_lower);
49 } else if (!g_ascii_strcasecmp(name, "focusraise")) {
50 a = action_new(action_focusraise);
51 } else if (!g_ascii_strcasecmp(name, "close")) {
52 a = action_new(action_close);
53 } else if (!g_ascii_strcasecmp(name, "kill")) {
54 a = action_new(action_kill);
55 } else if (!g_ascii_strcasecmp(name, "shadelower")) {
56 a = action_new(action_shadelower);
57 } else if (!g_ascii_strcasecmp(name, "unshaderaise")) {
58 a = action_new(action_unshaderaise);
59 } else if (!g_ascii_strcasecmp(name, "shade")) {
60 a = action_new(action_shade);
61 } else if (!g_ascii_strcasecmp(name, "unshade")) {
62 a = action_new(action_unshade);
63 } else if (!g_ascii_strcasecmp(name, "toggleshade")) {
64 a = action_new(action_toggle_shade);
65 } else if (!g_ascii_strcasecmp(name, "toggleomnipresent")) {
66 a = action_new(action_toggle_omnipresent);
67 } else if (!g_ascii_strcasecmp(name, "moverelativehorz")) {
68 a = action_new(action_move_relative_horz);
69 } else if (!g_ascii_strcasecmp(name, "moverelativevert")) {
70 a = action_new(action_move_relative_vert);
71 } else if (!g_ascii_strcasecmp(name, "resizerelativehorz")) {
72 a = action_new(action_resize_relative_horz);
73 } else if (!g_ascii_strcasecmp(name, "resizerelativevert")) {
74 a = action_new(action_resize_relative_vert);
75 } else if (!g_ascii_strcasecmp(name, "maximizefull")) {
76 a = action_new(action_maximize_full);
77 } else if (!g_ascii_strcasecmp(name, "unmaximizefull")) {
78 a = action_new(action_unmaximize_full);
79 } else if (!g_ascii_strcasecmp(name, "togglemaximizefull")) {
80 a = action_new(action_toggle_maximize_full);
81 } else if (!g_ascii_strcasecmp(name, "maximizehorz")) {
82 a = action_new(action_maximize_horz);
83 } else if (!g_ascii_strcasecmp(name, "unmaximizehorz")) {
84 a = action_new(action_unmaximize_horz);
85 } else if (!g_ascii_strcasecmp(name, "togglemaximizehorz")) {
86 a = action_new(action_toggle_maximize_horz);
87 } else if (!g_ascii_strcasecmp(name, "maximizevert")) {
88 a = action_new(action_maximize_vert);
89 } else if (!g_ascii_strcasecmp(name, "unmaximizevert")) {
90 a = action_new(action_unmaximize_vert);
91 } else if (!g_ascii_strcasecmp(name, "togglemaximizevert")) {
92 a = action_new(action_toggle_maximize_vert);
93 } else if (!g_ascii_strcasecmp(name, "sendtodesktop")) {
94 a = action_new(action_send_to_desktop);
95 a->data.sendto.follow = TRUE;
96 } else if (!g_ascii_strcasecmp(name, "sendtonextdesktop")) {
97 a = action_new(action_send_to_next_desktop);
98 a->data.sendtonextprev.wrap = FALSE;
99 a->data.sendtonextprev.follow = TRUE;
100 } else if (!g_ascii_strcasecmp(name, "sendtonextdesktopwrap")) {
101 a = action_new(action_send_to_next_desktop);
102 a->data.sendtonextprev.wrap = TRUE;
103 a->data.sendtonextprev.follow = TRUE;
104 } else if (!g_ascii_strcasecmp(name, "sendtopreviousdesktop")) {
105 a = action_new(action_send_to_previous_desktop);
106 a->data.sendtonextprev.wrap = FALSE;
107 a->data.sendtonextprev.follow = TRUE;
108 } else if (!g_ascii_strcasecmp(name, "sendtopreviousdesktopwrap")) {
109 a = action_new(action_send_to_previous_desktop);
110 a->data.sendtonextprev.wrap = TRUE;
111 a->data.sendtonextprev.follow = TRUE;
112 } else if (!g_ascii_strcasecmp(name, "desktop")) {
113 a = action_new(action_desktop);
114 } else if (!g_ascii_strcasecmp(name, "nextdesktop")) {
115 a = action_new(action_next_desktop);
116 a->data.nextprevdesktop.wrap = FALSE;
117 } else if (!g_ascii_strcasecmp(name, "nextdesktopwrap")) {
118 a = action_new(action_next_desktop);
119 a->data.nextprevdesktop.wrap = TRUE;
120 } else if (!g_ascii_strcasecmp(name, "previousdesktop")) {
121 a = action_new(action_previous_desktop);
122 a->data.nextprevdesktop.wrap = FALSE;
123 } else if (!g_ascii_strcasecmp(name, "previousdesktopwrap")) {
124 a = action_new(action_previous_desktop);
125 a->data.nextprevdesktop.wrap = TRUE;
126 } else if (!g_ascii_strcasecmp(name, "nextdesktopcolumn")) {
127 a = action_new(action_next_desktop_column);
128 a->data.nextprevdesktop.wrap = FALSE;
129 } else if (!g_ascii_strcasecmp(name, "nextdesktopcolumnwrap")) {
130 a = action_new(action_next_desktop_column);
131 a->data.nextprevdesktop.wrap = TRUE;
132 } else if (!g_ascii_strcasecmp(name, "previousdesktopcolumn")) {
133 a = action_new(action_previous_desktop_column);
134 a->data.nextprevdesktop.wrap = FALSE;
135 } else if (!g_ascii_strcasecmp(name, "previousdesktopcolumnwrap")) {
136 a = action_new(action_previous_desktop_column);
137 a->data.nextprevdesktop.wrap = TRUE;
138 } else if (!g_ascii_strcasecmp(name, "nextdesktoprow")) {
139 a = action_new(action_next_desktop_row);
140 a->data.nextprevdesktop.wrap = FALSE;
141 } else if (!g_ascii_strcasecmp(name, "nextdesktoprowwrap")) {
142 a = action_new(action_next_desktop_row);
143 a->data.nextprevdesktop.wrap = TRUE;
144 } else if (!g_ascii_strcasecmp(name, "previousdesktoprow")) {
145 a = action_new(action_previous_desktop_row);
146 a->data.nextprevdesktop.wrap = FALSE;
147 } else if (!g_ascii_strcasecmp(name, "previousdesktoprowwrap")) {
148 a = action_new(action_previous_desktop_row);
149 a->data.nextprevdesktop.wrap = TRUE;
150 } else if (!g_ascii_strcasecmp(name, "toggledecorations")) {
151 a = action_new(action_toggle_decorations);
152 } else if (!g_ascii_strcasecmp(name, "move")) {
153 a = action_new(action_move);
154 } else if (!g_ascii_strcasecmp(name, "resize")) {
155 a = action_new(action_resize);
156 } else if (!g_ascii_strcasecmp(name, "restart")) {
157 a = action_new(action_restart);
158 } else if (!g_ascii_strcasecmp(name, "exit")) {
159 a = action_new(action_exit);
160 } else if (!g_ascii_strcasecmp(name, "showmenu")) {
161 a = action_new(action_showmenu);
162 } else if (!g_ascii_strcasecmp(name, "nextwindowlinear")) {
163 a = action_new(action_cycle_windows);
164 a->data.cycle.linear = TRUE;
165 a->data.cycle.forward = TRUE;
166 } else if (!g_ascii_strcasecmp(name, "previouswindowlinear")) {
167 a = action_new(action_cycle_windows);
168 a->data.cycle.linear = TRUE;
169 a->data.cycle.forward = FALSE;
170 }
171
172 return a;
173 }
174
175 void action_execute(union ActionData *data)
176 {
177 GError *e = NULL;
178 if (data->execute.path)
179 if (!g_spawn_command_line_async(data->execute.path, &e)) {
180 g_warning("failed to execute '%s': %s",
181 data->execute.path, e->message);
182 }
183 }
184
185 void action_focus(union ActionData *data)
186 {
187 if (data->client.c)
188 client_focus(data->client.c);
189 }
190
191 void action_unfocus (union ActionData *data)
192 {
193 if (data->client.c)
194 client_unfocus(data->client.c);
195 }
196
197 void action_iconify(union ActionData *data)
198 {
199 if (data->client.c)
200 client_iconify(data->client.c, TRUE, TRUE);
201 }
202
203 void action_focusraise(union ActionData *data)
204 {
205 if (data->client.c) {
206 client_focus(data->client.c);
207 stacking_raise(data->client.c);
208 }
209 }
210
211 void action_raise(union ActionData *data)
212 {
213 if (data->client.c)
214 stacking_raise(data->client.c);
215 }
216
217 void action_unshaderaise(union ActionData *data)
218 {
219 if (data->client.c) {
220 if (data->client.c->shaded)
221 client_shade(data->client.c, FALSE);
222 else
223 stacking_raise(data->client.c);
224 }
225 }
226
227 void action_shadelower(union ActionData *data)
228 {
229 if (data->client.c) {
230 if (data->client.c->shaded)
231 stacking_lower(data->client.c);
232 else
233 client_shade(data->client.c, TRUE);
234 }
235 }
236
237 void action_lower(union ActionData *data)
238 {
239 if (data->client.c)
240 stacking_lower(data->client.c);
241 }
242
243 void action_close(union ActionData *data)
244 {
245 if (data->client.c)
246 client_close(data->client.c);
247 }
248
249 void action_kill(union ActionData *data)
250 {
251 if (data->client.c)
252 client_kill(data->client.c);
253 }
254
255 void action_shade(union ActionData *data)
256 {
257 if (data->client.c)
258 client_shade(data->client.c, TRUE);
259 }
260
261 void action_unshade(union ActionData *data)
262 {
263 if (data->client.c)
264 client_shade(data->client.c, FALSE);
265 }
266
267 void action_toggle_shade(union ActionData *data)
268 {
269 if (data->client.c)
270 client_shade(data->client.c, !data->client.c->shaded);
271 }
272
273 void action_toggle_omnipresent(union ActionData *data)
274 {
275 if (data->client.c)
276 client_set_desktop(data->client.c,
277 data->client.c->desktop == DESKTOP_ALL ?
278 screen_desktop : DESKTOP_ALL, FALSE);
279 }
280
281 void action_move_relative_horz(union ActionData *data)
282 {
283 Client *c = data->relative.c;
284 if (c)
285 client_configure(c, Corner_TopLeft,
286 c->area.x + data->relative.delta, c->area.y,
287 c->area.width, c->area.height, TRUE, TRUE);
288 }
289
290 void action_move_relative_vert(union ActionData *data)
291 {
292 Client *c = data->relative.c;
293 if (c)
294 client_configure(c, Corner_TopLeft,
295 c->area.x, c->area.y + data->relative.delta,
296 c->area.width, c->area.height, TRUE, TRUE);
297 }
298
299 void action_resize_relative_horz(union ActionData *data)
300 {
301 Client *c = data->relative.c;
302 if (c)
303 client_configure(c, Corner_TopLeft, c->area.x, c->area.y,
304 c->area.width + data->relative.delta,
305 c->area.height, TRUE, TRUE);
306 }
307
308 void action_resize_relative_vert(union ActionData *data)
309 {
310 Client *c = data->relative.c;
311 if (c && !c->shaded)
312 client_configure(c, Corner_TopLeft, c->area.x, c->area.y,
313 c->area.width, c->area.height + data->relative.delta,
314 TRUE, TRUE);
315 }
316
317 void action_maximize_full(union ActionData *data)
318 {
319 if (data->client.c)
320 client_maximize(data->client.c, TRUE, 0, TRUE);
321 }
322
323 void action_unmaximize_full(union ActionData *data)
324 {
325 if (data->client.c)
326 client_maximize(data->client.c, FALSE, 0, TRUE);
327 }
328
329 void action_toggle_maximize_full(union ActionData *data)
330 {
331 if (data->client.c)
332 client_maximize(data->client.c,
333 !(data->client.c->max_horz ||
334 data->client.c->max_vert),
335 0, TRUE);
336 }
337
338 void action_maximize_horz(union ActionData *data)
339 {
340 if (data->client.c)
341 client_maximize(data->client.c, TRUE, 1, TRUE);
342 }
343
344 void action_unmaximize_horz(union ActionData *data)
345 {
346 if (data->client.c)
347 client_maximize(data->client.c, FALSE, 1, TRUE);
348 }
349
350 void action_toggle_maximize_horz(union ActionData *data)
351 {
352 if (data->client.c)
353 client_maximize(data->client.c, !data->client.c->max_horz, 1, TRUE);
354 }
355
356 void action_maximize_vert(union ActionData *data)
357 {
358 if (data->client.c)
359 client_maximize(data->client.c, TRUE, 2, TRUE);
360 }
361
362 void action_unmaximize_vert(union ActionData *data)
363 {
364 if (data->client.c)
365 client_maximize(data->client.c, FALSE, 2, TRUE);
366 }
367
368 void action_toggle_maximize_vert(union ActionData *data)
369 {
370 if (data->client.c)
371 client_maximize(data->client.c, !data->client.c->max_vert, 2, TRUE);
372 }
373
374 void action_send_to_desktop(union ActionData *data)
375 {
376 if (data->sendto.c) {
377 if (data->sendto.desk < screen_num_desktops ||
378 data->sendto.desk == DESKTOP_ALL) {
379 client_set_desktop(data->desktop.c,
380 data->sendto.desk, data->sendto.follow);
381 if (data->sendto.follow) screen_set_desktop(data->sendto.desk);
382 }
383 }
384 }
385
386 void action_send_to_next_desktop(union ActionData *data)
387 {
388 guint d;
389
390 if (!data->sendtonextprev.c) return;
391
392 d = screen_desktop + 1;
393 if (d >= screen_num_desktops) {
394 if (!data->sendtonextprev.wrap) return;
395 d = 0;
396 }
397 client_set_desktop(data->sendtonextprev.c, d, data->sendtonextprev.follow);
398 if (data->sendtonextprev.follow) screen_set_desktop(d);
399 }
400
401 void action_send_to_previous_desktop(union ActionData *data)
402 {
403 guint d;
404
405 if (!data->sendtonextprev.c) return;
406
407 d = screen_desktop - 1;
408 if (d >= screen_num_desktops) {
409 if (!data->sendtonextprev.wrap) return;
410 d = screen_num_desktops - 1;
411 }
412 client_set_desktop(data->sendtonextprev.c, d, data->sendtonextprev.follow);
413 if (data->sendtonextprev.follow) screen_set_desktop(d);
414 }
415
416 void action_desktop(union ActionData *data)
417 {
418 if (data->desktop.desk < screen_num_desktops ||
419 data->desktop.desk == DESKTOP_ALL)
420 screen_set_desktop(data->desktop.desk);
421 }
422
423 void action_next_desktop(union ActionData *data)
424 {
425 guint d;
426
427 d = screen_desktop + 1;
428 if (d >= screen_num_desktops) {
429 if (!data->nextprevdesktop.wrap) return;
430 d = 0;
431 }
432 screen_set_desktop(d);
433 }
434
435 void action_previous_desktop(union ActionData *data)
436 {
437 guint d;
438
439 d = screen_desktop - 1;
440 if (d >= screen_num_desktops) {
441 if (!data->nextprevdesktop.wrap) return;
442 d = screen_num_desktops - 1;
443 }
444 screen_set_desktop(d);
445 }
446
447 static void cur_row_col(guint *r, guint *c)
448 {
449 switch (screen_desktop_layout.orientation) {
450 case Orientation_Horz:
451 switch (screen_desktop_layout.start_corner) {
452 case Corner_TopLeft:
453 *r = screen_desktop / screen_desktop_layout.columns;
454 *c = screen_desktop % screen_desktop_layout.columns;
455 break;
456 case Corner_BottomLeft:
457 *r = screen_desktop_layout.rows - 1 -
458 screen_desktop / screen_desktop_layout.columns;
459 *c = screen_desktop % screen_desktop_layout.columns;
460 break;
461 case Corner_TopRight:
462 *r = screen_desktop / screen_desktop_layout.columns;
463 *c = screen_desktop_layout.columns - 1 -
464 screen_desktop % screen_desktop_layout.columns;
465 break;
466 case Corner_BottomRight:
467 *r = screen_desktop_layout.rows - 1 -
468 screen_desktop / screen_desktop_layout.columns;
469 *c = screen_desktop_layout.columns - 1 -
470 screen_desktop % screen_desktop_layout.columns;
471 break;
472 }
473 break;
474 case Orientation_Vert:
475 switch (screen_desktop_layout.start_corner) {
476 case Corner_TopLeft:
477 *r = screen_desktop % screen_desktop_layout.rows;
478 *c = screen_desktop / screen_desktop_layout.rows;
479 break;
480 case Corner_BottomLeft:
481 *r = screen_desktop_layout.rows - 1 -
482 screen_desktop % screen_desktop_layout.rows;
483 *c = screen_desktop / screen_desktop_layout.rows;
484 break;
485 case Corner_TopRight:
486 *r = screen_desktop % screen_desktop_layout.rows;
487 *c = screen_desktop_layout.columns - 1 -
488 screen_desktop / screen_desktop_layout.rows;
489 break;
490 case Corner_BottomRight:
491 *r = screen_desktop_layout.rows - 1 -
492 screen_desktop % screen_desktop_layout.rows;
493 *c = screen_desktop_layout.columns - 1 -
494 screen_desktop / screen_desktop_layout.rows;
495 break;
496 }
497 break;
498 }
499 }
500
501 static guint translate_row_col(guint r, guint c)
502 {
503 switch (screen_desktop_layout.orientation) {
504 case Orientation_Horz:
505 switch (screen_desktop_layout.start_corner) {
506 case Corner_TopLeft:
507 return r * screen_desktop_layout.columns + c;
508 case Corner_BottomLeft:
509 return (screen_desktop_layout.rows - 1 - r) *
510 screen_desktop_layout.columns + c;
511 case Corner_TopRight:
512 return r * screen_desktop_layout.columns +
513 (screen_desktop_layout.columns - 1 - c);
514 case Corner_BottomRight:
515 return (screen_desktop_layout.rows - 1 - r) *
516 screen_desktop_layout.columns +
517 (screen_desktop_layout.columns - 1 - c);
518 }
519 case Orientation_Vert:
520 switch (screen_desktop_layout.start_corner) {
521 case Corner_TopLeft:
522 return c * screen_desktop_layout.rows + r;
523 case Corner_BottomLeft:
524 return c * screen_desktop_layout.rows +
525 (screen_desktop_layout.rows - 1 - r);
526 case Corner_TopRight:
527 return (screen_desktop_layout.columns - 1 - c) *
528 screen_desktop_layout.rows + r;
529 case Corner_BottomRight:
530 return (screen_desktop_layout.columns - 1 - c) *
531 screen_desktop_layout.rows +
532 (screen_desktop_layout.rows - 1 - r);
533 }
534 }
535 g_assert_not_reached();
536 return 0;
537 }
538
539 void action_next_desktop_column(union ActionData *data)
540 {
541 guint r, c, d;
542
543 cur_row_col(&r, &c);
544 ++c;
545 d = translate_row_col(r, c);
546 if (d >= screen_num_desktops) {
547 if (!data->nextprevdesktop.wrap) return;
548 c = 0;
549 }
550 if (d >= screen_num_desktops)
551 ++c;
552 d = translate_row_col(r, c);
553 if (d < screen_num_desktops)
554 screen_set_desktop(d);
555 }
556
557 void action_previous_desktop_column(union ActionData *data)
558 {
559 guint r, c, d;
560
561 cur_row_col(&r, &c);
562 --c;
563 d = translate_row_col(r, c);
564 if (d >= screen_num_desktops) {
565 if (!data->nextprevdesktop.wrap) return;
566 c = screen_desktop_layout.columns - 1;
567 }
568 if (d >= screen_num_desktops)
569 --c;
570 d = translate_row_col(r, c);
571 if (d < screen_num_desktops)
572 screen_set_desktop(d);
573 }
574
575 void action_next_desktop_row(union ActionData *data)
576 {
577 guint r, c, d;
578
579 cur_row_col(&r, &c);
580 ++r;
581 d = translate_row_col(r, c);
582 if (d >= screen_num_desktops) {
583 if (!data->nextprevdesktop.wrap) return;
584 r = 0;
585 }
586 if (d >= screen_num_desktops)
587 ++r;
588 d = translate_row_col(r, c);
589 if (d < screen_num_desktops)
590 screen_set_desktop(d);
591 }
592
593 void action_previous_desktop_row(union ActionData *data)
594 {
595 guint r, c, d;
596
597 cur_row_col(&r, &c);
598 --r;
599 d = translate_row_col(r, c);
600 if (d >= screen_num_desktops) {
601 if (!data->nextprevdesktop.wrap) return;
602 c = screen_desktop_layout.rows - 1;
603 }
604 if (d >= screen_num_desktops)
605 --r;
606 d = translate_row_col(r, c);
607 if (d < screen_num_desktops)
608 screen_set_desktop(d);
609 }
610
611 void action_toggle_decorations(union ActionData *data)
612 {
613 Client *c = data->client.c;
614 c->disabled_decorations = c->disabled_decorations ? 0 : ~0;
615 client_setup_decor_and_functions(c);
616 }
617
618 void action_move(union ActionData *data)
619 {
620 Client *c = data->move.c;
621 int x = data->move.x;
622 int y = data->move.y;
623
624 if (!c || !client_normal(c)) return;
625
626 dispatch_move(c, &x, &y);
627
628 frame_frame_gravity(c->frame, &x, &y); /* get where the client should be */
629 client_configure(c, Corner_TopLeft, x, y, c->area.width, c->area.height,
630 TRUE, data->move.final);
631 }
632
633 void action_resize(union ActionData *data)
634 {
635 Client *c = data->resize.c;
636 int w = data->resize.x;
637 int h = data->resize.y;
638
639 if (!c || c->shaded || !client_normal(c)) return;
640
641 dispatch_resize(c, &w, &h, data->resize.corner);
642
643 w -= c->frame->size.left + c->frame->size.right;
644 h -= c->frame->size.top + c->frame->size.bottom;
645
646 client_configure(c, data->resize.corner, c->area.x, c->area.y, w, h,
647 TRUE, data->resize.final);
648 }
649
650 void action_restart(union ActionData *data)
651 {
652 ob_restart_path = data->execute.path;
653 ob_shutdown = ob_restart = TRUE;
654 }
655
656 void action_exit(union ActionData *data)
657 {
658 ob_shutdown = TRUE;
659 }
660
661 void action_showmenu(union ActionData *data)
662 {
663 g_message(__FUNCTION__);
664 }
665
666 void action_cycle_windows(union ActionData *data)
667 {
668 if (data->cycle.linear) {
669 if (!data->cycle.final) {
670 GList *it, *start;
671
672 start = it = g_list_find(client_list, data->cycle.c);
673 do {
674 if (data->cycle.forward) {
675 it = it->next;
676 if (it == NULL) it = client_list;
677 } else {
678 it = it->prev;
679 if (it == NULL) it = g_list_last(client_list);
680 }
681 if (client_focus(it->data))
682 break;
683 } while (it != start);
684 }
685 } else {
686 }
687 }
688
This page took 0.072984 seconds and 4 git commands to generate.