14 #include "translate.h"
18 KeyBindingTree
*keyboard_firstnode
;
24 ObFrameContext context
;
27 static GSList
*interactive_states
;
29 static KeyBindingTree
*curpos
;
31 static void grab_for_window(Window win
, gboolean grab
)
38 p
= curpos
? curpos
->first_child
: keyboard_firstnode
;
40 grab_key(p
->key
, p
->state
, win
, GrabModeAsync
);
44 grab_key(config_keyboard_reset_keycode
,
45 config_keyboard_reset_state
,
50 void keyboard_grab_for_client(ObClient
*c
, gboolean grab
)
52 grab_for_window(c
->window
, grab
);
55 static void grab_keys(gboolean grab
)
59 grab_for_window(screen_support_win
, grab
);
60 for (it
= client_list
; it
; it
= g_list_next(it
))
61 grab_for_window(((ObClient
*)it
->data
)->window
, grab
);
64 static gboolean
chain_timeout(gpointer data
)
66 keyboard_reset_chains();
68 return FALSE
; /* don't repeat */
71 void keyboard_reset_chains()
73 ob_main_loop_timeout_remove(ob_main_loop
, chain_timeout
);
82 gboolean
keyboard_bind(GList
*keylist
, ObAction
*action
)
84 KeyBindingTree
*tree
, *t
;
88 g_assert(keylist
!= NULL
);
89 g_assert(action
!= NULL
);
91 if (!(tree
= tree_build(keylist
)))
94 if ((t
= tree_find(tree
, &conflict
)) != NULL
) {
95 /* already bound to something, use the existing tree */
102 g_warning("conflict with binding");
107 /* find if every key in this chain has modifiers, and also find the
108 bottom node of the tree */
109 while (t
->first_child
) {
115 /* when there are no modifiers in the binding, then the action cannot
117 if (!mods
&& action
->data
.any
.interactive
) {
118 action
->data
.any
.interactive
= FALSE
;
119 action
->data
.inter
.final
= TRUE
;
123 t
->actions
= g_slist_append(t
->actions
, action
);
124 /* assimilate this built tree into the main tree. assimilation
125 destroys/uses the tree */
126 if (tree
) tree_assimilate(tree
);
131 void keyboard_interactive_grab(guint state
, ObClient
*client
,
132 ObFrameContext context
, ObAction
*action
)
134 ObInteractiveState
*s
;
136 g_assert(action
->data
.any
.interactive
);
138 if (!interactive_states
) {
139 if (!grab_keyboard(TRUE
))
141 if (!grab_pointer(TRUE
, OB_CURSOR_NONE
)) {
142 grab_keyboard(FALSE
);
147 s
= g_new(ObInteractiveState
, 1);
152 s
->context
= context
;
154 interactive_states
= g_slist_append(interactive_states
, s
);
157 gboolean
keyboard_process_interactive_grab(const XEvent
*e
,
159 ObFrameContext
*context
)
162 gboolean handled
= FALSE
;
163 gboolean done
= FALSE
;
164 gboolean cancel
= FALSE
;
166 for (it
= interactive_states
; it
; it
= next
) {
167 ObInteractiveState
*s
= it
->data
;
169 next
= g_slist_next(it
);
172 *context
= s
->context
;
174 if ((e
->type
== KeyRelease
&&
175 !(s
->state
& e
->xkey
.state
)))
177 else if (e
->type
== KeyPress
) {
178 if (e
->xkey
.keycode
== ob_keycode(OB_KEY_RETURN
))
180 else if (e
->xkey
.keycode
== ob_keycode(OB_KEY_ESCAPE
))
181 cancel
= done
= TRUE
;
184 action_run_interactive(s
->action
, s
->client
,
185 e
->xkey
.state
, cancel
, TRUE
);
189 interactive_states
= g_slist_delete_link(interactive_states
, it
);
190 if (!interactive_states
) {
191 grab_keyboard(FALSE
);
192 grab_pointer(FALSE
, OB_CURSOR_NONE
);
193 keyboard_reset_chains();
203 void keyboard_event(ObClient
*client
, const XEvent
*e
)
207 g_assert(e
->type
== KeyPress
);
209 if (e
->xkey
.keycode
== config_keyboard_reset_keycode
&&
210 e
->xkey
.state
== config_keyboard_reset_state
)
212 keyboard_reset_chains();
217 p
= keyboard_firstnode
;
219 p
= curpos
->first_child
;
221 if (p
->key
== e
->xkey
.keycode
&&
222 p
->state
== e
->xkey
.state
)
224 if (p
->first_child
!= NULL
) { /* part of a chain */
225 ob_main_loop_timeout_remove(ob_main_loop
, chain_timeout
);
226 /* 5 second timeout for chains */
227 ob_main_loop_timeout_add(ob_main_loop
, 5 * G_USEC_PER_SEC
,
228 chain_timeout
, NULL
, NULL
);
235 for (it
= p
->actions
; it
; it
= it
->next
)
236 action_run_key(it
->data
, client
, e
->xkey
.state
,
237 e
->xkey
.x_root
, e
->xkey
.y_root
);
239 keyboard_reset_chains();
247 void keyboard_startup(gboolean reconfig
)
252 void keyboard_shutdown(gboolean reconfig
)
256 tree_destroy(keyboard_firstnode
);
257 keyboard_firstnode
= NULL
;
259 for (it
= interactive_states
; it
; it
= g_slist_next(it
))
261 g_slist_free(interactive_states
);
262 interactive_states
= NULL
;
264 ob_main_loop_timeout_remove(ob_main_loop
, chain_timeout
);