1 #include "openbox/action.h"
2 #include "openbox/action_list.h"
3 #include "openbox/action_list_run.h"
4 #include "openbox/action_parser.h"
5 #include "openbox/config_value.h"
6 #include "openbox/client_set.h"
7 #include "openbox/stacking.h"
8 #include "openbox/window.h"
9 #include "openbox/event.h"
10 #include "openbox/focus_cycle.h"
11 #include "openbox/openbox.h"
13 #include "obt/keyboard.h"
17 gboolean dock_windows;
18 gboolean desktop_windows;
22 ObFocusCyclePopupMode dialog_mode;
23 ObActionList *actions;
26 /* options for after we're done */
27 gboolean cancel; /* did the user cancel or not */
28 guint state; /* keyboard state when finished */
31 static gpointer setup_func(GHashTable *config,
32 ObActionIPreFunc *pre,
33 ObActionIInputFunc *in,
34 ObActionICancelFunc *c,
35 ObActionIPostFunc *post);
36 static gpointer setup_forward_func(GHashTable *config,
37 ObActionIPreFunc *pre,
38 ObActionIInputFunc *in,
39 ObActionICancelFunc *c,
40 ObActionIPostFunc *post);
41 static gpointer setup_backward_func(GHashTable *config,
42 ObActionIPreFunc *pre,
43 ObActionIInputFunc *in,
44 ObActionICancelFunc *c,
45 ObActionIPostFunc *post);
46 static void free_func(gpointer options);
47 static gboolean run_func(const ObClientSet *set,
48 const ObActionListRun *data, gpointer options);
49 static gboolean i_input_func(guint initial_state,
54 static void i_cancel_func(gpointer options);
55 static void i_post_func(gpointer options);
57 void action_cyclewindows_startup(void)
59 action_register_i("NextWindow", OB_ACTION_DEFAULT_FILTER_ALL,
60 setup_forward_func, free_func, run_func);
61 action_register_i("PreviousWindow", OB_ACTION_DEFAULT_FILTER_ALL,
62 setup_backward_func, free_func, run_func);
65 static gpointer setup_func(GHashTable *config,
66 ObActionIPreFunc *pre,
67 ObActionIInputFunc *input,
68 ObActionICancelFunc *cancel,
69 ObActionIPostFunc *post)
74 o = g_slice_new0(Options);
76 o->dialog_mode = OB_FOCUS_CYCLE_POPUP_MODE_LIST;
78 v = g_hash_table_lookup(config, "linear");
79 if (v && config_value_is_string(v))
80 o->linear = config_value_bool(v);
81 v = g_hash_table_lookup(config, "dialog");
82 if (v && config_value_is_string(v)) {
83 const gchar *s = config_value_string(v);
84 if (g_strcasecmp(s, "none") == 0)
85 o->dialog_mode = OB_FOCUS_CYCLE_POPUP_MODE_NONE;
86 else if (g_strcasecmp(s, "no") == 0)
87 o->dialog_mode = OB_FOCUS_CYCLE_POPUP_MODE_NONE;
88 else if (g_strcasecmp(s, "icons") == 0)
89 o->dialog_mode = OB_FOCUS_CYCLE_POPUP_MODE_ICONS;
91 v = g_hash_table_lookup(config, "bar");
92 if (v && config_value_is_string(v))
93 o->bar = config_value_bool(v);
94 v = g_hash_table_lookup(config, "raise");
95 if (v && config_value_is_string(v))
96 o->raise = config_value_bool(v);
97 v = g_hash_table_lookup(config, "panels");
98 if (v && config_value_is_string(v))
99 o->dock_windows = config_value_bool(v);
100 v = g_hash_table_lookup(config, "desktop");
101 if (v && config_value_is_string(v))
102 o->desktop_windows = config_value_bool(v);
104 v = g_hash_table_lookup(config, "finalactions");
105 if (v && config_value_is_action_list(v)) {
106 o->actions = config_value_action_list(v);
107 action_list_ref(o->actions);
110 ObActionParser *p = action_parser_new();
111 o->actions = action_parser_read_string(p,
115 action_parser_unref(p);
118 *input = i_input_func;
119 *cancel = i_cancel_func;
124 static gpointer setup_forward_func(GHashTable *config,
125 ObActionIPreFunc *pre,
126 ObActionIInputFunc *input,
127 ObActionICancelFunc *cancel,
128 ObActionIPostFunc *post)
130 Options *o = setup_func(config, pre, input, cancel, post);
135 static gpointer setup_backward_func(GHashTable *config,
136 ObActionIPreFunc *pre,
137 ObActionIInputFunc *input,
138 ObActionICancelFunc *cancel,
139 ObActionIPostFunc *post)
141 Options *o = setup_func(config, pre, input, cancel, post);
146 static void free_func(gpointer options)
148 Options *o = options;
150 action_list_unref(o->actions);
151 g_slice_free(Options, o);
154 static gboolean run_func(const ObClientSet *set,
155 const ObActionListRun *data, gpointer options)
157 Options *o = options;
158 struct _ObClient *ft;
160 if (client_set_is_empty(set)) return FALSE;
162 ft = focus_cycle(set,
173 if (o->raise && ft) stacking_temp_raise(CLIENT_AS_WINDOW(ft));
178 static gboolean i_input_func(guint initial_state,
184 Options *o = options;
185 guint mods, initial_mods;
187 initial_mods = obt_keyboard_only_modmasks(initial_state);
188 mods = obt_keyboard_only_modmasks(e->xkey.state);
189 if (e->type == KeyRelease) {
190 /* remove from the state the mask of the modifier key being
191 released, if it is a modifier key being released that is */
192 mods &= ~obt_keyboard_keyevent_to_modmask(e);
195 if (e->type == KeyPress) {
196 KeySym sym = obt_keyboard_keypress_to_keysym(e);
198 /* Escape cancels no matter what */
199 if (sym == XK_Escape) {
201 o->state = e->xkey.state;
205 /* There were no modifiers and they pressed enter */
206 else if ((sym == XK_Return || sym == XK_KP_Enter) && !initial_mods) {
208 o->state = e->xkey.state;
212 /* They released the modifiers */
213 else if (e->type == KeyRelease && initial_mods && !(mods & initial_mods))
216 o->state = e->xkey.state;
223 static void i_cancel_func(gpointer options)
225 Options *o = options;
230 static void i_post_func(gpointer options)
232 Options *o = options;
233 struct _ObClient *ft;
235 ft = focus_cycle(NULL,
246 action_list_run(o->actions, OB_USER_ACTION_KEYBOARD_KEY,
247 o->state, -1, -1, 0, OB_FRAME_CONTEXT_NONE, ft);