在不创建 window 的情况下,是否可以检测当前的 XCB 修改器状态?
Without creating a window, is it possible to detect the current XCB modifier state?
我使用 Xkb sticky
选项,我想编写一个程序,当修改键状态发生变化时,它会向标准输出发送一些文本,例如当 Ctrl 处于“活动”状态时,无论是否按下物理 Ctrl 键。我希望这个程序能够在不创建可见 X window 并保持打开状态的情况下工作,因为这会妨碍我使用其他应用程序。
是否可以使用 Xkb、XkbCommon、Xlib and/or XCB 库?我尝试按照 in the Xkb spec 的建议使用 XNextEvent
,但是这个函数会永远阻塞。
我对实现的完整尝试是 here,但这是相关部分:
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/XKBlib.h>
/* Various X and Xkb data that are often needed together */
typedef struct ExtensionInfo {
Display* display; /* An X display */
int base_event_code; /* Integer code offset for Xkb events */
int base_err_code; /* Integer code offset for Xkb errors */
int xkb_version_major; /* Dual-purpose version indicator; see XkbOpenDisplay(3) */
int xkb_version_minor; /* Dual-purpose version indicator; see XkbOpenDisplay(3) */
int xkb_reason; /* Error reason if XkbOpenDisplay fails, or success reason */
} ExtensionInfo;
int main(int argc, char *argv[]) {
ExtensionInfo *extension_info;
XkbEvent xkb_event;
extension_info->display = XkbOpenDisplay(
/* NULL here is allowed by XkbOpenDisplay but not mentioned explicitly
* in the XkbOpenDisplay man page - it defaults to $DISPLAY */
NULL,
&(extension_info->base_event_code),
&(extension_info->base_err_code),
&(extension_info->xkb_version_major),
&(extension_info->xkb_version_minor),
&(extension_info->xkb_reason)
);
const unsigned long int xkb_details_mask = (
XkbModifierBaseMask |
XkbModifierStateMask |
XkbModifierLatchMask |
XkbModifierLockMask
);
bool xkb_initialized = XkbSelectEventDetails(
extension_info->display,
XkbUseCoreKbd,
XkbStateNotifyMask,
xkb_details_mask,
xkb_details_mask
);
printf("Waiting...\n");
XNextEvent(extension_info->display, &xkb_event.core);
printf("Done.\n");
}
一般来说,是的,完全有可能调用任何类型的需要 Window 句柄的 X11 请求(例如,用于获取或设置选择)而不会弹出 屏幕上的 window -- 通过创建 InputOnly
window.
但是对于 Xkb*
你甚至不需要它。在发布的代码段中,您的问题是您根本没有调用 XkbSelectEvents
,因此不会向您的 X11 客户端传送任何 Xkb 事件。
下面的小例子确实在状态改变时得到一个事件:
#include <X11/Xlib.h>
#include <X11/XKBlib.h>
#include <err.h>
int main(void){
Display *dpy; int xkb_event;
if(!(dpy = XkbOpenDisplay(0, &xkb_event, 0, 0, 0, 0)))
errx(1, "cannot open display '%s'", XDisplayName(0));
XkbSelectEvents(dpy, XkbUseCoreKbd, XkbStateNotifyMask,
XkbStateNotifyMask);
for(;;){
XkbEvent e; XNextEvent(dpy, &e.core);
if(e.type == xkb_event && e.any.xkb_type == XkbStateNotify)
warnx("xkb state changed!");
}
}
我使用 Xkb sticky
选项,我想编写一个程序,当修改键状态发生变化时,它会向标准输出发送一些文本,例如当 Ctrl 处于“活动”状态时,无论是否按下物理 Ctrl 键。我希望这个程序能够在不创建可见 X window 并保持打开状态的情况下工作,因为这会妨碍我使用其他应用程序。
是否可以使用 Xkb、XkbCommon、Xlib and/or XCB 库?我尝试按照 in the Xkb spec 的建议使用 XNextEvent
,但是这个函数会永远阻塞。
我对实现的完整尝试是 here,但这是相关部分:
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/XKBlib.h>
/* Various X and Xkb data that are often needed together */
typedef struct ExtensionInfo {
Display* display; /* An X display */
int base_event_code; /* Integer code offset for Xkb events */
int base_err_code; /* Integer code offset for Xkb errors */
int xkb_version_major; /* Dual-purpose version indicator; see XkbOpenDisplay(3) */
int xkb_version_minor; /* Dual-purpose version indicator; see XkbOpenDisplay(3) */
int xkb_reason; /* Error reason if XkbOpenDisplay fails, or success reason */
} ExtensionInfo;
int main(int argc, char *argv[]) {
ExtensionInfo *extension_info;
XkbEvent xkb_event;
extension_info->display = XkbOpenDisplay(
/* NULL here is allowed by XkbOpenDisplay but not mentioned explicitly
* in the XkbOpenDisplay man page - it defaults to $DISPLAY */
NULL,
&(extension_info->base_event_code),
&(extension_info->base_err_code),
&(extension_info->xkb_version_major),
&(extension_info->xkb_version_minor),
&(extension_info->xkb_reason)
);
const unsigned long int xkb_details_mask = (
XkbModifierBaseMask |
XkbModifierStateMask |
XkbModifierLatchMask |
XkbModifierLockMask
);
bool xkb_initialized = XkbSelectEventDetails(
extension_info->display,
XkbUseCoreKbd,
XkbStateNotifyMask,
xkb_details_mask,
xkb_details_mask
);
printf("Waiting...\n");
XNextEvent(extension_info->display, &xkb_event.core);
printf("Done.\n");
}
一般来说,是的,完全有可能调用任何类型的需要 Window 句柄的 X11 请求(例如,用于获取或设置选择)而不会弹出 屏幕上的 window -- 通过创建 InputOnly
window.
但是对于 Xkb*
你甚至不需要它。在发布的代码段中,您的问题是您根本没有调用 XkbSelectEvents
,因此不会向您的 X11 客户端传送任何 Xkb 事件。
下面的小例子确实在状态改变时得到一个事件:
#include <X11/Xlib.h>
#include <X11/XKBlib.h>
#include <err.h>
int main(void){
Display *dpy; int xkb_event;
if(!(dpy = XkbOpenDisplay(0, &xkb_event, 0, 0, 0, 0)))
errx(1, "cannot open display '%s'", XDisplayName(0));
XkbSelectEvents(dpy, XkbUseCoreKbd, XkbStateNotifyMask,
XkbStateNotifyMask);
for(;;){
XkbEvent e; XNextEvent(dpy, &e.core);
if(e.type == xkb_event && e.any.xkb_type == XkbStateNotify)
warnx("xkb state changed!");
}
}