diff options
author | Mathias Gumz <akira at fluxbox dot org> | 2011-08-26 07:21:50 (GMT) |
---|---|---|
committer | Mathias Gumz <akira at fluxbox dot org> | 2011-08-26 07:21:50 (GMT) |
commit | ec6df5c3d19ed760f343d6755ad396b00ac8f4ea (patch) | |
tree | e07b0b28097d33667b5ee82ce997779c9cb2f96f | |
parent | 7b10649e281187980e84fdb81fa27e2bae0b8842 (diff) | |
download | fluxbox-ec6df5c3d19ed760f343d6755ad396b00ac8f4ea.zip fluxbox-ec6df5c3d19ed760f343d6755ad396b00ac8f4ea.tar.bz2 |
bugfix: remap keysyms to keycodes after 'MappingNotify', fix #3386257
setxkbmap and xmodmap both might change the keycodes. thus fluxbox needs
to remap the keysyms from the currently loaded keytree to new keycodes
after it received a 'MappingNotify' event.
we do not reload() the keys file because:
* the user might work on it right now
* remap only needed symbols is cheaper than parsing the keysfile anyway
-rw-r--r-- | src/Keys.cc | 36 |
1 files changed, 25 insertions, 11 deletions
diff --git a/src/Keys.cc b/src/Keys.cc index 79c273b..5d59701 100644 --- a/src/Keys.cc +++ b/src/Keys.cc | |||
@@ -137,7 +137,7 @@ public: | |||
137 | typedef std::list<t_key*> keylist_t; | 137 | typedef std::list<t_key*> keylist_t; |
138 | 138 | ||
139 | // constructor / destructor | 139 | // constructor / destructor |
140 | t_key(int type, unsigned int mod, unsigned int key, int context, | 140 | t_key(int type, unsigned int mod, unsigned int key, const char* key_str, int context, |
141 | bool isdouble); | 141 | bool isdouble); |
142 | t_key(t_key *k); | 142 | t_key(t_key *k); |
143 | ~t_key(); | 143 | ~t_key(); |
@@ -162,6 +162,7 @@ public: | |||
162 | int type; // KeyPress or ButtonPress | 162 | int type; // KeyPress or ButtonPress |
163 | unsigned int mod; | 163 | unsigned int mod; |
164 | unsigned int key; // key code or button number | 164 | unsigned int key; // key code or button number |
165 | std::string key_str; // key-symbol, needed for regrab() | ||
165 | int context; // ON_TITLEBAR, etc.: bitwise-or of all desired contexts | 166 | int context; // ON_TITLEBAR, etc.: bitwise-or of all desired contexts |
166 | bool isdouble; | 167 | bool isdouble; |
167 | FbTk::RefCount<FbTk::Command<void> > m_command; | 168 | FbTk::RefCount<FbTk::Command<void> > m_command; |
@@ -170,6 +171,7 @@ public: | |||
170 | }; | 171 | }; |
171 | 172 | ||
172 | Keys::t_key::t_key(int type_, unsigned int mod_, unsigned int key_, | 173 | Keys::t_key::t_key(int type_, unsigned int mod_, unsigned int key_, |
174 | const char* key_str_, | ||
173 | int context_, bool isdouble_) : | 175 | int context_, bool isdouble_) : |
174 | type(type_), | 176 | type(type_), |
175 | mod(mod_), | 177 | mod(mod_), |
@@ -177,6 +179,10 @@ Keys::t_key::t_key(int type_, unsigned int mod_, unsigned int key_, | |||
177 | context(context_), | 179 | context(context_), |
178 | isdouble(isdouble_), | 180 | isdouble(isdouble_), |
179 | m_command(0) { | 181 | m_command(0) { |
182 | |||
183 | if (key_str_) { | ||
184 | key_str.assign(key_str_); | ||
185 | } | ||
180 | context = context_ ? context_ : GLOBAL; | 186 | context = context_ ? context_ : GLOBAL; |
181 | } | 187 | } |
182 | 188 | ||
@@ -319,7 +325,7 @@ void Keys::reload() { | |||
319 | // free memory of previous grabs | 325 | // free memory of previous grabs |
320 | deleteTree(); | 326 | deleteTree(); |
321 | 327 | ||
322 | m_map["default:"] = new t_key(0,0,0,0,false); | 328 | m_map["default:"] = new t_key(0,0,0,0,0,false); |
323 | 329 | ||
324 | unsigned int current_line = 0; //so we can tell the user where the fault is | 330 | unsigned int current_line = 0; //so we can tell the user where the fault is |
325 | 331 | ||
@@ -349,7 +355,7 @@ void Keys::loadDefaults() { | |||
349 | fbdbg<<"Loading default key bindings"<<endl; | 355 | fbdbg<<"Loading default key bindings"<<endl; |
350 | 356 | ||
351 | deleteTree(); | 357 | deleteTree(); |
352 | m_map["default:"] = new t_key(0,0,0,0,false); | 358 | m_map["default:"] = new t_key(0,0,0,0,0,false); |
353 | addBinding("OnDesktop Mouse1 :HideMenus"); | 359 | addBinding("OnDesktop Mouse1 :HideMenus"); |
354 | addBinding("OnDesktop Mouse2 :WorkspaceMenu"); | 360 | addBinding("OnDesktop Mouse2 :WorkspaceMenu"); |
355 | addBinding("OnDesktop Mouse3 :RootMenu"); | 361 | addBinding("OnDesktop Mouse3 :RootMenu"); |
@@ -389,7 +395,7 @@ bool Keys::addBinding(const string &linebuffer) { | |||
389 | argc++; | 395 | argc++; |
390 | keyspace_t::iterator it = m_map.find(val[0]); | 396 | keyspace_t::iterator it = m_map.find(val[0]); |
391 | if (it == m_map.end()) | 397 | if (it == m_map.end()) |
392 | m_map[val[0]] = new t_key(0,0,0,0,false); | 398 | m_map[val[0]] = new t_key(0,0,0,0,0,false); |
393 | current_key = m_map[val[0]]; | 399 | current_key = m_map[val[0]]; |
394 | } | 400 | } |
395 | // for each argument | 401 | // for each argument |
@@ -399,6 +405,8 @@ bool Keys::addBinding(const string &linebuffer) { | |||
399 | 405 | ||
400 | if (arg[0] != ':') { // parse key(s) | 406 | if (arg[0] != ':') { // parse key(s) |
401 | 407 | ||
408 | const char* key_str = 0; | ||
409 | |||
402 | int tmpmod = FbTk::KeyUtil::getModifier(arg.c_str()); | 410 | int tmpmod = FbTk::KeyUtil::getModifier(arg.c_str()); |
403 | if(tmpmod) | 411 | if(tmpmod) |
404 | mod |= tmpmod; //If it's a modifier | 412 | mod |= tmpmod; //If it's a modifier |
@@ -462,6 +470,7 @@ bool Keys::addBinding(const string &linebuffer) { | |||
462 | 470 | ||
463 | } else if ((key = FbTk::KeyUtil::getKey(val[argc].c_str()))) { // convert from string symbol | 471 | } else if ((key = FbTk::KeyUtil::getKey(val[argc].c_str()))) { // convert from string symbol |
464 | type = KeyPress; | 472 | type = KeyPress; |
473 | key_str = val[argc].c_str(); | ||
465 | 474 | ||
466 | // keycode covers the following three two-byte cases: | 475 | // keycode covers the following three two-byte cases: |
467 | // 0x - hex | 476 | // 0x - hex |
@@ -484,13 +493,13 @@ bool Keys::addBinding(const string &linebuffer) { | |||
484 | current_key = current_key->find(type, mod, key, context, | 493 | current_key = current_key->find(type, mod, key, context, |
485 | isdouble); | 494 | isdouble); |
486 | if (!current_key) { | 495 | if (!current_key) { |
487 | first_new_key = new t_key(type, mod, key, context, | 496 | first_new_key = new t_key(type, mod, key, key_str, context, |
488 | isdouble); | 497 | isdouble); |
489 | current_key = first_new_key; | 498 | current_key = first_new_key; |
490 | } else if (current_key->m_command) // already being used | 499 | } else if (current_key->m_command) // already being used |
491 | return false; | 500 | return false; |
492 | } else { | 501 | } else { |
493 | t_key *temp_key = new t_key(type, mod, key, context, | 502 | t_key *temp_key = new t_key(type, mod, key, key_str, context, |
494 | isdouble); | 503 | isdouble); |
495 | current_key->keylist.push_back(temp_key); | 504 | current_key->keylist.push_back(temp_key); |
496 | current_key = temp_key; | 505 | current_key = temp_key; |
@@ -654,12 +663,17 @@ void Keys::setKeyMode(t_key *keyMode) { | |||
654 | t_key::keylist_t::iterator it = keyMode->keylist.begin(); | 663 | t_key::keylist_t::iterator it = keyMode->keylist.begin(); |
655 | t_key::keylist_t::iterator it_end = keyMode->keylist.end(); | 664 | t_key::keylist_t::iterator it_end = keyMode->keylist.end(); |
656 | for (; it != it_end; ++it) { | 665 | for (; it != it_end; ++it) { |
657 | if ((*it)->type == KeyPress) | 666 | t_key* t = *it; |
658 | grabKey((*it)->key, (*it)->mod); | 667 | if (t->type == KeyPress) { |
659 | else | 668 | if (!t->key_str.empty()) { |
660 | grabButton((*it)->key, (*it)->mod, (*it)->context); | 669 | int key = FbTk::KeyUtil::getKey(t->key_str.c_str()); |
670 | t->key = key; | ||
671 | } | ||
672 | grabKey(t->key, t->mod); | ||
673 | } else { | ||
674 | grabButton(t->key, t->mod, t->context); | ||
675 | } | ||
661 | } | 676 | } |
662 | m_keylist = keyMode; | 677 | m_keylist = keyMode; |
663 | } | 678 | } |
664 | 679 | ||
665 | |||