From 4c1a242968dff12e504f281224819b7cd3850a04 Mon Sep 17 00:00:00 2001 From: markt <markt> Date: Sun, 4 Mar 2007 17:47:37 +0000 Subject: moved some code around (regarding event handling) in preparation for upcoming features --- src/FbTk/EventHandler.hh | 4 +-- src/FbTk/EventManager.cc | 22 +++++++++++-- src/FbTk/EventManager.hh | 7 ++++- src/FocusControl.cc | 4 ++- src/Screen.cc | 71 +++++++++++++++++++++++++++++++++++------- src/Screen.hh | 16 ++++++++-- src/WorkspaceCmd.cc | 56 ++++----------------------------- src/fluxbox.cc | 80 ------------------------------------------------ src/fluxbox.hh | 8 ----- 9 files changed, 110 insertions(+), 158 deletions(-) diff --git a/src/FbTk/EventHandler.hh b/src/FbTk/EventHandler.hh index 3d2e545..45c7a2a 100644 --- a/src/FbTk/EventHandler.hh +++ b/src/FbTk/EventHandler.hh @@ -54,11 +54,11 @@ public: 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 diff --git a/src/FbTk/EventManager.cc b/src/FbTk/EventManager.cc index 02259ac..fd26950 100644 --- a/src/FbTk/EventManager.cc +++ b/src/FbTk/EventManager.cc @@ -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 @@ void EventManager::dispatch(Window win, XEvent &ev, bool parent) { evhand->keyPressEvent(ev.xkey); break; case KeyRelease: -#ifdef NOT_USED evhand->keyReleaseEvent(ev.xkey); -#endif break; case ButtonPress: evhand->buttonPressEvent(ev.xbutton); diff --git a/src/FbTk/EventManager.hh b/src/FbTk/EventManager.hh index 5bbaa00..149649b 100644 --- a/src/FbTk/EventManager.hh +++ b/src/FbTk/EventManager.hh @@ -43,6 +43,10 @@ public: 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 @@ public: 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 diff --git a/src/FocusControl.cc b/src/FocusControl.cc index f4c8cdf..e494d8f 100644 --- a/src/FocusControl.cc +++ b/src/FocusControl.cc @@ -30,6 +30,8 @@ #include "fluxbox.hh" #include "FbWinFrameTheme.hh" +#include "FbTk/EventManager.hh" + #include <string> #include <iostream> @@ -82,7 +84,7 @@ bool doSkipWindow(const WinClient &winclient, int opts) { 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; diff --git a/src/Screen.cc b/src/Screen.cc index b676a8b..3dfe324 100644 --- a/src/Screen.cc +++ b/src/Screen.cc @@ -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 @@ BScreen::BScreen(FbTk::ResourceManager &rm, 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 @@ BScreen::BScreen(FbTk::ResourceManager &rm, 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 @@ -538,6 +541,9 @@ BScreen::~BScreen() { if (! managed) return; + FbTk::EventManager *evm = FbTk::EventManager::instance(); + evm->remove(rootWindow()); + if (m_rootmenu.get() != 0) m_rootmenu->removeAll(); @@ -780,6 +786,59 @@ void BScreen::update(FbTk::Subject *subj) { } +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) { FbTk::Menu *menu = new FbMenu(menuTheme(), imageControl(), @@ -2054,16 +2113,6 @@ void BScreen::renderPosWindow() { } - - - -/** - Called when a set of watched modifiers has been released -*/ -void BScreen::notifyReleasedKeys() { - focusControl().stopCyclingFocus(); -} - void BScreen::updateSize() { // force update geometry rootWindow().updateGeometry(); diff --git a/src/Screen.hh b/src/Screen.hh index de1dc78..8694f6d 100644 --- a/src/Screen.hh +++ b/src/Screen.hh @@ -32,6 +32,8 @@ #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 @@ class Subject; /** 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 @@ public: 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(); @@ -294,8 +304,6 @@ public: 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 @@ -477,6 +485,8 @@ private: typedef std::map<Window, WinClient *> Groupables; Groupables m_expecting_groups; + bool m_cycling; + // Xinerama related private data bool m_xinerama_avail; int m_xinerama_num_heads; diff --git a/src/WorkspaceCmd.cc b/src/WorkspaceCmd.cc index 7d384aa..0cbf5b9 100644 --- a/src/WorkspaceCmd.cc +++ b/src/WorkspaceCmd.cc @@ -42,59 +42,15 @@ #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() { diff --git a/src/fluxbox.cc b/src/fluxbox.cc index c71e2f5..e4c68bf 100644 --- a/src/fluxbox.cc +++ b/src/fluxbox.cc @@ -228,7 +228,6 @@ Fluxbox::Fluxbox(int argc, char **argv, const char *dpy_name, const char *rcfile 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 @@ void Fluxbox::handleEvent(XEvent * const e) { switch (e->type) { case ButtonRelease: case ButtonPress: - handleButtonEvent(e->xbutton); break; case ConfigureRequest: { @@ -894,7 +892,6 @@ void Fluxbox::handleEvent(XEvent * const e) { break; case KeyRelease: case KeyPress: - handleKeyEvent(e->xkey); break; case ColormapNotify: { BScreen *screen = searchScreen(e->xcolormap.window); @@ -958,20 +955,6 @@ void Fluxbox::handleEvent(XEvent * const e) { } } -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 @@ void Fluxbox::handleClientMessage(XClientMessageEvent &ce) { } } -/** - 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; @@ -1810,28 +1752,6 @@ void Fluxbox::updateFocusedWindow(BScreen *screen, BScreen *old_screen) { } } -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) { AtomHandlerContainerIt it = m_atomhandler.begin(); AtomHandlerContainerIt it_end = m_atomhandler.end(); diff --git a/src/fluxbox.hh b/src/fluxbox.hh index 5613caa..66fdff5 100644 --- a/src/fluxbox.hh +++ b/src/fluxbox.hh @@ -141,8 +141,6 @@ public: 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 @@ public: 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 @@ private: 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 @@ private: FluxboxWindow *m_masked_window; BScreen *m_mousescreen, *m_keyscreen; - BScreen *m_watching_screen; - unsigned int m_watch_keyrelease; Atom m_fluxbox_pid; -- cgit v0.11.2