diff options
Diffstat (limited to 'src/client/qwaylanddisplay_p.h')
-rw-r--r-- | src/client/qwaylanddisplay_p.h | 275 |
1 files changed, 188 insertions, 87 deletions
diff --git a/src/client/qwaylanddisplay_p.h b/src/client/qwaylanddisplay_p.h index 14bb77198..5b564c8d7 100644 --- a/src/client/qwaylanddisplay_p.h +++ b/src/client/qwaylanddisplay_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QWAYLANDDISPLAY_H #define QWAYLANDDISPLAY_H @@ -51,10 +15,12 @@ // We mean it. // +#include <QtCore/QList> #include <QtCore/QObject> -#include <QtCore/QRect> #include <QtCore/QPointer> -#include <QtCore/QVector> +#include <QtCore/QRect> +#include <QtCore/QMutex> +#include <QtCore/QReadWriteLock> #include <QtCore/QWaitCondition> #include <QtCore/QLoggingCategory> @@ -66,36 +32,51 @@ #include <qpa/qplatforminputcontextfactory_p.h> #if QT_CONFIG(xkbcommon) -#include <QtXkbCommonSupport/private/qxkbcommon_p.h> +#include <QtGui/private/qxkbcommon_p.h> #endif struct wl_cursor_image; +struct wp_viewport; QT_BEGIN_NAMESPACE +#define WAYLAND_IM_KEY "wayland" + class QAbstractEventDispatcher; class QSocketNotifier; class QPlatformScreen; +class QPlatformPlaceholderScreen; namespace QtWayland { class qt_surface_extension; + class zwp_text_input_manager_v1; class zwp_text_input_manager_v2; - class zxdg_output_manager_v1; + class zwp_text_input_manager_v3; + class qt_text_input_method_manager_v1; + class wp_cursor_shape_manager_v1; + class wp_fractional_scale_manager_v1; + class wp_viewporter; + class xdg_toplevel_drag_manager_v1; } namespace QtWaylandClient { -Q_WAYLAND_CLIENT_EXPORT Q_DECLARE_LOGGING_CATEGORY(lcQpaWayland); +Q_WAYLANDCLIENT_EXPORT Q_DECLARE_LOGGING_CATEGORY(lcQpaWayland); class QWaylandInputDevice; class QWaylandBuffer; class QWaylandScreen; +class QWaylandXdgOutputManagerV1; class QWaylandClientBufferIntegration; class QWaylandWindowManagerIntegration; class QWaylandDataDeviceManager; #if QT_CONFIG(wayland_client_primary_selection) class QWaylandPrimarySelectionDeviceManagerV1; #endif +#if QT_CONFIG(tabletevent) +class QWaylandTabletManagerV2; +#endif +class QWaylandPointerGestures; class QWaylandTouchExtension; class QWaylandQtKeyExtension; class QWaylandWindow; @@ -105,6 +86,7 @@ class QWaylandSurface; class QWaylandShellIntegration; class QWaylandCursor; class QWaylandCursorTheme; +class EventThread; typedef void (*RegistryListener)(void *data, struct wl_registry *registry, @@ -112,18 +94,22 @@ typedef void (*RegistryListener)(void *data, const QString &interface, uint32_t version); -class Q_WAYLAND_CLIENT_EXPORT QWaylandDisplay : public QObject, public QtWayland::wl_registry { +class Q_WAYLANDCLIENT_EXPORT QWaylandDisplay : public QObject, public QtWayland::wl_registry { Q_OBJECT public: QWaylandDisplay(QWaylandIntegration *waylandIntegration); ~QWaylandDisplay(void) override; + bool initialize(); + #if QT_CONFIG(xkbcommon) struct xkb_context *xkbContext() const { return mXkbContext.get(); } #endif QList<QWaylandScreen *> screens() const { return mScreens; } + QPlatformPlaceholderScreen *placeholderScreen() const { return mPlaceholderScreen; } + void ensureScreen(); QWaylandScreen *screenForOutput(struct wl_output *output) const; void handleScreenInitialized(QWaylandScreen *screen); @@ -131,6 +117,7 @@ public: struct wl_surface *createSurface(void *handle); struct ::wl_region *createRegion(const QRegion &qregion); struct ::wl_subsurface *createSubSurface(QWaylandWindow *window, QWaylandWindow *parent); + struct ::wp_viewport *createViewport(QWaylandWindow *window); QWaylandShellIntegration *shellIntegration() const; QWaylandClientBufferIntegration *clientBufferIntegration() const; @@ -140,29 +127,91 @@ public: QWaylandCursor *waylandCursor(); QWaylandCursorTheme *loadCursorTheme(const QString &name, int pixelSize); #endif - struct wl_display *wl_display() const { return mDisplay; } + struct wl_display *wl_display() const + { + return mDisplay; + } struct ::wl_registry *wl_registry() { return object(); } - const struct wl_compositor *wl_compositor() const { return mCompositor.object(); } - QtWayland::wl_compositor *compositor() { return &mCompositor; } - int compositorVersion() const { return mCompositorVersion; } + QtWayland::wl_compositor *compositor() + { + return mGlobals.compositor.get(); + } QList<QWaylandInputDevice *> inputDevices() const { return mInputDevices; } QWaylandInputDevice *defaultInputDevice() const; QWaylandInputDevice *currentInputDevice() const { return defaultInputDevice(); } #if QT_CONFIG(wayland_datadevice) - QWaylandDataDeviceManager *dndSelectionHandler() const { return mDndSelectionHandler.data(); } + QWaylandDataDeviceManager *dndSelectionHandler() const + { + return mGlobals.dndSelectionHandler.get(); + } #endif #if QT_CONFIG(wayland_client_primary_selection) - QWaylandPrimarySelectionDeviceManagerV1 *primarySelectionManager() const { return mPrimarySelectionManager.data(); } + QWaylandPrimarySelectionDeviceManagerV1 *primarySelectionManager() const + { + return mGlobals.primarySelectionManager.get(); + } +#endif + QtWayland::qt_surface_extension *windowExtension() const + { + return mGlobals.surfaceExtension.get(); + } +#if QT_CONFIG(tabletevent) + QWaylandTabletManagerV2 *tabletManager() const + { + return mGlobals.tabletManager.get(); + } #endif - QtWayland::qt_surface_extension *windowExtension() const { return mWindowExtension.data(); } - QWaylandTouchExtension *touchExtension() const { return mTouchExtension.data(); } - QtWayland::zwp_text_input_manager_v2 *textInputManager() const { return mTextInputManager.data(); } - QWaylandHardwareIntegration *hardwareIntegration() const { return mHardwareIntegration.data(); } - QtWayland::zxdg_output_manager_v1 *xdgOutputManager() const { return mXdgOutputManager.data(); } + QWaylandPointerGestures *pointerGestures() const + { + return mGlobals.pointerGestures.get(); + } + QWaylandTouchExtension *touchExtension() const + { + return mGlobals.touchExtension.get(); + } + QtWayland::qt_text_input_method_manager_v1 *textInputMethodManager() const + { + return mGlobals.textInputMethodManager.get(); + } + QtWayland::zwp_text_input_manager_v1 *textInputManagerv1() const + { + return mGlobals.textInputManagerv1.get(); + } + QtWayland::zwp_text_input_manager_v2 *textInputManagerv2() const + { + return mGlobals.textInputManagerv2.get(); + } + QtWayland::zwp_text_input_manager_v3 *textInputManagerv3() const + { + return mGlobals.textInputManagerv3.get(); + } + QWaylandHardwareIntegration *hardwareIntegration() const + { + return mGlobals.hardwareIntegration.get(); + } + QWaylandXdgOutputManagerV1 *xdgOutputManager() const + { + return mGlobals.xdgOutputManager.get(); + } + QtWayland::wp_fractional_scale_manager_v1 *fractionalScaleManager() const + { + return mGlobals.fractionalScaleManager.get(); + } + QtWayland::wp_viewporter *viewporter() const + { + return mGlobals.viewporter.get(); + } + QtWayland::wp_cursor_shape_manager_v1 *cursorShapeManager() const + { + return mGlobals.cursorShapeManager.get(); + } + QtWayland::xdg_toplevel_drag_manager_v1 *xdgToplevelDragManager() const + { + return mGlobals.xdgToplevelDragManager.get(); + } - bool usingInputContextFromCompositor() const { return mUsingInputContextFromCompositor; } struct RegistryGlobal { uint32_t id; @@ -172,7 +221,10 @@ public: RegistryGlobal(uint32_t id_, const QString &interface_, uint32_t version_, struct ::wl_registry *registry_) : id(id_), interface(interface_), version(version_), registry(registry_) { } }; - QList<RegistryGlobal> globals() const { return mGlobals; } + QList<RegistryGlobal> globals() const + { + return mRegistryGlobals; + } bool hasRegistryGlobal(QStringView interfaceName) const; /* wl_registry_add_listener does not add but rather sets a listener, so this function is used @@ -180,9 +232,10 @@ public: void addRegistryListener(RegistryListener listener, void *data); void removeListener(RegistryListener listener, void *data); - QWaylandShm *shm() const { return mShm.data(); } - - static uint32_t currentTimeMillisec(); + QWaylandShm *shm() const + { + return mGlobals.shm.get(); + } void forceRoundTrip(); @@ -199,20 +252,31 @@ public: void handleKeyboardFocusChanged(QWaylandInputDevice *inputDevice); void handleWindowDestroyed(QWaylandWindow *window); - wl_event_queue *createEventQueue(); - void dispatchQueueWhile(wl_event_queue *queue, std::function<bool()> condition, int timeout = -1); + wl_event_queue *frameEventQueue() { return m_frameEventQueue; }; + + bool isKeyboardAvailable() const; + bool isWaylandInputContextRequested() const; + + void initEventThread(); -public slots: +public Q_SLOTS: void blockingReadEvents(); void flushRequests(); -private: - void waitForScreens(); - void checkError() const; +Q_SIGNALS: + void connected(); + void globalAdded(const RegistryGlobal &global); + void globalRemoved(const RegistryGlobal &global); +private: + void checkWaylandError(); + void reconnect(); + void setupConnection(); void handleWaylandSync(); void requestWaylandSync(); + void checkTextInputProtocol(); + struct Listener { Listener() = default; Listener(RegistryListener incomingListener, @@ -222,48 +286,85 @@ private: RegistryListener listener = nullptr; void *data = nullptr; }; - struct wl_display *mDisplay = nullptr; - QtWayland::wl_compositor mCompositor; - QScopedPointer<QWaylandShm> mShm; + std::unique_ptr<EventThread> m_eventThread; + wl_event_queue *m_frameEventQueue = nullptr; + QScopedPointer<EventThread> m_frameEventQueueThread; QList<QWaylandScreen *> mWaitingScreens; QList<QWaylandScreen *> mScreens; + QPlatformPlaceholderScreen *mPlaceholderScreen = nullptr; QList<QWaylandInputDevice *> mInputDevices; QList<Listener> mRegistryListeners; QWaylandIntegration *mWaylandIntegration = nullptr; #if QT_CONFIG(cursor) - QMap<std::pair<QString, int>, QWaylandCursorTheme *> mCursorThemes; // theme name and size + struct WaylandCursorTheme { + QString name; + int pixelSize; + std::unique_ptr<QWaylandCursorTheme> theme; + }; + std::vector<WaylandCursorTheme> mCursorThemes; + + struct FindExistingCursorThemeResult { + std::vector<WaylandCursorTheme>::const_iterator position; + bool found; + + QWaylandCursorTheme *theme() const noexcept + { return found ? position->theme.get() : nullptr; } + }; + FindExistingCursorThemeResult findExistingCursorTheme(const QString &name, + int pixelSize) const noexcept; QScopedPointer<QWaylandCursor> mCursor; #endif + + QScopedPointer<QWaylandWindowManagerIntegration> mWindowManagerIntegration; + + struct GlobalHolder + { + std::unique_ptr<QtWayland::wl_compositor> compositor; + std::unique_ptr<QWaylandShm> shm; #if QT_CONFIG(wayland_datadevice) - QScopedPointer<QWaylandDataDeviceManager> mDndSelectionHandler; + std::unique_ptr<QWaylandDataDeviceManager> dndSelectionHandler; #endif - QScopedPointer<QtWayland::qt_surface_extension> mWindowExtension; - QScopedPointer<QtWayland::wl_subcompositor> mSubCompositor; - QScopedPointer<QWaylandTouchExtension> mTouchExtension; - QScopedPointer<QWaylandQtKeyExtension> mQtKeyExtension; - QScopedPointer<QWaylandWindowManagerIntegration> mWindowManagerIntegration; + std::unique_ptr<QtWayland::qt_surface_extension> surfaceExtension; + std::unique_ptr<QtWayland::wl_subcompositor> subCompositor; + std::unique_ptr<QWaylandTouchExtension> touchExtension; + std::unique_ptr<QWaylandQtKeyExtension> qtKeyExtension; +#if QT_CONFIG(tabletevent) + std::unique_ptr<QWaylandTabletManagerV2> tabletManager; +#endif + std::unique_ptr<QWaylandPointerGestures> pointerGestures; #if QT_CONFIG(wayland_client_primary_selection) - QScopedPointer<QWaylandPrimarySelectionDeviceManagerV1> mPrimarySelectionManager; + std::unique_ptr<QWaylandPrimarySelectionDeviceManagerV1> primarySelectionManager; #endif - QScopedPointer<QtWayland::zwp_text_input_manager_v2> mTextInputManager; - QScopedPointer<QWaylandHardwareIntegration> mHardwareIntegration; - QScopedPointer<QtWayland::zxdg_output_manager_v1> mXdgOutputManager; - QSocketNotifier *mReadNotifier = nullptr; + std::unique_ptr<QtWayland::qt_text_input_method_manager_v1> textInputMethodManager; + std::unique_ptr<QtWayland::zwp_text_input_manager_v1> textInputManagerv1; + std::unique_ptr<QtWayland::zwp_text_input_manager_v2> textInputManagerv2; + std::unique_ptr<QtWayland::zwp_text_input_manager_v3> textInputManagerv3; + std::unique_ptr<QWaylandHardwareIntegration> hardwareIntegration; + std::unique_ptr<QWaylandXdgOutputManagerV1> xdgOutputManager; + std::unique_ptr<QtWayland::wp_viewporter> viewporter; + std::unique_ptr<QtWayland::wp_fractional_scale_manager_v1> fractionalScaleManager; + std::unique_ptr<QtWayland::wp_cursor_shape_manager_v1> cursorShapeManager; + std::unique_ptr<QtWayland::xdg_toplevel_drag_manager_v1> xdgToplevelDragManager; + } mGlobals; int mFd = -1; int mWritableNotificationFd = -1; - QList<RegistryGlobal> mGlobals; - int mCompositorVersion = -1; + QList<RegistryGlobal> mRegistryGlobals; uint32_t mLastInputSerial = 0; QWaylandInputDevice *mLastInputDevice = nullptr; QPointer<QWaylandWindow> mLastInputWindow; QPointer<QWaylandWindow> mLastKeyboardFocus; - QVector<QWaylandWindow *> mActiveWindows; + QList<QWaylandWindow *> mActiveWindows; struct wl_callback *mSyncCallback = nullptr; static const wl_callback_listener syncCallbackListener; - - bool mClientSideInputContextRequested = !QPlatformInputContextFactory::requested().isNull(); - bool mUsingInputContextFromCompositor = false; + bool mWaylandTryReconnect = false; + + bool mWaylandInputContextRequested = [] () { + const auto requested = QPlatformInputContextFactory::requested(); + return requested.isEmpty() || requested.contains(QLatin1String(WAYLAND_IM_KEY)); + }(); + QStringList mTextInputManagerList; + int mTextInputManagerIndex = INT_MAX; void registry_global(uint32_t id, const QString &interface, uint32_t version) override; void registry_global_remove(uint32_t id) override; |