]> icculus.org git repositories - dana/openbox.git/blob - openbox/actions/cyclewindows.c
Rename ObActions* to ObAction* and remove more 3.4-compat action stuff that was missed.
[dana/openbox.git] / openbox / actions / cyclewindows.c
1 #include "openbox/action.h"
2 #include "openbox/action_list.h"
3 #include "openbox/action_parser.h"
4 #include "openbox/action_value.h"
5 #include "openbox/stacking.h"
6 #include "openbox/window.h"
7 #include "openbox/event.h"
8 #include "openbox/focus_cycle.h"
9 #include "openbox/openbox.h"
10 #include "gettext.h"
11 #include "obt/keyboard.h"
12
13 typedef struct {
14     gboolean linear;
15     gboolean dock_windows;
16     gboolean desktop_windows;
17     gboolean only_hilite_windows;
18     gboolean all_desktops;
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(ObActionData *data, gpointer options);
48 static gboolean i_input_func(guint initial_state,
49                              XEvent *e,
50                              ObtIC *ic,
51                              gpointer options,
52                              gboolean *used);
53 static void     i_cancel_func(gpointer options);
54 static void     i_post_func(gpointer options);
55
56 void action_cyclewindows_startup(void)
57 {
58     action_register_i("NextWindow", setup_forward_func, free_func, run_func);
59     action_register_i("PreviousWindow", setup_backward_func, free_func,
60                       run_func);
61 }
62
63 static gpointer setup_func(GHashTable *config,
64                            ObActionIPreFunc *pre,
65                            ObActionIInputFunc *input,
66                            ObActionICancelFunc *cancel,
67                            ObActionIPostFunc *post)
68 {
69     ObActionValue *v;
70     Options *o;
71
72     o = g_slice_new0(Options);
73     o->bar = TRUE;
74     o->dialog_mode = OB_FOCUS_CYCLE_POPUP_MODE_LIST;
75
76     v = g_hash_table_lookup(config, "linear");
77     if (v && action_value_is_string(v))
78         o->linear = action_value_bool(v);
79     v = g_hash_table_lookup(config, "dialog");
80     if (v && action_value_is_string(v)) {
81         const gchar *s = action_value_string(v);
82         if (g_strcasecmp(s, "none") == 0)
83             o->dialog_mode = OB_FOCUS_CYCLE_POPUP_MODE_NONE;
84         else if (g_strcasecmp(s, "no") == 0)
85             o->dialog_mode = OB_FOCUS_CYCLE_POPUP_MODE_NONE;
86         else if (g_strcasecmp(s, "icons") == 0)
87             o->dialog_mode = OB_FOCUS_CYCLE_POPUP_MODE_ICONS;
88     }
89     v = g_hash_table_lookup(config, "bar");
90     if (v && action_value_is_string(v))
91         o->bar = action_value_bool(v);
92     v = g_hash_table_lookup(config, "raise");
93     if (v && action_value_is_string(v))
94         o->raise = action_value_bool(v);
95     v = g_hash_table_lookup(config, "panels");
96     if (v && action_value_is_string(v))
97         o->dock_windows = action_value_bool(v);
98     v = g_hash_table_lookup(config, "hilite");
99     if (v && action_value_is_string(v))
100         o->only_hilite_windows = action_value_bool(v);
101     v = g_hash_table_lookup(config, "desktop");
102     if (v && action_value_is_string(v))
103         o->desktop_windows = action_value_bool(v);
104     v = g_hash_table_lookup(config, "allDesktops");
105     if (v && action_value_is_string(v))
106         o->all_desktops = action_value_bool(v);
107
108     v = g_hash_table_lookup(config, "finalactions");
109     if (v && action_value_is_action_list(v)) {
110         o->actions = action_value_action_list(v);
111         action_list_ref(o->actions);
112     }
113     else {
114         ObActionParser *p = action_parser_new();
115         o->actions = action_parser_read_string(p,
116                                                 "focus\n"
117                                                 "raise\n"
118                                                 "unshade\n");
119         action_parser_unref(p);
120     }
121
122     *input = i_input_func;
123     *cancel = i_cancel_func;
124     *post = i_post_func;
125     return o;
126 }
127
128 static gpointer setup_forward_func(GHashTable *config,
129                                    ObActionIPreFunc *pre,
130                                    ObActionIInputFunc *input,
131                                    ObActionICancelFunc *cancel,
132                                    ObActionIPostFunc *post)
133 {
134     Options *o = setup_func(config, pre, input, cancel, post);
135     o->forward = TRUE;
136     return o;
137 }
138
139 static gpointer setup_backward_func(GHashTable *config,
140                                     ObActionIPreFunc *pre,
141                                     ObActionIInputFunc *input,
142                                     ObActionICancelFunc *cancel,
143                                     ObActionIPostFunc *post)
144 {
145     Options *o = setup_func(config, pre, input, cancel, post);
146     o->forward = FALSE;
147     return o;
148 }
149
150 static void free_func(gpointer options)
151 {
152     Options *o = options;
153
154     action_list_unref(o->actions);
155     g_slice_free(Options, o);
156 }
157
158 static gboolean run_func(ObActionData *data, gpointer options)
159 {
160     Options *o = options;
161     struct _ObClient *ft;
162
163     ft = focus_cycle(o->forward,
164                      o->all_desktops,
165                      !o->only_hilite_windows,
166                      o->dock_windows,
167                      o->desktop_windows,
168                      o->linear,
169                      TRUE,
170                      o->bar,
171                      o->dialog_mode,
172                      FALSE, FALSE);
173
174     stacking_restore();
175     if (o->raise && ft) stacking_temp_raise(CLIENT_AS_WINDOW(ft));
176
177     return TRUE;
178 }
179
180 static gboolean i_input_func(guint initial_state,
181                              XEvent *e,
182                              ObtIC *ic,
183                              gpointer options,
184                              gboolean *used)
185 {
186     Options *o = options;
187     guint mods, initial_mods;
188
189     initial_mods = obt_keyboard_only_modmasks(initial_state);
190     mods = obt_keyboard_only_modmasks(e->xkey.state);
191     if (e->type == KeyRelease) {
192         /* remove from the state the mask of the modifier key being
193            released, if it is a modifier key being released that is */
194         mods &= ~obt_keyboard_keyevent_to_modmask(e);
195     }
196
197     if (e->type == KeyPress) {
198         KeySym sym = obt_keyboard_keypress_to_keysym(e);
199
200         /* Escape cancels no matter what */
201         if (sym == XK_Escape) {
202             o->cancel = TRUE;
203             o->state = e->xkey.state;
204             return FALSE;
205         }
206
207         /* There were no modifiers and they pressed enter */
208         else if ((sym == XK_Return || sym == XK_KP_Enter) && !initial_mods) {
209             o->cancel = FALSE;
210             o->state = e->xkey.state;
211             return FALSE;
212         }
213     }
214     /* They released the modifiers */
215     else if (e->type == KeyRelease && initial_mods && !(mods & initial_mods))
216     {
217         o->cancel = FALSE;
218         o->state = e->xkey.state;
219         return FALSE;
220     }
221
222     return TRUE;
223 }
224
225 static void i_cancel_func(gpointer options)
226 {
227     Options *o = options;
228     o->cancel = TRUE;
229     o->state = 0;
230 }
231
232 static void i_post_func(gpointer options)
233 {
234     Options *o = options;
235     struct _ObClient *ft;
236
237     ft = focus_cycle(o->forward,
238                      o->all_desktops,
239                      !o->only_hilite_windows,
240                      o->dock_windows,
241                      o->desktop_windows,
242                      o->linear,
243                      TRUE,
244                      o->bar,
245                      o->dialog_mode,
246                      TRUE, o->cancel);
247
248     if (ft)
249         action_run_acts(o->actions, OB_USER_ACTION_KEYBOARD_KEY,
250                         o->state, -1, -1, 0, OB_FRAME_CONTEXT_NONE, ft);
251
252     stacking_restore();
253 }