我正在使用 Go 和 Xlib(使用 cgo)修补 X11,并且我正在尝试对基本窗口管理功能进行编程,但我在输入管理(本例中为键盘)方面遇到问题.
到目前为止,我已经创建了一个基本的 reparenting 窗口管理器 ,其中客户端窗口(即由该程序管理的窗口)被包装在由该程序创建的容器窗口中。容器窗口是根窗口的直接子窗口,客户端窗口是其容器窗口的直接子窗口。
我正在尝试抓住整个键盘并检查按键事件是否定向到窗口管理器以处理某些事情。如果这个关键事件与窗口管理器无关,我想将其传递给客户端窗口。我知道对于这个问题,可以选择 仅选择特定的键或修饰符 (使用
XGrabKey
)(我能够做到),但在这种情况下我希望能够抓住整个键盘。
到目前为止,我的以下代码不起作用,并且密钥未传递到客户端窗口。
...
C.XGrabKeyboard(
display,
rootWindow,
0,
C.GrabModeAsync,
C.GrabModeAsync,
C.CurrentTime,
)
...
for {
var event C.XEvent
C.XNextEvent(display, &event)
eventType := (*C.int)(unsafe.Pointer(&event[0]))
switch *eventType {
...
case C.KeyPress:
eventPayload := (*C.XKeyEvent)(unsafe.Pointer(&event[0]))
// Value of eventPayload.root here equals rootWindow.
// Value of eventPayload.window here equals rootWindow.
// Value of eventPayload.subwindow here equals a ContainerWindow.
if SOME_CONDITIONS_ARE_MET {
// Key event is directed towards the window manager. Process this key event.
...
continue
}
// Window manager has nothing to do with this key event. Pass it along.
C.XAllowEvents(display, C.ReplayKeyboard, C.CurrentTime)
...
}
}
值得一提的是,在本例中我使用了
C.XSynchronize(display, 1)
,因此不再需要调用 XSync
。在XFlush
之后再调用XAllowEvents
也没有解决问题。
顺便说一句,我最初在
这个堆栈溢出问题和这个网站中看到了
XAllowEvents
解决方案。
根据本手册对于
event_mode
的XAllowEvents()
参数:
ReplayKeyboard ...但不是来自 XGrabKeyboard()),键盘抓取被释放并且该事件被完全重新处理...
它表示 ,但不是来自
XGrabKeyboard()
,这意味着如果您使用 ReplayKeyboard
,XGrabKeyboard()
没有效果。
但是,您可以将 XGrabKey() 与
AnyKeys
和 AnyModifiers
一起使用,当然还有 XAllowEvents()
来实现 same-ish 行为:
C.XGrabKey(
display,
C.AnyKey,
C.AnyModifier,
rootWindow,
0,
C.GrabModeAsync,
C.GrabModeSync, // Take note of Sync
)