]> icculus.org git repositories - dana/openbox.git/blob - openbox/action.c
better comment parsing
[dana/openbox.git] / 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_new(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     /* deal with pointers */
26     if (a->func == action_execute || a->func == action_restart)
27         g_free(a->data.execute.path);
28
29     g_free(a);
30 }
31
32 void action_execute(union ActionData *data)
33 {
34     GError *e = NULL;
35     if (!g_spawn_command_line_async(data->execute.path, &e)) {
36         g_warning("failed to execute '%s': %s",
37                   data->execute.path, e->message);
38     }
39 }
40
41 void action_focus(union ActionData *data)
42 {
43     if (data->client.c)
44         client_focus(data->client.c);
45 }
46
47 void action_unfocus (union ActionData *data)
48 {
49     if (data->client.c)
50         client_unfocus(data->client.c);
51 }
52
53 void action_iconify(union ActionData *data)
54 {
55     if (data->client.c)
56         client_iconify(data->client.c, TRUE, TRUE);
57 }
58
59 void action_focusraise(union ActionData *data)
60 {
61     if (data->client.c) {
62         client_focus(data->client.c);
63         stacking_raise(data->client.c);
64     }
65 }
66
67 void action_raise(union ActionData *data)
68 {
69     if (data->client.c)
70         stacking_raise(data->client.c);
71 }
72
73 void action_lower(union ActionData *data)
74 {
75     if (data->client.c)
76         stacking_lower(data->client.c);
77 }
78
79 void action_close(union ActionData *data)
80 {
81     if (data->client.c)
82         client_close(data->client.c);
83 }
84
85 void action_kill(union ActionData *data)
86 {
87     if (data->client.c)
88         client_kill(data->client.c);
89 }
90
91 void action_shade(union ActionData *data)
92 {
93     if (data->client.c)
94         client_shade(data->client.c, TRUE);
95 }
96
97 void action_unshade(union ActionData *data)
98 {
99     if (data->client.c)
100         client_shade(data->client.c, FALSE);
101 }
102
103 void action_toggle_shade(union ActionData *data)
104 {
105     if (data->client.c)
106         client_shade(data->client.c, !data->client.c->shaded);
107 }
108
109 void action_toggle_omnipresent(union ActionData *data)
110
111     if (data->client.c)
112         client_set_desktop(data->client.c,
113                            data->client.c->desktop == DESKTOP_ALL ?
114                            screen_desktop : DESKTOP_ALL);
115 }
116
117 void action_move_relative(union ActionData *data)
118 {
119     Client *c = data->relative.c;
120     if (c)
121         client_configure(c, Corner_TopLeft,
122                          c->area.x + data->relative.dx,
123                          c->area.y + data->relative.dy,
124                          c->area.width, c->area.height, TRUE, TRUE);
125 }
126
127 void action_resize_relative(union ActionData *data)
128 {
129     Client *c = data->relative.c;
130     if (c)
131         client_configure(c, Corner_TopLeft, c->area.x, c->area.y,
132                          c->area.width + data->relative.dx,
133                          c->area.height + data->relative.dy, TRUE, TRUE);
134 }
135
136 void action_maximize_full(union ActionData *data)
137 {
138     if (data->client.c)
139         client_maximize(data->client.c, TRUE, 0, TRUE);
140 }
141
142 void action_unmaximize_full(union ActionData *data)
143 {
144     if (data->client.c)
145         client_maximize(data->client.c, FALSE, 0, TRUE);
146 }
147
148 void action_toggle_maximize_full(union ActionData *data)
149 {
150     if (data->client.c)
151         client_maximize(data->client.c,
152                         !(data->client.c->max_horz ||
153                           data->client.c->max_vert),
154                         0, TRUE);
155 }
156
157 void action_maximize_horz(union ActionData *data)
158 {
159     if (data->client.c)
160         client_maximize(data->client.c, TRUE, 1, TRUE);
161 }
162
163 void action_unmaximize_horz(union ActionData *data)
164 {
165     if (data->client.c)
166         client_maximize(data->client.c, FALSE, 1, TRUE);
167 }
168
169 void action_toggle_maximize_horz(union ActionData *data)
170 {
171     if (data->client.c)
172         client_maximize(data->client.c, !data->client.c->max_horz, 1, TRUE);
173 }
174
175 void action_maximize_vert(union ActionData *data)
176 {
177     if (data->client.c)
178         client_maximize(data->client.c, TRUE, 2, TRUE);
179 }
180
181 void action_unmaximize_vert(union ActionData *data)
182 {
183     if (data->client.c)
184         client_maximize(data->client.c, FALSE, 2, TRUE);
185 }
186
187 void action_toggle_maximize_vert(union ActionData *data)
188 {
189     if (data->client.c)
190         client_maximize(data->client.c, !data->client.c->max_vert, 2, TRUE);
191 }
192
193 void action_send_to_desktop(union ActionData *data)
194 {
195     if (data->sendto.c)
196         if (data->sendto.desktop < screen_num_desktops ||
197             data->sendto.desktop == DESKTOP_ALL)
198             client_set_desktop(data->sendto.c, data->sendto.desktop);
199 }
200
201 void action_send_to_next_desktop(union ActionData *data)
202 {
203     guint d;
204
205     if (!data->sendto.c) return;
206
207     d = screen_desktop + 1;
208     if (d >= screen_num_desktops) {
209         if (!data->sendtonextprev.wrap) return;
210         d = 0;
211     }
212     client_set_desktop(data->sendtonextprev.c, d);
213     if (data->sendtonextprev.follow) screen_set_desktop(d);
214 }
215
216 void action_send_to_previous_desktop(union ActionData *data)
217 {
218     guint d;
219
220     if (!data->sendto.c) return;
221
222     d = screen_desktop - 1;
223     if (d >= screen_num_desktops) {
224         if (!data->sendtonextprev.wrap) return;
225         d = screen_num_desktops - 1;
226     }
227     client_set_desktop(data->sendtonextprev.c, d);
228     if (data->sendtonextprev.follow) screen_set_desktop(d);
229 }
230
231 void action_desktop(union ActionData *data)
232 {
233     if (data->desktop.desk < screen_num_desktops ||
234         data->desktop.desk == DESKTOP_ALL)
235         screen_set_desktop(data->desktop.desk);
236 }
237
238 void action_next_desktop(union ActionData *data)
239 {
240     guint d;
241
242     d = screen_desktop + 1;
243     if (d >= screen_num_desktops) {
244         if (!data->nextprevdesktop.wrap) return;
245         d = 0;
246     }
247     screen_set_desktop(d);
248 }
249
250 void action_previous_desktop(union ActionData *data)
251 {
252     guint d;
253
254     d = screen_desktop - 1;
255     if (d >= screen_num_desktops) {
256         if (!data->nextprevdesktop.wrap) return;
257         d = screen_num_desktops - 1;
258     }
259     screen_set_desktop(d);
260 }
261
262 static void cur_row_col(guint *r, guint *c)
263 {
264     switch (screen_desktop_layout.orientation) {
265     case Orientation_Horz:
266         switch (screen_desktop_layout.start_corner) {
267         case Corner_TopLeft:
268             *r = screen_desktop / screen_desktop_layout.columns;
269             *c = screen_desktop % screen_desktop_layout.columns;
270             break;
271         case Corner_BottomLeft:
272             *r = screen_desktop_layout.rows - 1 -
273                 screen_desktop / screen_desktop_layout.columns;
274             *c = screen_desktop % screen_desktop_layout.columns;
275             break;
276         break;
277         case Corner_TopRight:
278             *r = screen_desktop / screen_desktop_layout.columns;
279             *c = screen_desktop_layout.columns - 1 -
280                 screen_desktop % screen_desktop_layout.columns;
281             break;
282         case Corner_BottomRight:
283             *r = screen_desktop_layout.rows - 1 -
284                 screen_desktop / screen_desktop_layout.columns;
285             *c = screen_desktop_layout.columns - 1 -
286                 screen_desktop % screen_desktop_layout.columns;
287             break;
288         break;
289         }
290     case Orientation_Vert:
291         switch (screen_desktop_layout.start_corner) {
292         case Corner_TopLeft:
293             *r = screen_desktop % screen_desktop_layout.rows;
294             *c = screen_desktop / screen_desktop_layout.rows;
295             break;
296         case Corner_BottomLeft:
297             *r = screen_desktop_layout.rows - 1 -
298                 screen_desktop % screen_desktop_layout.rows;
299             *c = screen_desktop / screen_desktop_layout.rows;
300             break;
301         break;
302         case Corner_TopRight:
303             *r = screen_desktop % screen_desktop_layout.rows;
304             *c = screen_desktop_layout.columns - 1 -
305                 screen_desktop / screen_desktop_layout.rows;
306             break;
307         case Corner_BottomRight:
308             *r = screen_desktop_layout.rows - 1 -
309                 screen_desktop % screen_desktop_layout.rows;
310             *c = screen_desktop_layout.columns - 1 -
311                 screen_desktop / screen_desktop_layout.rows;
312             break;
313         break;
314         }
315         break;
316     }
317 }
318
319 static guint translate_row_col(guint r, guint c)
320 {
321     switch (screen_desktop_layout.orientation) {
322     case Orientation_Horz:
323         switch (screen_desktop_layout.start_corner) {
324         case Corner_TopLeft:
325             return r * screen_desktop_layout.columns + c;
326         case Corner_BottomLeft:
327             return (screen_desktop_layout.rows - 1 - r) *
328                 screen_desktop_layout.columns + c;
329         case Corner_TopRight:
330             return r * screen_desktop_layout.columns +
331                 (screen_desktop_layout.columns - 1 - c);
332         case Corner_BottomRight:
333             return (screen_desktop_layout.rows - 1 - r) *
334                 screen_desktop_layout.columns +
335                 (screen_desktop_layout.columns - 1 - c);
336         }
337     case Orientation_Vert:
338         switch (screen_desktop_layout.start_corner) {
339         case Corner_TopLeft:
340             return c * screen_desktop_layout.rows + r;
341         case Corner_BottomLeft:
342             return c * screen_desktop_layout.rows +
343                 (screen_desktop_layout.rows - 1 - r);
344         case Corner_TopRight:
345             return (screen_desktop_layout.columns - 1 - c) *
346                 screen_desktop_layout.rows + r;
347         case Corner_BottomRight:
348             return (screen_desktop_layout.columns - 1 - c) *
349                 screen_desktop_layout.rows +
350                 (screen_desktop_layout.rows - 1 - r);
351         }
352     }
353     g_assert_not_reached();
354     return 0;
355 }
356
357 void action_next_desktop_column(union ActionData *data)
358 {
359     guint r, c, d;
360
361     cur_row_col(&r, &c);
362     ++c;
363     d = translate_row_col(r, c);
364     if (d >= screen_num_desktops) {
365         if (!data->nextprevdesktop.wrap) return;
366         c = 0;
367     }
368     if (d >= screen_num_desktops)
369         ++c;
370     d = translate_row_col(r, c);
371     if (d < screen_num_desktops)
372         screen_set_desktop(d);
373 }
374
375 void action_previous_desktop_column(union ActionData *data)
376 {
377     guint r, c, d;
378
379     cur_row_col(&r, &c);
380     --c;
381     d = translate_row_col(r, c);
382     if (d >= screen_num_desktops) {
383         if (!data->nextprevdesktop.wrap) return;
384         c = screen_desktop_layout.columns - 1;
385     }
386     if (d >= screen_num_desktops)
387         --c;
388     d = translate_row_col(r, c);
389     if (d < screen_num_desktops)
390         screen_set_desktop(d);
391 }
392
393 void action_next_desktop_row(union ActionData *data)
394 {
395     guint r, c, d;
396
397     cur_row_col(&r, &c);
398     ++r;
399     d = translate_row_col(r, c);
400     if (d >= screen_num_desktops) {
401         if (!data->nextprevdesktop.wrap) return;
402         r = 0;
403     }
404     if (d >= screen_num_desktops)
405         ++r;
406     d = translate_row_col(r, c);
407     if (d < screen_num_desktops)
408         screen_set_desktop(d);
409 }
410
411 void action_previous_desktop_row(union ActionData *data)
412 {
413     guint r, c, d;
414
415     cur_row_col(&r, &c);
416     --r;
417     d = translate_row_col(r, c);
418     if (d >= screen_num_desktops) {
419         if (!data->nextprevdesktop.wrap) return;
420         c = screen_desktop_layout.rows - 1;
421     }
422     if (d >= screen_num_desktops)
423         --r;
424     d = translate_row_col(r, c);
425     if (d < screen_num_desktops)
426         screen_set_desktop(d);
427 }
428
429 void action_toggle_decorations(union ActionData *data)
430 {
431     Client *c = data->client.c;
432     c->disabled_decorations = c->disabled_decorations ? 0 : ~0;
433     client_setup_decor_and_functions(c);
434 }
435
436 void action_move(union ActionData *data)
437 {
438     Client *c = data->move.c;
439     int x = data->move.x;
440     int y = data->move.y;
441
442     if (!c || !client_normal(c)) return;
443
444     dispatch_move(c, &x, &y);
445
446     frame_frame_gravity(c->frame, &x, &y); /* get where the client should be */
447     client_configure(c, Corner_TopLeft, x, y, c->area.width, c->area.height,
448                      TRUE, data->move.final);
449 }
450
451 void action_resize(union ActionData *data)
452 {
453     Client *c = data->resize.c;
454     int w = data->resize.x - c->frame->size.left - c->frame->size.right;
455     int h = data->resize.y - c->frame->size.top - c->frame->size.bottom;
456  
457     if (!c || !client_normal(c)) return;
458
459     /* XXX window snapping/struts */
460
461     client_configure(c, data->resize.corner, c->area.x, c->area.y, w, h,
462                      TRUE, data->resize.final);
463 }
464
465 void action_restart(union ActionData *data)
466 {
467     ob_restart_path = data->execute.path;
468     ob_shutdown = ob_restart = TRUE;
469 }
470
471 void action_exit(union ActionData *data)
472 {
473     ob_shutdown = TRUE;
474 }