Мне только что пришлось решить ту же проблему, и решение, указанное здесь, не сработало. В конце концов я нашел 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
Вам понадобится re -родительский оконный менеджер . Ваш оконный менеджер также должен убедиться, что распространение событий клавиатуры начинается с родительского окна, а не с исходного окна(Xlib по умолчанию).
Вы можете использовать трюк 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...