xcb: LeaveNotify получен сразу после EnterNotify

В целях обучения я пишу оконный менеджер на Rust, используя библиотеку xcb. Мой код и несколько тестовых окон (экземпляры xterm) выполняются внутри сеанса Xephyr. Я установил маску события в корневом окне как

xproto::EVENT_MASK_SUBSTRUCTURE_REDIRECT
| xproto::EVENT_MASK_SUBSTRUCTURE_NOTIFY
| xproto::EVENT_MASK_POINTER_MOTION
| xproto::EVENT_MASK_LEAVE_WINDOW
| xproto::EVENT_MASK_ENTER_WINDOW
| xproto::EVENT_MASK_BUTTON_PRESS
| xproto::EVENT_MASK_PROPERTY_CHANGE
| xproto::EVENT_MASK_FOCUS_CHANGE

и все дочерние окна имеют маску события

xproto::EVENT_MASK_ENTER_WINDOW
| xproto::EVENT_MASK_LEAVE_WINDOW
| xproto::EVENT_MASK_BUTTON_PRESS
| xproto::EVENT_MASK_PROPERTY_CHANGE
| xproto::EVENT_MASK_POINTER_MOTION
| xproto::EVENT_MASK_FOCUS_CHANGE
| xproto::EVENT_MASK_STRUCTURE_NOTIFY
| xproto::EVENT_MASK_EXPOSURE

Когда я перемещаю мышь над окном, не являющимся корневым, я использую событие EnterNotify, чтобы захватить кнопки мыши в этом окне, чтобы щелкнуть, чтобы сфокусироваться, и отменить захват LeaveNotify. Последовательность событий такова:

  • Мышь в корневом окне
  • Наведите указатель мыши на окно без полномочий root
  • Получить EnterNotify для окна без полномочий root
  • Кнопки захвата в окне без полномочий root
  • Немедленно получите LeaveNotify, пока указатель мыши все еще находится над окном без полномочий root
  • Отключить кнопки из-за LeaveNotify
  • Попытка щелкнуть окно без полномочий root
  • Получите второй LeaveNotify для некорневого окна
  • Получите EnterNotify для корневого окна и захватите кнопки мыши в корневом окне.
  • ButtonPress отправляется для корневого окна, несмотря на то, что курсор находится над некорневым окном

Я искренне не уверен, в чем может быть причина этого; использование Google и т.п. ничего полезного не дало.


Для тех, кто может наткнуться на это позже, частичное решение:

  • Слушайте только события входа в окно, чтобы захватить кнопки в окне
  • Корень маски должен быть только SUBSTRUCTURE_REDIRECT | SUBSTRUCTURE_NOTIFY | BUTTON_PRESS
  • Не маскируйте LEAVE_WINDOW на окна без полномочий root и не обрабатывайте эти события.

Я не хочу добавлять это как ответ, потому что:

  1. Я не уверен, что это правильный способ сделать это.
  2. Я не проверял это тщательно.
  3. Это не отвечает на мой основной вопрос о том, почему события воспринимаются таким образом?

person user7876637    schedule 27.08.2020    source источник


Ответы (1)


Посмотрите справочное руководство по протоколу. Он описывает (среди прочего) точный алгоритм генерации событий входа и выхода: https://www.x.org/releases/X11R7.6/doc/xproto/x11protocol.html#events:pointer_window

В вашем конкретном случае я бы ожидал, что событие LeaveNotify будет иметь mode: Grab, что означает, что окно больше не имеет обычного фокуса указателя, потому что что-то (ваша программа) захватило ввод.

Если это не ответ, я могу порекомендовать запустить ваш WM под xtrace / x11trace (доступен в Дистрибутивы на основе Debian как пакет xtrace). Эта программа печатает весь проходящий трафик X11. Это может помочь выяснить, что происходит.

person Uli Schlachter    schedule 28.08.2020
comment
Кажется, это оно! Большое спасибо! - person user7876637; 28.08.2020