1 #include "openbox/action.h"
2 #include "openbox/action_value.h"
3 #include "openbox/screen.h"
4 #include "openbox/client.h"
5 #include "openbox/openbox.h"
6 #include "obt/keyboard.h"
33 static gpointer setup_go_func(GHashTable *config,
34 ObActionIPreFunc *pre,
35 ObActionIInputFunc *input,
36 ObActionICancelFunc *cancel,
37 ObActionIPostFunc *post);
38 static gpointer setup_send_func(GHashTable *config,
39 ObActionIPreFunc *pre,
40 ObActionIInputFunc *input,
41 ObActionICancelFunc *cancel,
42 ObActionIPostFunc *post);
43 static void free_func(gpointer o);
44 static gboolean run_func(ObActionData *data, gpointer options);
46 static gboolean i_pre_func(guint state, gpointer options);
47 static gboolean i_input_func(guint initial_state,
52 static void i_post_func(gpointer options);
55 void action_desktop_startup(void)
57 action_register_i("GoToDesktop", setup_go_func, free_func, run_func);
58 action_register_i("SendToDesktop", setup_send_func, free_func, run_func);
61 static gpointer setup_func(GHashTable *config,
62 ObActionIPreFunc *pre,
63 ObActionIInputFunc *input,
64 ObActionICancelFunc *cancel,
65 ObActionIPostFunc *post)
70 o = g_slice_new0(Options);
71 /* don't go anywhere if there are no options given */
73 o->u.abs.desktop = screen_desktop;
74 /* wrap by default - it's handy! */
77 v = g_hash_table_lookup(config, "to");
78 if (v && action_value_is_string(v)) {
79 const gchar *s = action_value_string(v);
80 if (!g_ascii_strcasecmp(s, "last"))
82 else if (!g_ascii_strcasecmp(s, "current"))
84 else if (!g_ascii_strcasecmp(s, "next")) {
86 o->u.rel.linear = TRUE;
87 o->u.rel.dir = OB_DIRECTION_EAST;
89 else if (!g_ascii_strcasecmp(s, "previous")) {
91 o->u.rel.linear = TRUE;
92 o->u.rel.dir = OB_DIRECTION_WEST;
94 else if (!g_ascii_strcasecmp(s, "north") ||
95 !g_ascii_strcasecmp(s, "up")) {
97 o->u.rel.dir = OB_DIRECTION_NORTH;
99 else if (!g_ascii_strcasecmp(s, "south") ||
100 !g_ascii_strcasecmp(s, "down")) {
102 o->u.rel.dir = OB_DIRECTION_SOUTH;
104 else if (!g_ascii_strcasecmp(s, "west") ||
105 !g_ascii_strcasecmp(s, "left")) {
107 o->u.rel.dir = OB_DIRECTION_WEST;
109 else if (!g_ascii_strcasecmp(s, "east") ||
110 !g_ascii_strcasecmp(s, "right")) {
112 o->u.rel.dir = OB_DIRECTION_EAST;
116 o->u.abs.desktop = atoi(s) - 1;
120 v = g_hash_table_lookup(config, "wrap");
121 if (v && action_value_is_string(v))
122 o->u.rel.wrap = action_value_bool(v);
128 static gpointer setup_go_func(GHashTable *config,
129 ObActionIPreFunc *pre,
130 ObActionIInputFunc *input,
131 ObActionICancelFunc *cancel,
132 ObActionIPostFunc *post)
136 o = setup_func(config, pre, input, cancel, post);
137 if (o->type == RELATIVE) {
138 o->interactive = TRUE;
140 *input = i_input_func;
147 static gpointer setup_send_func(GHashTable *config,
148 ObActionIPreFunc *pre,
149 ObActionIInputFunc *input,
150 ObActionICancelFunc *cancel,
151 ObActionIPostFunc *post)
156 o = setup_func(config, pre, input, cancel, post);
160 v = g_hash_table_lookup(config, "follow");
161 if (v && action_value_is_string(v))
162 o->follow = action_value_bool(v);
164 if (o->type == RELATIVE && o->follow) {
165 o->interactive = TRUE;
167 *input = i_input_func;
174 static void free_func(gpointer o)
176 g_slice_free(Options, o);
179 static gboolean run_func(ObActionData *data, gpointer options)
181 Options *o = options;
186 d = screen_last_desktop;
192 d = o->u.abs.desktop;
195 d = screen_find_desktop(screen_desktop,
196 o->u.rel.dir, o->u.rel.wrap, o->u.rel.linear);
199 g_assert_not_reached();
202 if (d < screen_num_desktops &&
203 (d != screen_desktop ||
204 (data->client && data->client->desktop != screen_desktop))) {
207 action_client_move(data, TRUE);
208 if (o->send && data->client && client_normal(data->client)) {
209 client_set_desktop(data->client, d, o->follow, FALSE);
214 screen_set_desktop(d, TRUE);
216 client_bring_helper_windows(data->client);
219 action_client_move(data, FALSE);
222 return o->interactive;
225 static gboolean i_input_func(guint initial_state,
231 guint mods, initial_mods;
233 initial_mods = obt_keyboard_only_modmasks(initial_state);
234 mods = obt_keyboard_only_modmasks(e->xkey.state);
235 if (e->type == KeyRelease) {
236 /* remove from the state the mask of the modifier key being
237 released, if it is a modifier key being released that is */
238 mods &= ~obt_keyboard_keyevent_to_modmask(e);
241 if (e->type == KeyPress) {
242 KeySym sym = obt_keyboard_keypress_to_keysym(e);
244 /* Escape cancels no matter what */
245 if (sym == XK_Escape)
248 /* There were no modifiers and they pressed enter */
249 else if ((sym == XK_Return || sym == XK_KP_Enter) && !initial_mods)
252 /* They released the modifiers */
253 else if (e->type == KeyRelease && initial_mods && !(mods & initial_mods))
261 static gboolean i_pre_func(guint initial_state, gpointer options)
263 guint initial_mods = obt_keyboard_only_modmasks(initial_state);
265 Options *o = options;
266 o->interactive = FALSE;
270 screen_show_desktop_popup(screen_desktop, TRUE);
275 static void i_post_func(gpointer options)
277 screen_hide_desktop_popup();