evita que o Qemu / Spice pegue as chaves que estão vinculadas em outro lugar

1

Minha configuração: Qemu com exibição de Spice gerenciada pelo libvirt em execução Linux com X11.

Eu estou procurando uma maneira de preservar as combinações de teclas na janela gerenciador e servidor X quando um cliente Qemu está focado. opção libvirt ou Qemu, uma bandeira de compilação ou alguma mágica X11 - qualquer coisa.

Um exemplo concreto: quando pressiono as teclas Mod4+1 eu quero o WM para mudar para a tag 1 . Atualmente, o convidado recebe o 1 como uma entrada e o WM não recebe nada.

Clientes gráficos do Qemu (principalmente convidados do Windows aqui, mas que não importa) parecem pegar entradas de teclado indiscriminadamente ignorando mesmo xkb. Isso é óbvio pelo fato de que esses clientes ignoram opções como capslock(swapescape) .

Isso causa estragos no gerenciador de janelas. Por exemplo. quando um Qemu o cliente está focado quando percorro clientes, as ligações do WM são inutilizados até que eu desfoco o cliente ofensivo empurrando o mouse ao redor . Escusado será dizer que isso quebra qualquer fluxo de trabalho orientado por teclado. É irritante.

Além disso, como as entradas são passadas para o cliente, todos os tipos de coisas engraçadas podem acontecer dependendo do que o aplicativo dentro o convidado escolhe fazer com essas entradas…

Edit: Upstream aparentemente considera este o comportamento desejado: “nós pegamos o teclado quando temos o foco do teclado, como queremos que qualquer tecla pressione para ir para a vm assim que tivermos o foco do teclado ” - o que é exatamente o que pretendo evitar. Não há razão por que os clientes Spice devem ter o direito de todo teclado insumos, independentemente de serem focados.

    
por phg 21.08.2018 / 10:22

2 respostas

2

Você precisará de um re-parenting window manager . Seu gerenciador de janelas também precisa garantir que a propagação de eventos de teclado seja iniciada a partir da janela pai em vez da janela de origem (Xlib default ).

    
por 22.08.2018 / 08:55
1

Você pode usar o truque LD_PRELOAD para substituir a função XGrabKeyboard de Xlib (ou xcb_grab_keyboard de libxcb ).

Exemplo:

$ cat xgkb.c
#include <X11/Xlib.h>
int XGrabKeyboard(Display *dpy, Window gw, Bool oe, int pm, int km, Time t){
        return 0;
}
$ cc -shared xgkb.c -o xgkb.so
$ LD_PRELOAD='pwd'/xgkb.so your_program

Observe que LD_PRELOAD precisa de caminhos absolutos, LD_PRELOAD=./foo.so não funciona.

Naturalmente, você pode refinar isso deixando a captura ser bem-sucedida se algum flag for definido (por exemplo, alguma propriedade na janela raiz), chamando o% realXGrabKeyboard() com os mesmos argumentos do wrapper. (procure por dlopen(3) , dlsym(3) , RTLD_NEXT ).

Conclusão:

O virt-viewer está usando o XIGrabDevice (provavelmente via gtk) para pegar o teclado e o ponteiro, então algo um pouco mais envolvido é necessário, o que só vai zapp se o dispositivo for um teclado:

$ cat xigd.c
#define _GNU_SOURCE
#include <X11/Xlib.h>
#include <X11/extensions/XInput2.h>
#include <dlfcn.h>

#include <err.h>

Status XIGrabDevice(
        Display*           dpy,
        int                deviceid,
        Window             grab_window,
        Time               time,
        Cursor             cursor,
        int                grab_mode,
        int                paired_device_mode,
        Bool               owner_events,
        XIEventMask        *mask
){
        int n, is_kb;
        static Status (*XIGrabDevice_orig)(Display*, int, Window, Time,
                Cursor, int, int, Bool, XIEventMask*);
        if(!XIGrabDevice_orig)
                XIGrabDevice_orig = dlsym(RTLD_NEXT, "XIGrabDevice");
        XIDeviceInfo *info = XIQueryDevice(dpy, deviceid, &n);
        is_kb = info->num_classes == 1 && info->classes[0]->type == XIKeyClass;
        warnx("trying XIGrabDevice %d %s is_kb=%d %p\n",
                deviceid, info->name, is_kb, XIGrabDevice_orig);
        XIFreeDeviceInfo(info);
        return is_kb ? 0 :
                XIGrabDevice_orig(dpy, deviceid, grab_window,
                        time, cursor, grab_mode, paired_device_mode,
                        owner_events, mask);
}
$ cc -shared -ldl -Wall -W xigd.c -o xigd.so
$ LD_PRELOAD='pwd'/xigd.so virt-viewer ...
    
por 30.08.2018 / 22:10