From 617635f8eb87bd21ef9e57a578398fbba14173f2 Mon Sep 17 00:00:00 2001 From: Mathias Gumz Date: Wed, 9 Apr 2014 22:40:13 +0200 Subject: fix excessive loading of keys file caused by xmodmap xmodmap (and other tools) trigger MappingNotify events. a single xmodmap expression such as "keycode comma = comma semicolon" might trigger 4 or 5 MappingNotify events. loading the keys file on each of them is quite unefficient. fluxbox now uses a (250ms) timer which is reset upon further events. --- src/fluxbox.cc | 53 ++++++++++++++++++++++++++++++++++++++++++----------- src/fluxbox.hh | 1 + 2 files changed, 43 insertions(+), 11 deletions(-) diff --git a/src/fluxbox.cc b/src/fluxbox.cc index 07419ba..995ab91 100644 --- a/src/fluxbox.cc +++ b/src/fluxbox.cc @@ -187,6 +187,29 @@ int handleXIOErrors(Display* d) { } + +class KeyReloadHelper { +public: + void reload() { + Fluxbox* f = Fluxbox::instance(); + Keys* k = (f ? f->keys() : 0); + if (k) { + XRefreshKeyboardMapping(&(this->xmapping)); + FbTk::KeyUtil::instance().init(); + k->regrab(); + } + } + + XMappingEvent xmapping; +}; + +KeyReloadHelper s_key_reloader; + +typedef FbTk::SimpleCommand KeyReloadHelperCmd; +typedef FbTk::SimpleCommand FluxboxCmd; + + + /* functor to call a memberfunction with by a reference argument other places needs this helper as well it should be moved to FbTk/ @@ -303,11 +326,21 @@ Fluxbox::Fluxbox(int argc, char **argv, // Because when the command is executed we shouldn't do reconfig directly // because it could affect ongoing menu stuff so we need to reconfig in // the next event "round". - FbTk::RefCount > reconfig_cmd(new FbTk::SimpleCommand(*this, &Fluxbox::timed_reconfigure)); + FluxboxCmd* reconfig_cmd = new FluxboxCmd(*this, &Fluxbox::timed_reconfigure); m_reconfig_timer.setTimeout(1); - m_reconfig_timer.setCommand(reconfig_cmd); + m_reconfig_timer.setCommand(FbTk::RefCount >(reconfig_cmd)); m_reconfig_timer.fireOnce(true); + // xmodmap and other tools send a lot of MappingNotify events under some + // circumstances ("keysym comma = comma semicolon" creates 4 or 5). + // reloading the keys-file for every one of them is unclever. we postpone + // the reload() via a timer. + KeyReloadHelperCmd* rh_cmd = + new KeyReloadHelperCmd(s_key_reloader, &KeyReloadHelper::reload); + m_key_reload_timer.setTimeout(250 * FbTk::FbTime::IN_MILLISECONDS); + m_key_reload_timer.setCommand(FbTk::RefCount >(rh_cmd)); + m_key_reload_timer.fireOnce(true); + if (xsync) XSynchronize(disp, True); @@ -675,21 +708,18 @@ void Fluxbox::handleEvent(XEvent * const e) { break; case UnmapNotify: handleUnmapNotify(e->xunmap); - break; - case MappingNotify: - // Update stored modifier mapping - fbdbg<<"MappingNotify"<xmapping.request == MappingKeyboard || e->xmapping.request == MappingModifier) { - XRefreshKeyboardMapping(&e->xmapping); - FbTk::KeyUtil::instance().init(); // reinitialise the key utils - // reconfigure keys (if the mapping changes, they don't otherwise update - m_key->regrab(); + + s_key_reloader.xmapping = e->xmapping; + m_key_reload_timer.start(); } break; case CreateNotify: - break; + break; case DestroyNotify: { WinClient *winclient = searchWindow(e->xdestroywindow.window); if (winclient != 0) { @@ -1239,6 +1269,7 @@ void Fluxbox::load_rc(BScreen &screen) { } void Fluxbox::reconfigure() { + m_key_reload_timer.stop(); load_rc(); m_reconfigure_wait = true; m_reconfig_timer.start(); diff --git a/src/fluxbox.hh b/src/fluxbox.hh index f6a8f26..d0bc239 100644 --- a/src/fluxbox.hh +++ b/src/fluxbox.hh @@ -277,6 +277,7 @@ private: ///< when we execute reconfig command we must wait until next event round FbTk::Timer m_reconfig_timer; + FbTk::Timer m_key_reload_timer; bool m_showing_dialog; std::auto_ptr m_key; -- cgit v0.11.2