#include #include #include #include #include #include static int handler(Display *dpy, XErrorEvent *err) { (void) dpy, (void) err; puts("in error handler"); return 0; } static void __glXSendError(Display * dpy, int errorCode, int resourceID, int minorCode) { xError error; XLockDisplay(dpy); error.type = X_Error; error.errorCode = errorCode; error.sequenceNumber = dpy->request; error.resourceID = resourceID; error.minorCode = minorCode; error.majorCode = minorCode; _XError(dpy, &error); XUnlockDisplay(dpy); } static void sync_xcb(xcb_connection_t *c) { xcb_get_input_focus_reply(c, xcb_get_input_focus(c), NULL); } int main() { Window own; Display *dpy = XOpenDisplay(NULL); xcb_connection_t *c = XGetXCBConnection(dpy); XSetErrorHandler(handler); /* Sequence 7: CreateWindow */ own = xcb_generate_id(c); xcb_create_window(c, 24, own, RootWindow(dpy, 0), 0, 0, 10, 10, 0, XCB_COPY_FROM_PARENT, XCB_COPY_FROM_PARENT, XCB_CW_EVENT_MASK, (uint32_t[]) { XCB_EVENT_MASK_KEY_PRESS }); XKeyEvent event; event.type=KeyPress; event.keycode=42; event.display=dpy; event.root=own; /* Sequence 8: Send us an event */ XSendEvent(dpy,own,True,KeyPressMask,(XEvent *)&event); /* To avoid a race with the X11 server: Make sure the event we * just sent was already received by xcb (but not yet Xlib) * Sequence 9 */ sync_xcb(c); /* Send us another event */ /* Sequence 10: */ XSendEvent(dpy,own,True,KeyPressMask,(XEvent *)&event); assert(dpy->request == 10 && XNextRequest(dpy) == 11); assert(dpy->last_request_read == 8); /* Increase dpy->request some more */ /* Sequence 11: */ XNoOp(dpy); assert(dpy->request == 11 && XNextRequest(dpy) == 12); /* To avoid a race with the X11 server: Make sure the event we * just sent was already received by xcb (but not yet Xlib) * Sequence 12: */ sync_xcb(c); assert(dpy->request == 11); assert(dpy->last_request_read == 8); /* Set last_request_read into the future (incorrectly) */ __glXSendError(dpy, 42, 42, 42); assert(dpy->request == 11); assert(dpy->last_request_read == 11); /* XLib will now read the event we generated above (sequence number 10). * Thanks to XNoOp(), dpy->request was already 11. The call to _XError() * thus caused request_read to be 11. Since 10 is less than 11, widen() * assumes an overflow and adds 1 << 32 to the sequence. * * Something else that I just got right by trial and error makes sure * that dpy->xcb->pending_requests is NULL. */ XEvent xevent; XNextEvent(dpy, &xevent); XCloseDisplay(dpy); return 0; }