don't let KeyRelease events propagate to windows

This commit is contained in:
Mark Tiefenbruck 2008-09-28 01:26:21 -07:00
parent c8022b3bdb
commit 04a1d2a83b
7 changed files with 33 additions and 40 deletions

View file

@ -56,7 +56,6 @@ public:
virtual void leaveNotifyEvent(XCrossingEvent &) { } virtual void leaveNotifyEvent(XCrossingEvent &) { }
virtual void enterNotifyEvent(XCrossingEvent &) { } virtual void enterNotifyEvent(XCrossingEvent &) { }
virtual void notifyUngrabKeyboard() { }
virtual void grabButtons() { } virtual void grabButtons() { }
}; };

View file

@ -65,25 +65,14 @@ EventHandler *EventManager::find(Window win) {
return m_eventhandlers[win]; return m_eventhandlers[win];
} }
bool EventManager::grabKeyboard(EventHandler &ev, Window win) { bool EventManager::grabKeyboard(Window win) {
if (m_grabbing_keyboard)
ungrabKeyboard();
int ret = XGrabKeyboard(App::instance()->display(), win, False, int ret = XGrabKeyboard(App::instance()->display(), win, False,
GrabModeAsync, GrabModeAsync, CurrentTime); GrabModeAsync, GrabModeAsync, CurrentTime);
return (ret == Success);
if (ret == Success) {
m_grabbing_keyboard = &ev;
return true;
}
return false;
} }
void EventManager::ungrabKeyboard() { void EventManager::ungrabKeyboard() {
XUngrabKeyboard(App::instance()->display(), CurrentTime); XUngrabKeyboard(App::instance()->display(), CurrentTime);
if (m_grabbing_keyboard)
m_grabbing_keyboard->notifyUngrabKeyboard();
m_grabbing_keyboard = 0;
} }
Window EventManager::getEventWindow(XEvent &ev) { Window EventManager::getEventWindow(XEvent &ev) {
@ -190,10 +179,14 @@ void EventManager::dispatch(Window win, XEvent &ev, bool parent) {
evhand->exposeEvent(ev.xexpose); evhand->exposeEvent(ev.xexpose);
break; break;
case EnterNotify: case EnterNotify:
evhand->enterNotifyEvent(ev.xcrossing); if (ev.xcrossing.mode != NotifyGrab &&
ev.xcrossing.mode != NotifyUngrab)
evhand->enterNotifyEvent(ev.xcrossing);
break; break;
case LeaveNotify: case LeaveNotify:
evhand->leaveNotifyEvent(ev.xcrossing); if (ev.xcrossing.mode != NotifyGrab &&
ev.xcrossing.mode != NotifyUngrab)
evhand->leaveNotifyEvent(ev.xcrossing);
break; break;
default: default:
evhand->handleEvent(ev); evhand->handleEvent(ev);

View file

@ -42,9 +42,8 @@ public:
void add(EventHandler &ev, Window win) { registerEventHandler(ev, win); } void add(EventHandler &ev, Window win) { registerEventHandler(ev, win); }
void remove(Window win) { unregisterEventHandler(win); } void remove(Window win) { unregisterEventHandler(win); }
bool grabKeyboard(EventHandler &ev, Window win); bool grabKeyboard(Window win);
void ungrabKeyboard(); void ungrabKeyboard();
EventHandler *grabbingKeyboard() { return m_grabbing_keyboard; }
EventHandler *find(Window win); EventHandler *find(Window win);

View file

@ -91,7 +91,7 @@ void FocusControl::cycleFocus(const FocusableList &window_list,
const ClientPattern *pat, bool cycle_reverse) { const ClientPattern *pat, bool cycle_reverse) {
if (!m_cycling_list) { if (!m_cycling_list) {
if (&m_screen == FbTk::EventManager::instance()->grabbingKeyboard()) if (m_screen.isCycling())
// only set this when we're waiting for modifiers // only set this when we're waiting for modifiers
m_cycling_list = &window_list; m_cycling_list = &window_list;
m_was_iconic = 0; m_was_iconic = 0;

View file

@ -510,12 +510,6 @@ bool Keys::doAction(int type, unsigned int mods, unsigned int key,
// grab "None Escape" to exit keychain in the middle // grab "None Escape" to exit keychain in the middle
unsigned int esc = FbTk::KeyUtil::getKey("Escape"); unsigned int esc = FbTk::KeyUtil::getKey("Escape");
// if focus changes, windows will get NotifyWhileGrabbed,
// which they tend to ignore
if (temp_key && type == KeyPress &&
!FbTk::EventManager::instance()->grabbingKeyboard())
XUngrabKeyboard(Fluxbox::instance()->display(), CurrentTime);
if (temp_key && !temp_key->keylist.empty()) { // emacs-style if (temp_key && !temp_key->keylist.empty()) { // emacs-style
if (!saved_keymode) if (!saved_keymode)
saved_keymode = m_keylist; saved_keymode = m_keylist;
@ -536,6 +530,11 @@ bool Keys::doAction(int type, unsigned int mods, unsigned int key,
return false; return false;
} }
// if focus changes, windows will get NotifyWhileGrabbed,
// which they tend to ignore
if (type == KeyPress)
XUngrabKeyboard(Fluxbox::instance()->display(), CurrentTime);
WinClient *old = WindowCmd<void>::client(); WinClient *old = WindowCmd<void>::client();
WindowCmd<void>::setClient(current); WindowCmd<void>::setClient(current);
temp_key->m_command->execute(); temp_key->m_command->execute();

View file

@ -856,19 +856,26 @@ void BScreen::propertyNotify(Atom atom) {
} }
void BScreen::keyPressEvent(XKeyEvent &ke) { void BScreen::keyPressEvent(XKeyEvent &ke) {
Fluxbox::instance()->keys()->doAction(ke.type, ke.state, ke.keycode, if (Fluxbox::instance()->keys()->doAction(ke.type, ke.state, ke.keycode,
Keys::GLOBAL|Keys::ON_DESKTOP); Keys::GLOBAL|Keys::ON_DESKTOP))
// re-grab keyboard, so we don't pass KeyRelease to clients
FbTk::EventManager::instance()->grabKeyboard(rootWindow().window());
} }
void BScreen::keyReleaseEvent(XKeyEvent &ke) { void BScreen::keyReleaseEvent(XKeyEvent &ke) {
if (!m_cycling) if (m_cycling) {
return; unsigned int state = FbTk::KeyUtil::instance().cleanMods(ke.state);
state &= ~FbTk::KeyUtil::instance().keycodeToModmask(ke.keycode);
unsigned int state = FbTk::KeyUtil::instance().cleanMods(ke.state); if (state) // still cycling
state &= ~FbTk::KeyUtil::instance().keycodeToModmask(ke.keycode); return;
if (!state) // all modifiers were released m_cycling = false;
FbTk::EventManager::instance()->ungrabKeyboard(); focusControl().stopCyclingFocus();
}
FbTk::EventManager::instance()->ungrabKeyboard();
} }
void BScreen::buttonPressEvent(XButtonEvent &be) { void BScreen::buttonPressEvent(XButtonEvent &be) {
@ -880,11 +887,6 @@ void BScreen::buttonPressEvent(XButtonEvent &be) {
0, be.time); 0, be.time);
} }
void BScreen::notifyUngrabKeyboard() {
m_cycling = false;
focusControl().stopCyclingFocus();
}
void BScreen::cycleFocus(int options, const ClientPattern *pat, bool reverse) { void BScreen::cycleFocus(int options, const ClientPattern *pat, bool reverse) {
// get modifiers from event that causes this for focus order cycling // get modifiers from event that causes this for focus order cycling
XEvent ev = Fluxbox::instance()->lastEvent(); XEvent ev = Fluxbox::instance()->lastEvent();
@ -896,7 +898,7 @@ void BScreen::cycleFocus(int options, const ClientPattern *pat, bool reverse) {
if (!m_cycling && mods) { if (!m_cycling && mods) {
m_cycling = true; m_cycling = true;
FbTk::EventManager::instance()->grabKeyboard(*this, rootWindow().window()); FbTk::EventManager::instance()->grabKeyboard(rootWindow().window());
} }
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

View file

@ -237,7 +237,6 @@ public:
void keyPressEvent(XKeyEvent &ke); void keyPressEvent(XKeyEvent &ke);
void keyReleaseEvent(XKeyEvent &ke); void keyReleaseEvent(XKeyEvent &ke);
void buttonPressEvent(XButtonEvent &be); void buttonPressEvent(XButtonEvent &be);
void notifyUngrabKeyboard();
/** /**
* Cycles focus of windows * Cycles focus of windows
@ -247,6 +246,8 @@ public:
*/ */
void cycleFocus(int opts = 0, const ClientPattern *pat = 0, bool reverse = false); void cycleFocus(int opts = 0, const ClientPattern *pat = 0, bool reverse = false);
bool isCycling() const { return m_cycling; }
/** /**
* Creates an empty menu with specified label * Creates an empty menu with specified label
* @param label for the menu * @param label for the menu