diff --git a/hw/xnest/Args.c b/hw/xnest/Args.c index cbf0f7950..a2285acb3 100644 --- a/hw/xnest/Args.c +++ b/hw/xnest/Args.c @@ -34,7 +34,6 @@ is" without express or implied warranty. #include "Args.h" char *xnestDisplayName = NULL; -Bool xnestSynchronize = FALSE; Bool xnestFullGeneration = FALSE; int xnestDefaultClass; Bool xnestUserDefaultClass = FALSE; @@ -60,10 +59,6 @@ ddxProcessArgument(int argc, char *argv[], int i) } return 0; } - if (!strcmp(argv[i], "-sync")) { - xnestSynchronize = TRUE; - return 1; - } if (!strcmp(argv[i], "-full")) { xnestFullGeneration = TRUE; return 1; @@ -177,7 +172,6 @@ void ddxUseMsg(void) { ErrorF("-display string display name of the real server\n"); - ErrorF("-sync sinchronize with the real server\n"); ErrorF("-full utilize full regeneration\n"); ErrorF("-class string default visual class\n"); ErrorF("-depth int default depth\n"); diff --git a/hw/xnest/Args.h b/hw/xnest/Args.h index fae8fbf2d..7ee70c56b 100644 --- a/hw/xnest/Args.h +++ b/hw/xnest/Args.h @@ -19,7 +19,6 @@ is" without express or implied warranty. #include extern char *xnestDisplayName; -extern Bool xnestSynchronize; extern Bool xnestFullGeneration; extern int xnestDefaultClass; extern Bool xnestUserDefaultClass; diff --git a/hw/xnest/Display.c b/hw/xnest/Display.c index 71be6df38..e6184ad8b 100644 --- a/hw/xnest/Display.c +++ b/hw/xnest/Display.c @@ -74,9 +74,6 @@ xnestOpenDisplay(int argc, char *argv[]) FatalError("Unable to open display \"%s\".\n", XDisplayName(xnestDisplayName)); - if (xnestSynchronize) - XSynchronize(xnestDisplay, TRUE); - xnest_upstream_setup(); if (xnestParentWindow != (Window) 0) diff --git a/hw/xnest/Events.c b/hw/xnest/Events.c index 337f62a55..5b273bd7c 100644 --- a/hw/xnest/Events.c +++ b/hw/xnest/Events.c @@ -32,6 +32,7 @@ is" without express or implied warranty. #include "mi.h" #include "Xnest.h" +#include "xnest-xcb.h" #include "Args.h" #include "Color.h" @@ -65,42 +66,6 @@ SetTimeSinceLastInputEvent(void) lastEventTime = GetTimeInMillis(); } -static Bool -xnestExposurePredicate(Display * dpy, XEvent * event, char *args) -{ - return event->type == Expose || event->type == ProcessedExpose; -} - -static Bool -xnestNotExposurePredicate(Display * dpy, XEvent * event, char *args) -{ - return !xnestExposurePredicate(dpy, event, args); -} - -void -xnestCollectExposures(void) -{ - XEvent X; - WindowPtr pWin; - RegionRec Rgn; - BoxRec Box; - - while (XCheckIfEvent(xnestDisplay, &X, xnestExposurePredicate, NULL)) { - pWin = xnestWindowPtr(X.xexpose.window); - - if (pWin && X.xexpose.width && X.xexpose.height) { - Box.x1 = pWin->drawable.x + wBorderWidth(pWin) + X.xexpose.x; - Box.y1 = pWin->drawable.y + wBorderWidth(pWin) + X.xexpose.y; - Box.x2 = Box.x1 + X.xexpose.width; - Box.y2 = Box.y1 + X.xexpose.height; - - RegionInit(&Rgn, &Box, 1); - - miSendExposures(pWin, &Rgn, Box.x1, Box.y1); - } - } -} - void xnestQueueKeyEvent(int type, unsigned int keycode) { @@ -108,52 +73,62 @@ xnestQueueKeyEvent(int type, unsigned int keycode) QueueKeyboardEvents(xnestKeyboardDevice, type, keycode); } +#define EVTYPE(tname) tname *ev = (tname*)event + static void -xnest_handle_event(XEvent X) +xnest_handle_event(xcb_generic_event_t *event) { - switch (X.type) { + if (!event) + return; + + switch (event->response_type & ~0x80) { case KeyPress: { - xnestUpdateModifierState(X.xkey.state); - xnestQueueKeyEvent(KeyPress, X.xkey.keycode); + EVTYPE(xcb_key_press_event_t); + xnestUpdateModifierState(ev->state); + xnestQueueKeyEvent(KeyPress, ev->detail); break; } case KeyRelease: { - xnestUpdateModifierState(X.xkey.state); - xnestQueueKeyEvent(KeyRelease, X.xkey.keycode); + EVTYPE(xcb_key_release_event_t); + xnestUpdateModifierState(ev->state); + xnestQueueKeyEvent(KeyRelease, ev->detail); break; } case ButtonPress: { ValuatorMask mask; + EVTYPE(xcb_button_press_event_t); valuator_mask_set_range(&mask, 0, 0, NULL); - xnestUpdateModifierState(X.xkey.state); + xnestUpdateModifierState(ev->state); lastEventTime = GetTimeInMillis(); QueuePointerEvents(xnestPointerDevice, ButtonPress, - X.xbutton.button, POINTER_RELATIVE, &mask); + ev->detail, POINTER_RELATIVE, &mask); break; } case ButtonRelease: { ValuatorMask mask; + EVTYPE(xcb_button_release_event_t); valuator_mask_set_range(&mask, 0, 0, NULL); - xnestUpdateModifierState(X.xkey.state); + xnestUpdateModifierState(ev->state); lastEventTime = GetTimeInMillis(); QueuePointerEvents(xnestPointerDevice, ButtonRelease, - X.xbutton.button, POINTER_RELATIVE, &mask); + ev->detail, POINTER_RELATIVE, &mask); break; } case MotionNotify: { + EVTYPE(xcb_motion_notify_event_t); ValuatorMask mask; int valuators[2]; - valuators[0] = X.xmotion.x; - valuators[1] = X.xmotion.y; + valuators[0] = ev->event_x; + valuators[1] = ev->event_y; valuator_mask_set_range(&mask, 0, 2, valuators); lastEventTime = GetTimeInMillis(); QueuePointerEvents(xnestPointerDevice, MotionNotify, @@ -163,8 +138,9 @@ xnest_handle_event(XEvent X) case FocusIn: { - if (X.xfocus.detail != NotifyInferior) { - ScreenPtr pScreen = xnestScreen(X.xfocus.window); + EVTYPE(xcb_focus_in_event_t); + if (ev->detail != NotifyInferior) { + ScreenPtr pScreen = xnestScreen(ev->event); if (pScreen) xnestDirectInstallColormaps(pScreen); } @@ -173,8 +149,9 @@ xnest_handle_event(XEvent X) case FocusOut: { - if (X.xfocus.detail != NotifyInferior) { - ScreenPtr pScreen = xnestScreen(X.xfocus.window); + EVTYPE(xcb_focus_out_event_t); + if (ev->detail != NotifyInferior) { + ScreenPtr pScreen = xnestScreen(ev->event); if (pScreen) xnestDirectUninstallColormaps(pScreen); } @@ -186,15 +163,16 @@ xnest_handle_event(XEvent X) case EnterNotify: { - if (X.xcrossing.detail != NotifyInferior) { - ScreenPtr pScreen = xnestScreen(X.xcrossing.window); + EVTYPE(xcb_enter_notify_event_t); + if (ev->detail != NotifyInferior) { + ScreenPtr pScreen = xnestScreen(ev->event); if (pScreen) { ValuatorMask mask; int valuators[2]; - NewCurrentScreen(inputInfo.pointer, pScreen, X.xcrossing.x, - X.xcrossing.y); - valuators[0] = X.xcrossing.x; - valuators[1] = X.xcrossing.y; + NewCurrentScreen(inputInfo.pointer, pScreen, + ev->event_x, ev->event_y); + valuators[0] = ev->event_x; + valuators[1] = ev->event_y; valuator_mask_set_range(&mask, 0, 2, valuators); lastEventTime = GetTimeInMillis(); QueuePointerEvents(xnestPointerDevice, MotionNotify, @@ -207,8 +185,9 @@ xnest_handle_event(XEvent X) case LeaveNotify: { - if (X.xcrossing.detail != NotifyInferior) { - ScreenPtr pScreen = xnestScreen(X.xcrossing.window); + EVTYPE(xcb_leave_notify_event_t); + if (ev->detail != NotifyInferior) { + ScreenPtr pScreen = xnestScreen(ev->event); if (pScreen) { xnestDirectUninstallColormaps(pScreen); } @@ -218,8 +197,9 @@ xnest_handle_event(XEvent X) case DestroyNotify: { - if (xnestParentWindow != (Window) 0 && - X.xdestroywindow.window == xnestParentWindow) + xcb_destroy_notify_event_t *ev = (xcb_destroy_notify_event_t*)event; + if (xnestParentWindow && + ev->window == xnestParentWindow) exit(0); break; } @@ -230,11 +210,35 @@ xnest_handle_event(XEvent X) case MapNotify: case ReparentNotify: case UnmapNotify: - case NoExpose: break; + case Expose: + { + EVTYPE(xcb_expose_event_t); + WindowPtr pWin = xnestWindowPtr(ev->window); + if (pWin && ev->width && ev->height) { + RegionRec Rgn; + BoxRec Box = { + .x1 = pWin->drawable.x + wBorderWidth(pWin) + ev->x, + .y1 = pWin->drawable.y + wBorderWidth(pWin) + ev->y, + .x2 = Box.x1 + ev->width, + .y2 = Box.y1 + ev->height, + }; + RegionInit(&Rgn, &Box, 1); + miSendExposures(pWin, &Rgn, Box.x1, Box.y1); + } + } + break; + + case NoExpose: + ErrorF("xnest: received stray NoExpose\n"); + break; + case GraphicsExpose: + ErrorF("xnest: received stray GraphicsExpose\n"); + break; + default: - ErrorF("xnest warning: unhandled event: %d\n", X.type); + ErrorF("xnest warning: unhandled event: %d\n", event->response_type); break; } } @@ -242,9 +246,29 @@ xnest_handle_event(XEvent X) void xnestCollectEvents(void) { - XEvent X; - - while (XCheckIfEvent(xnestDisplay, &X, xnestNotExposurePredicate, NULL)) { - xnest_handle_event(X); + /* process queued events */ + struct xnest_event_queue *tmp = NULL, *walk = NULL; + xorg_list_for_each_entry_safe(walk, tmp, &xnestUpstreamInfo.eventQueue.entry, entry) { + xnest_handle_event(walk->event); + xorg_list_del(&walk->entry); + free(walk->event); + free(walk); } + + xcb_flush(xnestUpstreamInfo.conn); + + int err = xcb_connection_has_error(xnestUpstreamInfo.conn); + if (err) { + ErrorF("Xnest: upsream connection error: %d\n", err); + exit(0); + } + + /* fetch new events from xcb */ + xcb_generic_event_t *event = NULL; + while ((event = xcb_poll_for_event(xnestUpstreamInfo.conn))) { + xnest_handle_event(event); + free(event); + } + + xcb_flush(xnestUpstreamInfo.conn); } diff --git a/hw/xnest/Events.h b/hw/xnest/Events.h index 1c1b8cd46..3211ccac5 100644 --- a/hw/xnest/Events.h +++ b/hw/xnest/Events.h @@ -17,12 +17,9 @@ is" without express or implied warranty. #include -#define ProcessedExpose (LASTEvent + 1) - extern CARD32 lastEventTime; void SetTimeSinceLastInputEvent(void); -void xnestCollectExposures(void); void xnestCollectEvents(void); void xnestQueueKeyEvent(int type, unsigned int keycode); diff --git a/hw/xnest/GCOps.c b/hw/xnest/GCOps.c index e5bc1cad4..2549840cf 100644 --- a/hw/xnest/GCOps.c +++ b/hw/xnest/GCOps.c @@ -145,21 +145,13 @@ xnestGetImage(DrawablePtr pDrawable, int x, int y, int w, int h, free(reply); } -static Bool -xnestBitBlitPredicate(Display * dpy, XEvent * event, char *args) -{ - return event->type == GraphicsExpose || event->type == NoExpose; -} - static RegionPtr xnestBitBlitHelper(GCPtr pGC) { if (!pGC->graphicsExposures) return NullRegion; else { - XEvent event; RegionPtr pReg, pTmpReg; - BoxRec Box; Bool pending, overlap; pReg = RegionCreate(NULL, 1); @@ -167,24 +159,43 @@ xnestBitBlitHelper(GCPtr pGC) if (!pReg || !pTmpReg) return NullRegion; + xcb_flush(xnestUpstreamInfo.conn); + pending = TRUE; while (pending) { - XIfEvent(xnestDisplay, &event, xnestBitBlitPredicate, NULL); - - switch (event.type) { - case NoExpose: + xcb_generic_event_t *event = xcb_wait_for_event(xnestUpstreamInfo.conn); + if (!event) { pending = FALSE; break; + } - case GraphicsExpose: - Box.x1 = event.xgraphicsexpose.x; - Box.y1 = event.xgraphicsexpose.y; - Box.x2 = event.xgraphicsexpose.x + event.xgraphicsexpose.width; - Box.y2 = event.xgraphicsexpose.y + event.xgraphicsexpose.height; - RegionReset(pTmpReg, &Box); - RegionAppend(pReg, pTmpReg); - pending = event.xgraphicsexpose.count; - break; + switch (event->response_type & ~0x80) { + case NoExpose: + pending = FALSE; + free(event); + break; + + case GraphicsExpose: + { + xcb_graphics_exposure_event_t* ev = (xcb_graphics_exposure_event_t*)event; + BoxRec Box = { + .x1 = ev->x, + .y1 = ev->y, + .x2 = ev->x + ev->width, + .y2 = ev->y + ev->height, + }; + RegionReset(pTmpReg, &Box); + RegionAppend(pReg, pTmpReg); + pending = ev->count; + free(event); + break; + } + default: + { + struct xnest_event_queue *q = malloc(sizeof(struct xnest_event_queue)); + q->event = event; + xorg_list_add(&q->entry, &xnestUpstreamInfo.eventQueue.entry); + } } } diff --git a/hw/xnest/Handlers.c b/hw/xnest/Handlers.c index 27ea30a83..535860338 100644 --- a/hw/xnest/Handlers.c +++ b/hw/xnest/Handlers.c @@ -34,8 +34,7 @@ is" without express or implied warranty. void xnestBlockHandler(void *blockData, void *timeout) { - xnestCollectExposures(); - XFlush(xnestDisplay); + xnestCollectEvents(); } void diff --git a/hw/xnest/xcb.c b/hw/xnest/xcb.c index f298bab61..e6beefca0 100644 --- a/hw/xnest/xcb.c +++ b/hw/xnest/xcb.c @@ -37,6 +37,8 @@ void xnest_upstream_setup(void) { for (int i = 0; i < xnestUpstreamInfo.screenId; ++i) xcb_screen_next (&iter); xnestUpstreamInfo.screenInfo = iter.data; + + xorg_list_init(&xnestUpstreamInfo.eventQueue.entry); } /* retrieve upstream GC XID for our xserver GC */ diff --git a/hw/xnest/xnest-xcb.h b/hw/xnest/xnest-xcb.h index b3df9b2ef..87ccc7fb8 100644 --- a/hw/xnest/xnest-xcb.h +++ b/hw/xnest/xnest-xcb.h @@ -7,11 +7,19 @@ #include +#include "include/list.h" + +struct xnest_event_queue { + struct xorg_list entry; + xcb_generic_event_t *event; +}; + struct xnest_upstream_info { xcb_connection_t *conn; uint32_t screenId; const xcb_screen_t *screenInfo; const xcb_setup_t *setup; + struct xnest_event_queue eventQueue; }; extern struct xnest_upstream_info xnestUpstreamInfo;