]> Dogcows Code - chaz/openbox/blob - openbox/keyboard.c
move the keyboard and mouse plugins into the kernel for mucho sexiness.
[chaz/openbox] / openbox / keyboard.c
1 #include "focus.h"
2 #include "screen.h"
3 #include "frame.h"
4 #include "openbox.h"
5 #include "event.h"
6 #include "grab.h"
7 #include "client.h"
8 #include "action.h"
9 #include "prop.h"
10 #include "timer.h"
11 #include "keytree.h"
12 #include "keyboard.h"
13 #include "translate.h"
14
15 #include <glib.h>
16
17 KeyBindingTree *keyboard_firstnode;
18
19 static KeyBindingTree *curpos;
20 static ObTimer *chain_timer;
21 static gboolean interactive_grab;
22 static guint grabbed_state;
23 static ObClient *grabbed_client;
24 static ObAction *grabbed_action;
25 static ObFrameContext grabbed_context;
26
27 static void grab_for_window(Window win, gboolean grab)
28 {
29 KeyBindingTree *p;
30
31 ungrab_all_keys(win);
32
33 if (grab) {
34 p = curpos ? curpos->first_child : keyboard_firstnode;
35 while (p) {
36 grab_key(p->key, p->state, win, GrabModeAsync);
37 p = p->next_sibling;
38 }
39 }
40 }
41
42 void keyboard_grab_for_client(ObClient *c, gboolean grab)
43 {
44 grab_for_window(c->window, grab);
45 }
46
47 static void grab_keys(gboolean grab)
48 {
49 GList *it;
50
51 grab_for_window(screen_support_win, grab);
52 for (it = client_list; it; it = g_list_next(it))
53 grab_for_window(((ObClient*)it->data)->frame->window, grab);
54 }
55
56 void keyboard_reset_chains()
57 {
58 if (chain_timer) {
59 timer_stop(chain_timer);
60 chain_timer = NULL;
61 }
62 if (curpos) {
63 curpos = NULL;
64 grab_keys(TRUE);
65 }
66 }
67
68 static void chain_timeout(ObTimer *t, void *data)
69 {
70 keyboard_reset_chains();
71 }
72
73 gboolean keyboard_bind(GList *keylist, ObAction *action)
74 {
75 KeyBindingTree *tree, *t;
76 gboolean conflict;
77
78 g_assert(keylist != NULL);
79 g_assert(action != NULL);
80
81 if (!(tree = tree_build(keylist)))
82 return FALSE;
83
84 if ((t = tree_find(tree, &conflict)) != NULL) {
85 /* already bound to something, use the existing tree */
86 tree_destroy(tree);
87 tree = NULL;
88 } else
89 t = tree;
90 while (t->first_child) t = t->first_child;
91
92 if (conflict) {
93 g_warning("conflict with binding");
94 tree_destroy(tree);
95 return FALSE;
96 }
97
98 /* set the action */
99 t->actions = g_slist_append(t->actions, action);
100 /* assimilate this built tree into the main tree. assimilation
101 destroys/uses the tree */
102 if (tree) tree_assimilate(tree);
103
104 return TRUE;
105 }
106
107 void keyboard_interactive_grab(guint state, ObClient *client,
108 ObFrameContext context, ObAction *action)
109 {
110 if (!interactive_grab && grab_keyboard(TRUE)) {
111 interactive_grab = TRUE;
112 grabbed_state = state;
113 grabbed_client = client;
114 grabbed_action = action;
115 grabbed_context = context;
116 grab_pointer(TRUE, None);
117 }
118 }
119
120 gboolean keyboard_process_interactive_grab(const XEvent *e,
121 ObClient **client,
122 ObFrameContext *context)
123 {
124 gboolean handled = FALSE;
125 gboolean done = FALSE;
126
127 if (interactive_grab) {
128 *client = grabbed_client;
129 *context = grabbed_context;
130 }
131
132 if ((e->type == KeyRelease &&
133 !(grabbed_state & e->xkey.state)))
134 done = TRUE;
135 else if (e->type == KeyPress) {
136 if (e->xkey.keycode == ob_keycode(OB_KEY_RETURN))
137 done = TRUE;
138 else if (e->xkey.keycode == ob_keycode(OB_KEY_ESCAPE)) {
139 if (grabbed_action->func == action_cycle_windows) {
140 grabbed_action->data.cycle.cancel = TRUE;
141 }
142 if (grabbed_action->func == action_desktop_dir) {
143 grabbed_action->data.desktopdir.cancel = TRUE;
144 }
145 if (grabbed_action->func == action_send_to_desktop_dir)
146 {
147 grabbed_action->data.sendtodir.cancel = TRUE;
148 }
149 done = TRUE;
150 }
151 }
152 if (done) {
153 if (grabbed_action->func == action_cycle_windows) {
154 grabbed_action->data.cycle.final = TRUE;
155 }
156 if (grabbed_action->func == action_desktop_dir) {
157 grabbed_action->data.desktopdir.final = TRUE;
158 }
159 if (grabbed_action->func == action_send_to_desktop_dir) {
160 grabbed_action->data.sendtodir.final = TRUE;
161 }
162
163 grabbed_action->func(&grabbed_action->data);
164
165 interactive_grab = FALSE;
166 grab_keyboard(FALSE);
167 grab_pointer(FALSE, None);
168 keyboard_reset_chains();
169
170 handled = TRUE;
171 }
172
173 return handled;
174 }
175
176 void keyboard_event(ObClient *client, const XEvent *e)
177 {
178 KeyBindingTree *p;
179
180 g_assert(e->type == KeyPress);
181
182 if (curpos == NULL)
183 p = keyboard_firstnode;
184 else
185 p = curpos->first_child;
186 while (p) {
187 if (p->key == e->xkey.keycode &&
188 p->state == e->xkey.state) {
189 if (p->first_child != NULL) { /* part of a chain */
190 if (chain_timer) timer_stop(chain_timer);
191 /* 5 second timeout for chains */
192 chain_timer = timer_start(5000*1000, chain_timeout,
193 NULL);
194 curpos = p;
195 grab_keys(TRUE);
196 } else {
197 GSList *it;
198 for (it = p->actions; it; it = it->next) {
199 ObAction *act = it->data;
200 if (act->func != NULL) {
201 act->data.any.c = client;
202
203 if (act->func == action_cycle_windows)
204 {
205 act->data.cycle.final = FALSE;
206 act->data.cycle.cancel = FALSE;
207 }
208 if (act->func == action_desktop_dir)
209 {
210 act->data.desktopdir.final = FALSE;
211 act->data.desktopdir.cancel = FALSE;
212 }
213 if (act->func == action_send_to_desktop_dir)
214 {
215 act->data.sendtodir.final = FALSE;
216 act->data.sendtodir.cancel = FALSE;
217 }
218
219 if (act->func == action_moveresize)
220 {
221 screen_pointer_pos(&act->data.moveresize.x,
222 &act->data.moveresize.y);
223 }
224
225 if ((act->func == action_cycle_windows ||
226 act->func == action_desktop_dir ||
227 act->func == action_send_to_desktop_dir))
228 {
229 keyboard_interactive_grab(e->xkey.state, client,
230 0, act);
231 }
232
233 if (act->func == action_showmenu)
234 {
235 act->data.showmenu.x =
236 e->xkey.x_root;
237 act->data.showmenu.y =
238 e->xkey.y_root;
239 }
240
241 act->data.any.c = client;
242 act->func(&act->data);
243 }
244 }
245
246 keyboard_reset_chains();
247 }
248 break;
249 }
250 p = p->next_sibling;
251 }
252 }
253
254 void keyboard_startup()
255 {
256 grab_keys(TRUE);
257 }
258
259 void keyboard_shutdown()
260 {
261 tree_destroy(keyboard_firstnode);
262 keyboard_firstnode = NULL;
263 grab_keys(FALSE);
264 }
265
This page took 0.047137 seconds and 4 git commands to generate.