+ assert(callback);
+ if (_keybgrab_callback.callback) return false; // already grabbed
+
+ if (!openbox->screen(screen))
+ return false; // the screen is not managed
+
+ Window root = otk::display->screenInfo(screen)->rootWindow();
+ if (XGrabKeyboard(**otk::display, root, false, GrabModeAsync,
+ GrabModeAsync, CurrentTime))
+ return false;
+ _keybgrab_callback.callback = callback;
+ _keybgrab_callback.data = data;
+ return true;
+}
+
+
+void Bindings::ungrabKeyboard()
+{
+ if (!_keybgrab_callback.callback) return; // not grabbed
+
+ _keybgrab_callback = KeyCallbackData(0, 0);
+ if (!_grabbed) /* don't release out from under keychains */
+ XUngrabKeyboard(**otk::display, CurrentTime);
+ XUngrabPointer(**otk::display, CurrentTime);
+}
+
+
+bool Bindings::grabPointer(int screen)
+{
+ if (!openbox->screen(screen))
+ return false; // the screen is not managed
+
+ Window root = otk::display->screenInfo(screen)->rootWindow();
+ XGrabPointer(**otk::display, root, false, 0, GrabModeAsync,
+ GrabModeAsync, None, None, CurrentTime);
+ return true;
+}
+
+
+void Bindings::ungrabPointer()
+{
+ XUngrabPointer(**otk::display, CurrentTime);
+}
+
+
+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;
+