X11: Как ДЕЙСТВИТЕЛЬНО захватить указатель мыши?

Я реализовал виджет горизонтального разделителя в Xlib. Я пытаюсь схватить мышь, когда пользователь щелкает и перетаскивает полосу разделения (чтобы пользователь мог динамически перемещать разделение и, таким образом, изменять размер окон по обе стороны от полосы разделения).

Я использовал XGrabPointer() после получения щелчка левой кнопкой мыши в надежде, что все будущие движения мыши (перетаскивание) будут перенаправляться в окно разделителя до тех пор, пока левая кнопка не будет отпущена.

К сожалению, похоже, это так не работает. Если пользователь перетаскивает слишком быстро и указатель мыши входит в одно из окон по обе стороны от разделения, сообщения MotionEvent перенаправляются в это (дочернее) окно, а не в окно-разделитель.

Что я сделал не так? Мой XGrabPointer() вызов выглядит следующим образом:

::XGrabPointer(mDisplay, window, True,
               ButtonPressMask |
                 ButtonReleaseMask |
                 PointerMotionMask |
                 FocusChangeMask |
                 EnterWindowMask |
                  LeaveWindowMask,
               GrabModeAsync,
               GrabModeAsync,
               RootWindow(mDisplay, DefaultScreen(mDisplay)),
               None,
               CurrentTime);

person Drew Hall    schedule 08.05.2010    source источник


Ответы (1)


Мне почти неловко это признавать, но ответ оказался таким же простым, как изменение третьего параметра (owner_events) с True на False.

Из учебника/справочника Xlib на tronche.com:

Если owner_events имеет значение False, сообщаются обо всех сгенерированных событиях указателя относительно захвата_окна и сообщаются только в том случае, если они выбраны с помощью event_mask. Если owner_events имеет значение True и если о сгенерированном событии указателя обычно сообщается этому клиенту, о нем сообщается как обычно. В противном случае о событии сообщается относительно окна захвата и сообщается только в том случае, если оно выбрано с помощью event_mask.

Я до сих пор не уверен, что полностью понимаю поведение случая True, но моя интерпретация заключается в том, что если True, другие X-программы (то есть окна, созданные другими процессами) не могут получать XEvents, но те, которые попали бы в любое окно созданные вашим процессом, доставляются как обычно. В случае false сообщаются все события, относящиеся к конкретному выбранному вами окну. Это было поведение, которое я искал.

person Drew Hall    schedule 08.05.2010
comment
Если контекстное меню открыто (обычно после щелчка правой кнопкой мыши), XGrabPointer() возвращает уже захваченное, и я понятия не имею, как восстановить возможность захвата мыши. Можете ли вы дать мне какой-нибудь совет? - person ezain; 21.06.2019