1 #include "openbox/action.h"
2 #include "openbox/action_list_run.h"
3 #include "openbox/action_value.h"
4 #include "openbox/screen.h"
5 #include "openbox/client.h"
6 #include "openbox/openbox.h"
7 #include "obt/keyboard.h"
34 static gpointer setup_go_func(GHashTable *config,
35 ObActionIPreFunc *pre,
36 ObActionIInputFunc *input,
37 ObActionICancelFunc *cancel,
38 ObActionIPostFunc *post);
39 static gpointer setup_send_func(GHashTable *config,
40 ObActionIPreFunc *pre,
41 ObActionIInputFunc *input,
42 ObActionICancelFunc *cancel,
43 ObActionIPostFunc *post);
44 static void free_func(gpointer o);
45 static gboolean run_func(const ObActionListRun *data, gpointer options);
47 static gboolean i_pre_func(guint state, gpointer options);
48 static gboolean i_input_func(guint initial_state,
53 static void i_post_func(gpointer options);
56 void action_desktop_startup(void)
58 action_register_i("GoToDesktop", OB_ACTION_DEFAULT_FILTER_EMPTY,
59 setup_go_func, free_func, run_func);
60 action_register_i("SendToDesktop", OB_ACTION_DEFAULT_FILTER_SINGLE,
61 setup_send_func, free_func, run_func);
64 static gpointer setup_func(GHashTable *config,
65 ObActionIPreFunc *pre,
66 ObActionIInputFunc *input,
67 ObActionICancelFunc *cancel,
68 ObActionIPostFunc *post)
73 o = g_slice_new0(Options);
74 /* don't go anywhere if there are no options given */
76 o->u.abs.desktop = screen_desktop;
77 /* wrap by default - it's handy! */
80 v = g_hash_table_lookup(config, "to");
81 if (v && action_value_is_string(v)) {
82 const gchar *s = action_value_string(v);
83 if (!g_ascii_strcasecmp(s, "last"))
85 else if (!g_ascii_strcasecmp(s, "current"))
87 else if (!g_ascii_strcasecmp(s, "next")) {
89 o->u.rel.linear = TRUE;
90 o->u.rel.dir = OB_DIRECTION_EAST;
92 else if (!g_ascii_strcasecmp(s, "previous")) {
94 o->u.rel.linear = TRUE;
95 o->u.rel.dir = OB_DIRECTION_WEST;
97 else if (!g_ascii_strcasecmp(s, "north") ||
98 !g_ascii_strcasecmp(s, "up")) {
100 o->u.rel.dir = OB_DIRECTION_NORTH;
102 else if (!g_ascii_strcasecmp(s, "south") ||
103 !g_ascii_strcasecmp(s, "down")) {
105 o->u.rel.dir = OB_DIRECTION_SOUTH;
107 else if (!g_ascii_strcasecmp(s, "west") ||
108 !g_ascii_strcasecmp(s, "left")) {
110 o->u.rel.dir = OB_DIRECTION_WEST;
112 else if (!g_ascii_strcasecmp(s, "east") ||
113 !g_ascii_strcasecmp(s, "right")) {
115 o->u.rel.dir = OB_DIRECTION_EAST;
119 o->u.abs.desktop = atoi(s) - 1;
123 v = g_hash_table_lookup(config, "wrap");
124 if (v && action_value_is_string(v))
125 o->u.rel.wrap = action_value_bool(v);
131 static gpointer setup_go_func(GHashTable *config,
132 ObActionIPreFunc *pre,
133 ObActionIInputFunc *input,
134 ObActionICancelFunc *cancel,
135 ObActionIPostFunc *post)
139 o = setup_func(config, pre, input, cancel, post);
140 if (o->type == RELATIVE) {
141 o->interactive = TRUE;
143 *input = i_input_func;
150 static gpointer setup_send_func(GHashTable *config,
151 ObActionIPreFunc *pre,
152 ObActionIInputFunc *input,
153 ObActionICancelFunc *cancel,
154 ObActionIPostFunc *post)
159 o = setup_func(config, pre, input, cancel, post);
163 v = g_hash_table_lookup(config, "follow");
164 if (v && action_value_is_string(v))
165 o->follow = action_value_bool(v);
167 if (o->type == RELATIVE && o->follow) {
168 o->interactive = TRUE;
170 *input = i_input_func;
177 static void free_func(gpointer o)
179 g_slice_free(Options, o);
182 static gboolean run_func(const ObActionListRun *data, gpointer options)
184 Options *o = options;
189 d = screen_last_desktop;
195 d = o->u.abs.desktop;
198 d = screen_find_desktop(screen_desktop,
199 o->u.rel.dir, o->u.rel.wrap, o->u.rel.linear);
202 g_assert_not_reached();
205 if (d < screen_num_desktops &&
206 (d != screen_desktop ||
207 (data->target && data->target->desktop != screen_desktop))) {
210 action_client_move(data, TRUE);
211 if (o->send && data->target && client_normal(data->target)) {
212 client_set_desktop(data->target, d, o->follow, FALSE);
217 screen_set_desktop(d, TRUE);
219 client_bring_helper_windows(data->target);
222 action_client_move(data, FALSE);
225 return o->interactive;
228 static gboolean i_input_func(guint initial_state,
234 guint mods, initial_mods;
236 initial_mods = obt_keyboard_only_modmasks(initial_state);
237 mods = obt_keyboard_only_modmasks(e->xkey.state);
238 if (e->type == KeyRelease) {
239 /* remove from the state the mask of the modifier key being
240 released, if it is a modifier key being released that is */
241 mods &= ~obt_keyboard_keyevent_to_modmask(e);
244 if (e->type == KeyPress) {
245 KeySym sym = obt_keyboard_keypress_to_keysym(e);
247 /* Escape cancels no matter what */
248 if (sym == XK_Escape)
251 /* There were no modifiers and they pressed enter */
252 else if ((sym == XK_Return || sym == XK_KP_Enter) && !initial_mods)
255 /* They released the modifiers */
256 else if (e->type == KeyRelease && initial_mods && !(mods & initial_mods))
264 static gboolean i_pre_func(guint initial_state, gpointer options)
266 guint initial_mods = obt_keyboard_only_modmasks(initial_state);
268 Options *o = options;
269 o->interactive = FALSE;
273 screen_show_desktop_popup(screen_desktop, TRUE);
278 static void i_post_func(gpointer options)
280 screen_hide_desktop_popup();