У меня есть этот код для прослушивания событий клавиатуры активного окна:
#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,¤t_window,&rev);
XSelectInput(d,current_window, KeyPressMask | KeyReleaseMask | FocusChangeMask);
while(true)
{
XEvent e;
XNextEvent(d, &e);
switch(e.type)
{
case FocusOut:
XGetInputFocus(d,¤t_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);//*/
}
Это работает для многих окон. Но это не работает для некоторых окон, особенно для приложений GNOME, например наутилус. Почему это происходит и как я могу решить проблему?
Программа просто пытается слушать клавиатуру, ничего не мешая. Как будто клавиатура нажата с различием: программа не намерена терять информацию о раскладке языка. Когда клавиша нажата, некоторая информация, включая коды ASCII, выбирается и прикрепляется к событию клавиши в соответствии с языковой раскладкой, а затем отправляется событие клавиши. Программа нуждается в ключевом событии с прикрепленной к нему информацией. Поэтому программа не намерена захватывать клавиатуру. Это не заботится об активном или сфокусированном окне. Он просто пытается прослушивать клавиши, даже если окно программы не активно. Есть программы, которые регулярно проверяют XQueryKeymap
, но я не собираюсь этим пользоваться. Потому что он использует процессор, и тогда он будет больше, чем просто слушатель. Также, если проверка не частая, некоторые ключи могут сбежать.
Я полагаю, ваша программа не работает с окнами GTK3, которые используют xinput2. Это верно, если GTK3 был построен без --disable-xinput
,
насколько мне известно XSelectInput()
не будет работать с xinput2, вам нужно XISelectEvents()
для таких окон.
смотреть на meta_core_select_events()
функция из источников Mutter. Работает как для xinput2, так и для традиционных окон. это пластырь может быть также полезным.