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 ).
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.
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 ).
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 ...
Tags window-manager xkb qemu x11 spice