If we end up reading all pending X events in the course of other server
execution, then our notify FD callback won't get invoked and we won't
process them. Fix this by clearing the pending event queue before
blocking in the server.

Signed-off-by: Keith Packard <kei...@keithp.com>
---
 hw/kdrive/ephyr/ephyr.c | 118 +++++++++++++++++++++++++-----------------------
 1 file changed, 62 insertions(+), 56 deletions(-)

diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c
index 2114c1c..9f1c803 100644
--- a/hw/kdrive/ephyr/ephyr.c
+++ b/hw/kdrive/ephyr/ephyr.c
@@ -337,29 +337,28 @@ ephyrInternalDamageRedisplay(ScreenPtr pScreen)
 }
 
 static void
+ephyrXcbHandleEvent(xcb_generic_event_t *xev);
+
+static void
 ephyrScreenBlockHandler(ScreenPtr pScreen, void *timeout, void *pRead)
 {
     KdScreenPriv(pScreen);
     KdScreenInfo *screen = pScreenPriv->screen;
     EphyrScrPriv *scrpriv = screen->driver;
+    xcb_connection_t *conn = hostx_get_xcbconn();
+    xcb_generic_event_t *xev;
 
     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;
-    }
+    while ((xev = xcb_poll_for_queued_event(conn)) != NULL)
+        ephyrXcbHandleEvent(xev);
+
 }
 
 Bool
@@ -374,12 +373,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);
@@ -668,6 +661,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.
      */
@@ -679,6 +676,9 @@ ephyrFinishInitScreen(ScreenPtr pScreen)
         return FALSE;
 #endif
 
+    scrpriv->BlockHandler = pScreen->BlockHandler;
+    pScreen->BlockHandler = ephyrScreenBlockHandler;
+
     return TRUE;
 }
 
@@ -1117,6 +1117,49 @@ ephyrProcessConfigureNotify(xcb_generic_event_t *xev)
 }
 
 static void
+ephyrXcbHandleEvent(xcb_generic_event_t *xev)
+{
+    switch (xev->response_type & 0x7f) {
+    case 0:
+        ephyrProcessErrorEvent(xev);
+        break;
+
+    case XCB_EXPOSE:
+        ephyrProcessExpose(xev);
+        break;
+
+    case XCB_MOTION_NOTIFY:
+        ephyrProcessMouseMotion(xev);
+        break;
+
+    case XCB_KEY_PRESS:
+        ephyrProcessKeyPress(xev);
+        break;
+
+    case XCB_KEY_RELEASE:
+        ephyrProcessKeyRelease(xev);
+        break;
+
+    case XCB_BUTTON_PRESS:
+        ephyrProcessButtonPress(xev);
+        break;
+
+    case XCB_BUTTON_RELEASE:
+        ephyrProcessButtonRelease(xev);
+        break;
+
+    case XCB_CONFIGURE_NOTIFY:
+        ephyrProcessConfigureNotify(xev);
+        break;
+    }
+
+    if (ephyr_glamor)
+        ephyr_glamor_process_event(xev);
+
+    free(xev);
+}
+
+static void
 ephyrXcbNotify(int fd, int ready, void *data)
 {
     xcb_connection_t *conn = hostx_get_xcbconn();
@@ -1136,44 +1179,7 @@ ephyrXcbNotify(int fd, int ready, void *data)
             break;
         }
 
-        switch (xev->response_type & 0x7f) {
-        case 0:
-            ephyrProcessErrorEvent(xev);
-            break;
-
-        case XCB_EXPOSE:
-            ephyrProcessExpose(xev);
-            break;
-
-        case XCB_MOTION_NOTIFY:
-            ephyrProcessMouseMotion(xev);
-            break;
-
-        case XCB_KEY_PRESS:
-            ephyrProcessKeyPress(xev);
-            break;
-
-        case XCB_KEY_RELEASE:
-            ephyrProcessKeyRelease(xev);
-            break;
-
-        case XCB_BUTTON_PRESS:
-            ephyrProcessButtonPress(xev);
-            break;
-
-        case XCB_BUTTON_RELEASE:
-            ephyrProcessButtonRelease(xev);
-            break;
-
-        case XCB_CONFIGURE_NOTIFY:
-            ephyrProcessConfigureNotify(xev);
-            break;
-        }
-
-        if (ephyr_glamor)
-            ephyr_glamor_process_event(xev);
-
-        free(xev);
+        ephyrXcbHandleEvent(xev);
     }
 }
 
-- 
2.8.1

_______________________________________________
xorg-devel@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to