14 #include "translate.h"
18 KeyBindingTree *keyboard_firstnode;
24 ObFrameContext context;
27 static GSList *interactive_states;
29 static KeyBindingTree *curpos;
30 static ObTimer *chain_timer;
32 static void grab_for_window(Window win, gboolean grab)
39 p = curpos ? curpos->first_child : keyboard_firstnode;
41 grab_key(p->key, p->state, win, GrabModeAsync);
45 grab_key(config_keyboard_reset_keycode,
46 config_keyboard_reset_state,
51 void keyboard_grab_for_client(ObClient *c, gboolean grab)
53 grab_for_window(c->window, grab);
56 static void grab_keys(gboolean grab)
60 grab_for_window(screen_support_win, grab);
61 for (it = client_list; it; it = g_list_next(it))
62 grab_for_window(((ObClient*)it->data)->frame->window, grab);
65 void keyboard_reset_chains()
68 timer_stop(chain_timer);
77 static void chain_timeout(ObTimer *t, void *data)
79 keyboard_reset_chains();
82 gboolean keyboard_bind(GList *keylist, ObAction *action)
84 KeyBindingTree *tree, *t;
87 g_assert(keylist != NULL);
88 g_assert(action != NULL);
90 if (!(tree = tree_build(keylist)))
93 if ((t = tree_find(tree, &conflict)) != NULL) {
94 /* already bound to something, use the existing tree */
99 while (t->first_child) t = t->first_child;
102 g_warning("conflict with binding");
108 t->actions = g_slist_append(t->actions, action);
109 /* assimilate this built tree into the main tree. assimilation
110 destroys/uses the tree */
111 if (tree) tree_assimilate(tree);
116 void keyboard_interactive_grab(guint state, ObClient *client,
117 ObFrameContext context, ObAction *action)
119 ObInteractiveState *s;
121 if (!interactive_states) {
122 if (!grab_keyboard(TRUE))
124 if (!grab_pointer(TRUE, None)) {
125 grab_keyboard(FALSE);
130 s = g_new(ObInteractiveState, 1);
135 s->context = context;
137 interactive_states = g_slist_append(interactive_states, s);
140 gboolean keyboard_process_interactive_grab(const XEvent *e,
142 ObFrameContext *context)
145 gboolean handled = FALSE;
146 gboolean done = FALSE;
147 gboolean cancel = FALSE;
149 for (it = interactive_states; it; it = next) {
150 ObInteractiveState *s = it->data;
152 next = g_slist_next(it);
155 *context = s->context;
157 if ((e->type == KeyRelease &&
158 !(s->state & e->xkey.state)))
160 else if (e->type == KeyPress) {
161 if (e->xkey.keycode == ob_keycode(OB_KEY_RETURN))
163 else if (e->xkey.keycode == ob_keycode(OB_KEY_ESCAPE))
164 cancel = done = TRUE;
167 if (s->action->func == action_cycle_windows) {
168 s->action->data.cycle.cancel = cancel;
169 s->action->data.cycle.final = TRUE;
171 if (s->action->func == action_desktop_dir) {
172 s->action->data.desktopdir.cancel = cancel;
173 s->action->data.desktopdir.final = TRUE;
175 if (s->action->func == action_send_to_desktop_dir) {
176 s->action->data.sendtodir.cancel = cancel;
177 s->action->data.sendtodir.final = TRUE;
180 s->action->func(&s->action->data);
182 grab_keyboard(FALSE);
183 grab_pointer(FALSE, None);
184 keyboard_reset_chains();
187 interactive_states = g_slist_delete_link(interactive_states, it);
195 void keyboard_event(ObClient *client, const XEvent *e)
199 g_assert(e->type == KeyPress);
201 if (e->xkey.keycode == config_keyboard_reset_keycode &&
202 e->xkey.state == config_keyboard_reset_state)
204 keyboard_reset_chains();
209 p = keyboard_firstnode;
211 p = curpos->first_child;
213 if (p->key == e->xkey.keycode &&
214 p->state == e->xkey.state) {
215 if (p->first_child != NULL) { /* part of a chain */
216 if (chain_timer) timer_stop(chain_timer);
217 /* 5 second timeout for chains */
218 chain_timer = timer_start(5000*1000, chain_timeout,
224 for (it = p->actions; it; it = it->next) {
225 ObAction *act = it->data;
226 if (act->func != NULL) {
227 act->data.any.c = client;
229 if (act->func == action_cycle_windows)
231 act->data.cycle.final = FALSE;
232 act->data.cycle.cancel = FALSE;
234 if (act->func == action_desktop_dir)
236 act->data.desktopdir.final = FALSE;
237 act->data.desktopdir.cancel = FALSE;
239 if (act->func == action_send_to_desktop_dir)
241 act->data.sendtodir.final = FALSE;
242 act->data.sendtodir.cancel = FALSE;
245 if (act->func == action_moveresize)
247 screen_pointer_pos(&act->data.moveresize.x,
248 &act->data.moveresize.y);
251 if ((act->func == action_cycle_windows ||
252 act->func == action_desktop_dir ||
253 act->func == action_send_to_desktop_dir))
255 keyboard_interactive_grab(e->xkey.state, client,
259 if (act->func == action_showmenu)
261 act->data.showmenu.x = e->xkey.x_root;
262 act->data.showmenu.y = e->xkey.y_root;
265 act->data.any.c = client;
266 act->func(&act->data);
270 keyboard_reset_chains();
278 void keyboard_startup()
283 void keyboard_shutdown()
285 tree_destroy(keyboard_firstnode);
286 keyboard_firstnode = NULL;