add actions for key/mouse bindings etc
[mikachu/openbox.git] / openbox / action.c
1 #include "client.h"
2 #include "stacking.h"
3 #include "screen.h"
4
5 #include <glib.h>
6
7 void action_execute(char *path)
8 {
9     GError *e;
10     if (!g_spawn_command_line_async(path, &e)) {
11         g_warning("failed to execute '%s': %s", path, e->message);
12     }
13 }
14
15 void action_iconify(Client *c)
16 {
17     client_iconify(c, TRUE, TRUE);
18 }
19
20 void action_raise(Client *c)
21 {
22     stacking_raise(c);
23 }
24
25 void action_lower(Client *c)
26 {
27     stacking_lower(c);
28 }
29
30 void action_close(Client *c)
31 {
32     client_close(c);
33 }
34
35 void action_shade(Client *c)
36 {
37     client_shade(c, TRUE);
38 }
39
40 void action_unshade(Client *c)
41 {
42     client_shade(c, FALSE);
43 }
44
45 void action_toggle_shade(Client *c)
46 {
47     client_shade(c, !c->shaded);
48 }
49
50 void action_toggle_omnipresent(Client *c)
51 {
52     client_set_desktop(c, c->desktop == DESKTOP_ALL ?
53                        screen_desktop : DESKTOP_ALL);
54 }
55
56 void action_move_relative(Client *c, int dx, int dy)
57 {
58     client_configure(c, Corner_TopLeft, c->area.x + dx, c->area.y + dy,
59                      c->area.width, c->area.height, TRUE, TRUE);
60 }
61
62 void action_resize_relative(Client *c, int dx, int dy)
63 {
64     client_configure(c, Corner_TopLeft, c->area.x, c->area.y,
65                      c->area.width + dx, c->area.height + dy, TRUE, TRUE);
66 }
67
68 void action_maximize_full(Client *c)
69 {
70     client_maximize(c, TRUE, 0, TRUE);
71 }
72
73 void action_unmaximize_full(Client *c)
74 {
75     client_maximize(c, FALSE, 0, TRUE);
76 }
77
78 void action_toggle_maximize_full(Client *c)
79 {
80     client_maximize(c, !(c->max_horz || c->max_vert), 0, TRUE);
81 }
82
83 void action_maximize_horz(Client *c)
84 {
85     client_maximize(c, TRUE, 1, TRUE);
86 }
87
88 void action_unmaximize_horz(Client *c)
89 {
90     client_maximize(c, FALSE, 1, TRUE);
91 }
92
93 void action_toggle_maximize_horz(Client *c)
94 {
95     client_maximize(c, !c->max_horz, 1, TRUE);
96 }
97
98 void action_maximize_vert(Client *c)
99 {
100     client_maximize(c, TRUE, 2, TRUE);
101 }
102
103 void action_unmaximize_vert(Client *c)
104 {
105     client_maximize(c, FALSE, 2, TRUE);
106 }
107
108 void action_toggle_maximize_vert(Client *c)
109 {
110     client_maximize(c, !c->max_vert, 2, TRUE);
111 }
112
113 void action_send_to_desktop(Client *c, guint desktop)
114 {
115     if (desktop < screen_num_desktops || desktop == DESKTOP_ALL)
116         client_set_desktop(c, desktop);
117 }
118
119 void action_send_to_next_desktop(Client *c, gboolean wrap, gboolean follow)
120 {
121     guint d;
122
123     d = screen_desktop + 1;
124     if (d >= screen_num_desktops) {
125         if (!wrap) return;
126         d = 0;
127     }
128     client_set_desktop(c, d);
129     if (follow) screen_set_desktop(d);
130 }
131
132 void action_send_to_previous_desktop(Client *c, gboolean wrap, gboolean follow)
133 {
134     guint d;
135
136     d = screen_desktop - 1;
137     if (d >= screen_num_desktops) {
138         if (!wrap) return;
139         d = screen_num_desktops - 1;
140     }
141     client_set_desktop(c, d);
142     if (follow) screen_set_desktop(d);
143 }
144
145 void action_desktop(guint desktop)
146 {
147     if (desktop < screen_num_desktops || desktop == DESKTOP_ALL)
148         screen_set_desktop(desktop);
149 }
150
151 void action_next_desktop(gboolean wrap)
152 {
153     guint d;
154
155     d = screen_desktop + 1;
156     if (d >= screen_num_desktops) {
157         if (!wrap) return;
158         d = 0;
159     }
160     screen_set_desktop(d);
161 }
162
163 void action_previous_desktop(gboolean wrap)
164 {
165     guint d;
166
167     d = screen_desktop - 1;
168     if (d >= screen_num_desktops) {
169         if (!wrap) return;
170         d = screen_num_desktops - 1;
171     }
172     screen_set_desktop(d);
173 }
174
175 static void cur_row_col(guint *r, guint *c)
176 {
177     switch (screen_desktop_layout.orientation) {
178     case Orientation_Horz:
179         switch (screen_desktop_layout.start_corner) {
180         case Corner_TopLeft:
181             *r = screen_desktop / screen_desktop_layout.columns;
182             *c = screen_desktop % screen_desktop_layout.columns;
183             break;
184         case Corner_BottomLeft:
185             *r = screen_desktop_layout.rows - 1 -
186                 screen_desktop / screen_desktop_layout.columns;
187             *c = screen_desktop % screen_desktop_layout.columns;
188             break;
189         break;
190         case Corner_TopRight:
191             *r = screen_desktop / screen_desktop_layout.columns;
192             *c = screen_desktop_layout.columns - 1 -
193                 screen_desktop % screen_desktop_layout.columns;
194             break;
195         case Corner_BottomRight:
196             *r = screen_desktop_layout.rows - 1 -
197                 screen_desktop / screen_desktop_layout.columns;
198             *c = screen_desktop_layout.columns - 1 -
199                 screen_desktop % screen_desktop_layout.columns;
200             break;
201         break;
202         }
203     case Orientation_Vert:
204         switch (screen_desktop_layout.start_corner) {
205         case Corner_TopLeft:
206             *r = screen_desktop % screen_desktop_layout.rows;
207             *c = screen_desktop / screen_desktop_layout.rows;
208             break;
209         case Corner_BottomLeft:
210             *r = screen_desktop_layout.rows - 1 -
211                 screen_desktop % screen_desktop_layout.rows;
212             *c = screen_desktop / screen_desktop_layout.rows;
213             break;
214         break;
215         case Corner_TopRight:
216             *r = screen_desktop % screen_desktop_layout.rows;
217             *c = screen_desktop_layout.columns - 1 -
218                 screen_desktop / screen_desktop_layout.rows;
219             break;
220         case Corner_BottomRight:
221             *r = screen_desktop_layout.rows - 1 -
222                 screen_desktop % screen_desktop_layout.rows;
223             *c = screen_desktop_layout.columns - 1 -
224                 screen_desktop / screen_desktop_layout.rows;
225             break;
226         break;
227         }
228         break;
229     }
230 }
231
232 static guint translate_row_col(guint r, guint c)
233 {
234     switch (screen_desktop_layout.orientation) {
235     case Orientation_Horz:
236         switch (screen_desktop_layout.start_corner) {
237         case Corner_TopLeft:
238             return r * screen_desktop_layout.columns + c;
239         case Corner_BottomLeft:
240             return (screen_desktop_layout.rows - 1 - r) *
241                 screen_desktop_layout.columns + c;
242         case Corner_TopRight:
243             return r * screen_desktop_layout.columns +
244                 (screen_desktop_layout.columns - 1 - c);
245         case Corner_BottomRight:
246             return (screen_desktop_layout.rows - 1 - r) *
247                 screen_desktop_layout.columns +
248                 (screen_desktop_layout.columns - 1 - c);
249         }
250     case Orientation_Vert:
251         switch (screen_desktop_layout.start_corner) {
252         case Corner_TopLeft:
253             return c * screen_desktop_layout.rows + r;
254         case Corner_BottomLeft:
255             return c * screen_desktop_layout.rows +
256                 (screen_desktop_layout.rows - 1 - r);
257         case Corner_TopRight:
258             return (screen_desktop_layout.columns - 1 - c) *
259                 screen_desktop_layout.rows + r;
260         case Corner_BottomRight:
261             return (screen_desktop_layout.columns - 1 - c) *
262                 screen_desktop_layout.rows +
263                 (screen_desktop_layout.rows - 1 - r);
264         }
265     }
266     g_assert_not_reached();
267     return 0;
268 }
269
270 void action_next_desktop_column(gboolean wrap)
271 {
272     guint r, c, d;
273
274     cur_row_col(&r, &c);
275     ++c;
276     d = translate_row_col(r, c);
277     if (d >= screen_num_desktops) {
278         if (!wrap) return;
279         c = 0;
280     }
281     if (d >= screen_num_desktops)
282         ++c;
283     d = translate_row_col(r, c);
284     if (d < screen_num_desktops)
285         screen_set_desktop(d);
286 }
287
288 void action_previous_desktop_column(gboolean wrap)
289 {
290     guint r, c, d;
291
292     cur_row_col(&r, &c);
293     --c;
294     d = translate_row_col(r, c);
295     if (d >= screen_num_desktops) {
296         if (!wrap) return;
297         c = screen_desktop_layout.columns - 1;
298     }
299     if (d >= screen_num_desktops)
300         --c;
301     d = translate_row_col(r, c);
302     if (d < screen_num_desktops)
303         screen_set_desktop(d);
304 }
305
306 void action_next_desktop_row(gboolean wrap)
307 {
308     guint r, c, d;
309
310     cur_row_col(&r, &c);
311     ++r;
312     d = translate_row_col(r, c);
313     if (d >= screen_num_desktops) {
314         if (!wrap) return;
315         r = 0;
316     }
317     if (d >= screen_num_desktops)
318         ++r;
319     d = translate_row_col(r, c);
320     if (d < screen_num_desktops)
321         screen_set_desktop(d);
322 }
323
324 void action_previous_desktop_row(gboolean wrap)
325 {
326     guint r, c, d;
327
328     cur_row_col(&r, &c);
329     --r;
330     d = translate_row_col(r, c);
331     if (d >= screen_num_desktops) {
332         if (!wrap) return;
333         c = screen_desktop_layout.rows - 1;
334     }
335     if (d >= screen_num_desktops)
336         --r;
337     d = translate_row_col(r, c);
338     if (d < screen_num_desktops)
339         screen_set_desktop(d);
340 }
341
342 void action_toggle_decorations(Client *c)
343 {
344     c->disabled_decorations = c->disabled_decorations ? 0 : ~0;
345     client_setup_decor_and_functions(c);
346 }