all repos — openbox @ 6d40002093a5d8e665d4f310ea028d22e93e88cb

openbox fork - make it a bit more like ryudo

Big fat merge for epist.
This adds a config parser, chaining, and a tonne of other stuff.
Still need to fix up build system for the lex and yacc stuff.
Scott Moynes smoynes@nexus.carleton.ca
commit

6d40002093a5d8e665d4f310ea028d22e93e88cb

parent

00391787e32111fa5c9de606b5edf595846e7513

M util/epist/Makefile.amutil/epist/Makefile.am

@@ -4,7 +4,7 @@ CPPFLAGS= @CPPFLAGS@ @DEBUG@

EXTRA_PROGRAMS = epist -epist_SOURCES = epist.cc window.cc screen.cc main.cc actions.cc +epist_SOURCES = epist.cc window.cc screen.cc main.cc actions.cc yacc_parser.cc parser.cc keytree.cc lex.yy.c epist_LDADD = ../../src/XAtom.o ../../src/BaseDisplay.o \ ../../src/Util.o ../../src/i18n.o \ ../../src/GCCache.o ../../src/Color.o ../../src/Texture.o \

@@ -25,3 +25,10 @@ screen.o: screen.cc ../../src/XAtom.hh screen.hh window.hh epist.hh \

../../src/BaseDisplay.hh ../../src/Timer.hh ../../src/Util.hh window.o: window.cc window.hh epist.hh ../../src/BaseDisplay.hh \ ../../src/Timer.hh ../../src/Util.hh ../../src/XAtom.hh +yacc_parser.o: yacc_parser.cc yacc_parser.hh epist.hh ../../src/BaseDisplay.hh \ + ../../src/Timer.hh ../../src/Util.hh ../../src/XAtom.hh +keytree.o: keytree.cc keytree.hh epist.hh ../../src/BaseDisplay.hh \ + ../../src/Timer.hh ../../src/Util.hh ../../src/XAtom.hh +parser.o: parser.cc parser.hh epist.hh ../../src/BaseDisplay.hh \ + ../../src/Timer.hh ../../src/Util.hh ../../src/XAtom.hh +lex.yy.o: lex.yy.c
M util/epist/actions.ccutil/epist/actions.cc

@@ -23,13 +23,29 @@

#include "actions.hh" Action::Action(enum ActionType type, KeyCode keycode, unsigned int modifierMask, - int num) - : _type(type), _keycode(keycode), - _modifierMask(modifierMask), _numberParam(num) -{ } - -Action::Action(enum ActionType type, KeyCode keycode, unsigned int modifierMask, const std::string &str) - : _type(type), _keycode(keycode), - _modifierMask(modifierMask), _stringParam(str) -{ } + : _type(type), _keycode(keycode), _modifierMask(modifierMask) +{ + // These are the action types that take string arguments. This + // should probably be moved to a static member + ActionType str_types[] = { + execute, + nextWindowOfClass, + prevWindowOfClass, + nextWindowOfClassOnAllWorkspaces, + prevWindowOfClassOnAllWorkspaces, + noaction + }; + + for (int i = 0; str_types[i] != noaction; ++i) { + if (type == str_types[i]) { + _stringParam = str; + return; + } + } + + _numberParam = atoi( str.c_str() ); + + if (type == changeWorkspace) + _numberParam; +}
M util/epist/actions.hhutil/epist/actions.hh

@@ -93,8 +93,8 @@ enum ActionType _type;

const KeyCode _keycode; const unsigned int _modifierMask; - const int _numberParam; - const std::string _stringParam; + int _numberParam; + std::string _stringParam; public: inline enum ActionType type() const { return _type;} inline const KeyCode keycode() const { return _keycode; }

@@ -103,9 +103,7 @@ inline const int number() const { return _numberParam; }

inline const std::string &string() const { return _stringParam; } Action(enum ActionType type, KeyCode keycode, unsigned int modifierMask, - int number = 0); - Action(enum ActionType type, KeyCode keycode, unsigned int modifierMask, - const std::string &str); + const std::string &str = ""); }; typedef std::list<Action> ActionList;
M util/epist/epist.ccutil/epist/epist.cc

@@ -54,6 +54,7 @@ #include "actions.hh"

#include "epist.hh" #include "screen.hh" #include "window.hh" +#include "parser.hh" #include "../../src/XAtom.hh"

@@ -65,7 +66,7 @@

if (rc_file) _rc_file = rc_file; else - _rc_file = expandTilde("~/.openbox/epistrc"); + _rc_file = expandTilde("~/.epistrc"); _xatom = new XAtom(getXDisplay());

@@ -83,52 +84,11 @@ cout << "No compatible window manager found on any screens. Aborting.\n";

::exit(1); } - addAction(Action::nextScreen, ControlMask, "Tab"); - addAction(Action::prevScreen, ControlMask | ShiftMask, "Tab"); - addAction(Action::nextWindow, Mod1Mask, "Tab"); - addAction(Action::prevWindow, Mod1Mask | ShiftMask, "Tab"); - addAction(Action::toggleshade, Mod1Mask, "F5"); - addAction(Action::close, Mod1Mask, "F4"); - addAction(Action::nextWindowOnAllWorkspaces, Mod1Mask | ControlMask, "Tab"); - addAction(Action::prevWindowOnAllWorkspaces, - Mod1Mask | ShiftMask | ControlMask, "Tab"); - addAction(Action::prevWorkspace, Mod1Mask, "Left"); - addAction(Action::nextWorkspace, Mod1Mask, "Right"); - addAction(Action::raise, Mod1Mask, "Up"); - addAction(Action::lower, Mod1Mask, "Down"); - addAction(Action::moveWindowUp, Mod1Mask | ControlMask, "Up", 1); - addAction(Action::moveWindowDown, Mod1Mask | ControlMask, "Down", 1); - addAction(Action::moveWindowLeft, Mod1Mask | ControlMask, "Left", 1); - addAction(Action::moveWindowRight, Mod1Mask | ControlMask, "Right", 1); - addAction(Action::resizeWindowHeight, ShiftMask | Mod1Mask | ControlMask, - "Up", -1); - addAction(Action::resizeWindowHeight, ShiftMask | Mod1Mask | ControlMask, - "Down", 1); - addAction(Action::resizeWindowWidth, ShiftMask | Mod1Mask | ControlMask, - "Left", -1); - addAction(Action::resizeWindowWidth, ShiftMask | Mod1Mask | ControlMask, - "Right", 1); - addAction(Action::iconify, Mod1Mask | ControlMask, "I"); - addAction(Action::toggleomnipresent, Mod1Mask | ControlMask, "O"); - addAction(Action::toggleMaximizeHorizontal, ShiftMask | Mod1Mask, "X"); - addAction(Action::toggleMaximizeVertical, ShiftMask | ControlMask, "X"); - addAction(Action::toggleMaximizeFull, Mod1Mask | ControlMask, "X"); - addAction(Action::changeWorkspace, Mod1Mask | ControlMask, "1", 0); - addAction(Action::changeWorkspace, Mod1Mask | ControlMask, "2", 1); - addAction(Action::changeWorkspace, Mod1Mask | ControlMask, "3", 2); - addAction(Action::changeWorkspace, Mod1Mask | ControlMask, "4", 3); - addAction(Action::sendToWorkspace, Mod1Mask | ControlMask | ShiftMask, - "1", 0); - addAction(Action::sendToWorkspace, Mod1Mask | ControlMask | ShiftMask, - "2", 1); - addAction(Action::sendToWorkspace, Mod1Mask | ControlMask | ShiftMask, - "3", 2); - addAction(Action::sendToWorkspace, Mod1Mask | ControlMask | ShiftMask, - "4", 3); - addAction(Action::execute, Mod1Mask | ControlMask, "Escape", - "sleep 1 && xset dpms force off"); - addAction(Action::execute, Mod1Mask, "space", - "rxvt"); + _ktree = new keytree(getXDisplay()); + + // set up the key tree + parser p(_ktree); + p.parse(_rc_file); activateGrabs(); }

@@ -142,13 +102,8 @@ void epist::activateGrabs() {

ScreenList::const_iterator scrit, scrend = _screens.end(); - for (scrit = _screens.begin(); scrit != scrend; ++scrit) { - ActionList::const_iterator ait, end = _actions.end(); - - for(ait = _actions.begin(); ait != end; ++ait) { - (*scrit)->grabKey(ait->keycode(), ait->modifierMask()); - } - } + for (scrit = _screens.begin(); scrit != scrend; ++scrit) + _ktree->grabDefaults(*scrit); }

@@ -222,19 +177,3 @@

const XWindow *target = _screens[dest]->lastActiveWindow(); if (target) target->focus(); } - - -void epist::addAction(Action::ActionType act, unsigned int modifiers, - string key, int number) { - _actions.push_back(Action(act, XKeysymToKeycode(getXDisplay(), - XStringToKeysym(key.c_str())), - modifiers, number)); -} - - -void epist::addAction(Action::ActionType act, unsigned int modifiers, - string key, string str) { - _actions.push_back(Action(act, XKeysymToKeycode(getXDisplay(), - XStringToKeysym(key.c_str())), - modifiers, str)); -}
M util/epist/epist.hhutil/epist/epist.hh

@@ -32,6 +32,7 @@ #include <map>

#include "actions.hh" #include "window.hh" +#include "keytree.hh" #include "../../src/BaseDisplay.hh"

@@ -43,6 +44,7 @@ private:

std::string _rc_file; XAtom *_xatom; char **_argv; + keytree *_ktree; typedef std::vector<screen *> ScreenList; ScreenList _screens;

@@ -60,10 +62,6 @@ virtual void process_event(XEvent *e);

virtual bool handleSignal(int sig); void activateGrabs(); - void addAction(Action::ActionType act, unsigned int modifiers, - std::string key, int number = 0); - void addAction(Action::ActionType act, unsigned int modifiers, - std::string key, std::string str); public: epist(char **argv, char *display_name, char *rc_file);

@@ -83,6 +81,7 @@ scrolllockMask = ScrollLockMask;

} const ActionList &actions(void) { return _actions; } + keytree &getKeyTree(void) { return *_ktree; } WindowList& clientsList() { return _clients; } WindowList::iterator& activeWindow() { return _active; }
A util/epist/epist.y

@@ -0,0 +1,83 @@

+%{ +#include <stdio.h> +#include <string.h> +#include "parser.hh" + +#define YYPARSE_PARAM parser_obj +#define YYSTYPE char* + +extern "C" { + int yylex(); + int yywrap() { + return 1; + } +} + +void yyerror(const char *c) { + printf("ERROR: %s\n", c); +} + + +%} + +%token OBRACE EBRACE SEMICOLON DASH ACTION BINDING NUMBER QUOTES WORD + +%% + +commands: + | commands command + ; + +command: + action_command | chain_command + ; + +action_command: + binding ACTION parameter SEMICOLON + { + ((parser*)parser_obj)->setAction($2); + ((parser*)parser_obj)->endAction(); + } + + ; + +chain_command: + binding obrace commands ebrace + { + ((parser*)parser_obj)->endChain(); + } + ; + +binding: + binding_w_modifier bind_key + ; + +obrace: + OBRACE { ((parser*)parser_obj)->startChain(); } + ; + +ebrace: + EBRACE { /* ((parser*)parser_obj)->endChain(); */ } + ; + +binding_w_modifier: + | BINDING DASH binding_w_modifier { ((parser*)parser_obj)->addModifier($1); } + ; + +bind_key: + OBRACE { ((parser*)parser_obj)->setKey($1); } + | EBRACE { ((parser*)parser_obj)->setKey($1); } + | DASH { ((parser*)parser_obj)->setKey($1); } + | SEMICOLON { ((parser*)parser_obj)->setKey($1); } + | NUMBER { ((parser*)parser_obj)->setKey($1); } + | WORD { ((parser*)parser_obj)->setKey($1); } + ; + +parameter: + | NUMBER { ((parser*)parser_obj)->setArgument($1); } + | DASH NUMBER { ((parser*)parser_obj)->setArgument($1); } + | QUOTES { ((parser*)parser_obj)->setArgument($1); } + ; + +%% +
A util/epist/keytree.cc

@@ -0,0 +1,144 @@

+// -*- mode: C++; indent-tabs-mode: nil; -*- +// keytree.cc for Epistophy - a key handler for NETWM/EWMH window managers. +// Copyright (c) 2002 - 2002 Ben Jansens <ben at orodu.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. + +#include "keytree.hh" + +keytree::keytree(Display *display) : _display(display) +{ + _head = new keynode; + _head->parent = NULL; + _head->action = NULL; // head's action is always NULL + _current = _head; +} + +keytree::~keytree() +{ + clearTree(_head); +} + +void keytree::clearTree(keynode *node) +{ + if (!node) + return; + + ChildList::iterator it, end = node->children.end(); + for (it = node->children.begin(); it != end; ++it) + clearTree(*it); + + if (node->action) + delete node->action; + delete node; +} + +void keytree::grabDefaults(screen *scr) +{ + grabChildren(_head, scr); +} + +void keytree::grabChildren(keynode *node, screen *scr) +{ + ChildList::const_iterator it, end = node->children.end(); + for (it = node->children.begin(); it != end; ++it) + if ( (*it)->action ) + scr->grabKey( (*it)->action->keycode(), (*it)->action->modifierMask() ); +} + +void keytree::ungrabChildren(keynode *node, screen *scr) +{ + ChildList::const_iterator it, end = node->children.end(); + for (it = node->children.begin(); it != end; ++it) + if ( (*it)->action ) + scr->ungrabKey( (*it)->action->keycode(), (*it)->action->modifierMask()); +} + +const Action * keytree::getAction(const XEvent &e, unsigned int state, + screen *scr) +{ + Action *act; + + if (_current != _head) + ungrabChildren(_current, scr); + + ChildList::const_iterator it, end = _current->children.end(); + for (it = _current->children.begin(); it != end; ++it) { + act = (*it)->action; + if (e.xkey.keycode == act->keycode() && state == act->modifierMask()) { + if ( isLeaf(*it) ) { + if (_current != _head) + ungrabChildren(_current, scr); + _current = _head; + return act; + } + else { + _current = *it; + grabChildren(_current, scr); + return (const Action *)NULL; + } + } + } + + // action not found. back to the head + _current = _head; + return (const Action *)NULL; +} + +void keytree::addAction(Action::ActionType action, unsigned int mask, + string key, string arg) +{ + // can't grab non-modifier as topmost key + if (_current == _head && (mask == 0 || mask == ShiftMask)) + return; + + keynode *tmp = new keynode; + tmp->action = new Action(action, + XKeysymToKeycode(_display, + XStringToKeysym(key.c_str())), + mask, arg); + tmp->parent = _current; + _current->children.push_back(tmp); +} + +void keytree::advanceOnNewNode() +{ + keynode *tmp = new keynode; + tmp->action = NULL; + tmp->parent = _current; + _current->children.push_back(tmp); + _current = tmp; +} + +void keytree::retract() +{ + if (_current != _head) + _current = _current->parent; +} + +void keytree::setCurrentNodeProps(Action::ActionType action, unsigned int mask, + string key, string arg) +{ + if (_current->action) + delete _current->action; + _current->action = new Action(action, + XKeysymToKeycode(_display, + XStringToKeysym(key.c_str())), + mask, arg); +}
A util/epist/keytree.hh

@@ -0,0 +1,72 @@

+// -*- mode: C++; indent-tabs-mode: nil; -*- +// keytree.hh for Epistophy - a key handler for NETWM/EWMH window managers. +// Copyright (c) 2002 - 2002 Ben Jansens <ben at orodu.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. + +#ifndef _keytree_hh +#define _keytree_hh + +#include <list> +#include "actions.hh" +#include "screen.hh" + +struct keynode; // forward declaration +typedef std::list<keynode *> ChildList; + +struct keynode { + Action *action; + keynode *parent; + ChildList children; +}; + +class keytree { +public: + keytree(Display *); + ~keytree(); + + void grabDefaults(screen *); + const Action * getAction(const XEvent&, unsigned int, screen *); + +private: + // only mister parser needs to know about our sekrets (BUMMY) + friend class parser; + + void grabChildren(keynode *, screen *); + void ungrabChildren(keynode *, screen *); + + void addAction(Action::ActionType, unsigned int, std::string, std::string); + void advanceOnNewNode(); + void retract(); + void setCurrentNodeProps(Action::ActionType, unsigned int, std::string, std::string); + + void reset() + { _current = _head; } + + bool isLeaf(keynode *node) + { return node->children.empty(); } + + void clearTree(keynode *); + + keynode *_head; + keynode *_current; + Display *_display; +}; + +#endif // _keytree_hh
A util/epist/parser.cc

@@ -0,0 +1,145 @@

+extern "C" { +#include <stdio.h> +} +#include "parser.hh" + +parser::parser(keytree *kt) + : _mask(0), _action(Action::noaction), _key(""), _arg(""), _kt(kt) +{ +} + +parser::~parser() +{ + // nothing to see here. move along. +} + +void parser::parse(string rc_file) +{ + extern int yyparse(void *); + extern FILE *yyin; + + yyin = fopen(rc_file.c_str(), "r"); + + yyparse(this); + + fclose(yyin); + _kt->reset(); +} + +void parser::setAction(string act) +{ + struct { + string str; + Action::ActionType act; + } + actions[] = { + { "noaction", Action::noaction }, + { "execute", Action::execute }, + { "iconify", Action::iconify }, + { "raise", Action::raise }, + { "lower", Action::lower }, + { "close", Action::close }, + { "toggleshade", Action::toggleshade }, + { "toggleomnipresent", Action::toggleomnipresent }, + { "moveWindowUp", Action::moveWindowUp }, + { "moveWindowDown", Action::moveWindowDown }, + { "moveWindowLeft", Action::moveWindowLeft }, + { "moveWindowRight", Action::moveWindowRight }, + { "resizeWindowWidth", Action::resizeWindowWidth }, + { "resizeWindowHeight", Action::resizeWindowHeight }, + { "toggleMaximizeFull", Action::toggleMaximizeFull }, + { "toggleMaximizeVertical", Action::toggleMaximizeVertical }, + { "toggleMaximizeHorizontal", Action::toggleMaximizeHorizontal }, + { "sendToWorkspace", Action::sendToWorkspace }, + { "nextWindow", Action::nextWindow }, + { "prevWindow", Action::prevWindow }, + { "nextWindowOnAllWorkspaces", Action::nextWindowOnAllWorkspaces }, + { "prevWindowOnAllWorkspaces", Action::prevWindowOnAllWorkspaces }, + { "nextWindowOnAllScreens", Action::nextWindowOnAllScreens }, + { "prevWindowOnAllScreens", Action::prevWindowOnAllScreens }, + { "nextWindowOfClass", Action::nextWindowOfClass }, + { "prevWindowOfClass", Action::prevWindowOfClass }, + { "nextWindowOfClassOnAllWorkspaces", Action::nextWindowOfClassOnAllWorkspaces }, + { "prevWindowOfClassOnAllWorkspaces", Action::prevWindowOfClassOnAllWorkspaces }, + { "changeWorkspace", Action::changeWorkspace }, + { "nextWorkspace", Action::nextWorkspace }, + { "prevWorkspace", Action::prevWorkspace }, + { "nextScreen", Action::nextScreen }, + { "prevScreen", Action::prevScreen }, + { "showRootMenu", Action::showRootMenu }, + { "showWorkspaceMenu", Action::showWorkspaceMenu }, + { "stringChain", Action::stringChain }, + { "keyChain", Action::keyChain }, + { "numberChain", Action::numberChain }, + { "cancel", Action::cancel }, + { "", Action::noaction } + }; + + bool found = false; + + for (int i = 0; actions[i].str != ""; ++i) { + if (actions[i].str == act) { + _action = actions[i].act; + found = true; + } + } + + if (!found) + _action = Action::noaction; +} + +void parser::addModifier(string mod) +{ + struct { + string str; + unsigned int mask; + } + modifiers[] = { + { "Mod1", Mod1Mask }, + { "Mod2", Mod2Mask }, + { "Mod3", Mod3Mask }, + { "Control", ControlMask }, + { "Shift", ShiftMask }, + { "", 0 } + }; + + for (int i = 0; modifiers[i].str != ""; ++i) { + if (modifiers[i].str == mod) + _mask |= modifiers[i].mask; + } +} + +void parser::endAction() +{ + _kt->addAction(_action, _mask, _key, _arg); + reset(); +} + +void parser::startChain() +{ + _kt->advanceOnNewNode(); + setChainBinding(); + reset(); +} + +void parser::endChain() +{ + _kt->retract(); + reset(); +} + +void parser::setChainBinding() +{ + if (_mask != 0 && _key != "") { + _kt->setCurrentNodeProps(Action::noaction, _mask, _key, ""); + reset(); + } +} + +void parser::reset() +{ + _mask = 0; + _action = Action::noaction; + _key = ""; + _arg = ""; +}
A util/epist/parser.hh

@@ -0,0 +1,33 @@

+#include <string> +#include "actions.hh" +#include "keytree.hh" + +class parser { +public: + parser(keytree *); + ~parser(); + + void parse(std::string); + + void setKey(std::string key) + { _key = key; } + + void setArgument(std::string arg) + { _arg = arg; } + + void setAction(std::string); + void addModifier(std::string); + void endAction(); + void startChain(); + void setChainBinding(); + void endChain(); + +private: + void reset(); + + keytree *_kt; + unsigned int _mask; + Action::ActionType _action; + std::string _key; + std::string _arg; +};
M util/epist/screen.ccutil/epist/screen.cc

@@ -146,164 +146,162 @@ }

void screen::handleKeypress(const XEvent &e) { int scrolllockMask, numlockMask; - - ActionList::const_iterator it = _epist->actions().begin(); - ActionList::const_iterator end = _epist->actions().end(); - _epist->getLockModifiers(numlockMask, scrolllockMask); - for (; it != end; ++it) { - unsigned int state = e.xkey.state & ~(LockMask|scrolllockMask|numlockMask); - - if (e.xkey.keycode == it->keycode() && - state == it->modifierMask()) { - switch (it->type()) { - case Action::nextScreen: - _epist->cycleScreen(_number, true); - return; + // Mask out the lock modifiers. We want our keys to always work + // This should be made an option + unsigned int state = e.xkey.state & ~(LockMask|scrolllockMask|numlockMask); + const Action *it = _epist->getKeyTree().getAction(e, state, this); + + if (!it) + return; - case Action::prevScreen: - _epist->cycleScreen(_number, false); - return; + switch (it->type()) { + case Action::nextScreen: + _epist->cycleScreen(_number, true); + return; - case Action::nextWorkspace: - cycleWorkspace(true); - return; + case Action::prevScreen: + _epist->cycleScreen(_number, false); + return; - case Action::prevWorkspace: - cycleWorkspace(false); - return; + case Action::nextWorkspace: + cycleWorkspace(true); + return; - case Action::nextWindow: - cycleWindow(true); - return; + case Action::prevWorkspace: + cycleWorkspace(false); + return; - case Action::prevWindow: - cycleWindow(false); - return; + case Action::nextWindow: + cycleWindow(true); + return; - case Action::nextWindowOnAllWorkspaces: - cycleWindow(true, false, true); - return; - - case Action::prevWindowOnAllWorkspaces: - cycleWindow(false, false, true); - return; - - case Action::nextWindowOnAllScreens: - cycleWindow(true, true); - return; + case Action::prevWindow: + cycleWindow(false); + return; - case Action::prevWindowOnAllScreens: - cycleWindow(false, true); - return; + case Action::nextWindowOnAllWorkspaces: + cycleWindow(true, false, true); + return; - case Action::nextWindowOfClass: - cycleWindow(true, false, false, true, it->string()); - return; + case Action::prevWindowOnAllWorkspaces: + cycleWindow(false, false, true); + return; - case Action::prevWindowOfClass: - cycleWindow(false, false, false, true, it->string()); - return; + case Action::nextWindowOnAllScreens: + cycleWindow(true, true); + return; - case Action::nextWindowOfClassOnAllWorkspaces: - cycleWindow(true, false, true, true, it->string()); - return; + case Action::prevWindowOnAllScreens: + cycleWindow(false, true); + return; - case Action::prevWindowOfClassOnAllWorkspaces: - cycleWindow(false, false, true, true, it->string()); - return; + case Action::nextWindowOfClass: + cycleWindow(true, false, false, true, it->string()); + return; - case Action::changeWorkspace: - changeWorkspace(it->number()); - return; + case Action::prevWindowOfClass: + cycleWindow(false, false, false, true, it->string()); + return; + + case Action::nextWindowOfClassOnAllWorkspaces: + cycleWindow(true, false, true, true, it->string()); + return; + + case Action::prevWindowOfClassOnAllWorkspaces: + cycleWindow(false, false, true, true, it->string()); + return; - case Action::execute: - execCommand(it->string()); - return; + case Action::changeWorkspace: + // we subtract one so counting starts at 1 in the config file + changeWorkspace(it->number() - 1); + return; - default: - break; - } + case Action::execute: + execCommand(it->string()); + return; - // these actions require an active window - if (_active != _clients.end()) { - XWindow *window = *_active; + default: + break; + } - switch (it->type()) { - case Action::iconify: + // these actions require an active window + if (_active != _clients.end()) { + XWindow *window = *_active; + + switch (it->type()) { + case Action::iconify: window->iconify(); return; - case Action::close: + case Action::close: window->close(); return; - case Action::raise: + case Action::raise: window->raise(); return; - case Action::lower: + case Action::lower: window->lower(); return; - case Action::sendToWorkspace: + case Action::sendToWorkspace: window->sendTo(it->number()); return; - case Action::toggleomnipresent: + case Action::toggleomnipresent: if (window->desktop() == 0xffffffff) window->sendTo(_active_desktop); else window->sendTo(0xffffffff); return; - case Action::moveWindowUp: + case Action::moveWindowUp: window->move(window->x(), window->y() - it->number()); return; - case Action::moveWindowDown: + case Action::moveWindowDown: window->move(window->x(), window->y() + it->number()); return; - case Action::moveWindowLeft: + case Action::moveWindowLeft: window->move(window->x() - it->number(), window->y()); return; - case Action::moveWindowRight: + case Action::moveWindowRight: window->move(window->x() + it->number(), window->y()); return; - case Action::resizeWindowWidth: + case Action::resizeWindowWidth: window->resize(window->width() + it->number(), window->height()); return; - case Action::resizeWindowHeight: + case Action::resizeWindowHeight: window->resize(window->width(), window->height() + it->number()); return; - case Action::toggleshade: + case Action::toggleshade: window->shade(! window->shaded()); return; - case Action::toggleMaximizeHorizontal: + case Action::toggleMaximizeHorizontal: window->toggleMaximize(XWindow::Max_Horz); return; - case Action::toggleMaximizeVertical: + case Action::toggleMaximizeVertical: window->toggleMaximize(XWindow::Max_Vert); return; - case Action::toggleMaximizeFull: + case Action::toggleMaximizeFull: window->toggleMaximize(XWindow::Max_Full); return; - default: + default: assert(false); // unhandled action type! break; - } } - } } }

@@ -583,3 +581,21 @@ XGrabKey(display, keyCode,

modifierMask|numlockMask|LockMask|scrolllockMask, _root, True, GrabModeAsync, GrabModeAsync); } + +void screen::ungrabKey(const KeyCode keyCode, const int modifierMask) const { + + Display *display = _epist->getXDisplay(); + int numlockMask, scrolllockMask; + + _epist->getLockModifiers(numlockMask, scrolllockMask); + + XUngrabKey(display, keyCode, modifierMask, _root); + XUngrabKey(display, keyCode, modifierMask|LockMask, _root); + XUngrabKey(display, keyCode, modifierMask|scrolllockMask, _root); + XUngrabKey(display, keyCode, modifierMask|numlockMask, _root); + XUngrabKey(display, keyCode, modifierMask|LockMask|scrolllockMask, _root); + XUngrabKey(display, keyCode, modifierMask|scrolllockMask|numlockMask, _root); + XUngrabKey(display, keyCode, modifierMask|numlockMask|LockMask, _root); + XUngrabKey(display, keyCode, modifierMask|numlockMask|LockMask| + scrolllockMask, _root); +}
M util/epist/screen.hhutil/epist/screen.hh

@@ -86,6 +86,7 @@ void toggleShaded(const Window win) const;

void execCommand(const std::string &cmd) const; void grabKey(const KeyCode keyCode, const int modifierMask) const; + void ungrabKey(const KeyCode keyCode, const int modifierMask) const; }; #endif // __screen_hh