1 #include "openbox/action.h"
2 #include "openbox/action_list_run.h"
3 #include "openbox/config_value.h"
4 #include "openbox/screen.h"
5 #include "openbox/client.h"
6 #include "openbox/client_set.h"
7 #include "openbox/openbox.h"
8 #include "obt/keyboard.h"
34 /* for the foreach function */
39 static gpointer setup_go_func(GHashTable *config,
40 ObActionIPreFunc *pre,
41 ObActionIInputFunc *input,
42 ObActionICancelFunc *cancel,
43 ObActionIPostFunc *post);
44 static gpointer setup_send_func(GHashTable *config,
45 ObActionIPreFunc *pre,
46 ObActionIInputFunc *input,
47 ObActionICancelFunc *cancel,
48 ObActionIPostFunc *post);
49 static void free_func(gpointer o);
50 static gboolean run_func(const ObClientSet *set,
51 const ObActionListRun *data, gpointer options);
53 static gboolean i_pre_func(guint state, gpointer options);
54 static gboolean i_input_func(guint initial_state,
59 static void i_post_func(gpointer options);
62 void action_desktop_startup(void)
64 action_register_i("GoToDesktop", OB_ACTION_DEFAULT_FILTER_EMPTY,
65 setup_go_func, free_func, run_func);
66 action_register_i("SendToDesktop", OB_ACTION_DEFAULT_FILTER_SINGLE,
67 setup_send_func, free_func, run_func);
70 static gpointer setup_func(GHashTable *config,
71 ObActionIPreFunc *pre,
72 ObActionIInputFunc *input,
73 ObActionICancelFunc *cancel,
74 ObActionIPostFunc *post)
79 o = g_slice_new0(Options);
80 /* don't go anywhere if there are no options given */
82 o->u.abs.desktop = screen_desktop;
83 /* wrap by default - it's handy! */
86 v = g_hash_table_lookup(config, "to");
87 if (v && config_value_is_string(v)) {
88 const gchar *s = config_value_string(v);
89 if (!g_ascii_strcasecmp(s, "last"))
91 else if (!g_ascii_strcasecmp(s, "current"))
93 else if (!g_ascii_strcasecmp(s, "next")) {
95 o->u.rel.linear = TRUE;
96 o->u.rel.dir = OB_DIRECTION_EAST;
98 else if (!g_ascii_strcasecmp(s, "previous")) {
100 o->u.rel.linear = TRUE;
101 o->u.rel.dir = OB_DIRECTION_WEST;
103 else if (!g_ascii_strcasecmp(s, "north") ||
104 !g_ascii_strcasecmp(s, "up")) {
106 o->u.rel.dir = OB_DIRECTION_NORTH;
108 else if (!g_ascii_strcasecmp(s, "south") ||
109 !g_ascii_strcasecmp(s, "down")) {
111 o->u.rel.dir = OB_DIRECTION_SOUTH;
113 else if (!g_ascii_strcasecmp(s, "west") ||
114 !g_ascii_strcasecmp(s, "left")) {
116 o->u.rel.dir = OB_DIRECTION_WEST;
118 else if (!g_ascii_strcasecmp(s, "east") ||
119 !g_ascii_strcasecmp(s, "right")) {
121 o->u.rel.dir = OB_DIRECTION_EAST;
125 o->u.abs.desktop = atoi(s) - 1;
129 v = g_hash_table_lookup(config, "wrap");
130 if (v && config_value_is_string(v))
131 o->u.rel.wrap = config_value_bool(v);
137 static gpointer setup_go_func(GHashTable *config,
138 ObActionIPreFunc *pre,
139 ObActionIInputFunc *input,
140 ObActionICancelFunc *cancel,
141 ObActionIPostFunc *post)
145 o = setup_func(config, pre, input, cancel, post);
146 if (o->type == RELATIVE) {
147 o->interactive = TRUE;
149 *input = i_input_func;
156 static gpointer setup_send_func(GHashTable *config,
157 ObActionIPreFunc *pre,
158 ObActionIInputFunc *input,
159 ObActionICancelFunc *cancel,
160 ObActionIPostFunc *post)
165 o = setup_func(config, pre, input, cancel, post);
169 v = g_hash_table_lookup(config, "follow");
170 if (v && config_value_is_string(v))
171 o->follow = config_value_bool(v);
173 if (o->type == RELATIVE && o->follow) {
174 o->interactive = TRUE;
176 *input = i_input_func;
183 static void free_func(gpointer o)
185 g_slice_free(Options, o);
188 static gboolean each_send(ObClient *c, const ObActionListRun *data,
191 Options *o = options;
192 if (client_normal(c)) {
193 client_set_desktop(c, o->d, o->follow, FALSE);
194 o->moved = g_slist_prepend(o->moved, c);
199 static gboolean run_func(const ObClientSet *set,
200 const ObActionListRun *data, gpointer options)
202 Options *o = options;
207 d = screen_last_desktop;
213 d = o->u.abs.desktop;
216 d = screen_find_desktop(screen_desktop,
217 o->u.rel.dir, o->u.rel.wrap, o->u.rel.linear);
220 g_assert_not_reached();
223 if (d < screen_num_desktops) {
230 action_client_move(data, TRUE);
232 client_set_run(set, data, each_send, o);
239 if (d != screen_desktop)
240 screen_set_desktop(d, TRUE);
241 for (it = o->moved; it; it = g_slist_next(it))
242 client_bring_helper_windows(it->data);
244 g_slist_free(o->moved);
246 action_client_move(data, FALSE);
249 return o->interactive;
252 static gboolean i_input_func(guint initial_state,
258 guint mods, initial_mods;
260 initial_mods = obt_keyboard_only_modmasks(initial_state);
261 mods = obt_keyboard_only_modmasks(e->xkey.state);
262 if (e->type == KeyRelease) {
263 /* remove from the state the mask of the modifier key being
264 released, if it is a modifier key being released that is */
265 mods &= ~obt_keyboard_keyevent_to_modmask(e);
268 if (e->type == KeyPress) {
269 KeySym sym = obt_keyboard_keypress_to_keysym(e);
271 /* Escape cancels no matter what */
272 if (sym == XK_Escape)
275 /* There were no modifiers and they pressed enter */
276 else if ((sym == XK_Return || sym == XK_KP_Enter) && !initial_mods)
279 /* They released the modifiers */
280 else if (e->type == KeyRelease && initial_mods && !(mods & initial_mods))
288 static gboolean i_pre_func(guint initial_state, gpointer options)
290 guint initial_mods = obt_keyboard_only_modmasks(initial_state);
292 Options *o = options;
293 o->interactive = FALSE;
297 screen_show_desktop_popup(screen_desktop, TRUE);
302 static void i_post_func(gpointer options)
304 screen_hide_desktop_popup();