Предотвратите QEMU / SPICE от ключей захватывающих ключей, которые связаны в другом месте

Мне только что пришлось решить ту же проблему, и решение, указанное здесь, не сработало. В конце концов я нашел xkb-switch , который нормально работал с awesome. Он имеет дополнительный бонус в виде упрощенного кода в файле rc.lua .

-- language switcher
kbdcfg = {}
kbdcfg.cmd = "xkb-switch -n"
kbdcfg.widget = wibox.widget.textbox()

kbdcfg.current = io.popen("xkb-switch"):read("*a")
kbdcfg.widget:set_text(kbdcfg.current)
kbdcfg.switch = function()
    os.execute(kbdcfg.cmd)
    kbdcfg.current = io.popen("xkb-switch"):read("*a")
    kbdcfg.widget:set_text(kbdcfg.current)
end

3
21.08.2018, 13:22
2 ответа

Вам понадобится re -родительский оконный менеджер . Ваш оконный менеджер также должен убедиться, что распространение событий клавиатуры начинается с родительского окна, а не с исходного окна(Xlib по умолчанию).

2
27.01.2020, 21:21

Вы можете использовать трюк LD_PRELOAD, чтобы переопределить функцию XGrabKeyboardизXlib(или xcb_grab_keyboardиз libxcb).

Пример:

$ 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

Конечно, вы можете улучшить это, разрешив захват, если установлен какой-либо флаг (, например. некоторое свойство в корневом окне ), вызвав настоящее XGrabKeyboard()с теми же аргументами из оболочки. (ищите dlopen(3), dlsym(3),RTLD_NEXT).

Завершение:

virt -средство просмотра используетXIGrabDevice(возможно через gtk )для захвата и клавиатуры, и указателя, поэтому требуется что-то более сложное, что заблокирует захват только в том случае, если устройство является клавиатурой:

$ 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...
1
27.01.2020, 21:21

Теги

Похожие вопросы