Отправка события с помощью XSendEvent при получении указателя
Я разрабатываю плагин для оконного менеджера compiz. Я хочу нарисовать преобразованную текстуру окна и отправить событие в это окно. Когда трансформированное окно является средством визуализации, я беру указатель, чтобы взять контроль над всеми xevents, основная часть функции compiz, которая захватывает указатель, выглядит так:
status = XGrabPointer (privateScreen.dpy, privateScreen.eventManager.getGrabWindow(), true,
POINTER_GRAB_MASK,
GrabModeAsync, GrabModeAsync,
privateScreen.rootWindow(), cursor,
CurrentTime);
Когда указатель захвачен, я пересчитываю координаты нажатия кнопки и использую XSendEvent для отправки событий в окно назначения. Он отлично работает для окна Google Chrome или для простого приложения xwindow, например: ссылка К сожалению, он не работает правильно для окна, которое выполняет рендеринг OpenGL - я протестировал SDL и GLFW. Такое окно получает события щелчка, но с другими параметрами (xbutton.x_root, xbutton.y_root, xbutton.x, xbutton.y), чем я указал в XSendEvent. Каждый раз, когда я отправляю событие, эти параметры содержат одинаковые значения, которые кажутся положением мыши до вызова xgrabpointer. Когда указатель не захвачен, события (из XSendEvent) принимаются правильно. Должно быть определенное отношение между xsendevent, xgrabpointer и окном, которое выполняет рендеринг OpenGL. Более того, реализация клиентов (окон) может отличаться, потому что мой код не работает только для этих конкретных окон или, может, я что-то не так делаю?
Edit1
Давайте рассмотрим следующий пример: у меня есть полноэкранное окно, затем я могу использовать плагин для рисования текстуры трансформированного окна (например, преобразование масштаба (0,5, 0,5, 1,0)), но X11 по-прежнему видит полноэкранное окно, поэтому, когда я нажимаю на область за пределами трансформированного события текстуры перейти к окну. Когда я получаю указатель в плагине, я являюсь единственным получателем всех событий, тогда я могу пересчитать координаты на основе трансформации моего окна и отправить их в окно.
Edit2 Когда я использую Freeglut, все события правильно отправляются в окно назначения, когда указатель захвачен. Должны быть некоторые различия между реализациями библиотеки.
2 ответа
OpenGL не связан с событиями ввода, он просто рисует вещи, даже не зная, что такое события X11 или указатели.
Это должно быть то, что и SDL, и GLFW делают в своих настройках окна.
Однако мне интересно, почему вы вообще берете указатель? Расширение X Composite, являющееся основой для построения Compiz и других композитных WM, уже имеет специальный API для преобразования ввода указателя, см. http://www.x.org/archive/X11R7.5/doc/compositeproto/compositeproto.txt RedirectCoordinate
а также TransformCoordinate
, Вы должны использовать эти функции вместо того, чтобы возиться с захватом указателя. Захват указателя - действительно очень плохая идея.
Хорошо, кажется, что копия составного расширения X, которое я связал (и у меня есть на моем компьютере), является более ранним проектом, в котором все еще есть RedirectCoordinate. Есть более новая версия (которая, к сожалению, содержит ту же дату в заголовке - WTF?), Где перенаправление координат было удалено.
SDL обновляет положение мыши при обработке события MouseMotion. Он не использует координаты, которые хранятся в событии ButtonPress. Когда оконный менеджер захватывает указатель и отправляет событие ButtonPress в окно SDL, положение мыши внутри приемника не обновляется. Вот пример решения (следующий код должен быть добавлен в раздел после метки ButtonPress в SDL_x11events.c:
if(xevent.xany.send_event)
{
SDL_Mouse *mouse = SDL_GetMouse();
mouse->x = xevent.xbutton.x;
mouse->y = xevent.xbutton.y;
}