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
43#define WAYLAND_IM_KEY "wayland"
44
45class QAbstractEventDispatcher;
46class QSocketNotifier;
47class QPlatformScreen;
48class QPlatformPlaceholderScreen;
49
50namespace QtWayland {
51 class qt_surface_extension;
52 class zwp_text_input_manager_v1;
53 class zwp_text_input_manager_v2;
54 class zwp_text_input_manager_v3;
55 class qt_text_input_method_manager_v1;
56 class wp_cursor_shape_manager_v1;
57 class wp_fractional_scale_manager_v1;
58 class wp_viewporter;
59 class xdg_toplevel_drag_manager_v1;
60}
61
62namespace QtWaylandClient {
63
64Q_WAYLANDCLIENT_EXPORT Q_DECLARE_LOGGING_CATEGORY(lcQpaWayland);
65
66class QWaylandInputDevice;
67class QWaylandBuffer;
68class QWaylandScreen;
69class QWaylandXdgOutputManagerV1;
70class QWaylandClientBufferIntegration;
71class QWaylandWindowManagerIntegration;
72class QWaylandDataDeviceManager;
73#if QT_CONFIG(wayland_client_primary_selection)
74class QWaylandPrimarySelectionDeviceManagerV1;
75#endif
76#if QT_CONFIG(tabletevent)
77class QWaylandTabletManagerV2;
78#endif
79class QWaylandPointerGestures;
80class QWaylandTouchExtension;
81class QWaylandQtKeyExtension;
82class QWaylandWindow;
83class QWaylandIntegration;
84class QWaylandHardwareIntegration;
85class QWaylandSurface;
86class QWaylandShellIntegration;
87class QWaylandCursor;
88class QWaylandCursorTheme;
89class EventThread;
90
91typedef void (*RegistryListener)(void *data,
92 struct wl_registry *registry,
93 uint32_t id,
94 const QString &interface,
95 uint32_t version);
96
97class Q_WAYLANDCLIENT_EXPORT QWaylandDisplay : public QObject, public QtWayland::wl_registry {
98 Q_OBJECT
99
100public:
101 QWaylandDisplay(QWaylandIntegration *waylandIntegration);
102 ~QWaylandDisplay(void) override;
103
104 bool initialize();
105
106#if QT_CONFIG(xkbcommon)
107 struct xkb_context *xkbContext() const { return mXkbContext.get(); }
108#endif
109
110 QList<QWaylandScreen *> screens() const { return mScreens; }
111 QPlatformPlaceholderScreen *placeholderScreen() const { return mPlaceholderScreen; }
112 void ensureScreen();
113
114 QWaylandScreen *screenForOutput(struct wl_output *output) const;
115 void handleScreenInitialized(QWaylandScreen *screen);
116
117 struct wl_surface *createSurface(void *handle);
118 struct ::wl_region *createRegion(const QRegion &qregion);
119 struct ::wl_subsurface *createSubSurface(QWaylandWindow *window, QWaylandWindow *parent);
120 struct ::wp_viewport *createViewport(QWaylandWindow *window);
121
122 QWaylandShellIntegration *shellIntegration() const;
123 QWaylandClientBufferIntegration *clientBufferIntegration() const;
124 QWaylandWindowManagerIntegration *windowManagerIntegration() const;
125
126#if QT_CONFIG(cursor)
127 QWaylandCursor *waylandCursor();
128 QWaylandCursorTheme *loadCursorTheme(const QString &name, int pixelSize);
129#endif
130 struct wl_display *wl_display() const
131 {
132 return mDisplay;
133 }
134 struct ::wl_registry *wl_registry() { return object(); }
135
136 QtWayland::wl_compositor *compositor()
137 {
138 return mGlobals.compositor.get();
139 }
140
141 QList<QWaylandInputDevice *> inputDevices() const { return mInputDevices; }
142 QWaylandInputDevice *defaultInputDevice() const;
143 QWaylandInputDevice *currentInputDevice() const { return defaultInputDevice(); }
144#if QT_CONFIG(wayland_datadevice)
145 QWaylandDataDeviceManager *dndSelectionHandler() const
146 {
147 return mGlobals.dndSelectionHandler.get();
148 }
149#endif
150#if QT_CONFIG(wayland_client_primary_selection)
151 QWaylandPrimarySelectionDeviceManagerV1 *primarySelectionManager() const
152 {
153 return mGlobals.primarySelectionManager.get();
154 }
155#endif
156 QtWayland::qt_surface_extension *windowExtension() const
157 {
158 return mGlobals.surfaceExtension.get();
159 }
160#if QT_CONFIG(tabletevent)
161 QWaylandTabletManagerV2 *tabletManager() const
162 {
163 return mGlobals.tabletManager.get();
164 }
165#endif
166 QWaylandPointerGestures *pointerGestures() const
167 {
168 return mGlobals.pointerGestures.get();
169 }
170 QWaylandTouchExtension *touchExtension() const
171 {
172 return mGlobals.touchExtension.get();
173 }
174 QtWayland::qt_text_input_method_manager_v1 *textInputMethodManager() const
175 {
176 return mGlobals.textInputMethodManager.get();
177 }
178 QtWayland::zwp_text_input_manager_v1 *textInputManagerv1() const
179 {
180 return mGlobals.textInputManagerv1.get();
181 }
182 QtWayland::zwp_text_input_manager_v2 *textInputManagerv2() const
183 {
184 return mGlobals.textInputManagerv2.get();
185 }
186 QtWayland::zwp_text_input_manager_v3 *textInputManagerv3() const
187 {
188 return mGlobals.textInputManagerv3.get();
189 }
190 QWaylandHardwareIntegration *hardwareIntegration() const
191 {
192 return mGlobals.hardwareIntegration.get();
193 }
194 QWaylandXdgOutputManagerV1 *xdgOutputManager() const
195 {
196 return mGlobals.xdgOutputManager.get();
197 }
198 QtWayland::wp_fractional_scale_manager_v1 *fractionalScaleManager() const
199 {
200 return mGlobals.fractionalScaleManager.get();
201 }
202 QtWayland::wp_viewporter *viewporter() const
203 {
204 return mGlobals.viewporter.get();
205 }
206 QtWayland::wp_cursor_shape_manager_v1 *cursorShapeManager() const
207 {
208 return mGlobals.cursorShapeManager.get();
209 }
210 QtWayland::xdg_toplevel_drag_manager_v1 *xdgToplevelDragManager() const
211 {
212 return mGlobals.xdgToplevelDragManager.get();
213 }
214
215
216 struct RegistryGlobal {
217 uint32_t id;
218 QString interface;
219 uint32_t version;
220 struct ::wl_registry *registry = nullptr;
221 RegistryGlobal(uint32_t id_, const QString &interface_, uint32_t version_, struct ::wl_registry *registry_)
222 : id(id_), interface(interface_), version(version_), registry(registry_) { }
223 };
224 QList<RegistryGlobal> globals() const
225 {
226 return mRegistryGlobals;
227 }
228 bool hasRegistryGlobal(QStringView interfaceName) const;
229
230 /* wl_registry_add_listener does not add but rather sets a listener, so this function is used
231 * to enable many listeners at once. */
232 void addRegistryListener(RegistryListener listener, void *data);
233 void removeListener(RegistryListener listener, void *data);
234
235 QWaylandShm *shm() const
236 {
237 return mGlobals.shm.get();
238 }
239
240 void forceRoundTrip();
241
242 bool supportsWindowDecoration() const;
243
244 uint32_t lastInputSerial() const { return mLastInputSerial; }
245 QWaylandInputDevice *lastInputDevice() const { return mLastInputDevice; }
246 QWaylandWindow *lastInputWindow() const;
247 void setLastInputDevice(QWaylandInputDevice *device, uint32_t serial, QWaylandWindow *window);
248
249 bool isWindowActivated(const QWaylandWindow *window);
250 void handleWindowActivated(QWaylandWindow *window);
251 void handleWindowDeactivated(QWaylandWindow *window);
252 void handleKeyboardFocusChanged(QWaylandInputDevice *inputDevice);
253 void handleWindowDestroyed(QWaylandWindow *window);
254
255 wl_event_queue *frameEventQueue() { return m_frameEventQueue; };
256
257 bool isKeyboardAvailable() const;
258 bool isWaylandInputContextRequested() const;
259
260 void initEventThread();
261
262public Q_SLOTS:
263 void blockingReadEvents();
264 void flushRequests();
265
266Q_SIGNALS:
267 void connected();
268 void globalAdded(const RegistryGlobal &global);
269 void globalRemoved(const RegistryGlobal &global);
270
271private:
272 void checkWaylandError();
273 void reconnect();
274 void setupConnection();
275 void handleWaylandSync();
276 void requestWaylandSync();
277
278 void checkTextInputProtocol();
279
280 struct Listener {
281 Listener() = default;
282 Listener(RegistryListener incomingListener,
283 void* incomingData)
284 : listener(incomingListener), data(incomingData)
285 {}
286 RegistryListener listener = nullptr;
287 void *data = nullptr;
288 };
289 struct wl_display *mDisplay = nullptr;
290 std::unique_ptr<EventThread> m_eventThread;
291 wl_event_queue *m_frameEventQueue = nullptr;
292 QScopedPointer<EventThread> m_frameEventQueueThread;
293 QList<QWaylandScreen *> mWaitingScreens;
294 QList<QWaylandScreen *> mScreens;
295 QPlatformPlaceholderScreen *mPlaceholderScreen = nullptr;
296 QList<QWaylandInputDevice *> mInputDevices;
297 QList<Listener> mRegistryListeners;
298 QWaylandIntegration *mWaylandIntegration = nullptr;
299#if QT_CONFIG(cursor)
300 struct WaylandCursorTheme {
301 QString name;
302 int pixelSize;
303 std::unique_ptr<QWaylandCursorTheme> theme;
304 };
305 std::vector<WaylandCursorTheme> mCursorThemes;
306
307 struct FindExistingCursorThemeResult {
308 std::vector<WaylandCursorTheme>::const_iterator position;
309 bool found;
310
311 QWaylandCursorTheme *theme() const noexcept
312 { return found ? position->theme.get() : nullptr; }
313 };
314 FindExistingCursorThemeResult findExistingCursorTheme(const QString &name,
315 int pixelSize) const noexcept;
316 QScopedPointer<QWaylandCursor> mCursor;
317#endif
318
319 struct GlobalHolder
320 {
321 std::unique_ptr<QtWayland::wl_compositor> compositor;
322 std::unique_ptr<QWaylandShm> shm;
323#if QT_CONFIG(wayland_datadevice)
324 std::unique_ptr<QWaylandDataDeviceManager> dndSelectionHandler;
325#endif
326 std::unique_ptr<QtWayland::qt_surface_extension> surfaceExtension;
327 std::unique_ptr<QtWayland::wl_subcompositor> subCompositor;
328 std::unique_ptr<QWaylandTouchExtension> touchExtension;
329 std::unique_ptr<QWaylandQtKeyExtension> qtKeyExtension;
330#if QT_CONFIG(tabletevent)
331 std::unique_ptr<QWaylandTabletManagerV2> tabletManager;
332#endif
333 std::unique_ptr<QWaylandPointerGestures> pointerGestures;
334#if QT_CONFIG(wayland_client_primary_selection)
335 std::unique_ptr<QWaylandPrimarySelectionDeviceManagerV1> primarySelectionManager;
336#endif
337 std::unique_ptr<QtWayland::qt_text_input_method_manager_v1> textInputMethodManager;
338 std::unique_ptr<QtWayland::zwp_text_input_manager_v1> textInputManagerv1;
339 std::unique_ptr<QtWayland::zwp_text_input_manager_v2> textInputManagerv2;
340 std::unique_ptr<QtWayland::zwp_text_input_manager_v3> textInputManagerv3;
341 std::unique_ptr<QWaylandHardwareIntegration> hardwareIntegration;
342 std::unique_ptr<QWaylandXdgOutputManagerV1> xdgOutputManager;
343 std::unique_ptr<QtWayland::wp_viewporter> viewporter;
344 std::unique_ptr<QtWayland::wp_fractional_scale_manager_v1> fractionalScaleManager;
345 std::unique_ptr<QtWayland::wp_cursor_shape_manager_v1> cursorShapeManager;
346 std::unique_ptr<QtWayland::xdg_toplevel_drag_manager_v1> xdgToplevelDragManager;
347 std::unique_ptr<QWaylandWindowManagerIntegration> windowManagerIntegration;
348 } mGlobals;
349 int mFd = -1;
350 int mWritableNotificationFd = -1;
351 QList<RegistryGlobal> mRegistryGlobals;
352 uint32_t mLastInputSerial = 0;
353 QWaylandInputDevice *mLastInputDevice = nullptr;
354 QPointer<QWaylandWindow> mLastInputWindow;
355 QPointer<QWaylandWindow> mLastKeyboardFocus;
356 QList<QWaylandWindow *> mActiveWindows;
357 struct wl_callback *mSyncCallback = nullptr;
358 static const wl_callback_listener syncCallbackListener;
359 bool mWaylandTryReconnect = false;
360
361 bool mWaylandInputContextRequested = [] () {
362 const auto requested = QPlatformInputContextFactory::requested();
363 return requested.isEmpty() || requested.contains(str: QLatin1String(WAYLAND_IM_KEY));
364 }();
365 QStringList mTextInputManagerList;
366 int mTextInputManagerIndex = INT_MAX;
367
368 void registry_global(uint32_t id, const QString &interface, uint32_t version) override;
369 void registry_global_remove(uint32_t id) override;
370
371#if QT_CONFIG(xkbcommon)
372 QXkbCommon::ScopedXKBContext mXkbContext;
373#endif
374
375 friend class QWaylandIntegration;
376};
377
378}
379
380QT_END_NAMESPACE
381
382#endif // QWAYLANDDISPLAY_H
383

Provided by KDAB

Privacy Policy
Start learning QML with our Intro Training
Find out more

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