+void Bindings::fireKey(int screen, unsigned int modifiers, unsigned int key,
+ Time time, KeyAction::KA action)
+{
+ if (_keybgrab_callback.callback) {
+ Client *c = openbox->focusedClient();
+ KeyData data(screen, c, time, modifiers, key, action);
+ _keybgrab_callback.fire(&data);
+ }
+
+ // KeyRelease events only occur during keyboard grabs
+ if (action == KeyAction::Release) return;
+
+ if (key == _resetkey.key && modifiers == _resetkey.modifiers) {
+ resetChains(this);
+ } else {
+ KeyBindingTree *p = _curpos->first_child;
+ while (p) {
+ if (p->binding.key == key && p->binding.modifiers == modifiers) {
+ if (p->chain) {
+ if (_timer)
+ delete _timer;
+ _timer = new otk::Timer(5000, // 5 second timeout
+ (otk::Timer::TimeoutHandler)resetChains,
+ this);
+ // grab the server here to make sure no key presses get missed
+ otk::display->grab();
+ grabKeys(false);
+ _curpos = p;
+ grabKeys(true);
+ otk::display->ungrab();
+ } else {
+ Client *c = openbox->focusedClient();
+ KeyData data(screen, c, time, modifiers, key, action);
+ KeyCallbackList::iterator it, end = p->callbacks.end();
+ for (it = p->callbacks.begin(); it != end; ++it)
+ it->fire(&data);
+ resetChains(this);
+ }
+ break;
+ }
+ p = p->next_sibling;
+ }
+ }
+}
+
+void Bindings::resetChains(Bindings *self)
+{
+ if (self->_timer) {
+ delete self->_timer;
+ self->_timer = (otk::Timer *) 0;
+ }
+ // grab the server here to make sure no key pressed go missed
+ otk::display->grab();
+ self->grabKeys(false);
+ self->_curpos = &self->_keytree;
+ self->grabKeys(true);
+ otk::display->ungrab();
+}