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