3

I have this code to listen to keyboard events of the active window:

#include<X11/Xlib.h>
#include<stdio.h>
#include<stdlib.h>
#include <iostream>
#include <thread>
using namespace std;



#define IR_MODE 8192
#define SHIFT_MODE 16
#define US_MODE 0

static int ErrorHandler (Display *display, XErrorEvent *error)
{
    cout<< "An error ocurred. We don't know anything.";
    return 0;
}    

int main()
{
    Display *d = XOpenDisplay(0);
    if(d == 0)
    {
        cout<< "Cannot open display\n";
        exit(0);
    }
    Window root = DefaultRootWindow(d);


    XSetErrorHandler(ErrorHandler);

    Window current_window;
    int rev;
    XGetInputFocus(d,&current_window,&rev);

    XSelectInput(d,current_window, KeyPressMask | KeyReleaseMask | FocusChangeMask);

    while(true) 
    {
        XEvent e;
        XNextEvent(d, &e);
        switch(e.type)
        {
            case FocusOut:
                XGetInputFocus(d,&current_window,&rev);
                if(current_window == PointerRoot || current_window == None)
                {
                    current_window = root;
                }
                XSelectInput(d,current_window,  KeyPressMask | KeyReleaseMask | FocusChangeMask);
                break;
            case KeyPress:
            {                   
                cout<< "key pressed\n";
                break;
            }
            case KeyRelease:
                cout<< "key released\n";
                break;
        }
    }    
    XCloseDisplay(d);//*/
}

It works for many windows. But it fails for some windows, specially for gnome applications, e.g. nautilus. Why does this happen and how can I solve the problem?

The program just tries to listen to keyboard without interfering anything. As if the keyboard is being tapped with a difference: the program doesn't intend to lose language layout info. When a key is pressed, some information including ASCII codes are chosen and attached to the key event according to language layout and then the key event is sent. The program needs the key event with the information attached to it. So The program does not intend to Grab keyboard. It does not care for active or focused window. It just tries to listen to keys even if the program's window is not active. There are programs which check regularly with XQueryKeymap, but I'm not going to use that. Because it uses up CPU and then it will be more than just a fair listener. Also if checking is not frequent some keys may escape.

Minimus Heximus
  • 2,683
  • 3
  • 25
  • 50
  • Wild guess: GTK apps do not use the usual Xlib events to process input, but rather use an configurable input method. See e.g. [the fedora docs](https://fedoraproject.org/wiki/I18N/InputMethods). At least some of them internally use the [XI extension](http://www.x.org/archive/X11R7.6/doc/man/man3/XOpenIM.3.xhtml). Why exactly do you not consider a grab an option? That would be quite simple code, [see e.g. my answer here](http://stackoverflow.com/questions/30994628/why-does-xgrabkey-return-badrequest/31156362#31156362). – Phillip Sep 10 '15 at 13:45
  • @Phillip: Because with grabbing I lose language layout info. See [this](http://stackoverflow.com/a/22774310/2029077). – Minimus Heximus Sep 10 '15 at 14:06
  • @user2029077, FYI: `keylistener` tag is inappropriate here, see its description: "A key listener is an implementation of the Observer pattern which is created specifically for handling keyboard events." – gavv Sep 23 '15 at 17:08
  • But the key-listener questions seems be similar to this one. A keylogger does not need to care for CPU usage. – Minimus Heximus Sep 23 '15 at 17:22
  • In fact, most of `keylistener` questions are related to `KeyListener` from Java: http://docs.oracle.com/javase/7/docs/api/java/awt/event/KeyListener.html – gavv Sep 24 '15 at 11:49

1 Answers1

2

I guess your program does not work with GTK3 windows which uses xinput2. This is true if GTK3 was built without --disable-xinput.

AFAIK XSelectInput() won't work with xinput2, you need XISelectEvents() for such windows.

Look at meta_core_select_events() function from Mutter sources. It works both for xinput2 and traditional windows. This patch may be also helpful.

gavv
  • 4,649
  • 1
  • 23
  • 40
  • What have you tried? These guides may be helpful: http://www.clearchain.com/blog/posts/xinput-1-xinput-2-conversion-guide and http://who-t.blogspot.ru/2009/05/xi2-recipes-part-1.html – gavv Sep 14 '15 at 05:41
  • yet I have not reached a working code but I award the bounty,/ – Minimus Heximus Sep 17 '15 at 12:00
  • I assume porting to xinput-2 will no be a trivial step. Feel free to open a new post when you have a specific problem. – gavv Sep 17 '15 at 15:03