1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QWAYLANDDISPLAY_H
5#define QWAYLANDDISPLAY_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <QtCore/QList>
19#include <QtCore/QObject>
20#include <QtCore/QPointer>
21#include <QtCore/QRect>
22#include <QtCore/QMutex>
23#include <QtCore/QReadWriteLock>
24
25#include <QtCore/QWaitCondition>
26#include <QtCore/QLoggingCategory>
27
28#include <QtWaylandClient/private/qwayland-wayland.h>
29#include <QtWaylandClient/private/qtwaylandclientglobal_p.h>
30#include <QtWaylandClient/private/qwaylandshm_p.h>
31
32#include <qpa/qplatforminputcontextfactory_p.h>
33
34#if QT_CONFIG(xkbcommon)
35#include <QtGui/private/qxkbcommon_p.h>
36#endif
37
38struct wl_cursor_image;
39struct wp_viewport;
40
41QT_BEGIN_NAMESPACE
42
43class QAbstractEventDispatcher;
44class QSocketNotifier;
45class QPlatformScreen;
46class QPlatformPlaceholderScreen;
47
48namespace QtWayland {
49 class qt_surface_extension;
50 class zwp_text_input_manager_v1;
51 class zwp_text_input_manager_v2;
52 class zwp_text_input_manager_v4;
53 class qt_text_input_method_manager_v1;
54 class wp_cursor_shape_manager_v1;
55 class wp_fractional_scale_manager_v1;
56 class wp_viewporter;
57 class qt_toplevel_drag_manager_v1;
58}
59
60namespace QtWaylandClient {
61
62Q_WAYLANDCLIENT_EXPORT Q_DECLARE_LOGGING_CATEGORY(lcQpaWayland);
63
64class QWaylandInputDevice;
65class QWaylandBuffer;
66class QWaylandScreen;
67class QWaylandXdgOutputManagerV1;
68class QWaylandClientBufferIntegration;
69class QWaylandWindowManagerIntegration;
70class QWaylandDataDeviceManager;
71#if QT_CONFIG(wayland_client_primary_selection)
72class QWaylandPrimarySelectionDeviceManagerV1;
73#endif
74#if QT_CONFIG(tabletevent)
75class QWaylandTabletManagerV2;
76#endif
77class QWaylandPointerGestures;
78class QWaylandTouchExtension;
79class QWaylandQtKeyExtension;
80class QWaylandWindow;
81class QWaylandIntegration;
82class QWaylandHardwareIntegration;
83class QWaylandSurface;
84class QWaylandShellIntegration;
85class QWaylandCursor;
86class QWaylandCursorTheme;
87class EventThread;
88
89typedef void (*RegistryListener)(void *data,
90 struct wl_registry *registry,
91 uint32_t id,
92 const QString &interface,
93 uint32_t version);
94
95class Q_WAYLANDCLIENT_EXPORT QWaylandDisplay : public QObject, public QtWayland::wl_registry {
96 Q_OBJECT
97
98public:
99 QWaylandDisplay(QWaylandIntegration *waylandIntegration);
100 ~QWaylandDisplay(void) override;
101
102 bool initialize();
103
104#if QT_CONFIG(xkbcommon)
105 struct xkb_context *xkbContext() const { return mXkbContext.get(); }
106#endif
107
108 QList<QWaylandScreen *> screens() const { return mScreens; }
109 QPlatformPlaceholderScreen *placeholderScreen() const { return mPlaceholderScreen; }
110 void ensureScreen();
111
112 QWaylandScreen *screenForOutput(struct wl_output *output) const;
113 void handleScreenInitialized(QWaylandScreen *screen);
114
115 struct wl_surface *createSurface(void *handle);
116 struct ::wl_region *createRegion(const QRegion &qregion);
117 struct ::wl_subsurface *createSubSurface(QWaylandWindow *window, QWaylandWindow *parent);
118 struct ::wp_viewport *createViewport(QWaylandWindow *window);
119
120 QWaylandShellIntegration *shellIntegration() const;
121 QWaylandClientBufferIntegration *clientBufferIntegration() const;
122 QWaylandWindowManagerIntegration *windowManagerIntegration() const;
123
124#if QT_CONFIG(cursor)
125 QWaylandCursor *waylandCursor();
126 QWaylandCursorTheme *loadCursorTheme(const QString &name, int pixelSize);
127#endif
128 struct wl_display *wl_display() const { return mDisplay; }
129 struct ::wl_registry *wl_registry() { return object(); }
130
131 const struct wl_compositor *wl_compositor() const { return mCompositor.object(); }
132 QtWayland::wl_compositor *compositor() { return &mCompositor; }
133
134 QList<QWaylandInputDevice *> inputDevices() const { return mInputDevices; }
135 QWaylandInputDevice *defaultInputDevice() const;
136 QWaylandInputDevice *currentInputDevice() const { return defaultInputDevice(); }
137#if QT_CONFIG(wayland_datadevice)
138 QWaylandDataDeviceManager *dndSelectionHandler() const { return mDndSelectionHandler.get(); }
139#endif
140#if QT_CONFIG(wayland_client_primary_selection)
141 QWaylandPrimarySelectionDeviceManagerV1 *primarySelectionManager() const { return mPrimarySelectionManager.data(); }
142#endif
143 QtWayland::qt_surface_extension *windowExtension() const { return mWindowExtension.data(); }
144#if QT_CONFIG(tabletevent)
145 QWaylandTabletManagerV2 *tabletManager() const { return mTabletManager.data(); }
146#endif
147 QWaylandPointerGestures *pointerGestures() const { return mPointerGestures.data(); }
148 QWaylandTouchExtension *touchExtension() const { return mTouchExtension.data(); }
149 QtWayland::qt_text_input_method_manager_v1 *textInputMethodManager() const { return mTextInputMethodManager.data(); }
150 QtWayland::zwp_text_input_manager_v1 *textInputManagerv1() const { return mTextInputManagerv1.data(); }
151 QtWayland::zwp_text_input_manager_v2 *textInputManagerv2() const { return mTextInputManagerv2.data(); }
152 QtWayland::zwp_text_input_manager_v4 *textInputManagerv4() const { return mTextInputManagerv4.data(); }
153 QWaylandHardwareIntegration *hardwareIntegration() const { return mHardwareIntegration.data(); }
154 QWaylandXdgOutputManagerV1 *xdgOutputManager() const { return mXdgOutputManager.data(); }
155 QtWayland::wp_fractional_scale_manager_v1 *fractionalScaleManager() const { return mFractionalScaleManager.data(); }
156 QtWayland::wp_viewporter *viewporter() const { return mViewporter.data(); }
157 QtWayland::wp_cursor_shape_manager_v1 *cursorShapeManager() const { return mCursorShapeManager.data();}
158 QtWayland::qt_toplevel_drag_manager_v1 *xdgToplevelDragManager() const { return mXdgToplevelDragManager.data();}
159
160 struct RegistryGlobal {
161 uint32_t id;
162 QString interface;
163 uint32_t version;
164 struct ::wl_registry *registry = nullptr;
165 RegistryGlobal(uint32_t id_, const QString &interface_, uint32_t version_, struct ::wl_registry *registry_)
166 : id(id_), interface(interface_), version(version_), registry(registry_) { }
167 };
168 QList<RegistryGlobal> globals() const { return mGlobals; }
169 bool hasRegistryGlobal(QStringView interfaceName) const;
170
171 /* wl_registry_add_listener does not add but rather sets a listener, so this function is used
172 * to enable many listeners at once. */
173 void addRegistryListener(RegistryListener listener, void *data);
174 void removeListener(RegistryListener listener, void *data);
175
176 QWaylandShm *shm() const { return mShm.data(); }
177
178 static uint32_t currentTimeMillisec();
179
180 void forceRoundTrip();
181
182 bool supportsWindowDecoration() const;
183
184 uint32_t lastInputSerial() const { return mLastInputSerial; }
185 QWaylandInputDevice *lastInputDevice() const { return mLastInputDevice; }
186 QWaylandWindow *lastInputWindow() const;
187 void setLastInputDevice(QWaylandInputDevice *device, uint32_t serial, QWaylandWindow *window);
188
189 bool isWindowActivated(const QWaylandWindow *window);
190 void handleWindowActivated(QWaylandWindow *window);
191 void handleWindowDeactivated(QWaylandWindow *window);
192 void handleKeyboardFocusChanged(QWaylandInputDevice *inputDevice);
193 void handleWindowDestroyed(QWaylandWindow *window);
194
195 wl_event_queue *frameEventQueue() { return m_frameEventQueue; };
196
197 bool isKeyboardAvailable() const;
198 bool isClientSideInputContextRequested() const;
199
200 void initEventThread();
201
202public slots:
203 void blockingReadEvents();
204 void flushRequests();
205
206signals:
207 void reconnected();
208 void globalAdded(const RegistryGlobal &global);
209 void globalRemoved(const RegistryGlobal &global);
210
211private:
212 void checkWaylandError();
213 void reconnect();
214 void setupConnection();
215 void handleWaylandSync();
216 void requestWaylandSync();
217
218 void checkTextInputProtocol();
219
220 struct Listener {
221 Listener() = default;
222 Listener(RegistryListener incomingListener,
223 void* incomingData)
224 : listener(incomingListener), data(incomingData)
225 {}
226 RegistryListener listener = nullptr;
227 void *data = nullptr;
228 };
229
230 struct wl_display *mDisplay = nullptr;
231 std::unique_ptr<EventThread> m_eventThread;
232 wl_event_queue *m_frameEventQueue = nullptr;
233 QScopedPointer<EventThread> m_frameEventQueueThread;
234 QtWayland::wl_compositor mCompositor;
235 QScopedPointer<QWaylandShm> mShm;
236 QList<QWaylandScreen *> mWaitingScreens;
237 QList<QWaylandScreen *> mScreens;
238 QPlatformPlaceholderScreen *mPlaceholderScreen = nullptr;
239 QList<QWaylandInputDevice *> mInputDevices;
240 QList<Listener> mRegistryListeners;
241 QWaylandIntegration *mWaylandIntegration = nullptr;
242#if QT_CONFIG(cursor)
243 struct WaylandCursorTheme {
244 QString name;
245 int pixelSize;
246 std::unique_ptr<QWaylandCursorTheme> theme;
247 };
248 std::vector<WaylandCursorTheme> mCursorThemes;
249
250 struct FindExistingCursorThemeResult {
251 std::vector<WaylandCursorTheme>::const_iterator position;
252 bool found;
253
254 QWaylandCursorTheme *theme() const noexcept
255 { return found ? position->theme.get() : nullptr; }
256 };
257 FindExistingCursorThemeResult findExistingCursorTheme(const QString &name, int pixelSize) const noexcept;
258
259 QScopedPointer<QWaylandCursor> mCursor;
260#endif
261#if QT_CONFIG(wayland_datadevice)
262 QScopedPointer<QWaylandDataDeviceManager> mDndSelectionHandler;
263#endif
264 QScopedPointer<QtWayland::qt_surface_extension> mWindowExtension;
265 QScopedPointer<QtWayland::wl_subcompositor> mSubCompositor;
266 QScopedPointer<QWaylandTouchExtension> mTouchExtension;
267 QScopedPointer<QWaylandQtKeyExtension> mQtKeyExtension;
268 QScopedPointer<QWaylandWindowManagerIntegration> mWindowManagerIntegration;
269#if QT_CONFIG(tabletevent)
270 QScopedPointer<QWaylandTabletManagerV2> mTabletManager;
271#endif
272 QScopedPointer<QWaylandPointerGestures> mPointerGestures;
273#if QT_CONFIG(wayland_client_primary_selection)
274 QScopedPointer<QWaylandPrimarySelectionDeviceManagerV1> mPrimarySelectionManager;
275#endif
276 QScopedPointer<QtWayland::qt_text_input_method_manager_v1> mTextInputMethodManager;
277 QScopedPointer<QtWayland::zwp_text_input_manager_v1> mTextInputManagerv1;
278 QScopedPointer<QtWayland::zwp_text_input_manager_v2> mTextInputManagerv2;
279 QScopedPointer<QtWayland::zwp_text_input_manager_v4> mTextInputManagerv4;
280 QScopedPointer<QWaylandHardwareIntegration> mHardwareIntegration;
281 QScopedPointer<QWaylandXdgOutputManagerV1> mXdgOutputManager;
282 QScopedPointer<QtWayland::wp_viewporter> mViewporter;
283 QScopedPointer<QtWayland::wp_fractional_scale_manager_v1> mFractionalScaleManager;
284 QScopedPointer<QtWayland::wp_cursor_shape_manager_v1> mCursorShapeManager;
285 QScopedPointer<QtWayland::qt_toplevel_drag_manager_v1> mXdgToplevelDragManager;
286 int mFd = -1;
287 int mWritableNotificationFd = -1;
288 QList<RegistryGlobal> mGlobals;
289 uint32_t mLastInputSerial = 0;
290 QWaylandInputDevice *mLastInputDevice = nullptr;
291 QPointer<QWaylandWindow> mLastInputWindow;
292 QPointer<QWaylandWindow> mLastKeyboardFocus;
293 QList<QWaylandWindow *> mActiveWindows;
294 struct wl_callback *mSyncCallback = nullptr;
295 static const wl_callback_listener syncCallbackListener;
296 bool mWaylandTryReconnect = false;
297
298 bool mClientSideInputContextRequested = [] () {
299 const QString& requested = QPlatformInputContextFactory::requested();
300 return !requested.isEmpty() && requested != QLatin1String("wayland");
301 }();
302 QStringList mTextInputManagerList;
303 int mTextInputManagerIndex = INT_MAX;
304
305 void registry_global(uint32_t id, const QString &interface, uint32_t version) override;
306 void registry_global_remove(uint32_t id) override;
307
308#if QT_CONFIG(xkbcommon)
309 QXkbCommon::ScopedXKBContext mXkbContext;
310#endif
311
312 friend class QWaylandIntegration;
313};
314
315}
316
317QT_END_NAMESPACE
318
319#endif // QWAYLANDDISPLAY_H
320

source code of qtwayland/src/client/qwaylanddisplay_p.h