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.
This commit is contained in:
mathias 2005-05-06 09:22:53 +00:00
parent 7d4f711204
commit 6c057c6903
10 changed files with 137 additions and 111 deletions

View file

@ -1,5 +1,14 @@
(Format: Year/Month/Day) (Format: Year/Month/Day)
Changes for 0.9.13 Changes for 0.9.13
*05/05/05:
* Fix #1160244, #1099704, #1094107 Mutiple keyboard layout (Mathias + thanx
to Vadim)
Switching to a secondary/third keyboard layout via the xkb-extensions
leads to broken NextWindow/PrevWindow and broken fbrun/CommandDialog:
- be aware of what xkb is doing to the event.state
- minor cleaning
CommandDialog.cc WorkspaceCmd.cc Keys.cc FbTk/KeyUtil.cc/hh
FbTk/TextBox.cc fluxbox.cc FbRun.cc
*05/05/03: *05/05/03:
* Fix drawing of no-title menus, plus updating of int menu items (Simon) * Fix drawing of no-title menus, plus updating of int menu items (Simon)
IntResMenuItem.hh/cc MenuItem.hh Menu.cc Screen.cc ToggleMenu.hh IntResMenuItem.hh/cc MenuItem.hh Menu.cc Screen.cc ToggleMenu.hh

View file

@ -33,6 +33,7 @@
#include "FbTk/ImageControl.hh" #include "FbTk/ImageControl.hh"
#include "FbTk/EventManager.hh" #include "FbTk/EventManager.hh"
#include "FbTk/StringUtil.hh" #include "FbTk/StringUtil.hh"
#include "FbTk/KeyUtil.hh"
#include "FbTk/App.hh" #include "FbTk/App.hh"
#include <X11/keysym.h> #include <X11/keysym.h>
@ -43,11 +44,11 @@
#include <stdexcept> #include <stdexcept>
using namespace std; using namespace std;
CommandDialog::CommandDialog(BScreen &screen, CommandDialog::CommandDialog(BScreen &screen,
const std::string &title, const std::string precommand) : const std::string &title, const std::string precommand) :
FbTk::FbWindow(screen.rootWindow().screenNumber(), 0, 0, 200, 1, ExposureMask), FbTk::FbWindow(screen.rootWindow().screenNumber(), 0, 0, 200, 1, ExposureMask),
m_textbox(*this, screen.winFrameTheme().font(), ""), m_textbox(*this, screen.winFrameTheme().font(), ""),
m_label(*this, screen.winFrameTheme().font(), title), m_label(*this, screen.winFrameTheme().font(), title),
m_gc(m_textbox), m_gc(m_textbox),
m_screen(screen), m_screen(screen),
m_move_x(0), m_move_x(0),
@ -121,12 +122,13 @@ void CommandDialog::motionNotifyEvent(XMotionEvent &event) {
} }
void CommandDialog::keyPressEvent(XKeyEvent &event) { void CommandDialog::keyPressEvent(XKeyEvent &event) {
if (event.state) unsigned int state = FbTk::KeyUtil::instance().isolateModifierMask(event.state);
if (state)
return; return;
KeySym ks; KeySym ks;
char keychar[1]; char keychar;
XLookupString(&event, keychar, 1, &ks, 0); XLookupString(&event, &keychar, 1, &ks, 0);
if (ks == XK_Return) { if (ks == XK_Return) {
hide(); // hide and return focus to a FluxboxWindow hide(); // hide and return focus to a FluxboxWindow
@ -135,7 +137,7 @@ void CommandDialog::keyPressEvent(XKeyEvent &event) {
parseLine(m_precommand + m_textbox.text())); parseLine(m_precommand + m_textbox.text()));
if (cmd.get()) if (cmd.get())
cmd->execute(); cmd->execute();
// post execute // post execute
if (*m_postcommand != 0) if (*m_postcommand != 0)
m_postcommand->execute(); m_postcommand->execute();
@ -152,7 +154,7 @@ void CommandDialog::tabComplete() {
try { try {
string::size_type first = m_textbox.text().find_last_not_of("ABCDEFGHIJKLMNOPQRSTUVWXYZ" string::size_type first = m_textbox.text().find_last_not_of("ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz" "abcdefghijklmnopqrstuvwxyz"
"0123456789", "0123456789",
m_textbox.cursorPosition()); m_textbox.cursorPosition());
if (first == string::npos) if (first == string::npos)
first = 0; first = 0;
@ -173,7 +175,7 @@ void CommandDialog::tabComplete() {
if (!matches.empty()) { if (!matches.empty()) {
// sort and apply larges match // sort and apply larges match
std::sort(matches.begin(), matches.end(), less<string>()); std::sort(matches.begin(), matches.end(), less<string>());
m_textbox.setText(m_textbox.text() + matches[0].substr(prefix.size())); m_textbox.setText(m_textbox.text() + matches[0].substr(prefix.size()));
} else } else
XBell(FbTk::App::instance()->display(), 0); XBell(FbTk::App::instance()->display(), 0);
@ -204,7 +206,7 @@ void CommandDialog::init() {
// setup label // setup label
// we listen to motion notify too // we listen to motion notify too
m_label.setEventMask(m_label.eventMask() | ButtonPressMask | ButtonMotionMask); m_label.setEventMask(m_label.eventMask() | ButtonPressMask | ButtonMotionMask);
m_label.setGC(m_screen.winFrameTheme().labelTextFocusGC()); m_label.setGC(m_screen.winFrameTheme().labelTextFocusGC());
m_label.show(); m_label.show();
@ -234,7 +236,7 @@ void CommandDialog::init() {
void CommandDialog::updateSizes() { void CommandDialog::updateSizes() {
m_label.moveResize(0, 0, m_label.moveResize(0, 0,
width(), m_textbox.font().height() + 2); width(), m_textbox.font().height() + 2);
m_textbox.moveResize(2, m_label.height(), m_textbox.moveResize(2, m_label.height(),
width() - 4, m_textbox.font().height() + 2); width() - 4, m_textbox.font().height() + 2);
} }

View file

@ -26,6 +26,30 @@
#include <string> #include <string>
namespace {
struct t_modlist{
char *str;
unsigned int mask;
bool operator == (const char *modstr) const {
return (strcasecmp(str, modstr) == 0 && mask !=0);
}
};
const struct t_modlist modlist[] = {
{"SHIFT", ShiftMask},
{"LOCK", LockMask},
{"CONTROL", ControlMask},
{"MOD1", Mod1Mask},
{"MOD2", Mod2Mask},
{"MOD3", Mod3Mask},
{"MOD4", Mod4Mask},
{"MOD5", Mod5Mask},
{0, 0}
};
};
namespace FbTk { namespace FbTk {
std::auto_ptr<KeyUtil> KeyUtil::s_keyutil; std::auto_ptr<KeyUtil> KeyUtil::s_keyutil;
@ -57,19 +81,7 @@ void KeyUtil::loadModmap() {
XFreeModifiermap(m_modmap); XFreeModifiermap(m_modmap);
m_modmap = XGetModifierMapping(App::instance()->display()); m_modmap = XGetModifierMapping(App::instance()->display());
// mask to use for modifier
static const int mods[] = {
ShiftMask,
LockMask,
ControlMask,
Mod1Mask,
Mod2Mask,
Mod3Mask,
Mod4Mask,
Mod5Mask,
0
};
// find modifiers and set them // find modifiers and set them
for (int i=0, realkey=0; i<8; ++i) { for (int i=0, realkey=0; i<8; ++i) {
for (int key=0; key<m_modmap->max_keypermod; ++key, ++realkey) { for (int key=0; key<m_modmap->max_keypermod; ++key, ++realkey) {
@ -77,17 +89,18 @@ void KeyUtil::loadModmap() {
if (m_modmap->modifiermap[realkey] == 0) if (m_modmap->modifiermap[realkey] == 0)
continue; continue;
KeySym ks = XKeycodeToKeysym(App::instance()->display(), m_modmap->modifiermap[realkey], 0); KeySym ks = XKeycodeToKeysym(App::instance()->display(),
m_modmap->modifiermap[realkey], 0);
switch (ks) { switch (ks) {
case XK_Caps_Lock: case XK_Caps_Lock:
m_capslock = mods[i]; m_capslock = modlist[i].mask;
break; break;
case XK_Scroll_Lock: case XK_Scroll_Lock:
m_scrolllock = mods[i]; m_scrolllock = modlist[i].mask;
break; break;
case XK_Num_Lock: case XK_Num_Lock:
m_numlock = mods[i]; m_numlock = modlist[i].mask;
break; break;
} }
} }
@ -164,31 +177,13 @@ unsigned int KeyUtil::getKey(const char *keystr) {
} }
struct t_modlist{
char *str;
unsigned int mask;
bool operator == (const char *modstr) const {
return (strcasecmp(str, modstr) == 0 && mask !=0);
}
};
/** /**
@return the modifier for the modstr else zero on failure. @return the modifier for the modstr else zero on failure.
*/ */
unsigned int KeyUtil::getModifier(const char *modstr) { unsigned int KeyUtil::getModifier(const char *modstr) {
if (!modstr) if (!modstr)
return 0; return 0;
const static struct t_modlist modlist[] = {
{"SHIFT", ShiftMask},
{"CONTROL", ControlMask},
{"MOD1", Mod1Mask},
{"MOD2", Mod2Mask},
{"MOD3", Mod3Mask},
{"MOD4", Mod4Mask},
{"MOD5", Mod5Mask},
{0, 0}
};
// find mod mask string // find mod mask string
for (unsigned int i=0; modlist[i].str !=0; i++) { for (unsigned int i=0; modlist[i].str !=0; i++) {
if (modlist[i] == modstr) if (modlist[i] == modstr)
@ -210,7 +205,8 @@ void KeyUtil::ungrabKeys() {
unsigned int KeyUtil::keycodeToModmask(unsigned int keycode) { unsigned int KeyUtil::keycodeToModmask(unsigned int keycode) {
XModifierKeymap *modmap = instance().m_modmap; XModifierKeymap *modmap = instance().m_modmap;
if (!modmap) return 0; if (!modmap)
return 0;
// search through modmap for this keycode // search through modmap for this keycode
for (int mod=0; mod < 8; mod++) { for (int mod=0; mod < 8; mod++) {
@ -218,7 +214,7 @@ unsigned int KeyUtil::keycodeToModmask(unsigned int keycode) {
// modifiermap is an array with 8 sets of keycodes // modifiermap is an array with 8 sets of keycodes
// each max_keypermod long, but in a linear array. // each max_keypermod long, but in a linear array.
if (modmap->modifiermap[modmap->max_keypermod*mod + key] == keycode) { if (modmap->modifiermap[modmap->max_keypermod*mod + key] == keycode) {
return (1<<mod); return modlist[mod].mask;
} }
} }
} }

View file

@ -70,6 +70,14 @@ public:
return mods & ~(capslock() | numlock() ); return mods & ~(capslock() | numlock() );
} }
/**
strip away everything which is actually not a modifier
eg, xkb-keyboardgroups are encoded as bit 13 and 14
*/
unsigned int isolateModifierMask(unsigned int mods) {
return mods & (ShiftMask|LockMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask);
}
/** /**
Convert the specified key into appropriate modifier mask Convert the specified key into appropriate modifier mask
@return corresponding modifier mask @return corresponding modifier mask
@ -78,6 +86,7 @@ public:
int numlock() const { return Mod2Mask; } //m_numlock; } int numlock() const { return Mod2Mask; } //m_numlock; }
int capslock() const { return LockMask; } //m_capslock; } int capslock() const { return LockMask; } //m_capslock; }
int scrolllock() const { return Mod5Mask; } //m_scrolllock; } int scrolllock() const { return Mod5Mask; } //m_scrolllock; }
private: private:
void loadModmap(); void loadModmap();

View file

@ -209,7 +209,7 @@ void TextBox::buttonPressEvent(XButtonEvent &event) {
} }
void TextBox::keyPressEvent(XKeyEvent &event) { void TextBox::keyPressEvent(XKeyEvent &event) {
// strip numlock and scrolllock mask
event.state = KeyUtil::instance().cleanMods(event.state); event.state = KeyUtil::instance().cleanMods(event.state);
KeySym ks; KeySym ks;
@ -218,8 +218,8 @@ void TextBox::keyPressEvent(XKeyEvent &event) {
// a modifier key by itself doesn't do anything // a modifier key by itself doesn't do anything
if (IsModifierKey(ks)) return; if (IsModifierKey(ks)) return;
if (event.state) { // handle keybindings with state if (FbTk::KeyUtil::instance().isolateModifierMask(event.state)) { // handle keybindings with state
if (event.state == ControlMask) { if ((event.state & ControlMask) == ControlMask) {
switch (ks) { switch (ks) {
case XK_b: case XK_b:
@ -248,7 +248,8 @@ void TextBox::keyPressEvent(XKeyEvent &event) {
m_end_pos = 0; m_end_pos = 0;
break; break;
} }
} else if (event.state == ShiftMask || event.state == 0x80) { // shif and altgr } else if ((event.state & ShiftMask)== ShiftMask ||
(event.state & 0x80) == 0x80) { // shif and altgr
if (isprint(keychar[0])) { if (isprint(keychar[0])) {
std::string val; std::string val;
val += keychar[0]; val += keychar[0];

View file

@ -27,7 +27,6 @@
#include "FbTk/StringUtil.hh" #include "FbTk/StringUtil.hh"
#include "FbTk/App.hh" #include "FbTk/App.hh"
#include "FbTk/Command.hh" #include "FbTk/Command.hh"
#include "FbTk/KeyUtil.hh"
#include "CommandParser.hh" #include "CommandParser.hh"
#include "FbTk/I18n.hh" #include "FbTk/I18n.hh"
@ -81,6 +80,8 @@
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/Xproto.h> #include <X11/Xproto.h>
#include <X11/keysym.h> #include <X11/keysym.h>
#include <X11/Xutil.h>
#include <X11/XKBlib.h>
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
@ -102,7 +103,7 @@ Keys::Keys(const char *filename):
load(filename); load(filename);
} }
Keys::~Keys() { Keys::~Keys() {
FbTk::KeyUtil::ungrabKeys(); FbTk::KeyUtil::ungrabKeys();
deleteTree(); deleteTree();
@ -112,12 +113,12 @@ Keys::~Keys() {
void Keys::deleteTree() { void Keys::deleteTree() {
while (!m_keylist.empty()) { while (!m_keylist.empty()) {
if (m_keylist.back()) if (m_keylist.back())
delete m_keylist.back(); delete m_keylist.back();
m_keylist.pop_back(); m_keylist.pop_back();
} }
} }
/** /**
Load and grab keys Load and grab keys
TODO: error checking TODO: error checking
@return true on success else false @return true on success else false
@ -125,7 +126,7 @@ void Keys::deleteTree() {
bool Keys::load(const char *filename) { bool Keys::load(const char *filename) {
if (!filename) if (!filename)
return false; return false;
//ungrab all keys //ungrab all keys
FbTk::KeyUtil::ungrabKeys(); FbTk::KeyUtil::ungrabKeys();
@ -133,7 +134,7 @@ bool Keys::load(const char *filename) {
deleteTree(); deleteTree();
FbTk::App::instance()->sync(false); FbTk::App::instance()->sync(false);
//open the file //open the file
ifstream infile(filename); ifstream infile(filename);
if (!infile) if (!infile)
@ -158,8 +159,8 @@ bool Keys::load(const char *filename) {
bool Keys::save(const char *filename) const { bool Keys::save(const char *filename) const {
//!! //!!
//!! TODO: fix keybinding saving //!! TODO: fix keybinding saving
//!! (we probably need to save key actions //!! (we probably need to save key actions
//!! as strings instead of creating new Commands) //!! as strings instead of creating new Commands)
// open file for writing // open file for writing
@ -178,16 +179,16 @@ bool Keys::addBinding(const std::string &linebuffer) {
// must have at least 1 argument // must have at least 1 argument
if (val.size() <= 0) if (val.size() <= 0)
return true; // empty lines are valid. return true; // empty lines are valid.
if (val[0][0] == '#' || val[0][0] == '!' ) //the line is commented if (val[0][0] == '#' || val[0][0] == '!' ) //the line is commented
return true; // still a valid line. return true; // still a valid line.
unsigned int key = 0, mod = 0; unsigned int key = 0, mod = 0;
char keyarg = 0; char keyarg = 0;
t_key *current_key=0, *last_key=0; t_key *current_key=0, *last_key=0;
_FB_USES_NLS; _FB_USES_NLS;
// for each argument // for each argument
for (unsigned int argc=0; argc<val.size(); argc++) { for (unsigned int argc=0; argc<val.size(); argc++) {
if (val[argc][0] != ':') { // parse key(s) if (val[argc][0] != ':') { // parse key(s)
@ -199,7 +200,7 @@ bool Keys::addBinding(const std::string &linebuffer) {
int tmpmod = FbTk::KeyUtil::getModifier(val[argc].c_str()); int tmpmod = FbTk::KeyUtil::getModifier(val[argc].c_str());
if(tmpmod) if(tmpmod)
mod |= tmpmod; //If it's a modifier mod |= tmpmod; //If it's a modifier
else { else {
key = FbTk::KeyUtil::getKey(val[argc].c_str()); // else get the key key = FbTk::KeyUtil::getKey(val[argc].c_str()); // else get the key
if (key == 0) { if (key == 0) {
cerr<<_FBTEXT(Keys, InvalidKeyMod, "Keys: Invalid key/modifier on line", "A bad key/modifier string was found on line (number following)")<<" "<< 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) {
if (!current_key) { if (!current_key) {
current_key = new t_key(key, mod); current_key = new t_key(key, mod);
last_key = current_key; last_key = current_key;
} else { } else {
t_key *temp_key = new t_key(key, mod); t_key *temp_key = new t_key(key, mod);
last_key->keylist.push_back(temp_key); last_key->keylist.push_back(temp_key);
last_key = temp_key; last_key = temp_key;
} }
} }
} }
} else { // parse command line } else { // parse command line
if (last_key == 0) { if (last_key == 0) {
@ -224,7 +225,7 @@ bool Keys::addBinding(const std::string &linebuffer) {
return false; return false;
} }
bool ret_val = true; bool ret_val = true;
const char *str = const char *str =
FbTk::StringUtil::strcasestr(linebuffer.c_str(), FbTk::StringUtil::strcasestr(linebuffer.c_str(),
val[argc].c_str() + 1); // +1 to skip ':' val[argc].c_str() + 1); // +1 to skip ':'
if (str == 0) { if (str == 0) {
@ -263,41 +264,42 @@ bool Keys::addBinding(const std::string &linebuffer) {
@return the KeyAction of the XKeyEvent @return the KeyAction of the XKeyEvent
*/ */
void Keys::doAction(XKeyEvent &ke) { void Keys::doAction(XKeyEvent &ke) {
static t_key *next_key = 0;
// Remove numlock, capslock and scrolllock
ke.state = FbTk::KeyUtil::instance().cleanMods(ke.state); ke.state = FbTk::KeyUtil::instance().cleanMods(ke.state);
static struct t_key* next_key = 0;
if (!next_key) { if (!next_key) {
for (unsigned int i=0; i<m_keylist.size(); i++) { for (unsigned int i=0; i<m_keylist.size(); i++) {
if (*m_keylist[i] == ke) { if (*m_keylist[i] == ke) {
if (m_keylist[i]->keylist.size()) { if (m_keylist[i]->keylist.size()) {
next_key = m_keylist[i]; next_key = m_keylist[i];
break; //end for-loop break; //end for-loop
} else { } else {
if (*m_keylist[i]->m_command != 0) if (*m_keylist[i]->m_command != 0)
m_keylist[i]->m_command->execute(); m_keylist[i]->m_command->execute();
} }
} }
} }
} else { //check the nextkey } else { //check the nextkey
t_key *temp_key = next_key->find(ke); t_key *temp_key = next_key->find(ke);
if (temp_key) { if (temp_key) {
if (temp_key->keylist.size()) { if (temp_key->keylist.size()) {
next_key = temp_key; next_key = temp_key;
} else { } else {
next_key = 0; next_key = 0;
if (*temp_key->m_command != 0) if (*temp_key->m_command != 0)
temp_key->m_command->execute(); temp_key->m_command->execute();
} }
} else { } else {
temp_key = next_key; temp_key = next_key;
next_key = 0; next_key = 0;
if (*temp_key->m_command != 0) if (*temp_key->m_command != 0)
temp_key->m_command->execute(); temp_key->m_command->execute();
} }
} }
} }
@ -318,7 +320,7 @@ bool Keys::mergeTree(t_key *newtree, t_key *basetree) {
if (basetree==0) { if (basetree==0) {
unsigned int baselist_i=0; unsigned int baselist_i=0;
for (; baselist_i<m_keylist.size(); baselist_i++) { for (; baselist_i<m_keylist.size(); baselist_i++) {
if (m_keylist[baselist_i]->mod == newtree->mod && if (m_keylist[baselist_i]->mod == newtree->mod &&
m_keylist[baselist_i]->key == newtree->key) { m_keylist[baselist_i]->key == newtree->key) {
if (newtree->keylist.size() && *m_keylist[baselist_i]->m_command == 0) { if (newtree->keylist.size() && *m_keylist[baselist_i]->m_command == 0) {
//assumes the newtree only have one branch //assumes the newtree only have one branch
@ -330,12 +332,12 @@ bool Keys::mergeTree(t_key *newtree, t_key *basetree) {
if (baselist_i == m_keylist.size()) { if (baselist_i == m_keylist.size()) {
FbTk::KeyUtil::grabKey(newtree->key, newtree->mod); FbTk::KeyUtil::grabKey(newtree->key, newtree->mod);
m_keylist.push_back(new t_key(newtree)); m_keylist.push_back(new t_key(newtree));
if (newtree->keylist.size()) if (newtree->keylist.size())
return mergeTree(newtree->keylist[0], m_keylist.back()); return mergeTree(newtree->keylist[0], m_keylist.back());
return true; return true;
} }
} else { } else {
unsigned int baselist_i = 0; unsigned int baselist_i = 0;
for (; baselist_i<basetree->keylist.size(); baselist_i++) { for (; baselist_i<basetree->keylist.size(); baselist_i++) {
@ -346,24 +348,24 @@ bool Keys::mergeTree(t_key *newtree, t_key *basetree) {
return mergeTree(newtree->keylist[0], basetree->keylist[baselist_i]); return mergeTree(newtree->keylist[0], basetree->keylist[baselist_i]);
} else } else
return false; return false;
} }
} }
//if it wasn't in the list grab the key and add it to the list //if it wasn't in the list grab the key and add it to the list
if (baselist_i==basetree->keylist.size()) { if (baselist_i==basetree->keylist.size()) {
FbTk::KeyUtil::grabKey(newtree->key, newtree->mod); FbTk::KeyUtil::grabKey(newtree->key, newtree->mod);
basetree->keylist.push_back(new t_key(newtree)); basetree->keylist.push_back(new t_key(newtree));
if (newtree->keylist.size()) if (newtree->keylist.size())
return mergeTree(newtree->keylist[0], basetree->keylist.back()); return mergeTree(newtree->keylist[0], basetree->keylist.back());
return true; return true;
} }
} }
return false; return false;
} }
Keys::t_key::t_key(unsigned int key_, unsigned int mod_, FbTk::RefCount<FbTk::Command> command) { Keys::t_key::t_key(unsigned int key_, unsigned int mod_, FbTk::RefCount<FbTk::Command> command) {
key = key_; key = key_;
mod = mod_; mod = mod_;
m_command = command; m_command = command;
} }
@ -373,8 +375,8 @@ Keys::t_key::t_key(t_key *k) {
m_command = k->m_command; m_command = k->m_command;
} }
Keys::t_key::~t_key() { Keys::t_key::~t_key() {
while (!keylist.empty()) { while (!keylist.empty()) {
t_key *k = keylist.back(); t_key *k = keylist.back();
if (k != 0) { // make sure we don't have a bad key pointer if (k != 0) { // make sure we don't have a bad key pointer
delete k; delete k;

View file

@ -31,6 +31,7 @@
#include "FbTk/NotCopyable.hh" #include "FbTk/NotCopyable.hh"
#include "FbTk/RefCount.hh" #include "FbTk/RefCount.hh"
#include "FbTk/Command.hh" #include "FbTk/Command.hh"
#include "FbTk/KeyUtil.hh"
class Keys:private FbTk::NotCopyable { class Keys:private FbTk::NotCopyable {
public: public:
@ -86,21 +87,22 @@ private:
inline t_key *find(unsigned int key_, unsigned int mod_) { inline t_key *find(unsigned int key_, unsigned int mod_) {
for (unsigned int i=0; i<keylist.size(); i++) { for (unsigned int i=0; i<keylist.size(); i++) {
if (keylist[i]->key == key_ && keylist[i]->mod == mod_) if (keylist[i]->key == key_ && keylist[i]->mod == FbTk::KeyUtil::instance().isolateModifierMask(mod_))
return keylist[i]; return keylist[i];
} }
return 0; return 0;
} }
inline t_key *find(XKeyEvent &ke) { inline t_key *find(XKeyEvent &ke) {
for (unsigned int i=0; i<keylist.size(); i++) { for (unsigned int i=0; i<keylist.size(); i++) {
if (keylist[i]->key == ke.keycode && keylist[i]->mod == ke.state) if (keylist[i]->key == ke.keycode &&
keylist[i]->mod == FbTk::KeyUtil::instance().isolateModifierMask(ke.state))
return keylist[i]; return keylist[i];
} }
return 0; return 0;
} }
inline bool operator == (XKeyEvent &ke) const { inline bool operator == (XKeyEvent &ke) const {
return (mod == ke.state && key == ke.keycode); return (mod == FbTk::KeyUtil::instance().isolateModifierMask(ke.state) && key == ke.keycode);
} }
FbTk::RefCount<FbTk::Command> m_command; FbTk::RefCount<FbTk::Command> m_command;

View file

@ -42,13 +42,13 @@
#include <iostream> #include <iostream>
void NextWindowCmd::execute() { void NextWindowCmd::execute() {
BScreen *screen = Fluxbox::instance()->keyScreen(); BScreen *screen = Fluxbox::instance()->keyScreen();
if (screen != 0) { if (screen != 0) {
Fluxbox *fb = Fluxbox::instance(); Fluxbox *fb = Fluxbox::instance();
// special case for commands from key events // special case for commands from key events
if (fb->lastEvent().type == KeyPress) { if (fb->lastEvent().type == KeyPress) {
unsigned int mods = FbTk::KeyUtil::instance().cleanMods(fb->lastEvent().xkey.state); unsigned int mods = FbTk::KeyUtil::instance().cleanMods(fb->lastEvent().xkey.state);
mods = FbTk::KeyUtil::instance().isolateModifierMask(mods);
if (mods == 0) // can't stacked cycle unless there is a mod to grab if (mods == 0) // can't stacked cycle unless there is a mod to grab
screen->nextFocus(m_option | BScreen::CYCLELINEAR); screen->nextFocus(m_option | BScreen::CYCLELINEAR);
else { else {
@ -71,6 +71,7 @@ void PrevWindowCmd::execute() {
// special case for commands from key events // special case for commands from key events
if (fb->lastEvent().type == KeyPress) { if (fb->lastEvent().type == KeyPress) {
unsigned int mods = FbTk::KeyUtil::instance().cleanMods(fb->lastEvent().xkey.state); unsigned int mods = FbTk::KeyUtil::instance().cleanMods(fb->lastEvent().xkey.state);
mods = FbTk::KeyUtil::instance().isolateModifierMask(mods);
if (mods == 0) // can't stacked cycle unless there is a mod to grab if (mods == 0) // can't stacked cycle unless there is a mod to grab
screen->prevFocus(m_option | BScreen::CYCLELINEAR); screen->prevFocus(m_option | BScreen::CYCLELINEAR);
else { else {

View file

@ -777,11 +777,13 @@ void Fluxbox::handleEvent(XEvent * const e) {
#ifdef DEBUG #ifdef DEBUG
cerr<<__FILE__<<"("<<__FUNCTION__<<"): MappingNotify"<<endl; cerr<<__FILE__<<"("<<__FUNCTION__<<"): MappingNotify"<<endl;
#endif // DEBUG #endif // DEBUG
if (e->xmapping.request == MappingKeyboard
FbTk::KeyUtil::instance().init(); // reinitialise the key utils || e->xmapping.request == MappingModifier) {
// reconfigure keys (if the mapping changes, they don't otherwise update XRefreshKeyboardMapping(&e->xmapping);
m_key->reconfigure(StringUtil::expandFilename(*m_rc_keyfile).c_str()); FbTk::KeyUtil::instance().init(); // reinitialise the key utils
// reconfigure keys (if the mapping changes, they don't otherwise update
m_key->reconfigure(StringUtil::expandFilename(*m_rc_keyfile).c_str());
}
break; break;
case CreateNotify: case CreateNotify:
break; break;
@ -1076,7 +1078,6 @@ void Fluxbox::handleKeyEvent(XKeyEvent &ke) {
if (keyScreen() == 0 || mouseScreen() == 0) if (keyScreen() == 0 || mouseScreen() == 0)
return; return;
switch (ke.type) { switch (ke.type) {
case KeyPress: case KeyPress:
m_key->doAction(ke); m_key->doAction(ke);
@ -1089,9 +1090,10 @@ void Fluxbox::handleKeyEvent(XKeyEvent &ke) {
if (m_watching_screen && m_watch_keyrelease) { if (m_watching_screen && m_watch_keyrelease) {
// mask the mod of the released key out // mask the mod of the released key out
// won't mask anything if it isn't a mod // won't mask anything if it isn't a mod
ke.state &= ~FbTk::KeyUtil::instance().keycodeToModmask(ke.keycode); unsigned int state = FbTk::KeyUtil::instance().isolateModifierMask(ke.state);
state &= ~FbTk::KeyUtil::instance().keycodeToModmask(ke.keycode);
if ((m_watch_keyrelease & ke.state) == 0) {
if ((m_watch_keyrelease & state) == 0) {
m_watching_screen->notifyReleasedKeys(ke); m_watching_screen->notifyReleasedKeys(ke);
XUngrabKeyboard(FbTk::App::instance()->display(), CurrentTime); XUngrabKeyboard(FbTk::App::instance()->display(), CurrentTime);
@ -1107,8 +1109,6 @@ void Fluxbox::handleKeyEvent(XKeyEvent &ke) {
default: default:
break; break;
} }
} }
/// handle system signals /// handle system signals
@ -1951,12 +1951,15 @@ void Fluxbox::unfocusWindow(WinClient &client, bool full_revert, bool unfocus_fr
void Fluxbox::watchKeyRelease(BScreen &screen, unsigned int mods) { void Fluxbox::watchKeyRelease(BScreen &screen, unsigned int mods) {
if (mods == 0) { if (mods == 0) {
cerr<<"WARNING: attempt to grab without modifiers!"<<endl; cerr<<"WARNING: attempt to grab without modifiers!"<<endl;
return; return;
} }
m_watching_screen = &screen; m_watching_screen = &screen;
m_watch_keyrelease = mods;
// just make sure we are saving the mods with any other flags (xkb)
m_watch_keyrelease = FbTk::KeyUtil::instance().isolateModifierMask(mods);
XGrabKeyboard(FbTk::App::instance()->display(), XGrabKeyboard(FbTk::App::instance()->display(),
screen.rootWindow().window(), True, screen.rootWindow().window(), True,
GrabModeAsync, GrabModeAsync, CurrentTime); GrabModeAsync, GrabModeAsync, CurrentTime);

View file

@ -223,7 +223,7 @@ void FbRun::redrawLabel() {
} }
void FbRun::keyPressEvent(XKeyEvent &ke) { void FbRun::keyPressEvent(XKeyEvent &ke) {
// strip numlock, capslock and scrolllock mask
ke.state = FbTk::KeyUtil::instance().cleanMods(ke.state); ke.state = FbTk::KeyUtil::instance().cleanMods(ke.state);
int cp= cursorPosition(); int cp= cursorPosition();
@ -232,10 +232,11 @@ void FbRun::keyPressEvent(XKeyEvent &ke) {
char keychar[1]; char keychar[1];
XLookupString(&ke, keychar, 1, &ks, 0); XLookupString(&ke, keychar, 1, &ks, 0);
// a modifier key by itself doesn't do anything // a modifier key by itself doesn't do anything
if (IsModifierKey(ks)) return; if (IsModifierKey(ks))
return;
if (ke.state) { // a modifier key is down if (FbTk::KeyUtil::instance().isolateModifierMask(ke.state)) { // a modifier key is down
if (ke.state == ControlMask) { if ((ke.state & ControlMask) == ControlMask) {
switch (ks) { switch (ks) {
case XK_p: case XK_p:
prevHistoryItem(); prevHistoryItem();
@ -248,7 +249,7 @@ void FbRun::keyPressEvent(XKeyEvent &ke) {
setCursorPosition(cp); setCursorPosition(cp);
break; break;
} }
} else if (ke.state == (Mod1Mask | ShiftMask)) { } else if ((ke.state & (Mod1Mask|ShiftMask)) == (Mod1Mask | ShiftMask)) {
switch (ks) { switch (ks) {
case XK_less: case XK_less:
firstHistoryItem(); firstHistoryItem();