diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c index e5f188334..015aef53d 100644 --- a/hw/kdrive/ephyr/ephyr.c +++ b/hw/kdrive/ephyr/ephyr.c @@ -336,6 +336,16 @@ ephyrInternalDamageRedisplay(ScreenPtr pScreen) } } +static void +ephyrXcbProcessEvents(Bool queued_only); + +static Bool +ephyrEventWorkProc(ClientPtr client, void *closure) +{ + ephyrXcbProcessEvents(TRUE); + return TRUE; +} + static void ephyrScreenBlockHandler(ScreenPtr pScreen, void *timeout, void *pRead) { @@ -345,20 +355,16 @@ ephyrScreenBlockHandler(ScreenPtr pScreen, void *timeout, void *pRead) pScreen->BlockHandler = scrpriv->BlockHandler; (*pScreen->BlockHandler)(pScreen, timeout, pRead); + scrpriv->BlockHandler = pScreen->BlockHandler; + pScreen->BlockHandler = ephyrScreenBlockHandler; - if (scrpriv->pDamage) { - - /* Re-wrap if we're still tracking damage - */ - scrpriv->BlockHandler = pScreen->BlockHandler; - pScreen->BlockHandler = ephyrScreenBlockHandler; + if (scrpriv->pDamage) ephyrInternalDamageRedisplay(pScreen); - } else { - /* Done tracking damage, note that we've left - * the block handler unwrapped - */ - scrpriv->BlockHandler = NULL; + if (hostx_has_queued_event()) { + if (!QueueWorkProc(ephyrEventWorkProc, NULL, NULL)) + FatalError("cannot queue event processing in ephyr block handler"); + AdjustWaitForDelay(timeout, 0); } } @@ -374,12 +380,6 @@ ephyrSetInternalDamage(ScreenPtr pScreen) (DamageDestroyFunc) 0, DamageReportNone, TRUE, pScreen, pScreen); - /* Wrap only once */ - if (scrpriv->BlockHandler == NULL) { - scrpriv->BlockHandler = pScreen->BlockHandler; - pScreen->BlockHandler = ephyrScreenBlockHandler; - } - pPixmap = (*pScreen->GetScreenPixmap) (pScreen); DamageRegister(&pPixmap->drawable, scrpriv->pDamage); @@ -682,6 +682,10 @@ ephyrInitScreen(ScreenPtr pScreen) Bool ephyrFinishInitScreen(ScreenPtr pScreen) { + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + EphyrScrPriv *scrpriv = screen->driver; + /* FIXME: Calling this even if not using shadow. * Seems harmless enough. But may be safer elsewhere. */ @@ -693,6 +697,9 @@ ephyrFinishInitScreen(ScreenPtr pScreen) return FALSE; #endif + scrpriv->BlockHandler = pScreen->BlockHandler; + pScreen->BlockHandler = ephyrScreenBlockHandler; + return TRUE; } @@ -1131,12 +1138,13 @@ ephyrProcessConfigureNotify(xcb_generic_event_t *xev) } static void -ephyrXcbNotify(int fd, int ready, void *data) +ephyrXcbProcessEvents(Bool queued_only) { xcb_connection_t *conn = hostx_get_xcbconn(); while (TRUE) { - xcb_generic_event_t *xev = xcb_poll_for_event(conn); + xcb_generic_event_t *xev = hostx_get_event(queued_only); + if (!xev) { /* If our XCB connection has died (for example, our window was * closed), exit now. @@ -1191,6 +1199,12 @@ ephyrXcbNotify(int fd, int ready, void *data) } } +static void +ephyrXcbNotify(int fd, int ready, void *data) +{ + ephyrXcbProcessEvents(FALSE); +} + void ephyrCardFini(KdCardInfo * card) { diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c index abe6edaf0..887f6544c 100644 --- a/hw/kdrive/ephyr/hostx.c +++ b/hw/kdrive/ephyr/hostx.c @@ -70,6 +70,7 @@ struct EphyrHostXVars { xcb_gcontext_t gc; xcb_render_pictformat_t argb_format; xcb_cursor_t empty_cursor; + xcb_generic_event_t *saved_event; int depth; Bool use_sw_cursor; Bool use_fullscreen; @@ -1227,6 +1228,31 @@ hostx_get_xcbconn(void) return HostX.conn; } +xcb_generic_event_t * +hostx_get_event(Bool queued_only) +{ + xcb_generic_event_t *xev; + + if (HostX.saved_event) { + xev = HostX.saved_event; + HostX.saved_event = NULL; + } else { + if (queued_only) + xev = xcb_poll_for_queued_event(HostX.conn); + else + xev = xcb_poll_for_event(HostX.conn); + } + return xev; +} + +Bool +hostx_has_queued_event(void) +{ + if (!HostX.saved_event) + HostX.saved_event = xcb_poll_for_queued_event(HostX.conn); + return HostX.saved_event != NULL; +} + int hostx_get_screen(void) { diff --git a/hw/kdrive/ephyr/hostx.h b/hw/kdrive/ephyr/hostx.h index 6e0b07ba0..d0f30119c 100644 --- a/hw/kdrive/ephyr/hostx.h +++ b/hw/kdrive/ephyr/hostx.h @@ -157,6 +157,12 @@ hostx_size_set_from_configure(Bool); xcb_connection_t * hostx_get_xcbconn(void); +xcb_generic_event_t * +hostx_get_event(Bool queued_only); + +Bool +hostx_has_queued_event(void); + int hostx_get_screen(void);