我有一些使用XGrabButton捕获鼠标点击的代码。我希望它始终捕获指定按钮上的所有点击,无论其他任何问题。它目前使用以下调用:
XSelectInput(display, window, ButtonPressMask);
XGrabButton(display, Button2, AnyModifier, window, True,
ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None);
XGrabButton(display, Button3, AnyModifier, window, True,
ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None);
XGrabButton(display, Button4, AnyModifier, window, True,
ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None);
但是,按住按钮1(鼠标左键,我的代码未捕获)会导致其他按钮的点击无法捕获。我该如何防止这种情况发生?
编辑以澄清:
按住按钮1时,如何捕捉按钮2-4?
答案 0 :(得分:0)
不确定这是否有效,但您可以强制不要通过以下方式获取代码中的button1:
XUngrabButton(display, Button1, AnyModifier, window);
答案 1 :(得分:0)
希望代码有更多内容,如果它按照您的说法行事:
“但是,按住按钮1(鼠标左键,未被我的代码捕获)会导致其他按钮无法捕获。 “
该行:
XSelectInput(display, window, ButtonPressMask);
将导致捕获所有按钮。其他XGrabButton
调用是(冗余?),因为您没有指定任何与默认参数不同的参数。
然而;如果它实际上就是你说的那样,即使代码Button1
没有被捕获,或者你有一些其他代码,即XSelectInput
未被调用 - 我将把它作为基础开始
每个窗口都有一个事件队列。在该窗口中生成事件时,事件 已发送 到窗口。但是,只有 接收 的窗口,如果已选择该事件或始终选中该事件。 或者作为Xlib例程的副作用。只有当 收到 事件时,才会将其置于队列中。
如果我们使用XSelectInput()
并选择大多数掩码, / usr / include / X11 / Xh EVENT DEFINITIONS ,并使用XNextEvent()
来查看,我们通常会看到像这样的东西:
...
19: Event EnterNotify # Window Entry/Exit Events
20: Event KeymapNotify # X send after every EnterNotify and FocusIn event
21: Event MotionNotify # Keyboard and Pointer Events
22: Event ButtonPress 2 # Button 2 down
23: Event ButtonRelease 2 # Button 2 up
24: Event ButtonPress 1 # Button 1 down
25: Event ButtonPress 2 # Button 1 and 2 down
...
如果 我们从XSelectInput
删除 ButtonPressMask 和 ButtonReleaseMask 并使用XGrabButton()
为1
以外的每个按钮抓取事件并再次运行程序,事件正在映射趋势:
22: Event LeaveNotify # Button 1 pressed causes "blurring" of window.
23: Event EnterNotify # Button 1 released
24: Event KeymapNotify
25: Event ButtonPress 3 # Button 3 down
26: Event ButtonPress 1 # Button 3 + 1 down; 1 registers as Press
# even if not tracked.
27: Event ButtonRelease 3 # Button 3 up
28: Event MotionNotify
29: Event ButtonRelease 1 # Button 1 up
30: Event LeaveNotify # Button 1 pressed, 1+2 pressed, 1+2+3 …
31: Event EnterNotify # Button 1 released, 2 released, …
32: Event KeymapNotify
33: Event ButtonPress 2
34: Event ButtonPress 3
35: Event ButtonPress 1
36: Event ButtonRelease 2
37: Event ButtonRelease 3
我们观察到按下多个按钮事件会继承第一个状态。您还可以使用ltrace
,strace
,xev
等查看此内容。 xev 注册内部未捕获的按钮。如前面提到的;事件已发送到窗口,但只有已注册已收到。除了一些副作用之外,例如可以看到:
按下一个未设置为捕获的按钮会导致 LeaveNotify ,(窗口保留) - 并且阻止并行事件。
这里有很多事情需要考虑。所有这些都取决于代码项目其余部分的逻辑。但是有一些基础知识。最简单的是捕获所有按钮,标记和跟踪; XNextEvent
static const char *event_names[] = {
"", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
"MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
"KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
"CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
"ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
"ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
"SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
"ClientMessage", "MappingNotify"
};
/* ... */
Display *dpy;
XEvent ev;
int k = 0;
/* ... */
for (;;) {
XNextEvent(dpy, &ev);
if ((ev.type == ButtonPress || ev.type == ButtonRelease) &&
ev.xbutton.button == Button1) {
fprintf(stderr,
"%04d: BLOCK! %-18s %d\n",
k++, event_names[ev.type],
ev.xbutton.button);
continue;
}
fprintf(stderr, "%04d: PASS! Work %-18s", k++, event_names[ev.type]);
switch (ev.type) {
case ButtonPress:
case ButtonRelease:
fprintf(stderr, " %d", ev.xbutton.button);
break;
}
putchar('\n');
}
导致类似:
0005: PASS! Work FocusIn
0006: BLOCK! ButtonPress 1
0007: BLOCK! ButtonRelease 1
0008: BLOCK! ButtonPress 1
0009: BLOCK! ButtonRelease 1
0010: BLOCK! ButtonPress 1
0011: PASS! Work ButtonPress 3 # Button 1 is also down
0012: PASS! Work ButtonRelease 3
0013: BLOCK! ButtonRelease 1
0014: PASS! Work ButtonPress 3
0015: PASS! Work ButtonRelease 3
0016: BLOCK! ButtonPress 1
0017: PASS! Work ButtonPress 3
0018: PASS! Work ButtonRelease 3
0019: BLOCK! ButtonRelease 1
0020: PASS! Work ButtonPress 2
0021: PASS! Work ButtonPress 3
0022: BLOCK! ButtonPress 1
0023: BLOCK! ButtonRelease 1
0024: PASS! Work ButtonRelease 2
0025: PASS! Work ButtonRelease 3
0026: BLOCK! ButtonPress 1
0027: PASS! Work ButtonPress 3
0028: PASS! Work ButtonRelease 3
0029: PASS! Work ButtonPress 2
0030: PASS! Work ButtonRelease 2
0031: BLOCK! ButtonRelease 1
0032: PASS! Work FocusOut
另一种方法是使用XIfEvent,XCheckIfEvent()
等。这一切都取决于结构。要记住/检查的一件事是一些功能;即如果 匹配,XIfEvent
从队列中删除该事件!因此,如果您实现predicate
函数,如果事件是 Button1Press ,则返回False
- 该事件将保留在队列中。