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