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
)->frame
->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 if (!interactive_states
) {
137 if (!grab_keyboard(TRUE
))
139 if (!grab_pointer(TRUE
, None
)) {
140 grab_keyboard(FALSE
);
145 s
= g_new(ObInteractiveState
, 1);
150 s
->context
= context
;
152 interactive_states
= g_slist_append(interactive_states
, s
);
155 gboolean
keyboard_process_interactive_grab(const XEvent
*e
,
157 ObFrameContext
*context
)
160 gboolean handled
= FALSE
;
161 gboolean done
= FALSE
;
162 gboolean cancel
= FALSE
;
164 for (it
= interactive_states
; it
; it
= next
) {
165 ObInteractiveState
*s
= it
->data
;
167 next
= g_slist_next(it
);
170 *context
= s
->context
;
172 if ((e
->type
== KeyRelease
&&
173 !(s
->state
& e
->xkey
.state
)))
175 else if (e
->type
== KeyPress
) {
176 if (e
->xkey
.keycode
== ob_keycode(OB_KEY_RETURN
))
178 else if (e
->xkey
.keycode
== ob_keycode(OB_KEY_ESCAPE
))
179 cancel
= done
= TRUE
;
182 g_assert(s
->action
->data
.any
.interactive
);
184 s
->action
->data
.inter
.cancel
= cancel
;
185 s
->action
->data
.inter
.final
= TRUE
;
187 s
->action
->func(&s
->action
->data
);
189 grab_keyboard(FALSE
);
190 grab_pointer(FALSE
, None
);
191 keyboard_reset_chains();
194 interactive_states
= g_slist_delete_link(interactive_states
, it
);
202 void keyboard_event(ObClient
*client
, const XEvent
*e
)
206 g_assert(e
->type
== KeyPress
);
208 if (e
->xkey
.keycode
== config_keyboard_reset_keycode
&&
209 e
->xkey
.state
== config_keyboard_reset_state
)
211 keyboard_reset_chains();
216 p
= keyboard_firstnode
;
218 p
= curpos
->first_child
;
220 if (p
->key
== e
->xkey
.keycode
&&
221 p
->state
== e
->xkey
.state
) {
222 if (p
->first_child
!= NULL
) { /* part of a chain */
223 ob_main_loop_timeout_remove(ob_main_loop
, chain_timeout
);
224 /* 5 second timeout for chains */
225 ob_main_loop_timeout_add(ob_main_loop
, 5 * G_USEC_PER_SEC
,
226 chain_timeout
, NULL
, NULL
);
232 for (it
= p
->actions
; it
; it
= it
->next
) {
233 ObAction
*act
= it
->data
;
234 if (act
->func
!= NULL
) {
235 act
->data
.any
.c
= client
;
237 if (act
->func
== action_moveresize
) {
238 screen_pointer_pos(&act
->data
.moveresize
.x
,
239 &act
->data
.moveresize
.y
);
242 if (act
->data
.any
.interactive
) {
243 act
->data
.inter
.cancel
= FALSE
;
244 act
->data
.inter
.final
= FALSE
;
245 keyboard_interactive_grab(e
->xkey
.state
, client
,
249 if (act
->func
== action_showmenu
) {
250 act
->data
.showmenu
.x
= e
->xkey
.x_root
;
251 act
->data
.showmenu
.y
= e
->xkey
.y_root
;
254 act
->data
.any
.c
= client
;
255 act
->func(&act
->data
);
259 keyboard_reset_chains();
267 void keyboard_startup(gboolean reconfig
)
272 void keyboard_shutdown(gboolean reconfig
)
276 tree_destroy(keyboard_firstnode
);
277 keyboard_firstnode
= NULL
;
279 for (it
= interactive_states
; it
; it
= g_slist_next(it
))
281 g_slist_free(interactive_states
);
282 interactive_states
= NULL
;
284 ob_main_loop_timeout_remove(ob_main_loop
, chain_timeout
);