]> icculus.org git repositories - dana/openbox.git/blob - openbox/actions/cyclewindows.c
Use ObConfigValue to parse gravity coords, remove parse special functions from config...
[dana/openbox.git] / openbox / actions / cyclewindows.c
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"
12 #include "gettext.h"
13 #include "obt/keyboard.h"
14
15 typedef struct {
16     gboolean linear;
17     gboolean dock_windows;
18     gboolean desktop_windows;
19     gboolean forward;
20     gboolean bar;
21     gboolean raise;
22     ObFocusCyclePopupMode dialog_mode;
23     ObActionList *actions;
24
25
26     /* options for after we're done */
27     gboolean cancel; /* did the user cancel or not */
28     guint state;     /* keyboard state when finished */
29 } Options;
30
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,
50                              XEvent *e,
51                              ObtIC *ic,
52                              gpointer options,
53                              gboolean *used);
54 static void     i_cancel_func(gpointer options);
55 static void     i_post_func(gpointer options);
56
57 void action_cyclewindows_startup(void)
58 {
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);
63 }
64
65 static gpointer setup_func(GHashTable *config,
66                            ObActionIPreFunc *pre,
67                            ObActionIInputFunc *input,
68                            ObActionICancelFunc *cancel,
69                            ObActionIPostFunc *post)
70 {
71     ObConfigValue *v;
72     Options *o;
73
74     o = g_slice_new0(Options);
75     o->bar = TRUE;
76     o->dialog_mode = OB_FOCUS_CYCLE_POPUP_MODE_LIST;
77
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;
90     }
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);
103
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);
108     }
109     else {
110         ObActionParser *p = action_parser_new();
111         o->actions = action_parser_read_string(p,
112                                                 "focus\n"
113                                                 "raise\n"
114                                                 "unshade\n");
115         action_parser_unref(p);
116     }
117
118     *input = i_input_func;
119     *cancel = i_cancel_func;
120     *post = i_post_func;
121     return o;
122 }
123
124 static gpointer setup_forward_func(GHashTable *config,
125                                    ObActionIPreFunc *pre,
126                                    ObActionIInputFunc *input,
127                                    ObActionICancelFunc *cancel,
128                                    ObActionIPostFunc *post)
129 {
130     Options *o = setup_func(config, pre, input, cancel, post);
131     o->forward = TRUE;
132     return o;
133 }
134
135 static gpointer setup_backward_func(GHashTable *config,
136                                     ObActionIPreFunc *pre,
137                                     ObActionIInputFunc *input,
138                                     ObActionICancelFunc *cancel,
139                                     ObActionIPostFunc *post)
140 {
141     Options *o = setup_func(config, pre, input, cancel, post);
142     o->forward = FALSE;
143     return o;
144 }
145
146 static void free_func(gpointer options)
147 {
148     Options *o = options;
149
150     action_list_unref(o->actions);
151     g_slice_free(Options, o);
152 }
153
154 static gboolean run_func(const ObClientSet *set,
155                          const ObActionListRun *data, gpointer options)
156 {
157     Options *o = options;
158     struct _ObClient *ft;
159
160     if (client_set_is_empty(set)) return FALSE;
161
162     ft = focus_cycle(set,
163                      o->forward,
164                      o->dock_windows,
165                      o->desktop_windows,
166                      o->linear,
167                      TRUE,
168                      o->bar,
169                      o->dialog_mode,
170                      FALSE, FALSE);
171
172     stacking_restore();
173     if (o->raise && ft) stacking_temp_raise(CLIENT_AS_WINDOW(ft));
174
175     return TRUE;
176 }
177
178 static gboolean i_input_func(guint initial_state,
179                              XEvent *e,
180                              ObtIC *ic,
181                              gpointer options,
182                              gboolean *used)
183 {
184     Options *o = options;
185     guint mods, initial_mods;
186
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);
193     }
194
195     if (e->type == KeyPress) {
196         KeySym sym = obt_keyboard_keypress_to_keysym(e);
197
198         /* Escape cancels no matter what */
199         if (sym == XK_Escape) {
200             o->cancel = TRUE;
201             o->state = e->xkey.state;
202             return FALSE;
203         }
204
205         /* There were no modifiers and they pressed enter */
206         else if ((sym == XK_Return || sym == XK_KP_Enter) && !initial_mods) {
207             o->cancel = FALSE;
208             o->state = e->xkey.state;
209             return FALSE;
210         }
211     }
212     /* They released the modifiers */
213     else if (e->type == KeyRelease && initial_mods && !(mods & initial_mods))
214     {
215         o->cancel = FALSE;
216         o->state = e->xkey.state;
217         return FALSE;
218     }
219
220     return TRUE;
221 }
222
223 static void i_cancel_func(gpointer options)
224 {
225     Options *o = options;
226     o->cancel = TRUE;
227     o->state = 0;
228 }
229
230 static void i_post_func(gpointer options)
231 {
232     Options *o = options;
233     struct _ObClient *ft;
234
235     ft = focus_cycle(NULL,
236                      o->forward,
237                      o->dock_windows,
238                      o->desktop_windows,
239                      o->linear,
240                      TRUE,
241                      o->bar,
242                      o->dialog_mode,
243                      TRUE, o->cancel);
244
245     if (ft)
246         action_list_run(o->actions, OB_USER_ACTION_KEYBOARD_KEY,
247                         o->state, -1, -1, 0, OB_FRAME_CONTEXT_NONE, ft);
248
249     stacking_restore();
250 }