From 144091995610ea1b562e96d5e55c99659034bd55 Mon Sep 17 00:00:00 2001 From: markt Date: Tue, 19 Dec 2006 18:08:33 +0000 Subject: Change to data structure for keybindings, ungrab and grab keys when switching keymodes instead of deciding whether we need it and repeating the key. --- ChangeLog | 11 +++ src/FbTk/KeyUtil.cc | 16 ++-- src/Keys.cc | 251 ++++++++++++++++++---------------------------------- src/Keys.hh | 11 +-- src/fluxbox.cc | 13 +-- 5 files changed, 113 insertions(+), 189 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6367429..0ef21fb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,16 @@ (Format: Year/Month/Day) Changes for 1.0rc3: +*06/12/19: + * Little simplification of data structure for keybindings (Mark) + Side effects: + - "Mod4 a b" now behaves like "Mod4 a None b" -- in fact, "None" is now + completely obsolete + - You can press "Escape" to cancel any Emacs-style keychain in progress + (unless it's bound to something else) + - If there is a conflict between bindings, the first one in the file wins + - Fixes handling of keychains like "Mod4 a Mod1 b" + - Should fix some issues with "None" modifier + Keys.cc/hh FbTk/KeyUtil.cc fluxbox.cc *06/12/18: * Rotate items in toolbar the same way as tabs (Mark) Toolbar.cc diff --git a/src/FbTk/KeyUtil.cc b/src/FbTk/KeyUtil.cc index 24e43c8..de9f947 100644 --- a/src/FbTk/KeyUtil.cc +++ b/src/FbTk/KeyUtil.cc @@ -124,42 +124,42 @@ void KeyUtil::grabKey(unsigned int key, unsigned int mod) { XGrabKey(display, key, mod, root, True, - GrabModeAsync, GrabModeSync); + GrabModeAsync, GrabModeAsync); // Grab with numlock, capslock and scrlock //numlock XGrabKey(display, key, mod|nummod, root, True, - GrabModeAsync, GrabModeSync); + GrabModeAsync, GrabModeAsync); //scrolllock XGrabKey(display, key, mod|scrollmod, root, True, - GrabModeAsync, GrabModeSync); + GrabModeAsync, GrabModeAsync); //capslock XGrabKey(display, key, mod|capsmod, root, True, - GrabModeAsync, GrabModeSync); + GrabModeAsync, GrabModeAsync); //capslock+numlock XGrabKey(display, key, mod|capsmod|nummod, root, True, - GrabModeAsync, GrabModeSync); + GrabModeAsync, GrabModeAsync); //capslock+scrolllock XGrabKey(display, key, mod|capsmod|scrollmod, root, True, - GrabModeAsync, GrabModeSync); + GrabModeAsync, GrabModeAsync); //capslock+numlock+scrolllock XGrabKey(display, key, mod|capsmod|scrollmod|nummod, root, True, - GrabModeAsync, GrabModeSync); + GrabModeAsync, GrabModeAsync); //numlock+scrollLock XGrabKey(display, key, mod|nummod|scrollmod, root, True, - GrabModeAsync, GrabModeSync); + GrabModeAsync, GrabModeAsync); } diff --git a/src/Keys.cc b/src/Keys.cc index b1f6763..2404a0a 100644 --- a/src/Keys.cc +++ b/src/Keys.cc @@ -94,6 +94,7 @@ using std::endl; using std::string; using std::vector; using std::ifstream; +using std::pair; Keys::Keys(): m_display(FbTk::App::instance()->display()) @@ -109,14 +110,8 @@ Keys::~Keys() { /// Destroys the keytree void Keys::deleteTree() { - for (keyspace_t::iterator map_it = m_map.begin(); map_it != m_map.end(); ++map_it) { - keylist_t::iterator it = map_it->second->begin(); - const keylist_t::iterator it_end = map_it->second->end(); - for ( ; it != it_end; it++) - delete *it; - map_it->second->clear(); + for (keyspace_t::iterator map_it = m_map.begin(); map_it != m_map.end(); ++map_it) delete map_it->second; - } m_map.clear(); } @@ -129,13 +124,10 @@ bool Keys::load(const char *filename) { if (!filename) return false; - //ungrab all keys - FbTk::KeyUtil::ungrabKeys(); - //free memory of previous grabs deleteTree(); - m_map["default:"] = new keylist_t; + m_map["default:"] = new t_key(0,0); FbTk::App::instance()->sync(false); @@ -144,21 +136,25 @@ bool Keys::load(const char *filename) { if (!infile) return false; // faild to open file - m_current_line = 0;//current line, so we can tell the user where the fault is + unsigned int current_line = 0;//so we can tell the user where the fault is while (!infile.eof()) { string linebuffer; getline(infile, linebuffer); - m_current_line++; + current_line++; - addBinding(linebuffer); + if (!addBinding(linebuffer)) { + cerr<<_FB_CONSOLETEXT(Keys, InvalidKeyMod, + "Keys: Invalid key/modifier on line", + "A bad key/modifier string was found on line (number following)")<<" "<< + current_line<<"): "<find(key, mod); + if (!current_key) { + first_new_key = new t_key(key, mod); + current_key = first_new_key; + } else if (*current_key->m_command) // already being used + return false; } else { t_key *temp_key = new t_key(key, mod); - last_key->keylist.push_back(temp_key); - last_key = temp_key; + current_key->keylist.push_back(temp_key); + current_key = temp_key; } + mod = 0; + key = 0; } } else { // parse command line - if (last_key == 0) { - cerr<<_FB_CONSOLETEXT(Keys, BadLine, "Keys: Error on line", "Error on line (number following)")<<": "< "< "<m_command = CommandParser::instance().parseLine(str); - - if (*last_key->m_command == 0) { - cerr<<_FB_CONSOLETEXT(Keys, BadLine, "Keys: Error on line", "Error on line (number following)")<<": "< "<m_command = CommandParser::instance().parseLine(str); + if (!str || *current_key->m_command == 0 || mod) { + delete first_new_key; + return false; + } + + // success + first_new_keylist->keylist.push_back(first_new_key); + return true; } // end if } // end for return false; } - -/** - @return the KeyAction of the XKeyEvent; return false if not bound -*/ +// return true if bound to a command, else false bool Keys::doAction(XKeyEvent &ke) { ke.state = FbTk::KeyUtil::instance().cleanMods(ke.state); - static struct t_key* next_key = 0; - - if (!next_key) { - bool retval = false; - // need a local keylist, in case m_command->execute() changes it - keylist_t *keylist = m_keylist; - for (size_t i = 0; i < keylist->size(); i++) { - if (*(*keylist)[i] == ke) { - if ((*keylist)[i]->keylist.size()) { - next_key = (*keylist)[i]; - return true; //still counts as being grabbed - } - if (*(*keylist)[i]->m_command != 0) { - (*keylist)[i]->m_command->execute(); - retval = true; - } - } - } - return retval; - } + static t_key* next_key = m_keylist; + if (!next_key) + next_key = m_keylist; t_key *temp_key = next_key->find(ke); - if (temp_key) { - if (temp_key->keylist.size()) { - next_key = temp_key; - return true; - } - next_key = 0; - if (*temp_key->m_command == 0) - return false; - temp_key->m_command->execute(); + + + // need to save this for emacs-style keybindings + static t_key *saved_keymode = 0; + + if (temp_key && temp_key->keylist.size()) { // emacs-style + saved_keymode = m_keylist; + next_key = temp_key; + setKeyMode(next_key); + // grab "None Escape" to exit keychain in the middle + unsigned int esc = FbTk::KeyUtil::getKey("Escape"); + FbTk::KeyUtil::grabKey(esc,0); return true; } - temp_key = next_key; - next_key = 0; - if (*temp_key->m_command == 0) + if (!temp_key || *temp_key->m_command == 0) { + next_key = 0; + if (saved_keymode) { + setKeyMode(saved_keymode); + saved_keymode = 0; + } return false; + } temp_key->m_command->execute(); + if (saved_keymode) { + if (next_key == m_keylist) // don't reset keymode if command changed it + setKeyMode(saved_keymode); + saved_keymode = 0; + } + next_key = 0; return true; } @@ -345,62 +314,21 @@ bool Keys::reconfigure(const char *filename) { return load(filename); } -/** - Merges two chains and binds new keys - @return true on success else false. -*/ -bool Keys::mergeTree(t_key *newtree, t_key *basetree) { - size_t baselist_i = 0; - if (basetree==0) { - for (; baselist_isize(); baselist_i++) { - if ((*m_keylist)[baselist_i]->mod == newtree->mod && - (*m_keylist)[baselist_i]->key == newtree->key) { - if (newtree->keylist.size() && *(*m_keylist)[baselist_i]->m_command == 0) { - //assumes the newtree only have one branch - return mergeTree(newtree->keylist[0], (*m_keylist)[baselist_i]); - } else - break; - } - } - - if (baselist_i == m_keylist->size()) { - FbTk::KeyUtil::grabKey(newtree->key, newtree->mod); - m_keylist->push_back(new t_key(newtree)); - if (newtree->keylist.size()) - return mergeTree(newtree->keylist[0], m_keylist->back()); - return true; - } - - } else { - for (; baselist_ikeylist.size(); baselist_i++) { - if (basetree->keylist[baselist_i]->mod == newtree->mod && - basetree->keylist[baselist_i]->key == newtree->key) { - if (newtree->keylist.size()) { - //assumes the newtree only have on branch - return mergeTree(newtree->keylist[0], basetree->keylist[baselist_i]); - } else - return false; - } - } - //if it wasn't in the list grab the key and add it to the list - if (baselist_i==basetree->keylist.size()) { - FbTk::KeyUtil::grabKey(newtree->key, newtree->mod); - basetree->keylist.push_back(new t_key(newtree)); - if (newtree->keylist.size()) - return mergeTree(newtree->keylist[0], basetree->keylist.back()); - return true; - } - } - - return false; -} - -void Keys::keyMode(string keyMode = "default") { +void Keys::keyMode(string keyMode) { keyspace_t::iterator it = m_map.find(keyMode + ":"); if (it == m_map.end()) - m_keylist = m_map["default:"]; + setKeyMode(m_map["default:"]); else - m_keylist = it->second; + setKeyMode(it->second); +} + +void Keys::setKeyMode(t_key *keyMode) { + FbTk::KeyUtil::ungrabKeys(); + keylist_t::iterator it = keyMode->keylist.begin(); + keylist_t::iterator it_end = keyMode->keylist.end(); + for (; it != it_end; ++it) + FbTk::KeyUtil::grabKey((*it)->key,(*it)->mod); + m_keylist = keyMode; } Keys::t_key::t_key(unsigned int key_, unsigned int mod_, FbTk::RefCount command) { @@ -416,12 +344,7 @@ Keys::t_key::t_key(t_key *k) { } Keys::t_key::~t_key() { - while (!keylist.empty()) { - t_key *k = keylist.back(); - if (k != 0) { // make sure we don't have a bad key pointer - delete k; - keylist.pop_back(); - } - } - + for (keylist_t::iterator list_it = keylist.begin(); list_it != keylist.end(); ++list_it) + delete *list_it; + keylist.clear(); } diff --git a/src/Keys.hh b/src/Keys.hh index 6b393e7..8e919b3 100644 --- a/src/Keys.hh +++ b/src/Keys.hh @@ -116,18 +116,13 @@ private: keylist_t keylist; }; - /** - merge two linked list - @return true on success, else false - */ - bool mergeTree(t_key *newtree, t_key *basetree=0); + void setKeyMode(t_key *keyMode); - typedef std::map keyspace_t; - keylist_t *m_keylist; + typedef std::map keyspace_t; + t_key *m_keylist; keyspace_t m_map; Display *m_display; ///< display connection - unsigned int m_current_line; }; #endif // KEYS_HH diff --git a/src/fluxbox.cc b/src/fluxbox.cc index 8a810a4..9fe22f7 100644 --- a/src/fluxbox.cc +++ b/src/fluxbox.cc @@ -1119,16 +1119,11 @@ void Fluxbox::handleKeyEvent(XKeyEvent &ke) { case KeyPress: // see if we need to keep watching for key releases m_watching_screen = 0; - if (m_key->doAction(ke)) { - XAllowEvents(FbTk::App::instance()->display(), AsyncKeyboard, CurrentTime); - // if we've done some action other than cycling focus - if (old_watching_screen && m_watching_screen != old_watching_screen) - old_watching_screen->notifyReleasedKeys(ke); - } else { - XAllowEvents(FbTk::App::instance()->display(), ReplayKeyboard, CurrentTime); - // could still be cycling + if (!m_key->doAction(ke)) // could still be cycling m_watching_screen = old_watching_screen; - } + else if (old_watching_screen && + m_watching_screen != old_watching_screen) + old_watching_screen->notifyReleasedKeys(ke); break; case KeyRelease: { // we ignore most key releases unless we need to use -- cgit v0.11.2