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