我开发了一个程序,允许我控制客户端和 X11 服务器之间的 X11 通信。我想用它来控制提供给客户端的鼠标和键盘输入。另外,我想运行客户端程序,同时能够与其他窗口交互。
不幸的是,每当我向程序发送“假”鼠标单击或“假”键盘按钮单击时,窗口都会获得输入焦点。这不是我想要的,因为它会从当时拥有的任何窗口中窃取输入焦点。
我已经尝试了多种方法,例如通过不将
SetInputFocus
请求转发到 X11 服务器并伪造 GetInputFocus
响应来阻止客户端请求输入焦点,等等,但我的尝试总是导致客户端窗口冻结。
请向我推荐一种解决此问题的方法。
您看过 XTEST 扩展协议吗?
https://www.x.org/releases/X11R7.7/doc/xextproto/xtest.html
X11 的
XTEST
扩展是在 X11 上发送“假”输入的标准方法,并且可能比自己制作和发送原始事件更好地处理一些边缘情况。
一个简单的解决方案,尽管有点 hacky,是在使用
XTEST
发送输入后,立即使用 XSetInputFocus()
将焦点恢复到原始窗口。这可能会导致非常短暂的焦点切换,但如果做得足够快,可能几乎不会被注意到。
另一种值得尝试的方法是在发送任何输入之前尝试“锁定焦点”在窗口上,这样您可以使用窗口管理器功能和 X11 功能的组合强制焦点保留在当前活动的窗口上。模拟输入后,如果您愿意,您可以释放此焦点锁定。
从这个意义上说,这可能是解决这个问题的更好方法,使用“WM_HINTS”之类的东西来防止目标窗口获得焦点。
例如使用
WM_HINTS
。
#include <X11/Xlib.h>
#include <X11/Xutil.h>
int main() {
Display *display = XOpenDisplay(NULL);
if (!display) {
return 1; // fail if couldn't open the display
}
// Where 0xSOME_WINDOW_ID is ID of the target window you want to prevent gaining focus
Window targetWindow = 0xSOME_WINDOW_ID;
XWMHints *hints = XAllocWMHints();
hints->input = False; // hint the window manager not to give focus to this window
hints->flags = InputHint;
XSetWMHints(display, targetWindow, hints);
XFree(hints);
XCloseDisplay(display);
return 0;
}
但是
WM_HINTS
只是 - 提示...没有办法知道给定的 WM 是否会尊重输入提示而不尝试它。