+ // KeyRelease events only occur during keyboard grabs
+ if (action == KeyAction::Release) return;
+
+ if (key == _resetkey.key && modifiers == _resetkey.modifiers) {
+ resetChains(this);
+ XAllowEvents(**otk::display, AsyncKeyboard, CurrentTime);
+ } 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);
+ if (!_grabbed && !_keybgrab_callback.callback) {
+ Window root = otk::display->screenInfo(screen)->rootWindow();
+ //grab should never fail because we should have a sync grab at
+ //this point
+ XGrabKeyboard(**otk::display, root, 0, GrabModeAsync,
+ GrabModeSync, CurrentTime);
+ }
+ _grabbed = true;
+ _curpos = p;
+ XAllowEvents(**otk::display, AsyncKeyboard, CurrentTime);
+ } 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);
+ XAllowEvents(**otk::display, AsyncKeyboard, CurrentTime);
+ resetChains(this);
+ }
+ break;
+ }
+ p = p->next_sibling;
+ }
+ }
+}