6

After calling XGrabKeyboard(), my application captures and displays all key presses / releases, including those for the GUI and PrintScreen keys. However, the user is no longer able to move the application's window. So far, this occurs on Fedora 17 and Ubuntu 12.04.

How can I allow the user to move the application while being under the effect of XGrabKeyboard()?

Below is sample code for my Qt application:

bool KeyboardStatus::x11Event(XEvent *event) {
    switch (event->type) {
        case FocusIn:
            XGrabKeyboard(x11Info().display(), winId(), false, GrabModeAsync, GrabModeAsync, CurrentTime);
            break;

        case FocusOut:
            XUngrabKeyboard(x11Info().display(), CurrentTime);
            break;

        case KeyPress:
            // Display which key was pressed to user
            return true;

        case KeyRelease:
            // Display which key was released to user
            return true;
    }

    return false;
}

Taking the grab statement out of the event handler does not solve the issue. Here is a sample project which illustrates the problem: TestGrab.zip

Daniel
  • 8,655
  • 5
  • 60
  • 87
  • 1
    I tried a simple example of just creating an X11 window and then grabbing the keyboard and I seem to be able to move the window fine. I looked up the documentation for `XGrabKeyboard` and it says that it generates a `FocusIn` event, but it looks like you're calling `XGrabKeyboard` within a `FocusIn` event. Is it possible you're in an infinite loop on `FocusIn` events and so the 'window grab' isn't handled, perhaps? Try print something out on a `FocusIn` event. – Jengerer Jan 30 '13 at 19:26
  • @Jengerer I moved the grab and ungrab calls outside the event loop but the window remains frozen upon grabbing the keyboard. Perhaps this is a Qt-specific issue. What OS are you using? – Daniel Feb 02 '13 at 09:23
  • 1
    @DanielK just what do you mean by "outside event loop"? Everything (in single threaded app) is running in the event loop, so maybe you mean, outside the event handler? So how does it get called? If by signal, try changing signal connection to queued, maybe. – hyde Feb 04 '13 at 12:43
  • @hyde You're right, I misspoke. I meant "outside the event handler". I moved the grab code to a slot which gets called by a clicked signal from a GUI button. I'll try the queued method. – Daniel Feb 04 '13 at 15:46
  • 1
    @DanielK if it's triggered by button, then *probably* making connection queued makes not difference, I was thinking may you emitted from the event handler (with direct connection, that is same as direct function call). Another thing to try is, try different window manager/desktop environment, especially if your Ubuntu and Fedora both had same one. – hyde Feb 04 '13 at 16:10
  • 1
    Is KeyboardStatus your main application class? – parkydr Feb 07 '13 at 11:03
  • @parkydr Yes it is. It's derived from a QWidget and has a Q_OBJECT statement in the declaration of the class. This is a small project so it's the only declared class in the application. – Daniel Feb 07 '13 at 14:33
  • 1
    I've set up the same thing but I can move the window on Debian testing. – parkydr Feb 07 '13 at 17:41
  • 1
    Qwidget has methods for handling focus, key presses and grabbing the keyboard. Maybe those would work better. – parkydr Feb 07 '13 at 18:25
  • 1
    Which window manager are you using? I changed x11Event to always return true so all events are thrown away. Although nothing works in the window, I can move it around as this is done by the window manager not the application. – parkydr Feb 07 '13 at 21:22
  • @parkydr It's happening with Gnome on Fedora 17 and Unity on Ubuntu 12.04. When you tried it on Debian, are you sure you're grabbing the keyboard? Does your app prevent the windows manager from receiving key events? – Daniel Feb 12 '13 at 01:32
  • I've added a sample project to the description of the question. Can you tell me if you get the same issue if you run it? – Daniel Feb 12 '13 at 01:36
  • @parkydr Qt's [`QWidget::grabKeyboard()`](http://qt-project.org/doc/qt-4.8/qwidget.html#grabKeyboard) also freezes the window. – Daniel Feb 12 '13 at 01:57
  • @parkydr There's no real reason why I'm not using Qt's [`QWidget::keyPressEvent()`](http://qt-project.org/doc/qt-4.8/qwidget.html#keyPressEvent) and [`QWidget::keyReleaseEvent()`](http://qt-project.org/doc/qt-4.8/qwidget.html#keyReleaseEvent). However the issue occurs regardless which method of key detection I'm using. – Daniel Feb 12 '13 at 02:07
  • 1
    I'm using kwin (KDE) and it is working e.g. Alt Tab doesn't change windows – parkydr Feb 12 '13 at 06:32
  • 1
    I've now tries it with FVWM and Gnome. FVWM works but with Gnome, I get the same fault. I'm not using QT, just straight Xlib. The keyboard is being grabbed but I can't move the window. – parkydr Feb 12 '13 at 10:39
  • @parkydr Thanks for the help. If it happens just with Xlib on Gnome I don't think there's anything I can do about it. If you post "It's an Xlib / Gnome issue" as an answer to this question, I'll be glad to mark it as the correct answer. – Daniel Feb 12 '13 at 10:42
  • 1
    I still think there may be a way but I can't think of one. Interesting problem though. – parkydr Feb 12 '13 at 11:08

2 Answers2

2

I have tried this on KDE, FVWM and GNOME (just using Xlib), and only the GNOME window manager has this problem.

I thought it might be possible to fix it by picking up the ConfigureNotify event, but it is not generated when you try to move the window.

parkydr
  • 7,596
  • 3
  • 32
  • 42
2

I have had similar problem with XFCE on Cygwin. Here the problem was with insufficient input mask passed to XSelectInput. Adding FocusChangeMask to KeyPressMask | KeyReleaseMask solved the problem.

Once again, it helped me to fix similar problem on xfce/cygwin.

Anonymous
  • 2,122
  • 19
  • 26