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