Hello everybody (esp. Peter ;-),

I tried to get to the bottom of my lost XI_Enter events today. As I
mentioned, I'm not getting those events which should occur when a cursor
is inside the window when it is first created. I've experimented a bit
with the relevant part from xinput, and I've stripped it down to a
minimal example which shows the problem (source code attached).

It seems to be some kind of race condition: if there is any significant
delay between creation of the window and the first call to XNextEvent,
then the XI_Event is very unlikely to arrive, as opposed to the standard
EnterNotify. After removing the sleep(1) in the code, it works almost
always. The standard events are never lost, neither are any subsequent
XI_Enter or XI_Leave events. It's only the very first one, and only if
the cursor is already inside the window upon creation.

My xserver, inputproto, libXi and xinput have been rebuilt from FDO git
master yesterday. I'd really appreciate it if some of you with more
inside knowledge could have a look at this and tell me if I am
forgetting something..

Yours, Florian
-- 
0666 - Filemode of the Beast
#include <X11/Xlib.h>
#include <X11/extensions/XInput2.h>

#include <string.h>

#define BitIsOn(ptr, bit) (((unsigned char *) (ptr))[(bit)>>3] & (1 << ((bit) & 7)))
#define SetBit(ptr, bit)  (((unsigned char *) (ptr))[(bit)>>3] |= (1 << ((bit) & 7)))

static Window create_win(Display *dpy)
{
	Window win = XCreateWindow(dpy, DefaultRootWindow(dpy), 0, 0, 200,
					200, 0, CopyFromParent, InputOutput, CopyFromParent, 0,0 );
	//Window win = XCreateSimpleWindow(dpy, win, 0, 0, 400, 400, 0, 0, WhitePixel(dpy, 0));


	XSelectInput(dpy, win, StructureNotifyMask | SubstructureNotifyMask |
		ExposureMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask |
		KeyReleaseMask | VisibilityChangeMask | EnterWindowMask |
		LeaveWindowMask | PointerMotionMask | ButtonMotionMask );
	XMapWindow(dpy, win);
	XFlush(dpy);
	return win;
}


int main( int argc, char	*argv[] ) {

	Display	*display = XOpenDisplay(NULL);
	
	XIEventMask mask;
	Window win;

	win = create_win(display);

	XSync(display,False);
	/* Select for motion events */
	mask.deviceid = XIAllMasterDevices;
	mask.mask_len = 2;
	mask.mask = calloc(mask.mask_len, sizeof(char));
	SetBit(mask.mask, XI_ButtonPress);
	SetBit(mask.mask, XI_ButtonRelease);
	SetBit(mask.mask, XI_Motion);
	SetBit(mask.mask, XI_Enter);
	SetBit(mask.mask, XI_Leave);
	XISelectEvents(display, win, &mask, 1);

	free(mask.mask);
	XSync(display,False);

	// removing this sleep increases the probability of
	// actually receiving the first XI_Enter
	sleep(1);

	while(1) {

		XEvent xev;
		XNextEvent(display, &xev);
		//fghPrintEvent(&xev); printf("\n");
		XIEvent ev = *((XIEvent*)&xev);

		if (ev.type == EnterNotify)
			printf("got standard EnterNotify\n");

		if (ev.type == LeaveNotify)
			printf("got standard LeaveNotify\n");

		if (ev.type == GenericEvent) {

				XIDeviceEvent *event = (XIDeviceEvent*)&ev;
				switch (event->evtype) {
						case XI_Enter:
								printf("XI_Enter\n");
								break;
						case XI_Leave:
								printf("XI_Leave\n");
								break;
						default:
								break;
				}
		}

		XIFreeEventData(&ev);

	}

	XDestroyWindow(display, win);

	return 0;
}

// build with gcc -lX11 -lXi -Wall -o xi2test xi2test.c
_______________________________________________
xorg mailing list
xorg@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/xorg

Reply via email to