moved some code around (regarding event handling) in preparation for upcoming features
@@ -54,11 +54,11 @@ virtual void buttonReleaseEvent(XButtonEvent &) { }
virtual void exposeEvent(XExposeEvent &) { } virtual void motionNotifyEvent(XMotionEvent &) { } virtual void keyPressEvent(XKeyEvent &) { } -#ifdef NOT_USED virtual void keyReleaseEvent(XKeyEvent &) { } -#endif virtual void leaveNotifyEvent(XCrossingEvent &) { } virtual void enterNotifyEvent(XCrossingEvent &) { } + + virtual void notifyUngrabKeyboard() { } }; } // end namespace FbTk
@@ -66,6 +66,26 @@ EventHandler *EventManager::find(Window win) {
return m_eventhandlers[win]; } +bool EventManager::grabKeyboard(EventHandler &ev, Window win) { + if (m_grabbing_keyboard) + ungrabKeyboard(); + + int ret = XGrabKeyboard(App::instance()->display(), win, False, + GrabModeAsync, GrabModeAsync, CurrentTime); + + if (ret == Success) { + m_grabbing_keyboard = &ev; + return true; + } + return false; +} + +void EventManager::ungrabKeyboard() { + XUngrabKeyboard(App::instance()->display(), CurrentTime); + if (m_grabbing_keyboard) + m_grabbing_keyboard->notifyUngrabKeyboard(); + m_grabbing_keyboard = 0; +} Window EventManager::getEventWindow(XEvent &ev) { // we only have cases for events that differ from xany@@ -156,9 +176,7 @@ case KeyPress:
evhand->keyPressEvent(ev.xkey); break; case KeyRelease: -#ifdef NOT_USED evhand->keyReleaseEvent(ev.xkey); -#endif break; case ButtonPress: evhand->buttonPressEvent(ev.xbutton);
@@ -43,6 +43,10 @@ void remove(const FbWindow &win);
void add(EventHandler &ev, Window win) { registerEventHandler(ev, win); } void remove(Window win) { unregisterEventHandler(win); } + bool grabKeyboard(EventHandler &ev, Window win); + void ungrabKeyboard(); + EventHandler *grabbingKeyboard() { return m_grabbing_keyboard; } + EventHandler *find(Window win); // Some events have the parent window as the xany.window@@ -53,13 +57,14 @@ void registerEventHandler(EventHandler &ev, Window win);
void unregisterEventHandler(Window win); private: - EventManager() { } + EventManager(): m_grabbing_keyboard(0) { } ~EventManager(); void dispatch(Window win, XEvent &event, bool parent = false); typedef std::map<Window, EventHandler *> EventHandlerMap; EventHandlerMap m_eventhandlers; EventHandlerMap m_parent; + EventHandler *m_grabbing_keyboard; }; } //end namespace FbTk
@@ -30,6 +30,8 @@ #include "Workspace.hh"
#include "fluxbox.hh" #include "FbWinFrameTheme.hh" +#include "FbTk/EventManager.hh" + #include <string> #include <iostream>@@ -82,7 +84,7 @@
void FocusControl::cycleFocus(FocusedWindows *window_list, int opts, bool cycle_reverse) { if (!m_cycling_list) { - if (&m_screen == Fluxbox::instance()->watchingScreen()) + if (&m_screen == FbTk::EventManager::instance()->grabbingKeyboard()) // only set this when we're waiting for modifiers m_cycling_list = window_list; m_was_iconic = 0;
@@ -28,6 +28,7 @@
#include "Screen.hh" #include "fluxbox.hh" +#include "Keys.hh" #include "Window.hh" #include "Workspace.hh" #include "Netizen.hh"@@ -364,6 +365,7 @@ m_name(screenname),
m_altname(altscreenname), m_focus_control(new FocusControl(*this)), m_placement_strategy(new ScreenPlacement(*this)), + m_cycling(false), m_xinerama_headinfo(0), m_restart(false), m_shutdown(false) {@@ -416,7 +418,8 @@ "informational message saying screen number (%d), visual (%lx), and colour depth (%d)").c_str(),
screenNumber(), XVisualIDFromVisual(rootWindow().visual()), rootWindow().depth()); - + FbTk::EventManager *evm = FbTk::EventManager::instance(); + evm->add(*this, rootWindow()); rootWindow().setCursor(XCreateFontCursor(disp, XC_left_ptr)); // load this screens resources@@ -537,6 +540,9 @@
if (! managed) return; + + FbTk::EventManager *evm = FbTk::EventManager::instance(); + evm->remove(rootWindow()); if (m_rootmenu.get() != 0) m_rootmenu->removeAll();@@ -778,6 +784,59 @@ const Icons::iterator it_end = iconList().end();
for (; it != it_end; ++it) fluxbox->updateFrameExtents(**it); +} + +void BScreen::keyPressEvent(XKeyEvent &ke) { + Fluxbox::instance()->keys()->doAction(ke.type, ke.state, ke.keycode); +} + +void BScreen::keyReleaseEvent(XKeyEvent &ke) { + if (!m_cycling) + return; + + unsigned int state = FbTk::KeyUtil::instance().cleanMods(ke.state); + state &= ~FbTk::KeyUtil::instance().keycodeToModmask(ke.keycode); + + if (!state) // all modifiers were released + FbTk::EventManager::instance()->ungrabKeyboard(); +} + +void BScreen::buttonPressEvent(XButtonEvent &be) { + if (be.button == 1 && !isRootColormapInstalled()) + imageControl().installRootColormap(); + + Keys *keys = Fluxbox::instance()->keys(); + keys->doAction(be.type, be.state, be.button); +} + +void BScreen::notifyUngrabKeyboard() { + m_cycling = false; + focusControl().stopCyclingFocus(); +} + +void BScreen::cycleFocus(int options, bool reverse) { + // get modifiers from event that causes this for focus order cycling + XEvent ev = Fluxbox::instance()->lastEvent(); + unsigned int mods = 0; + if (ev.type == KeyPress) + mods = FbTk::KeyUtil::instance().cleanMods(ev.xkey.state); + else if (ev.type == ButtonPress) + mods = FbTk::KeyUtil::instance().cleanMods(ev.xbutton.state); + + if (!m_cycling && mods) { + m_cycling = true; + FbTk::EventManager::instance()->grabKeyboard(*this, rootWindow().window()); + } + + if (mods == 0) // can't stacked cycle unless there is a mod to grab + options |= FocusControl::CYCLELINEAR; + + FocusControl::FocusedWindows *win_list = + (options & FocusControl::CYCLELINEAR) ? + &focusControl().creationOrderList() : + &focusControl().focusedOrderList(); + + focusControl().cycleFocus(win_list, options, reverse); } FbTk::Menu *BScreen::createMenu(const string &label) {@@ -2052,16 +2111,6 @@
if (tmp) imageControl().removeImage(tmp); -} - - - - -/** - Called when a set of watched modifiers has been released -*/ -void BScreen::notifyReleasedKeys() { - focusControl().stopCyclingFocus(); } void BScreen::updateSize() {
@@ -32,6 +32,8 @@ #include "FbRootWindow.hh"
#include "MenuTheme.hh" #include "PlacementStrategy.hh" +#include "FbTk/EventHandler.hh" +#include "FbTk/TypeAhead.hh" #include "FbTk/Resource.hh" #include "FbTk/Subject.hh" #include "FbTk/MultLayers.hh"@@ -78,7 +80,8 @@ /// Handles screen connection, screen clients and workspaces
/** Create workspaces, handles switching between workspaces and windows */ -class BScreen : public FbTk::Observer, private FbTk::NotCopyable { +class BScreen: public FbTk::EventHandler, public FbTk::Observer, + private FbTk::NotCopyable { public: /// a window becomes active / focussed on a different workspace enum FollowModel {@@ -209,6 +212,13 @@ //@}
void update(FbTk::Subject *subj); + void keyPressEvent(XKeyEvent &ke); + void keyReleaseEvent(XKeyEvent &ke); + void buttonPressEvent(XButtonEvent &be); + void notifyUngrabKeyboard(); + + void cycleFocus(int opts, bool reverse); + FbTk::Menu *createMenu(const std::string &label); FbTk::Menu *createToggleMenu(const std::string &label); void hideMenus();@@ -293,8 +303,6 @@ void hidePosition();
/// show geomentry with "width x height"-text, not size of window void showGeometry(int width, int height); void hideGeometry(); - - void notifyReleasedKeys(); void setLayer(FbTk::XLayerItem &item, int layernum); // remove? no, items are never removed from their layer until they die@@ -476,6 +484,8 @@ // This is a map of windows to clients for clients that had a left
// window set, but that window wasn't present at the time typedef std::map<Window, WinClient *> Groupables; Groupables m_expecting_groups; + + bool m_cycling; // Xinerama related private data bool m_xinerama_avail;
@@ -42,59 +42,15 @@ #include <algorithm>
#include <functional> void NextWindowCmd::execute() { - Fluxbox *fb = Fluxbox::instance(); - BScreen *screen = fb->keyScreen(); - if (screen != 0) { - // get modifiers from event that causes this for focus order cycling - unsigned int mods = 0; - XEvent ev = fb->lastEvent(); - if (ev.type == KeyPress) { - mods = FbTk::KeyUtil::instance().cleanMods(ev.xkey.state); - } else if (ev.type == ButtonPress) { - mods = FbTk::KeyUtil::instance().cleanMods(ev.xbutton.state); - } - int options = m_option; - if (mods == 0) // can't stacked cycle unless there is a mod to grab - options |= FocusControl::CYCLELINEAR; - else - // set a watch for the release of exactly these modifiers - fb->watchKeyRelease(*screen, mods); - - FocusControl::FocusedWindows *win_list = - (options & FocusControl::CYCLELINEAR) ? - &screen->focusControl().creationOrderList() : - &screen->focusControl().focusedOrderList(); - - screen->focusControl().cycleFocus(win_list, m_option); - } + BScreen *screen = Fluxbox::instance()->keyScreen(); + if (screen != 0) + screen->cycleFocus(m_option, false); } void PrevWindowCmd::execute() { - Fluxbox *fb = Fluxbox::instance(); - BScreen *screen = fb->keyScreen(); - if (screen != 0) { - // get modifiers from event that causes this for focus order cycling - unsigned int mods = 0; - XEvent ev = fb->lastEvent(); - if (ev.type == KeyPress) { - mods = FbTk::KeyUtil::instance().cleanMods(ev.xkey.state); - } else if (ev.type == ButtonPress) { - mods = FbTk::KeyUtil::instance().cleanMods(ev.xbutton.state); - } - int options = m_option; - if (mods == 0) // can't stacked cycle unless there is a mod to grab - options |= FocusControl::CYCLELINEAR; - else - // set a watch for the release of exactly these modifiers - fb->watchKeyRelease(*screen, mods); - - FocusControl::FocusedWindows *win_list = - (options & FocusControl::CYCLELINEAR) ? - &screen->focusControl().creationOrderList() : - &screen->focusControl().focusedOrderList(); - - screen->focusControl().cycleFocus(win_list, m_option, true); - } + BScreen *screen = Fluxbox::instance()->keyScreen(); + if (screen != 0) + screen->cycleFocus(m_option, true); } void DirFocusCmd::execute() {
@@ -228,7 +228,6 @@ m_rc_mod_key(m_resourcemanager, "Mod1", "session.modKey", "Session.ModKey"),
m_masked_window(0), m_mousescreen(0), m_keyscreen(0), - m_watching_screen(0), m_watch_keyrelease(0), m_last_time(0), m_masked(0), m_rc_file(rcfilename ? rcfilename : ""),@@ -746,7 +745,6 @@
switch (e->type) { case ButtonRelease: case ButtonPress: - handleButtonEvent(e->xbutton); break; case ConfigureRequest: {@@ -894,7 +892,6 @@ case Expose:
break; case KeyRelease: case KeyPress: - handleKeyEvent(e->xkey); break; case ColormapNotify: { BScreen *screen = searchScreen(e->xcolormap.window);@@ -958,20 +955,6 @@
} } -void Fluxbox::handleButtonEvent(XButtonEvent &be) { - m_last_time = be.time; - - BScreen *screen = searchScreen(be.window); - if (be.type == ButtonRelease || !screen) - // no bindings for this type yet - return; - - if (be.button == 1 && !screen->isRootColormapInstalled()) - screen->imageControl().installRootColormap(); - - m_key->doAction(be.type, be.state, be.button); -} - void Fluxbox::handleUnmapNotify(XUnmapEvent &ue) { BScreen *screen = searchScreen(ue.event);@@ -1092,47 +1075,6 @@
} } -/** - Handles KeyRelease and KeyPress events -*/ -void Fluxbox::handleKeyEvent(XKeyEvent &ke) { - - if (keyScreen() == 0 || mouseScreen() == 0) - return; - - switch (ke.type) { - case KeyPress: - m_key->doAction(ke.type, ke.state, ke.keycode); - break; - case KeyRelease: { - // we ignore most key releases unless we need to use - // a release to stop something (e.g. window cycling). - - // we notify if _all_ of the watched modifiers are released - if (m_watching_screen && m_watch_keyrelease) { - // mask the mod of the released key out - // won't mask anything if it isn't a mod - unsigned int state = FbTk::KeyUtil::instance().isolateModifierMask(ke.state); - state &= ~FbTk::KeyUtil::instance().keycodeToModmask(ke.keycode); - - if ((m_watch_keyrelease & state) == 0) { - - m_watching_screen->notifyReleasedKeys(); - XUngrabKeyboard(FbTk::App::instance()->display(), CurrentTime); - - // once they are released, we drop the watch - m_watching_screen = 0; - m_watch_keyrelease = 0; - } - } - - break; - } - default: - break; - } -} - /// handle system signals void Fluxbox::handleSignal(int signum) { _FB_USES_NLS;@@ -1808,28 +1750,6 @@ for (AtomHandlerContainerIt it= m_atomhandler.begin();
it != m_atomhandler.end(); it++) (*it).first->updateFocusedWindow(*old_screen, 0); } -} - -void Fluxbox::watchKeyRelease(BScreen &screen, unsigned int mods) { - - if (mods == 0) { - cerr<<"WARNING: attempt to grab without modifiers!"<<endl; - return; - } - // just make sure we are saving the mods with any other flags (xkb) - m_watch_keyrelease = FbTk::KeyUtil::instance().isolateModifierMask(mods); - - if (m_watching_screen == &screen) - return; - if (m_watching_screen) - m_watching_screen->focusControl().stopCyclingFocus(); - m_watching_screen = &screen; - - // TODO: it's possible (and happens to me sometimes) for the mods to be - // released before we grab the keyboard -- not sure of a good way to fix it - XGrabKeyboard(FbTk::App::instance()->display(), - screen.rootWindow().window(), True, - GrabModeAsync, GrabModeAsync, CurrentTime); } void Fluxbox::updateFrameExtents(FluxboxWindow &win) {
@@ -141,8 +141,6 @@
void maskWindowEvents(Window w, FluxboxWindow *bw) { m_masked = w; m_masked_window = bw; } - void watchKeyRelease(BScreen &screen, unsigned int mods); - void shutdown(); void load_rc(BScreen &scr); void saveStyleFilename(const char *val) { m_rc_stylefile = (val == 0 ? "" : val); }@@ -203,8 +201,6 @@ // screen mouse was in at last key event
BScreen *mouseScreen() { return m_mousescreen; } // screen of window that last key event (i.e. focused window) went to BScreen *keyScreen() { return m_keyscreen; } - // screen we are watching for modifier changes - BScreen *watchingScreen() { return m_watching_screen; } const XEvent &lastEvent() const { return m_last_event; } AttentionNoticeHandler &attentionHandler() { return m_attention_handler; }@@ -228,10 +224,8 @@
void handleEvent(XEvent *xe); void setupConfigFiles(); - void handleButtonEvent(XButtonEvent &be); void handleUnmapNotify(XUnmapEvent &ue); void handleClientMessage(XClientMessageEvent &ce); - void handleKeyEvent(XKeyEvent &ke); std::auto_ptr<FbAtoms> m_fbatoms;@@ -272,8 +266,6 @@
FluxboxWindow *m_masked_window; BScreen *m_mousescreen, *m_keyscreen; - BScreen *m_watching_screen; - unsigned int m_watch_keyrelease; Atom m_fluxbox_pid;