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.
This commit is contained in:
parent
00391787e3
commit
6d40002093
12 changed files with 643 additions and 190 deletions
|
@ -4,7 +4,7 @@ CPPFLAGS= @CPPFLAGS@ @DEBUG@
|
||||||
|
|
||||||
EXTRA_PROGRAMS = epist
|
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 \
|
epist_LDADD = ../../src/XAtom.o ../../src/BaseDisplay.o \
|
||||||
../../src/Util.o ../../src/i18n.o \
|
../../src/Util.o ../../src/i18n.o \
|
||||||
../../src/GCCache.o ../../src/Color.o ../../src/Texture.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
|
../../src/BaseDisplay.hh ../../src/Timer.hh ../../src/Util.hh
|
||||||
window.o: window.cc window.hh epist.hh ../../src/BaseDisplay.hh \
|
window.o: window.cc window.hh epist.hh ../../src/BaseDisplay.hh \
|
||||||
../../src/Timer.hh ../../src/Util.hh ../../src/XAtom.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
|
||||||
|
|
|
@ -22,14 +22,30 @@
|
||||||
|
|
||||||
#include "actions.hh"
|
#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,
|
Action::Action(enum ActionType type, KeyCode keycode, unsigned int modifierMask,
|
||||||
const std::string &str)
|
const std::string &str)
|
||||||
: _type(type), _keycode(keycode),
|
: _type(type), _keycode(keycode), _modifierMask(modifierMask)
|
||||||
_modifierMask(modifierMask), _stringParam(str)
|
{
|
||||||
{ }
|
// 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;
|
||||||
|
}
|
||||||
|
|
|
@ -93,8 +93,8 @@ private:
|
||||||
const KeyCode _keycode;
|
const KeyCode _keycode;
|
||||||
const unsigned int _modifierMask;
|
const unsigned int _modifierMask;
|
||||||
|
|
||||||
const int _numberParam;
|
int _numberParam;
|
||||||
const std::string _stringParam;
|
std::string _stringParam;
|
||||||
public:
|
public:
|
||||||
inline enum ActionType type() const { return _type;}
|
inline enum ActionType type() const { return _type;}
|
||||||
inline const KeyCode keycode() const { return _keycode; }
|
inline const KeyCode keycode() const { return _keycode; }
|
||||||
|
@ -103,9 +103,7 @@ public:
|
||||||
inline const std::string &string() const { return _stringParam; }
|
inline const std::string &string() const { return _stringParam; }
|
||||||
|
|
||||||
Action(enum ActionType type, KeyCode keycode, unsigned int modifierMask,
|
Action(enum ActionType type, KeyCode keycode, unsigned int modifierMask,
|
||||||
int number = 0);
|
const std::string &str = "");
|
||||||
Action(enum ActionType type, KeyCode keycode, unsigned int modifierMask,
|
|
||||||
const std::string &str);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::list<Action> ActionList;
|
typedef std::list<Action> ActionList;
|
||||||
|
|
|
@ -54,6 +54,7 @@ using std::string;
|
||||||
#include "epist.hh"
|
#include "epist.hh"
|
||||||
#include "screen.hh"
|
#include "screen.hh"
|
||||||
#include "window.hh"
|
#include "window.hh"
|
||||||
|
#include "parser.hh"
|
||||||
#include "../../src/XAtom.hh"
|
#include "../../src/XAtom.hh"
|
||||||
|
|
||||||
|
|
||||||
|
@ -65,7 +66,7 @@ epist::epist(char **argv, char *dpy_name, char *rc_file)
|
||||||
if (rc_file)
|
if (rc_file)
|
||||||
_rc_file = rc_file;
|
_rc_file = rc_file;
|
||||||
else
|
else
|
||||||
_rc_file = expandTilde("~/.openbox/epistrc");
|
_rc_file = expandTilde("~/.epistrc");
|
||||||
|
|
||||||
_xatom = new XAtom(getXDisplay());
|
_xatom = new XAtom(getXDisplay());
|
||||||
|
|
||||||
|
@ -83,52 +84,11 @@ epist::epist(char **argv, char *dpy_name, char *rc_file)
|
||||||
::exit(1);
|
::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
addAction(Action::nextScreen, ControlMask, "Tab");
|
_ktree = new keytree(getXDisplay());
|
||||||
addAction(Action::prevScreen, ControlMask | ShiftMask, "Tab");
|
|
||||||
addAction(Action::nextWindow, Mod1Mask, "Tab");
|
// set up the key tree
|
||||||
addAction(Action::prevWindow, Mod1Mask | ShiftMask, "Tab");
|
parser p(_ktree);
|
||||||
addAction(Action::toggleshade, Mod1Mask, "F5");
|
p.parse(_rc_file);
|
||||||
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");
|
|
||||||
|
|
||||||
activateGrabs();
|
activateGrabs();
|
||||||
}
|
}
|
||||||
|
@ -142,13 +102,8 @@ void epist::activateGrabs() {
|
||||||
|
|
||||||
ScreenList::const_iterator scrit, scrend = _screens.end();
|
ScreenList::const_iterator scrit, scrend = _screens.end();
|
||||||
|
|
||||||
for (scrit = _screens.begin(); scrit != scrend; ++scrit) {
|
for (scrit = _screens.begin(); scrit != scrend; ++scrit)
|
||||||
ActionList::const_iterator ait, end = _actions.end();
|
_ktree->grabDefaults(*scrit);
|
||||||
|
|
||||||
for(ait = _actions.begin(); ait != end; ++ait) {
|
|
||||||
(*scrit)->grabKey(ait->keycode(), ait->modifierMask());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -222,19 +177,3 @@ void epist::cycleScreen(int current, bool forward) const {
|
||||||
const XWindow *target = _screens[dest]->lastActiveWindow();
|
const XWindow *target = _screens[dest]->lastActiveWindow();
|
||||||
if (target) target->focus();
|
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));
|
|
||||||
}
|
|
||||||
|
|
|
@ -32,6 +32,7 @@ extern "C" {
|
||||||
|
|
||||||
#include "actions.hh"
|
#include "actions.hh"
|
||||||
#include "window.hh"
|
#include "window.hh"
|
||||||
|
#include "keytree.hh"
|
||||||
|
|
||||||
#include "../../src/BaseDisplay.hh"
|
#include "../../src/BaseDisplay.hh"
|
||||||
|
|
||||||
|
@ -43,6 +44,7 @@ private:
|
||||||
std::string _rc_file;
|
std::string _rc_file;
|
||||||
XAtom *_xatom;
|
XAtom *_xatom;
|
||||||
char **_argv;
|
char **_argv;
|
||||||
|
keytree *_ktree;
|
||||||
|
|
||||||
typedef std::vector<screen *> ScreenList;
|
typedef std::vector<screen *> ScreenList;
|
||||||
ScreenList _screens;
|
ScreenList _screens;
|
||||||
|
@ -60,10 +62,6 @@ private:
|
||||||
virtual bool handleSignal(int sig);
|
virtual bool handleSignal(int sig);
|
||||||
|
|
||||||
void activateGrabs();
|
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:
|
public:
|
||||||
epist(char **argv, char *display_name, char *rc_file);
|
epist(char **argv, char *display_name, char *rc_file);
|
||||||
|
@ -83,6 +81,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
const ActionList &actions(void) { return _actions; }
|
const ActionList &actions(void) { return _actions; }
|
||||||
|
keytree &getKeyTree(void) { return *_ktree; }
|
||||||
|
|
||||||
WindowList& clientsList() { return _clients; }
|
WindowList& clientsList() { return _clients; }
|
||||||
WindowList::iterator& activeWindow() { return _active; }
|
WindowList::iterator& activeWindow() { return _active; }
|
||||||
|
|
83
util/epist/epist.y
Normal file
83
util/epist/epist.y
Normal file
|
@ -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); }
|
||||||
|
;
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
144
util/epist/keytree.cc
Normal file
144
util/epist/keytree.cc
Normal file
|
@ -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);
|
||||||
|
}
|
72
util/epist/keytree.hh
Normal file
72
util/epist/keytree.hh
Normal file
|
@ -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
|
145
util/epist/parser.cc
Normal file
145
util/epist/parser.cc
Normal file
|
@ -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 = "";
|
||||||
|
}
|
33
util/epist/parser.hh
Normal file
33
util/epist/parser.hh
Normal file
|
@ -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;
|
||||||
|
};
|
|
@ -146,164 +146,162 @@ void screen::processEvent(const XEvent &e) {
|
||||||
|
|
||||||
void screen::handleKeypress(const XEvent &e) {
|
void screen::handleKeypress(const XEvent &e) {
|
||||||
int scrolllockMask, numlockMask;
|
int scrolllockMask, numlockMask;
|
||||||
|
|
||||||
ActionList::const_iterator it = _epist->actions().begin();
|
|
||||||
ActionList::const_iterator end = _epist->actions().end();
|
|
||||||
|
|
||||||
_epist->getLockModifiers(numlockMask, scrolllockMask);
|
_epist->getLockModifiers(numlockMask, scrolllockMask);
|
||||||
|
|
||||||
for (; it != end; ++it) {
|
// Mask out the lock modifiers. We want our keys to always work
|
||||||
unsigned int state = e.xkey.state & ~(LockMask|scrolllockMask|numlockMask);
|
// This should be made an option
|
||||||
|
unsigned int state = e.xkey.state & ~(LockMask|scrolllockMask|numlockMask);
|
||||||
if (e.xkey.keycode == it->keycode() &&
|
const Action *it = _epist->getKeyTree().getAction(e, state, this);
|
||||||
state == it->modifierMask()) {
|
|
||||||
|
if (!it)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (it->type()) {
|
||||||
|
case Action::nextScreen:
|
||||||
|
_epist->cycleScreen(_number, true);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case Action::prevScreen:
|
||||||
|
_epist->cycleScreen(_number, false);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case Action::nextWorkspace:
|
||||||
|
cycleWorkspace(true);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case Action::prevWorkspace:
|
||||||
|
cycleWorkspace(false);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case Action::nextWindow:
|
||||||
|
cycleWindow(true);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case Action::prevWindow:
|
||||||
|
cycleWindow(false);
|
||||||
|
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::prevWindowOnAllScreens:
|
||||||
|
cycleWindow(false, true);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case Action::nextWindowOfClass:
|
||||||
|
cycleWindow(true, false, false, true, it->string());
|
||||||
|
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::changeWorkspace:
|
||||||
|
// we subtract one so counting starts at 1 in the config file
|
||||||
|
changeWorkspace(it->number() - 1);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case Action::execute:
|
||||||
|
execCommand(it->string());
|
||||||
|
return;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// these actions require an active window
|
||||||
|
if (_active != _clients.end()) {
|
||||||
|
XWindow *window = *_active;
|
||||||
|
|
||||||
switch (it->type()) {
|
switch (it->type()) {
|
||||||
case Action::nextScreen:
|
case Action::iconify:
|
||||||
_epist->cycleScreen(_number, true);
|
|
||||||
return;
|
|
||||||
|
|
||||||
case Action::prevScreen:
|
|
||||||
_epist->cycleScreen(_number, false);
|
|
||||||
return;
|
|
||||||
|
|
||||||
case Action::nextWorkspace:
|
|
||||||
cycleWorkspace(true);
|
|
||||||
return;
|
|
||||||
|
|
||||||
case Action::prevWorkspace:
|
|
||||||
cycleWorkspace(false);
|
|
||||||
return;
|
|
||||||
|
|
||||||
case Action::nextWindow:
|
|
||||||
cycleWindow(true);
|
|
||||||
return;
|
|
||||||
|
|
||||||
case Action::prevWindow:
|
|
||||||
cycleWindow(false);
|
|
||||||
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::prevWindowOnAllScreens:
|
|
||||||
cycleWindow(false, true);
|
|
||||||
return;
|
|
||||||
|
|
||||||
case Action::nextWindowOfClass:
|
|
||||||
cycleWindow(true, false, false, true, it->string());
|
|
||||||
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::changeWorkspace:
|
|
||||||
changeWorkspace(it->number());
|
|
||||||
return;
|
|
||||||
|
|
||||||
case Action::execute:
|
|
||||||
execCommand(it->string());
|
|
||||||
return;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// these actions require an active window
|
|
||||||
if (_active != _clients.end()) {
|
|
||||||
XWindow *window = *_active;
|
|
||||||
|
|
||||||
switch (it->type()) {
|
|
||||||
case Action::iconify:
|
|
||||||
window->iconify();
|
window->iconify();
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case Action::close:
|
case Action::close:
|
||||||
window->close();
|
window->close();
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case Action::raise:
|
case Action::raise:
|
||||||
window->raise();
|
window->raise();
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case Action::lower:
|
case Action::lower:
|
||||||
window->lower();
|
window->lower();
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case Action::sendToWorkspace:
|
case Action::sendToWorkspace:
|
||||||
window->sendTo(it->number());
|
window->sendTo(it->number());
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case Action::toggleomnipresent:
|
case Action::toggleomnipresent:
|
||||||
if (window->desktop() == 0xffffffff)
|
if (window->desktop() == 0xffffffff)
|
||||||
window->sendTo(_active_desktop);
|
window->sendTo(_active_desktop);
|
||||||
else
|
else
|
||||||
window->sendTo(0xffffffff);
|
window->sendTo(0xffffffff);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case Action::moveWindowUp:
|
case Action::moveWindowUp:
|
||||||
window->move(window->x(), window->y() - it->number());
|
window->move(window->x(), window->y() - it->number());
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case Action::moveWindowDown:
|
case Action::moveWindowDown:
|
||||||
window->move(window->x(), window->y() + it->number());
|
window->move(window->x(), window->y() + it->number());
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case Action::moveWindowLeft:
|
case Action::moveWindowLeft:
|
||||||
window->move(window->x() - it->number(), window->y());
|
window->move(window->x() - it->number(), window->y());
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case Action::moveWindowRight:
|
case Action::moveWindowRight:
|
||||||
window->move(window->x() + it->number(), window->y());
|
window->move(window->x() + it->number(), window->y());
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case Action::resizeWindowWidth:
|
case Action::resizeWindowWidth:
|
||||||
window->resize(window->width() + it->number(), window->height());
|
window->resize(window->width() + it->number(), window->height());
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case Action::resizeWindowHeight:
|
case Action::resizeWindowHeight:
|
||||||
window->resize(window->width(), window->height() + it->number());
|
window->resize(window->width(), window->height() + it->number());
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case Action::toggleshade:
|
case Action::toggleshade:
|
||||||
window->shade(! window->shaded());
|
window->shade(! window->shaded());
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case Action::toggleMaximizeHorizontal:
|
case Action::toggleMaximizeHorizontal:
|
||||||
window->toggleMaximize(XWindow::Max_Horz);
|
window->toggleMaximize(XWindow::Max_Horz);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case Action::toggleMaximizeVertical:
|
case Action::toggleMaximizeVertical:
|
||||||
window->toggleMaximize(XWindow::Max_Vert);
|
window->toggleMaximize(XWindow::Max_Vert);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case Action::toggleMaximizeFull:
|
case Action::toggleMaximizeFull:
|
||||||
window->toggleMaximize(XWindow::Max_Full);
|
window->toggleMaximize(XWindow::Max_Full);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
assert(false); // unhandled action type!
|
assert(false); // unhandled action type!
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -583,3 +581,21 @@ void screen::grabKey(const KeyCode keyCode, const int modifierMask) const {
|
||||||
modifierMask|numlockMask|LockMask|scrolllockMask,
|
modifierMask|numlockMask|LockMask|scrolllockMask,
|
||||||
_root, True, GrabModeAsync, GrabModeAsync);
|
_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);
|
||||||
|
}
|
||||||
|
|
|
@ -86,6 +86,7 @@ public:
|
||||||
void execCommand(const std::string &cmd) const;
|
void execCommand(const std::string &cmd) const;
|
||||||
|
|
||||||
void grabKey(const KeyCode keyCode, const int modifierMask) const;
|
void grabKey(const KeyCode keyCode, const int modifierMask) const;
|
||||||
|
void ungrabKey(const KeyCode keyCode, const int modifierMask) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __screen_hh
|
#endif // __screen_hh
|
||||||
|
|
Loading…
Reference in a new issue