]> Dogcows Code - chaz/openbox/blob - src/bindings.cc
so close to keybindings. wont link for now.
[chaz/openbox] / src / bindings.cc
1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2
3 #ifdef HAVE_CONFIG_H
4 # include "../config.h"
5 #endif
6
7 #include "bindings.hh"
8 #include "screen.hh"
9 #include "openbox.hh"
10 #include "client.hh"
11 #include "frame.hh"
12 #include "python.hh"
13 #include "otk/display.hh"
14
15 extern "C" {
16 #include <X11/Xlib.h>
17
18 #include "gettext.h"
19 #define _(str) gettext(str)
20 }
21
22 namespace ob {
23
24 #include <stdio.h>
25 static void print_branch(const BindingTree *first, std::string str)
26 {
27 const BindingTree *p = first;
28
29 while (p) {
30 if (p->first_child)
31 print_branch(p->first_child, str + " " + p->text);
32 if (!p->chain)
33 printf("%d%s\n", p->id, (str + " " + p->text).c_str());
34 p = p->next_sibling;
35 }
36 }
37
38
39 void OBBindings::display()
40 {
41 if (_keytree.first_child) {
42 printf("Key Tree:\n");
43 print_branch(_keytree.first_child, "");
44 }
45 if (_mousetree) {
46 printf("Mouse Tree:\n");
47 BindingTree *p = _mousetree;
48 while (p) {
49 printf("%d %s\n", p->id, p->text.c_str());
50 p = p->next_sibling;
51 }
52 }
53 }
54
55
56 static bool buttonvalue(const std::string &button, unsigned int *val)
57 {
58 if (button == "1" || button == "Button1") {
59 *val |= Button1;
60 } else if (button == "2" || button == "Button2") {
61 *val |= Button2;
62 } else if (button == "3" || button == "Button3") {
63 *val |= Button3;
64 } else if (button == "4" || button == "Button4") {
65 *val |= Button4;
66 } else if (button == "5" || button == "Button5") {
67 *val |= Button5;
68 } else
69 return false;
70 return true;
71 }
72
73 static bool modvalue(const std::string &mod, unsigned int *val)
74 {
75 if (mod == "C") { // control
76 *val |= ControlMask;
77 } else if (mod == "S") { // shift
78 *val |= ShiftMask;
79 } else if (mod == "A" || // alt/mod1
80 mod == "M" ||
81 mod == "Mod1" ||
82 mod == "M1") {
83 *val |= Mod1Mask;
84 } else if (mod == "Mod2" || // mod2
85 mod == "M2") {
86 *val |= Mod2Mask;
87 } else if (mod == "Mod3" || // mod3
88 mod == "M3") {
89 *val |= Mod3Mask;
90 } else if (mod == "W" || // windows/mod4
91 mod == "Mod4" ||
92 mod == "M4") {
93 *val |= Mod4Mask;
94 } else if (mod == "Mod5" || // mod5
95 mod == "M5") {
96 *val |= Mod5Mask;
97 } else { // invalid
98 return false;
99 }
100 return true;
101 }
102
103 bool OBBindings::translate(const std::string &str, Binding &b,
104 bool askey) const
105 {
106 // parse out the base key name
107 std::string::size_type keybegin = str.find_last_of('-');
108 keybegin = (keybegin == std::string::npos) ? 0 : keybegin + 1;
109 std::string key(str, keybegin);
110
111 // parse out the requested modifier keys
112 unsigned int modval = 0;
113 std::string::size_type begin = 0, end;
114 while (begin != keybegin) {
115 end = str.find_first_of('-', begin);
116
117 std::string mod(str, begin, end-begin);
118 if (!modvalue(mod, &modval)) {
119 // printf(_("Invalid modifier element in key binding: %s\n"), mod.c_str());
120 return false;
121 }
122
123 begin = end + 1;
124 }
125
126 // set the binding
127 b.modifiers = modval;
128 if (askey) {
129 KeySym sym = XStringToKeysym(const_cast<char *>(key.c_str()));
130 if (sym == NoSymbol) return false;
131 b.key = XKeysymToKeycode(otk::OBDisplay::display, sym);
132 return b.key != 0;
133 } else {
134 return buttonvalue(key, &b.key);
135 }
136 }
137
138 static void destroytree(BindingTree *tree)
139 {
140 while (tree) {
141 BindingTree *c = tree->first_child;
142 delete tree;
143 tree = c;
144 }
145 }
146
147 BindingTree *OBBindings::buildtree(const StringVect &keylist, int id) const
148 {
149 if (keylist.empty()) return 0; // nothing in the list.. return 0
150
151 BindingTree *ret = 0, *p;
152
153 StringVect::const_reverse_iterator it, end = keylist.rend();
154 for (it = keylist.rbegin(); it != end; ++it) {
155 p = ret;
156 ret = new BindingTree(id);
157 if (!p) ret->chain = false; // only the first built node
158 ret->first_child = p;
159 if (!translate(*it, ret->binding, true)) {
160 destroytree(ret);
161 ret = 0;
162 break;
163 }
164 ret->text = *it; // XXX: rm me
165 }
166 return ret;
167 }
168
169
170 OBBindings::OBBindings()
171 : _curpos(&_keytree), _mousetree(0)
172 {
173 }
174
175
176 OBBindings::~OBBindings()
177 {
178 grabMouseOnAll(false); // ungrab everything
179 grabKeys(false);
180 remove_all();
181 }
182
183
184 bool OBBindings::add_mouse(const std::string &button, int id)
185 {
186 BindingTree n;
187
188 if (!translate(button, n.binding, false))
189 return false;
190
191 BindingTree *p = _mousetree, **newp = &_mousetree;
192 while (p) {
193 if (p->binding == n.binding)
194 return false; // conflict
195 p = p->next_sibling;
196 newp = &p->next_sibling;
197 }
198
199 grabMouseOnAll(false); // ungrab everything
200
201 *newp = new BindingTree(id);
202 (*newp)->text = button;
203 (*newp)->chain = false;
204 (*newp)->binding.key = n.binding.key;
205 (*newp)->binding.modifiers = n.binding.modifiers;
206
207 grabMouseOnAll(true);
208
209 return true;
210 }
211
212
213 int OBBindings::remove_mouse(const std::string &button)
214 {
215 (void)button;
216 assert(false); // XXX: function not implemented yet
217
218 grabMouseOnAll(false); // ungrab everything
219
220 // do shit...
221
222 grabMouseOnAll(true);
223 }
224
225
226 void OBBindings::assimilate(BindingTree *node)
227 {
228 BindingTree *a, *b, *tmp, *last;
229
230 if (!_keytree.first_child) {
231 // there are no nodes at this level yet
232 _keytree.first_child = node;
233 } else {
234 a = _keytree.first_child;
235 last = a;
236 b = node;
237 while (a) {
238 last = a;
239 if (a->binding != b->binding) {
240 a = a->next_sibling;
241 } else {
242 tmp = b;
243 b = b->first_child;
244 delete tmp;
245 a = a->first_child;
246 }
247 }
248 if (last->binding != b->binding)
249 last->next_sibling = b;
250 else {
251 last->first_child = b->first_child;
252 delete b;
253 }
254 }
255 }
256
257
258 int OBBindings::find_key(BindingTree *search) const {
259 BindingTree *a, *b;
260 a = _keytree.first_child;
261 b = search;
262 while (a && b) {
263 if (a->binding != b->binding) {
264 a = a->next_sibling;
265 } else {
266 if (a->chain == b->chain) {
267 if (!a->chain) {
268 return a->id; // found it! (return the actual id, not the search's)
269 }
270 } else {
271 return -2; // the chain status' don't match (conflict!)
272 }
273 b = b->first_child;
274 a = a->first_child;
275 }
276 }
277 return -1; // it just isn't in here
278 }
279
280
281 bool OBBindings::add_key(const StringVect &keylist, int id)
282 {
283 BindingTree *tree;
284
285 if (!(tree = buildtree(keylist, id)))
286 return false; // invalid binding requested
287
288 if (find_key(tree) != -1) {
289 // conflicts with another binding
290 destroytree(tree);
291 return false;
292 }
293
294 grabKeys(false);
295
296 // assimilate this built tree into the main tree
297 assimilate(tree); // assimilation destroys/uses the tree
298
299 grabKeys(true);
300
301 return true;
302 }
303
304
305 int OBBindings::find_key(const StringVect &keylist)
306 {
307 BindingTree *tree;
308 bool ret;
309
310 if (!(tree = buildtree(keylist, 0)))
311 return false; // invalid binding requested
312
313 ret = find_key(tree) >= 0;
314
315 destroytree(tree);
316
317 return ret;
318 }
319
320
321 int OBBindings::remove_key(const StringVect &keylist)
322 {
323 (void)keylist;
324 assert(false); // XXX: function not implemented yet
325
326 grabKeys(false);
327 _curpos = &_keytree;
328
329 // do shit here...
330
331 grabKeys(true);
332
333 }
334
335
336 static void remove_branch(BindingTree *first)
337 {
338 BindingTree *p = first;
339
340 while (p) {
341 if (p->first_child)
342 remove_branch(p->first_child);
343 BindingTree *s = p->next_sibling;
344 delete p;
345 p = s;
346 }
347 }
348
349
350 void OBBindings::remove_all()
351 {
352 if (_keytree.first_child) {
353 remove_branch(_keytree.first_child);
354 _keytree.first_child = 0;
355 }
356 BindingTree *p = _mousetree;
357 while (p) {
358 BindingTree *n = p->next_sibling;
359 delete p;
360 p = n;
361 }
362 _mousetree = 0;
363 }
364
365
366 void OBBindings::process(unsigned int modifiers, unsigned int key)
367 {
368 BindingTree *c = _curpos->first_child;
369
370 while (c) {
371 if (c->binding.key == key && c->binding.modifiers == modifiers) {
372 _curpos = c;
373 break;
374 }
375 }
376 if (c) {
377 if (!_curpos->chain) {
378 // XXX execute command for _curpos->id
379 _curpos = &_keytree; // back to the start
380 }
381 }
382 }
383
384
385 void OBBindings::grabMouse(bool grab, const OBClient *client)
386 {
387 BindingTree *p = _mousetree;
388 while (p) {
389 if (grab)
390 otk::OBDisplay::grabButton(p->binding.key, p->binding.modifiers,
391 client->frame->window(), false,
392 ButtonMotionMask | ButtonPressMask |
393 ButtonReleaseMask, GrabModeAsync,
394 GrabModeAsync, None, None, false);
395 else
396 otk::OBDisplay::ungrabButton(p->binding.key, p->binding.modifiers,
397 client->frame->window());
398 p = p->next_sibling;
399 }
400 }
401
402
403 void OBBindings::grabMouseOnAll(bool grab)
404 {
405 for (int i = 0; i < Openbox::instance->screenCount(); ++i) {
406 OBScreen *s = Openbox::instance->screen(i);
407 assert(s);
408 OBScreen::ClientList::iterator it, end = s->clients.end();
409 for (it = s->clients.begin(); it != end; ++it)
410 grabMouse(grab, *it);
411 }
412 }
413
414
415 void OBBindings::grabKeys(bool grab)
416 {
417 for (int i = 0; i < Openbox::instance->screenCount(); ++i) {
418 Window root = otk::OBDisplay::screenInfo(i)->rootWindow();
419
420 BindingTree *p = _curpos->first_child;
421 while (p) {
422 if (grab)
423 otk::OBDisplay::grabKey(p->binding.key, p->binding.modifiers,
424 root, false, GrabModeAsync, GrabModeAsync,
425 false);
426 else
427 otk::OBDisplay::ungrabKey(p->binding.key, p->binding.modifiers,
428 root);
429 p = p->next_sibling;
430 }
431 }
432 }
433
434
435 void OBBindings::fire(OBActions::ActionType type, Window window,
436 unsigned int modifiers, unsigned int key, Time time)
437 {
438 if (type == OBActions::Action_KeyPress) {
439 BindingTree *p = _curpos->first_child;
440 while (p) {
441 if (p->binding.key == key && p->binding.modifiers == modifiers) {
442 if (p->chain) {
443 grabKeys(false);
444 _curpos = p;
445 grabKeys(true);
446 } else {
447 python_callback_binding(p->id, type, window, modifiers, key, time);
448 _curpos = &_keytree;
449 }
450 break;
451 }
452 p = p->next_sibling;
453 }
454
455 assert(false);
456 } else {
457 BindingTree *p = _mousetree;
458 while (p) {
459 if (p->binding.key == key && p->binding.modifiers == modifiers) {
460 python_callback_binding(p->id, type, window, modifiers, key, time);
461 break;
462 }
463 p = p->next_sibling;
464 }
465 }
466 }
467
468
469 }
This page took 0.054699 seconds and 4 git commands to generate.