]> icculus.org git repositories - mikachu/openbox.git/blob - openbox/actions/desktop.c
Merge branch 'work' into wip/mikabox
[mikachu/openbox.git] / openbox / actions / desktop.c
1 #include "openbox/actions.h"
2 #include "openbox/screen.h"
3 #include "openbox/client.h"
4 #include <glib.h>
5
6 typedef enum {
7     LAST,
8     CURRENT,
9     RELATIVE,
10     ABSOLUTE
11 } SwitchType;
12
13 typedef struct {
14     SwitchType type;
15     union {
16         struct {
17             guint desktop;
18         } abs;
19
20         struct {
21             gboolean linear;
22             gboolean wrap;
23             ObDirection dir;
24         } rel;
25     };
26     gboolean send;
27     gboolean follow;
28 } Options;
29
30 static gpointer setup_go_func(xmlNodePtr node);
31 static gpointer setup_send_func(xmlNodePtr node);
32 static gboolean run_func(ObActionsData *data, gpointer options);
33
34 void action_desktop_startup(void)
35 {
36     actions_register("GoToDesktop", setup_go_func, g_free, run_func,
37                      NULL, NULL);
38     actions_register("SendToDesktop", setup_send_func, g_free, run_func,
39                      NULL, NULL);
40 }
41
42 static gpointer setup_go_func(xmlNodePtr node)
43 {
44     xmlNodePtr n;
45     Options *o;
46
47     o = g_new0(Options, 1);
48     /* don't go anywhere if theres no options given */
49     o->type = ABSOLUTE;
50     o->abs.desktop = screen_desktop;
51     /* wrap by default - it's handy! */
52     o->rel.wrap = TRUE;
53
54     if ((n = obt_parse_find_node(node, "to"))) {
55         gchar *s = obt_parse_node_string(n);
56         if (!g_ascii_strcasecmp(s, "last"))
57             o->type = LAST;
58         else if (!g_ascii_strcasecmp(s, "current"))
59             o->type = CURRENT;
60         else if (!g_ascii_strcasecmp(s, "next")) {
61             o->type = RELATIVE;
62             o->rel.linear = TRUE;
63             o->rel.dir = OB_DIRECTION_EAST;
64         }
65         else if (!g_ascii_strcasecmp(s, "previous")) {
66             o->type = RELATIVE;
67             o->rel.linear = TRUE;
68             o->rel.dir = OB_DIRECTION_WEST;
69         }
70         else if (!g_ascii_strcasecmp(s, "north") ||
71                  !g_ascii_strcasecmp(s, "up")) {
72             o->type = RELATIVE;
73             o->rel.dir = OB_DIRECTION_NORTH;
74         }
75         else if (!g_ascii_strcasecmp(s, "south") ||
76                  !g_ascii_strcasecmp(s, "down")) {
77             o->type = RELATIVE;
78             o->rel.dir = OB_DIRECTION_SOUTH;
79         }
80         else if (!g_ascii_strcasecmp(s, "west") ||
81                  !g_ascii_strcasecmp(s, "left")) {
82             o->type = RELATIVE;
83             o->rel.dir = OB_DIRECTION_WEST;
84         }
85         else if (!g_ascii_strcasecmp(s, "east") ||
86                  !g_ascii_strcasecmp(s, "right")) {
87             o->type = RELATIVE;
88             o->rel.dir = OB_DIRECTION_EAST;
89         }
90         else {
91             o->type = ABSOLUTE;
92             o->abs.desktop = atoi(s) - 1;
93         }
94         g_free(s);
95     }
96
97     if ((n = obt_parse_find_node(node, "wrap")))
98         o->rel.wrap = obt_parse_node_bool(n);
99
100     return o;
101 }
102
103 static gpointer setup_send_func(xmlNodePtr node)
104 {
105     xmlNodePtr n;
106     Options *o;
107
108     o = setup_go_func(node);
109     o->send = TRUE;
110     o->follow = TRUE;
111
112     if ((n = obt_parse_find_node(node, "follow")))
113         o->follow = obt_parse_node_bool(n);
114
115     return o;
116 }
117
118 /* Always return FALSE because its not interactive */
119 static gboolean run_func(ObActionsData *data, gpointer options)
120 {
121     Options *o = options;
122     guint d;
123
124     switch (o->type) {
125     case LAST:
126         d = screen_last_desktop;
127         break;
128     case CURRENT:
129         d = screen_desktop;
130         break;
131     case ABSOLUTE:
132         d = o->abs.desktop;
133         break;
134     case RELATIVE:
135         d = screen_find_desktop(screen_desktop,
136                                 o->rel.dir, o->rel.wrap, o->rel.linear);
137         break;
138     }
139
140     if (d < screen_num_desktops &&
141         (d != screen_desktop ||
142          (data->client && data->client->desktop != screen_desktop))) {
143         gboolean go = TRUE;
144
145         actions_client_move(data, TRUE);
146         if (o->send && data->client && client_normal(data->client)) {
147             client_set_desktop(data->client, d, o->follow, FALSE);
148             go = o->follow;
149         }
150
151         if (go) {
152             screen_set_desktop(d, TRUE);
153             if (data->client)
154                 client_bring_helper_windows(data->client);
155         }
156
157         actions_client_move(data, FALSE);
158     }
159     return FALSE;
160 }