// Keys.cc for Fluxbox - an X11 Window manager // Copyright (c) 2001 - 2003 Henrik Kinnunen (fluxgen(at)users.sourceforge.net) // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. //$Id: Keys.cc,v 1.35 2003/07/02 05:42:21 fluxgen Exp $ #include "Keys.hh" #include "StringUtil.hh" #include "App.hh" #include "Command.hh" #include "CommandParser.hh" #ifdef HAVE_CONFIG_H #include "config.h" #endif // HAVE_CONFIG_H #ifdef HAVE_CTYPE_H #include #endif // HAVE_CTYPE_H #include #include #include #include #ifdef HAVE_SYS_TYPES_H #include #endif // HAVE_SYS_TYPES_H #ifdef HAVE_SYS_WAIT_H #include #endif // HAVE_SYS_WAIT_H #ifdef HAVE_UNISTD_H #include #endif // HAVE_UNISTD_H #ifdef HAVE_SYS_STAT_H #include #endif // HAVE_SYS_STAT_H #include #include #include #include #include #include #include #include using namespace std; Keys::Keys(const char *filename): m_capslock_mod(0), m_numlock_mod(0), m_scrolllock_mod(0), m_abortkey(0), m_display(FbTk::App::instance()->display()), m_modmap(0) { loadModmap(); if (filename != 0) load(filename); } Keys::~Keys() { if (m_modmap) { XFreeModifiermap(m_modmap); } ungrabKeys(); deleteTree(); } /// Destroys the keytree and m_abortkey void Keys::deleteTree() { while (!m_keylist.empty()) { if (m_keylist.back() && m_keylist.back() != 0) delete m_keylist.back(); m_keylist.pop_back(); } if (m_abortkey) { delete m_abortkey; m_abortkey=0; } } /// Ungrabs the keys void Keys::ungrabKeys() { for (int screen=0; screen val; //Parse arguments FbTk::StringUtil::stringtok(val, linebuffer.c_str()); //must have at least 1 argument if (val.size() <= 0) continue; if (val[0][0] == '#') //the line is commented continue; unsigned int key=0, mod=0; char keyarg=0; t_key *current_key=0, *last_key=0; for (unsigned int argc=0; argc1) { //keyarg=0; int tmpmod = getModifier(val[argc].c_str()); if(tmpmod) mod|=tmpmod; //If it's a modifier else { key = getKey(val[argc].c_str()); // else get the key if (key == 0) { cerr<<"["<keylist.push_back(temp_key); last_key = temp_key; } } } } else { // parse command line if (last_key == 0) { cerr<<"File: "< "< "<m_command = CommandParser::instance().parseLine(str); if (*last_key->m_command == 0) { cerr<<"File: "< "<keylist.size()) { next_key = m_keylist[i]; break; //end for-loop } else { if (*m_keylist[i]->m_command != 0) m_keylist[i]->m_command->execute(); } } } } else { //check the nextkey t_key *temp_key = next_key->find(ke); if (temp_key) { if (temp_key->keylist.size()) { next_key = temp_key; } else { next_key = 0; if (*temp_key->m_command != 0) temp_key->m_command->execute(); } } else { temp_key = next_key; next_key = 0; if (*temp_key->m_command != 0) temp_key->m_command->execute(); } } } /** deletes the tree and load configuration returns true on success else false */ bool Keys::reconfigure(const char *filename) { deleteTree(); 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) { if (basetree==0) { unsigned int baselist_i=0; for (; baselist_imod == 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()) { 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 { unsigned int baselist_i = 0; 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()) { 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; } Keys::t_key::t_key(unsigned int key_, unsigned int mod_, FbTk::RefCount command) { key = key_; mod = mod_; m_command = command; } Keys::t_key::t_key(t_key *k) { key = k->key; mod = k->mod; m_command = k->m_command; } 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(); } } } /** * load state relating to the modifier map */ void Keys::loadModmap() { if (m_modmap) { XFreeModifiermap(m_modmap); } m_modmap = XGetModifierMapping(m_display); // mask to use for modifier int mods[] = { ShiftMask, LockMask, ControlMask, Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask, 0 }; // find modifiers and set them for (int i=0, realkey=0; i<8; ++i) { for (int key=0; keymax_keypermod; ++key, ++realkey) { if (m_modmap->modifiermap[realkey] == 0) continue; KeySym ks = XKeycodeToKeysym(m_display, m_modmap->modifiermap[realkey], 0); switch (ks) { case XK_Caps_Lock: m_capslock_mod = mods[i]; break; case XK_Scroll_Lock: m_scrolllock_mod = mods[i]; break; case XK_Num_Lock: m_numlock_mod = mods[i]; break; } } } } unsigned int Keys::keycodeToModmask(unsigned int keycode) { if (!m_modmap) return 0; // search through modmap for this keycode for (int mod=0; mod < 8; mod++) { for (int key=0; key < m_modmap->max_keypermod; ++key) { // modifiermap is an array with 8 sets of keycodes // each max_keypermod long, but in a linear array. if (m_modmap->modifiermap[m_modmap->max_keypermod*mod + key] == keycode) { return (1<