1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the plugins of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#ifndef QWAYLANDDISPLAY_H
41#define QWAYLANDDISPLAY_H
42
43//
44// W A R N I N G
45// -------------
46//
47// This file is not part of the Qt API. It exists purely as an
48// implementation detail. This header file may change from version to
49// version without notice, or even be removed.
50//
51// We mean it.
52//
53
54#include <QtCore/QObject>
55#include <QtCore/QRect>
56#include <QtCore/QPointer>
57#include <QtCore/QVector>
58#include <QtCore/QMutex>
59#include <QtCore/QReadWriteLock>
60
61#include <QtCore/QWaitCondition>
62#include <QtCore/QLoggingCategory>
63
64#include <QtWaylandClient/private/qwayland-wayland.h>
65#include <QtWaylandClient/private/qtwaylandclientglobal_p.h>
66#include <QtWaylandClient/private/qwaylandshm_p.h>
67
68#include <qpa/qplatforminputcontextfactory_p.h>
69
70#if QT_CONFIG(xkbcommon)
71#include <QtXkbCommonSupport/private/qxkbcommon_p.h>
72#endif
73
74struct wl_cursor_image;
75
76QT_BEGIN_NAMESPACE
77
78class QAbstractEventDispatcher;
79class QSocketNotifier;
80class QPlatformScreen;
81class QPlatformPlaceholderScreen;
82
83namespace QtWayland {
84 class qt_surface_extension;
85 class zwp_text_input_manager_v2;
86}
87
88namespace QtWaylandClient {
89
90Q_WAYLAND_CLIENT_EXPORT Q_DECLARE_LOGGING_CATEGORY(lcQpaWayland);
91
92class QWaylandInputDevice;
93class QWaylandBuffer;
94class QWaylandScreen;
95class QWaylandXdgOutputManagerV1;
96class QWaylandClientBufferIntegration;
97class QWaylandWindowManagerIntegration;
98class QWaylandDataDeviceManager;
99#if QT_CONFIG(wayland_client_primary_selection)
100class QWaylandPrimarySelectionDeviceManagerV1;
101#endif
102#if QT_CONFIG(tabletevent)
103class QWaylandTabletManagerV2;
104#endif
105class QWaylandTouchExtension;
106class QWaylandQtKeyExtension;
107class QWaylandWindow;
108class QWaylandIntegration;
109class QWaylandHardwareIntegration;
110class QWaylandSurface;
111class QWaylandShellIntegration;
112class QWaylandCursor;
113class QWaylandCursorTheme;
114
115typedef void (*RegistryListener)(void *data,
116 struct wl_registry *registry,
117 uint32_t id,
118 const QString &interface,
119 uint32_t version);
120
121class Q_WAYLAND_CLIENT_EXPORT QWaylandDisplay : public QObject, public QtWayland::wl_registry {
122 Q_OBJECT
123
124public:
125 struct FrameQueue {
126 FrameQueue(wl_event_queue *q = nullptr) : queue(q), mutex(new QMutex) {}
127 wl_event_queue *queue;
128 QMutex *mutex;
129 };
130
131 QWaylandDisplay(QWaylandIntegration *waylandIntegration);
132 ~QWaylandDisplay(void) override;
133
134#if QT_CONFIG(xkbcommon)
135 struct xkb_context *xkbContext() const { return mXkbContext.get(); }
136#endif
137
138 QList<QWaylandScreen *> screens() const { return mScreens; }
139 QPlatformPlaceholderScreen *placeholderScreen() const { return mPlaceholderScreen; }
140 void ensureScreen();
141
142 QWaylandScreen *screenForOutput(struct wl_output *output) const;
143 void handleScreenInitialized(QWaylandScreen *screen);
144
145 struct wl_surface *createSurface(void *handle);
146 struct ::wl_region *createRegion(const QRegion &qregion);
147 struct ::wl_subsurface *createSubSurface(QWaylandWindow *window, QWaylandWindow *parent);
148
149 QWaylandShellIntegration *shellIntegration() const;
150 QWaylandClientBufferIntegration *clientBufferIntegration() const;
151 QWaylandWindowManagerIntegration *windowManagerIntegration() const;
152
153#if QT_CONFIG(cursor)
154 QWaylandCursor *waylandCursor();
155 QWaylandCursorTheme *loadCursorTheme(const QString &name, int pixelSize);
156#endif
157 struct wl_display *wl_display() const { return mDisplay; }
158 struct ::wl_registry *wl_registry() { return object(); }
159
160 const struct wl_compositor *wl_compositor() const { return mCompositor.object(); }
161 QtWayland::wl_compositor *compositor() { return &mCompositor; }
162 int compositorVersion() const { return mCompositorVersion; }
163
164 QList<QWaylandInputDevice *> inputDevices() const { return mInputDevices; }
165 QWaylandInputDevice *defaultInputDevice() const;
166 QWaylandInputDevice *currentInputDevice() const { return defaultInputDevice(); }
167#if QT_CONFIG(wayland_datadevice)
168 QWaylandDataDeviceManager *dndSelectionHandler() const { return mDndSelectionHandler.data(); }
169#endif
170#if QT_CONFIG(wayland_client_primary_selection)
171 QWaylandPrimarySelectionDeviceManagerV1 *primarySelectionManager() const { return mPrimarySelectionManager.data(); }
172#endif
173 QtWayland::qt_surface_extension *windowExtension() const { return mWindowExtension.data(); }
174#if QT_CONFIG(tabletevent)
175 QWaylandTabletManagerV2 *tabletManager() const { return mTabletManager.data(); }
176#endif
177 QWaylandTouchExtension *touchExtension() const { return mTouchExtension.data(); }
178 QtWayland::zwp_text_input_manager_v2 *textInputManager() const { return mTextInputManager.data(); }
179 QWaylandHardwareIntegration *hardwareIntegration() const { return mHardwareIntegration.data(); }
180 QWaylandXdgOutputManagerV1 *xdgOutputManager() const { return mXdgOutputManager.data(); }
181
182 struct RegistryGlobal {
183 uint32_t id;
184 QString interface;
185 uint32_t version;
186 struct ::wl_registry *registry = nullptr;
187 RegistryGlobal(uint32_t id_, const QString &interface_, uint32_t version_, struct ::wl_registry *registry_)
188 : id(id_), interface(interface_), version(version_), registry(registry_) { }
189 };
190 QList<RegistryGlobal> globals() const { return mGlobals; }
191 bool hasRegistryGlobal(QStringView interfaceName) const;
192
193 /* wl_registry_add_listener does not add but rather sets a listener, so this function is used
194 * to enable many listeners at once. */
195 void addRegistryListener(RegistryListener listener, void *data);
196 void removeListener(RegistryListener listener, void *data);
197
198 QWaylandShm *shm() const { return mShm.data(); }
199
200 static uint32_t currentTimeMillisec();
201
202 void forceRoundTrip();
203
204 bool supportsWindowDecoration() const;
205
206 uint32_t lastInputSerial() const { return mLastInputSerial; }
207 QWaylandInputDevice *lastInputDevice() const { return mLastInputDevice; }
208 QWaylandWindow *lastInputWindow() const;
209 void setLastInputDevice(QWaylandInputDevice *device, uint32_t serial, QWaylandWindow *window);
210
211 bool isWindowActivated(const QWaylandWindow *window);
212 void handleWindowActivated(QWaylandWindow *window);
213 void handleWindowDeactivated(QWaylandWindow *window);
214 void handleKeyboardFocusChanged(QWaylandInputDevice *inputDevice);
215 void handleWindowDestroyed(QWaylandWindow *window);
216
217 wl_event_queue *createEventQueue();
218 FrameQueue createFrameQueue();
219 void destroyFrameQueue(const FrameQueue &q);
220 void dispatchQueueWhile(wl_event_queue *queue, std::function<bool()> condition, int timeout = -1);
221
222public slots:
223 void blockingReadEvents();
224 void flushRequests();
225
226private:
227 void waitForScreens();
228 void checkError() const;
229
230 void handleWaylandSync();
231 void requestWaylandSync();
232
233 struct Listener {
234 Listener() = default;
235 Listener(RegistryListener incomingListener,
236 void* incomingData)
237 : listener(incomingListener), data(incomingData)
238 {}
239 RegistryListener listener = nullptr;
240 void *data = nullptr;
241 };
242
243 struct wl_display *mDisplay = nullptr;
244 QtWayland::wl_compositor mCompositor;
245 QScopedPointer<QWaylandShm> mShm;
246 QList<QWaylandScreen *> mWaitingScreens;
247 QList<QWaylandScreen *> mScreens;
248 QPlatformPlaceholderScreen *mPlaceholderScreen = nullptr;
249 QList<QWaylandInputDevice *> mInputDevices;
250 QList<Listener> mRegistryListeners;
251 QWaylandIntegration *mWaylandIntegration = nullptr;
252#if QT_CONFIG(cursor)
253 QMap<std::pair<QString, int>, QWaylandCursorTheme *> mCursorThemes; // theme name and size
254 QScopedPointer<QWaylandCursor> mCursor;
255#endif
256#if QT_CONFIG(wayland_datadevice)
257 QScopedPointer<QWaylandDataDeviceManager> mDndSelectionHandler;
258#endif
259 QScopedPointer<QtWayland::qt_surface_extension> mWindowExtension;
260 QScopedPointer<QtWayland::wl_subcompositor> mSubCompositor;
261 QScopedPointer<QWaylandTouchExtension> mTouchExtension;
262 QScopedPointer<QWaylandQtKeyExtension> mQtKeyExtension;
263 QScopedPointer<QWaylandWindowManagerIntegration> mWindowManagerIntegration;
264#if QT_CONFIG(tabletevent)
265 QScopedPointer<QWaylandTabletManagerV2> mTabletManager;
266#endif
267#if QT_CONFIG(wayland_client_primary_selection)
268 QScopedPointer<QWaylandPrimarySelectionDeviceManagerV1> mPrimarySelectionManager;
269#endif
270 QScopedPointer<QtWayland::zwp_text_input_manager_v2> mTextInputManager;
271 QScopedPointer<QWaylandHardwareIntegration> mHardwareIntegration;
272 QScopedPointer<QWaylandXdgOutputManagerV1> mXdgOutputManager;
273 QSocketNotifier *mReadNotifier = nullptr;
274 int mFd = -1;
275 int mWritableNotificationFd = -1;
276 QList<RegistryGlobal> mGlobals;
277 int mCompositorVersion = -1;
278 uint32_t mLastInputSerial = 0;
279 QWaylandInputDevice *mLastInputDevice = nullptr;
280 QPointer<QWaylandWindow> mLastInputWindow;
281 QPointer<QWaylandWindow> mLastKeyboardFocus;
282 QVector<QWaylandWindow *> mActiveWindows;
283 QVector<FrameQueue> mExternalQueues;
284 struct wl_callback *mSyncCallback = nullptr;
285 static const wl_callback_listener syncCallbackListener;
286 QReadWriteLock m_frameQueueLock;
287
288 bool mClientSideInputContextRequested = !QPlatformInputContextFactory::requested().isNull();
289
290 void registry_global(uint32_t id, const QString &interface, uint32_t version) override;
291 void registry_global_remove(uint32_t id) override;
292
293#if QT_CONFIG(xkbcommon)
294 QXkbCommon::ScopedXKBContext mXkbContext;
295#endif
296
297 friend class QWaylandIntegration;
298};
299
300}
301
302QT_END_NAMESPACE
303
304#endif // QWAYLANDDISPLAY_H
305

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