Надеюсь, в коде есть что-то еще, если он действует так, как вы говорите:
" Однако нажатие и удержание кнопки 1 (левая кнопка мыши, , которая не фиксируется моим кодом ) приводит к тому, что нажатия на другие кнопки не фиксируются. "
Строка:
XSelectInput(display, window, ButtonPressMask);
приведет к захвату всех кнопок. Дополнительные вызовы XGrabButton
( избыточны? ), так как вы не указываете никаких параметров, которые отличаются от параметров по умолчанию.
Тем не менее, если на самом деле это то, как вы говорите, что даже с этим кодом Button1
не захвачен, или у вас есть какой-то другой код, где, например, XSelectInput
не вызывается - для начала я приму это как основу.
Распределение событий
В каждом окне есть очередь событий. Событие отправляется окну, когда оно генерируется в этом окне. Но только окно получает событие, если оно выбрало его или оно всегда выбрано. Или как побочный эффект для процедуры Xlib . Только когда получает событие, оно помещается в очередь.
Если мы используем XSelectInput()
и выбираем большинство масок, / usr / include / X11 / Xh ОПРЕДЕЛЕНИЯ СОБЫТИЙ и используем 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
...
Если , мы удаляем ButtonPressMask и ButtonReleaseMask из XSelectInput
и используем 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
, которая возвращает False
, если событие то есть Button1Press - это событие останется в очереди.