[PATCH xserver] ephyr: Process queued X events before blocking

Keith Packard keithp at keithp.com
Sun Jun 5 03:27:04 UTC 2016


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 <keithp at 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



More information about the xorg-devel mailing list