Why XGrabKey generates extra focus-out and focus-in events?
Finally, as you know linux means freedom, i modified xserver to get rid of grab-style focusout:
sudo apt-get build-dep xorg-server
apt-get source xorg-server
cd xorg-server-*
#modify or patch dix/events.c: comment off "DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab);" in ActivateKeyboardGrab(), comment off "DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab);" in DeactivateKeyboardGrab()
sudo apt-get install devscripts
debuild -us -uc #"-us -uc" to avoid the signature step
cd ..
sudo dpkg --install xserver-xorg-core_*.deb
#clear dependencies:
sudo apt-mark auto $(apt-cache showsrc xorg-server | grep Build-Depends | perl -p -e 's/(?:[\[(].+?[\])]|Build-Depends:|,|\|)//g')
sudo apt-get autoremove
And i also need to get rid of XGrabKeyboard in gtk context menu:
sudo apt-get build-dep gtk+2.0
apt-get source gtk+2.0
cd gtk+2.0-*
#modify or patch it: add "return TRUE;" in first line of popup_grab_on_window() of gtk/gtkmenu.c
dpkg-source --commit
debuild -us -uc #"-us -uc" to avoid the signature step, maybe need: sudo apt-get install devscripts
cd ..
sudo dpkg --install libgtk2.0-0_*.deb
#clear dependencies:
sudo apt-mark auto $(apt-cache showsrc gtk+2.0 | grep Build-Depends | perl -p -e 's/(?:[\[(].+?[\])]|Build-Depends:|,|\|)//g')
sudo apt-get autoremove
Now myboard.py works well.
If you are using ubuntu raring-updates edition, you could give a try to:
https://code.google.com/p/diyism-myboard/downloads/detail?name=xserver-xorg-core_1.13.3-0ubuntu6.2_i386.deb
and:
https://code.google.com/p/diyism-myboard/downloads/detail?name=libgtk2.0-0_2.24.17-0ubuntu2_i386.deb
During XGrabKey(board), discover which window had been focused
Wait for the next FocusOut
event, verify that the mode
is set to NotifyUngrab
, get the focus with XGetInputFocus()
, and send away your synthetic events.
FocusIn/FocusOut not generated
Having focus refers to the window which receives keyboard input when you press a key.
The focus handling depends on your window manager. The most common mode is click to focus, which your window manager is set to, where you only get focus when you click on the window. An alternative is that the keyboard focus follows the mouse, which is what you are expecting.
There should be a setting to change this in your window manager settings.
The cursor changing does not indicate focus, just that the terminal has defined a different cursor.
To demonstrate, open a terminal and an xev window.
- Click on the xev window and press a key, you will see key events.
- Move the mouse to the terminal window, you'll see the motion and leave events
- Press a key and you'll still see key events from xev
- Click on the terminal window, xev will give a focus out event
- Press a key, the characters will be displayed in the terminal window
- Move the mouse over the xev window and press a key, the character will still come out in the terminal window
How to prevent window from loosing focus when receiving a grabbed key from X11
Finally got it to work in a "proper" way:
bool MainWidget::nativeEvent(const QByteArray &eventType, void *message, long *)
{
#ifdef Q_OS_LINUX
if (eventType == "xcb_generic_event_t")
{
xcb_generic_event_t* event = static_cast<xcb_generic_event_t *>(message);
switch (event->response_type & 127)
{
case XCB_FOCUS_OUT: {
xcb_focus_out_event_t *fe = (xcb_focus_out_event_t *)event;
if ((fe->mode==XCB_NOTIFY_MODE_GRAB && fe->detail==XCB_NOTIFY_DETAIL_NONLINEAR)
|| (fe->mode==XCB_NOTIFY_MODE_NORMAL && fe->detail==XCB_NOTIFY_DETAIL_NONLINEAR ))
hide();
break;
}
}
}
#endif
return false;
}
X11 FocusIn is not working
It appears as though I set the FocusChangeMask at the wrong place. By adding the line XSelectInput(x_display, opengl_window, FocusChangeMask)
, it now triggers the FocusIn event. It was triggering the other display because it had the mask but this one didn't.
Why does XGrabKey return BadRequest?
A return value of 1
does not mean that a BadRequest error occured. Xlib handles errors via an error handler, and the function will always return 1
, if it returns at all.
Your code does not work because you have to do the XGrabKey
on the root window (GetDefaultRootWindow(Gtk::gdk_display)
). Here's a pure Xlib demo:
#include <X11/Xlib.h>
#include <X11/keysym.h>
#include <stdio.h>
int main() {
Display *d = XOpenDisplay(0);
Window root = DefaultRootWindow(d);
int keycode = XKeysymToKeycode(d, XK_BackSpace);
int rv = XGrabKey(d, keycode, AnyModifier, root, 1, GrabModeAsync, GrabModeAsync);
printf("XGrabKey returned %d\n", rv);
XEvent evt;
while(1) {
XNextEvent(d, &evt);
printf("Got event %d\n", evt.type);
}
}
To then capture the X11 events from GTK use gdk_window_add_filter
on a NULL
or on the root window and a GdkFilterFunc
that processes the events associated with your global hotkey:
#include <X11/Xlib.h>
#include <X11/keysym.h>
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#include <stdio.h>
GdkFilterReturn filter(GdkXEvent *xevent, GdkEvent *event, gpointer data) {
XKeyEvent *ev = (XKeyEvent *)xevent;
if(ev->type == 2) {
printf("Backspace hit.\n");
}
return GDK_FILTER_CONTINUE;
}
int main(int argc, char *argv[]) {
gtk_init(&argc, &argv);
GdkScreen *scr = gdk_screen_get_default();
GdkWindow *groot = gdk_screen_get_root_window(scr);
gdk_window_set_events(groot, GDK_KEY_PRESS_MASK);
gdk_window_add_filter(groot, filter, NULL);
Display *d = gdk_x11_get_default_xdisplay();
Window root = GDK_WINDOW_XID(groot);
int keycode = XKeysymToKeycode(d, XK_BackSpace);
XGrabKey(d, keycode, AnyModifier, root, 1, GrabModeAsync, GrabModeAsync);
gtk_main();
}
As a side note, a modifier mask of 0
means that no modifiers must be enabled, even those that would not modify the meaning of a key. A grab on the letter "A" with a 0
modifier would not match NumLock + A. That's why I used AnyModifer
.
X sends many key up events when a key is held
Here is the more definitive answer, right from these boards. First result on Google:
Ignore auto repeat in X11 applications
Related Topics
Behaviour of Increment and Decrement Operators in Python
How to Check File Size in Python
How to Get the Last Day of the Month
How to Get the Day of Week Given a Date
Background Thread With Qthread in Pyqt
Generating Variable Names on Fly in Python
Python Lambda'S Binding to Local Values
Convert Timestamps With Offset to Datetime Obj Using Strptime
How to Modify Lines in a File In-Place
Comparing a String to Multiple Items in Python
How to Simulate Input to Stdin for Pyunit
Sending a Password Over Ssh or Scp with Subprocess.Popen
How to Split a Huge CSV File Based on Content of First Column
When Using Os.Execlp, Why 'Python' Needs 'Python' as Argv[0]
Oserror 38 [Errno 38] with Multiprocessing
Python Multiprocessing Memory Usage