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