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