StructureNotifyMask interfere com outras janelas no Linux Mint

0

Estou tentando capturar todas as entradas de teclado com base no código de esta resposta . A captura real de chaves está funcionando bem. No entanto, a execução do código no Linux Mint Cinnamon causa outros problemas:

  1. Não consigo arrastar ou redimensionar nenhuma janela usando o mouse
  2. Clicar nas opções da barra de menus em xed e nemo (arquivo, visualização, etc ...) não abre as opções de submenu
  3. Clicar no menu Iniciar exibe a lista de aplicativos, mas o foco é mantido pela janela atrás dele, portanto, não posso passar o mouse, rolar ou clicar nos itens da lista de aplicativos.

Uma versão simplificada, mas funcional, do código segue. Reduzi a causa para a presença da máscara de evento StructureNotifyMask em XSelectInput . Sem essa máscara de evento, nenhum dos problemas acima está presente. Mas isso também significa que o programa não é notificado quando a janela é mapeada e, portanto, a captura não funciona.

Como posso obter a captura para funcionar sem nenhuma das questões acima? Eu tentei incluir um segundo XSelectInput após o programa ser notificado do mapeamento que tem apenas a tecla pressionada e liberar máscaras de evento. No entanto, isso não parece resolver o problema.

#include <X11/Xlib.h>
#include <X11/keysym.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, /* x, y, width, height */
                           0, 0, InputOnly, /* border, depth, class */
                           CopyFromParent, /* visual */
                           0, NULL); /* valuemask and attributes */

    XSelectInput(display, window, StructureNotifyMask | KeyPressMask | KeyReleaseMask);    

    XMapWindow(display, window);

    do {
        XNextEvent(display, &event);
    } while (event.type != MapNotify);

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

    escape = XKeysymToKeycode(display, XK_Escape);
    printf("\nPress ESC to exit.\n\n");
    fflush(stdout);

    while (1) {

        XNextEvent(display, &event);

        if (event.type == KeyPress) {
            printf("KeyPress: keycode %u state %u\n", event.xkey.keycode, event.xkey.state);
            fflush(stdout);

        } else
        if (event.type == KeyRelease) {

            printf("KeyRelease: keycode %u state %u\n", event.xkey.keycode, event.xkey.state);
            fflush(stdout);

            if (event.xkey.keycode == escape)
                break;
        } else {

            printf("Event type %d\n", event.type);
            fflush(stdout);
        }
    }

    XUngrabKeyboard(display, CurrentTime);

    XDestroyWindow(display, window);
    XCloseDisplay(display);
    return 0;
}
    
por Elfalem 02.11.2017 / 02:18

1 resposta

1

Você não pode fazer um XGrabKeyboard permanente. Esta captura destina-se apenas a ser usada temporariamente, contanto que algum tipo de interação esteja em andamento.

Se você continuar segurando, todas as outras funções que precisam ser capturadas (como as operações do WM que você mencionou) não funcionarão.

    
por 02.11.2017 / 11:03