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