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