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 
74 struct wl_cursor_image;
75 
76 QT_BEGIN_NAMESPACE
77 
78 class QAbstractEventDispatcher;
79 class QSocketNotifier;
80 class QPlatformScreen;
81 class QPlatformPlaceholderScreen;
82 
83 namespace QtWayland {
84     class qt_surface_extension;
85     class zwp_text_input_manager_v2;
86 }
87 
88 namespace QtWaylandClient {
89 
90 Q_WAYLAND_CLIENT_EXPORT Q_DECLARE_LOGGING_CATEGORY(lcQpaWayland);
91 
92 class QWaylandInputDevice;
93 class QWaylandBuffer;
94 class QWaylandScreen;
95 class QWaylandXdgOutputManagerV1;
96 class QWaylandClientBufferIntegration;
97 class QWaylandWindowManagerIntegration;
98 class QWaylandDataDeviceManager;
99 #if QT_CONFIG(wayland_client_primary_selection)
100 class QWaylandPrimarySelectionDeviceManagerV1;
101 #endif
102 class QWaylandTabletManagerV2;
103 class QWaylandTouchExtension;
104 class QWaylandQtKeyExtension;
105 class QWaylandWindow;
106 class QWaylandIntegration;
107 class QWaylandHardwareIntegration;
108 class QWaylandSurface;
109 class QWaylandShellIntegration;
110 class QWaylandCursor;
111 class QWaylandCursorTheme;
112 
113 typedef void (*RegistryListener)(void *data,
114                                  struct wl_registry *registry,
115                                  uint32_t id,
116                                  const QString &interface,
117                                  uint32_t version);
118 
119 class Q_WAYLAND_CLIENT_EXPORT QWaylandDisplay : public QObject, public QtWayland::wl_registry {
120     Q_OBJECT
121 
122 public:
123     struct FrameQueue {
queueFrameQueue124         FrameQueue(wl_event_queue *q = nullptr) : queue(q), mutex(new QMutex) {}
125         wl_event_queue *queue;
126         QMutex *mutex;
127     };
128 
129     QWaylandDisplay(QWaylandIntegration *waylandIntegration);
130     ~QWaylandDisplay(void) override;
131 
132 #if QT_CONFIG(xkbcommon)
xkbContext()133     struct xkb_context *xkbContext() const { return mXkbContext.get(); }
134 #endif
135 
screens()136     QList<QWaylandScreen *> screens() const { return mScreens; }
placeholderScreen()137     QPlatformPlaceholderScreen *placeholderScreen() const { return mPlaceholderScreen; }
138     void ensureScreen();
139 
140     QWaylandScreen *screenForOutput(struct wl_output *output) const;
141     void handleScreenInitialized(QWaylandScreen *screen);
142 
143     struct wl_surface *createSurface(void *handle);
144     struct ::wl_region *createRegion(const QRegion &qregion);
145     struct ::wl_subsurface *createSubSurface(QWaylandWindow *window, QWaylandWindow *parent);
146 
147     QWaylandShellIntegration *shellIntegration() const;
148     QWaylandClientBufferIntegration *clientBufferIntegration() const;
149     QWaylandWindowManagerIntegration *windowManagerIntegration() const;
150 
151 #if QT_CONFIG(cursor)
152     QWaylandCursor *waylandCursor();
153     QWaylandCursorTheme *loadCursorTheme(const QString &name, int pixelSize);
154 #endif
wl_display()155     struct wl_display *wl_display() const { return mDisplay; }
wl_registry()156     struct ::wl_registry *wl_registry() { return object(); }
157 
wl_compositor()158     const struct wl_compositor *wl_compositor() const { return mCompositor.object(); }
compositor()159     QtWayland::wl_compositor *compositor() { return &mCompositor; }
compositorVersion()160     int compositorVersion() const { return mCompositorVersion; }
161 
inputDevices()162     QList<QWaylandInputDevice *> inputDevices() const { return mInputDevices; }
163     QWaylandInputDevice *defaultInputDevice() const;
currentInputDevice()164     QWaylandInputDevice *currentInputDevice() const { return defaultInputDevice(); }
165 #if QT_CONFIG(wayland_datadevice)
dndSelectionHandler()166     QWaylandDataDeviceManager *dndSelectionHandler() const { return mDndSelectionHandler.data(); }
167 #endif
168 #if QT_CONFIG(wayland_client_primary_selection)
primarySelectionManager()169     QWaylandPrimarySelectionDeviceManagerV1 *primarySelectionManager() const { return mPrimarySelectionManager.data(); }
170 #endif
windowExtension()171     QtWayland::qt_surface_extension *windowExtension() const { return mWindowExtension.data(); }
tabletManager()172     QWaylandTabletManagerV2 *tabletManager() const { return mTabletManager.data(); }
touchExtension()173     QWaylandTouchExtension *touchExtension() const { return mTouchExtension.data(); }
textInputManager()174     QtWayland::zwp_text_input_manager_v2 *textInputManager() const { return mTextInputManager.data(); }
hardwareIntegration()175     QWaylandHardwareIntegration *hardwareIntegration() const { return mHardwareIntegration.data(); }
xdgOutputManager()176     QWaylandXdgOutputManagerV1 *xdgOutputManager() const { return mXdgOutputManager.data(); }
177 
178     struct RegistryGlobal {
179         uint32_t id;
180         QString interface;
181         uint32_t version;
182         struct ::wl_registry *registry = nullptr;
RegistryGlobalRegistryGlobal183         RegistryGlobal(uint32_t id_, const QString &interface_, uint32_t version_, struct ::wl_registry *registry_)
184             : id(id_), interface(interface_), version(version_), registry(registry_) { }
185     };
globals()186     QList<RegistryGlobal> globals() const { return mGlobals; }
187     bool hasRegistryGlobal(QStringView interfaceName) const;
188 
189     /* wl_registry_add_listener does not add but rather sets a listener, so this function is used
190      * to enable many listeners at once. */
191     void addRegistryListener(RegistryListener listener, void *data);
192     void removeListener(RegistryListener listener, void *data);
193 
shm()194     QWaylandShm *shm() const { return mShm.data(); }
195 
196     static uint32_t currentTimeMillisec();
197 
198     void forceRoundTrip();
199 
200     bool supportsWindowDecoration() const;
201 
lastInputSerial()202     uint32_t lastInputSerial() const { return mLastInputSerial; }
lastInputDevice()203     QWaylandInputDevice *lastInputDevice() const { return mLastInputDevice; }
204     QWaylandWindow *lastInputWindow() const;
205     void setLastInputDevice(QWaylandInputDevice *device, uint32_t serial, QWaylandWindow *window);
206 
207     bool isWindowActivated(const QWaylandWindow *window);
208     void handleWindowActivated(QWaylandWindow *window);
209     void handleWindowDeactivated(QWaylandWindow *window);
210     void handleKeyboardFocusChanged(QWaylandInputDevice *inputDevice);
211     void handleWindowDestroyed(QWaylandWindow *window);
212 
213     wl_event_queue *createEventQueue();
214     FrameQueue createFrameQueue();
215     void destroyFrameQueue(const FrameQueue &q);
216     void dispatchQueueWhile(wl_event_queue *queue, std::function<bool()> condition, int timeout = -1);
217 
218     bool isKeyboardAvailable() const;
219 public slots:
220     void blockingReadEvents();
221     void flushRequests();
222 
223 private:
224     void waitForScreens();
225     void checkError() const;
226 
227     void handleWaylandSync();
228     void requestWaylandSync();
229 
230     struct Listener {
231         Listener() = default;
ListenerListener232         Listener(RegistryListener incomingListener,
233                  void* incomingData)
234         : listener(incomingListener), data(incomingData)
235         {}
236         RegistryListener listener = nullptr;
237         void *data = nullptr;
238     };
239 
240     struct wl_display *mDisplay = nullptr;
241     QtWayland::wl_compositor mCompositor;
242     QScopedPointer<QWaylandShm> mShm;
243     QList<QWaylandScreen *> mWaitingScreens;
244     QList<QWaylandScreen *> mScreens;
245     QPlatformPlaceholderScreen *mPlaceholderScreen = nullptr;
246     QList<QWaylandInputDevice *> mInputDevices;
247     QList<Listener> mRegistryListeners;
248     QWaylandIntegration *mWaylandIntegration = nullptr;
249 #if QT_CONFIG(cursor)
250     QMap<std::pair<QString, int>, QWaylandCursorTheme *> mCursorThemes; // theme name and size
251     QScopedPointer<QWaylandCursor> mCursor;
252 #endif
253 #if QT_CONFIG(wayland_datadevice)
254     QScopedPointer<QWaylandDataDeviceManager> mDndSelectionHandler;
255 #endif
256     QScopedPointer<QtWayland::qt_surface_extension> mWindowExtension;
257     QScopedPointer<QtWayland::wl_subcompositor> mSubCompositor;
258     QScopedPointer<QWaylandTouchExtension> mTouchExtension;
259     QScopedPointer<QWaylandQtKeyExtension> mQtKeyExtension;
260     QScopedPointer<QWaylandWindowManagerIntegration> mWindowManagerIntegration;
261     QScopedPointer<QWaylandTabletManagerV2> mTabletManager;
262 #if QT_CONFIG(wayland_client_primary_selection)
263     QScopedPointer<QWaylandPrimarySelectionDeviceManagerV1> mPrimarySelectionManager;
264 #endif
265     QScopedPointer<QtWayland::zwp_text_input_manager_v2> mTextInputManager;
266     QScopedPointer<QWaylandHardwareIntegration> mHardwareIntegration;
267     QScopedPointer<QWaylandXdgOutputManagerV1> mXdgOutputManager;
268     QSocketNotifier *mReadNotifier = nullptr;
269     int mFd = -1;
270     int mWritableNotificationFd = -1;
271     QList<RegistryGlobal> mGlobals;
272     int mCompositorVersion = -1;
273     uint32_t mLastInputSerial = 0;
274     QWaylandInputDevice *mLastInputDevice = nullptr;
275     QPointer<QWaylandWindow> mLastInputWindow;
276     QPointer<QWaylandWindow> mLastKeyboardFocus;
277     QVector<QWaylandWindow *> mActiveWindows;
278     QVector<FrameQueue> mExternalQueues;
279     struct wl_callback *mSyncCallback = nullptr;
280     static const wl_callback_listener syncCallbackListener;
281     QReadWriteLock m_frameQueueLock;
282 
283     bool mClientSideInputContextRequested = !QPlatformInputContextFactory::requested().isNull();
284 
285     void registry_global(uint32_t id, const QString &interface, uint32_t version) override;
286     void registry_global_remove(uint32_t id) override;
287 
288 #if QT_CONFIG(xkbcommon)
289     QXkbCommon::ScopedXKBContext mXkbContext;
290 #endif
291 
292     friend class QWaylandIntegration;
293 };
294 
295 }
296 
297 QT_END_NAMESPACE
298 
299 #endif // QWAYLANDDISPLAY_H
300