diff options
author | mathias <mathias> | 2005-05-06 09:22:53 (GMT) |
---|---|---|
committer | mathias <mathias> | 2005-05-06 09:22:53 (GMT) |
commit | 6c057c6903151aab92309310087d5af455ecefce (patch) | |
tree | 1d4c98ad1637df09b89593b3e6a4a70245db4602 /src/Keys.cc | |
parent | 7d4f711204ab0b51d45eaff332708f529c11c9f5 (diff) | |
download | fluxbox_pavel-6c057c6903151aab92309310087d5af455ecefce.zip fluxbox_pavel-6c057c6903151aab92309310087d5af455ecefce.tar.bz2 |
Fix for #1160244, #1099704, #1094107:
if the xkb-extension is enabled and the user switches between his/her
keyboardlayouts fluxbox's keybhandling doesn't work well anymore because
xkeyevent.state contains also xkb-related flags and thus we have to handle
that with caution.
KeyUtils now contain 'isolateModifierMask()' to really work only on the
modifiers. why not as part of cleanMods() ? because the XLookupString return
false results, eg TextBox's would only print chars from the first
keyboardlayout.
Diffstat (limited to 'src/Keys.cc')
-rw-r--r-- | src/Keys.cc | 76 |
1 files changed, 39 insertions, 37 deletions
diff --git a/src/Keys.cc b/src/Keys.cc index 96f57cb..0d3eecd 100644 --- a/src/Keys.cc +++ b/src/Keys.cc | |||
@@ -27,7 +27,6 @@ | |||
27 | #include "FbTk/StringUtil.hh" | 27 | #include "FbTk/StringUtil.hh" |
28 | #include "FbTk/App.hh" | 28 | #include "FbTk/App.hh" |
29 | #include "FbTk/Command.hh" | 29 | #include "FbTk/Command.hh" |
30 | #include "FbTk/KeyUtil.hh" | ||
31 | 30 | ||
32 | #include "CommandParser.hh" | 31 | #include "CommandParser.hh" |
33 | #include "FbTk/I18n.hh" | 32 | #include "FbTk/I18n.hh" |
@@ -81,6 +80,8 @@ | |||
81 | #include <X11/Xlib.h> | 80 | #include <X11/Xlib.h> |
82 | #include <X11/Xproto.h> | 81 | #include <X11/Xproto.h> |
83 | #include <X11/keysym.h> | 82 | #include <X11/keysym.h> |
83 | #include <X11/Xutil.h> | ||
84 | #include <X11/XKBlib.h> | ||
84 | 85 | ||
85 | #include <iostream> | 86 | #include <iostream> |
86 | #include <fstream> | 87 | #include <fstream> |
@@ -102,7 +103,7 @@ Keys::Keys(const char *filename): | |||
102 | load(filename); | 103 | load(filename); |
103 | } | 104 | } |
104 | 105 | ||
105 | Keys::~Keys() { | 106 | Keys::~Keys() { |
106 | 107 | ||
107 | FbTk::KeyUtil::ungrabKeys(); | 108 | FbTk::KeyUtil::ungrabKeys(); |
108 | deleteTree(); | 109 | deleteTree(); |
@@ -112,12 +113,12 @@ Keys::~Keys() { | |||
112 | void Keys::deleteTree() { | 113 | void Keys::deleteTree() { |
113 | while (!m_keylist.empty()) { | 114 | while (!m_keylist.empty()) { |
114 | if (m_keylist.back()) | 115 | if (m_keylist.back()) |
115 | delete m_keylist.back(); | 116 | delete m_keylist.back(); |
116 | m_keylist.pop_back(); | 117 | m_keylist.pop_back(); |
117 | } | 118 | } |
118 | } | 119 | } |
119 | 120 | ||
120 | /** | 121 | /** |
121 | Load and grab keys | 122 | Load and grab keys |
122 | TODO: error checking | 123 | TODO: error checking |
123 | @return true on success else false | 124 | @return true on success else false |
@@ -125,7 +126,7 @@ void Keys::deleteTree() { | |||
125 | bool Keys::load(const char *filename) { | 126 | bool Keys::load(const char *filename) { |
126 | if (!filename) | 127 | if (!filename) |
127 | return false; | 128 | return false; |
128 | 129 | ||
129 | //ungrab all keys | 130 | //ungrab all keys |
130 | FbTk::KeyUtil::ungrabKeys(); | 131 | FbTk::KeyUtil::ungrabKeys(); |
131 | 132 | ||
@@ -133,7 +134,7 @@ bool Keys::load(const char *filename) { | |||
133 | deleteTree(); | 134 | deleteTree(); |
134 | 135 | ||
135 | FbTk::App::instance()->sync(false); | 136 | FbTk::App::instance()->sync(false); |
136 | 137 | ||
137 | //open the file | 138 | //open the file |
138 | ifstream infile(filename); | 139 | ifstream infile(filename); |
139 | if (!infile) | 140 | if (!infile) |
@@ -158,8 +159,8 @@ bool Keys::load(const char *filename) { | |||
158 | 159 | ||
159 | bool Keys::save(const char *filename) const { | 160 | bool Keys::save(const char *filename) const { |
160 | //!! | 161 | //!! |
161 | //!! TODO: fix keybinding saving | 162 | //!! TODO: fix keybinding saving |
162 | //!! (we probably need to save key actions | 163 | //!! (we probably need to save key actions |
163 | //!! as strings instead of creating new Commands) | 164 | //!! as strings instead of creating new Commands) |
164 | 165 | ||
165 | // open file for writing | 166 | // open file for writing |
@@ -178,16 +179,16 @@ bool Keys::addBinding(const std::string &linebuffer) { | |||
178 | // must have at least 1 argument | 179 | // must have at least 1 argument |
179 | if (val.size() <= 0) | 180 | if (val.size() <= 0) |
180 | return true; // empty lines are valid. | 181 | return true; // empty lines are valid. |
181 | 182 | ||
182 | if (val[0][0] == '#' || val[0][0] == '!' ) //the line is commented | 183 | if (val[0][0] == '#' || val[0][0] == '!' ) //the line is commented |
183 | return true; // still a valid line. | 184 | return true; // still a valid line. |
184 | 185 | ||
185 | unsigned int key = 0, mod = 0; | 186 | unsigned int key = 0, mod = 0; |
186 | char keyarg = 0; | 187 | char keyarg = 0; |
187 | t_key *current_key=0, *last_key=0; | 188 | t_key *current_key=0, *last_key=0; |
188 | 189 | ||
189 | _FB_USES_NLS; | 190 | _FB_USES_NLS; |
190 | // for each argument | 191 | // for each argument |
191 | for (unsigned int argc=0; argc<val.size(); argc++) { | 192 | for (unsigned int argc=0; argc<val.size(); argc++) { |
192 | 193 | ||
193 | if (val[argc][0] != ':') { // parse key(s) | 194 | if (val[argc][0] != ':') { // parse key(s) |
@@ -199,7 +200,7 @@ bool Keys::addBinding(const std::string &linebuffer) { | |||
199 | int tmpmod = FbTk::KeyUtil::getModifier(val[argc].c_str()); | 200 | int tmpmod = FbTk::KeyUtil::getModifier(val[argc].c_str()); |
200 | if(tmpmod) | 201 | if(tmpmod) |
201 | mod |= tmpmod; //If it's a modifier | 202 | mod |= tmpmod; //If it's a modifier |
202 | else { | 203 | else { |
203 | key = FbTk::KeyUtil::getKey(val[argc].c_str()); // else get the key | 204 | key = FbTk::KeyUtil::getKey(val[argc].c_str()); // else get the key |
204 | if (key == 0) { | 205 | if (key == 0) { |
205 | cerr<<_FBTEXT(Keys, InvalidKeyMod, "Keys: Invalid key/modifier on line", "A bad key/modifier string was found on line (number following)")<<" "<< | 206 | cerr<<_FBTEXT(Keys, InvalidKeyMod, "Keys: Invalid key/modifier on line", "A bad key/modifier string was found on line (number following)")<<" "<< |
@@ -209,13 +210,13 @@ bool Keys::addBinding(const std::string &linebuffer) { | |||
209 | if (!current_key) { | 210 | if (!current_key) { |
210 | current_key = new t_key(key, mod); | 211 | current_key = new t_key(key, mod); |
211 | last_key = current_key; | 212 | last_key = current_key; |
212 | } else { | 213 | } else { |
213 | t_key *temp_key = new t_key(key, mod); | 214 | t_key *temp_key = new t_key(key, mod); |
214 | last_key->keylist.push_back(temp_key); | 215 | last_key->keylist.push_back(temp_key); |
215 | last_key = temp_key; | 216 | last_key = temp_key; |
216 | } | 217 | } |
217 | } | 218 | } |
218 | } | 219 | } |
219 | 220 | ||
220 | } else { // parse command line | 221 | } else { // parse command line |
221 | if (last_key == 0) { | 222 | if (last_key == 0) { |
@@ -224,7 +225,7 @@ bool Keys::addBinding(const std::string &linebuffer) { | |||
224 | return false; | 225 | return false; |
225 | } | 226 | } |
226 | bool ret_val = true; | 227 | bool ret_val = true; |
227 | const char *str = | 228 | const char *str = |
228 | FbTk::StringUtil::strcasestr(linebuffer.c_str(), | 229 | FbTk::StringUtil::strcasestr(linebuffer.c_str(), |
229 | val[argc].c_str() + 1); // +1 to skip ':' | 230 | val[argc].c_str() + 1); // +1 to skip ':' |
230 | if (str == 0) { | 231 | if (str == 0) { |
@@ -263,41 +264,42 @@ bool Keys::addBinding(const std::string &linebuffer) { | |||
263 | @return the KeyAction of the XKeyEvent | 264 | @return the KeyAction of the XKeyEvent |
264 | */ | 265 | */ |
265 | void Keys::doAction(XKeyEvent &ke) { | 266 | void Keys::doAction(XKeyEvent &ke) { |
266 | static t_key *next_key = 0; | 267 | |
267 | // Remove numlock, capslock and scrolllock | ||
268 | ke.state = FbTk::KeyUtil::instance().cleanMods(ke.state); | 268 | ke.state = FbTk::KeyUtil::instance().cleanMods(ke.state); |
269 | 269 | ||
270 | static struct t_key* next_key = 0; | ||
271 | |||
270 | if (!next_key) { | 272 | if (!next_key) { |
271 | 273 | ||
272 | for (unsigned int i=0; i<m_keylist.size(); i++) { | 274 | for (unsigned int i=0; i<m_keylist.size(); i++) { |
273 | if (*m_keylist[i] == ke) { | 275 | if (*m_keylist[i] == ke) { |
274 | if (m_keylist[i]->keylist.size()) { | 276 | if (m_keylist[i]->keylist.size()) { |
275 | next_key = m_keylist[i]; | 277 | next_key = m_keylist[i]; |
276 | break; //end for-loop | 278 | break; //end for-loop |
277 | } else { | 279 | } else { |
278 | if (*m_keylist[i]->m_command != 0) | 280 | if (*m_keylist[i]->m_command != 0) |
279 | m_keylist[i]->m_command->execute(); | 281 | m_keylist[i]->m_command->execute(); |
280 | } | 282 | } |
281 | } | 283 | } |
282 | } | 284 | } |
283 | 285 | ||
284 | } else { //check the nextkey | 286 | } else { //check the nextkey |
285 | t_key *temp_key = next_key->find(ke); | 287 | t_key *temp_key = next_key->find(ke); |
286 | if (temp_key) { | 288 | if (temp_key) { |
287 | if (temp_key->keylist.size()) { | 289 | if (temp_key->keylist.size()) { |
288 | next_key = temp_key; | 290 | next_key = temp_key; |
289 | } else { | 291 | } else { |
290 | next_key = 0; | 292 | next_key = 0; |
291 | if (*temp_key->m_command != 0) | 293 | if (*temp_key->m_command != 0) |
292 | temp_key->m_command->execute(); | 294 | temp_key->m_command->execute(); |
293 | } | 295 | } |
294 | } else { | 296 | } else { |
295 | temp_key = next_key; | 297 | temp_key = next_key; |
296 | next_key = 0; | 298 | next_key = 0; |
297 | if (*temp_key->m_command != 0) | 299 | if (*temp_key->m_command != 0) |
298 | temp_key->m_command->execute(); | 300 | temp_key->m_command->execute(); |
299 | 301 | ||
300 | } | 302 | } |
301 | } | 303 | } |
302 | } | 304 | } |
303 | 305 | ||
@@ -318,7 +320,7 @@ bool Keys::mergeTree(t_key *newtree, t_key *basetree) { | |||
318 | if (basetree==0) { | 320 | if (basetree==0) { |
319 | unsigned int baselist_i=0; | 321 | unsigned int baselist_i=0; |
320 | for (; baselist_i<m_keylist.size(); baselist_i++) { | 322 | for (; baselist_i<m_keylist.size(); baselist_i++) { |
321 | if (m_keylist[baselist_i]->mod == newtree->mod && | 323 | if (m_keylist[baselist_i]->mod == newtree->mod && |
322 | m_keylist[baselist_i]->key == newtree->key) { | 324 | m_keylist[baselist_i]->key == newtree->key) { |
323 | if (newtree->keylist.size() && *m_keylist[baselist_i]->m_command == 0) { | 325 | if (newtree->keylist.size() && *m_keylist[baselist_i]->m_command == 0) { |
324 | //assumes the newtree only have one branch | 326 | //assumes the newtree only have one branch |
@@ -330,12 +332,12 @@ bool Keys::mergeTree(t_key *newtree, t_key *basetree) { | |||
330 | 332 | ||
331 | if (baselist_i == m_keylist.size()) { | 333 | if (baselist_i == m_keylist.size()) { |
332 | FbTk::KeyUtil::grabKey(newtree->key, newtree->mod); | 334 | FbTk::KeyUtil::grabKey(newtree->key, newtree->mod); |
333 | m_keylist.push_back(new t_key(newtree)); | 335 | m_keylist.push_back(new t_key(newtree)); |
334 | if (newtree->keylist.size()) | 336 | if (newtree->keylist.size()) |
335 | return mergeTree(newtree->keylist[0], m_keylist.back()); | 337 | return mergeTree(newtree->keylist[0], m_keylist.back()); |
336 | return true; | 338 | return true; |
337 | } | 339 | } |
338 | 340 | ||
339 | } else { | 341 | } else { |
340 | unsigned int baselist_i = 0; | 342 | unsigned int baselist_i = 0; |
341 | for (; baselist_i<basetree->keylist.size(); baselist_i++) { | 343 | for (; baselist_i<basetree->keylist.size(); baselist_i++) { |
@@ -346,24 +348,24 @@ bool Keys::mergeTree(t_key *newtree, t_key *basetree) { | |||
346 | return mergeTree(newtree->keylist[0], basetree->keylist[baselist_i]); | 348 | return mergeTree(newtree->keylist[0], basetree->keylist[baselist_i]); |
347 | } else | 349 | } else |
348 | return false; | 350 | return false; |
349 | } | 351 | } |
350 | } | 352 | } |
351 | //if it wasn't in the list grab the key and add it to the list | 353 | //if it wasn't in the list grab the key and add it to the list |
352 | if (baselist_i==basetree->keylist.size()) { | 354 | if (baselist_i==basetree->keylist.size()) { |
353 | FbTk::KeyUtil::grabKey(newtree->key, newtree->mod); | 355 | FbTk::KeyUtil::grabKey(newtree->key, newtree->mod); |
354 | basetree->keylist.push_back(new t_key(newtree)); | 356 | basetree->keylist.push_back(new t_key(newtree)); |
355 | if (newtree->keylist.size()) | 357 | if (newtree->keylist.size()) |
356 | return mergeTree(newtree->keylist[0], basetree->keylist.back()); | 358 | return mergeTree(newtree->keylist[0], basetree->keylist.back()); |
357 | return true; | 359 | return true; |
358 | } | 360 | } |
359 | } | 361 | } |
360 | 362 | ||
361 | return false; | 363 | return false; |
362 | } | 364 | } |
363 | 365 | ||
364 | Keys::t_key::t_key(unsigned int key_, unsigned int mod_, FbTk::RefCount<FbTk::Command> command) { | 366 | Keys::t_key::t_key(unsigned int key_, unsigned int mod_, FbTk::RefCount<FbTk::Command> command) { |
365 | key = key_; | 367 | key = key_; |
366 | mod = mod_; | 368 | mod = mod_; |
367 | m_command = command; | 369 | m_command = command; |
368 | } | 370 | } |
369 | 371 | ||
@@ -373,8 +375,8 @@ Keys::t_key::t_key(t_key *k) { | |||
373 | m_command = k->m_command; | 375 | m_command = k->m_command; |
374 | } | 376 | } |
375 | 377 | ||
376 | Keys::t_key::~t_key() { | 378 | Keys::t_key::~t_key() { |
377 | while (!keylist.empty()) { | 379 | while (!keylist.empty()) { |
378 | t_key *k = keylist.back(); | 380 | t_key *k = keylist.back(); |
379 | if (k != 0) { // make sure we don't have a bad key pointer | 381 | if (k != 0) { // make sure we don't have a bad key pointer |
380 | delete k; | 382 | delete k; |