XNextEvent не работает, когда программа не запускается из терминала - PullRequest
1 голос
/ 11 марта 2020

Я пытаюсь создать программу, которая реагирует на нажатия клавиш пользователя для отображения информации на экране.

Мне удалось создать окно для отображения информации, но у меня проблемы с захватом нажатий клавиш - или, более конкретно, захватом нажатий клавиш при запуске программы не непосредственно с моего терминала.

Если я просто запускаю его как ./program, нажатия клавиш регистрируются, как и ожидалось, но если я запускаю его из сопоставления sxhkd, оно не работает.

Я собрал урезанный версия программы без отображения информации для иллюстрации проблемы:

#include <X11/Xlib.h>
#include <stdlib.h>
#include <stdio.h>

int main()
{
    Display *display;
    Window   window, rootwindow;
    XEvent   event;
    KeySym   escape;

    display = XOpenDisplay(NULL);
    rootwindow = DefaultRootWindow(display);

    window = XCreateWindow(display, rootwindow,
                           -99, -99, 1, 1, 
                           0, 0, InputOnly,
                           CopyFromParent,
                           0, NULL); 

    XSetWindowAttributes winattr;
    winattr.override_redirect = 1;
    XChangeWindowAttributes(display, window, CWOverrideRedirect, &winattr);

    XGrabKeyboard(display, rootwindow, False, GrabModeAsync, GrabModeAsync, CurrentTime);

    XMapWindow(display, window);
    XSelectInput(display, rootwindow, KeyPressMask | KeyReleaseMask );

    while (1)
      {
          XNextEvent(display, &event);

          /* keyboard events */
          if (event.type == KeyPress)
          {
              printf( "KeyPress: %x\n", event.xkey.keycode );
              system("echo test >> ~/output");

              /* exit on ESC key press */
              if ( event.xkey.keycode == 0x09 )
                  break;
          }
          else if (event.type == KeyRelease)
          {
              printf( "KeyRelease: %x\n", event.xkey.keycode );
          }
      }

    XUngrabKeyboard(display, CurrentTime);
    XUnmapWindow(display, window);
    XCloseDisplay(display);
    return 0;
}

Вы можете создать ее с помощью gcc main.c -o program -lX11 -lXfixes -lXtst.

Если вы запустите ./program в своем терминале, вы должны увидеть Распечатывается информация KeyPress и KeyRelease, и вы можете остановить программу с помощью ES C.

Но если вы сопоставите его с сочетанием клавиш где-то, чтобы он не запускался таким образом, программа не будет реагировать на нажатия клавиш и не выйдет на ES C (вам потребуется чтобы убить его вручную).

Я думаю, виновник устанавливает override_redirect для созданного окна, но мне нужно это сделать, поскольку я не хочу, чтобы программа открывала новое управляемое окно, а наложила .

Я не совсем уверен, в чем проблема, поэтому, возможно, потребуется исправить заголовок этого вопроса.

Возможно ли то, чего я пытаюсь достичь? И если так, что я делаю не так?

lsof вывод:

0r      CHR                1,3       0t0       2051 /dev/null
1w      CHR                1,3       0t0       2051 /dev/null
2w      REG                8,3   3590712     524358 /home/eyfl/.xsession-errors
3u     unix 0x00000000648e641e       0t0    4028921 type=STREAM
4u     unix 0x00000000f842df04       0t0      24192 /tmp/bspwm_0_0-socket type=STREAM
...