1From c8853fb402c4ea6cc978d8cf1c50232f5edb81f4 Mon Sep 17 00:00:00 2001 2From: Jeffy Chen <jeffy.chen@rock-chips.com> 3Date: Sat, 9 May 2020 17:05:32 +0800 4Subject: [PATCH 08/17] qwaylanddisplay: Wakeup main event dispatcher when 5 events pending 6 7The socket might not be able to generate poll events to wakeup the main 8event dispatcher when there're multiple wayland clients(e.g. waylandsink) 9reading it. 10 11So let's create a extra thread to check the wayland display event queue 12for pending events and wakeup the main event dispatcher. 13 14Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com> 15--- 16 src/client/qwaylanddisplay.cpp | 50 +++++++++++++++++++++++++++++++++- 17 src/client/qwaylanddisplay_p.h | 2 ++ 18 2 files changed, 51 insertions(+), 1 deletion(-) 19 20diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp 21index 86045a3..dc61d23 100644 22--- a/src/client/qwaylanddisplay.cpp 23+++ b/src/client/qwaylanddisplay.cpp 24@@ -83,6 +83,8 @@ 25 26 #include <QtCore/QDebug> 27 28+#include <QThread> 29+ 30 #include <errno.h> 31 32 #include <tuple> // for std::tie 33@@ -284,6 +286,48 @@ private: 34 35 Q_LOGGING_CATEGORY(lcQpaWayland, "qt.qpa.wayland"); // for general (uncategorized) Wayland platform logging 36 37+class QWaylandDisplayThread : public QThread 38+{ 39+public: 40+ QWaylandDisplayThread(struct wl_display *display); 41+ ~QWaylandDisplayThread(); 42+ 43+protected: 44+ virtual void run() override; 45+ 46+private: 47+ struct wl_display *mDisplay = nullptr; 48+ bool quit; 49+}; 50+ 51+QWaylandDisplayThread::QWaylandDisplayThread(struct wl_display *display) 52+ : mDisplay(display), quit(false) 53+{ 54+ start(); 55+} 56+ 57+QWaylandDisplayThread::~QWaylandDisplayThread() 58+{ 59+ quit = true; 60+ wait(); 61+} 62+ 63+void QWaylandDisplayThread::run() 64+{ 65+ while (!quit) { 66+ if (wl_display_prepare_read(mDisplay) != 0) { 67+ // wakeup dispatcher for pending events 68+ if (auto *dispatcher = QCoreApplication::eventDispatcher()) 69+ dispatcher->wakeUp(); 70+ } else { 71+ wl_display_flush(mDisplay); 72+ wl_display_cancel_read(mDisplay); 73+ } 74+ 75+ usleep(100000); 76+ } 77+} 78+ 79 struct wl_surface *QWaylandDisplay::createSurface(void *handle) 80 { 81 struct wl_surface *surface = mCompositor.create_surface(); 82@@ -351,6 +395,8 @@ QWaylandDisplay::QWaylandDisplay(QWaylandIntegration *waylandIntegration) 83 if (!mXkbContext) 84 qCWarning(lcQpaWayland, "failed to create xkb context"); 85 #endif 86+ 87+ mThread = new QWaylandDisplayThread(mDisplay); 88 } 89 90 QWaylandDisplay::~QWaylandDisplay(void) 91@@ -377,8 +423,10 @@ QWaylandDisplay::~QWaylandDisplay(void) 92 #if QT_CONFIG(cursor) 93 qDeleteAll(mCursorThemes); 94 #endif 95- if (mDisplay) 96+ if (mDisplay) { 97+ delete mThread; 98 wl_display_disconnect(mDisplay); 99+ } 100 } 101 102 // Steps which is called just after constructor. This separates registry_global() out of the constructor 103diff --git a/src/client/qwaylanddisplay_p.h b/src/client/qwaylanddisplay_p.h 104index 42bc661..fb632b3 100644 105--- a/src/client/qwaylanddisplay_p.h 106+++ b/src/client/qwaylanddisplay_p.h 107@@ -109,6 +109,7 @@ class QWaylandSurface; 108 class QWaylandShellIntegration; 109 class QWaylandCursor; 110 class QWaylandCursorTheme; 111+class QWaylandDisplayThread; 112 class EventThread; 113 114 typedef void (*RegistryListener)(void *data, 115@@ -276,6 +277,7 @@ private: 116 QList<QWaylandWindow *> mActiveWindows; 117 struct wl_callback *mSyncCallback = nullptr; 118 static const wl_callback_listener syncCallbackListener; 119+ QWaylandDisplayThread *mThread = nullptr; 120 121 bool mClientSideInputContextRequested = !QPlatformInputContextFactory::requested().isNull(); 122 123-- 1242.20.1 125 126