]> icculus.org git repositories - mikachu/openbox.git/blob - openbox/actions/desktop.c
Allow moving to the current desktop, to show the desktop popup
[mikachu/openbox.git] / openbox / actions / desktop.c
1 #include "openbox/actions.h"
2 #include "openbox/screen.h"
3 #include "openbox/client.h"
4 #include "openbox/openbox.h"
5 #include "obt/keyboard.h"
6
7 typedef enum {
8     LAST,
9     CURRENT,
10     RELATIVE,
11     ABSOLUTE
12 } SwitchType;
13
14 typedef struct {
15     SwitchType type;
16     union {
17         struct {
18             guint desktop;
19         } abs;
20
21         struct {
22             gboolean linear;
23             gboolean wrap;
24             ObDirection dir;
25         } rel;
26     } u;
27     gboolean send;
28     gboolean follow;
29 } Options;
30
31 static gpointer setup_func(xmlNodePtr node);
32 static gpointer setup_send_func(xmlNodePtr node);
33 static void free_func(gpointer o);
34 static gboolean run_func(ObActionsData *data, gpointer options);
35
36 /* 3.4-compatibility */
37 static gpointer setup_go_last_func(xmlNodePtr node);
38 static gpointer setup_send_last_func(xmlNodePtr node);
39 static gpointer setup_go_abs_func(xmlNodePtr node);
40 static gpointer setup_go_next_func(xmlNodePtr node);
41 static gpointer setup_send_next_func(xmlNodePtr node);
42 static gpointer setup_go_prev_func(xmlNodePtr node);
43 static gpointer setup_send_prev_func(xmlNodePtr node);
44 static gpointer setup_go_left_func(xmlNodePtr node);
45 static gpointer setup_send_left_func(xmlNodePtr node);
46 static gpointer setup_go_right_func(xmlNodePtr node);
47 static gpointer setup_send_right_func(xmlNodePtr node);
48 static gpointer setup_go_up_func(xmlNodePtr node);
49 static gpointer setup_send_up_func(xmlNodePtr node);
50 static gpointer setup_go_down_func(xmlNodePtr node);
51 static gpointer setup_send_down_func(xmlNodePtr node);
52
53 void action_desktop_startup(void)
54 {
55     actions_register("GoToDesktop", setup_func, free_func, run_func);
56     actions_register("SendToDesktop", setup_send_func, free_func, run_func);
57     /* 3.4-compatibility */
58     actions_register("DesktopLast", setup_go_last_func, free_func, run_func);
59     actions_register("SendToDesktopLast", setup_send_last_func,
60                      free_func, run_func);
61     actions_register("Desktop", setup_go_abs_func, free_func, run_func);
62     actions_register("DesktopNext", setup_go_next_func, free_func, run_func);
63     actions_register("SendToDesktopNext", setup_send_next_func,
64                      free_func, run_func);
65     actions_register("DesktopPrevious", setup_go_prev_func,
66                      free_func, run_func);
67     actions_register("SendToDesktopPrevious", setup_send_prev_func,
68                      free_func, run_func);
69     actions_register("DesktopLeft", setup_go_left_func, free_func, run_func);
70     actions_register("SendToDesktopLeft", setup_send_left_func,
71                      free_func, run_func);
72     actions_register("DesktopRight", setup_go_right_func,
73                      free_func, run_func);
74     actions_register("SendToDesktopRight", setup_send_right_func,
75                      free_func, run_func);
76     actions_register("DesktopUp", setup_go_up_func, free_func, run_func);
77     actions_register("SendToDesktopUp", setup_send_up_func,
78                      free_func, run_func);
79     actions_register("DesktopDown", setup_go_down_func, free_func, run_func);
80     actions_register("SendToDesktopDown", setup_send_down_func,
81                      free_func, run_func);
82 }
83
84 static gpointer setup_func(xmlNodePtr node)
85 {
86     xmlNodePtr n;
87     Options *o;
88
89     o = g_slice_new0(Options);
90     /* don't go anywhere if there are no options given */
91     o->type = ABSOLUTE;
92     o->u.abs.desktop = screen_desktop;
93     /* wrap by default - it's handy! */
94     o->u.rel.wrap = TRUE;
95
96     if ((n = obt_xml_find_node(node, "to"))) {
97         gchar *s = obt_xml_node_string(n);
98         if (!g_ascii_strcasecmp(s, "last"))
99             o->type = LAST;
100         else if (!g_ascii_strcasecmp(s, "current"))
101             o->type = CURRENT;
102         else if (!g_ascii_strcasecmp(s, "next")) {
103             o->type = RELATIVE;
104             o->u.rel.linear = TRUE;
105             o->u.rel.dir = OB_DIRECTION_EAST;
106         }
107         else if (!g_ascii_strcasecmp(s, "previous")) {
108             o->type = RELATIVE;
109             o->u.rel.linear = TRUE;
110             o->u.rel.dir = OB_DIRECTION_WEST;
111         }
112         else if (!g_ascii_strcasecmp(s, "north") ||
113                  !g_ascii_strcasecmp(s, "up")) {
114             o->type = RELATIVE;
115             o->u.rel.dir = OB_DIRECTION_NORTH;
116         }
117         else if (!g_ascii_strcasecmp(s, "south") ||
118                  !g_ascii_strcasecmp(s, "down")) {
119             o->type = RELATIVE;
120             o->u.rel.dir = OB_DIRECTION_SOUTH;
121         }
122         else if (!g_ascii_strcasecmp(s, "west") ||
123                  !g_ascii_strcasecmp(s, "left")) {
124             o->type = RELATIVE;
125             o->u.rel.dir = OB_DIRECTION_WEST;
126         }
127         else if (!g_ascii_strcasecmp(s, "east") ||
128                  !g_ascii_strcasecmp(s, "right")) {
129             o->type = RELATIVE;
130             o->u.rel.dir = OB_DIRECTION_EAST;
131         }
132         else {
133             o->type = ABSOLUTE;
134             o->u.abs.desktop = atoi(s) - 1;
135         }
136         g_free(s);
137     }
138
139     if ((n = obt_xml_find_node(node, "wrap")))
140         o->u.rel.wrap = obt_xml_node_bool(n);
141
142     return o;
143 }
144
145 static gpointer setup_send_func(xmlNodePtr node)
146 {
147     xmlNodePtr n;
148     Options *o;
149
150     o = setup_func(node);
151     if ((n = obt_xml_find_node(node, "desktop"))) {
152         /* 3.4 compatibility */
153         o->u.abs.desktop = obt_xml_node_int(n) - 1;
154         o->type = ABSOLUTE;
155     }
156     o->send = TRUE;
157     o->follow = TRUE;
158
159     if ((n = obt_xml_find_node(node, "follow")))
160         o->follow = obt_xml_node_bool(n);
161
162     return o;
163 }
164
165 static void free_func(gpointer o)
166 {
167     g_slice_free(Options, o);
168 }
169
170 static gboolean run_func(ObActionsData *data, gpointer options)
171 {
172     Options *o = options;
173     guint d;
174
175     switch (o->type) {
176     case LAST:
177         d = screen_last_desktop;
178         break;
179     case CURRENT:
180         d = screen_desktop;
181         break;
182     case ABSOLUTE:
183         d = o->u.abs.desktop;
184         break;
185     case RELATIVE:
186         d = screen_find_desktop(screen_desktop,
187                                 o->u.rel.dir, o->u.rel.wrap, o->u.rel.linear);
188         break;
189     default:
190         g_assert_not_reached();
191     }
192
193     if (d < screen_num_desktops) {
194         gboolean go = TRUE;
195
196         actions_client_move(data, TRUE);
197         if (o->send && data->client && client_normal(data->client)) {
198             client_set_desktop(data->client, d, o->follow, FALSE);
199             go = o->follow;
200         }
201
202         if (go) {
203             screen_set_desktop(d, TRUE);
204             if (data->client)
205                 client_bring_helper_windows(data->client);
206         }
207
208         actions_client_move(data, FALSE);
209     }
210
211     return FALSE;
212 }
213
214 /* 3.4-compatilibity */
215 static gpointer setup_follow(xmlNodePtr node)
216 {
217     xmlNodePtr n;
218     Options *o = g_slice_new0(Options);
219     o->send = TRUE;
220     o->follow = TRUE;
221     if ((n = obt_xml_find_node(node, "follow")))
222         o->follow = obt_xml_node_bool(n);
223     return o;
224 }
225
226 static gpointer setup_go_last_func(xmlNodePtr node)
227 {
228     Options *o = g_slice_new0(Options);
229     o->type = LAST;
230     return o;
231 }
232
233 static gpointer setup_send_last_func(xmlNodePtr node)
234 {
235     Options *o = setup_follow(node);
236     o->type = LAST;
237     return o;
238 }
239
240 static gpointer setup_go_abs_func(xmlNodePtr node)
241 {
242     xmlNodePtr n;
243     Options *o = g_slice_new0(Options);
244     o->type = ABSOLUTE;
245     if ((n = obt_xml_find_node(node, "desktop")))
246         o->u.abs.desktop = obt_xml_node_int(n) - 1;
247     else
248         o->u.abs.desktop = screen_desktop;
249     return o;
250 }
251
252 static void setup_rel(Options *o, xmlNodePtr node, gboolean lin,
253                       ObDirection dir)
254 {
255     xmlNodePtr n;
256
257     o->type = RELATIVE;
258     o->u.rel.linear = lin;
259     o->u.rel.dir = dir;
260     o->u.rel.wrap = TRUE;
261
262     if ((n = obt_xml_find_node(node, "wrap")))
263         o->u.rel.wrap = obt_xml_node_bool(n);
264 }
265
266 static gpointer setup_go_next_func(xmlNodePtr node)
267 {
268     Options *o = g_slice_new0(Options);
269     setup_rel(o, node, TRUE, OB_DIRECTION_EAST);
270     return o;
271 }
272
273 static gpointer setup_send_next_func(xmlNodePtr node)
274 {
275     Options *o = setup_follow(node);
276     setup_rel(o, node, TRUE, OB_DIRECTION_EAST);
277     return o;
278 }
279
280 static gpointer setup_go_prev_func(xmlNodePtr node)
281 {
282     Options *o = g_slice_new0(Options);
283     setup_rel(o, node, TRUE, OB_DIRECTION_WEST);
284     return o;
285 }
286
287 static gpointer setup_send_prev_func(xmlNodePtr node)
288 {
289     Options *o = setup_follow(node);
290     setup_rel(o, node, TRUE, OB_DIRECTION_WEST);
291     return o;
292 }
293
294 static gpointer setup_go_left_func(xmlNodePtr node)
295 {
296     Options *o = g_slice_new0(Options);
297     setup_rel(o, node, FALSE, OB_DIRECTION_WEST);
298     return o;
299 }
300
301 static gpointer setup_send_left_func(xmlNodePtr node)
302 {
303     Options *o = setup_follow(node);
304     setup_rel(o, node, FALSE, OB_DIRECTION_WEST);
305     return o;
306 }
307
308 static gpointer setup_go_right_func(xmlNodePtr node)
309 {
310     Options *o = g_slice_new0(Options);
311     setup_rel(o, node, FALSE, OB_DIRECTION_EAST);
312     return o;
313 }
314
315 static gpointer setup_send_right_func(xmlNodePtr node)
316 {
317     Options *o = setup_follow(node);
318     setup_rel(o, node, FALSE, OB_DIRECTION_EAST);
319     return o;
320 }
321
322 static gpointer setup_go_up_func(xmlNodePtr node)
323 {
324     Options *o = g_slice_new0(Options);
325     setup_rel(o, node, FALSE, OB_DIRECTION_NORTH);
326     return o;
327 }
328
329 static gpointer setup_send_up_func(xmlNodePtr node)
330 {
331     Options *o = setup_follow(node);
332     setup_rel(o, node, FALSE, OB_DIRECTION_NORTH);
333     return o;
334 }
335
336 static gpointer setup_go_down_func(xmlNodePtr node)
337 {
338     Options *o = g_slice_new0(Options);
339     setup_rel(o, node, FALSE, OB_DIRECTION_SOUTH);
340     return o;
341 }
342
343 static gpointer setup_send_down_func(xmlNodePtr node)
344 {
345     Options *o = setup_follow(node);
346     setup_rel(o, node, FALSE, OB_DIRECTION_SOUTH);
347     return o;
348 }