]> Dogcows Code - chaz/openbox/blob - openbox/action.c
add unshaderaise and shadelower actions from Mikachu
[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, "sendtonextdesktop")) {
94 a = action_new(action_send_to_next_desktop);
95 a->data.sendtonextprev.wrap = FALSE;
96 a->data.sendtonextprev.follow = TRUE;
97 } else if (!g_ascii_strcasecmp(name, "sendtonextdesktopwrap")) {
98 a = action_new(action_send_to_next_desktop);
99 a->data.sendtonextprev.wrap = TRUE;
100 a->data.sendtonextprev.follow = TRUE;
101 } else if (!g_ascii_strcasecmp(name, "sendtopreviousdesktop")) {
102 a = action_new(action_send_to_previous_desktop);
103 a->data.sendtonextprev.wrap = FALSE;
104 a->data.sendtonextprev.follow = TRUE;
105 } else if (!g_ascii_strcasecmp(name, "sendtopreviousdesktopwrap")) {
106 a = action_new(action_send_to_previous_desktop);
107 a->data.sendtonextprev.wrap = TRUE;
108 a->data.sendtonextprev.follow = TRUE;
109 } else if (!g_ascii_strcasecmp(name, "desktop")) {
110 a = action_new(action_desktop);
111 } else if (!g_ascii_strcasecmp(name, "nextdesktop")) {
112 a = action_new(action_next_desktop);
113 a->data.nextprevdesktop.wrap = FALSE;
114 } else if (!g_ascii_strcasecmp(name, "nextdesktopwrap")) {
115 a = action_new(action_next_desktop);
116 a->data.nextprevdesktop.wrap = TRUE;
117 } else if (!g_ascii_strcasecmp(name, "previousdesktop")) {
118 a = action_new(action_previous_desktop);
119 a->data.nextprevdesktop.wrap = FALSE;
120 } else if (!g_ascii_strcasecmp(name, "previousdesktopwrap")) {
121 a = action_new(action_previous_desktop);
122 a->data.nextprevdesktop.wrap = TRUE;
123 } else if (!g_ascii_strcasecmp(name, "nextdesktopcolumn")) {
124 a = action_new(action_next_desktop_column);
125 a->data.nextprevdesktop.wrap = FALSE;
126 } else if (!g_ascii_strcasecmp(name, "nextdesktopcolumnwrap")) {
127 a = action_new(action_next_desktop_column);
128 a->data.nextprevdesktop.wrap = TRUE;
129 } else if (!g_ascii_strcasecmp(name, "previousdesktopcolumn")) {
130 a = action_new(action_previous_desktop_column);
131 a->data.nextprevdesktop.wrap = FALSE;
132 } else if (!g_ascii_strcasecmp(name, "previousdesktopcolumnwrap")) {
133 a = action_new(action_previous_desktop_column);
134 a->data.nextprevdesktop.wrap = TRUE;
135 } else if (!g_ascii_strcasecmp(name, "nextdesktoprow")) {
136 a = action_new(action_next_desktop_row);
137 a->data.nextprevdesktop.wrap = FALSE;
138 } else if (!g_ascii_strcasecmp(name, "nextdesktoprowwrap")) {
139 a = action_new(action_next_desktop_row);
140 a->data.nextprevdesktop.wrap = TRUE;
141 } else if (!g_ascii_strcasecmp(name, "previousdesktoprow")) {
142 a = action_new(action_previous_desktop_row);
143 a->data.nextprevdesktop.wrap = FALSE;
144 } else if (!g_ascii_strcasecmp(name, "previousdesktoprowwrap")) {
145 a = action_new(action_previous_desktop_row);
146 a->data.nextprevdesktop.wrap = TRUE;
147 } else if (!g_ascii_strcasecmp(name, "toggledecorations")) {
148 a = action_new(action_toggle_decorations);
149 } else if (!g_ascii_strcasecmp(name, "move")) {
150 a = action_new(action_move);
151 } else if (!g_ascii_strcasecmp(name, "resize")) {
152 a = action_new(action_resize);
153 } else if (!g_ascii_strcasecmp(name, "restart")) {
154 a = action_new(action_restart);
155 } else if (!g_ascii_strcasecmp(name, "exit")) {
156 a = action_new(action_exit);
157 }
158 return a;
159 }
160
161 void action_execute(union ActionData *data)
162 {
163 GError *e = NULL;
164 if (data->execute.path)
165 if (!g_spawn_command_line_async(data->execute.path, &e)) {
166 g_warning("failed to execute '%s': %s",
167 data->execute.path, e->message);
168 }
169 }
170
171 void action_focus(union ActionData *data)
172 {
173 if (data->client.c)
174 client_focus(data->client.c);
175 }
176
177 void action_unfocus (union ActionData *data)
178 {
179 if (data->client.c)
180 client_unfocus(data->client.c);
181 }
182
183 void action_iconify(union ActionData *data)
184 {
185 if (data->client.c)
186 client_iconify(data->client.c, TRUE, TRUE);
187 }
188
189 void action_focusraise(union ActionData *data)
190 {
191 if (data->client.c) {
192 client_focus(data->client.c);
193 stacking_raise(data->client.c);
194 }
195 }
196
197 void action_raise(union ActionData *data)
198 {
199 if (data->client.c)
200 stacking_raise(data->client.c);
201 }
202
203 void action_unshaderaise(union ActionData *data)
204 {
205 if (data->client.c) {
206 if (data->client.c->shaded)
207 client_shade(data->client.c, FALSE);
208 else
209 stacking_raise(data->client.c);
210 }
211 }
212
213 void action_shadelower(union ActionData *data)
214 {
215 if (data->client.c) {
216 if (data->client.c->shaded)
217 stacking_lower(data->client.c);
218 else
219 client_shade(data->client.c, TRUE);
220 }
221 }
222
223 void action_lower(union ActionData *data)
224 {
225 if (data->client.c)
226 stacking_lower(data->client.c);
227 }
228
229 void action_close(union ActionData *data)
230 {
231 if (data->client.c)
232 client_close(data->client.c);
233 }
234
235 void action_kill(union ActionData *data)
236 {
237 if (data->client.c)
238 client_kill(data->client.c);
239 }
240
241 void action_shade(union ActionData *data)
242 {
243 if (data->client.c)
244 client_shade(data->client.c, TRUE);
245 }
246
247 void action_unshade(union ActionData *data)
248 {
249 if (data->client.c)
250 client_shade(data->client.c, FALSE);
251 }
252
253 void action_toggle_shade(union ActionData *data)
254 {
255 if (data->client.c)
256 client_shade(data->client.c, !data->client.c->shaded);
257 }
258
259 void action_toggle_omnipresent(union ActionData *data)
260 {
261 if (data->client.c)
262 client_set_desktop(data->client.c,
263 data->client.c->desktop == DESKTOP_ALL ?
264 screen_desktop : DESKTOP_ALL, FALSE);
265 }
266
267 void action_move_relative_horz(union ActionData *data)
268 {
269 Client *c = data->relative.c;
270 if (c)
271 client_configure(c, Corner_TopLeft,
272 c->area.x + data->relative.delta, c->area.y,
273 c->area.width, c->area.height, TRUE, TRUE);
274 }
275
276 void action_move_relative_vert(union ActionData *data)
277 {
278 Client *c = data->relative.c;
279 if (c)
280 client_configure(c, Corner_TopLeft,
281 c->area.x, c->area.y + data->relative.delta,
282 c->area.width, c->area.height, TRUE, TRUE);
283 }
284
285 void action_resize_relative_horz(union ActionData *data)
286 {
287 Client *c = data->relative.c;
288 if (c)
289 client_configure(c, Corner_TopLeft, c->area.x, c->area.y,
290 c->area.width + data->relative.delta,
291 c->area.height, TRUE, TRUE);
292 }
293
294 void action_resize_relative_vert(union ActionData *data)
295 {
296 Client *c = data->relative.c;
297 if (c)
298 client_configure(c, Corner_TopLeft, c->area.x, c->area.y,
299 c->area.width, c->area.height + data->relative.delta,
300 TRUE, TRUE);
301 }
302
303 void action_maximize_full(union ActionData *data)
304 {
305 if (data->client.c)
306 client_maximize(data->client.c, TRUE, 0, TRUE);
307 }
308
309 void action_unmaximize_full(union ActionData *data)
310 {
311 if (data->client.c)
312 client_maximize(data->client.c, FALSE, 0, TRUE);
313 }
314
315 void action_toggle_maximize_full(union ActionData *data)
316 {
317 if (data->client.c)
318 client_maximize(data->client.c,
319 !(data->client.c->max_horz ||
320 data->client.c->max_vert),
321 0, TRUE);
322 }
323
324 void action_maximize_horz(union ActionData *data)
325 {
326 if (data->client.c)
327 client_maximize(data->client.c, TRUE, 1, TRUE);
328 }
329
330 void action_unmaximize_horz(union ActionData *data)
331 {
332 if (data->client.c)
333 client_maximize(data->client.c, FALSE, 1, TRUE);
334 }
335
336 void action_toggle_maximize_horz(union ActionData *data)
337 {
338 if (data->client.c)
339 client_maximize(data->client.c, !data->client.c->max_horz, 1, TRUE);
340 }
341
342 void action_maximize_vert(union ActionData *data)
343 {
344 if (data->client.c)
345 client_maximize(data->client.c, TRUE, 2, TRUE);
346 }
347
348 void action_unmaximize_vert(union ActionData *data)
349 {
350 if (data->client.c)
351 client_maximize(data->client.c, FALSE, 2, TRUE);
352 }
353
354 void action_toggle_maximize_vert(union ActionData *data)
355 {
356 if (data->client.c)
357 client_maximize(data->client.c, !data->client.c->max_vert, 2, TRUE);
358 }
359
360 void action_send_to_desktop(union ActionData *data)
361 {
362 if (data->sendto.c)
363 if (data->sendto.desktop < screen_num_desktops ||
364 data->sendto.desktop == DESKTOP_ALL)
365 client_set_desktop(data->sendto.c, data->sendto.desktop, TRUE);
366 }
367
368 void action_send_to_next_desktop(union ActionData *data)
369 {
370 guint d;
371
372 if (!data->sendto.c) return;
373
374 d = screen_desktop + 1;
375 if (d >= screen_num_desktops) {
376 if (!data->sendtonextprev.wrap) return;
377 d = 0;
378 }
379 client_set_desktop(data->sendtonextprev.c, d, data->sendtonextprev.follow);
380 if (data->sendtonextprev.follow) screen_set_desktop(d);
381 }
382
383 void action_send_to_previous_desktop(union ActionData *data)
384 {
385 guint d;
386
387 if (!data->sendto.c) return;
388
389 d = screen_desktop - 1;
390 if (d >= screen_num_desktops) {
391 if (!data->sendtonextprev.wrap) return;
392 d = screen_num_desktops - 1;
393 }
394 client_set_desktop(data->sendtonextprev.c, d, data->sendtonextprev.follow);
395 if (data->sendtonextprev.follow) screen_set_desktop(d);
396 }
397
398 void action_desktop(union ActionData *data)
399 {
400 if (data->desktop.desk < screen_num_desktops ||
401 data->desktop.desk == DESKTOP_ALL)
402 screen_set_desktop(data->desktop.desk);
403 }
404
405 void action_next_desktop(union ActionData *data)
406 {
407 guint d;
408
409 d = screen_desktop + 1;
410 if (d >= screen_num_desktops) {
411 if (!data->nextprevdesktop.wrap) return;
412 d = 0;
413 }
414 screen_set_desktop(d);
415 }
416
417 void action_previous_desktop(union ActionData *data)
418 {
419 guint d;
420
421 d = screen_desktop - 1;
422 if (d >= screen_num_desktops) {
423 if (!data->nextprevdesktop.wrap) return;
424 d = screen_num_desktops - 1;
425 }
426 screen_set_desktop(d);
427 }
428
429 static void cur_row_col(guint *r, guint *c)
430 {
431 switch (screen_desktop_layout.orientation) {
432 case Orientation_Horz:
433 switch (screen_desktop_layout.start_corner) {
434 case Corner_TopLeft:
435 *r = screen_desktop / screen_desktop_layout.columns;
436 *c = screen_desktop % screen_desktop_layout.columns;
437 break;
438 case Corner_BottomLeft:
439 *r = screen_desktop_layout.rows - 1 -
440 screen_desktop / screen_desktop_layout.columns;
441 *c = screen_desktop % screen_desktop_layout.columns;
442 break;
443 break;
444 case Corner_TopRight:
445 *r = screen_desktop / screen_desktop_layout.columns;
446 *c = screen_desktop_layout.columns - 1 -
447 screen_desktop % screen_desktop_layout.columns;
448 break;
449 case Corner_BottomRight:
450 *r = screen_desktop_layout.rows - 1 -
451 screen_desktop / screen_desktop_layout.columns;
452 *c = screen_desktop_layout.columns - 1 -
453 screen_desktop % screen_desktop_layout.columns;
454 break;
455 break;
456 }
457 case Orientation_Vert:
458 switch (screen_desktop_layout.start_corner) {
459 case Corner_TopLeft:
460 *r = screen_desktop % screen_desktop_layout.rows;
461 *c = screen_desktop / screen_desktop_layout.rows;
462 break;
463 case Corner_BottomLeft:
464 *r = screen_desktop_layout.rows - 1 -
465 screen_desktop % screen_desktop_layout.rows;
466 *c = screen_desktop / screen_desktop_layout.rows;
467 break;
468 break;
469 case Corner_TopRight:
470 *r = screen_desktop % screen_desktop_layout.rows;
471 *c = screen_desktop_layout.columns - 1 -
472 screen_desktop / screen_desktop_layout.rows;
473 break;
474 case Corner_BottomRight:
475 *r = screen_desktop_layout.rows - 1 -
476 screen_desktop % screen_desktop_layout.rows;
477 *c = screen_desktop_layout.columns - 1 -
478 screen_desktop / screen_desktop_layout.rows;
479 break;
480 break;
481 }
482 break;
483 }
484 }
485
486 static guint translate_row_col(guint r, guint c)
487 {
488 switch (screen_desktop_layout.orientation) {
489 case Orientation_Horz:
490 switch (screen_desktop_layout.start_corner) {
491 case Corner_TopLeft:
492 return r * screen_desktop_layout.columns + c;
493 case Corner_BottomLeft:
494 return (screen_desktop_layout.rows - 1 - r) *
495 screen_desktop_layout.columns + c;
496 case Corner_TopRight:
497 return r * screen_desktop_layout.columns +
498 (screen_desktop_layout.columns - 1 - c);
499 case Corner_BottomRight:
500 return (screen_desktop_layout.rows - 1 - r) *
501 screen_desktop_layout.columns +
502 (screen_desktop_layout.columns - 1 - c);
503 }
504 case Orientation_Vert:
505 switch (screen_desktop_layout.start_corner) {
506 case Corner_TopLeft:
507 return c * screen_desktop_layout.rows + r;
508 case Corner_BottomLeft:
509 return c * screen_desktop_layout.rows +
510 (screen_desktop_layout.rows - 1 - r);
511 case Corner_TopRight:
512 return (screen_desktop_layout.columns - 1 - c) *
513 screen_desktop_layout.rows + r;
514 case Corner_BottomRight:
515 return (screen_desktop_layout.columns - 1 - c) *
516 screen_desktop_layout.rows +
517 (screen_desktop_layout.rows - 1 - r);
518 }
519 }
520 g_assert_not_reached();
521 return 0;
522 }
523
524 void action_next_desktop_column(union ActionData *data)
525 {
526 guint r, c, d;
527
528 cur_row_col(&r, &c);
529 ++c;
530 d = translate_row_col(r, c);
531 if (d >= screen_num_desktops) {
532 if (!data->nextprevdesktop.wrap) return;
533 c = 0;
534 }
535 if (d >= screen_num_desktops)
536 ++c;
537 d = translate_row_col(r, c);
538 if (d < screen_num_desktops)
539 screen_set_desktop(d);
540 }
541
542 void action_previous_desktop_column(union ActionData *data)
543 {
544 guint r, c, d;
545
546 cur_row_col(&r, &c);
547 --c;
548 d = translate_row_col(r, c);
549 if (d >= screen_num_desktops) {
550 if (!data->nextprevdesktop.wrap) return;
551 c = screen_desktop_layout.columns - 1;
552 }
553 if (d >= screen_num_desktops)
554 --c;
555 d = translate_row_col(r, c);
556 if (d < screen_num_desktops)
557 screen_set_desktop(d);
558 }
559
560 void action_next_desktop_row(union ActionData *data)
561 {
562 guint r, c, d;
563
564 cur_row_col(&r, &c);
565 ++r;
566 d = translate_row_col(r, c);
567 if (d >= screen_num_desktops) {
568 if (!data->nextprevdesktop.wrap) return;
569 r = 0;
570 }
571 if (d >= screen_num_desktops)
572 ++r;
573 d = translate_row_col(r, c);
574 if (d < screen_num_desktops)
575 screen_set_desktop(d);
576 }
577
578 void action_previous_desktop_row(union ActionData *data)
579 {
580 guint r, c, d;
581
582 cur_row_col(&r, &c);
583 --r;
584 d = translate_row_col(r, c);
585 if (d >= screen_num_desktops) {
586 if (!data->nextprevdesktop.wrap) return;
587 c = screen_desktop_layout.rows - 1;
588 }
589 if (d >= screen_num_desktops)
590 --r;
591 d = translate_row_col(r, c);
592 if (d < screen_num_desktops)
593 screen_set_desktop(d);
594 }
595
596 void action_toggle_decorations(union ActionData *data)
597 {
598 Client *c = data->client.c;
599 c->disabled_decorations = c->disabled_decorations ? 0 : ~0;
600 client_setup_decor_and_functions(c);
601 }
602
603 void action_move(union ActionData *data)
604 {
605 Client *c = data->move.c;
606 int x = data->move.x;
607 int y = data->move.y;
608
609 if (!c || !client_normal(c)) return;
610
611 dispatch_move(c, &x, &y);
612
613 frame_frame_gravity(c->frame, &x, &y); /* get where the client should be */
614 client_configure(c, Corner_TopLeft, x, y, c->area.width, c->area.height,
615 TRUE, data->move.final);
616 }
617
618 void action_resize(union ActionData *data)
619 {
620 Client *c = data->resize.c;
621 int w = data->resize.x;
622 int h = data->resize.y;
623
624 if (!c || !client_normal(c)) return;
625
626 dispatch_resize(c, &w, &h, data->resize.corner);
627
628 w -= c->frame->size.left + c->frame->size.right;
629 h -= c->frame->size.top + c->frame->size.bottom;
630 client_configure(c, data->resize.corner, c->area.x, c->area.y, w, h,
631 TRUE, data->resize.final);
632 }
633
634 void action_restart(union ActionData *data)
635 {
636 ob_restart_path = data->execute.path;
637 ob_shutdown = ob_restart = TRUE;
638 }
639
640 void action_exit(union ActionData *data)
641 {
642 ob_shutdown = TRUE;
643 }
This page took 0.066872 seconds and 5 git commands to generate.