1 #include "kernel/focus.h"
2 #include "kernel/screen.h"
3 #include "kernel/frame.h"
4 #include "kernel/dispatch.h"
5 #include "kernel/openbox.h"
6 #include "kernel/event.h"
7 #include "kernel/grab.h"
8 #include "kernel/client.h"
9 #include "kernel/action.h"
10 #include "kernel/prop.h"
11 #include "kernel/timer.h"
12 #include "parser/parse.h"
15 #include "translate.h"
21 <action name="ChangeDesktop">
28 static void parse_key(xmlDocPtr doc
, xmlNodePtr node
, GList
*keylist
)
35 n
= parse_find_node("keybind", node
);
37 if (parse_attr_string("key", n
, &key
)) {
38 keylist
= g_list_append(keylist
, key
);
40 parse_key(doc
, n
->xmlChildrenNode
, keylist
);
42 it
= g_list_last(keylist
);
44 keylist
= g_list_delete_link(keylist
, it
);
46 n
= parse_find_node("keybind", n
->next
);
49 nact
= parse_find_node("action", node
);
51 if ((action
= action_parse(doc
, nact
))) {
52 /* validate that its okay for a key binding */
53 if (action
->func
== action_moveresize
&&
54 action
->data
.moveresize
.corner
!=
55 prop_atoms
.net_wm_moveresize_move_keyboard
&&
56 action
->data
.moveresize
.corner
!=
57 prop_atoms
.net_wm_moveresize_size_keyboard
) {
63 kbind(keylist
, action
);
65 nact
= parse_find_node("action", nact
->next
);
70 static void parse_xml(xmlDocPtr doc
, xmlNodePtr node
, void *d
)
72 parse_key(doc
, node
->xmlChildrenNode
, NULL
);
75 void plugin_setup_config()
77 parse_register("keyboard", parse_xml
, NULL
);
80 KeyBindingTree
*firstnode
= NULL
;
82 static KeyBindingTree
*curpos
;
83 static guint reset_key
, reset_state
;
84 static ObTimer
*chain_timer
;
86 static void grab_for_window(Window win
, gboolean grab
)
93 p
= curpos
? curpos
->first_child
: firstnode
;
95 grab_key(p
->key
, p
->state
, win
, GrabModeAsync
);
99 grab_key(reset_key
, reset_state
, win
, GrabModeAsync
);
103 static void grab_keys(gboolean grab
)
107 grab_for_window(screen_support_win
, grab
);
108 for (it
= client_list
; it
; it
= g_list_next(it
))
109 grab_for_window(((ObClient
*)it
->data
)->frame
->window
, grab
);
112 static void reset_chains()
115 timer_stop(chain_timer
);
124 static void chain_timeout(void *data
)
129 gboolean
kbind(GList
*keylist
, Action
*action
)
131 KeyBindingTree
*tree
, *t
;
134 g_assert(keylist
!= NULL
);
135 g_assert(action
!= NULL
);
137 if (!(tree
= tree_build(keylist
)))
140 if ((t
= tree_find(tree
, &conflict
)) != NULL
) {
141 /* already bound to something, use the existing tree */
146 while (t
->first_child
) t
= t
->first_child
;
149 g_warning("conflict with binding");
155 t
->actions
= g_slist_append(t
->actions
, action
);
156 /* assimilate this built tree into the main tree. assimilation
157 destroys/uses the tree */
158 if (tree
) tree_assimilate(tree
);
163 static void event(ObEvent
*e
, void *foo
)
165 static KeyBindingTree
*grabbed_key
= NULL
;
167 if (e
->type
== Event_Client_Mapped
) {
168 grab_for_window(e
->data
.c
.client
->window
, TRUE
);
170 } else if (e
->type
== Event_Client_Destroy
) {
171 grab_for_window(e
->data
.c
.client
->window
, FALSE
);
176 gboolean done
= FALSE
;
178 if ((e
->type
== Event_X_KeyRelease
&&
179 !(grabbed_key
->state
& e
->data
.x
.e
->xkey
.state
)))
181 else if (e
->type
== Event_X_KeyPress
) {
182 if (e
->data
.x
.e
->xkey
.keycode
== ob_keycode(OB_KEY_RETURN
))
184 else if (e
->data
.x
.e
->xkey
.keycode
== ob_keycode(OB_KEY_ESCAPE
)) {
186 for (it
= grabbed_key
->actions
; it
; it
= it
->next
) {
187 Action
*act
= it
->data
;
188 act
->data
.cycle
.cancel
= TRUE
;
195 for (it
= grabbed_key
->actions
; it
; it
= it
->next
) {
196 Action
*act
= it
->data
;
197 act
->data
.cycle
.final
= TRUE
;
198 act
->func(&act
->data
);
201 grab_keyboard(FALSE
);
206 if (e
->type
== Event_X_KeyRelease
)
209 g_assert(e
->type
== Event_X_KeyPress
);
211 if (e
->data
.x
.e
->xkey
.keycode
== reset_key
&&
212 e
->data
.x
.e
->xkey
.state
== reset_state
) {
219 p
= curpos
->first_child
;
221 if (p
->key
== e
->data
.x
.e
->xkey
.keycode
&&
222 p
->state
== e
->data
.x
.e
->xkey
.state
) {
223 if (p
->first_child
!= NULL
) { /* part of a chain */
224 if (chain_timer
) timer_stop(chain_timer
);
225 /* 5 second timeout for chains */
226 chain_timer
= timer_start(5000*1000, chain_timeout
,
232 for (it
= p
->actions
; it
; it
= it
->next
) {
233 Action
*act
= it
->data
;
234 if (act
->func
!= NULL
) {
235 act
->data
.any
.c
= focus_client
;
237 if (act
->func
== action_cycle_windows
) {
238 act
->data
.cycle
.final
= FALSE
;
239 act
->data
.cycle
.cancel
= FALSE
;
242 if (act
->func
== action_moveresize
) {
243 screen_pointer_pos(&act
->data
.moveresize
.x
,
244 &act
->data
.moveresize
.y
);
247 if (act
->func
== action_cycle_windows
&&
248 !grabbed_key
&& grab_keyboard(TRUE
)) {
252 if (act
->func
== action_showmenu
) {
253 act
->data
.showmenu
.x
= e
->data
.x
.e
->xkey
.x_root
;
254 act
->data
.showmenu
.y
= e
->data
.x
.e
->xkey
.y_root
;
257 act
->data
.any
.c
= focus_client
;
258 act
->func(&act
->data
);
271 void plugin_startup()
276 dispatch_register(Event_Client_Mapped
| Event_Client_Destroy
|
277 Event_X_KeyPress
| Event_X_KeyRelease
,
278 (EventHandler
)event
, NULL
);
280 translate_key("C-g", &reset_state
, &reset_key
);
285 void plugin_shutdown()
287 dispatch_register(0, (EventHandler
)event
, NULL
);
289 tree_destroy(firstnode
);