Sending an event using XSendEvent when a pointer is grabbed

797 views Asked by At

I develop a plugin for compiz window manager. I want to draw a transformed window texture and send an event to that window. When a transformed window is renderer I grab pointer to take control off all xevents, the main part of compiz function which grabs pointer looks like this:

 status = XGrabPointer (privateScreen.dpy, privateScreen.eventManager.getGrabWindow(), true,
                        POINTER_GRAB_MASK,
                        GrabModeAsync, GrabModeAsync,
                        privateScreen.rootWindow(), cursor,
                        CurrentTime);

When a pointer is grabbed I recalculate button press coordinates and I use XSendEvent to send events to the destination window. It works fine for google chrome window or for a simple xwindow application like this: link Unfortunately it doesn't work correctly for a window which performs OpenGL rendering - I have tested SDL and GLFW. Such window receives click events but with different parameters (xbutton.x_root, xbutton.y_root, xbutton.x, xbutton.y) than I specified in XSendEvent. Each time when I send an event those parameters contains the same values which seem to be the mouse position before xgrabpointer was called. When a pointer is not grabbed events (from XSendEvent) are received correctly. There must be some specific relation between xsendevent, xgrabpointer and a window which performs OpenGL rendering. Moreover clients (windows) implementation may differ because my code doesn't work only for that specific windows or maybe I do something wrong ?

Edit1

Let's consider following example: I have a fullscreen window, then I can use a plugin to draw transformed window texture (for example scale transformation (0.5, 0.5, 1.0)), but X11 still sees a fullscreen window, so when I click on the region outside a transformed texture event go to the window. When I grab pointer in the plugin I'm the only receiver off all events, then I can recalculate cooridnates based on my window transfomation and send them to the window.

Edit2 When I use Freeglut all events are sent correctly to the destination window when pointer is grabbed. There have to be some differences between library implementations.

2

There are 2 answers

1
datenwolf On

OpenGL is not concerned with input events, it just draws things, without even knowing what X11 or pointer events are.

This must be something both SDL and GLFW do in their window setup.

However I wonder why you are grabbing the pointer at all? The X Composite extension, which is the foundation on which Compiz and other compositing WMs are built already has a dedicated API for pointer input transformation, see http://www.x.org/archive/X11R7.5/doc/compositeproto/compositeproto.txt RedirectCoordinate and TransformCoordinate. You should use those functions instead of messing with grabbing the pointer. Grabbing the pointer is a really, really bad idea.

Okay, it seems that the copy of the X composite extension I linked (and I have on my computer) is an earlier draft still with the RedirectCoordinate in it. There's a newer version (which unfortunately carries the same date in its head – WTF?) where coordinate redirection has been removed.

0
Irbis On

SDL updates a mouse position when handling MouseMotion event. It doesn't use coordinates which are stored in ButtonPress event. When a window manager grabs a pointer and sends ButtonPress event to the SDL window, a mouse position inside receiver is not updated. Here is example solution (following code should be added to the section after ButtonPress label in SDL_x11events.c:

if(xevent.xany.send_event)
{
     SDL_Mouse *mouse = SDL_GetMouse();
     mouse->x = xevent.xbutton.x;
     mouse->y = xevent.xbutton.y;
}