diff options
Diffstat (limited to 'src')
155 files changed, 6374 insertions, 3481 deletions
diff --git a/src/3rdparty/protocol/HPND_LICENSE.txt b/src/3rdparty/protocol/HPND_LICENSE.txt new file mode 100644 index 000000000..e7a4915da --- /dev/null +++ b/src/3rdparty/protocol/HPND_LICENSE.txt @@ -0,0 +1,20 @@ +Permission to use, copy, modify, distribute, and sell this +software and its documentation for any purpose is hereby granted +without fee, provided that the above copyright notice appear in +all copies and that both that copyright notice and this permission +notice appear in supporting documentation, and that the name of +the copyright holders not be used in advertising or publicity +pertaining to distribution of the software without specific, +written prior permission. The copyright holders make no +representations about the suitability of this software for any +purpose. It is provided "as is" without express or implied +warranty. + +THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN +AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. diff --git a/src/3rdparty/protocol/MIT_LICENSE.txt b/src/3rdparty/protocol/MIT_LICENSE.txt new file mode 100644 index 000000000..edc2e5fb5 --- /dev/null +++ b/src/3rdparty/protocol/MIT_LICENSE.txt @@ -0,0 +1,18 @@ +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/src/3rdparty/protocol/ivi-application.xml b/src/3rdparty/protocol/ivi-application.xml index 61ec7d273..8f2422688 100644 --- a/src/3rdparty/protocol/ivi-application.xml +++ b/src/3rdparty/protocol/ivi-application.xml @@ -5,23 +5,24 @@ Copyright (C) 2013 DENSO CORPORATION Copyright (c) 2013 BMW Car IT GmbH - Permission to use, copy, modify, distribute, and sell this software and - its documentation for any purpose is hereby granted without fee, provided - that the above copyright notice appear in all copies and that both that - copyright notice and this permission notice appear in supporting - documentation, and that the name of the copyright holders not be used in - advertising or publicity pertaining to distribution of the software - without specific, written prior permission. The copyright holders make - no representations about the suitability of this software for any - purpose. It is provided "as is" without express or implied warranty. - - THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER - RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF - CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice (including the next + paragraph) shall be included in all copies or substantial portions of the + Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. </copyright> <interface name="ivi_surface" version="1"> diff --git a/src/3rdparty/protocol/qt_attribution.json b/src/3rdparty/protocol/qt_attribution.json new file mode 100644 index 000000000..327c408b9 --- /dev/null +++ b/src/3rdparty/protocol/qt_attribution.json @@ -0,0 +1,70 @@ +[ + { + "Id": "wayland-protocol", + "Name": "Wayland Protocol", + "QDocModule": "qtwaylandcompositor", + "QtUsage": "Used in the Qt Wayland Compositor, and the Qt Wayland platform plugin.", + + "Description": "Wayland is a protocol for a compositor to talk to its clients.", + "Homepage": "https://wayland.freedesktop.org", + "Version": "1.6.1", + "DownloadLocation": "https://cgit.freedesktop.org/wayland/wayland/tag/?id=1.6.1", + "LicenseId": "HPND", + "License": "HPND License", + "LicenseFile": "HPND_LICENSE.txt", + "Copyright": "Copyright © 2008-2011 Kristian Høgsberg + Copyright © 2010-2011 Intel Corporation + Copyright © 2012-2013 Collabora, Ltd." + }, + + { + "Id": "wayland-ivi-extension-protocol", + "Name": "Wayland IVI Extension Protocol", + "QDocModule": "qtwaylandcompositor", + "QtUsage": "Used in the Qt Wayland Compositor, and the Qt Wayland platform plugin.", + + "Description": "\"Wayland IVI Extension\" is forked from IVI Layer Management to define a common set of APIs by wayland style protocol and provide reference implementation which can be loaded on Weston.", + "Homepage": "http://projects.genivi.org/wayland-ivi-extension", + "Version": "1.9.1", + "DownloadLocation": "http://git.projects.genivi.org/?p=wayland-ivi-extension.git;a=commit;h=44598504503eea5ac7f94c88477a5a78bda01f30", + "LicenseId": "MIT", + "License": "MIT License", + "LicenseFile": "MIT_LICENSE.txt", + "Copyright": "Copyright (C) 2013 DENSO CORPORATION +Copyright (c) 2013 BMW Car IT GmbH" + }, + + { + "Id": "wayland-xdg-shell-protocol", + "Name": "Wayland XDG Shell Protocol", + "QDocModule": "qtwaylandcompositor", + "QtUsage": "Used in the Qt Wayland Compositor, and the Qt Wayland platform plugin.", + + "Description": "The XDG-Shell protocol is an extended way to manage surfaces under Wayland compositors.", + "Homepage": "https://wayland.freedesktop.org", + "Version": "1.9.0", + "DownloadLocation": "https://cgit.freedesktop.org/wayland/weston/tag/?id=1.9.0", + "LicenseId": "MIT", + "License": "MIT License", + "LicenseFile": "MIT_LICENSE.txt", + "Copyright": "Copyright © 2008-2013 Kristian Høgsberg +Copyright © 2013 Rafael Antognolli +Copyright © 2013 Jasper St. Pierre +Copyright © 2010-2013 Intel Corporation" + }, + + { + "Id": "wayland-txt-input-unstable", + "Name": "Wayland Text Input Protocol", + "QDocModule": "qtwaylandcompositor", + "QtUsage": "Used in the Qt Wayland Compositor, and the Qt Wayland platform plugin.", + + "Description": "Adds support for text input and input methods to applications.", + "Homepage": "https://wayland.freedesktop.org", + "LicenseId": "HPND", + "License": "HPND License", + "LicenseFile": "HPND_LICENSE.txt", + "Copyright": "Copyright © 2012, 2013 Intel Corporation +Copyright © 2015, 2016 Jan Arne Petersen" + } +] diff --git a/src/3rdparty/protocol/xdg-shell.xml b/src/3rdparty/protocol/xdg-shell.xml index 44a3a12cb..f98e760d4 100644 --- a/src/3rdparty/protocol/xdg-shell.xml +++ b/src/3rdparty/protocol/xdg-shell.xml @@ -7,26 +7,24 @@ Copyright © 2013 Jasper St. Pierre Copyright © 2010-2013 Intel Corporation - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that copyright notice and this permission - notice appear in supporting documentation, and that the name of - the copyright holders not be used in advertising or publicity - pertaining to distribution of the software without specific, - written prior permission. The copyright holders make no - representations about the suitability of this software for any - purpose. It is provided "as is" without express or implied - warranty. - - THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, - ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF - THIS SOFTWARE. + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice (including the next + paragraph) shall be included in all copies or substantial portions of the + Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. </copyright> <interface name="xdg_shell" version="1"> @@ -248,10 +246,19 @@ Start an interactive, user-driven move of the surface. This request must be used in response to some sort of user action - like a button press, key press, or touch down event. + like a button press, key press, or touch down event. The passed + serial is used to determine the type of interactive move (touch, + pointer, etc). The server may ignore move requests depending on the state of - the surface (e.g. fullscreen or maximized). + the surface (e.g. fullscreen or maximized), or if the passed serial + is no longer valid. + + If triggered, the surface will lose the focus of the device + (wl_pointer, wl_touch, etc) used for the move. It is up to the + compositor to visually indicate that the move is taking place, such as + updating a pointer cursor, during the move. There is no guarantee + that the device focus will return when the move is completed. </description> <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/> <arg name="serial" type="uint" summary="the serial of the user event"/> @@ -260,9 +267,7 @@ <enum name="resize_edge"> <description summary="edge values for resizing"> These values are used to indicate which edge of a surface - is being dragged in a resize operation. The server may - use this information to adapt its behavior, e.g. choose - an appropriate cursor image. + is being dragged in a resize operation. </description> <entry name="none" value="0"/> <entry name="top" value="1"/> @@ -280,10 +285,33 @@ Start a user-driven, interactive resize of the surface. This request must be used in response to some sort of user action - like a button press, key press, or touch down event. + like a button press, key press, or touch down event. The passed + serial is used to determine the type of interactive resize (touch, + pointer, etc). The server may ignore resize requests depending on the state of the surface (e.g. fullscreen or maximized). + + If triggered, the client will receive configure events with the + "resize" state enum value and the expected sizes. See the "resize" + enum value for more details about what is required. The client + must also acknowledge configure events using "ack_configure". After + the resize is completed, the client will receive another "configure" + event without the resize state. + + If triggered, the surface also will lose the focus of the device + (wl_pointer, wl_touch, etc) used for the resize. It is up to the + compositor to visually indicate that the resize is taking place, + such as updating a pointer cursor, during the resize. There is no + guarantee that the device focus will return when the resize is + completed. + + The edges parameter specifies how the surface should be resized, + and is one of the values of the resize_edge enum. The compositor + may use this information to update the surface position for + example when dragging the top left corner. The compositor may also + use this information to adapt its behavior, e.g. choose an + appropriate cursor image. </description> <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/> <arg name="serial" type="uint" summary="the serial of the user event"/> diff --git a/src/client/client.pro b/src/client/client.pro index 8be00c7ac..34955dfbb 100644 --- a/src/client/client.pro +++ b/src/client/client.pro @@ -2,15 +2,20 @@ TARGET = QtWaylandClient MODULE = waylandclient QT += core-private gui-private -QT_FOR_PRIVATE += platformsupport-private +QT_FOR_PRIVATE += service_support-private +QT_PRIVATE += fontdatabase_support-private eventdispatcher_support-private theme_support-private # We have a bunch of C code with casts, so we can't have this option QMAKE_CXXFLAGS_WARN_ON -= -Wcast-qual +# Prevent gold linker from crashing. +# This started happening when QtPlatformSupport was modularized. +use_gold_linker: CONFIG += no_linker_version_script + CONFIG -= precompile_header -CONFIG += link_pkgconfig qpa/genericunixfontdatabase wayland-scanner +CONFIG += link_pkgconfig wayland-scanner -!equals(QT_WAYLAND_GL_CONFIG, nogl) { +contains(QT_CONFIG, opengl) { DEFINES += QT_WAYLAND_GL_SUPPORT } @@ -38,7 +43,7 @@ WAYLANDCLIENTSOURCES += \ ../extensions/surface-extension.xml \ ../extensions/touch-extension.xml \ ../extensions/qtkey-extension.xml \ - ../extensions/windowmanager.xml \ + ../extensions/qt-windowmanager.xml \ ../3rdparty/protocol/text-input-unstable-v2.xml \ ../3rdparty/protocol/xdg-shell.xml \ @@ -116,7 +121,7 @@ HEADERS += qwaylandintegration_p.h \ ../shared/qwaylandinputmethodeventbuilder_p.h \ ../shared/qwaylandmimehelper_p.h \ ../shared/qwaylandxkb_p.h \ - ../shared/qwaylandshmformathelper_p.h + ../shared/qwaylandsharedmemoryformathelper_p.h include(hardwareintegration/hardwareintegration.pri) include(shellintegration/shellintegration.pri) diff --git a/src/client/global/qwaylandclientextension.cpp b/src/client/global/qwaylandclientextension.cpp index 04aca8c2e..8e46197f1 100644 --- a/src/client/global/qwaylandclientextension.cpp +++ b/src/client/global/qwaylandclientextension.cpp @@ -40,6 +40,8 @@ #include <QtWaylandClient/private/qwaylandintegration_p.h> #include <QtGui/QGuiApplication> #include <QtGui/qpa/qplatformnativeinterface.h> +#include <QtGui/private/qguiapplication_p.h> +#include <QtCore/QDebug> QT_BEGIN_NAMESPACE @@ -51,35 +53,40 @@ QWaylandClientExtensionPrivate::QWaylandClientExtensionPrivate() { // Keep the possibility to use a custom waylandIntegration as a plugin, // but also add the possibility to run it as a QML component. - struct ::wl_display *waylandDisplay = NULL; - if (QGuiApplication::platformNativeInterface()) { - waylandDisplay = static_cast<struct ::wl_display*>(QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("wl_display")); - } else { + waylandIntegration = static_cast<QtWaylandClient::QWaylandIntegration *>(QGuiApplicationPrivate::platformIntegration()); + if (!waylandIntegration) waylandIntegration = new QtWaylandClient::QWaylandIntegration(); - waylandDisplay = waylandIntegration->display()->wl_display(); - } - Q_ASSERT(waylandDisplay); - struct ::wl_registry *registry = wl_display_get_registry(waylandDisplay); - QtWayland::wl_registry::init(registry); + if (!waylandIntegration->nativeInterface()->nativeResourceForIntegration("wl_display")) + qWarning() << "This application requires a Wayland platform plugin"; } -void QWaylandClientExtensionPrivate::registry_global(uint32_t id, const QString &interfaceName, uint32_t ver) +void QWaylandClientExtensionPrivate::handleRegistryGlobal(void *data, ::wl_registry *registry, uint32_t id, + const QString &interface, uint32_t version) { - Q_Q(QWaylandClientExtension); - if (interfaceName == QLatin1String(q->extensionInterface()->name)) { - struct ::wl_registry *registry = static_cast<struct ::wl_registry *>(QtWayland::wl_registry::object()); - q->bind(registry, id, ver); - active = true; - emit q->activeChanged(); + QWaylandClientExtension *extension = static_cast<QWaylandClientExtension *>(data); + if (interface == QLatin1String(extension->extensionInterface()->name) && !extension->d_func()->active) { + extension->bind(registry, id, version); + extension->d_func()->active = true; + emit extension->activeChanged(); } } +void QWaylandClientExtension::addRegistryListener() +{ + Q_D(QWaylandClientExtension); + d->waylandIntegration->display()->addRegistryListener(&QWaylandClientExtensionPrivate::handleRegistryGlobal, this); +} + QWaylandClientExtension::QWaylandClientExtension(const int ver) : QObject(*new QWaylandClientExtensionPrivate()) { Q_D(QWaylandClientExtension); d->version = ver; + + // The registry listener uses virtual functions and we don't want it to be called from + // the constructor. + QMetaObject::invokeMethod(this, "addRegistryListener", Qt::QueuedConnection); } QtWaylandClient::QWaylandIntegration *QWaylandClientExtension::integration() const diff --git a/src/client/global/qwaylandclientextension.h b/src/client/global/qwaylandclientextension.h index afb3f868f..d1610c271 100644 --- a/src/client/global/qwaylandclientextension.h +++ b/src/client/global/qwaylandclientextension.h @@ -71,6 +71,9 @@ protected: Q_SIGNALS: void versionChanged(); void activeChanged(); + +private Q_SLOTS: + void addRegistryListener(); }; template <typename T> diff --git a/src/client/global/qwaylandclientextension_p.h b/src/client/global/qwaylandclientextension_p.h index 70cf36c3d..7c88161fa 100644 --- a/src/client/global/qwaylandclientextension_p.h +++ b/src/client/global/qwaylandclientextension_p.h @@ -48,25 +48,23 @@ // We mean it. // -#include "qwaylandclientextension.h" #include <QtCore/private/qobject_p.h> +#include <QtWaylandClient/QWaylandClientExtension> #include <QtWaylandClient/private/qwaylandintegration_p.h> -#include <QtWaylandClient/private/qwayland-wayland.h> QT_BEGIN_NAMESPACE -class Q_WAYLAND_CLIENT_EXPORT QWaylandClientExtensionPrivate : public QObjectPrivate, public QtWayland::wl_registry +class Q_WAYLAND_CLIENT_EXPORT QWaylandClientExtensionPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QWaylandClientExtension) public: QWaylandClientExtensionPrivate(); + static void handleRegistryGlobal(void *data, ::wl_registry *registry, uint32_t id, + const QString &interface, uint32_t version); QtWaylandClient::QWaylandIntegration *waylandIntegration; int version; bool active; - -protected: - void registry_global(uint32_t id, const QString &interfaceName, uint32_t version) Q_DECL_OVERRIDE; }; class Q_WAYLAND_CLIENT_EXPORT QWaylandClientExtensionTemplatePrivate : public QWaylandClientExtensionPrivate diff --git a/src/client/qwaylanddatadevice.cpp b/src/client/qwaylanddatadevice.cpp index 7deb32609..f1a1ba6f0 100644 --- a/src/client/qwaylanddatadevice.cpp +++ b/src/client/qwaylanddatadevice.cpp @@ -185,7 +185,8 @@ void QWaylandDataDevice::data_device_enter(uint32_t serial, wl_surface *surface, void QWaylandDataDevice::data_device_leave() { - QWindowSystemInterface::handleDrag(m_dragWindow, 0, QPoint(), Qt::IgnoreAction); + if (m_dragWindow) + QWindowSystemInterface::handleDrag(m_dragWindow, 0, QPoint(), Qt::IgnoreAction); QDrag *drag = static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->currentDrag(); if (!drag) { diff --git a/src/client/qwaylanddatadevice_p.h b/src/client/qwaylanddatadevice_p.h index df0f297bc..318636de7 100644 --- a/src/client/qwaylanddatadevice_p.h +++ b/src/client/qwaylanddatadevice_p.h @@ -53,6 +53,7 @@ // #include <QObject> +#include <QPointer> #include <QPoint> #include <QtWaylandClient/private/qwayland-wayland.h> @@ -108,7 +109,7 @@ private: QWaylandDisplay *m_display; QWaylandInputDevice *m_inputDevice; uint32_t m_enterSerial; - QWindow *m_dragWindow; + QPointer<QWindow> m_dragWindow; QPoint m_dragPoint; QScopedPointer<QWaylandDataOffer> m_dragOffer; QScopedPointer<QWaylandDataOffer> m_selectionOffer; diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp index b83bd39e2..5f2c4e2ea 100644 --- a/src/client/qwaylanddisplay.cpp +++ b/src/client/qwaylanddisplay.cpp @@ -84,7 +84,8 @@ struct wl_surface *QWaylandDisplay::createSurface(void *handle) QWaylandShellSurface *QWaylandDisplay::createShellSurface(QWaylandWindow *window) { - Q_ASSERT(mWaylandIntegration->shellIntegration()); + if (!mWaylandIntegration->shellIntegration()) + return 0; return mWaylandIntegration->shellIntegration()->createShellSurface(window); } diff --git a/src/client/qwaylandintegration.cpp b/src/client/qwaylandintegration.cpp index 147e45b0c..32b4b8953 100644 --- a/src/client/qwaylandintegration.cpp +++ b/src/client/qwaylandintegration.cpp @@ -50,9 +50,9 @@ #include "qwaylandwindowmanagerintegration_p.h" #include "qwaylandscreen_p.h" -#include "QtPlatformSupport/private/qgenericunixfontdatabase_p.h" -#include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h> -#include <QtPlatformSupport/private/qgenericunixthemes_p.h> +#include <QtFontDatabaseSupport/private/qgenericunixfontdatabase_p.h> +#include <QtEventDispatcherSupport/private/qgenericunixeventdispatcher_p.h> +#include <QtThemeSupport/private/qgenericunixthemes_p.h> #include <QtGui/private/qguiapplication_p.h> @@ -119,7 +119,6 @@ public: QWaylandIntegration::QWaylandIntegration() : mClientBufferIntegration(0) - , mShellIntegration(Q_NULLPTR) , mInputDeviceIntegration(Q_NULLPTR) , mFontDb(new QGenericUnixFontDatabase()) , mNativeInterface(new QWaylandNativeInterface(this)) @@ -131,17 +130,17 @@ QWaylandIntegration::QWaylandIntegration() , mShellIntegrationInitialized(false) { initializeInputDeviceIntegration(); - mDisplay = new QWaylandDisplay(this); + mDisplay.reset(new QWaylandDisplay(this)); #ifndef QT_NO_DRAGANDDROP - mClipboard = new QWaylandClipboard(mDisplay); - mDrag = new QWaylandDrag(mDisplay); + mClipboard.reset(new QWaylandClipboard(mDisplay.data())); + mDrag.reset(new QWaylandDrag(mDisplay.data())); #endif QString icStr = QPlatformInputContextFactory::requested(); if (!icStr.isNull()) { mInputContext.reset(QPlatformInputContextFactory::create(icStr)); } else { //try to use the input context using the wl_text_input interface - QPlatformInputContext *ctx = new QWaylandInputContext(mDisplay); + QPlatformInputContext *ctx = new QWaylandInputContext(mDisplay.data()); mInputContext.reset(ctx); //use the traditional way for on screen keyboards for now @@ -154,20 +153,11 @@ QWaylandIntegration::QWaylandIntegration() QWaylandIntegration::~QWaylandIntegration() { -#ifndef QT_NO_DRAGANDDROP - delete mDrag; - delete mClipboard; -#endif -#ifndef QT_NO_ACCESSIBILITY - delete mAccessibility; -#endif - delete mNativeInterface; - delete mDisplay; } QPlatformNativeInterface * QWaylandIntegration::nativeInterface() const { - return mNativeInterface; + return mNativeInterface.data(); } bool QWaylandIntegration::hasCapability(QPlatformIntegration::Capability cap) const @@ -220,28 +210,28 @@ QAbstractEventDispatcher *QWaylandIntegration::createEventDispatcher() const void QWaylandIntegration::initialize() { QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::eventDispatcher; - QObject::connect(dispatcher, SIGNAL(aboutToBlock()), mDisplay, SLOT(flushRequests())); - QObject::connect(dispatcher, SIGNAL(awake()), mDisplay, SLOT(flushRequests())); + QObject::connect(dispatcher, SIGNAL(aboutToBlock()), mDisplay.data(), SLOT(flushRequests())); + QObject::connect(dispatcher, SIGNAL(awake()), mDisplay.data(), SLOT(flushRequests())); int fd = wl_display_get_fd(mDisplay->wl_display()); - QSocketNotifier *sn = new QSocketNotifier(fd, QSocketNotifier::Read, mDisplay); - QObject::connect(sn, SIGNAL(activated(int)), mDisplay, SLOT(flushRequests())); + QSocketNotifier *sn = new QSocketNotifier(fd, QSocketNotifier::Read, mDisplay.data()); + QObject::connect(sn, SIGNAL(activated(int)), mDisplay.data(), SLOT(flushRequests())); } QPlatformFontDatabase *QWaylandIntegration::fontDatabase() const { - return mFontDb; + return mFontDb.data(); } #ifndef QT_NO_DRAGANDDROP QPlatformClipboard *QWaylandIntegration::clipboard() const { - return mClipboard; + return mClipboard.data(); } QPlatformDrag *QWaylandIntegration::drag() const { - return mDrag; + return mDrag.data(); } #endif // QT_NO_DRAGANDDROP @@ -268,7 +258,7 @@ QVariant QWaylandIntegration::styleHint(StyleHint hint) const #ifndef QT_NO_ACCESSIBILITY QPlatformAccessibility *QWaylandIntegration::accessibility() const { - return mAccessibility; + return mAccessibility.data(); } #endif @@ -279,7 +269,7 @@ QPlatformServices *QWaylandIntegration::services() const QWaylandDisplay *QWaylandIntegration::display() const { - return mDisplay; + return mDisplay.data(); } QStringList QWaylandIntegration::themeNames() const @@ -297,7 +287,7 @@ QWaylandClientBufferIntegration *QWaylandIntegration::clientBufferIntegration() if (!mClientBufferIntegrationInitialized) const_cast<QWaylandIntegration *>(this)->initializeClientBufferIntegration(); - return mClientBufferIntegration && mClientBufferIntegration->isValid() ? mClientBufferIntegration : 0; + return mClientBufferIntegration && mClientBufferIntegration->isValid() ? mClientBufferIntegration.data() : nullptr; } QWaylandServerBufferIntegration *QWaylandIntegration::serverBufferIntegration() const @@ -305,7 +295,7 @@ QWaylandServerBufferIntegration *QWaylandIntegration::serverBufferIntegration() if (!mServerBufferIntegrationInitialized) const_cast<QWaylandIntegration *>(this)->initializeServerBufferIntegration(); - return mServerBufferIntegration; + return mServerBufferIntegration.data(); } QWaylandShellIntegration *QWaylandIntegration::shellIntegration() const @@ -313,7 +303,7 @@ QWaylandShellIntegration *QWaylandIntegration::shellIntegration() const if (!mShellIntegrationInitialized) const_cast<QWaylandIntegration *>(this)->initializeShellIntegration(); - return mShellIntegration; + return mShellIntegration.data(); } void QWaylandIntegration::initializeClientBufferIntegration() @@ -339,10 +329,10 @@ void QWaylandIntegration::initializeClientBufferIntegration() QStringList keys = QWaylandClientBufferIntegrationFactory::keys(); if (keys.contains(targetKey)) { - mClientBufferIntegration = QWaylandClientBufferIntegrationFactory::create(targetKey, QStringList()); + mClientBufferIntegration.reset(QWaylandClientBufferIntegrationFactory::create(targetKey, QStringList())); } if (mClientBufferIntegration) - mClientBufferIntegration->initialize(mDisplay); + mClientBufferIntegration->initialize(mDisplay.data()); else qWarning("Failed to load client buffer integration: %s\n", qPrintable(targetKey)); } @@ -369,10 +359,10 @@ void QWaylandIntegration::initializeServerBufferIntegration() QStringList keys = QWaylandServerBufferIntegrationFactory::keys(); if (keys.contains(targetKey)) { - mServerBufferIntegration = QWaylandServerBufferIntegrationFactory::create(targetKey, QStringList()); + mServerBufferIntegration.reset(QWaylandServerBufferIntegrationFactory::create(targetKey, QStringList())); } if (mServerBufferIntegration) - mServerBufferIntegration->initialize(mDisplay); + mServerBufferIntegration->initialize(mDisplay.data()); else qWarning("Failed to load server buffer integration %s\n", qPrintable(targetKey)); } @@ -388,7 +378,7 @@ void QWaylandIntegration::initializeShellIntegration() QStringList keys = QWaylandShellIntegrationFactory::keys(); if (keys.contains(targetKey)) { qDebug("Using the '%s' shell integration", qPrintable(targetKey)); - mShellIntegration = QWaylandShellIntegrationFactory::create(targetKey, QStringList()); + mShellIntegration.reset(QWaylandShellIntegrationFactory::create(targetKey, QStringList())); } } else { QStringList preferredShells; @@ -398,17 +388,14 @@ void QWaylandIntegration::initializeShellIntegration() Q_FOREACH (QString preferredShell, preferredShells) { if (mDisplay->hasRegistryGlobal(preferredShell)) { - mShellIntegration = createShellIntegration(preferredShell); + mShellIntegration.reset(createShellIntegration(preferredShell)); break; } } } - Q_ASSERT(mShellIntegration); - - if (!mShellIntegration->initialize(mDisplay)) { - delete mShellIntegration; - mShellIntegration = Q_NULLPTR; + if (!mShellIntegration || !mShellIntegration->initialize(mDisplay.data())) { + mShellIntegration.reset(); qWarning("Failed to load shell integration %s", qPrintable(targetKey)); } } @@ -432,7 +419,7 @@ void QWaylandIntegration::initializeInputDeviceIntegration() QStringList keys = QWaylandInputDeviceIntegrationFactory::keys(); if (keys.contains(targetKey)) { - mInputDeviceIntegration = QWaylandInputDeviceIntegrationFactory::create(targetKey, QStringList()); + mInputDeviceIntegration.reset(QWaylandInputDeviceIntegrationFactory::create(targetKey, QStringList())); qDebug("Using the '%s' input device integration", qPrintable(targetKey)); } else { qWarning("Wayland inputdevice integration '%s' not found, using default", qPrintable(targetKey)); @@ -442,9 +429,9 @@ void QWaylandIntegration::initializeInputDeviceIntegration() QWaylandShellIntegration *QWaylandIntegration::createShellIntegration(const QString &interfaceName) { if (interfaceName == QLatin1Literal("wl_shell")) { - return new QWaylandWlShellIntegration(mDisplay); + return new QWaylandWlShellIntegration(mDisplay.data()); } else if (interfaceName == QLatin1Literal("xdg_shell")) { - return new QWaylandXdgShellIntegration(mDisplay); + return new QWaylandXdgShellIntegration(mDisplay.data()); } else { return Q_NULLPTR; } diff --git a/src/client/qwaylandintegration_p.h b/src/client/qwaylandintegration_p.h index 4f5e651d2..3b91313b5 100644 --- a/src/client/qwaylandintegration_p.h +++ b/src/client/qwaylandintegration_p.h @@ -54,6 +54,8 @@ #include <qpa/qplatformintegration.h> #include <QtWaylandClient/qwaylandclientexport.h> +#include <QtCore/QScopedPointer> + QT_BEGIN_NAMESPACE namespace QtWaylandClient { @@ -112,10 +114,10 @@ public: virtual QWaylandShellIntegration *shellIntegration() const; protected: - QWaylandClientBufferIntegration *mClientBufferIntegration; - QWaylandServerBufferIntegration *mServerBufferIntegration; - QWaylandShellIntegration *mShellIntegration; - QWaylandInputDeviceIntegration *mInputDeviceIntegration; + QScopedPointer<QWaylandClientBufferIntegration> mClientBufferIntegration; + QScopedPointer<QWaylandServerBufferIntegration> mServerBufferIntegration; + QScopedPointer<QWaylandShellIntegration> mShellIntegration; + QScopedPointer<QWaylandInputDeviceIntegration> mInputDeviceIntegration; private: void initializeClientBufferIntegration(); @@ -124,16 +126,16 @@ private: void initializeInputDeviceIntegration(); QWaylandShellIntegration *createShellIntegration(const QString& interfaceName); - QPlatformFontDatabase *mFontDb; + QScopedPointer<QPlatformFontDatabase> mFontDb; #ifndef QT_NO_DRAGANDDROP - QPlatformClipboard *mClipboard; - QPlatformDrag *mDrag; + QScopedPointer<QPlatformClipboard> mClipboard; + QScopedPointer<QPlatformDrag> mDrag; #endif - QWaylandDisplay *mDisplay; - QPlatformNativeInterface *mNativeInterface; + QScopedPointer<QWaylandDisplay> mDisplay; + QScopedPointer<QPlatformNativeInterface> mNativeInterface; QScopedPointer<QPlatformInputContext> mInputContext; #ifndef QT_NO_ACCESSIBILITY - QPlatformAccessibility *mAccessibility; + QScopedPointer<QPlatformAccessibility> mAccessibility; #endif bool mClientBufferIntegrationInitialized; bool mServerBufferIntegrationInitialized; diff --git a/src/client/qwaylandnativeinterface.cpp b/src/client/qwaylandnativeinterface.cpp index 2c87bb9f6..52c61eec1 100644 --- a/src/client/qwaylandnativeinterface.cpp +++ b/src/client/qwaylandnativeinterface.cpp @@ -76,7 +76,7 @@ void *QWaylandNativeInterface::nativeResourceForIntegration(const QByteArray &re if (lowerCaseResource == "egldisplay" && m_integration->clientBufferIntegration()) return m_integration->clientBufferIntegration()->nativeResource(QWaylandClientBufferIntegration::EglDisplay); - return 0; + return nullptr; } void *QWaylandNativeInterface::nativeResourceForWindow(const QByteArray &resourceString, QWindow *window) @@ -88,21 +88,22 @@ void *QWaylandNativeInterface::nativeResourceForWindow(const QByteArray &resourc if (lowerCaseResource == "compositor") return const_cast<wl_compositor *>(m_integration->display()->wl_compositor()); if (lowerCaseResource == "surface") { - return ((QWaylandWindow *) window->handle())->object(); + QWaylandWindow *w = static_cast<QWaylandWindow*>(window->handle()); + return w ? w->object() : nullptr; } if (lowerCaseResource == "wl_shell_surface") { - QWaylandWindow *w = (QWaylandWindow *) window->handle(); + QWaylandWindow *w = static_cast<QWaylandWindow*>(window->handle()); if (!w) - return NULL; + return nullptr; QWaylandWlShellSurface *s = qobject_cast<QWaylandWlShellSurface *>(w->shellSurface()); if (!s) - return NULL; + return nullptr; return s->object(); } if (lowerCaseResource == "egldisplay" && m_integration->clientBufferIntegration()) return m_integration->clientBufferIntegration()->nativeResource(QWaylandClientBufferIntegration::EglDisplay); - return NULL; + return nullptr; } void *QWaylandNativeInterface::nativeResourceForScreen(const QByteArray &resourceString, QScreen *screen) @@ -112,12 +113,13 @@ void *QWaylandNativeInterface::nativeResourceForScreen(const QByteArray &resourc if (lowerCaseResource == "output") return ((QWaylandScreen *) screen->handle())->output(); - return NULL; + return nullptr; } #ifndef QT_NO_OPENGL void *QWaylandNativeInterface::nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context) { +#ifdef QT_WAYLAND_GL_SUPPORT QByteArray lowerCaseResource = resource.toLower(); if (lowerCaseResource == "eglconfig" && m_integration->clientBufferIntegration()) @@ -128,8 +130,9 @@ void *QWaylandNativeInterface::nativeResourceForContext(const QByteArray &resour if (lowerCaseResource == "egldisplay" && m_integration->clientBufferIntegration()) return m_integration->clientBufferIntegration()->nativeResourceForContext(QWaylandClientBufferIntegration::EglDisplay, context->handle()); +#endif - return 0; + return nullptr; } #endif // QT_NO_OPENGL @@ -171,7 +174,7 @@ QFunctionPointer QWaylandNativeInterface::platformFunction(const QByteArray &res } else if (resource == QWaylandWindowFunctions::isSyncIdentifier()) { return QFunctionPointer(isSync); } - return 0; + return nullptr; } diff --git a/src/client/qwaylandshm.cpp b/src/client/qwaylandshm.cpp index 790a0e1b9..e94357bb5 100644 --- a/src/client/qwaylandshm.cpp +++ b/src/client/qwaylandshm.cpp @@ -39,7 +39,7 @@ #include <QtWaylandClient/private/qwaylandshm_p.h> #include <QtWaylandClient/private/qwaylanddisplay_p.h> -#include "qwaylandshmformathelper_p.h" +#include "qwaylandsharedmemoryformathelper_p.h" QT_BEGIN_NAMESPACE @@ -73,12 +73,12 @@ bool QWaylandShm::formatSupported(QImage::Format format) const wl_shm_format QWaylandShm::formatFrom(QImage::Format format) { - return QWaylandShmFormatHelper::fromQImageFormat(format); + return QWaylandSharedMemoryFormatHelper::fromQImageFormat(format); } QImage::Format QWaylandShm::formatFrom(wl_shm_format format) { - return QWaylandShmFormatHelper::fromWaylandShmFormat(format); + return QWaylandSharedMemoryFormatHelper::fromWaylandShmFormat(format); } } diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp index 01a0d48bb..6b9dde7c7 100644 --- a/src/client/qwaylandwindow.cpp +++ b/src/client/qwaylandwindow.cpp @@ -83,7 +83,7 @@ QWaylandWindow::QWaylandWindow(QWindow *window) , mMousePressedInContentArea(Qt::NoButton) , m_cursor(Qt::ArrowCursor) , mWaitingForFrameSync(false) - , mFrameCallback(0) + , mFrameCallback(nullptr) , mRequestResizeSent(false) , mCanResize(true) , mResizeDirty(false) @@ -198,6 +198,7 @@ void QWaylandWindow::initWindow() setMask(window()->mask()); setWindowStateInternal(window()->windowState()); handleContentOrientationChange(window()->contentOrientation()); + mFlags = window()->flags(); } bool QWaylandWindow::shouldCreateShellSurface() const @@ -456,14 +457,12 @@ void QWaylandWindow::requestResize() void QWaylandWindow::attach(QWaylandBuffer *buffer, int x, int y) { - if (mFrameCallback) { - wl_callback_destroy(mFrameCallback); - mFrameCallback = 0; - } + mFrameCallback = nullptr; if (buffer) { - mFrameCallback = frame(); - wl_callback_add_listener(mFrameCallback, &QWaylandWindow::callbackListener, this); + auto callback = frame(); + wl_callback_add_listener(callback, &QWaylandWindow::callbackListener, this); + mFrameCallback = callback; mWaitingForFrameSync = true; attach(buffer->buffer(), x, y); @@ -494,11 +493,11 @@ void QWaylandWindow::frameCallback(void *data, struct wl_callback *callback, uin self->mWaitingForFrameSync = false; wl_callback_destroy(callback); - self->mFrameCallback = 0; + self->mFrameCallback.testAndSetRelaxed(callback, nullptr); if (self->mUpdateRequested) { QWindowPrivate *w = QWindowPrivate::get(self->window()); - w->deliverUpdateRequest(); self->mUpdateRequested = false; + w->deliverUpdateRequest(); } } @@ -583,6 +582,9 @@ void QWaylandWindow::setWindowFlags(Qt::WindowFlags flags) { if (mShellSurface) mShellSurface->setWindowFlags(flags); + + mFlags = flags; + createDecoration(); } bool QWaylandWindow::createDecoration() @@ -617,9 +619,9 @@ bool QWaylandWindow::createDecoration() default: break; } - if (window()->flags() & Qt::FramelessWindowHint || isFullscreen()) + if (mFlags & Qt::FramelessWindowHint || isFullscreen()) decoration = false; - if (window()->flags() & Qt::BypassWindowManagerHint) + if (mFlags & Qt::BypassWindowManagerHint) decoration = false; if (mSubSurfaceWindow) decoration = false; @@ -667,8 +669,7 @@ bool QWaylandWindow::createDecoration() QMargins m = frameMargins(); subsurf->set_position(pos.x() + m.left(), pos.y() + m.top()); } - if (!mChildren.isEmpty()) - window()->requestUpdate(); + QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size())); } return mWindowDecoration; diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h index 82898152c..e0c42ace5 100644 --- a/src/client/qwaylandwindow_p.h +++ b/src/client/qwaylandwindow_p.h @@ -53,6 +53,7 @@ #include <QtCore/QWaitCondition> #include <QtCore/QMutex> +#include <QtCore/QAtomicPointer> #include <QtGui/QIcon> #include <QtCore/QVariant> @@ -220,7 +221,7 @@ protected: WId mWindowId; bool mWaitingForFrameSync; - struct wl_callback *mFrameCallback; + QAtomicPointer<struct wl_callback> mFrameCallback; QWaitCondition mFrameSyncWait; QMutex mResizeLock; @@ -237,6 +238,7 @@ protected: QIcon mWindowIcon; Qt::WindowState mState; + Qt::WindowFlags mFlags; QRegion mMask; QWaylandShmBackingStore *mBackingStore; diff --git a/src/client/qwaylandwindowmanagerintegration_p.h b/src/client/qwaylandwindowmanagerintegration_p.h index f0c7ced6d..09a79d48d 100644 --- a/src/client/qwaylandwindowmanagerintegration_p.h +++ b/src/client/qwaylandwindowmanagerintegration_p.h @@ -55,9 +55,9 @@ #include <QtCore/QScopedPointer> #include <wayland-client.h> -#include <QtPlatformSupport/private/qgenericunixservices_p.h> +#include <QtServiceSupport/private/qgenericunixservices_p.h> -#include <QtWaylandClient/private/qwayland-windowmanager.h> +#include <QtWaylandClient/private/qwayland-qt-windowmanager.h> #include <QtWaylandClient/qwaylandclientexport.h> QT_BEGIN_NAMESPACE diff --git a/src/client/qwaylandwlshellsurface_p.h b/src/client/qwaylandwlshellsurface_p.h index c319cd983..ef732ef85 100644 --- a/src/client/qwaylandwlshellsurface_p.h +++ b/src/client/qwaylandwlshellsurface_p.h @@ -55,9 +55,9 @@ #include <wayland-client.h> -#include <QtWaylandClient/private/qwayland-wayland.h> #include <QtWaylandClient/qwaylandclientexport.h> -#include "qwaylandshellsurface_p.h" +#include <QtWaylandClient/private/qwayland-wayland.h> +#include <QtWaylandClient/private/qwaylandshellsurface_p.h> QT_BEGIN_NAMESPACE diff --git a/src/client/qwaylandxdgpopup_p.h b/src/client/qwaylandxdgpopup_p.h index 1f211012d..ff5804113 100644 --- a/src/client/qwaylandxdgpopup_p.h +++ b/src/client/qwaylandxdgpopup_p.h @@ -47,9 +47,9 @@ #include <wayland-client.h> -#include <QtWaylandClient/private/qwayland-xdg-shell.h> #include <QtWaylandClient/qwaylandclientexport.h> -#include "qwaylandshellsurface_p.h" +#include <QtWaylandClient/private/qwayland-xdg-shell.h> +#include <QtWaylandClient/private/qwaylandshellsurface_p.h> QT_BEGIN_NAMESPACE diff --git a/src/client/qwaylandxdgshell_p.h b/src/client/qwaylandxdgshell_p.h index 77b05b462..c04a9ce66 100644 --- a/src/client/qwaylandxdgshell_p.h +++ b/src/client/qwaylandxdgshell_p.h @@ -57,7 +57,7 @@ #include <QtWaylandClient/private/qwayland-xdg-shell.h> #include <QtWaylandClient/qwaylandclientexport.h> -#include "qwaylandshellsurface_p.h" +#include <QtWaylandClient/private/qwaylandshellsurface_p.h> QT_BEGIN_NAMESPACE diff --git a/src/client/qwaylandxdgsurface_p.h b/src/client/qwaylandxdgsurface_p.h index 1ce029af8..27decabb4 100644 --- a/src/client/qwaylandxdgsurface_p.h +++ b/src/client/qwaylandxdgsurface_p.h @@ -56,9 +56,9 @@ #include <wayland-client.h> -#include <QtWaylandClient/private/qwayland-xdg-shell.h> #include <QtWaylandClient/qwaylandclientexport.h> -#include "qwaylandshellsurface_p.h" +#include <QtWaylandClient/private/qwayland-xdg-shell.h> +#include <QtWaylandClient/private/qwaylandshellsurface_p.h> QT_BEGIN_NAMESPACE diff --git a/src/compositor/compositor.pro b/src/compositor/compositor.pro index fe58df7ec..251d757e2 100644 --- a/src/compositor/compositor.pro +++ b/src/compositor/compositor.pro @@ -5,7 +5,7 @@ QT = core gui-private qtHaveModule(quick): QT += quick -contains(QT_CONFIG, opengl):MODULE_DEFINES = QT_COMPOSITOR_WAYLAND_GL +contains(QT_CONFIG, opengl):MODULE_DEFINES = QT_WAYLAND_COMPOSITOR_GL CONFIG -= precompile_header CONFIG += link_pkgconfig @@ -23,7 +23,7 @@ INCLUDEPATH += ../shared HEADERS += ../shared/qwaylandmimehelper_p.h \ ../shared/qwaylandinputmethodeventbuilder_p.h \ - ../shared/qwaylandshmformathelper_p.h + ../shared/qwaylandsharedmemoryformathelper_p.h SOURCES += ../shared/qwaylandmimehelper.cpp \ ../shared/qwaylandinputmethodeventbuilder.cpp diff --git a/src/compositor/compositor_api/compositor_api.pri b/src/compositor/compositor_api/compositor_api.pri index 1724ec965..0253cd0ee 100644 --- a/src/compositor/compositor_api/compositor_api.pri +++ b/src/compositor/compositor_api/compositor_api.pri @@ -6,15 +6,19 @@ HEADERS += \ compositor_api/qwaylandclient.h \ compositor_api/qwaylandsurface.h \ compositor_api/qwaylandsurface_p.h \ - compositor_api/qwaylandinput.h \ - compositor_api/qwaylandinput_p.h \ + compositor_api/qwaylandseat.h \ + compositor_api/qwaylandseat_p.h \ compositor_api/qwaylandkeyboard.h \ compositor_api/qwaylandkeyboard_p.h \ + compositor_api/qwaylandkeymap.h \ + compositor_api/qwaylandkeymap_p.h \ compositor_api/qwaylandpointer.h \ compositor_api/qwaylandpointer_p.h \ compositor_api/qwaylandtouch.h \ compositor_api/qwaylandtouch_p.h \ compositor_api/qwaylandoutput.h \ + compositor_api/qwaylandoutputmode.h \ + compositor_api/qwaylandoutputmode_p.h \ compositor_api/qwaylanddrag.h \ compositor_api/qwaylandbufferref.h \ compositor_api/qwaylanddestroylistener.h \ @@ -24,17 +28,20 @@ HEADERS += \ compositor_api/qwaylandresource.h \ compositor_api/qwaylandsurfacegrabber.h \ compositor_api/qwaylandinputmethodcontrol.h \ - compositor_api/qwaylandinputmethodcontrol_p.h + compositor_api/qwaylandinputmethodcontrol_p.h \ + compositor_api/qwaylandoutputmode_p.h SOURCES += \ compositor_api/qwaylandcompositor.cpp \ compositor_api/qwaylandclient.cpp \ compositor_api/qwaylandsurface.cpp \ - compositor_api/qwaylandinput.cpp \ + compositor_api/qwaylandseat.cpp \ compositor_api/qwaylandkeyboard.cpp \ + compositor_api/qwaylandkeymap.cpp \ compositor_api/qwaylandpointer.cpp \ compositor_api/qwaylandtouch.cpp \ compositor_api/qwaylandoutput.cpp \ + compositor_api/qwaylandoutputmode.cpp \ compositor_api/qwaylanddrag.cpp \ compositor_api/qwaylandbufferref.cpp \ compositor_api/qwaylanddestroylistener.cpp \ @@ -45,7 +52,9 @@ SOURCES += \ QT += core-private -qtHaveModule(quick) { +qtHaveModule(quick):contains(QT_CONFIG, opengl) { + DEFINES += QT_WAYLAND_COMPOSITOR_QUICK + SOURCES += \ compositor_api/qwaylandquickcompositor.cpp \ compositor_api/qwaylandquicksurface.cpp \ diff --git a/src/compositor/compositor_api/qwaylandbufferref.cpp b/src/compositor/compositor_api/qwaylandbufferref.cpp index 624deaff9..6f175de95 100644 --- a/src/compositor/compositor_api/qwaylandbufferref.cpp +++ b/src/compositor/compositor_api/qwaylandbufferref.cpp @@ -38,14 +38,14 @@ #include <QAtomicInt> #include "qwaylandbufferref.h" -#include "wayland_wrapper/qwlsurfacebuffer_p.h" +#include "wayland_wrapper/qwlclientbuffer_p.h" QT_BEGIN_NAMESPACE class QWaylandBufferRefPrivate { public: - QtWayland::SurfaceBuffer *buffer; + QtWayland::ClientBuffer *buffer; bool nullOrDestroyed() { return !buffer || buffer->isDestroyed(); @@ -55,7 +55,7 @@ public: /*! * \class QWaylandBufferRef * \inmodule QtWaylandCompositor - * \preliminary + * \since 5.8 * \brief The QWaylandBufferRef class holds the reference to a surface buffer * * This class can be used to reference a surface buffer. As long as a reference @@ -74,7 +74,7 @@ QWaylandBufferRef::QWaylandBufferRef() /*! * Constructs a reference to \a buffer. */ -QWaylandBufferRef::QWaylandBufferRef(QtWayland::SurfaceBuffer *buffer) +QWaylandBufferRef::QWaylandBufferRef(QtWayland::ClientBuffer *buffer) : d(new QWaylandBufferRefPrivate) { d->buffer = buffer; @@ -104,17 +104,18 @@ QWaylandBufferRef::~QWaylandBufferRef() } /*! - * Assigns \a ref to this buffer. The previously referenced buffer is - * dereferenced and the new one gets a new reference. + * Assigns \a ref to this buffer and adds a reference to it. The previously referenced buffer is + * dereferenced. */ QWaylandBufferRef &QWaylandBufferRef::operator=(const QWaylandBufferRef &ref) { + if (ref.d->buffer) + ref.d->buffer->ref(); + if (d->buffer) d->buffer->deref(); d->buffer = ref.d->buffer; - if (d->buffer) - d->buffer->ref(); return *this; } @@ -141,7 +142,7 @@ bool QWaylandBufferRef::operator!=(const QWaylandBufferRef &ref) * Returns true if this QWaylandBufferRef does not reference a buffer. * Otherwise returns false. * - * \sa hasBuffer() + * \sa hasBuffer(), hasContent() */ bool QWaylandBufferRef::isNull() const { @@ -151,12 +152,21 @@ bool QWaylandBufferRef::isNull() const /*! * Returns true if this QWaylandBufferRef references a buffer. Otherwise returns false. * - * \sa isNull() + * \sa isNull(), hasContent() */ bool QWaylandBufferRef::hasBuffer() const { return d->buffer; } +/*! + * Returns true if this QWaylandBufferRef references a buffer that has content. Otherwise returns false. + * + * \sa isNull(), hasBuffer() + */ +bool QWaylandBufferRef::hasContent() const +{ + return QtWayland::ClientBuffer::hasContent(d->buffer); +} /*! * Returns true if this QWaylandBufferRef references a buffer that @@ -176,6 +186,14 @@ struct ::wl_resource *QWaylandBufferRef::wl_buffer() const } /*! + * \internal + */ +QtWayland::ClientBuffer *QWaylandBufferRef::buffer() const +{ + return d->buffer; +} + +/*! * Returns the size of the buffer. * If the buffer referenced is null, an invalid QSize() is returned. */ @@ -205,8 +223,8 @@ QWaylandBufferRef::BufferType QWaylandBufferRef::bufferType() const if (d->nullOrDestroyed()) return BufferType_Null; - if (isShm()) - return BufferType_Shm; + if (isSharedMemory()) + return BufferType_SharedMemory; return BufferType_Egl; } @@ -222,12 +240,12 @@ QWaylandBufferRef::BufferFormatEgl QWaylandBufferRef::bufferFormatEgl() const /*! * Returns true if the buffer is a shared memory buffer. Otherwise returns false. */ -bool QWaylandBufferRef::isShm() const +bool QWaylandBufferRef::isSharedMemory() const { if (d->nullOrDestroyed()) return false; - return d->buffer->isShm(); + return d->buffer->isSharedMemory(); } /*! @@ -241,36 +259,44 @@ QImage QWaylandBufferRef::image() const return d->buffer->image(); } -#ifdef QT_COMPOSITOR_WAYLAND_GL -GLuint QWaylandBufferRef::textureForPlane(int plane) const +#ifdef QT_WAYLAND_COMPOSITOR_GL +/*! + * Returns an OpenGL texture for the buffer. \a plane is the index for multi-plane formats, such as YUV. + * + * The returned texture is owned by the buffer. The texture is only valid for as + * long as the buffer reference exists. The caller of this function must not delete the texture, and must + * keep a reference to the buffer for as long as the texture is being used. + * + * Returns \c nullptr if there is no valid buffer, or if no texture can be created. + */ +QOpenGLTexture *QWaylandBufferRef::toOpenGLTexture(int plane) const { if (d->nullOrDestroyed()) - return 0; + return nullptr; - return d->buffer->textureForPlane(plane); + return d->buffer->toOpenGlTexture(plane); } -#endif /*! - * Binds the buffer to the current OpenGL texture. This may - * perform a copy of the buffer data, depending on the platform - * and the type of the buffer. + * Returns the native handle for this buffer, and marks it as locked so it will not be + * released until unlockNativeBuffer() is called. + * + * Returns 0 if there is no native handle for this buffer, or if the lock was unsuccessful. */ -void QWaylandBufferRef::bindToTexture() const +quintptr QWaylandBufferRef::lockNativeBuffer() { - if (d->nullOrDestroyed()) - return; - - return d->buffer->bindToTexture(); - + return d->buffer->lockNativeBuffer(); } -void QWaylandBufferRef::updateTexture() const +/*! + * Marks the native buffer as no longer in use. \a handle must correspond to the value returned by + * a previous call to lockNativeBuffer(). + */ +void QWaylandBufferRef::unlockNativeBuffer(quintptr handle) { - if (d->nullOrDestroyed() || d->buffer->isShm()) - return; - - d->buffer->updateTexture(); + d->buffer->unlockNativeBuffer(handle); } +#endif + QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandbufferref.h b/src/compositor/compositor_api/qwaylandbufferref.h index 50c85b965..06486ef3a 100644 --- a/src/compositor/compositor_api/qwaylandbufferref.h +++ b/src/compositor/compositor_api/qwaylandbufferref.h @@ -39,7 +39,7 @@ #include <QImage> -#ifdef QT_COMPOSITOR_WAYLAND_GL +#ifdef QT_WAYLAND_COMPOSITOR_GL #include <QtGui/qopengl.h> #endif @@ -50,22 +50,24 @@ struct wl_resource; QT_BEGIN_NAMESPACE +class QOpenGLTexture; + namespace QtWayland { - class SurfaceBuffer; + class ClientBuffer; } class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandBufferRef { public: QWaylandBufferRef(); - explicit QWaylandBufferRef(QtWayland::SurfaceBuffer *buffer); QWaylandBufferRef(const QWaylandBufferRef &ref); ~QWaylandBufferRef(); QWaylandBufferRef &operator=(const QWaylandBufferRef &ref); bool isNull() const; bool hasBuffer() const; + bool hasContent() const; bool isDestroyed() const; bool operator==(const QWaylandBufferRef &ref); bool operator!=(const QWaylandBufferRef &ref); @@ -77,7 +79,7 @@ public: enum BufferType { BufferType_Null, - BufferType_Shm, + BufferType_SharedMemory, BufferType_Egl }; @@ -94,18 +96,22 @@ public: BufferType bufferType() const; BufferFormatEgl bufferFormatEgl() const; - bool isShm() const; + bool isSharedMemory() const; QImage image() const; -#ifdef QT_COMPOSITOR_WAYLAND_GL - GLuint textureForPlane(int plane) const; + +#ifdef QT_WAYLAND_COMPOSITOR_GL + QOpenGLTexture *toOpenGLTexture(int plane = 0) const; #endif - void bindToTexture() const; - void updateTexture() const; + quintptr lockNativeBuffer(); + void unlockNativeBuffer(quintptr handle); private: + explicit QWaylandBufferRef(QtWayland::ClientBuffer *buffer); + QtWayland::ClientBuffer *buffer() const; class QWaylandBufferRefPrivate *const d; friend class QWaylandBufferRefPrivate; + friend class QWaylandSurfacePrivate; }; QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandclient.cpp b/src/compositor/compositor_api/qwaylandclient.cpp index fbf8c1275..eb12fa3d8 100644 --- a/src/compositor/compositor_api/qwaylandclient.cpp +++ b/src/compositor/compositor_api/qwaylandclient.cpp @@ -87,7 +87,7 @@ public: /*! * \qmltype WaylandClient * \inqmlmodule QtWayland.Compositor - * \preliminary + * \since 5.8 * \brief Represents a client connecting to the WaylandCompositor. * * This type represents a client connecting to the compositor using the Wayland protocol. @@ -97,7 +97,7 @@ public: /*! * \class QWaylandClient * \inmodule QtWaylandCompositor - * \preliminary + * \since 5.8 * \brief The QWaylandClient class represents a client connecting to the QWaylandCompositor. * * This class corresponds to a client connecting to the compositor using the Wayland protocol. @@ -164,6 +164,24 @@ QWaylandClient *QWaylandClient::fromWlClient(QWaylandCompositor *compositor, wl_ } /*! + * \qmlproperty object QtWaylandCompositor::WaylandClient::compositor + * + * This property holds the compositor of this WaylandClient. + */ + +/*! + * \property QWaylandClient::compositor + * + * This property holds the compositor of this QWaylandClient. + */ +QWaylandCompositor *QWaylandClient::compositor() const +{ + Q_D(const QWaylandClient); + + return d->compositor; +} + +/*! * Returns the Wayland client of this QWaylandClient. */ wl_client *QWaylandClient::client() const diff --git a/src/compositor/compositor_api/qwaylandclient.h b/src/compositor/compositor_api/qwaylandclient.h index 26e7b95e5..50e7baf72 100644 --- a/src/compositor/compositor_api/qwaylandclient.h +++ b/src/compositor/compositor_api/qwaylandclient.h @@ -55,6 +55,7 @@ class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandClient : public QObject Q_OBJECT Q_DECLARE_PRIVATE(QWaylandClient) + Q_PROPERTY(QWaylandCompositor *compositor READ compositor CONSTANT) Q_PROPERTY(qint64 userId READ userId CONSTANT) Q_PROPERTY(qint64 groupId READ groupId CONSTANT) Q_PROPERTY(qint64 processId READ processId CONSTANT) @@ -63,6 +64,8 @@ public: static QWaylandClient *fromWlClient(QWaylandCompositor *compositor, wl_client *wlClient); + QWaylandCompositor *compositor() const; + wl_client *client() const; qint64 userId() const; diff --git a/src/compositor/compositor_api/qwaylandcompositor.cpp b/src/compositor/compositor_api/qwaylandcompositor.cpp index 795cb6a59..bcee61d8b 100644 --- a/src/compositor/compositor_api/qwaylandcompositor.cpp +++ b/src/compositor/compositor_api/qwaylandcompositor.cpp @@ -39,7 +39,7 @@ #include "qwaylandcompositor_p.h" #include <QtWaylandCompositor/qwaylandclient.h> -#include <QtWaylandCompositor/qwaylandinput.h> +#include <QtWaylandCompositor/qwaylandseat.h> #include <QtWaylandCompositor/qwaylandoutput.h> #include <QtWaylandCompositor/qwaylandview.h> #include <QtWaylandCompositor/qwaylandclient.h> @@ -53,17 +53,21 @@ #include "wayland_wrapper/qwldatadevice_p.h" #include "wayland_wrapper/qwldatadevicemanager_p.h" +#include "wayland_wrapper/qwlbuffermanager_p.h" #include "hardware_integration/qwlclientbufferintegration_p.h" #include "hardware_integration/qwlclientbufferintegrationfactory_p.h" #include "hardware_integration/qwlserverbufferintegration_p.h" #include "hardware_integration/qwlserverbufferintegrationfactory_p.h" + +#ifdef QT_WAYLAND_COMPOSITOR_GL #include "hardware_integration/qwlhwintegration_p.h" +#endif -#include "extensions/qwaylandwindowmanagerextension.h" +#include "extensions/qwaylandqtwindowmanager.h" #include "qwaylandxkb_p.h" -#include "qwaylandshmformathelper_p.h" +#include "qwaylandsharedmemoryformathelper_p.h" #include <QtCore/QCoreApplication> #include <QtCore/QStringList> @@ -76,8 +80,9 @@ #include <QtGui/qpa/qplatformnativeinterface.h> #include <QtGui/private/qguiapplication_p.h> -#ifdef QT_COMPOSITOR_WAYLAND_GL -# include <QtGui/private/qopengltextureblitter_p.h> +#ifdef QT_WAYLAND_COMPOSITOR_GL +# include <QOpenGLTextureBlitter> +# include <QOpenGLTexture> # include <QOpenGLContext> # include <QOpenGLFramebufferObject> # include <QMatrix4x4> @@ -97,7 +102,7 @@ public: { if (e->type == QWindowSystemInterfacePrivate::Key) { QWindowSystemInterfacePrivate::KeyEvent *ke = static_cast<QWindowSystemInterfacePrivate::KeyEvent *>(e); - QWaylandKeyboardPrivate *keyb = QWaylandKeyboardPrivate::get(compositor->defaultInputDevice()->keyboard()); + QWaylandKeyboardPrivate *keyb = QWaylandKeyboardPrivate::get(compositor->defaultSeat()->keyboard()); uint32_t code = ke->nativeScanCode; bool isDown = ke->keyType == QEvent::KeyPress; @@ -122,7 +127,7 @@ public: QWindowSystemEventHandler::sendEvent(e); if (!ke->repeat) { - keyb->updateKeymap(); + keyb->maybeUpdateKeymap(); keyb->updateModifierState(code, isDown ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED); } } else { @@ -138,12 +143,13 @@ public: QWaylandCompositorPrivate::QWaylandCompositorPrivate(QWaylandCompositor *compositor) : display(0) -#if defined (QT_COMPOSITOR_WAYLAND_GL) +#if defined (QT_WAYLAND_COMPOSITOR_GL) , use_hw_integration_extension(true) , client_buffer_integration(0) , server_buffer_integration(0) #endif , retainSelection(false) + , preInitialized(false) , initialized(false) { if (QGuiApplication::platformNativeInterface()) @@ -170,9 +176,10 @@ void QWaylandCompositorPrivate::init() wl_subcompositor::init(display, 1); data_device_manager = new QtWayland::DataDeviceManager(q); + buffer_manager = new QtWayland::BufferManager(q); wl_display_init_shm(display); - QVector<wl_shm_format> formats = QWaylandShmFormatHelper::supportedWaylandFormats(); + QVector<wl_shm_format> formats = QWaylandSharedMemoryFormatHelper::supportedWaylandFormats(); foreach (wl_shm_format format, formats) wl_display_add_shm_format(display, format); @@ -197,7 +204,7 @@ void QWaylandCompositorPrivate::init() QObject::connect(dispatcher, SIGNAL(aboutToBlock()), q, SLOT(processWaylandEvents())); initializeHardwareIntegration(); - initializeDefaultInputDevice(); + initializeSeats(); initialized = true; @@ -207,6 +214,8 @@ void QWaylandCompositorPrivate::init() QCoreApplication::sendEvent(object.data(), &polishEvent); } } + + emit q->createdChanged(); } QWaylandCompositorPrivate::~QWaylandCompositorPrivate() @@ -220,6 +229,19 @@ QWaylandCompositorPrivate::~QWaylandCompositorPrivate() wl_display_destroy(display); } +void QWaylandCompositorPrivate::preInit() +{ + Q_Q(QWaylandCompositor); + + if (preInitialized) + return; + + if (seats.empty()) + seats.append(q->createSeat()); + + preInitialized = true; +} + void QWaylandCompositorPrivate::destroySurface(QWaylandSurface *surface) { Q_Q(QWaylandCompositor); @@ -287,7 +309,7 @@ void QWaylandCompositorPrivate::compositor_create_surface(wl_compositor::Resourc { Q_Q(QWaylandCompositor); QWaylandClient *client = QWaylandClient::fromWlClient(q, resource->client()); - emit q->createSurface(client, id, resource->version()); + emit q->surfaceRequested(client, id, resource->version()); #ifndef QT_NO_DEBUG Q_ASSERT_X(!QWaylandSurfacePrivate::hasUninitializedSurface(), "QWaylandCompositor", QStringLiteral("Found uninitialized QWaylandSurface after emitting QWaylandCompositor::createSurface for id %1. All surfaces has to be initialized immediately after creation. See QWaylandSurface::initialize.").arg(id).toLocal8Bit().constData()); #endif @@ -332,7 +354,7 @@ QWaylandSurface *QWaylandCompositorPrivate::createDefaultSurface() void QWaylandCompositorPrivate::initializeHardwareIntegration() { -#ifdef QT_COMPOSITOR_WAYLAND_GL +#ifdef QT_WAYLAND_COMPOSITOR_GL Q_Q(QWaylandCompositor); if (use_hw_integration_extension) hw_integration.reset(new QtWayland::HardwareIntegration(q)); @@ -347,17 +369,15 @@ void QWaylandCompositorPrivate::initializeHardwareIntegration() #endif } -void QWaylandCompositorPrivate::initializeDefaultInputDevice() +void QWaylandCompositorPrivate::initializeSeats() { - Q_Q(QWaylandCompositor); - QWaylandInputDevice *device = q->createInputDevice(); - inputDevices.append(device); - q->defaultInputDeviceChanged(device, nullptr); + for (QWaylandSeat *seat : qAsConst(seats)) + seat->initialize(); } void QWaylandCompositorPrivate::loadClientBufferIntegration() { -#ifdef QT_COMPOSITOR_WAYLAND_GL +#ifdef QT_WAYLAND_COMPOSITOR_GL Q_Q(QWaylandCompositor); QStringList keys = QtWayland::ClientBufferIntegrationFactory::keys(); QString targetKey; @@ -386,7 +406,7 @@ void QWaylandCompositorPrivate::loadClientBufferIntegration() void QWaylandCompositorPrivate::loadServerBufferIntegration() { -#ifdef QT_COMPOSITOR_WAYLAND_GL +#ifdef QT_WAYLAND_COMPOSITOR_GL QStringList keys = QtWayland::ServerBufferIntegrationFactory::keys(); QString targetKey; QByteArray serverBufferIntegration = qgetenv("QT_WAYLAND_SERVER_BUFFER_INTEGRATION"); @@ -404,16 +424,16 @@ void QWaylandCompositorPrivate::loadServerBufferIntegration() /*! \qmltype WaylandCompositor \inqmlmodule QtWayland.Compositor - \preliminary + \since 5.8 \brief Manages the Wayland display server. The WaylandCompositor manages the connections to the clients, as well as the different - \l{WaylandOutput}{outputs} and \l{QWaylandInputDevice}{input devices}. + \l{WaylandOutput}{outputs} and \l{QWaylandSeat}{seats}. Normally, a compositor application will have a single WaylandCompositor instance, which can have several outputs as children. When a client requests the compositor to create a surface, the request is handled by - the onCreateSurface handler. + the onSurfaceRequested handler. Extensions that are supported by the compositor should be instantiated and added to the extensions property. @@ -423,11 +443,11 @@ void QWaylandCompositorPrivate::loadServerBufferIntegration() /*! \class QWaylandCompositor \inmodule QtWaylandCompositor - \preliminary + \since 5.8 \brief The QWaylandCompositor class manages the Wayland display server. The QWaylandCompositor manages the connections to the clients, as well as the different \l{QWaylandOutput}{outputs} - and \l{QWaylandInputDevice}{input devices}. + and \l{QWaylandSeat}{seats}. Normally, a compositor application will have a single WaylandCompositor instance, which can have several outputs as children. @@ -464,11 +484,22 @@ QWaylandCompositor::~QWaylandCompositor() void QWaylandCompositor::create() { Q_D(QWaylandCompositor); + d->preInit(); d->init(); } /*! - * Returns true if the QWaylandCompositor has been initialized. Otherwise returns false. + * \qmlproperty bool QtWaylandCompositor::WaylandCompositor::created + * + * This property is true if WaylandCompositor has been initialized, + * otherwise it's false. + */ + +/*! + * \property QWaylandCompositor::created + * + * This property is true if QWaylandCompositor has been initialized, + * otherwise it's false. */ bool QWaylandCompositor::isCreated() const { @@ -500,11 +531,17 @@ bool QWaylandCompositor::isCreated() const void QWaylandCompositor::setSocketName(const QByteArray &name) { Q_D(QWaylandCompositor); + + if (d->socket_name == name) + return; + if (d->initialized) { qWarning("%s: Changing socket name after initializing the compositor is not supported.\n", Q_FUNC_INFO); return; } + d->socket_name = name; + emit socketNameChanged(name); } QByteArray QWaylandCompositor::socketName() const @@ -568,9 +605,9 @@ void QWaylandCompositor::destroyClient(QWaylandClient *client) if (!client) return; - QWaylandWindowManagerExtension *wmExtension = QWaylandWindowManagerExtension::findIn(this); + QWaylandQtWindowManager *wmExtension = QWaylandQtWindowManager::findIn(this); if (wmExtension) - wmExtension->sendQuitMessage(client->client()); + wmExtension->sendQuitMessage(client); wl_client_destroy(client->client()); } @@ -682,33 +719,33 @@ void QWaylandCompositor::processWaylandEvents() /*! * \internal */ -QWaylandInputDevice *QWaylandCompositor::createInputDevice() +QWaylandSeat *QWaylandCompositor::createSeat() { - return new QWaylandInputDevice(this); + return new QWaylandSeat(this); } /*! * \internal */ -QWaylandPointer *QWaylandCompositor::createPointerDevice(QWaylandInputDevice *inputDevice) +QWaylandPointer *QWaylandCompositor::createPointerDevice(QWaylandSeat *seat) { - return new QWaylandPointer(inputDevice); + return new QWaylandPointer(seat); } /*! * \internal */ -QWaylandKeyboard *QWaylandCompositor::createKeyboardDevice(QWaylandInputDevice *inputDevice) +QWaylandKeyboard *QWaylandCompositor::createKeyboardDevice(QWaylandSeat *seat) { - return new QWaylandKeyboard(inputDevice); + return new QWaylandKeyboard(seat); } /*! * \internal */ -QWaylandTouch *QWaylandCompositor::createTouchDevice(QWaylandInputDevice *inputDevice) +QWaylandTouch *QWaylandCompositor::createTouchDevice(QWaylandSeat *seat) { - return new QWaylandTouch(inputDevice); + return new QWaylandTouch(seat); } /*! @@ -725,7 +762,12 @@ QWaylandTouch *QWaylandCompositor::createTouchDevice(QWaylandInputDevice *inputD void QWaylandCompositor::setRetainedSelectionEnabled(bool enabled) { Q_D(QWaylandCompositor); + + if (d->retainSelection == enabled) + return; + d->retainSelection = enabled; + emit retainedSelectionChanged(enabled); } bool QWaylandCompositor::retainedSelectionEnabled() const @@ -751,38 +793,38 @@ void QWaylandCompositor::overrideSelection(const QMimeData *data) } /*! - * \qmlproperty object QtWaylandCompositor::WaylandCompositor::defaultInputDevice + * \qmlproperty object QtWaylandCompositor::WaylandCompositor::defaultSeat * - * This property contains the default input device for this + * This property contains the default seat for this * WaylandCompositor. */ /*! - * \property QWaylandCompositor::defaultInputDevice + * \property QWaylandCompositor::defaultSeat * - * This property contains the default input device for this + * This property contains the default seat for this * QWaylandCompositor. */ -QWaylandInputDevice *QWaylandCompositor::defaultInputDevice() const +QWaylandSeat *QWaylandCompositor::defaultSeat() const { Q_D(const QWaylandCompositor); - if (d->inputDevices.size()) - return d->inputDevices.first(); + if (d->seats.size()) + return d->seats.first(); return Q_NULLPTR; } /*! * \internal * - * Currently, Qt only supports a single input device, so this exists for + * Currently, Qt only supports a single seat, so this exists for * future proofing the APIs. */ -QWaylandInputDevice *QWaylandCompositor::inputDeviceFor(QInputEvent *inputEvent) +QWaylandSeat *QWaylandCompositor::seatFor(QInputEvent *inputEvent) { Q_D(QWaylandCompositor); - QWaylandInputDevice *dev = NULL; - for (int i = 0; i < d->inputDevices.size(); i++) { - QWaylandInputDevice *candidate = d->inputDevices.at(i); + QWaylandSeat *dev = NULL; + for (int i = 0; i < d->seats.size(); i++) { + QWaylandSeat *candidate = d->seats.at(i); if (candidate->isOwner(inputEvent)) { dev = candidate; break; @@ -810,12 +852,17 @@ QWaylandInputDevice *QWaylandCompositor::inputDeviceFor(QInputEvent *inputEvent) */ bool QWaylandCompositor::useHardwareIntegrationExtension() const { +#ifdef QT_WAYLAND_COMPOSITOR_GL Q_D(const QWaylandCompositor); return d->use_hw_integration_extension; +#else + return false; +#endif } void QWaylandCompositor::setUseHardwareIntegrationExtension(bool use) { +#ifdef QT_WAYLAND_COMPOSITOR_GL Q_D(QWaylandCompositor); if (use == d->use_hw_integration_extension) return; @@ -825,6 +872,10 @@ void QWaylandCompositor::setUseHardwareIntegrationExtension(bool use) d->use_hw_integration_extension = use; useHardwareIntegrationExtensionChanged(); +#else + if (use) + qWarning() << "Hardware integration not supported without OpenGL support"; +#endif } /*! @@ -832,22 +883,22 @@ void QWaylandCompositor::setUseHardwareIntegrationExtension(bool use) * The default implementation requires a OpenGL context to be bound to the current thread * to work. If this is not possible, reimplement this function in your compositor subclass * to implement custom logic. - * The default implementation only grabs SHM and OpenGL buffers, reimplement this in your + * The default implementation only grabs shared memory and OpenGL buffers, reimplement this in your * compositor subclass to handle more buffer types. * \note You should not call this manually, but rather use QWaylandSurfaceGrabber (\a grabber). */ void QWaylandCompositor::grabSurface(QWaylandSurfaceGrabber *grabber, const QWaylandBufferRef &buffer) { - if (buffer.isShm()) { + if (buffer.isSharedMemory()) { emit grabber->success(buffer.image()); } else { -#ifdef QT_COMPOSITOR_WAYLAND_GL +#ifdef QT_WAYLAND_COMPOSITOR_GL if (QOpenGLContext::currentContext()) { QOpenGLFramebufferObject fbo(buffer.size()); fbo.bind(); QOpenGLTextureBlitter blitter; blitter.create(); - blitter.bind(); + glViewport(0, 0, buffer.size().width(), buffer.size().height()); @@ -856,15 +907,10 @@ void QWaylandCompositor::grabSurface(QWaylandSurfaceGrabber *grabber, const QWay ? QOpenGLTextureBlitter::OriginTopLeft : QOpenGLTextureBlitter::OriginBottomLeft; - GLuint texture; - glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_2D, texture); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - buffer.bindToTexture(); - blitter.blit(texture, QMatrix4x4(), surfaceOrigin); - + auto texture = buffer.toOpenGLTexture(); + blitter.bind(texture->target()); + blitter.blit(texture->textureId(), QMatrix4x4(), surfaceOrigin); blitter.release(); - glDeleteTextures(1, &texture); emit grabber->success(fbo.toImage()); } else diff --git a/src/compositor/compositor_api/qwaylandcompositor.h b/src/compositor/compositor_api/qwaylandcompositor.h index f97484d86..8b190d1d2 100644 --- a/src/compositor/compositor_api/qwaylandcompositor.h +++ b/src/compositor/compositor_api/qwaylandcompositor.h @@ -58,7 +58,7 @@ class QOpenGLContext; class QWaylandCompositorPrivate; class QWaylandClient; class QWaylandSurface; -class QWaylandInputDevice; +class QWaylandSeat; class QWaylandGlobalInterface; class QWaylandView; class QWaylandPointer; @@ -73,11 +73,12 @@ class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandCompositor : public QWaylandObject { Q_OBJECT Q_DECLARE_PRIVATE(QWaylandCompositor) - Q_PROPERTY(QByteArray socketName READ socketName WRITE setSocketName) - Q_PROPERTY(bool retainedSelection READ retainedSelectionEnabled WRITE setRetainedSelectionEnabled) + Q_PROPERTY(QByteArray socketName READ socketName WRITE setSocketName NOTIFY socketNameChanged) + Q_PROPERTY(bool created READ isCreated NOTIFY createdChanged) + Q_PROPERTY(bool retainedSelection READ retainedSelectionEnabled WRITE setRetainedSelectionEnabled NOTIFY retainedSelectionChanged) Q_PROPERTY(QWaylandOutput *defaultOutput READ defaultOutput WRITE setDefaultOutput NOTIFY defaultOutputChanged) Q_PROPERTY(bool useHardwareIntegrationExtension READ useHardwareIntegrationExtension WRITE setUseHardwareIntegrationExtension NOTIFY useHardwareIntegrationExtensionChanged) - Q_PROPERTY(QWaylandInputDevice *defaultInputDevice READ defaultInputDevice NOTIFY defaultInputDeviceChanged) + Q_PROPERTY(QWaylandSeat *defaultSeat READ defaultSeat NOTIFY defaultSeatChanged) public: QWaylandCompositor(QObject *parent = nullptr); @@ -111,11 +112,11 @@ public: bool retainedSelectionEnabled() const; void overrideSelection(const QMimeData *data); - QWaylandInputDevice *defaultInputDevice() const; + QWaylandSeat *defaultSeat() const; QWaylandView *createSurfaceView(QWaylandSurface *surface); - QWaylandInputDevice *inputDeviceFor(QInputEvent *inputEvent); + QWaylandSeat *seatFor(QInputEvent *inputEvent); bool useHardwareIntegrationExtension() const; void setUseHardwareIntegrationExtension(bool use); @@ -126,21 +127,29 @@ public Q_SLOTS: void processWaylandEvents(); Q_SIGNALS: - void createSurface(QWaylandClient *client, uint id, int version); + void createdChanged(); + void socketNameChanged(const QByteArray &socketName); + void retainedSelectionChanged(bool retainedSelection); + + void surfaceRequested(QWaylandClient *client, uint id, int version); void surfaceCreated(QWaylandSurface *surface); void surfaceAboutToBeDestroyed(QWaylandSurface *surface); void subsurfaceChanged(QWaylandSurface *child, QWaylandSurface *parent); void defaultOutputChanged(); - void defaultInputDeviceChanged(QWaylandInputDevice *newDevice, QWaylandInputDevice *oldDevice); + void defaultSeatChanged(QWaylandSeat *newDevice, QWaylandSeat *oldDevice); void useHardwareIntegrationExtensionChanged(); + + void outputAdded(QWaylandOutput *output); + void outputRemoved(QWaylandOutput *output); + protected: virtual void retainedSelectionReceived(QMimeData *mimeData); - virtual QWaylandInputDevice *createInputDevice(); - virtual QWaylandPointer *createPointerDevice(QWaylandInputDevice *inputDevice); - virtual QWaylandKeyboard *createKeyboardDevice(QWaylandInputDevice *inputDevice); - virtual QWaylandTouch *createTouchDevice(QWaylandInputDevice *inputDevice); + virtual QWaylandSeat *createSeat(); + virtual QWaylandPointer *createPointerDevice(QWaylandSeat *seat); + virtual QWaylandKeyboard *createKeyboardDevice(QWaylandSeat *seat); + virtual QWaylandTouch *createTouchDevice(QWaylandSeat *seat); QWaylandCompositor(QWaylandCompositorPrivate &dptr, QObject *parent = nullptr); }; diff --git a/src/compositor/compositor_api/qwaylandcompositor_p.h b/src/compositor/compositor_api/qwaylandcompositor_p.h index 8966acb38..5255f3d58 100644 --- a/src/compositor/compositor_api/qwaylandcompositor_p.h +++ b/src/compositor/compositor_api/qwaylandcompositor_p.h @@ -64,6 +64,7 @@ namespace QtWayland { class ClientBufferIntegration; class ServerBufferIntegration; class DataDeviceManager; + class BufferManager; } class QWindowSystemEventHandler; @@ -77,6 +78,7 @@ public: QWaylandCompositorPrivate(QWaylandCompositor *compositor); ~QWaylandCompositorPrivate(); + void preInit(); void init(); void destroySurface(QWaylandSurface *surface); @@ -88,14 +90,15 @@ public: inline QtWayland::ServerBufferIntegration *serverBufferIntegration() const; QtWayland::DataDeviceManager *dataDeviceManager() const { return data_device_manager; } + QtWayland::BufferManager *bufferManager() const { return buffer_manager; } void feedRetainedSelectionData(QMimeData *data); - QWaylandPointer *callCreatePointerDevice(QWaylandInputDevice *inputDevice) - { return q_func()->createPointerDevice(inputDevice); } - QWaylandKeyboard *callCreateKeyboardDevice(QWaylandInputDevice *inputDevice) - { return q_func()->createKeyboardDevice(inputDevice); } - QWaylandTouch *callCreateTouchDevice(QWaylandInputDevice *inputDevice) - { return q_func()->createTouchDevice(inputDevice); } + QWaylandPointer *callCreatePointerDevice(QWaylandSeat *seat) + { return q_func()->createPointerDevice(seat); } + QWaylandKeyboard *callCreateKeyboardDevice(QWaylandSeat *seat) + { return q_func()->createKeyboardDevice(seat); } + QWaylandTouch *callCreateTouchDevice(QWaylandSeat *seat) + { return q_func()->createTouchDevice(seat); } inline void addClient(QWaylandClient *client); inline void removeClient(QWaylandClient *client); @@ -114,7 +117,7 @@ protected: protected: void initializeHardwareIntegration(); void initializeExtensions(); - void initializeDefaultInputDevice(); + void initializeSeats(); void loadClientBufferIntegration(); void loadServerBufferIntegration(); @@ -122,12 +125,13 @@ protected: QByteArray socket_name; struct wl_display *display; - QList<QWaylandInputDevice *> inputDevices; + QList<QWaylandSeat *> seats; QList<QWaylandOutput *> outputs; QList<QWaylandSurface *> all_surfaces; QtWayland::DataDeviceManager *data_device_manager; + QtWayland::BufferManager *buffer_manager; QElapsedTimer timer; @@ -135,7 +139,7 @@ protected: QList<QWaylandClient *> clients; -#ifdef QT_COMPOSITOR_WAYLAND_GL +#ifdef QT_WAYLAND_COMPOSITOR_GL bool use_hw_integration_extension; QScopedPointer<QtWayland::HardwareIntegration> hw_integration; QScopedPointer<QtWayland::ClientBufferIntegration> client_buffer_integration; @@ -145,6 +149,7 @@ protected: QScopedPointer<QWindowSystemEventHandler> eventHandler; bool retainSelection; + bool preInitialized; bool initialized; QList<QPointer<QObject> > polish_objects; @@ -154,7 +159,7 @@ protected: QtWayland::ClientBufferIntegration * QWaylandCompositorPrivate::clientBufferIntegration() const { -#ifdef QT_COMPOSITOR_WAYLAND_GL +#ifdef QT_WAYLAND_COMPOSITOR_GL return client_buffer_integration.data(); #else return 0; @@ -163,7 +168,7 @@ QtWayland::ClientBufferIntegration * QWaylandCompositorPrivate::clientBufferInte QtWayland::ServerBufferIntegration * QWaylandCompositorPrivate::serverBufferIntegration() const { -#ifdef QT_COMPOSITOR_WAYLAND_GL +#ifdef QT_WAYLAND_COMPOSITOR_GL return server_buffer_integration.data(); #else return 0; @@ -185,16 +190,20 @@ void QWaylandCompositorPrivate::removeClient(QWaylandClient *client) void QWaylandCompositorPrivate::addOutput(QWaylandOutput *output) { Q_ASSERT(output); + Q_Q(QWaylandCompositor); if (outputs.contains(output)) return; outputs.append(output); + emit q->outputAdded(output); } void QWaylandCompositorPrivate::removeOutput(QWaylandOutput *output) { Q_ASSERT(output); Q_ASSERT(outputs.count(output) == 1); - outputs.removeOne(output); + Q_Q(QWaylandCompositor); + if (outputs.removeOne(output)) + emit q->outputRemoved(output); } QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylanddestroylistener_p.h b/src/compositor/compositor_api/qwaylanddestroylistener_p.h index 63b2d3ce9..03ba73a7f 100644 --- a/src/compositor/compositor_api/qwaylanddestroylistener_p.h +++ b/src/compositor/compositor_api/qwaylanddestroylistener_p.h @@ -48,7 +48,7 @@ // We mean it. // -#include "qwaylanddestroylistener.h" +#include <QtWaylandCompositor/QWaylandDestroyListener> #include <QtCore/private/qobject_p.h> diff --git a/src/compositor/compositor_api/qwaylanddrag.cpp b/src/compositor/compositor_api/qwaylanddrag.cpp index cc45c1279..3c3d9ce52 100644 --- a/src/compositor/compositor_api/qwaylanddrag.cpp +++ b/src/compositor/compositor_api/qwaylanddrag.cpp @@ -40,33 +40,33 @@ #include "qwldatadevice_p.h" #include "qwaylandview.h" -#include <QtWaylandCompositor/private/qwaylandinput_p.h> +#include <QtWaylandCompositor/private/qwaylandseat_p.h> QT_BEGIN_NAMESPACE class QWaylandDragPrivate : public QObjectPrivate { public: - QWaylandDragPrivate(QWaylandInputDevice *id) - : inputDevice(id) + QWaylandDragPrivate(QWaylandSeat *seat) + : seat(seat) { } QtWayland::DataDevice *dataDevice() { - return QWaylandInputDevicePrivate::get(inputDevice)->dataDevice(); + return QWaylandSeatPrivate::get(seat)->dataDevice(); } const QtWayland::DataDevice *dataDevice() const { - return QWaylandInputDevicePrivate::get(inputDevice)->dataDevice(); + return QWaylandSeatPrivate::get(seat)->dataDevice(); } - QWaylandInputDevice *inputDevice; + QWaylandSeat *seat; }; -QWaylandDrag::QWaylandDrag(QWaylandInputDevice *inputDevice) - : QObject(* new QWaylandDragPrivate(inputDevice)) +QWaylandDrag::QWaylandDrag(QWaylandSeat *seat) + : QObject(* new QWaylandDragPrivate(seat)) { } @@ -81,6 +81,19 @@ QWaylandSurface *QWaylandDrag::icon() const return dataDevice->dragIcon(); } +QWaylandSurface *QWaylandDrag::origin() const +{ + Q_D(const QWaylandDrag); + const QtWayland::DataDevice *dataDevice = d->dataDevice(); + return dataDevice ? dataDevice->dragOrigin() : nullptr; +} + +QWaylandSeat *QWaylandDrag::seat() const +{ + Q_D(const QWaylandDrag); + return d->seat; +} + bool QWaylandDrag::visible() const { diff --git a/src/compositor/compositor_api/qwaylanddrag.h b/src/compositor/compositor_api/qwaylanddrag.h index 00a2bee8e..08ad11018 100644 --- a/src/compositor/compositor_api/qwaylanddrag.h +++ b/src/compositor/compositor_api/qwaylanddrag.h @@ -46,12 +46,7 @@ QT_BEGIN_NAMESPACE class QWaylandDragPrivate; class QWaylandSurface; -class QWaylandView; -class QWaylandInputDevice; - -namespace QtWayland { - class DataDevice; -} +class QWaylandSeat; class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandDrag : public QObject { @@ -62,10 +57,11 @@ class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandDrag : public QObject Q_PROPERTY(bool visible READ visible NOTIFY iconChanged) public: - explicit QWaylandDrag(QWaylandInputDevice *inputDevice); + explicit QWaylandDrag(QWaylandSeat *seat); QWaylandSurface *icon() const; - // QPointF position() const; + QWaylandSurface *origin() const; + QWaylandSeat *seat() const; bool visible() const; public Q_SLOTS: @@ -76,9 +72,6 @@ public Q_SLOTS: Q_SIGNALS: void iconChanged(); void dragStarted(); // QWaylandSurface *icon???? - -private: - //friend class QtWayland::DataDevice; }; QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandinputmethodcontrol.cpp b/src/compositor/compositor_api/qwaylandinputmethodcontrol.cpp index 122c589da..68279bb97 100644 --- a/src/compositor/compositor_api/qwaylandinputmethodcontrol.cpp +++ b/src/compositor/compositor_api/qwaylandinputmethodcontrol.cpp @@ -38,7 +38,7 @@ #include "qwaylandinputmethodcontrol_p.h" #include "qwaylandcompositor.h" -#include "qwaylandinput.h" +#include "qwaylandseat.h" #include "qwaylandsurface.h" #include "qwaylandview.h" #include "qwaylandtextinput.h" @@ -48,8 +48,8 @@ QWaylandInputMethodControl::QWaylandInputMethodControl(QWaylandSurface *surface) : QObject(*new QWaylandInputMethodControlPrivate(surface), surface) { - connect(d_func()->compositor, &QWaylandCompositor::defaultInputDeviceChanged, - this, &QWaylandInputMethodControl::defaultInputDeviceChanged); + connect(d_func()->compositor, &QWaylandCompositor::defaultSeatChanged, + this, &QWaylandInputMethodControl::defaultSeatChanged); QWaylandTextInput *textInput = d_func()->textInput(); if (textInput) { connect(textInput, &QWaylandTextInput::surfaceEnabled, this, &QWaylandInputMethodControl::surfaceEnabled); @@ -135,13 +135,13 @@ void QWaylandInputMethodControl::setSurface(QWaylandSurface *surface) setEnabled(textInput && textInput->isSurfaceEnabled(d->surface)); } -void QWaylandInputMethodControl::defaultInputDeviceChanged() +void QWaylandInputMethodControl::defaultSeatChanged() { Q_D(QWaylandInputMethodControl); disconnect(d->textInput(), 0, this, 0); - d->inputDevice = d->compositor->defaultInputDevice(); + d->seat = d->compositor->defaultSeat(); QWaylandTextInput *textInput = d->textInput(); connect(textInput, &QWaylandTextInput::surfaceEnabled, this, &QWaylandInputMethodControl::surfaceEnabled); @@ -153,7 +153,7 @@ void QWaylandInputMethodControl::defaultInputDeviceChanged() QWaylandInputMethodControlPrivate::QWaylandInputMethodControlPrivate(QWaylandSurface *surface) : QObjectPrivate() , compositor(surface->compositor()) - , inputDevice(compositor->defaultInputDevice()) + , seat(compositor->defaultSeat()) , surface(surface) , enabled(false) { @@ -161,5 +161,5 @@ QWaylandInputMethodControlPrivate::QWaylandInputMethodControlPrivate(QWaylandSur QWaylandTextInput *QWaylandInputMethodControlPrivate::textInput() const { - return QWaylandTextInput::findIn(inputDevice); + return QWaylandTextInput::findIn(seat); } diff --git a/src/compositor/compositor_api/qwaylandinputmethodcontrol.h b/src/compositor/compositor_api/qwaylandinputmethodcontrol.h index f71650294..ab894c9c5 100644 --- a/src/compositor/compositor_api/qwaylandinputmethodcontrol.h +++ b/src/compositor/compositor_api/qwaylandinputmethodcontrol.h @@ -74,7 +74,7 @@ Q_SIGNALS: #endif private: - void defaultInputDeviceChanged(); + void defaultSeatChanged(); void surfaceEnabled(QWaylandSurface *surface); void surfaceDisabled(QWaylandSurface *surface); }; diff --git a/src/compositor/compositor_api/qwaylandinputmethodcontrol_p.h b/src/compositor/compositor_api/qwaylandinputmethodcontrol_p.h index a687e5299..a4f9ce877 100644 --- a/src/compositor/compositor_api/qwaylandinputmethodcontrol_p.h +++ b/src/compositor/compositor_api/qwaylandinputmethodcontrol_p.h @@ -56,7 +56,7 @@ QT_BEGIN_NAMESPACE class QWaylandCompositor; -class QWaylandInputDevice; +class QWaylandSeat; class QWaylandSurface; class QWaylandTextInput; @@ -70,7 +70,7 @@ public: QWaylandTextInput *textInput() const; QWaylandCompositor *compositor; - QWaylandInputDevice *inputDevice; + QWaylandSeat *seat; QWaylandSurface *surface; bool enabled; }; diff --git a/src/compositor/compositor_api/qwaylandkeyboard.cpp b/src/compositor/compositor_api/qwaylandkeyboard.cpp index 22870654e..5bbec0a45 100644 --- a/src/compositor/compositor_api/qwaylandkeyboard.cpp +++ b/src/compositor/compositor_api/qwaylandkeyboard.cpp @@ -37,8 +37,9 @@ #include "qwaylandkeyboard.h" #include "qwaylandkeyboard_p.h" +#include <QtWaylandCompositor/QWaylandKeymap> #include <QtWaylandCompositor/QWaylandCompositor> -#include <QtWaylandCompositor/QWaylandInputDevice> +#include <QtWaylandCompositor/QWaylandSeat> #include <QtWaylandCompositor/QWaylandClient> #include <QtCore/QFile> @@ -53,7 +54,7 @@ QT_BEGIN_NAMESPACE -QWaylandKeyboardPrivate::QWaylandKeyboardPrivate(QWaylandInputDevice *seat) +QWaylandKeyboardPrivate::QWaylandKeyboardPrivate(QWaylandSeat *seat) : QtWaylandServer::wl_keyboard() , seat(seat) , focus() @@ -71,9 +72,6 @@ QWaylandKeyboardPrivate::QWaylandKeyboardPrivate(QWaylandInputDevice *seat) , repeatRate(40) , repeatDelay(400) { -#ifndef QT_NO_WAYLAND_XKB - initXKB(); -#endif } QWaylandKeyboardPrivate::~QWaylandKeyboardPrivate() @@ -232,7 +230,10 @@ void QWaylandKeyboardPrivate::updateModifierState(uint code, uint32_t state) #endif } -void QWaylandKeyboardPrivate::updateKeymap() +// If there is no key currently pressed, update the keymap right away. +// Otherwise, delay the update when keys are released +// see http://lists.freedesktop.org/archives/wayland-devel/2013-October/011395.html +void QWaylandKeyboardPrivate::maybeUpdateKeymap() { // There must be no keys pressed when changing the keymap, // see http://lists.freedesktop.org/archives/wayland-devel/2013-October/011395.html @@ -348,18 +349,19 @@ void QWaylandKeyboardPrivate::createXKBKeymap() if (!xkb_context) return; - struct xkb_rule_names rule_names = { strdup(qPrintable(keymap.rules())), - strdup(qPrintable(keymap.model())), - strdup(qPrintable(keymap.layout())), - strdup(qPrintable(keymap.variant())), - strdup(qPrintable(keymap.options())) }; - struct xkb_keymap *keymap = xkb_keymap_new_from_names(xkb_context, &rule_names, static_cast<xkb_keymap_compile_flags>(0)); - - if (keymap) { - createXKBState(keymap); - xkb_keymap_unref(keymap); + auto keymap = seat->keymap(); + struct xkb_rule_names rule_names = { strdup(qPrintable(keymap->rules())), + strdup(qPrintable(keymap->model())), + strdup(qPrintable(keymap->layout())), + strdup(qPrintable(keymap->variant())), + strdup(qPrintable(keymap->options())) }; + struct xkb_keymap *xkbKeymap = xkb_keymap_new_from_names(xkb_context, &rule_names, static_cast<xkb_keymap_compile_flags>(0)); + + if (xkbKeymap) { + createXKBState(xkbKeymap); + xkb_keymap_unref(xkbKeymap); } else { - qWarning("Failed to load the '%s' XKB keymap.", qPrintable(this->keymap.layout())); + qWarning("Failed to load the '%s' XKB keymap.", qPrintable(keymap->layout())); } free((char *)rule_names.rules); @@ -381,27 +383,36 @@ void QWaylandKeyboardPrivate::sendRepeatInfo() /*! * \class QWaylandKeyboard * \inmodule QtWaylandCompositor - * \preliminary + * \since 5.8 * \brief The QWaylandKeyboard class represents a keyboard device. * - * This class provides access to the keyboard device in a QWaylandInputDevice. It corresponds to + * This class provides access to the keyboard device in a QWaylandSeat. It corresponds to * the Wayland interface wl_keyboard. */ /*! - * Constructs a QWaylandKeyboard for the given \a inputDevice and with the given \a parent. + * Constructs a QWaylandKeyboard for the given \a seat and with the given \a parent. */ -QWaylandKeyboard::QWaylandKeyboard(QWaylandInputDevice *inputDevice, QObject *parent) - : QWaylandObject(* new QWaylandKeyboardPrivate(inputDevice), parent) +QWaylandKeyboard::QWaylandKeyboard(QWaylandSeat *seat, QObject *parent) + : QWaylandObject(* new QWaylandKeyboardPrivate(seat), parent) { Q_D(QWaylandKeyboard); connect(&d->focusDestroyListener, &QWaylandDestroyListener::fired, this, &QWaylandKeyboard::focusDestroyed); + auto keymap = seat->keymap(); + connect(keymap, &QWaylandKeymap::layoutChanged, this, &QWaylandKeyboard::updateKeymap); + connect(keymap, &QWaylandKeymap::variantChanged, this, &QWaylandKeyboard::updateKeymap); + connect(keymap, &QWaylandKeymap::optionsChanged, this, &QWaylandKeyboard::updateKeymap); + connect(keymap, &QWaylandKeymap::rulesChanged, this, &QWaylandKeyboard::updateKeymap); + connect(keymap, &QWaylandKeymap::modelChanged, this, &QWaylandKeyboard::updateKeymap); +#ifndef QT_NO_WAYLAND_XKB + d->initXKB(); +#endif } /*! - * Returns the input device for this QWaylandKeyboard. + * Returns the seat for this QWaylandKeyboard. */ -QWaylandInputDevice *QWaylandKeyboard::inputDevice() const +QWaylandSeat *QWaylandKeyboard::seat() const { Q_D(const QWaylandKeyboard); return d->seat; @@ -429,6 +440,13 @@ void QWaylandKeyboard::focusDestroyed(void *data) d->focusResource = 0; } +void QWaylandKeyboard::updateKeymap() +{ + Q_D(QWaylandKeyboard); + d->pendingKeymap = true; + d->maybeUpdateKeymap(); +} + /*! * Returns the client that currently has keyboard focus. */ @@ -538,23 +556,6 @@ void QWaylandKeyboard::setFocus(QWaylandSurface *surface) } /*! - * Sets the keyboard's keymap to \a keymap. - */ -void QWaylandKeyboard::setKeymap(const QWaylandKeymap &keymap) -{ - Q_D(QWaylandKeyboard); - d->keymap = keymap; - d->pendingKeymap = true; - - // If there is no key currently pressed, update right away the keymap - // Otherwise, delay the update when keys are released - // see http://lists.freedesktop.org/archives/wayland-devel/2013-October/011395.html - if (d->keys.isEmpty()) { - d->updateKeymap(); - } -} - -/*! * \internal */ void QWaylandKeyboard::addClient(QWaylandClient *client, uint32_t id, uint32_t version) diff --git a/src/compositor/compositor_api/qwaylandkeyboard.h b/src/compositor/compositor_api/qwaylandkeyboard.h index b5bf6fe5c..685134ff7 100644 --- a/src/compositor/compositor_api/qwaylandkeyboard.h +++ b/src/compositor/compositor_api/qwaylandkeyboard.h @@ -47,27 +47,8 @@ QT_BEGIN_NAMESPACE class QWaylandKeyboard; class QWaylandKeyboardPrivate; -class QWaylandInputDevice; - -class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandKeymap -{ -public: - QWaylandKeymap(const QString &layout = QString(), const QString &variant = QString(), const QString &options = QString(), - const QString &model = QString(), const QString &rules = QString()); - - inline QString layout() const { return m_layout; } - inline QString variant() const { return m_variant; } - inline QString options() const { return m_options; } - inline QString rules() const { return m_rules; } - inline QString model() const { return m_model; } - -private: - QString m_layout; - QString m_variant; - QString m_options; - QString m_rules; - QString m_model; -}; +class QWaylandSeat; +class QWaylandKeymap; class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandKeyboard : public QWaylandObject { @@ -76,9 +57,9 @@ class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandKeyboard : public QWaylandObject Q_PROPERTY(quint32 repeatRate READ repeatRate WRITE setRepeatRate NOTIFY repeatRateChanged) Q_PROPERTY(quint32 repeatDelay READ repeatDelay WRITE setRepeatDelay NOTIFY repeatDelayChanged) public: - QWaylandKeyboard(QWaylandInputDevice *inputDevice, QObject *parent = nullptr); + QWaylandKeyboard(QWaylandSeat *seat, QObject *parent = nullptr); - QWaylandInputDevice *inputDevice() const; + QWaylandSeat *seat() const; QWaylandCompositor *compositor() const; quint32 repeatRate() const; @@ -88,7 +69,6 @@ public: void setRepeatDelay(quint32 delay); virtual void setFocus(QWaylandSurface *surface); - virtual void setKeymap(const QWaylandKeymap &keymap); virtual void sendKeyModifiers(QWaylandClient *client, uint32_t serial); virtual void sendKeyPressEvent(uint code); @@ -106,6 +86,9 @@ Q_SIGNALS: private: void focusDestroyed(void *data); + +private Q_SLOTS: + void updateKeymap(); }; QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandkeyboard_p.h b/src/compositor/compositor_api/qwaylandkeyboard_p.h index ede97d8ba..fc43853cc 100644 --- a/src/compositor/compositor_api/qwaylandkeyboard_p.h +++ b/src/compositor/compositor_api/qwaylandkeyboard_p.h @@ -50,7 +50,7 @@ // #include <QtWaylandCompositor/qwaylandexport.h> -#include <QtWaylandCompositor/qwaylandinput.h> +#include <QtWaylandCompositor/qwaylandseat.h> #include <QtWaylandCompositor/qwaylandkeyboard.h> #include <QtWaylandCompositor/qwaylanddestroylistener.h> @@ -74,7 +74,7 @@ public: static QWaylandKeyboardPrivate *get(QWaylandKeyboard *keyboard); - QWaylandKeyboardPrivate(QWaylandInputDevice *seat); + QWaylandKeyboardPrivate(QWaylandSeat *seat); ~QWaylandKeyboardPrivate(); QWaylandCompositor *compositor() const { return seat->compositor(); } @@ -91,7 +91,7 @@ public: void keyEvent(uint code, uint32_t state); void sendKeyEvent(uint code, uint32_t state); void updateModifierState(uint code, uint32_t state); - void updateKeymap(); + void maybeUpdateKeymap(); void checkFocusResource(Resource *resource); void sendEnter(QWaylandSurface *surface, Resource *resource); @@ -111,7 +111,7 @@ private: void sendRepeatInfo(); - QWaylandInputDevice *seat; + QWaylandSeat *seat; QWaylandSurface *focus; Resource *focusResource; @@ -123,7 +123,6 @@ private: uint32_t modsLocked; uint32_t group; - QWaylandKeymap keymap; bool pendingKeymap; #ifndef QT_NO_WAYLAND_XKB size_t keymap_size; diff --git a/src/compositor/compositor_api/qwaylandkeymap.cpp b/src/compositor/compositor_api/qwaylandkeymap.cpp new file mode 100644 index 000000000..d11070f26 --- /dev/null +++ b/src/compositor/compositor_api/qwaylandkeymap.cpp @@ -0,0 +1,129 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWaylandCompositor module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwaylandkeymap.h" +#include "qwaylandkeymap_p.h" + +QT_BEGIN_NAMESPACE + +QWaylandKeymap::QWaylandKeymap(const QString &layout, const QString &variant, const QString &options, const QString &model, const QString &rules, QObject *parent) + : QObject(*new QWaylandKeymapPrivate(layout, variant, options, model, rules), parent) +{ +} + +QString QWaylandKeymap::layout() const { + Q_D(const QWaylandKeymap); + return d->m_layout; +} + +void QWaylandKeymap::setLayout(const QString &layout) +{ + Q_D(QWaylandKeymap); + if (d->m_layout == layout) + return; + d->m_layout = layout; + emit layoutChanged(); +} + +QString QWaylandKeymap::variant() const +{ + Q_D(const QWaylandKeymap); + return d->m_variant; +} + +void QWaylandKeymap::setVariant(const QString &variant) +{ + Q_D(QWaylandKeymap); + if (d->m_variant == variant) + return; + d->m_variant = variant; + emit variantChanged(); +} + +QString QWaylandKeymap::options() const { + Q_D(const QWaylandKeymap); + return d->m_options; +} + +void QWaylandKeymap::setOptions(const QString &options) +{ + Q_D(QWaylandKeymap); + if (d->m_options == options) + return; + d->m_options = options; + emit optionsChanged(); +} + +QString QWaylandKeymap::rules() const { + Q_D(const QWaylandKeymap); + return d->m_rules; +} + +void QWaylandKeymap::setRules(const QString &rules) +{ + Q_D(QWaylandKeymap); + if (d->m_rules == rules) + return; + d->m_rules = rules; + emit rulesChanged(); +} + +QString QWaylandKeymap::model() const { + Q_D(const QWaylandKeymap); + return d->m_model; +} + +void QWaylandKeymap::setModel(const QString &model) +{ + Q_D(QWaylandKeymap); + if (d->m_model == model) + return; + d->m_model = model; + emit modelChanged(); +} + +QWaylandKeymapPrivate::QWaylandKeymapPrivate(const QString &layout, const QString &variant, + const QString &options, const QString &model, + const QString &rules) + : m_layout(layout) + , m_variant(variant) + , m_options(options) + , m_rules(rules) + , m_model(model) +{ +} + +QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandkeymap.h b/src/compositor/compositor_api/qwaylandkeymap.h new file mode 100644 index 000000000..c543691df --- /dev/null +++ b/src/compositor/compositor_api/qwaylandkeymap.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWaylandCompositor module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDKEYMAP_H +#define QWAYLANDKEYMAP_H + +#include <QtCore/QObject> +#include <QtWaylandCompositor/qwaylandexport.h> + +QT_BEGIN_NAMESPACE + +class QWaylandKeymapPrivate; + +class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandKeymap : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QWaylandKeymap) + Q_PROPERTY(QString layout READ layout WRITE setLayout NOTIFY layoutChanged) + Q_PROPERTY(QString variant READ variant WRITE setVariant NOTIFY variantChanged) + Q_PROPERTY(QString options READ options WRITE setOptions NOTIFY optionsChanged) + Q_PROPERTY(QString rules READ rules WRITE setRules NOTIFY rulesChanged) + Q_PROPERTY(QString model READ model WRITE setModel NOTIFY modelChanged) +public: + QWaylandKeymap(const QString &layout = QString(), const QString &variant = QString(), const QString &options = QString(), + const QString &model = QString(), const QString &rules = QString(), QObject *parent = nullptr); + + QString layout() const; + void setLayout(const QString &layout); + QString variant() const; + void setVariant(const QString &variant); + QString options() const; + void setOptions(const QString &options); + QString rules() const; + void setRules(const QString &rules); + QString model() const; + void setModel(const QString &model); + +Q_SIGNALS: + void layoutChanged(); + void variantChanged(); + void optionsChanged(); + void rulesChanged(); + void modelChanged(); +}; + +QT_END_NAMESPACE + +#endif //QWAYLANDKEYMAP_H diff --git a/src/compositor/compositor_api/qwaylandkeymap_p.h b/src/compositor/compositor_api/qwaylandkeymap_p.h new file mode 100644 index 000000000..2c968ef38 --- /dev/null +++ b/src/compositor/compositor_api/qwaylandkeymap_p.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWaylandCompositor module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDKEYMAP_P_H +#define QWAYLANDKEYMAP_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtWaylandCompositor/qwaylandkeymap.h> +#include <QtCore/private/qobject_p.h> + +QT_BEGIN_NAMESPACE + +class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandKeymapPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QWaylandKeymap) +public: + QWaylandKeymapPrivate(const QString &layout, const QString &variant, const QString &options, + const QString &model, const QString &rules); + + QString m_layout; + QString m_variant; + QString m_options; + QString m_rules; + QString m_model; +}; + +QT_END_NAMESPACE + +#endif // QWAYLANDKEYMAP_P_H diff --git a/src/compositor/compositor_api/qwaylandoutput.cpp b/src/compositor/compositor_api/qwaylandoutput.cpp index a2ebf8b25..0129bd33b 100644 --- a/src/compositor/compositor_api/qwaylandoutput.cpp +++ b/src/compositor/compositor_api/qwaylandoutput.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2014-2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> +** Copyright (C) 2014-2016 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> ** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB). ** Contact: http://www.qt.io/licensing/ ** @@ -48,6 +48,7 @@ #include <QtCore/QtMath> #include <QtGui/QWindow> #include <QtGui/QExposeEvent> +#include <QtGui/QScreen> #include <private/qobject_p.h> QT_BEGIN_NAMESPACE @@ -102,16 +103,14 @@ QWaylandOutputPrivate::QWaylandOutputPrivate() : QtWaylandServer::wl_output() , compositor(Q_NULLPTR) , window(Q_NULLPTR) + , currentMode(-1) + , preferredMode(-1) , subpixel(QWaylandOutput::SubpixelUnknown) , transform(QWaylandOutput::TransformNormal) , scaleFactor(1) - , sizeFollowsWindow(true) + , sizeFollowsWindow(false) , initialized(false) { - mode.size = QSize(); - mode.refreshRate = 60; - - qRegisterMetaType<QWaylandOutput::Mode>("WaylandOutput::Mode"); } QWaylandOutputPrivate::~QWaylandOutputPrivate() @@ -120,15 +119,10 @@ QWaylandOutputPrivate::~QWaylandOutputPrivate() void QWaylandOutputPrivate::output_bind_resource(Resource *resource) { - send_geometry(resource->handle, - position.x(), position.y(), - physicalSize.width(), physicalSize.height(), - toWlSubpixel(subpixel), manufacturer, model, - toWlTransform(transform)); + sendGeometry(resource); - send_mode(resource->handle, mode_current | mode_preferred, - mode.size.width(), mode.size.height(), - mode.refreshRate * 1000); + for (const QWaylandOutputMode &mode : modes) + sendMode(resource, mode); if (resource->version() >= 2) { send_scale(resource->handle, scaleFactor); @@ -136,19 +130,46 @@ void QWaylandOutputPrivate::output_bind_resource(Resource *resource) } } +void QWaylandOutputPrivate::sendGeometry(const Resource *resource) +{ + send_geometry(resource->handle, + position.x(), position.y(), + physicalSize.width(), physicalSize.height(), + toWlSubpixel(subpixel), manufacturer, model, + toWlTransform(transform)); +} + void QWaylandOutputPrivate::sendGeometryInfo() { - Q_FOREACH (Resource *resource, resourceMap().values()) { - send_geometry(resource->handle, - position.x(), position.y(), - physicalSize.width(), physicalSize.height(), - toWlSubpixel(subpixel), manufacturer, model, - toWlTransform(transform)); + for (const Resource *resource : resourceMap().values()) { + sendGeometry(resource); if (resource->version() >= 2) send_done(resource->handle); } } +void QWaylandOutputPrivate::sendMode(const Resource *resource, const QWaylandOutputMode &mode) +{ + quint32 flags = 0; + if (currentMode == modes.indexOf(mode)) + flags |= QtWaylandServer::wl_output::mode_current; + if (preferredMode == modes.indexOf(mode)) + flags |= QtWaylandServer::wl_output::mode_preferred; + + send_mode(resource->handle, flags, + mode.size().width(), mode.size().height(), + mode.refreshRate()); +} + +void QWaylandOutputPrivate::sendModesInfo() +{ + for (const Resource *resource : resourceMap().values()) { + for (const QWaylandOutputMode &mode : modes) + sendMode(resource, mode); + if (resource->version() >= 2) + send_done(resource->handle); + } +} void QWaylandOutputPrivate::addView(QWaylandView *view, QWaylandSurface *surface) { @@ -189,7 +210,7 @@ QWaylandOutput::QWaylandOutput() /*! \qmltype WaylandOutput \inqmlmodule QtWayland.Compositor - \preliminary + \since 5.8 \brief Provides access to a displayable area managed by the compositor. The WaylandOutput manages a rectangular area within bounds of the compositor's @@ -202,7 +223,7 @@ QWaylandOutput::QWaylandOutput() /*! \class QWaylandOutput \inmodule QtWaylandCompositor - \preliminary + \since 5.8 \brief The QWaylandOutput class represents a displayable area managed by the compositor. The QWaylandOutput manages a rectangular area within bounds of the compositor's @@ -252,16 +273,23 @@ void QWaylandOutput::initialize() Q_ASSERT(d->compositor); Q_ASSERT(d->compositor->isCreated()); - if (d->window) - d->mode.size = d->window->size(); - else - d->sizeFollowsWindow = false; + // Replace modes with one that follows the window size and refresh rate, + // but only if window size is valid + if (d->window && d->sizeFollowsWindow) { + QWaylandOutputMode mode(d->window->size(), + qFloor(d->window->screen()->refreshRate() * 1000)); + if (mode.isValid()) { + d->modes.clear(); + addMode(mode, true); + setCurrentMode(mode); + } + } QWaylandCompositorPrivate::get(d->compositor)->addOutput(this); if (d->window) { - QObject::connect(d->window, &QWindow::widthChanged, this, &QWaylandOutput::setWidth); - QObject::connect(d->window, &QWindow::heightChanged, this, &QWaylandOutput::setHeight); + QObject::connect(d->window, &QWindow::widthChanged, this, &QWaylandOutput::handleSetWidth); + QObject::connect(d->window, &QWindow::heightChanged, this, &QWaylandOutput::handleSetHeight); QObject::connect(d->window, &QObject::destroyed, this, &QWaylandOutput::handleWindowDestroyed); } @@ -431,39 +459,75 @@ void QWaylandOutput::setPosition(const QPoint &pt) } /*! - * \property QWaylandOutput::mode - * - * This property holds the output's size in pixels and refresh rate in Hz. + * Returns the list of modes. */ -QWaylandOutput::Mode QWaylandOutput::mode() const +QList<QWaylandOutputMode> QWaylandOutput::modes() const { - return d_func()->mode; + Q_D(const QWaylandOutput); + return d->modes.toList(); } -void QWaylandOutput::setMode(const Mode &mode) +/*! + * Adds the mode \a mode to the output and mark it as preferred + * if \a preferred is \c true. + * Please note there can only be one preferred mode. + */ +void QWaylandOutput::addMode(const QWaylandOutputMode &mode, bool preferred) { Q_D(QWaylandOutput); - if (d->mode.size == mode.size && d->mode.refreshRate == mode.refreshRate) + + if (!mode.isValid()) { + qWarning("Cannot add an invalid mode"); return; + } - d->mode = mode; + d->modes.append(mode); - Q_FOREACH (QWaylandOutputPrivate::Resource *resource, d->resourceMap().values()) { - d->send_mode(resource->handle, d->mode_current, - d->mode.size.width(), d->mode.size.height(), - d->mode.refreshRate * 1000); - if (resource->version() >= 2) - d->send_done(resource->handle); + if (preferred) + d->preferredMode = d->modes.indexOf(mode); + + emit modeAdded(); +} + +/*! + * Returns the output's size in pixels and refresh rate in mHz. + * If the current mode is not set it will return an invalid mode. + * + * \sa QWaylandOutput::modes + * \sa QWaylandOutputMode + */ +QWaylandOutputMode QWaylandOutput::currentMode() const +{ + Q_D(const QWaylandOutput); + + if (d->currentMode >= 0 && d->currentMode <= d->modes.size() - 1) + return d->modes.at(d->currentMode); + return QWaylandOutputMode(); +} + +/*! + * Sets the current mode. + * The mode \a mode must have been previously added. + * + * \sa QWaylandOutput::modes + * \sa QWaylandOutputMode + */ +void QWaylandOutput::setCurrentMode(const QWaylandOutputMode &mode) +{ + Q_D(QWaylandOutput); + + int index = d->modes.indexOf(mode); + if (index < 0) { + qWarning("Cannot set an unknown QWaylandOutput mode as current"); + return; } - Q_EMIT modeChanged(); + d->currentMode = index; + + Q_EMIT currentModeChanged(); Q_EMIT geometryChanged(); - if (d->window) { - d->window->resize(mode.size); - d->window->setMinimumSize(mode.size); - d->window->setMaximumSize(mode.size); - } + d->sendModesInfo(); } /*! @@ -477,37 +541,12 @@ void QWaylandOutput::setMode(const Mode &mode) * * This property holds the geometry of the QWaylandOutput. * - * \sa QWaylandOutput::mode + * \sa QWaylandOutput::currentMode */ QRect QWaylandOutput::geometry() const { Q_D(const QWaylandOutput); - return QRect(d->position, d->mode.size); -} - -void QWaylandOutput::setGeometry(const QRect &geometry) -{ - Q_D(QWaylandOutput); - if (d->position == geometry.topLeft() && d->mode.size == geometry.size()) - return; - - d->position = geometry.topLeft(); - d->mode.size = geometry.size(); - - Q_FOREACH (QWaylandOutputPrivate::Resource *resource, d->resourceMap().values()) { - d->send_geometry(resource->handle, - d->position.x(), d->position.y(), - d->physicalSize.width(), d->physicalSize.height(), - toWlSubpixel(d->subpixel), d->manufacturer, d->model, - toWlTransform(d->transform)); - d->send_mode(resource->handle, d->mode_current, - d->mode.size.width(), d->mode.size.height(), - d->mode.refreshRate * 1000); - if (resource->version() >= 2) - d->send_done(resource->handle); - } - Q_EMIT positionChanged(); - Q_EMIT modeChanged(); + return QRect(d->position, currentMode().size()); } /*! @@ -527,13 +566,14 @@ void QWaylandOutput::setGeometry(const QRect &geometry) * The available geometry is in output coordinates space, starts from 0,0 and it's as big * as the output by default. * - * \sa QWaylandOutput::mode, QWaylandOutput::geometry + * \sa QWaylandOutput::currentMode, QWaylandOutput::geometry */ QRect QWaylandOutput::availableGeometry() const { Q_D(const QWaylandOutput); + if (!d->availableGeometry.isValid()) - return QRect(QPoint(0, 0), d->mode.size); + return QRect(QPoint(0, 0), currentMode().size()); return d->availableGeometry; } @@ -565,7 +605,7 @@ void QWaylandOutput::setAvailableGeometry(const QRect &availableGeometry) * * This property holds the physical size of the QWaylandOutput in millimeters. * - * \sa QWaylandOutput::geometry, QWaylandOutput::mode + * \sa QWaylandOutput::geometry, QWaylandOutput::currentMode */ QSize QWaylandOutput::physicalSize() const { @@ -755,7 +795,10 @@ void QWaylandOutput::setScaleFactor(int scale) * This property controls whether the size of the WaylandOutput matches the * size of its window. * - * The default is \c true if this WaylandOutput has a window. + * If this property is true, all modes previously added are replaced by a + * mode that matches window size and screen refresh rate. + * + * The default is false. */ /*! @@ -764,7 +807,10 @@ void QWaylandOutput::setScaleFactor(int scale) * This property controls whether the size of the QWaylandOutput matches the * size of its window. * - * The default is \c true if this QWaylandOutput has a window. + * If this property is true, all modes previously added are replaced by a + * mode that matches window size and screen refresh rate. + * + * The default is false. */ bool QWaylandOutput::sizeFollowsWindow() const { @@ -781,13 +827,6 @@ void QWaylandOutput::setSizeFollowsWindow(bool follow) } if (follow != d->sizeFollowsWindow) { - if (follow) { - QObject::connect(d->window, &QWindow::widthChanged, this, &QWaylandOutput::setWidth); - QObject::connect(d->window, &QWindow::heightChanged, this, &QWaylandOutput::setHeight); - } else { - QObject::disconnect(d->window, &QWindow::widthChanged, this, &QWaylandOutput::setWidth); - QObject::disconnect(d->window, &QWindow::heightChanged, this, &QWaylandOutput::setHeight); - } d->sizeFollowsWindow = follow; Q_EMIT sizeFollowsWindowChanged(); } @@ -833,7 +872,7 @@ void QWaylandOutput::frameStarted() Q_D(QWaylandOutput); for (int i = 0; i < d->surfaceViews.size(); i++) { QWaylandSurfaceViewMapper &surfacemapper = d->surfaceViews[i]; - if (surfacemapper.maybeThrottelingView()) + if (surfacemapper.maybePrimaryView()) surfacemapper.surface->frameStarted(); } } @@ -846,12 +885,12 @@ void QWaylandOutput::sendFrameCallbacks() Q_D(QWaylandOutput); for (int i = 0; i < d->surfaceViews.size(); i++) { const QWaylandSurfaceViewMapper &surfacemapper = d->surfaceViews.at(i); - if (surfacemapper.surface && surfacemapper.surface->isMapped()) { + if (surfacemapper.surface && surfacemapper.surface->hasContent()) { if (!surfacemapper.has_entered) { surfaceEnter(surfacemapper.surface); d->surfaceViews[i].has_entered = true; } - if (surfacemapper.maybeThrottelingView()) + if (surfacemapper.maybePrimaryView()) surfacemapper.surface->sendFrameCallbacks(); } } @@ -882,35 +921,63 @@ void QWaylandOutput::surfaceLeave(QWaylandSurface *surface) } /*! - * Sets the width of this QWaylandOutput to \a newWidth. - * - * \sa setHeight, QWaylandOutput::geometry + * \internal */ -void QWaylandOutput::setWidth(int newWidth) +void QWaylandOutput::handleSetWidth(int newWidth) { Q_D(QWaylandOutput); - if (d->mode.size.width() == newWidth) + + if (!d->window || !d->sizeFollowsWindow) return; - QSize s = d->mode.size; - s.setWidth(newWidth); - setGeometry(QRect(d->position, s)); + if (d->currentMode <= d->modes.size() - 1) { + if (d->currentMode >= 0) { + QWaylandOutputMode mode = d->modes.at(d->currentMode); + mode.setWidth(newWidth); + d->modes.replace(d->currentMode, mode); + d->sendModesInfo(); + } else { + // We didn't add a mode during the initialization because the window + // size was invalid, let's add it now + QWaylandOutputMode mode(d->window->size(), + qFloor(d->window->screen()->refreshRate() * 1000)); + if (mode.isValid()) { + d->modes.clear(); + addMode(mode, true); + setCurrentMode(mode); + } + } + } } /*! - * Sets the height of this QWaylandOutput to \a newHeight. - * - * \sa setWidth, QWaylandOutput::geometry + * \internal */ -void QWaylandOutput::setHeight(int newHeight) +void QWaylandOutput::handleSetHeight(int newHeight) { Q_D(QWaylandOutput); - if (d->mode.size.height() == newHeight) + + if (!d->window || !d->sizeFollowsWindow) return; - QSize s = d->mode.size; - s.setHeight(newHeight); - setGeometry(QRect(d->position, s)); + if (d->currentMode <= d->modes.size() - 1) { + if (d->currentMode >= 0) { + QWaylandOutputMode mode = d->modes.at(d->currentMode); + mode.setHeight(newHeight); + d->modes.replace(d->currentMode, mode); + d->sendModesInfo(); + } else { + // We didn't add a mode during the initialization because the window + // size was invalid, let's add it now + QWaylandOutputMode mode(d->window->size(), + qFloor(d->window->screen()->refreshRate() * 1000)); + if (mode.isValid()) { + d->modes.clear(); + addMode(mode, true); + setCurrentMode(mode); + } + } + } } /*! diff --git a/src/compositor/compositor_api/qwaylandoutput.h b/src/compositor/compositor_api/qwaylandoutput.h index e4cbb6109..190231c12 100644 --- a/src/compositor/compositor_api/qwaylandoutput.h +++ b/src/compositor/compositor_api/qwaylandoutput.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2014-2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> +** Copyright (C) 2014-2016 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> ** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB). ** Contact: http://www.qt.io/licensing/ ** @@ -39,6 +39,7 @@ #define QWAYLANDOUTPUT_H #include <QtWaylandCompositor/qwaylandcompositorextension.h> +#include <QtWaylandCompositor/QWaylandOutputMode> #include <QtCore/QObject> #include <QObject> @@ -66,7 +67,6 @@ class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandOutput : public QWaylandObject Q_PROPERTY(QString manufacturer READ manufacturer WRITE setManufacturer NOTIFY manufacturerChanged) Q_PROPERTY(QString model READ model WRITE setModel NOTIFY modelChanged) Q_PROPERTY(QPoint position READ position WRITE setPosition NOTIFY positionChanged) - Q_PROPERTY(QWaylandOutput::Mode mode READ mode WRITE setMode NOTIFY modeChanged) Q_PROPERTY(QRect geometry READ geometry NOTIFY geometryChanged) Q_PROPERTY(QRect availableGeometry READ availableGeometry WRITE setAvailableGeometry NOTIFY availableGeometryChanged) Q_PROPERTY(QSize physicalSize READ physicalSize WRITE setPhysicalSize NOTIFY physicalSizeChanged) @@ -99,12 +99,6 @@ public: }; Q_ENUM(Transform) - struct Mode - { - QSize size; - qreal refreshRate; - }; - QWaylandOutput(); QWaylandOutput(QWaylandCompositor *compositor, QWindow *window); ~QWaylandOutput(); @@ -127,13 +121,14 @@ public: QPoint position() const; void setPosition(const QPoint &pt); - Mode mode() const; - void setMode(const Mode &mode); + QList<QWaylandOutputMode> modes() const; + + void addMode(const QWaylandOutputMode &mode, bool preferred = false); + + QWaylandOutputMode currentMode() const; + void setCurrentMode(const QWaylandOutputMode &mode); QRect geometry() const; - void setGeometry(const QRect &geometry); - void setWidth(int newWidth); - void setHeight(int newHeight); QRect availableGeometry() const; void setAvailableGeometry(const QRect &availableGeometry); @@ -169,7 +164,8 @@ Q_SIGNALS: void windowChanged(); void positionChanged(); void geometryChanged(); - void modeChanged(); + void modeAdded(); + void currentModeChanged(); void availableGeometryChanged(); void physicalSizeChanged(); void scaleFactorChanged(); @@ -182,6 +178,8 @@ Q_SIGNALS: void windowDestroyed(); private Q_SLOTS: + void handleSetWidth(int newWidth); + void handleSetHeight(int newHeight); void handleWindowDestroyed(); protected: @@ -192,6 +190,4 @@ protected: QT_END_NAMESPACE -Q_DECLARE_METATYPE(QWaylandOutput::Mode) - #endif // QWAYLANDOUTPUT_H diff --git a/src/compositor/compositor_api/qwaylandoutput_p.h b/src/compositor/compositor_api/qwaylandoutput_p.h index 9b6ba9076..638575db9 100644 --- a/src/compositor/compositor_api/qwaylandoutput_p.h +++ b/src/compositor/compositor_api/qwaylandoutput_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2014-2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> +** Copyright (C) 2014-2016 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> ** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB). ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ @@ -78,10 +78,10 @@ struct QWaylandSurfaceViewMapper , has_entered(false) {} - QWaylandView *maybeThrottelingView() const + QWaylandView *maybePrimaryView() const { for (int i = 0; i < views.size(); i++) { - if (surface && surface->throttlingView() == views.at(i)) + if (surface && surface->primaryView() == views.at(i)) return views.at(i); } return Q_NULLPTR; @@ -102,19 +102,25 @@ public: void addView(QWaylandView *view, QWaylandSurface *surface); void removeView(QWaylandView *view, QWaylandSurface *surface); + + void sendGeometry(const Resource *resource); void sendGeometryInfo(); + void sendMode(const Resource *resource, const QWaylandOutputMode &mode); + void sendModesInfo(); + protected: void output_bind_resource(Resource *resource) Q_DECL_OVERRIDE; - private: QWaylandCompositor *compositor; QWindow *window; QString manufacturer; QString model; QPoint position; - QWaylandOutput::Mode mode; + QVector<QWaylandOutputMode> modes; + int currentMode; + int preferredMode; QRect availableGeometry; QVector<QWaylandSurfaceViewMapper> surfaceViews; QSize physicalSize; diff --git a/src/compositor/compositor_api/qwaylandoutputmode.cpp b/src/compositor/compositor_api/qwaylandoutputmode.cpp new file mode 100644 index 000000000..463b984ad --- /dev/null +++ b/src/compositor/compositor_api/qwaylandoutputmode.cpp @@ -0,0 +1,139 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWaylandCompositor module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwaylandoutputmode.h" +#include "qwaylandoutputmode_p.h" + +/*! + \class QWaylandOutputMode + \inmodule QtWaylandCompositor + \since 5.8 + \brief The QWaylandOutputMode class holds the resolution and refresh rate of an output. + + QWaylandOutputMode holds the resolution and refresh rate of an output. + Resolution is expressed in pixels and refresh rate is measured in mHz. + + \sa QWaylandOutput +*/ + +QWaylandOutputMode::QWaylandOutputMode() + : d(new QWaylandOutputModePrivate) +{ +} + +QWaylandOutputMode::QWaylandOutputMode(const QSize &size, int refreshRate) + : d(new QWaylandOutputModePrivate) +{ + d->size = size; + d->refreshRate = refreshRate; +} + +QWaylandOutputMode::QWaylandOutputMode(const QWaylandOutputMode &other) + : d(new QWaylandOutputModePrivate) +{ + d->size = other.size(); + d->refreshRate = other.refreshRate(); +} + +QWaylandOutputMode::~QWaylandOutputMode() +{ + delete d; +} + +QWaylandOutputMode &QWaylandOutputMode::operator=(const QWaylandOutputMode &other) +{ + d->size = other.size(); + d->refreshRate = other.refreshRate(); + return *this; +} + +/*! + Returns \c true if this mode is equal to \a other, + otherwise returns \c false. +*/ +bool QWaylandOutputMode::operator==(const QWaylandOutputMode &other) const +{ + return size() == other.size() && refreshRate() == refreshRate(); +} + +/*! + Returns \c true if this mode is not equal to \a other, + otherwise returns \c false. +*/ +bool QWaylandOutputMode::operator!=(const QWaylandOutputMode &other) const +{ + return size() != other.size() || refreshRate() != refreshRate(); +} + +/*! + Returns whether this mode contains a valid resolution and refresh rate. +*/ +bool QWaylandOutputMode::isValid() const +{ + return !d->size.isEmpty() && d->refreshRate > 0; +} + +/*! + Returns the resolution in pixels. +*/ +QSize QWaylandOutputMode::size() const +{ + return d->size; +} + +/*! + Returns the refresh rate in mHz. +*/ +int QWaylandOutputMode::refreshRate() const +{ + return d->refreshRate; +} + +/*! + * \internal + */ +void QWaylandOutputMode::setWidth(int width) +{ + d->size.setWidth(width); +} + +/*! + * \internal + */ +void QWaylandOutputMode::setHeight(int height) +{ + d->size.setHeight(height); +} diff --git a/src/compositor/compositor_api/qwaylandoutputmode.h b/src/compositor/compositor_api/qwaylandoutputmode.h new file mode 100644 index 000000000..4ef57f2ee --- /dev/null +++ b/src/compositor/compositor_api/qwaylandoutputmode.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWaylandCompositor module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDOUTPUTMODE_H +#define QWAYLANDOUTPUTMODE_H + +#include <QtWaylandCompositor/qwaylandexport.h> +#include <QtCore/QSize> + +QT_BEGIN_NAMESPACE + +class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandOutputMode +{ +public: + explicit QWaylandOutputMode(); + QWaylandOutputMode(const QSize &size, int refreshRate); + QWaylandOutputMode(const QWaylandOutputMode &other); + ~QWaylandOutputMode(); + + QWaylandOutputMode &operator=(const QWaylandOutputMode &other); + bool operator==(const QWaylandOutputMode &other) const; + bool operator!=(const QWaylandOutputMode &other) const; + + bool isValid() const; + + QSize size() const; + int refreshRate() const; + +private: + class QWaylandOutputModePrivate *const d; + friend class QWaylandOutput; + + void setWidth(int width); + void setHeight(int height); +}; + +QT_END_NAMESPACE + +#endif // QWAYLANDOUTPUTMODE_H diff --git a/src/compositor/compositor_api/qwaylandoutputmode_p.h b/src/compositor/compositor_api/qwaylandoutputmode_p.h new file mode 100644 index 000000000..e9a0eaa37 --- /dev/null +++ b/src/compositor/compositor_api/qwaylandoutputmode_p.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWaylandCompositor module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDOUTPUTMODE_P_H +#define QWAYLANDOUTPUTMODE_P_H + +#include <QtWaylandCompositor/QWaylandOutput> + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +QT_BEGIN_NAMESPACE + +class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandOutputModePrivate +{ +public: + QWaylandOutputModePrivate() {} + + QSize size; + int refreshRate = 60000; +}; + +QT_END_NAMESPACE + +#endif // QWAYLANDOUTPUTMODE_P_H diff --git a/src/compositor/compositor_api/qwaylandpointer.cpp b/src/compositor/compositor_api/qwaylandpointer.cpp index 5e9778637..2ff56a1e6 100644 --- a/src/compositor/compositor_api/qwaylandpointer.cpp +++ b/src/compositor/compositor_api/qwaylandpointer.cpp @@ -43,7 +43,7 @@ QT_BEGIN_NAMESPACE QWaylandSurfaceRole QWaylandPointerPrivate::s_role("wl_pointer"); -QWaylandPointerPrivate::QWaylandPointerPrivate(QWaylandPointer *pointer, QWaylandInputDevice *seat) +QWaylandPointerPrivate::QWaylandPointerPrivate(QWaylandPointer *pointer, QWaylandSeat *seat) : QObjectPrivate() , wl_pointer() , seat(seat) @@ -94,27 +94,27 @@ void QWaylandPointerPrivate::pointer_set_cursor(wl_pointer::Resource *resource, /*! * \class QWaylandPointer * \inmodule QtWaylandCompositor - * \preliminary + * \since 5.8 * \brief The QWaylandPointer class represents a pointer device. * - * This class provides access to the pointer device in a QWaylandInputDevice. It corresponds to + * This class provides access to the pointer device in a QWaylandSeat. It corresponds to * the Wayland interface wl_pointer. */ /*! - * Constructs a QWaylandPointer for the given \a inputDevice and with the given \a parent. + * Constructs a QWaylandPointer for the given \a seat and with the given \a parent. */ -QWaylandPointer::QWaylandPointer(QWaylandInputDevice *inputDevice, QObject *parent) - : QWaylandObject(* new QWaylandPointerPrivate(this, inputDevice), parent) +QWaylandPointer::QWaylandPointer(QWaylandSeat *seat, QObject *parent) + : QWaylandObject(* new QWaylandPointerPrivate(this, seat), parent) { connect(&d_func()->focusDestroyListener, &QWaylandDestroyListener::fired, this, &QWaylandPointer::focusDestroyed); - connect(inputDevice, &QWaylandInputDevice::mouseFocusChanged, this, &QWaylandPointer::pointerFocusChanged); + connect(seat, &QWaylandSeat::mouseFocusChanged, this, &QWaylandPointer::pointerFocusChanged); } /*! * Returns the input device for this QWaylandPointer. */ -QWaylandInputDevice *QWaylandPointer::inputDevice() const +QWaylandSeat *QWaylandPointer::seat() const { Q_D(const QWaylandPointer); return d->seat; @@ -151,34 +151,45 @@ void QWaylandPointer::setOutput(QWaylandOutput *output) /*! * Sends a mouse press event for \a button to the view currently holding mouse focus. + * + * Returns the serial number of the press event. */ -void QWaylandPointer::sendMousePressEvent(Qt::MouseButton button) +uint QWaylandPointer::sendMousePressEvent(Qt::MouseButton button) { Q_D(QWaylandPointer); uint32_t time = d->compositor()->currentTimeMsecs(); d->buttonCount++; + uint serial = 0; + if (d->focusResource) - sendButton(d->focusResource, time, button, WL_POINTER_BUTTON_STATE_PRESSED); + serial = sendButton(d->focusResource, time, button, WL_POINTER_BUTTON_STATE_PRESSED); if (d->buttonCount == 1) { emit buttonPressedChanged(); } + + return serial; } /*! * Sends a mouse release event for \a button to the view currently holding mouse focus. + * + * Returns the serial number of the release event. */ -void QWaylandPointer::sendMouseReleaseEvent(Qt::MouseButton button) +uint QWaylandPointer::sendMouseReleaseEvent(Qt::MouseButton button) { Q_D(QWaylandPointer); uint32_t time = d->compositor()->currentTimeMsecs(); d->buttonCount--; + uint serial = 0; if (d->focusResource) - sendButton(d->focusResource, time, button, WL_POINTER_BUTTON_STATE_RELEASED); + serial = sendButton(d->focusResource, time, button, WL_POINTER_BUTTON_STATE_RELEASED); if (d->buttonCount == 0) emit buttonPressedChanged(); + + return serial; } /*! @@ -308,11 +319,12 @@ struct wl_resource *QWaylandPointer::focusResource() const /*! * \internal */ -void QWaylandPointer::sendButton(struct wl_resource *resource, uint32_t time, Qt::MouseButton button, uint32_t state) +uint QWaylandPointer::sendButton(struct wl_resource *resource, uint32_t time, Qt::MouseButton button, uint32_t state) { Q_D(QWaylandPointer); uint32_t serial = d->compositor()->nextSerial(); d->send_button(resource, serial, time, toWaylandButton(button), state); + return serial; } /*! diff --git a/src/compositor/compositor_api/qwaylandpointer.h b/src/compositor/compositor_api/qwaylandpointer.h index 9d7d06807..87bf31c97 100644 --- a/src/compositor/compositor_api/qwaylandpointer.h +++ b/src/compositor/compositor_api/qwaylandpointer.h @@ -45,7 +45,7 @@ QT_BEGIN_NAMESPACE class QWaylandPointer; class QWaylandPointerPrivate; -class QWaylandInputDevice; +class QWaylandSeat; class QWaylandView; class QWaylandOutput; class QWaylandClient; @@ -56,16 +56,16 @@ class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandPointer : public QWaylandObject Q_DECLARE_PRIVATE(QWaylandPointer) Q_PROPERTY(bool isButtonPressed READ isButtonPressed NOTIFY buttonPressedChanged) public: - QWaylandPointer(QWaylandInputDevice *inputDevice, QObject *parent = nullptr); + QWaylandPointer(QWaylandSeat *seat, QObject *parent = nullptr); - QWaylandInputDevice *inputDevice() const; + QWaylandSeat *seat() const; QWaylandCompositor *compositor() const; QWaylandOutput *output() const; void setOutput(QWaylandOutput *output); - virtual void sendMousePressEvent(Qt::MouseButton button); - virtual void sendMouseReleaseEvent(Qt::MouseButton button); + virtual uint sendMousePressEvent(Qt::MouseButton button); + virtual uint sendMouseReleaseEvent(Qt::MouseButton button); virtual void sendMouseMoveEvent(QWaylandView *view, const QPointF &localPos, const QPointF &outputSpacePos); virtual void sendMouseWheelEvent(Qt::Orientation orientation, int delta); @@ -80,7 +80,7 @@ public: wl_resource *focusResource() const; static uint32_t toWaylandButton(Qt::MouseButton button); - void sendButton(struct wl_resource *resource, uint32_t time, Qt::MouseButton button, uint32_t state); + uint sendButton(struct wl_resource *resource, uint32_t time, Qt::MouseButton button, uint32_t state); Q_SIGNALS: void outputChanged(); void buttonPressedChanged(); diff --git a/src/compositor/compositor_api/qwaylandpointer_p.h b/src/compositor/compositor_api/qwaylandpointer_p.h index 5ac030029..54ac72d11 100644 --- a/src/compositor/compositor_api/qwaylandpointer_p.h +++ b/src/compositor/compositor_api/qwaylandpointer_p.h @@ -61,7 +61,7 @@ #include <QtWaylandCompositor/private/qwayland-server-wayland.h> #include <QtWaylandCompositor/QWaylandView> #include <QtWaylandCompositor/QWaylandSurface> -#include <QtWaylandCompositor/QWaylandInputDevice> +#include <QtWaylandCompositor/QWaylandSeat> #include <stdint.h> @@ -74,7 +74,7 @@ class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandPointerPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QWaylandPointer) public: - QWaylandPointerPrivate(QWaylandPointer *pointer, QWaylandInputDevice *seat); + QWaylandPointerPrivate(QWaylandPointer *pointer, QWaylandSeat *seat); QWaylandCompositor *compositor() const { return seat->compositor(); } @@ -86,7 +86,7 @@ protected: private: void focusDestroyed(void *data); - QWaylandInputDevice *seat; + QWaylandSeat *seat; QWaylandOutput *output; QPointF localPosition; diff --git a/src/compositor/compositor_api/qwaylandquickcompositor.cpp b/src/compositor/compositor_api/qwaylandquickcompositor.cpp index 64e6fec70..b69e20791 100644 --- a/src/compositor/compositor_api/qwaylandquickcompositor.cpp +++ b/src/compositor/compositor_api/qwaylandquickcompositor.cpp @@ -37,7 +37,8 @@ #include <QtQml/QQmlEngine> #include <QQuickWindow> -#include <QtGui/private/qopengltextureblitter_p.h> +#include <QOpenGLTextureBlitter> +#include <QOpenGLTexture> #include <QOpenGLFramebufferObject> #include <QMatrix4x4> #include <QRunnable> @@ -101,6 +102,7 @@ void QWaylandQuickCompositor::create() void QWaylandQuickCompositor::classBegin() { + QWaylandCompositorPrivate::get(this)->preInit(); } void QWaylandQuickCompositor::componentComplete() @@ -114,7 +116,7 @@ void QWaylandQuickCompositor::componentComplete() */ void QWaylandQuickCompositor::grabSurface(QWaylandSurfaceGrabber *grabber, const QWaylandBufferRef &buffer) { - if (buffer.isShm()) { + if (buffer.isSharedMemory()) { QWaylandCompositor::grabSurface(grabber, buffer); return; } @@ -139,7 +141,6 @@ void QWaylandQuickCompositor::grabSurface(QWaylandSurfaceGrabber *grabber, const fbo.bind(); QOpenGLTextureBlitter blitter; blitter.create(); - blitter.bind(); glViewport(0, 0, buffer.size().width(), buffer.size().height()); @@ -148,15 +149,10 @@ void QWaylandQuickCompositor::grabSurface(QWaylandSurfaceGrabber *grabber, const ? QOpenGLTextureBlitter::OriginTopLeft : QOpenGLTextureBlitter::OriginBottomLeft; - GLuint texture; - glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_2D, texture); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - buffer.bindToTexture(); - blitter.blit(texture, QMatrix4x4(), surfaceOrigin); - + auto texture = buffer.toOpenGLTexture(); + blitter.bind(texture->target()); + blitter.blit(texture->textureId(), QMatrix4x4(), surfaceOrigin); blitter.release(); - glDeleteTextures(1, &texture); emit grabber->success(fbo.toImage()); } diff --git a/src/compositor/compositor_api/qwaylandquickitem.cpp b/src/compositor/compositor_api/qwaylandquickitem.cpp index 5e90c06c7..e6cfce343 100644 --- a/src/compositor/compositor_api/qwaylandquickitem.cpp +++ b/src/compositor/compositor_api/qwaylandquickitem.cpp @@ -39,14 +39,18 @@ #include "qwaylandquicksurface.h" #include "qwaylandinputmethodcontrol.h" #include "qwaylandtextinput.h" +#include "qwaylandquickoutput.h" #include <QtWaylandCompositor/qwaylandcompositor.h> -#include <QtWaylandCompositor/qwaylandinput.h> +#include <QtWaylandCompositor/qwaylandseat.h> #include <QtWaylandCompositor/qwaylandbufferref.h> +#include <QtWaylandCompositor/QWaylandDrag> #include <QtWaylandCompositor/private/qwlclientbufferintegration_p.h> #include <QtGui/QKeyEvent> #include <QtGui/QGuiApplication> #include <QtGui/QScreen> +#include <QtGui/QOpenGLFunctions> +#include <QtGui/QOpenGLTexture> #include <QtQuick/QSGSimpleTextureNode> #include <QtQuick/QQuickWindow> @@ -185,52 +189,40 @@ QWaylandBufferMaterial::QWaylandBufferMaterial(QWaylandBufferRef::BufferFormatEg QWaylandBufferMaterial::~QWaylandBufferMaterial() { - QOpenGLFunctions *gl = QOpenGLContext::currentContext()->functions(); - - for (GLuint texture : m_textures) - gl->glDeleteTextures(1, &texture); } -void QWaylandBufferMaterial::setTextureForPlane(int plane, uint texture) +void QWaylandBufferMaterial::setTextureForPlane(int plane, QOpenGLTexture *texture) { if (plane < 0 || plane >= bufferTypes[m_format].planeCount) { qWarning("plane index is out of range"); return; } - QOpenGLFunctions *gl = QOpenGLContext::currentContext()->functions(); - const GLenum target = bufferTypes[m_format].textureTarget; - - gl->glBindTexture(target, texture); - setTextureParameters(target); + texture->bind(); + setTextureParameters(texture->target()); ensureTextures(plane - 1); - if (m_textures.size() <= plane) { + if (m_textures.size() <= plane) m_textures << texture; - } else { - std::swap(m_textures[plane], texture); - gl->glDeleteTextures(1, &texture); - } + else + m_textures[plane] = texture; } void QWaylandBufferMaterial::bind() { - QOpenGLFunctions *gl = QOpenGLContext::currentContext()->functions(); - const GLenum target = bufferTypes[m_format].textureTarget; - ensureTextures(bufferTypes[m_format].planeCount); switch (m_textures.size()) { case 3: - gl->glActiveTexture(GL_TEXTURE2); - gl->glBindTexture(target, m_textures[2]); + if (m_textures[2]) + m_textures[2]->bind(GL_TEXTURE2); case 2: - gl->glActiveTexture(GL_TEXTURE1); - gl->glBindTexture(target, m_textures[1]); + if (m_textures[1]) + m_textures[1]->bind(GL_TEXTURE1); case 1: - gl->glActiveTexture(GL_TEXTURE0); - gl->glBindTexture(target, m_textures[0]); + if (m_textures[0]) + m_textures[0]->bind(GL_TEXTURE0); } } @@ -257,15 +249,8 @@ void QWaylandBufferMaterial::setTextureParameters(GLenum target) //TODO move this into a separate centralized texture management class void QWaylandBufferMaterial::ensureTextures(int count) { - QOpenGLFunctions *gl = QOpenGLContext::currentContext()->functions(); - const GLenum target = bufferTypes[m_format].textureTarget; - GLuint texture; - for (int plane = m_textures.size(); plane < count; plane++) { - gl->glGenTextures(1, &texture); - gl->glBindTexture(target, texture); - setTextureParameters(target); - m_textures << texture; + m_textures << nullptr; } } @@ -293,7 +278,7 @@ public: delete m_sgTex; m_sgTex = 0; if (m_ref.hasBuffer()) { - if (buffer.isShm()) { + if (buffer.isSharedMemory()) { m_sgTex = surfaceItem->window()->createTextureFromImage(buffer.image()); if (m_sgTex) { m_sgTex->bind(); @@ -305,11 +290,8 @@ public: opt |= QQuickWindow::TextureHasAlphaChannel; } - GLuint texture; - glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_2D, texture); - buffer.bindToTexture(); - m_sgTex = surfaceItem->window()->createTextureFromId(texture , QSize(surfaceItem->width(), surfaceItem->height()), opt); + auto texture = buffer.toOpenGLTexture(); + m_sgTex = surfaceItem->window()->createTextureFromId(texture->textureId() , QSize(surfaceItem->width(), surfaceItem->height()), opt); } } emit textureChanged(); @@ -332,7 +314,7 @@ private: /*! * \qmltype WaylandQuickItem * \inqmlmodule QtWayland.Compositor - * \preliminary + * \since 5.8 * \brief Provides a Qt Quick item that represents a WaylandView. * * Qt Quick-based Wayland compositors can use this type to display a client's @@ -343,7 +325,7 @@ private: /*! * \class QWaylandQuickItem * \inmodule QtWaylandCompositor - * \preliminary + * \since 5.8 * \brief The QWaylandQuickItem class provides a Qt Quick item representing a QWaylandView. * * When writing a QWaylandCompositor in Qt Quick, this class can be used to display a @@ -492,13 +474,13 @@ void QWaylandQuickItem::mousePressEvent(QMouseEvent *event) return; } - QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event); + QWaylandSeat *seat = compositor()->seatFor(event); if (d->focusOnClick) - takeFocus(inputDevice); + takeFocus(seat); - inputDevice->sendMouseMoveEvent(d->view.data(), event->localPos() / d->scaleFactor(), event->windowPos()); - inputDevice->sendMousePressEvent(event->button()); + seat->sendMouseMoveEvent(d->view.data(), mapToSurface(event->localPos()), event->windowPos()); + seat->sendMousePressEvent(event->button()); } /*! @@ -508,8 +490,20 @@ void QWaylandQuickItem::mouseMoveEvent(QMouseEvent *event) { Q_D(QWaylandQuickItem); if (d->shouldSendInputEvents()) { - QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event); - inputDevice->sendMouseMoveEvent(d->view.data(), event->localPos() / d->scaleFactor(), event->windowPos()); + QWaylandSeat *seat = compositor()->seatFor(event); + if (d->isDragging) { + QWaylandQuickOutput *currentOutput = qobject_cast<QWaylandQuickOutput *>(view()->output()); + //TODO: also check if dragging onto other outputs + QWaylandQuickItem *targetItem = qobject_cast<QWaylandQuickItem *>(currentOutput->pickClickableItem(mapToScene(event->localPos()))); + QWaylandSurface *targetSurface = targetItem ? targetItem->surface() : nullptr; + if (targetSurface) { + QPointF position = mapToItem(targetItem, event->localPos()); + QPointF surfacePosition = targetItem->mapToSurface(position); + seat->drag()->dragMove(targetSurface, surfacePosition); + } + } else { + seat->sendMouseMoveEvent(d->view.data(), mapToSurface(event->localPos()), event->windowPos()); + } } else { emit mouseMove(event->windowPos()); event->ignore(); @@ -523,8 +517,13 @@ void QWaylandQuickItem::mouseReleaseEvent(QMouseEvent *event) { Q_D(QWaylandQuickItem); if (d->shouldSendInputEvents()) { - QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event); - inputDevice->sendMouseReleaseEvent(event->button()); + QWaylandSeat *seat = compositor()->seatFor(event); + if (d->isDragging) { + d->isDragging = false; + seat->drag()->drop(); + } else { + seat->sendMouseReleaseEvent(event->button()); + } } else { emit mouseRelease(); event->ignore(); @@ -542,8 +541,8 @@ void QWaylandQuickItem::hoverEnterEvent(QHoverEvent *event) return; } if (d->shouldSendInputEvents()) { - QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event); - inputDevice->sendMouseMoveEvent(d->view.data(), event->pos(), mapToScene(event->pos())); + QWaylandSeat *seat = compositor()->seatFor(event); + seat->sendMouseMoveEvent(d->view.data(), event->pos(), mapToScene(event->pos())); } else { event->ignore(); } @@ -562,8 +561,8 @@ void QWaylandQuickItem::hoverMoveEvent(QHoverEvent *event) } } if (d->shouldSendInputEvents()) { - QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event); - inputDevice->sendMouseMoveEvent(d->view.data(), event->pos() / d->scaleFactor(), mapToScene(event->pos())); + QWaylandSeat *seat = compositor()->seatFor(event); + seat->sendMouseMoveEvent(d->view.data(), mapToSurface(event->pos()), mapToScene(event->pos())); } else { event->ignore(); } @@ -576,8 +575,8 @@ void QWaylandQuickItem::hoverLeaveEvent(QHoverEvent *event) { Q_D(QWaylandQuickItem); if (d->shouldSendInputEvents()) { - QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event); - inputDevice->setMouseFocus(Q_NULLPTR); + QWaylandSeat *seat = compositor()->seatFor(event); + seat->setMouseFocus(Q_NULLPTR); } else { event->ignore(); } @@ -595,8 +594,8 @@ void QWaylandQuickItem::wheelEvent(QWheelEvent *event) return; } - QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event); - inputDevice->sendMouseWheelEvent(event->orientation(), event->delta()); + QWaylandSeat *seat = compositor()->seatFor(event); + seat->sendMouseWheelEvent(event->orientation(), event->delta()); } else { event->ignore(); } @@ -609,8 +608,8 @@ void QWaylandQuickItem::keyPressEvent(QKeyEvent *event) { Q_D(QWaylandQuickItem); if (d->shouldSendInputEvents()) { - QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event); - inputDevice->sendFullKeyEvent(event); + QWaylandSeat *seat = compositor()->seatFor(event); + seat->sendFullKeyEvent(event); } else { event->ignore(); } @@ -623,8 +622,8 @@ void QWaylandQuickItem::keyReleaseEvent(QKeyEvent *event) { Q_D(QWaylandQuickItem); if (d->shouldSendInputEvents() && hasFocus()) { - QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event); - inputDevice->sendFullKeyEvent(event); + QWaylandSeat *seat = compositor()->seatFor(event); + seat->sendFullKeyEvent(event); } else { event->ignore(); } @@ -637,19 +636,7 @@ void QWaylandQuickItem::touchEvent(QTouchEvent *event) { Q_D(QWaylandQuickItem); if (d->shouldSendInputEvents() && d->touchEventsEnabled) { - QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event); - - if (event->type() == QEvent::TouchBegin) { - QQuickItem *grabber = window()->mouseGrabberItem(); - if (grabber != this) - grabMouse(); - } - - if (event->type() == QEvent::TouchEnd) { - QQuickItem *grabber = window()->mouseGrabberItem(); - if (grabber == this) - ungrabMouse(); - } + QWaylandSeat *seat = compositor()->seatFor(event); QPoint pointPos; const QList<QTouchEvent::TouchPoint> &points = event->touchPoints(); @@ -662,26 +649,18 @@ void QWaylandQuickItem::touchEvent(QTouchEvent *event) } event->accept(); - if (inputDevice->mouseFocus() != d->view.data()) { - inputDevice->sendMouseMoveEvent(d->view.data(), pointPos, mapToScene(pointPos)); + if (seat->mouseFocus() != d->view.data()) { + seat->sendMouseMoveEvent(d->view.data(), pointPos, mapToScene(pointPos)); } - inputDevice->sendFullTouchEvent(event); + seat->sendFullTouchEvent(surface(), event); + + if (event->type() == QEvent::TouchBegin && d->focusOnClick) + takeFocus(seat); } else { event->ignore(); } } -/*! - * \internal - */ -void QWaylandQuickItem::mouseUngrabEvent() -{ - if (surface()) { - QTouchEvent e(QEvent::TouchCancel); - touchEvent(&e); - } -} - #ifndef QT_NO_IM /*! * \internal @@ -763,31 +742,107 @@ void QWaylandQuickItem::setSubsurfaceHandler(QObject *handler) } /*! + * \property QWaylandQuickItem::output + * + * This property holds the output on which this item is displayed. + */ +QWaylandOutput *QWaylandQuickItem::output() const +{ + Q_D(const QWaylandQuickItem); + return d->view->output(); +} + +void QWaylandQuickItem::setOutput(QWaylandOutput *output) +{ + Q_D(QWaylandQuickItem); + d->view->setOutput(output); +} + +/*! + * \property QWaylandQuickItem::bufferLocked + * + * This property holds whether the item's buffer is currently locked. As long as + * the buffer is locked, it will not be released and returned to the client. + * + * The default is false. + */ +bool QWaylandQuickItem::isBufferLocked() const +{ + Q_D(const QWaylandQuickItem); + return d->view->isBufferLocked(); +} + +void QWaylandQuickItem::setBufferLocked(bool locked) +{ + Q_D(QWaylandQuickItem); + d->view->setBufferLocked(locked); +} + +/*! + * \property bool QWaylandQuickItem::allowDiscardFrontBuffer + * + * By default, the item locks the current buffer until a new buffer is available + * and updatePaintNode() is called. Set this property to true to allow Qt to release the buffer + * immediately when the throttling view is no longer using it. This is useful for items that have + * slow update intervals. + */ +bool QWaylandQuickItem::allowDiscardFrontBuffer() const +{ + Q_D(const QWaylandQuickItem); + return d->view->allowDiscardFrontBuffer(); +} + +void QWaylandQuickItem::setAllowDiscardFrontBuffer(bool discard) +{ + Q_D(QWaylandQuickItem); + d->view->setAllowDiscardFrontBuffer(discard); +} + +/*! + * \qmlmethod QtWaylandCompositor::WaylandQuickItem::setPrimary + * + * Makes this WaylandQuickItem the primary view for the surface. + */ + +/*! + * Makes this QWaylandQuickItem's view the primary view for the surface. + * + * \sa QWaylandSurface::primaryView + */ +void QWaylandQuickItem::setPrimary() +{ + Q_D(QWaylandQuickItem); + d->view->setPrimary(); +} + +/*! * \internal */ void QWaylandQuickItem::handleSurfaceChanged() { Q_D(QWaylandQuickItem); if (d->oldSurface) { - disconnect(d->oldSurface, &QWaylandSurface::mappedChanged, this, &QWaylandQuickItem::surfaceMappedChanged); + disconnect(d->oldSurface, &QWaylandSurface::hasContentChanged, this, &QWaylandQuickItem::surfaceMappedChanged); disconnect(d->oldSurface, &QWaylandSurface::parentChanged, this, &QWaylandQuickItem::parentChanged); disconnect(d->oldSurface, &QWaylandSurface::sizeChanged, this, &QWaylandQuickItem::updateSize); disconnect(d->oldSurface, &QWaylandSurface::bufferScaleChanged, this, &QWaylandQuickItem::updateSize); disconnect(d->oldSurface, &QWaylandSurface::configure, this, &QWaylandQuickItem::updateBuffer); disconnect(d->oldSurface, &QWaylandSurface::redraw, this, &QQuickItem::update); disconnect(d->oldSurface, &QWaylandSurface::childAdded, this, &QWaylandQuickItem::handleSubsurfaceAdded); + disconnect(d->oldSurface, &QWaylandSurface::dragStarted, this, &QWaylandQuickItem::handleDragStarted); #ifndef QT_NO_IM disconnect(d->oldSurface->inputMethodControl(), &QWaylandInputMethodControl::updateInputMethod, this, &QWaylandQuickItem::updateInputMethod); #endif } if (QWaylandSurface *newSurface = d->view->surface()) { - connect(newSurface, &QWaylandSurface::mappedChanged, this, &QWaylandQuickItem::surfaceMappedChanged); + connect(newSurface, &QWaylandSurface::hasContentChanged, this, &QWaylandQuickItem::surfaceMappedChanged); connect(newSurface, &QWaylandSurface::parentChanged, this, &QWaylandQuickItem::parentChanged); connect(newSurface, &QWaylandSurface::sizeChanged, this, &QWaylandQuickItem::updateSize); connect(newSurface, &QWaylandSurface::bufferScaleChanged, this, &QWaylandQuickItem::updateSize); connect(newSurface, &QWaylandSurface::configure, this, &QWaylandQuickItem::updateBuffer); connect(newSurface, &QWaylandSurface::redraw, this, &QQuickItem::update); connect(newSurface, &QWaylandSurface::childAdded, this, &QWaylandQuickItem::handleSubsurfaceAdded); + connect(newSurface, &QWaylandSurface::dragStarted, this, &QWaylandQuickItem::handleDragStarted); #ifndef QT_NO_IM connect(newSurface->inputMethodControl(), &QWaylandInputMethodControl::updateInputMethod, this, &QWaylandQuickItem::updateInputMethod); #endif @@ -814,16 +869,16 @@ void QWaylandQuickItem::handleSurfaceChanged() * Calling this function causes the item to take the focus of the * input \a device. */ -void QWaylandQuickItem::takeFocus(QWaylandInputDevice *device) +void QWaylandQuickItem::takeFocus(QWaylandSeat *device) { forceActiveFocus(); if (!surface()) return; - QWaylandInputDevice *target = device; + QWaylandSeat *target = device; if (!target) { - target = compositor()->defaultInputDevice(); + target = compositor()->defaultSeat(); } target->setKeyboardFocus(surface()); QWaylandTextInput *textInput = QWaylandTextInput::findIn(target); @@ -869,7 +924,7 @@ void QWaylandQuickItem::updateSize() * \qmlproperty bool QtWaylandCompositor::WaylandQuickItem::focusOnClick * * This property specifies whether the WaylandQuickItem should take focus when - * it is clicked. + * it is clicked or touched. * * The default is \c true. */ @@ -878,7 +933,7 @@ void QWaylandQuickItem::updateSize() * \property QWaylandQuickItem::focusOnClick * * This property specifies whether the QWaylandQuickItem should take focus when - * it is clicked. + * it is clicked or touched. * * The default is \c true. */ @@ -904,13 +959,23 @@ void QWaylandQuickItem::setFocusOnClick(bool focus) */ bool QWaylandQuickItem::inputRegionContains(const QPointF &localPosition) { - Q_D(QWaylandQuickItem); if (QWaylandSurface *s = surface()) - return s->inputRegionContains(localPosition.toPoint() / d->scaleFactor()); + return s->inputRegionContains(mapToSurface(localPosition).toPoint()); return false; } /*! + * Maps the given \a point in this item's coordinate system to the equivalent + * point within the Wayland surface's coordinate system, and returns the mapped + * coordinate. + */ +QPointF QWaylandQuickItem::mapToSurface(const QPointF &point) const +{ + Q_D(const QWaylandQuickItem); + return point / d->scaleFactor(); +} + +/*! * \qmlproperty bool QtWaylandCompositor::WaylandQuickItem::sizeFollowsSurface * * This property specifies whether the size of the item should always match @@ -1049,9 +1114,9 @@ void QWaylandQuickItem::updateInputMethod(Qt::InputMethodQueries queries) QSGNode *QWaylandQuickItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) { Q_D(QWaylandQuickItem); - const bool mapped = surface() && surface()->isMapped() && d->view->currentBuffer().hasBuffer(); + const bool hasContent = surface() && surface()->hasContent() && d->view->currentBuffer().hasContent(); - if (!mapped || !d->paintEnabled) { + if (!hasContent || !d->paintEnabled) { delete oldNode; return 0; } @@ -1061,7 +1126,8 @@ QSGNode *QWaylandQuickItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat const QRectF rect = invertY ? QRectF(0, height(), width(), -height()) : QRectF(0, 0, width(), height()); - if (ref.isShm() || bufferTypes[ref.bufferFormatEgl()].canProvideTexture) { + if (ref.isSharedMemory() || bufferTypes[ref.bufferFormatEgl()].canProvideTexture) { + // This case could covered by the more general path below, but this is more efficient (especially when using ShaderEffect items). QSGSimpleTextureNode *node = static_cast<QSGSimpleTextureNode *>(oldNode); if (!node) { @@ -1104,13 +1170,11 @@ QSGNode *QWaylandQuickItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat if (d->newTexture) { d->newTexture = false; for (int plane = 0; plane < bufferTypes[ref.bufferFormatEgl()].planeCount; plane++) - if (uint texture = ref.textureForPlane(plane)) + if (auto texture = ref.toOpenGLTexture(plane)) material->setTextureForPlane(plane, texture); material->bind(); - ref.bindToTexture(); } - ref.updateTexture(); QSGGeometry::updateTexturedRectGeometry(geometry, rect, QRectF(0, 0, 1, 1)); node->setGeometry(geometry); @@ -1144,6 +1208,8 @@ void QWaylandQuickItem::setInputEventsEnabled(bool enabled) { Q_D(QWaylandQuickItem); if (d->inputEventsEnabled != enabled) { + if (enabled) + setEnabled(true); d->setInputEventsEnabled(enabled); emit inputEventsEnabledChanged(); } @@ -1178,5 +1244,13 @@ void QWaylandQuickItem::handleSubsurfacePosition(const QPoint &pos) QQuickItem::setPosition(pos * d->scaleFactor()); } +void QWaylandQuickItem::handleDragStarted(QWaylandDrag *drag) +{ + Q_D(QWaylandQuickItem); + Q_ASSERT(drag->origin() == surface()); + drag->seat()->setMouseFocus(nullptr); + d->isDragging = true; +} + QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandquickitem.h b/src/compositor/compositor_api/qwaylandquickitem.h index 07b6a40a4..821826d69 100644 --- a/src/compositor/compositor_api/qwaylandquickitem.h +++ b/src/compositor/compositor_api/qwaylandquickitem.h @@ -51,14 +51,13 @@ Q_DECLARE_METATYPE(QWaylandQuickSurface*) QT_BEGIN_NAMESPACE -class QWaylandInputDevice; +class QWaylandSeat; class QWaylandQuickItemPrivate; class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandQuickItem : public QQuickItem { Q_OBJECT Q_DECLARE_PRIVATE(QWaylandQuickItem) - Q_PROPERTY(QWaylandView *view READ view CONSTANT) Q_PROPERTY(QWaylandCompositor *compositor READ compositor) Q_PROPERTY(QWaylandSurface *surface READ surface WRITE setSurface NOTIFY surfaceChanged) Q_PROPERTY(bool paintEnabled READ paintEnabled WRITE setPaintEnabled) @@ -68,6 +67,9 @@ class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandQuickItem : public QQuickItem Q_PROPERTY(bool focusOnClick READ focusOnClick WRITE setFocusOnClick NOTIFY focusOnClickChanged) Q_PROPERTY(bool sizeFollowsSurface READ sizeFollowsSurface WRITE setSizeFollowsSurface NOTIFY sizeFollowsSurfaceChanged) Q_PROPERTY(QObject *subsurfaceHandler READ subsurfaceHandler WRITE setSubsurfaceHandler NOTIFY subsurfaceHandlerChanged) + Q_PROPERTY(QWaylandOutput *output READ output WRITE setOutput NOTIFY outputChanged) + Q_PROPERTY(bool bufferLocked READ isBufferLocked WRITE setBufferLocked NOTIFY bufferLockedChanged) + Q_PROPERTY(bool allowDiscardFrontBuffer READ allowDiscardFrontBuffer WRITE setAllowDiscardFrontBuffer NOTIFY allowDiscardFrontBufferChanged) public: QWaylandQuickItem(QQuickItem *parent = nullptr); ~QWaylandQuickItem(); @@ -95,6 +97,7 @@ public: void setFocusOnClick(bool focus); bool inputRegionContains(const QPointF &localPosition); + Q_INVOKABLE QPointF mapToSurface(const QPointF &point) const; bool sizeFollowsSurface() const; void setSizeFollowsSurface(bool sizeFollowsSurface); @@ -107,6 +110,17 @@ public: QObject *subsurfaceHandler() const; void setSubsurfaceHandler(QObject*); + QWaylandOutput *output() const; + void setOutput(QWaylandOutput *output); + + bool isBufferLocked() const; + void setBufferLocked(bool locked); + + bool allowDiscardFrontBuffer() const; + void setAllowDiscardFrontBuffer(bool discard); + + Q_INVOKABLE void setPrimary(); + protected: void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE; void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE; @@ -120,7 +134,6 @@ protected: void keyReleaseEvent(QKeyEvent *event) Q_DECL_OVERRIDE; void touchEvent(QTouchEvent *event) Q_DECL_OVERRIDE; - void mouseUngrabEvent() Q_DECL_OVERRIDE; #ifndef QT_NO_IM void inputMethodEvent(QInputMethodEvent *event) Q_DECL_OVERRIDE; @@ -128,7 +141,7 @@ protected: virtual void surfaceChangedEvent(QWaylandSurface *newSurface, QWaylandSurface *oldSurface); public Q_SLOTS: - virtual void takeFocus(QWaylandInputDevice *device = nullptr); + virtual void takeFocus(QWaylandSeat *device = nullptr); void setPaintEnabled(bool paintEnabled); void raise(); void lower(); @@ -143,6 +156,7 @@ private Q_SLOTS: void beforeSync(); void handleSubsurfaceAdded(QWaylandSurface *childSurface); void handleSubsurfacePosition(const QPoint &pos); + void handleDragStarted(QWaylandDrag *drag); #ifndef QT_NO_IM void updateInputMethod(Qt::InputMethodQueries queries); #endif @@ -158,6 +172,9 @@ Q_SIGNALS: void mouseRelease(); void sizeFollowsSurfaceChanged(); void subsurfaceHandlerChanged(); + void outputChanged(); + void bufferLockedChanged(); + void allowDiscardFrontBufferChanged(); protected: QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) Q_DECL_OVERRIDE; diff --git a/src/compositor/compositor_api/qwaylandquickitem_p.h b/src/compositor/compositor_api/qwaylandquickitem_p.h index b529ba959..5eba99572 100644 --- a/src/compositor/compositor_api/qwaylandquickitem_p.h +++ b/src/compositor/compositor_api/qwaylandquickitem_p.h @@ -52,14 +52,14 @@ #include <QtQuick/QSGMaterialShader> #include <QtQuick/QSGMaterial> -#include "qwaylandquickitem.h" - +#include <QtWaylandCompositor/QWaylandQuickItem> #include <QtWaylandCompositor/QWaylandOutput> QT_BEGIN_NAMESPACE class QWaylandSurfaceTextureProvider; class QMutex; +class QOpenGLTexture; class QWaylandBufferMaterialShader : public QSGMaterialShader { @@ -85,7 +85,7 @@ public: QWaylandBufferMaterial(QWaylandBufferRef::BufferFormatEgl format); ~QWaylandBufferMaterial(); - void setTextureForPlane(int plane, uint texture); + void setTextureForPlane(int plane, QOpenGLTexture *texture); void bind(); @@ -97,7 +97,7 @@ private: void ensureTextures(int count); const QWaylandBufferRef::BufferFormatEgl m_format; - QVarLengthArray<GLuint, 3> m_textures; + QVarLengthArray<QOpenGLTexture*, 3> m_textures; }; class QWaylandQuickItemPrivate : public QQuickItemPrivate @@ -110,8 +110,9 @@ public: , oldSurface(Q_NULLPTR) , provider(Q_NULLPTR) , paintEnabled(true) - , touchEventsEnabled(false) + , touchEventsEnabled(true) , inputEventsEnabled(true) + , isDragging(false) , newTexture(false) , focusOnClick(true) , sizeFollowsSurface(true) @@ -138,9 +139,11 @@ public: QObject::connect(view.data(), &QWaylandView::surfaceChanged, q, &QWaylandQuickItem::surfaceChanged); QObject::connect(view.data(), &QWaylandView::surfaceChanged, q, &QWaylandQuickItem::handleSurfaceChanged); QObject::connect(view.data(), &QWaylandView::surfaceDestroyed, q, &QWaylandQuickItem::surfaceDestroyed); + QObject::connect(view.data(), &QWaylandView::outputChanged, q, &QWaylandQuickItem::outputChanged); + QObject::connect(view.data(), &QWaylandView::bufferLockedChanged, q, &QWaylandQuickItem::bufferLockedChanged); + QObject::connect(view.data(), &QWaylandView::allowDiscardFrontBufferChanged, q, &QWaylandQuickItem::allowDiscardFrontBuffer); } - void setInputEventsEnabled(bool enable) { Q_Q(QWaylandQuickItem); @@ -164,6 +167,7 @@ public: bool paintEnabled; bool touchEventsEnabled; bool inputEventsEnabled; + bool isDragging; bool newTexture; bool focusOnClick; bool sizeFollowsSurface; diff --git a/src/compositor/compositor_api/qwaylandquickoutput.cpp b/src/compositor/compositor_api/qwaylandquickoutput.cpp index 8abf6cbb1..0e25362fc 100644 --- a/src/compositor/compositor_api/qwaylandquickoutput.cpp +++ b/src/compositor/compositor_api/qwaylandquickoutput.cpp @@ -37,6 +37,7 @@ #include "qwaylandquickoutput.h" #include "qwaylandquickcompositor.h" +#include "qwaylandquickitem_p.h" QT_BEGIN_NAMESPACE @@ -102,6 +103,44 @@ void QWaylandQuickOutput::setAutomaticFrameCallback(bool automatic) automaticFrameCallbackChanged(); } +static QQuickItem* clickableItemAtPosition(QQuickItem *rootItem, const QPointF &position) +{ + if (!rootItem->isEnabled() || !rootItem->isVisible()) + return nullptr; + + QList<QQuickItem *> paintOrderItems = QQuickItemPrivate::get(rootItem)->paintOrderChildItems(); + auto negativeZStart = paintOrderItems.crend(); + for (auto it = paintOrderItems.crbegin(); it != paintOrderItems.crend(); ++it) { + if ((*it)->z() < 0) { + negativeZStart = it; + break; + } + QQuickItem *item = clickableItemAtPosition(*it, rootItem->mapToItem(*it, position)); + if (item) + return item; + } + + if (rootItem->contains(position) && rootItem->acceptedMouseButtons() != Qt::NoButton) + return rootItem; + + for (auto it = negativeZStart; it != paintOrderItems.crend(); ++it) { + QQuickItem *item = clickableItemAtPosition(*it, rootItem->mapToItem(*it, position)); + if (item) + return item; + } + + return nullptr; +} + +QQuickItem *QWaylandQuickOutput::pickClickableItem(const QPointF &position) +{ + QQuickWindow *quickWindow = qobject_cast<QQuickWindow *>(window()); + if (!quickWindow) + return nullptr; + + return clickableItemAtPosition(quickWindow->contentItem(), position); +} + /*! * \internal */ diff --git a/src/compositor/compositor_api/qwaylandquickoutput.h b/src/compositor/compositor_api/qwaylandquickoutput.h index 83091e4c7..2cef03282 100644 --- a/src/compositor/compositor_api/qwaylandquickoutput.h +++ b/src/compositor/compositor_api/qwaylandquickoutput.h @@ -59,6 +59,8 @@ public: bool automaticFrameCallback() const; void setAutomaticFrameCallback(bool automatic); + QQuickItem *pickClickableItem(const QPointF &position); + public Q_SLOTS: void updateStarted(); diff --git a/src/compositor/compositor_api/qwaylandinput.cpp b/src/compositor/compositor_api/qwaylandseat.cpp index 6f0f8c758..f6a5276d4 100644 --- a/src/compositor/compositor_api/qwaylandinput.cpp +++ b/src/compositor/compositor_api/qwaylandseat.cpp @@ -34,8 +34,8 @@ ** ****************************************************************************/ -#include "qwaylandinput.h" -#include "qwaylandinput_p.h" +#include "qwaylandseat.h" +#include "qwaylandseat_p.h" #include "qwaylandcompositor.h" #include "qwaylandinputmethodcontrol.h" @@ -43,8 +43,8 @@ #include <QtWaylandCompositor/QWaylandDrag> #include <QtWaylandCompositor/QWaylandTouch> #include <QtWaylandCompositor/QWaylandPointer> -#include <QtWaylandCompositor/QWaylandWlShellSurface> -#include <QtWaylandCompositor/private/qwaylandinput_p.h> +#include <QtWaylandCompositor/QWaylandKeymap> +#include <QtWaylandCompositor/private/qwaylandseat_p.h> #include <QtWaylandCompositor/private/qwaylandcompositor_p.h> #include <QtWaylandCompositor/private/qwldatadevice_p.h> @@ -53,37 +53,39 @@ QT_BEGIN_NAMESPACE -QWaylandInputDevicePrivate::QWaylandInputDevicePrivate(QWaylandInputDevice *inputdevice, QWaylandCompositor *compositor) +QWaylandSeatPrivate::QWaylandSeatPrivate(QWaylandSeat *seat) : QObjectPrivate() - , QtWaylandServer::wl_seat(compositor->display(), 4) - , compositor(compositor) + , QtWaylandServer::wl_seat() + , isInitialized(false) + , compositor(nullptr) , mouseFocus(Q_NULLPTR) , keyboardFocus(nullptr) , capabilities() , data_device() - , drag_handle(new QWaylandDrag(inputdevice)) + , drag_handle(new QWaylandDrag(seat)) + , keymap(new QWaylandKeymap()) { } -QWaylandInputDevicePrivate::~QWaylandInputDevicePrivate() +QWaylandSeatPrivate::~QWaylandSeatPrivate() { } -void QWaylandInputDevicePrivate::setCapabilities(QWaylandInputDevice::CapabilityFlags caps) +void QWaylandSeatPrivate::setCapabilities(QWaylandSeat::CapabilityFlags caps) { - Q_Q(QWaylandInputDevice); + Q_Q(QWaylandSeat); if (capabilities != caps) { - QWaylandInputDevice::CapabilityFlags changed = caps ^ capabilities; + QWaylandSeat::CapabilityFlags changed = caps ^ capabilities; - if (changed & QWaylandInputDevice::Pointer) { + if (changed & QWaylandSeat::Pointer) { pointer.reset(pointer.isNull() ? QWaylandCompositorPrivate::get(compositor)->callCreatePointerDevice(q) : 0); } - if (changed & QWaylandInputDevice::Keyboard) { + if (changed & QWaylandSeat::Keyboard) { keyboard.reset(keyboard.isNull() ? QWaylandCompositorPrivate::get(compositor)->callCreateKeyboardDevice(q) : 0); } - if (changed & QWaylandInputDevice::Touch) { + if (changed & QWaylandSeat::Touch) { touch.reset(touch.isNull() ? QWaylandCompositorPrivate::get(compositor)->callCreateTouchDevice(q) : 0); } @@ -93,112 +95,127 @@ void QWaylandInputDevicePrivate::setCapabilities(QWaylandInputDevice::Capability wl_seat::send_capabilities(resources.at(i)->handle, (uint32_t)capabilities); } - if ((changed & caps & QWaylandInputDevice::Keyboard) && keyboardFocus != nullptr) + if ((changed & caps & QWaylandSeat::Keyboard) && keyboardFocus != nullptr) keyboard->setFocus(keyboardFocus); } } -void QWaylandInputDevicePrivate::clientRequestedDataDevice(QtWayland::DataDeviceManager *, struct wl_client *client, uint32_t id) +void QWaylandSeatPrivate::clientRequestedDataDevice(QtWayland::DataDeviceManager *, struct wl_client *client, uint32_t id) { - Q_Q(QWaylandInputDevice); + Q_Q(QWaylandSeat); if (!data_device) data_device.reset(new QtWayland::DataDevice(q)); data_device->add(client, id, 1); } -void QWaylandInputDevicePrivate::seat_destroy_resource(wl_seat::Resource *) +void QWaylandSeatPrivate::seat_destroy_resource(wl_seat::Resource *) { // cleanupDataDeviceForClient(resource->client(), true); } -void QWaylandInputDevicePrivate::seat_bind_resource(wl_seat::Resource *resource) +void QWaylandSeatPrivate::seat_bind_resource(wl_seat::Resource *resource) { // The order of capabilities matches the order defined in the wayland protocol wl_seat::send_capabilities(resource->handle, (uint32_t)capabilities); } -void QWaylandInputDevicePrivate::seat_get_pointer(wl_seat::Resource *resource, uint32_t id) +void QWaylandSeatPrivate::seat_get_pointer(wl_seat::Resource *resource, uint32_t id) { if (!pointer.isNull()) { pointer->addClient(QWaylandClient::fromWlClient(compositor, resource->client()), id, resource->version()); } } -void QWaylandInputDevicePrivate::seat_get_keyboard(wl_seat::Resource *resource, uint32_t id) +void QWaylandSeatPrivate::seat_get_keyboard(wl_seat::Resource *resource, uint32_t id) { if (!keyboard.isNull()) { keyboard->addClient(QWaylandClient::fromWlClient(compositor, resource->client()), id, resource->version()); } } -void QWaylandInputDevicePrivate::seat_get_touch(wl_seat::Resource *resource, uint32_t id) +void QWaylandSeatPrivate::seat_get_touch(wl_seat::Resource *resource, uint32_t id) { if (!touch.isNull()) { touch->addClient(QWaylandClient::fromWlClient(compositor, resource->client()), id, resource->version()); } } -QWaylandKeymap::QWaylandKeymap(const QString &layout, const QString &variant, const QString &options, const QString &model, const QString &rules) - : m_layout(layout) - , m_variant(variant) - , m_options(options) - , m_rules(rules) - , m_model(model) -{ -} - - /*! - * \class QWaylandInputDevice + * \class QWaylandSeat * \inmodule QtWaylandCompositor - * \preliminary - * \brief The QWaylandInputDevice class provides access to keyboard, mouse, and touch input. + * \since 5.8 + * \brief The QWaylandSeat class provides access to keyboard, mouse, and touch input. * - * The QWaylandInputDevice provides access to different types of user input and maintains + * The QWaylandSeat provides access to different types of user input and maintains * a keyboard focus and a mouse pointer. It corresponds to the wl_seat interface in the Wayland protocol. */ /*! - * \enum QWaylandInputDevice::CapabilityFlag + * \enum QWaylandSeat::CapabilityFlag * - * This enum type describes the capabilities of a QWaylandInputDevice. + * This enum type describes the capabilities of a QWaylandSeat. * - * \value Pointer The QWaylandInputDevice supports pointer input. - * \value Keyboard The QWaylandInputDevice supports keyboard input. - * \value Touch The QWaylandInputDevice supports touch input. + * \value Pointer The QWaylandSeat supports pointer input. + * \value Keyboard The QWaylandSeat supports keyboard input. + * \value Touch The QWaylandSeat supports touch input. */ /*! - * Constructs a QWaylandInputDevice for the given \a compositor and with the given \a capabilityFlags. + * Constructs a QWaylandSeat for the given \a compositor and with the given \a capabilityFlags. */ -QWaylandInputDevice::QWaylandInputDevice(QWaylandCompositor *compositor, CapabilityFlags capabilityFlags) - : QWaylandObject(*new QWaylandInputDevicePrivate(this,compositor)) +QWaylandSeat::QWaylandSeat(QWaylandCompositor *compositor, CapabilityFlags capabilityFlags) + : QWaylandObject(*new QWaylandSeatPrivate(this)) { - d_func()->setCapabilities(capabilityFlags); + Q_D(QWaylandSeat); + d->compositor = compositor; + d->capabilities = capabilityFlags; + if (compositor->isCreated()) + initialize(); } /*! - * Destroys the QWaylandInputDevice + * Destroys the QWaylandSeat */ -QWaylandInputDevice::~QWaylandInputDevice() +QWaylandSeat::~QWaylandSeat() { } +void QWaylandSeat::initialize() +{ + Q_D(QWaylandSeat); + d->init(d->compositor->display(), 4); + + if (d->capabilities & QWaylandSeat::Pointer) + d->pointer.reset(QWaylandCompositorPrivate::get(d->compositor)->callCreatePointerDevice(this)); + if (d->capabilities & QWaylandSeat::Touch) + d->touch.reset(QWaylandCompositorPrivate::get(d->compositor)->callCreateTouchDevice(this)); + if (d->capabilities & QWaylandSeat::Keyboard) + d->keyboard.reset(QWaylandCompositorPrivate::get(d->compositor)->callCreateKeyboardDevice(this)); + + d->isInitialized = true; +} + +bool QWaylandSeat::isInitialized() const +{ + Q_D(const QWaylandSeat); + return d->isInitialized; +} + /*! - * Sends a mouse press event for \a button to the QWaylandInputDevice's pointer device. + * Sends a mouse press event for \a button to the QWaylandSeat's pointer device. */ -void QWaylandInputDevice::sendMousePressEvent(Qt::MouseButton button) +void QWaylandSeat::sendMousePressEvent(Qt::MouseButton button) { - Q_D(QWaylandInputDevice); + Q_D(QWaylandSeat); d->pointer->sendMousePressEvent(button); } /*! - * Sends a mouse release event for \a button to the QWaylandInputDevice's pointer device. + * Sends a mouse release event for \a button to the QWaylandSeat's pointer device. */ -void QWaylandInputDevice::sendMouseReleaseEvent(Qt::MouseButton button) +void QWaylandSeat::sendMouseReleaseEvent(Qt::MouseButton button) { - Q_D(QWaylandInputDevice); + Q_D(QWaylandSeat); d->pointer->sendMouseReleaseEvent(button); } @@ -206,97 +223,94 @@ void QWaylandInputDevice::sendMouseReleaseEvent(Qt::MouseButton button) * Sets the mouse focus to \a view and sends a mouse move event to the pointer device with the * local position \a localPos and output space position \a outputSpacePos. **/ -void QWaylandInputDevice::sendMouseMoveEvent(QWaylandView *view, const QPointF &localPos, const QPointF &outputSpacePos) +void QWaylandSeat::sendMouseMoveEvent(QWaylandView *view, const QPointF &localPos, const QPointF &outputSpacePos) { - Q_D(QWaylandInputDevice); + Q_D(QWaylandSeat); d->pointer->sendMouseMoveEvent(view, localPos, outputSpacePos); } /*! - * Sends a mouse wheel event to the QWaylandInputDevice's pointer device with the given \a orientation and \a delta. + * Sends a mouse wheel event to the QWaylandSeat's pointer device with the given \a orientation and \a delta. */ -void QWaylandInputDevice::sendMouseWheelEvent(Qt::Orientation orientation, int delta) +void QWaylandSeat::sendMouseWheelEvent(Qt::Orientation orientation, int delta) { - Q_D(QWaylandInputDevice); + Q_D(QWaylandSeat); d->pointer->sendMouseWheelEvent(orientation, delta); } /*! * Sends a key press event with the key \a code to the keyboard device. */ -void QWaylandInputDevice::sendKeyPressEvent(uint code) +void QWaylandSeat::sendKeyPressEvent(uint code) { - Q_D(QWaylandInputDevice); + Q_D(QWaylandSeat); d->keyboard->sendKeyPressEvent(code); } /*! * Sends a key release event with the key \a code to the keyboard device. */ -void QWaylandInputDevice::sendKeyReleaseEvent(uint code) +void QWaylandSeat::sendKeyReleaseEvent(uint code) { - Q_D(QWaylandInputDevice); + Q_D(QWaylandSeat); d->keyboard->sendKeyReleaseEvent(code); } /*! - * Sends a touch point event with the given \a id and \a state to the touch device. The position - * of the touch point is given by \a point. + * Sends a touch point event to the \a surface on a touch device with the given + * \a id, \a point and \a state. + * + * Returns the serial for the touch up or touch down event. */ -void QWaylandInputDevice::sendTouchPointEvent(int id, const QPointF &point, Qt::TouchPointState state) +uint QWaylandSeat::sendTouchPointEvent(QWaylandSurface *surface, int id, const QPointF &point, Qt::TouchPointState state) { - Q_D(QWaylandInputDevice); - if (d->touch.isNull()) { - return; - } - d->touch->sendTouchPointEvent(id, point,state); + Q_D(QWaylandSeat); + + if (d->touch.isNull()) + return 0; + + return d->touch->sendTouchPointEvent(surface, id, point,state); } /*! - * Sends a frame event to the touch device. + * Sends a frame event to the touch device of a \a client. */ -void QWaylandInputDevice::sendTouchFrameEvent() +void QWaylandSeat::sendTouchFrameEvent(QWaylandClient *client) { - Q_D(QWaylandInputDevice); - if (!d->touch.isNull()) { - d->touch->sendFrameEvent(); - } + Q_D(QWaylandSeat); + if (!d->touch.isNull()) + d->touch->sendFrameEvent(client); } /*! - * Sends a cancel event to the touch device. + * Sends a cancel event to the touch device of a \a client. */ -void QWaylandInputDevice::sendTouchCancelEvent() +void QWaylandSeat::sendTouchCancelEvent(QWaylandClient *client) { - Q_D(QWaylandInputDevice); - if (!d->touch.isNull()) { - d->touch->sendCancelEvent(); - } + Q_D(QWaylandSeat); + if (!d->touch.isNull()) + d->touch->sendCancelEvent(client); } /*! - * Sends the \a event to the touch device. + * Sends the \a event to the specified \a surface on the touch device. */ -void QWaylandInputDevice::sendFullTouchEvent(QTouchEvent *event) +void QWaylandSeat::sendFullTouchEvent(QWaylandSurface *surface, QTouchEvent *event) { - Q_D(QWaylandInputDevice); - if (!mouseFocus()) { - qWarning("Cannot send touch event, no pointer focus, fix the compositor"); - return; - } + Q_D(QWaylandSeat); if (!d->touch) return; - d->touch->sendFullTouchEvent(event); + d->touch->sendFullTouchEvent(surface, event); } /*! * Sends the \a event to the keyboard device. */ -void QWaylandInputDevice::sendFullKeyEvent(QKeyEvent *event) +void QWaylandSeat::sendFullKeyEvent(QKeyEvent *event) { - Q_D(QWaylandInputDevice); + Q_D(QWaylandSeat); if (!keyboardFocus()) { qWarning("Cannot send key event, no keyboard focus, fix the compositor"); @@ -327,18 +341,18 @@ void QWaylandInputDevice::sendFullKeyEvent(QKeyEvent *event) /*! * Returns the keyboard for this input device. */ -QWaylandKeyboard *QWaylandInputDevice::keyboard() const +QWaylandKeyboard *QWaylandSeat::keyboard() const { - Q_D(const QWaylandInputDevice); + Q_D(const QWaylandSeat); return d->keyboard.data(); } /*! * Returns the current focused surface for keyboard input. */ -QWaylandSurface *QWaylandInputDevice::keyboardFocus() const +QWaylandSurface *QWaylandSeat::keyboardFocus() const { - Q_D(const QWaylandInputDevice); + Q_D(const QWaylandSeat); if (d->keyboard.isNull() || !d->keyboard->focus()) return Q_NULLPTR; @@ -348,9 +362,9 @@ QWaylandSurface *QWaylandInputDevice::keyboardFocus() const /*! * Sets the current keyboard focus to \a surface. */ -bool QWaylandInputDevice::setKeyboardFocus(QWaylandSurface *surface) +bool QWaylandSeat::setKeyboardFocus(QWaylandSurface *surface) { - Q_D(QWaylandInputDevice); + Q_D(QWaylandSeat); if (surface && surface->isDestroyed()) return false; @@ -358,10 +372,6 @@ bool QWaylandInputDevice::setKeyboardFocus(QWaylandSurface *surface) if (surface == oldSurface) return true; - QWaylandWlShellSurface *wlShellsurface = QWaylandWlShellSurface::findIn(surface); - if (wlShellsurface && wlShellsurface->focusPolicy() == QWaylandWlShellSurface::NoKeyboardFocus) - return false; - d->keyboardFocus = surface; if (!d->keyboard.isNull()) d->keyboard->setFocus(surface); @@ -371,48 +381,45 @@ bool QWaylandInputDevice::setKeyboardFocus(QWaylandSurface *surface) return true; } -/*! - * Sets the key map of this QWaylandInputDevice to \a keymap. - */ -void QWaylandInputDevice::setKeymap(const QWaylandKeymap &keymap) +QWaylandKeymap *QWaylandSeat::keymap() { - if (keyboard()) - keyboard()->setKeymap(keymap); + Q_D(const QWaylandSeat); + return d->keymap.data(); } /*! - * Returns the pointer device for this QWaylandInputDevice. + * Returns the pointer device for this QWaylandSeat. */ -QWaylandPointer *QWaylandInputDevice::pointer() const +QWaylandPointer *QWaylandSeat::pointer() const { - Q_D(const QWaylandInputDevice); + Q_D(const QWaylandSeat); return d->pointer.data(); } /*! - * Returns the touch device for this QWaylandInputDevice. + * Returns the touch device for this QWaylandSeat. */ -QWaylandTouch *QWaylandInputDevice::touch() const +QWaylandTouch *QWaylandSeat::touch() const { - Q_D(const QWaylandInputDevice); + Q_D(const QWaylandSeat); return d->touch.data(); } /*! * Returns the view that currently has mouse focus. */ -QWaylandView *QWaylandInputDevice::mouseFocus() const +QWaylandView *QWaylandSeat::mouseFocus() const { - Q_D(const QWaylandInputDevice); + Q_D(const QWaylandSeat); return d->mouseFocus; } /*! * Sets the current mouse focus to \a view. */ -void QWaylandInputDevice::setMouseFocus(QWaylandView *view) +void QWaylandSeat::setMouseFocus(QWaylandView *view) { - Q_D(QWaylandInputDevice); + Q_D(QWaylandSeat); if (view == d->mouseFocus) return; @@ -422,52 +429,52 @@ void QWaylandInputDevice::setMouseFocus(QWaylandView *view) } /*! - * Returns the compositor for this QWaylandInputDevice. + * Returns the compositor for this QWaylandSeat. */ -QWaylandCompositor *QWaylandInputDevice::compositor() const +QWaylandCompositor *QWaylandSeat::compositor() const { - Q_D(const QWaylandInputDevice); + Q_D(const QWaylandSeat); return d->compositor; } /*! - * Returns the drag object for this QWaylandInputDevice. + * Returns the drag object for this QWaylandSeat. */ -QWaylandDrag *QWaylandInputDevice::drag() const +QWaylandDrag *QWaylandSeat::drag() const { - Q_D(const QWaylandInputDevice); + Q_D(const QWaylandSeat); return d->drag_handle.data(); } /*! - * Returns the capability flags for this QWaylandInputDevice. + * Returns the capability flags for this QWaylandSeat. */ -QWaylandInputDevice::CapabilityFlags QWaylandInputDevice::capabilities() const +QWaylandSeat::CapabilityFlags QWaylandSeat::capabilities() const { - Q_D(const QWaylandInputDevice); + Q_D(const QWaylandSeat); return d->capabilities; } /*! * \internal */ -bool QWaylandInputDevice::isOwner(QInputEvent *inputEvent) const +bool QWaylandSeat::isOwner(QInputEvent *inputEvent) const { Q_UNUSED(inputEvent); return true; } /*! - * Returns the QWaylandInputDevice corresponding to the \a resource. The \a resource is expected + * Returns the QWaylandSeat corresponding to the \a resource. The \a resource is expected * to have the type wl_seat. */ -QWaylandInputDevice *QWaylandInputDevice::fromSeatResource(struct ::wl_resource *resource) +QWaylandSeat *QWaylandSeat::fromSeatResource(struct ::wl_resource *resource) { - return static_cast<QWaylandInputDevicePrivate *>(QWaylandInputDevicePrivate::Resource::fromResource(resource)->seat_object)->q_func(); + return static_cast<QWaylandSeatPrivate *>(QWaylandSeatPrivate::Resource::fromResource(resource)->seat_object)->q_func(); } /*! - * \fn void QWaylandInputDevice::mouseFocusChanged(QWaylandView *newFocus, QWaylandView *oldFocus) + * \fn void QWaylandSeat::mouseFocusChanged(QWaylandView *newFocus, QWaylandView *oldFocus) * * This signal is emitted when the mouse focus has changed from \a oldFocus to \a newFocus. */ diff --git a/src/compositor/compositor_api/qwaylandinput.h b/src/compositor/compositor_api/qwaylandseat.h index d1cb922b7..3e90342c7 100644 --- a/src/compositor/compositor_api/qwaylandinput.h +++ b/src/compositor/compositor_api/qwaylandseat.h @@ -34,8 +34,8 @@ ** ****************************************************************************/ -#ifndef QWAYLANDINPUT_H -#define QWAYLANDINPUT_H +#ifndef QWAYLANDSEAT_H +#define QWAYLANDSEAT_H #include <QtCore/qnamespace.h> #include <QtCore/QPoint> @@ -53,20 +53,19 @@ class QKeyEvent; class QTouchEvent; class QWaylandView; class QInputEvent; -class QWaylandInputDevicePrivate; +class QWaylandSeatPrivate; class QWaylandDrag; class QWaylandKeyboard; class QWaylandPointer; class QWaylandTouch; -namespace QtWayland { -class InputDevice; -} - -class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandInputDevice : public QWaylandObject +class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandSeat : public QWaylandObject { Q_OBJECT - Q_DECLARE_PRIVATE(QWaylandInputDevice) + Q_DECLARE_PRIVATE(QWaylandSeat) + + Q_PROPERTY(QWaylandDrag *drag READ drag CONSTANT) + Q_PROPERTY(QWaylandKeymap *keymap READ keymap CONSTANT) public: enum CapabilityFlag { // The order should match the enum WL_SEAT_CAPABILITY_* @@ -79,8 +78,10 @@ public: Q_DECLARE_FLAGS(CapabilityFlags, CapabilityFlag) Q_ENUM(CapabilityFlags) - QWaylandInputDevice(QWaylandCompositor *compositor, CapabilityFlags capabilityFlags = DefaultCapabilities); - virtual ~QWaylandInputDevice(); + QWaylandSeat(QWaylandCompositor *compositor, CapabilityFlags capabilityFlags = DefaultCapabilities); + virtual ~QWaylandSeat(); + virtual void initialize(); + bool isInitialized() const; void sendMousePressEvent(Qt::MouseButton button); void sendMouseReleaseEvent(Qt::MouseButton button); @@ -93,11 +94,11 @@ public: void sendFullKeyEvent(QKeyEvent *event); void sendFullKeyEvent(QWaylandSurface *surface, QKeyEvent *event); - void sendTouchPointEvent(int id, const QPointF &point, Qt::TouchPointState state); - void sendTouchFrameEvent(); - void sendTouchCancelEvent(); + uint sendTouchPointEvent(QWaylandSurface *surface, int id, const QPointF &point, Qt::TouchPointState state); + void sendTouchFrameEvent(QWaylandClient *client); + void sendTouchCancelEvent(QWaylandClient *client); - void sendFullTouchEvent(QTouchEvent *event); + void sendFullTouchEvent(QWaylandSurface *surface, QTouchEvent *event); QWaylandPointer *pointer() const; //Normally set by the mouse device, @@ -108,7 +109,7 @@ public: QWaylandKeyboard *keyboard() const; QWaylandSurface *keyboardFocus() const; bool setKeyboardFocus(QWaylandSurface *surface); - void setKeymap(const QWaylandKeymap &keymap); + QWaylandKeymap *keymap(); QWaylandTouch *touch() const; @@ -116,11 +117,11 @@ public: QWaylandDrag *drag() const; - QWaylandInputDevice::CapabilityFlags capabilities() const; + QWaylandSeat::CapabilityFlags capabilities() const; virtual bool isOwner(QInputEvent *inputEvent) const; - static QWaylandInputDevice *fromSeatResource(struct ::wl_resource *resource); + static QWaylandSeat *fromSeatResource(struct ::wl_resource *resource); Q_SIGNALS: void mouseFocusChanged(QWaylandView *newFocus, QWaylandView *oldFocus); @@ -128,8 +129,8 @@ Q_SIGNALS: void cursorSurfaceRequest(QWaylandSurface *surface, int hotspotX, int hotspotY); }; -Q_DECLARE_OPERATORS_FOR_FLAGS(QWaylandInputDevice::CapabilityFlags) +Q_DECLARE_OPERATORS_FOR_FLAGS(QWaylandSeat::CapabilityFlags) QT_END_NAMESPACE -#endif // QWAYLANDINPUT_H +#endif // QWAYLANDSEAT_H diff --git a/src/compositor/compositor_api/qwaylandinput_p.h b/src/compositor/compositor_api/qwaylandseat_p.h index 5e57c43cc..eb86aec37 100644 --- a/src/compositor/compositor_api/qwaylandinput_p.h +++ b/src/compositor/compositor_api/qwaylandseat_p.h @@ -34,8 +34,8 @@ ** ****************************************************************************/ -#ifndef QWAYLANDINPUT_P_H -#define QWAYLANDINPUT_P_H +#ifndef QWAYLANDSEAT_P_H +#define QWAYLANDSEAT_P_H // // W A R N I N G @@ -51,7 +51,7 @@ #include <stdint.h> #include <QtWaylandCompositor/qwaylandexport.h> -#include <QtWaylandCompositor/qwaylandinput.h> +#include <QtWaylandCompositor/qwaylandseat.h> #include <QtCore/QList> #include <QtCore/QPoint> @@ -68,7 +68,7 @@ QT_BEGIN_NAMESPACE class QKeyEvent; class QTouchEvent; -class QWaylandInputDevice; +class QWaylandSeat; class QWaylandDrag; class QWaylandView; @@ -85,18 +85,18 @@ class InputMethod; } -class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandInputDevicePrivate : public QObjectPrivate, public QtWaylandServer::wl_seat +class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandSeatPrivate : public QObjectPrivate, public QtWaylandServer::wl_seat { public: - Q_DECLARE_PUBLIC(QWaylandInputDevice) + Q_DECLARE_PUBLIC(QWaylandSeat) - QWaylandInputDevicePrivate(QWaylandInputDevice *device, QWaylandCompositor *compositor); - ~QWaylandInputDevicePrivate(); + QWaylandSeatPrivate(QWaylandSeat *seat); + ~QWaylandSeatPrivate(); void clientRequestedDataDevice(QtWayland::DataDeviceManager *dndSelection, struct wl_client *client, uint32_t id); - void setCapabilities(QWaylandInputDevice::CapabilityFlags caps); + void setCapabilities(QWaylandSeat::CapabilityFlags caps); - static QWaylandInputDevicePrivate *get(QWaylandInputDevice *device) { return device->d_func(); } + static QWaylandSeatPrivate *get(QWaylandSeat *device) { return device->d_func(); } QtWayland::DataDevice *dataDevice() const { return data_device.data(); } @@ -113,19 +113,21 @@ protected: void seat_destroy_resource(wl_seat::Resource *resource) Q_DECL_OVERRIDE; private: + bool isInitialized; QWaylandCompositor *compositor; QWaylandView *mouseFocus; QWaylandSurface *keyboardFocus; - QWaylandInputDevice::CapabilityFlags capabilities; + QWaylandSeat::CapabilityFlags capabilities; QScopedPointer<QWaylandPointer> pointer; QScopedPointer<QWaylandKeyboard> keyboard; QScopedPointer<QWaylandTouch> touch; QScopedPointer<QtWayland::DataDevice> data_device; QScopedPointer<QWaylandDrag> drag_handle; + QScopedPointer<QWaylandKeymap> keymap; }; QT_END_NAMESPACE -#endif // QWAYLANDINPUT_P_H +#endif // QWAYLANDSEAT_P_H diff --git a/src/compositor/compositor_api/qwaylandsurface.cpp b/src/compositor/compositor_api/qwaylandsurface.cpp index edb34e0bd..f79fd57ef 100644 --- a/src/compositor/compositor_api/qwaylandsurface.cpp +++ b/src/compositor/compositor_api/qwaylandsurface.cpp @@ -40,6 +40,7 @@ #include "wayland_wrapper/qwldatadevice_p.h" #include "wayland_wrapper/qwldatadevicemanager_p.h" +#include "wayland_wrapper/qwlbuffermanager_p.h" #include "wayland_wrapper/qwlregion_p.h" #include "extensions/qwlextendedsurface_p.h" @@ -52,7 +53,7 @@ #include <QtWaylandCompositor/private/qwaylandcompositor_p.h> #include <QtWaylandCompositor/private/qwaylandview_p.h> -#include <QtWaylandCompositor/private/qwaylandinput_p.h> +#include <QtWaylandCompositor/private/qwaylandseat_p.h> #include <QtCore/private/qobject_p.h> @@ -123,19 +124,18 @@ QWaylandSurfacePrivate::QWaylandSurfacePrivate() , compositor(Q_NULLPTR) , refCount(1) , client(Q_NULLPTR) - , buffer(0) , role(0) , inputRegion(infiniteRegion()) , bufferScale(1) , isCursorSurface(false) , destroyed(false) - , mapped(false) + , hasContent(false) , isInitialized(false) , contentOrientation(Qt::PrimaryOrientation) , inputMethodControl(Q_NULLPTR) , subsurface(0) { - pending.buffer = 0; + pending.buffer = QWaylandBufferRef(); pending.newlyAttached = false; pending.inputRegion = infiniteRegion(); pending.bufferScale = 1; @@ -153,9 +153,6 @@ QWaylandSurfacePrivate::~QWaylandSurfacePrivate() bufferRef = QWaylandBufferRef(); - for (int i = 0; i < bufferPool.size(); i++) - bufferPool[i]->setDestroyIfUnused(true); - foreach (QtWayland::FrameCallback *c, pendingFrameCallbacks) c->destroy(); foreach (QtWayland::FrameCallback *c, frameCallbacks) @@ -193,9 +190,9 @@ void QWaylandSurfacePrivate::notifyViewsAboutDestruction() foreach (QWaylandView *view, views) { QWaylandViewPrivate::get(view)->markSurfaceAsDestroyed(q); } - if (mapped) { - mapped = false; - emit q->mappedChanged(); + if (hasContent) { + hasContent = false; + emit q->hasContentChanged(); } } @@ -237,9 +234,7 @@ void QWaylandSurfacePrivate::surface_destroy(Resource *resource) void QWaylandSurfacePrivate::surface_attach(Resource *, struct wl_resource *buffer, int x, int y) { - if (pending.buffer) - pending.buffer->disown(); - pending.buffer = createSurfaceBuffer(buffer); + pending.buffer = QWaylandBufferRef(getBuffer(buffer)); pending.offset = QPoint(x, y); pending.newlyAttached = true; } @@ -274,19 +269,37 @@ void QWaylandSurfacePrivate::surface_commit(Resource *) { Q_Q(QWaylandSurface); - if (pending.buffer || pending.newlyAttached) { - setBackBuffer(pending.buffer, pending.damage); + if (pending.buffer.hasBuffer() || pending.newlyAttached) + bufferRef = pending.buffer; + + auto buffer = bufferRef.buffer(); + if (buffer) + buffer->setCommitted(pending.damage); + + setSize(bufferRef.size()); + damage = pending.damage.intersected(QRect(QPoint(), size)); + + for (int i = 0; i < views.size(); i++) { + views.at(i)->bufferCommitted(bufferRef, damage); } - pending.buffer = 0; - pending.offset = QPoint(); - pending.newlyAttached = false; - pending.damage = QRegion(); + emit q->damaged(damage); + + bool oldHasContent = hasContent; + hasContent = bufferRef.hasContent(); + if (oldHasContent != hasContent) + emit q->hasContentChanged(); + + if (!pending.offset.isNull()) + emit q->offsetForNextFrame(pending.offset); setBufferScale(pending.bufferScale); - if (buffer) - buffer->setCommitted(); + + pending.buffer = QWaylandBufferRef(); + pending.offset = QPoint(); + pending.newlyAttached = false; + pending.damage = QRegion(); frameCallbacks << pendingFrameCallbacks; pendingFrameCallbacks.clear(); @@ -326,58 +339,16 @@ void QWaylandSurfacePrivate::surface_set_buffer_scale(QtWaylandServer::wl_surfac pending.bufferScale = scale; } -void QWaylandSurfacePrivate::setBackBuffer(QtWayland::SurfaceBuffer *b, const QRegion &d) +QtWayland::ClientBuffer *QWaylandSurfacePrivate::getBuffer(struct ::wl_resource *buffer) { - Q_Q(QWaylandSurface); - buffer = b; - - bufferRef = QWaylandBufferRef(buffer); - - setSize(bufferRef.size()); - damage = d.intersected(QRect(QPoint(), size)); - - for (int i = 0; i < views.size(); i++) { - views.at(i)->attach(bufferRef, damage); - } - - emit q->damaged(damage); - - bool oldMapped = mapped; - mapped = QtWayland::SurfaceBuffer::hasContent(buffer); - if (oldMapped != mapped) - emit q->mappedChanged(); - - if (!pending.offset.isNull()) - emit q->offsetForNextFrame(pending.offset); -} - -QtWayland::SurfaceBuffer *QWaylandSurfacePrivate::createSurfaceBuffer(struct ::wl_resource *buffer) -{ - Q_Q(QWaylandSurface); - QtWayland::SurfaceBuffer *newBuffer = 0; - for (int i = 0; i < bufferPool.size(); i++) { - if (!bufferPool[i]->isRegisteredWithBuffer()) { - newBuffer = bufferPool[i]; - newBuffer->initialize(buffer); - break; - } - } - - if (!newBuffer) { - newBuffer = new QtWayland::SurfaceBuffer(q); - newBuffer->initialize(buffer); - bufferPool.append(newBuffer); - if (bufferPool.size() > 3) - qWarning() << "Increased buffer pool size to" << bufferPool.size() << "for surface" << q; - } - - return newBuffer; + QtWayland::BufferManager *bufMan = QWaylandCompositorPrivate::get(compositor)->bufferManager(); + return bufMan->getBuffer(buffer); } /*! * \qmltype WaylandSurface * \inqmlmodule QtWayland.Compositor - * \preliminary + * \since 5.8 * \brief Represents a rectangular area on an output device. * * This type encapsulates a rectangular area of pixels that is displayed on an output device. It @@ -387,7 +358,7 @@ QtWayland::SurfaceBuffer *QWaylandSurfacePrivate::createSurfaceBuffer(struct ::w /*! * \class QWaylandSurface * \inmodule QtWaylandCompositor - * \preliminary + * \since 5.8 * \brief The QWaylandSurface class represents a rectangular area on an output device. * * This class encapsulates a rectangular area of pixels that is displayed on an output device. It @@ -484,20 +455,20 @@ QWaylandClient *QWaylandSurface::client() const } /*! - * \qmlproperty bool QtWaylandCompositor::WaylandSurface::isMapped + * \qmlproperty bool QtWaylandCompositor::WaylandSurface::hasContent * * This property holds whether the WaylandSurface has content. */ /*! - * \property QWaylandSurface::isMapped + * \property QWaylandSurface::hasContent * * This property holds whether the QWaylandSurface has content. */ -bool QWaylandSurface::isMapped() const +bool QWaylandSurface::hasContent() const { Q_D(const QWaylandSurface); - return d->mapped; + return d->hasContent; } /*! @@ -590,7 +561,7 @@ Qt::ScreenOrientation QWaylandSurface::contentOrientation() const QWaylandSurface::Origin QWaylandSurface::origin() const { Q_D(const QWaylandSurface); - return d->buffer ? d->buffer->origin() : QWaylandSurface::OriginTopLeft; + return d->bufferRef.origin(); } /*! @@ -708,9 +679,9 @@ QWaylandInputMethodControl *QWaylandSurface::inputMethodControl() const void QWaylandSurface::updateSelection() { Q_D(QWaylandSurface); - QWaylandInputDevice *inputDevice = d->compositor->defaultInputDevice(); - if (inputDevice) { - const QtWayland::DataDevice *dataDevice = QWaylandInputDevicePrivate::get(inputDevice)->dataDevice(); + QWaylandSeat *seat = d->compositor->defaultSeat(); + if (seat) { + const QtWayland::DataDevice *dataDevice = QWaylandSeatPrivate::get(seat)->dataDevice(); if (dataDevice) { QWaylandCompositorPrivate::get(d->compositor)->dataDeviceManager()->offerRetainedSelection( dataDevice->resourceMap().value(d->resource()->client())->handle); @@ -719,11 +690,11 @@ void QWaylandSurface::updateSelection() } /*! - * Returns this QWaylandSurface's throttling view. + * Returns this QWaylandSurface's primary view. * - * \sa QWaylandView::advance() + * \sa QWaylandView::advance(), QWaylandSurface::setPrimaryView() */ -QWaylandView *QWaylandSurface::throttlingView() const +QWaylandView *QWaylandSurface::primaryView() const { Q_D(const QWaylandSurface); if (d->views.isEmpty()) @@ -732,15 +703,20 @@ QWaylandView *QWaylandSurface::throttlingView() const } /*! - * Sets this QWaylandSurface's throttling view to \a view, in case there are - * multiple views of this surface. The throttling view is the view that + * Sets this QWaylandSurface's primary view to \a view, in case there are + * multiple views of this surface. The primary view is the view that * governs the client's refresh rate. It takes care of discarding buffer * references when QWaylandView::advance() is called. See the documentation * for QWaylandView::advance() for more details. * + * In shell surface integrations, such as QWaylandWlShellIntegration and + * QWaylandXdgShellV5Integration, maximize and fullscreen requests from the + * client will only have an effect if the integration has the primary view + * of the surface. + * * \sa QWaylandView::advance() */ -void QWaylandSurface::setThrottlingView(QWaylandView *view) +void QWaylandSurface::setPrimaryView(QWaylandView *view) { Q_D(QWaylandSurface); @@ -835,8 +811,7 @@ void QWaylandSurfacePrivate::refView(QWaylandView *view) views.append(view); ref(); - QWaylandBufferRef ref(buffer); - view->attach(ref, QRect(QPoint(0,0), ref.size())); + view->bufferCommitted(bufferRef, QRect(QPoint(0,0), bufferRef.size())); } void QWaylandSurfacePrivate::derefView(QWaylandView *view) @@ -894,4 +869,16 @@ void QWaylandSurfacePrivate::Subsurface::subsurface_set_desync(wl_subsurface::Re qDebug() << Q_FUNC_INFO; } +/*! + * \qmlsignal void QtWaylandCompositor::WaylandSurface::dragStarted(object drag) + * + * This signal is emitted when a \a drag has started from this surface. + */ + +/*! + * \fn void QWaylandSurface::dragStarted(QWaylandDrag *drag) + * + * This signal is emitted when a \a drag has started from this surface. + */ + QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandsurface.h b/src/compositor/compositor_api/qwaylandsurface.h index 816b5c987..40753ad47 100644 --- a/src/compositor/compositor_api/qwaylandsurface.h +++ b/src/compositor/compositor_api/qwaylandsurface.h @@ -60,6 +60,7 @@ class QWaylandBufferRef; class QWaylandView; class QWaylandSurfaceOp; class QWaylandInputMethodControl; +class QWaylandDrag; class QWaylandSurfaceRole { @@ -81,7 +82,7 @@ class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandSurface : public QWaylandObject Q_PROPERTY(int bufferScale READ bufferScale NOTIFY bufferScaleChanged) Q_PROPERTY(Qt::ScreenOrientation contentOrientation READ contentOrientation NOTIFY contentOrientationChanged) Q_PROPERTY(QWaylandSurface::Origin origin READ origin NOTIFY originChanged) - Q_PROPERTY(bool isMapped READ isMapped NOTIFY mappedChanged) + Q_PROPERTY(bool hasContent READ hasContent NOTIFY hasContentChanged) Q_PROPERTY(bool cursorSurface READ isCursorSurface WRITE markAsCursorSurface) public: @@ -104,7 +105,7 @@ public: bool setRole(QWaylandSurfaceRole *role, wl_resource *errorResource, uint32_t errorCode); QWaylandSurfaceRole *role() const; - bool isMapped() const; + bool hasContent() const; QSize size() const; int bufferScale() const; @@ -123,8 +124,8 @@ public: Q_INVOKABLE void frameStarted(); Q_INVOKABLE void sendFrameCallbacks(); - QWaylandView *throttlingView() const; - void setThrottlingView(QWaylandView *view); + QWaylandView *primaryView() const; + void setPrimaryView(QWaylandView *view); QList<QWaylandView *> views() const; @@ -143,7 +144,7 @@ protected: QWaylandSurface(QWaylandSurfacePrivate &dptr); Q_SIGNALS: - void mappedChanged(); + void hasContentChanged(); void damaged(const QRegion &rect); void parentChanged(QWaylandSurface *newParent, QWaylandSurface *oldParent); void childAdded(QWaylandSurface *child); @@ -156,6 +157,7 @@ Q_SIGNALS: void subsurfacePositionChanged(const QPoint &position); void subsurfacePlaceAbove(QWaylandSurface *sibling); void subsurfacePlaceBelow(QWaylandSurface *sibling); + void dragStarted(QWaylandDrag *drag); void configure(bool hasBuffer); void redraw(); diff --git a/src/compositor/compositor_api/qwaylandsurface_p.h b/src/compositor/compositor_api/qwaylandsurface_p.h index e37179cc6..94ec287bd 100644 --- a/src/compositor/compositor_api/qwaylandsurface_p.h +++ b/src/compositor/compositor_api/qwaylandsurface_p.h @@ -52,7 +52,7 @@ #include <QtWaylandCompositor/qwaylandexport.h> #include <private/qobject_p.h> -#include <private/qwlsurfacebuffer_p.h> +#include <private/qwlclientbuffer_p.h> #include <QtWaylandCompositor/qwaylandsurface.h> #include <QtWaylandCompositor/qwaylandbufferref.h> @@ -134,8 +134,7 @@ protected: void surface_set_buffer_transform(Resource *resource, int32_t transform) Q_DECL_OVERRIDE; void surface_set_buffer_scale(Resource *resource, int32_t bufferScale) Q_DECL_OVERRIDE; - void setBackBuffer(QtWayland::SurfaceBuffer *buffer, const QRegion &damage); - QtWayland::SurfaceBuffer *createSurfaceBuffer(struct ::wl_resource *buffer); + QtWayland::ClientBuffer *getBuffer(struct ::wl_resource *buffer); public: //member variables QWaylandCompositor *compositor; @@ -143,12 +142,11 @@ public: //member variables QWaylandClient *client; QList<QWaylandView *> views; QRegion damage; - QtWayland::SurfaceBuffer *buffer; QWaylandBufferRef bufferRef; QWaylandSurfaceRole *role; struct { - QtWayland::SurfaceBuffer *buffer; + QWaylandBufferRef buffer; QRegion damage; QPoint offset; bool newlyAttached; @@ -165,13 +163,11 @@ public: //member variables QRegion inputRegion; QRegion opaqueRegion; - QVector<QtWayland::SurfaceBuffer *> bufferPool; - QSize size; int bufferScale; bool isCursorSurface; bool destroyed; - bool mapped; + bool hasContent; bool isInitialized; Qt::ScreenOrientation contentOrientation; QWindow::Visibility visibility; diff --git a/src/compositor/compositor_api/qwaylandsurfacegrabber.cpp b/src/compositor/compositor_api/qwaylandsurfacegrabber.cpp index d415642c4..58a8b7be6 100644 --- a/src/compositor/compositor_api/qwaylandsurfacegrabber.cpp +++ b/src/compositor/compositor_api/qwaylandsurfacegrabber.cpp @@ -46,12 +46,13 @@ QT_BEGIN_NAMESPACE /*! \class QWaylandSurfaceGrabber \inmodule QtWaylandCompositor - \preliminary + \since 5.8 \brief The QWaylandSurfaceGrabber class allows to read the content of a QWaylandSurface Sometimes it is needed to get the contents of a surface, for example to provide a screenshot to the user. The QWaylandSurfaceGrabber class provides a simple method to do so, without - having to care what type of buffer backs the surface, be it SHM, OpenGL or something else. + having to care what type of buffer backs the surface, be it shared memory, OpenGL or something + else. */ /*! diff --git a/src/compositor/compositor_api/qwaylandtouch.cpp b/src/compositor/compositor_api/qwaylandtouch.cpp index a9b44527e..92a8f5cf3 100644 --- a/src/compositor/compositor_api/qwaylandtouch.cpp +++ b/src/compositor/compositor_api/qwaylandtouch.cpp @@ -38,7 +38,7 @@ #include "qwaylandtouch_p.h" #include <QtWaylandCompositor/QWaylandCompositor> -#include <QtWaylandCompositor/QWaylandInputDevice> +#include <QtWaylandCompositor/QWaylandSeat> #include <QtWaylandCompositor/QWaylandView> #include <QtWaylandCompositor/QWaylandClient> @@ -46,60 +46,49 @@ QT_BEGIN_NAMESPACE -QWaylandTouchPrivate::QWaylandTouchPrivate(QWaylandTouch *touch, QWaylandInputDevice *seat) +QWaylandTouchPrivate::QWaylandTouchPrivate(QWaylandTouch *touch, QWaylandSeat *seat) : wl_touch() , seat(seat) - , focusResource() { Q_UNUSED(touch); } -void QWaylandTouchPrivate::resetFocusState() -{ - focusDestroyListener.reset(); - focusResource = 0; -} - -void QWaylandTouchPrivate::touch_bind_resource(Resource *resource) -{ - focusResource = resource; -} - -void QWaylandTouchPrivate::touch_destroy_resource(Resource *resource) -{ - if (focusResource == resource) { - resetFocusState(); - } -} - void QWaylandTouchPrivate::touch_release(Resource *resource) { wl_resource_destroy(resource->handle); } -void QWaylandTouchPrivate::sendDown(uint32_t time, int touch_id, const QPointF &position) +uint QWaylandTouchPrivate::sendDown(QWaylandSurface *surface, uint32_t time, int touch_id, const QPointF &position) { Q_Q(QWaylandTouch); - if (!focusResource || !q->mouseFocus()) - return; + auto focusResource = resourceMap().value(surface->client()->client()); + if (!focusResource) + return 0; uint32_t serial = q->compositor()->nextSerial(); - wl_touch_send_down(focusResource->handle, serial, time, q->mouseFocus()->surfaceResource(), touch_id, + wl_touch_send_down(focusResource->handle, serial, time, surface->resource(), touch_id, wl_fixed_from_double(position.x()), wl_fixed_from_double(position.y())); + return serial; } -void QWaylandTouchPrivate::sendUp(uint32_t time, int touch_id) +uint QWaylandTouchPrivate::sendUp(QWaylandClient *client, uint32_t time, int touch_id) { + auto focusResource = resourceMap().value(client->client()); + if (!focusResource) - return; + return 0; uint32_t serial = compositor()->nextSerial(); wl_touch_send_up(focusResource->handle, serial, time, touch_id); + return serial; } -void QWaylandTouchPrivate::sendMotion(uint32_t time, int touch_id, const QPointF &position) + +void QWaylandTouchPrivate::sendMotion(QWaylandClient *client, uint32_t time, int touch_id, const QPointF &position) { + auto focusResource = resourceMap().value(client->client()); + if (!focusResource) return; @@ -110,26 +99,25 @@ void QWaylandTouchPrivate::sendMotion(uint32_t time, int touch_id, const QPointF /*! * \class QWaylandTouch * \inmodule QtWaylandCompositor - * \preliminary + * \since 5.8 * \brief The QWaylandTouch class provides access to a touch device. * - * This class provides access to the touch device in a QWaylandInputDevice. It corresponds to + * This class provides access to the touch device in a QWaylandSeat. It corresponds to * the Wayland interface wl_touch. */ /*! - * Constructs a QWaylandTouch for the \a inputDevice and with the given \a parent. + * Constructs a QWaylandTouch for the \a seat and with the given \a parent. */ -QWaylandTouch::QWaylandTouch(QWaylandInputDevice *inputDevice, QObject *parent) - : QWaylandObject(*new QWaylandTouchPrivate(this, inputDevice), parent) +QWaylandTouch::QWaylandTouch(QWaylandSeat *seat, QObject *parent) + : QWaylandObject(*new QWaylandTouchPrivate(this, seat), parent) { - connect(&d_func()->focusDestroyListener, &QWaylandDestroyListener::fired, this, &QWaylandTouch::focusDestroyed); } /*! * Returns the input device for this QWaylandTouch. */ -QWaylandInputDevice *QWaylandTouch::inputDevice() const +QWaylandSeat *QWaylandTouch::seat() const { Q_D(const QWaylandTouch); return d->seat; @@ -145,71 +133,73 @@ QWaylandCompositor *QWaylandTouch::compositor() const } /*! - * Sends a touch point event for the touch device with the given \a id, + * Sends a touch point event to the touch device of \a surface with the given \a id, * \a position, and \a state. * - * - * \sa mouseFocus() + * Returns the serial of the down or up event if sent, otherwise 0. */ -void QWaylandTouch::sendTouchPointEvent(int id, const QPointF &position, Qt::TouchPointState state) +uint QWaylandTouch::sendTouchPointEvent(QWaylandSurface *surface, int id, const QPointF &position, Qt::TouchPointState state) { Q_D(QWaylandTouch); uint32_t time = compositor()->currentTimeMsecs(); + uint serial = 0; switch (state) { case Qt::TouchPointPressed: - d->sendDown(time, id, position); + serial = d->sendDown(surface, time, id, position); break; case Qt::TouchPointMoved: - d->sendMotion(time, id, position); + d->sendMotion(surface->client(), time, id, position); break; case Qt::TouchPointReleased: - d->sendUp(time, id); + serial = d->sendUp(surface->client(), time, id); break; case Qt::TouchPointStationary: // stationary points are not sent through wayland, the client must cache them break; - default: - break; } + + return serial; } /*! - * Sends a touch frame event for the touch device. This indicates the end of a + * Sends a touch frame event to the touch device of a \a client. This indicates the end of a * contact point list. */ -void QWaylandTouch::sendFrameEvent() +void QWaylandTouch::sendFrameEvent(QWaylandClient *client) { Q_D(QWaylandTouch); - if (d->focusResource) - d->send_frame(d->focusResource->handle); + auto focusResource = d->resourceMap().value(client->client()); + if (focusResource) + d->send_frame(focusResource->handle); } /*! - * Sends a touch cancel event for the touch device. + * Sends a touch cancel event to the touch device of a \a client. */ -void QWaylandTouch::sendCancelEvent() +void QWaylandTouch::sendCancelEvent(QWaylandClient *client) { Q_D(QWaylandTouch); - if (d->focusResource) - d->send_cancel(d->focusResource->handle); + auto focusResource = d->resourceMap().value(client->client()); + if (focusResource) + d->send_cancel(focusResource->handle); } /*! - * Sends all the touch points in \a event for this touch device, followed - * by a touch frame event. + * Sends all touch points in \a event to the specified \a surface, + * followed by a touch frame event. * * \sa sendTouchPointEvent(), sendFrameEvent() */ -void QWaylandTouch::sendFullTouchEvent(QTouchEvent *event) +void QWaylandTouch::sendFullTouchEvent(QWaylandSurface *surface, QTouchEvent *event) { Q_D(QWaylandTouch); if (event->type() == QEvent::TouchCancel) { - sendCancelEvent(); + sendCancelEvent(surface->client()); return; } QtWayland::TouchExtensionGlobal *ext = QtWayland::TouchExtensionGlobal::findIn(d->compositor()); - if (ext && ext->postTouchEvent(event, d->seat->mouseFocus())) + if (ext && ext->postTouchEvent(event, surface)) return; const QList<QTouchEvent::TouchPoint> points = event->touchPoints(); @@ -220,9 +210,9 @@ void QWaylandTouch::sendFullTouchEvent(QTouchEvent *event) for (int i = 0; i < pointCount; ++i) { const QTouchEvent::TouchPoint &tp(points.at(i)); // Convert the local pos in the compositor window to surface-relative. - sendTouchPointEvent(tp.id(), tp.pos(), tp.state()); + sendTouchPointEvent(surface, tp.id(), tp.pos(), tp.state()); } - sendFrameEvent(); + sendFrameEvent(surface->client()); } /*! @@ -234,45 +224,4 @@ void QWaylandTouch::addClient(QWaylandClient *client, uint32_t id, uint32_t vers d->add(client->client(), id, qMin<uint32_t>(QtWaylandServer::wl_touch::interfaceVersion(), version)); } -/*! - * Returns the Wayland resource for this QWaylandTouch. - */ -struct wl_resource *QWaylandTouch::focusResource() const -{ - Q_D(const QWaylandTouch); - if (!d->focusResource) - return Q_NULLPTR; - return d->focusResource->handle; -} - -/*! - * Returns the view currently holding mouse focus in the input device. - */ -QWaylandView *QWaylandTouch::mouseFocus() const -{ - Q_D(const QWaylandTouch); - return d->seat->mouseFocus(); -} - -/*! - * \internal - */ -void QWaylandTouch::focusDestroyed(void *data) -{ - Q_UNUSED(data) - Q_D(QWaylandTouch); - d->resetFocusState(); -} - -/*! - * \internal - */ -void QWaylandTouch::mouseFocusChanged(QWaylandView *newFocus, QWaylandView *oldFocus) -{ - Q_UNUSED(newFocus); - Q_UNUSED(oldFocus); - Q_D(QWaylandTouch); - d->resetFocusState(); -} - QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandtouch.h b/src/compositor/compositor_api/qwaylandtouch.h index b6c40ea96..05ee5ad40 100644 --- a/src/compositor/compositor_api/qwaylandtouch.h +++ b/src/compositor/compositor_api/qwaylandtouch.h @@ -48,34 +48,30 @@ QT_BEGIN_NAMESPACE class QWaylandTouch; class QWaylandTouchPrivate; -class QWaylandInputDevice; +class QWaylandSeat; class QWaylandView; class QWaylandClient; +class QWaylandSurface; class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandTouch : public QWaylandObject { Q_OBJECT Q_DECLARE_PRIVATE(QWaylandTouch) public: - QWaylandTouch(QWaylandInputDevice *inputDevice, QObject *parent = nullptr); + QWaylandTouch(QWaylandSeat *seat, QObject *parent = nullptr); - QWaylandInputDevice *inputDevice() const; + QWaylandSeat *seat() const; QWaylandCompositor *compositor() const; - virtual void sendTouchPointEvent(int id, const QPointF &position, Qt::TouchPointState state); - virtual void sendFrameEvent(); - virtual void sendCancelEvent(); - - virtual void sendFullTouchEvent(QTouchEvent *event); + virtual uint sendTouchPointEvent(QWaylandSurface *surface, int id, const QPointF &position, Qt::TouchPointState state); + virtual void sendFrameEvent(QWaylandClient *client); + virtual void sendCancelEvent(QWaylandClient *client); + virtual void sendFullTouchEvent(QWaylandSurface *surface, QTouchEvent *event); virtual void addClient(QWaylandClient *client, uint32_t id, uint32_t version); - wl_resource *focusResource() const; - - QWaylandView *mouseFocus() const; private: void focusDestroyed(void *data); - void mouseFocusChanged(QWaylandView *newFocus, QWaylandView *oldFocus); }; QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandtouch_p.h b/src/compositor/compositor_api/qwaylandtouch_p.h index ea334eea1..75529134b 100644 --- a/src/compositor/compositor_api/qwaylandtouch_p.h +++ b/src/compositor/compositor_api/qwaylandtouch_p.h @@ -52,7 +52,7 @@ #include <QtWaylandCompositor/qwaylandexport.h> #include <QtWaylandCompositor/QWaylandDestroyListener> #include <QtWaylandCompositor/QWaylandTouch> -#include <QtWaylandCompositor/QWaylandInputDevice> +#include <QtWaylandCompositor/QWaylandSeat> #include <QtWaylandCompositor/QWaylandView> #include <QtWaylandCompositor/QWaylandCompositor> @@ -67,35 +67,18 @@ class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandTouchPrivate : public QObjectPrivate, { Q_DECLARE_PUBLIC(QWaylandTouch) public: - explicit QWaylandTouchPrivate(QWaylandTouch *touch, QWaylandInputDevice *seat); + explicit QWaylandTouchPrivate(QWaylandTouch *touch, QWaylandSeat *seat); QWaylandCompositor *compositor() const { return seat->compositor(); } - void sendDown(uint32_t time, int touch_id, const QPointF &position); - void sendMotion(uint32_t time, int touch_id, const QPointF &position); - void sendUp(uint32_t time, int touch_id); + uint sendDown(QWaylandSurface *surface, uint32_t time, int touch_id, const QPointF &position); + void sendMotion(QWaylandClient *client, uint32_t time, int touch_id, const QPointF &position); + uint sendUp(QWaylandClient *client, uint32_t time, int touch_id); - void setFocusResource() - { - if (focusResource) - return; - - QWaylandView *mouseFocus = seat->mouseFocus(); - if (!mouseFocus || !mouseFocus->surface()) - return; - - focusResource = resourceMap().value(mouseFocus->surface()->waylandClient()); - } private: - void resetFocusState(); - void touch_bind_resource(Resource *resource) Q_DECL_OVERRIDE; - void touch_destroy_resource(Resource *resource) Q_DECL_OVERRIDE; void touch_release(Resource *resource) Q_DECL_OVERRIDE; - QWaylandInputDevice *seat; - - Resource *focusResource; - QWaylandDestroyListener focusDestroyListener; + QWaylandSeat *seat; }; QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandview.cpp b/src/compositor/compositor_api/qwaylandview.cpp index 12b67bf5d..2302fe604 100644 --- a/src/compositor/compositor_api/qwaylandview.cpp +++ b/src/compositor/compositor_api/qwaylandview.cpp @@ -37,7 +37,7 @@ #include "qwaylandview.h" #include "qwaylandview_p.h" #include "qwaylandsurface.h" -#include <QtWaylandCompositor/QWaylandInputDevice> +#include <QtWaylandCompositor/QWaylandSeat> #include <QtWaylandCompositor/QWaylandCompositor> #include <QtWaylandCompositor/private/qwaylandsurface_p.h> @@ -59,7 +59,7 @@ void QWaylandViewPrivate::markSurfaceAsDestroyed(QWaylandSurface *surface) /*! * \qmltype WaylandView * \inqmlmodule QtWayland.Compositor - * \preliminary + * \since 5.8 * \brief Represents a view of a surface on an output. * * The WaylandView corresponds to the presentation of a surface on a specific @@ -70,7 +70,7 @@ void QWaylandViewPrivate::markSurfaceAsDestroyed(QWaylandSurface *surface) /*! * \class QWaylandView * \inmodule QtWaylandCompositor - * \preliminary + * \since 5.8 * \brief The QWaylandView class represents a view of a surface on an output. * * The QWaylandView corresponds to the presentation of a surface on a specific @@ -96,7 +96,7 @@ QWaylandView::~QWaylandView() if (d->surface) { if (d->output) QWaylandOutputPrivate::get(d->output)->removeView(this, d->surface); - QWaylandInputDevice *i = d->surface->compositor()->defaultInputDevice(); + QWaylandSeat *i = d->surface->compositor()->defaultSeat(); if (i->mouseFocus() == this) i->setMouseFocus(Q_NULLPTR); @@ -145,12 +145,13 @@ void QWaylandView::setSurface(QWaylandSurface *newSurface) d->surface = newSurface; - if (!d->bufferLock) { + if (!d->bufferLocked) { d->currentBuffer = QWaylandBufferRef(); d->currentDamage = QRegion(); } d->nextBuffer = QWaylandBufferRef(); + d->nextBufferCommitted = false; d->nextDamage = QRegion(); if (d->surface) { @@ -198,51 +199,49 @@ void QWaylandView::setOutput(QWaylandOutput *newOutput) } /*! - * Attaches a new buffer \a ref and a \a damage region to this QWaylandView. These - * will become current on a subsequent call to the advance() method. + * This function is called when a new \a buffer is committed to this view's surface. + * \a damage contains the region that is different from the current buffer, i.e. the + * region that needs to be updated. + * The new \a buffer will become current on the next call to advance(). + * + * Subclasses that reimplement this function \e must call the base implementation. */ -void QWaylandView::attach(const QWaylandBufferRef &ref, const QRegion &damage) +void QWaylandView::bufferCommitted(const QWaylandBufferRef &buffer, const QRegion &damage) { Q_D(QWaylandView); QMutexLocker locker(&d->bufferMutex); - d->nextBuffer = ref; + d->nextBuffer = buffer; d->nextDamage = damage; + d->nextBufferCommitted = true; } /*! - * Sets the next buffer and damage region to current and returns \c true. If the buffer - * is locked or if no new buffer has been attached since the last call to - * advance(), the function returns \c false and does nothing. - * - * If this view is set as the surface's throttling view, discardCurrentBuffer() - * is called on all views of the same surface for which the - * \l{QWaylandView::discardFrontBuffers}{discardFrontBuffers} - * property is set to true and the current buffer is the same as the - * throttling view's current buffer. + * Updates the current buffer and damage region to the latest version committed by the client. + * Returns true if new content was committed since the previous call to advance(). + * Otherwise returns false. * - * To enable clients to reuse existing buffers, enable the primary view to ensure - * that views running on a lower frequency will release their front buffer - * references. This design approach should avoid the situation where the lower - * frequency views throttle the frame rate of the client application. + * \sa currentBuffer(), currentDamage() */ bool QWaylandView::advance() { Q_D(QWaylandView); - if (d->currentBuffer == d->nextBuffer && !d->forceAdvanceSucceed) + + if (!d->nextBufferCommitted && !d->forceAdvanceSucceed) return false; - if (d->bufferLock) + if (d->bufferLocked) return false; - if (d->surface && d->surface->throttlingView() == this) { + if (d->surface && d->surface->primaryView() == this) { Q_FOREACH (QWaylandView *view, d->surface->views()) { - if (view != this && view->discardFrontBuffers() && view->d_func()->currentBuffer == d->currentBuffer) + if (view != this && view->allowDiscardFrontBuffer() && view->d_func()->currentBuffer == d->currentBuffer) view->discardCurrentBuffer(); } } QMutexLocker locker(&d->bufferMutex); d->forceAdvanceSucceed = false; + d->nextBufferCommitted = false; d->currentBuffer = d->nextBuffer; d->currentDamage = d->nextDamage; return true; @@ -280,7 +279,7 @@ QRegion QWaylandView::currentDamage() } /*! - * \qmlproperty bool QtWaylandCompositor::WaylandView::bufferLock + * \qmlproperty bool QtWaylandCompositor::WaylandView::bufferLocked * * This property holds whether the view's buffer is currently locked. When * the buffer is locked, advance() will not advance to the next buffer and @@ -290,7 +289,7 @@ QRegion QWaylandView::currentDamage() */ /*! - * \property QWaylandView::bufferLock + * \property QWaylandView::bufferLocked * * This property holds whether the view's buffer is currently locked. When * the buffer is locked, advance() will not advance to the next buffer @@ -301,42 +300,71 @@ QRegion QWaylandView::currentDamage() bool QWaylandView::isBufferLocked() const { Q_D(const QWaylandView); - return d->bufferLock; + return d->bufferLocked; } -void QWaylandView::setBufferLock(bool locked) +void QWaylandView::setBufferLocked(bool locked) { Q_D(QWaylandView); - if (d->bufferLock == locked) + if (d->bufferLocked == locked) return; - d->bufferLock = locked; - emit bufferLockChanged(); + d->bufferLocked = locked; + emit bufferLockedChanged(); } /*! - * \qmlproperty bool QtWaylandCompositor::WaylandView::discardFrontBuffers + * \qmlproperty bool QtWaylandCompositor::WaylandView::allowDiscardFrontBuffer * * By default, the view locks the current buffer until advance() is called. Set this property - * to true to allow Qt to release the buffer when the throttling view is no longer using it. + * to true to allow Qt to release the buffer when the primary view is no longer using it. + * + * This can be used to avoid the situation where a secondary view that updates on a lower + * frequency will throttle the frame rate of the client application. */ + /*! - * \property QWaylandView::discardFrontBuffers + * \property QWaylandView::allowDiscardFrontBuffer * * By default, the view locks the current buffer until advance() is called. Set this property - * to \c true to allow Qt to release the buffer when the throttling view is no longer using it. + * to \c true to allow Qt to release the buffer when the primary view is no longer using it. + * + * This can be used to avoid the situation where a secondary view that updates on a lower + * frequency will throttle the frame rate of the client application. */ -bool QWaylandView::discardFrontBuffers() const +bool QWaylandView::allowDiscardFrontBuffer() const { Q_D(const QWaylandView); - return d->discardFrontBuffers; + return d->allowDiscardFrontBuffer; } -void QWaylandView::setDiscardFrontBuffers(bool discard) +void QWaylandView::setAllowDiscardFrontBuffer(bool discard) { Q_D(QWaylandView); - if (d->discardFrontBuffers == discard) + if (d->allowDiscardFrontBuffer == discard) return; - d->discardFrontBuffers = discard; - emit discardFrontBuffersChanged(); + d->allowDiscardFrontBuffer = discard; + emit allowDiscardFrontBufferChanged(); +} + +/*! + * Makes this QWaylandView the primary view for the surface. + * + * \sa QWaylandSurface::primaryView + */ +void QWaylandView::setPrimary() +{ + Q_D(QWaylandView); + d->surface->setPrimaryView(this); +} + +/*! + * Returns true if this QWaylandView is the primary view for the QWaylandSurface + * + * \sa QWaylandSurface::primaryView + */ +bool QWaylandView::isPrimary() const +{ + Q_D(const QWaylandView); + return d->surface->primaryView() == this; } /*! diff --git a/src/compositor/compositor_api/qwaylandview.h b/src/compositor/compositor_api/qwaylandview.h index f89d8ca78..987340034 100644 --- a/src/compositor/compositor_api/qwaylandview.h +++ b/src/compositor/compositor_api/qwaylandview.h @@ -56,8 +56,8 @@ class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandView : public QObject Q_PROPERTY(QObject *renderObject READ renderObject CONSTANT) Q_PROPERTY(QWaylandSurface *surface READ surface WRITE setSurface NOTIFY surfaceChanged) Q_PROPERTY(QWaylandOutput *output READ output WRITE setOutput NOTIFY outputChanged) - Q_PROPERTY(bool bufferLock READ isBufferLocked WRITE setBufferLock NOTIFY bufferLockChanged) - Q_PROPERTY(bool discardFrontBuffers READ discardFrontBuffers WRITE setDiscardFrontBuffers NOTIFY discardFrontBuffersChanged) + Q_PROPERTY(bool bufferLocked READ isBufferLocked WRITE setBufferLocked NOTIFY bufferLockedChanged) + Q_PROPERTY(bool allowDiscardFrontBuffer READ allowDiscardFrontBuffer WRITE setAllowDiscardFrontBuffer NOTIFY allowDiscardFrontBufferChanged) public: QWaylandView(QObject *renderObject = nullptr, QObject *parent = nullptr); virtual ~QWaylandView(); @@ -70,17 +70,20 @@ public: QWaylandOutput *output() const; void setOutput(QWaylandOutput *output); - virtual void attach(const QWaylandBufferRef &ref, const QRegion &damage); + virtual void bufferCommitted(const QWaylandBufferRef &buffer, const QRegion &damage); virtual bool advance(); virtual void discardCurrentBuffer(); virtual QWaylandBufferRef currentBuffer(); virtual QRegion currentDamage(); bool isBufferLocked() const; - void setBufferLock(bool locked); + void setBufferLocked(bool locked); - bool discardFrontBuffers() const; - void setDiscardFrontBuffers(bool discard); + bool allowDiscardFrontBuffer() const; + void setAllowDiscardFrontBuffer(bool discard); + + void setPrimary(); + bool isPrimary() const; struct wl_resource *surfaceResource() const; @@ -88,8 +91,8 @@ Q_SIGNALS: void surfaceChanged(); void surfaceDestroyed(); void outputChanged(); - void bufferLockChanged(); - void discardFrontBuffersChanged(); + void bufferLockedChanged(); + void allowDiscardFrontBufferChanged(); }; QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandview_p.h b/src/compositor/compositor_api/qwaylandview_p.h index 8c4cea085..8c55eca36 100644 --- a/src/compositor/compositor_api/qwaylandview_p.h +++ b/src/compositor/compositor_api/qwaylandview_p.h @@ -69,10 +69,11 @@ public: : renderObject(Q_NULLPTR) , surface(Q_NULLPTR) , output(Q_NULLPTR) - , bufferLock(false) + , nextBufferCommitted(false) + , bufferLocked(false) , broadcastRequestedPositionChanged(false) , forceAdvanceSucceed(false) - , discardFrontBuffers(false) + , allowDiscardFrontBuffer(false) { } void markSurfaceAsDestroyed(QWaylandSurface *surface); @@ -86,10 +87,11 @@ public: QRegion currentDamage; QWaylandBufferRef nextBuffer; QRegion nextDamage; - bool bufferLock; + bool nextBufferCommitted; + bool bufferLocked; bool broadcastRequestedPositionChanged; bool forceAdvanceSucceed; - bool discardFrontBuffers; + bool allowDiscardFrontBuffer; }; QT_END_NAMESPACE diff --git a/src/compositor/doc/src/qtwaylandcompositor-overview.qdoc b/src/compositor/doc/src/qtwaylandcompositor-overview.qdoc index d2f0f6f40..05ab4fb03 100644 --- a/src/compositor/doc/src/qtwaylandcompositor-overview.qdoc +++ b/src/compositor/doc/src/qtwaylandcompositor-overview.qdoc @@ -62,6 +62,20 @@ Take a look at the \l{Qt Wayland Compositor Examples} for a demonstration on how the APIs can be used to write custom display servers. + \section1 Licenses and Attributions + + Qt Wayland Compositor and the Qt Wayland integration plugin + are available under commercial licenses from \l{The Qt Company}. + In addition, they are available under the + \l{GNU Lesser General Public License, version 3}, or + the \l{GNU General Public License, version 2}. + See \l{Qt Licensing} for further details. + + Qt Wayland Compositor and the Qt Wayland integration plugin + use protocol definitions under following permissive licenses: + + \generatelist{groupsbymodule attributions-qtwaylandcompositor} + \section1 API Reference The Qt Wayland Compositor API can be used from C++ or QML. diff --git a/src/compositor/extensions/extensions.pri b/src/compositor/extensions/extensions.pri index 4894eb3c4..9c5b37eac 100644 --- a/src/compositor/extensions/extensions.pri +++ b/src/compositor/extensions/extensions.pri @@ -5,47 +5,59 @@ WAYLANDSERVERSOURCES += \ ../extensions/surface-extension.xml \ ../extensions/touch-extension.xml \ ../extensions/qtkey-extension.xml \ - ../extensions/windowmanager.xml \ + ../extensions/qt-windowmanager.xml \ ../3rdparty/protocol/text-input-unstable-v2.xml \ ../3rdparty/protocol/xdg-shell.xml \ + ../3rdparty/protocol/ivi-application.xml \ HEADERS += \ extensions/qwlextendedsurface_p.h \ extensions/qwlqttouch_p.h \ extensions/qwlqtkey_p.h \ + extensions/qwaylandshell.h \ + extensions/qwaylandshell_p.h \ extensions/qwaylandwlshell.h \ extensions/qwaylandwlshell_p.h \ extensions/qwaylandtextinput.h \ extensions/qwaylandtextinput_p.h \ extensions/qwaylandtextinputmanager.h \ extensions/qwaylandtextinputmanager_p.h \ - extensions/qwaylandwindowmanagerextension.h \ - extensions/qwaylandwindowmanagerextension_p.h \ - extensions/qwaylandxdgshell.h \ - extensions/qwaylandxdgshell_p.h \ + extensions/qwaylandqtwindowmanager.h \ + extensions/qwaylandqtwindowmanager_p.h \ + extensions/qwaylandxdgshellv5.h \ + extensions/qwaylandxdgshellv5_p.h \ extensions/qwaylandshellsurface.h \ + extensions/qwaylandiviapplication.h \ + extensions/qwaylandiviapplication_p.h \ + extensions/qwaylandivisurface.h \ + extensions/qwaylandivisurface_p.h \ SOURCES += \ extensions/qwlextendedsurface.cpp \ extensions/qwlqttouch.cpp \ extensions/qwlqtkey.cpp \ + extensions/qwaylandshell.cpp \ extensions/qwaylandwlshell.cpp \ extensions/qwaylandtextinput.cpp \ extensions/qwaylandtextinputmanager.cpp \ - extensions/qwaylandwindowmanagerextension.cpp \ - extensions/qwaylandxdgshell.cpp \ + extensions/qwaylandqtwindowmanager.cpp \ + extensions/qwaylandxdgshellv5.cpp \ + extensions/qwaylandiviapplication.cpp \ + extensions/qwaylandivisurface.cpp \ -qtHaveModule(quick) { +qtHaveModule(quick):contains(QT_CONFIG, opengl) { HEADERS += \ extensions/qwaylandquickshellsurfaceitem.h \ extensions/qwaylandquickshellsurfaceitem_p.h \ + extensions/qwaylandivisurfaceintegration_p.h \ extensions/qwaylandwlshellintegration_p.h \ - extensions/qwaylandxdgshellintegration_p.h \ + extensions/qwaylandxdgshellv5integration_p.h \ SOURCES += \ extensions/qwaylandquickshellsurfaceitem.cpp \ + extensions/qwaylandivisurfaceintegration.cpp \ extensions/qwaylandwlshellintegration.cpp \ - extensions/qwaylandxdgshellintegration.cpp \ + extensions/qwaylandxdgshellv5integration.cpp \ } diff --git a/src/compositor/extensions/qwaylandiviapplication.cpp b/src/compositor/extensions/qwaylandiviapplication.cpp new file mode 100644 index 000000000..30784e4ec --- /dev/null +++ b/src/compositor/extensions/qwaylandiviapplication.cpp @@ -0,0 +1,166 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWaylandCompositor module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwaylandiviapplication.h" +#include "qwaylandiviapplication_p.h" + +#include <QtWaylandCompositor/QWaylandCompositor> +#include <QtWaylandCompositor/QWaylandSurface> +#include <QtWaylandCompositor/QWaylandIviSurface> +#include <QtWaylandCompositor/QWaylandResource> + +QT_BEGIN_NAMESPACE + +/*! + * Constructs a QWaylandIviApplication object. + */ +QWaylandIviApplication::QWaylandIviApplication() + : QWaylandCompositorExtensionTemplate<QWaylandIviApplication>(*new QWaylandIviApplicationPrivate()) +{ +} + +/*! + * Constructs a QWaylandIviApplication object for the provided \a compositor. + */ +QWaylandIviApplication::QWaylandIviApplication(QWaylandCompositor *compositor) + : QWaylandCompositorExtensionTemplate<QWaylandIviApplication>(compositor, *new QWaylandIviApplicationPrivate()) +{ +} + +/*! + * Initializes the shell extension. + */ +void QWaylandIviApplication::initialize() +{ + Q_D(QWaylandIviApplication); + QWaylandCompositorExtensionTemplate::initialize(); + + QWaylandCompositor *compositor = static_cast<QWaylandCompositor *>(extensionContainer()); + if (!compositor) { + qWarning() << "Failed to find QWaylandCompositor when initializing QWaylandIviApplication"; + return; + } + + d->init(compositor->display(), 1); +} + +/*! + * Returns the Wayland interface for the QWaylandIviApplication. + */ +const struct wl_interface *QWaylandIviApplication::interface() +{ + return QWaylandIviApplicationPrivate::interface(); +} + +QByteArray QWaylandIviApplication::interfaceName() +{ + return QWaylandIviApplicationPrivate::interfaceName(); +} + +/*! + * \qmlsignal void QtWaylandCompositor::IviApplication::iviSurfaceRequested(object surface, int iviId, object resource) + * + * This signal is emitted when the client has requested an \c ivi_surface to be associated + * with \a surface, which is identified by \a id. The handler for this signal is + * expected to create the ivi surface and initialize it within the scope of the + * signal emission. If no ivi surface is created, a default one will be created instead. + */ + +/*! + * \fn void QWaylandWlShell::iviSurfaceRequested(QWaylandSurface *surface, uint iviId, const QWaylandResource &resource) + * + * This signal is emitted when the client has requested an \c ivi_surface to be associated + * with \a surface, which is identified by \a id. The handler for this signal is + * expected to create the ivi surface and initialize it within the scope of the + * signal emission. If no ivi surface is created, a default one will be created instead. + */ + +/*! + * \qmlsignal void QtWaylandCompositor::IviApplication::iviSurfaceCreated(object *iviSurface) + * + * This signal is emitted when an IviSurface has been created. The supplied \a iviSurface is + * most commonly used to instantiate a ShellSurfaceItem. + */ + +/*! + * \fn void QtWaylandCompositor::IviApplication::iviSurfaceCreated(QWaylandIviSurface *iviSurface) + * + * This signal is emitted when an IviSurface has been created. + */ + +QWaylandIviApplicationPrivate::QWaylandIviApplicationPrivate() + : QWaylandCompositorExtensionPrivate() + , ivi_application() +{ +} + +void QWaylandIviApplicationPrivate::unregisterIviSurface(QWaylandIviSurface *iviSurface) +{ + m_iviSurfaces.remove(iviSurface->iviId()); +} + +void QWaylandIviApplicationPrivate::ivi_application_surface_create(QtWaylandServer::ivi_application::Resource *resource, + uint32_t ivi_id, wl_resource *surfaceResource, uint32_t id) +{ + Q_Q(QWaylandIviApplication); + QWaylandSurface *surface = QWaylandSurface::fromResource(surfaceResource); + + if (m_iviSurfaces.contains(ivi_id)) { + wl_resource_post_error(resource->handle, IVI_APPLICATION_ERROR_IVI_ID, + "Given ivi_id, %d, is already assigned to wl_surface@%d", ivi_id, + wl_resource_get_id(m_iviSurfaces[ivi_id]->surface()->resource())); + return; + } + + if (!surface->setRole(QWaylandIviSurface::role(), resource->handle, IVI_APPLICATION_ERROR_ROLE)) + return; + + QWaylandResource iviSurfaceResource(wl_resource_create(resource->client(), &ivi_surface_interface, + wl_resource_get_version(resource->handle), id)); + + emit q->iviSurfaceRequested(surface, ivi_id, iviSurfaceResource); + + QWaylandIviSurface *iviSurface = QWaylandIviSurface::fromResource(iviSurfaceResource.resource()); + + if (!iviSurface) + iviSurface = new QWaylandIviSurface(q, surface, ivi_id, iviSurfaceResource); + + m_iviSurfaces.insert(ivi_id, iviSurface); + + emit q->iviSurfaceCreated(iviSurface); +} + +QT_END_NAMESPACE diff --git a/src/compositor/extensions/qwaylandiviapplication.h b/src/compositor/extensions/qwaylandiviapplication.h new file mode 100644 index 000000000..a3e057a86 --- /dev/null +++ b/src/compositor/extensions/qwaylandiviapplication.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWaylandCompositor module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDIVIAPPLICATION_H +#define QWAYLANDIVIAPPLICATION_H + +#include <QtWaylandCompositor/QWaylandCompositorExtension> +#include <QtCore/QSize> + +class QWaylandIviSurface; +class QWaylandSurface; +class QWaylandResource; +class QWaylandIviApplicationPrivate; + +QT_BEGIN_NAMESPACE + +class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandIviApplication : public QWaylandCompositorExtensionTemplate<QWaylandIviApplication> +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QWaylandIviApplication) + +public: + QWaylandIviApplication(); + QWaylandIviApplication(QWaylandCompositor *compositor); + + void initialize() Q_DECL_OVERRIDE; + + static const struct wl_interface *interface(); + static QByteArray interfaceName(); + +Q_SIGNALS: + void iviSurfaceRequested(QWaylandSurface *surface, uint iviId, const QWaylandResource &resource); + void iviSurfaceCreated(QWaylandIviSurface *iviSurface); +}; + +QT_END_NAMESPACE + +#endif // QWAYLANDIVIAPPLICATION_H diff --git a/src/compositor/extensions/qwaylandiviapplication_p.h b/src/compositor/extensions/qwaylandiviapplication_p.h new file mode 100644 index 000000000..ea211a84a --- /dev/null +++ b/src/compositor/extensions/qwaylandiviapplication_p.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWaylandCompositor module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDIVIAPPLICATION_P_H +#define QWAYLANDIVIAPPLICATION_P_H + +#include <QtWaylandCompositor/private/qwaylandcompositorextension_p.h> +#include <QtWaylandCompositor/private/qwayland-server-ivi-application.h> + +#include <QtWaylandCompositor/QWaylandIviApplication> + +#include <QHash> + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +QT_BEGIN_NAMESPACE + +class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandIviApplicationPrivate + : public QWaylandCompositorExtensionPrivate + , public QtWaylandServer::ivi_application +{ + Q_DECLARE_PUBLIC(QWaylandIviApplication) + +public: + QWaylandIviApplicationPrivate(); + static QWaylandIviApplicationPrivate *get(QWaylandIviApplication *iviApplication) { return iviApplication->d_func(); } + void unregisterIviSurface(QWaylandIviSurface *iviSurface); + + QHash<uint, QWaylandIviSurface*> m_iviSurfaces; + +protected: + void ivi_application_surface_create(Resource *resource, uint32_t ivi_id, wl_resource *surface, uint32_t id) Q_DECL_OVERRIDE; +}; + +QT_END_NAMESPACE + +#endif // QWAYLANDIVIAPPLICATION_P_H diff --git a/src/compositor/extensions/qwaylandivisurface.cpp b/src/compositor/extensions/qwaylandivisurface.cpp new file mode 100644 index 000000000..06e12a5ab --- /dev/null +++ b/src/compositor/extensions/qwaylandivisurface.cpp @@ -0,0 +1,226 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWaylandCompositor module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwaylandivisurface.h" +#include "qwaylandivisurface_p.h" +#include "qwaylandiviapplication_p.h" +#include "qwaylandivisurfaceintegration_p.h" + +#include <QtWaylandCompositor/QWaylandResource> + +QT_BEGIN_NAMESPACE + +QWaylandSurfaceRole QWaylandIviSurfacePrivate::s_role("ivi_surface"); + +/*! + * \class QWaylandIviSurface + * \inmodule QtWaylandCompositor + * \since 5.8 + * \brief The QWaylandIviSurface class provides a simple way to identify and resize a surface. + * + * This class is part of the QWaylandIviApplication extension and provides a way to + * extend the functionality of an existing QWaylandSurface with features a way to + * resize and identify it. + * + * It corresponds to the Wayland interface ivi_surface. + */ + +/*! + * Constructs a QWaylandIviSurface. + */ +QWaylandIviSurface::QWaylandIviSurface() + : QWaylandShellSurfaceTemplate<QWaylandIviSurface>(*new QWaylandIviSurfacePrivate()) +{ +} + +/*! + * Constructs a QWaylandIviSurface for \a surface and initializes it with the + * given \a application, \a surface, \a iviId, and \a resource. + */ +QWaylandIviSurface::QWaylandIviSurface(QWaylandIviApplication *application, QWaylandSurface *surface, uint iviId, const QWaylandResource &resource) + : QWaylandShellSurfaceTemplate<QWaylandIviSurface>(*new QWaylandIviSurfacePrivate()) +{ + initialize(application, surface, iviId, resource); +} + +/*! + * \qmlmethod void QtWaylandCompositor::IviSurface::initialize(object iviApplication, object surface, int iviId, object resource) + * + * Initializes the IviSurface, associating it with the given \a iviApplication, \a surface, + * \a client, \a iviId, and \a resource. + */ + +/*! + * Initializes the QWaylandIviSurface, associating it with the given \a iviApplication, \a surface, + * \a iviId, and \a resource. + */ +void QWaylandIviSurface::initialize(QWaylandIviApplication *iviApplication, QWaylandSurface *surface, uint iviId, const QWaylandResource &resource) +{ + Q_D(QWaylandIviSurface); + + d->m_iviApplication = iviApplication; + d->m_surface = surface; + d->m_iviId = iviId; + + d->init(resource.resource()); + setExtensionContainer(surface); + + emit surfaceChanged(); + emit iviIdChanged(); + + QWaylandCompositorExtension::initialize(); +} + +/*! + * \qmlproperty object QtWaylandCompositor::IviSurface::surface + * + * This property holds the surface associated with this IviSurface. + */ + +/*! + * \property QWaylandIviSurface::surface + * + * This property holds the surface associated with this QWaylandIviSurface. + */ +QWaylandSurface *QWaylandIviSurface::surface() const +{ + Q_D(const QWaylandIviSurface); + return d->m_surface; +} + +/*! + * \qmlproperty int QtWaylandCompositor::IviSurface::iviId + * \readonly + * + * This property holds the ivi id id of this IviSurface. + */ + +/*! + * \property QWaylandIviSurface::iviId + * + * This property holds the ivi id of this QWaylandIviSurface. + */ +uint QWaylandIviSurface::iviId() const +{ + Q_D(const QWaylandIviSurface); + return d->m_iviId; +} + +/*! + * Returns the Wayland interface for the QWaylandIviSurface. + */ +const struct wl_interface *QWaylandIviSurface::interface() +{ + return QWaylandIviSurfacePrivate::interface(); +} + +QByteArray QWaylandIviSurface::interfaceName() +{ + return QWaylandIviSurfacePrivate::interfaceName(); +} + +/*! + * Returns the surface role for the QWaylandIviSurface. + */ +QWaylandSurfaceRole *QWaylandIviSurface::role() +{ + return &QWaylandIviSurfacePrivate::s_role; +} + +/*! + * Returns the QWaylandIviSurface corresponding to the \a resource. + */ +QWaylandIviSurface *QWaylandIviSurface::fromResource(wl_resource *resource) +{ + auto iviSurfaceResource = QWaylandIviSurfacePrivate::Resource::fromResource(resource); + if (!iviSurfaceResource) + return nullptr; + return static_cast<QWaylandIviSurfacePrivate *>(iviSurfaceResource->ivi_surface_object)->q_func(); +} + +/*! + * \qmlmethod int QtWaylandCompositor::IviSurface::sendConfigure(size size) + * + * Sends a configure event to the client, telling it to resize the surface to the given \a size. + */ + +/*! + * Sends a configure event to the client, telling it to resize the surface to the given \a size. + */ +void QWaylandIviSurface::sendConfigure(const QSize &size) +{ + Q_D(QWaylandIviSurface); + d->send_configure(size.width(), size.height()); +} + +#ifdef QT_WAYLAND_COMPOSITOR_QUICK +QWaylandQuickShellIntegration *QWaylandIviSurface::createIntegration(QWaylandQuickShellSurfaceItem *item) +{ + return new QtWayland::IviSurfaceIntegration(item); +} +#endif + +/*! + * \internal + */ +void QWaylandIviSurface::initialize() +{ + QWaylandShellSurfaceTemplate::initialize(); +} + +QWaylandIviSurfacePrivate::QWaylandIviSurfacePrivate() + : QWaylandCompositorExtensionPrivate() + , ivi_surface() + , m_iviApplication(nullptr) + , m_surface(nullptr) + , m_iviId(UINT_MAX) +{ +} + +void QWaylandIviSurfacePrivate::ivi_surface_destroy_resource(QtWaylandServer::ivi_surface::Resource *resource) +{ + Q_UNUSED(resource); + Q_Q(QWaylandIviSurface); + QWaylandIviApplicationPrivate::get(m_iviApplication)->unregisterIviSurface(q); + delete q; +} + +void QWaylandIviSurfacePrivate::ivi_surface_destroy(QtWaylandServer::ivi_surface::Resource *resource) +{ + wl_resource_destroy(resource->handle); +} + +QT_END_NAMESPACE diff --git a/src/compositor/extensions/qwaylandivisurface.h b/src/compositor/extensions/qwaylandivisurface.h new file mode 100644 index 000000000..37c37c0f3 --- /dev/null +++ b/src/compositor/extensions/qwaylandivisurface.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWaylandCompositor module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDIVISURFACE_H +#define QWAYLANDIVISURFACE_H + +#include <QtWaylandCompositor/QWaylandShellSurface> + +class QWaylandIviSurfacePrivate; +class QWaylandSurface; +class QWaylandIviApplication; +class QWaylandSurfaceRole; +class QWaylandResource; +class wl_resource; + +QT_BEGIN_NAMESPACE + +class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandIviSurface : public QWaylandShellSurfaceTemplate<QWaylandIviSurface> +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QWaylandIviSurface) + Q_PROPERTY(QWaylandSurface *surface READ surface NOTIFY surfaceChanged) + Q_PROPERTY(uint iviId READ iviId NOTIFY iviIdChanged) + +public: + QWaylandIviSurface(); + QWaylandIviSurface(QWaylandIviApplication *application, QWaylandSurface *surface, uint iviId, const QWaylandResource &resource); + + Q_INVOKABLE void initialize(QWaylandIviApplication *iviApplication, QWaylandSurface *surface, + uint iviId, const QWaylandResource &resource); + + QWaylandSurface *surface() const; + uint iviId() const; + + static const struct wl_interface *interface(); + static QByteArray interfaceName(); + static QWaylandSurfaceRole *role(); + static QWaylandIviSurface *fromResource(::wl_resource *resource); + + Q_INVOKABLE void sendConfigure(const QSize &size); + +#ifdef QT_WAYLAND_COMPOSITOR_QUICK + QWaylandQuickShellIntegration *createIntegration(QWaylandQuickShellSurfaceItem *item) Q_DECL_OVERRIDE; +#endif + +Q_SIGNALS: + void surfaceChanged(); + void iviIdChanged(); + +private: + void initialize(); +}; + +QT_END_NAMESPACE + +#endif // QWAYLANDIVISURFACE_H diff --git a/src/compositor/extensions/qwaylandivisurface_p.h b/src/compositor/extensions/qwaylandivisurface_p.h new file mode 100644 index 000000000..db237721d --- /dev/null +++ b/src/compositor/extensions/qwaylandivisurface_p.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWaylandCompositor module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDIVISURFACE_P_H +#define QWAYLANDIVISURFACE_P_H + +#include <QtWaylandCompositor/private/qwaylandcompositorextension_p.h> +#include <QtWaylandCompositor/private/qwayland-server-ivi-application.h> + +#include <QtWaylandCompositor/QWaylandIviSurface> + +#include <QtWaylandCompositor/QWaylandSurfaceRole> + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +QT_BEGIN_NAMESPACE + +class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandIviSurfacePrivate + : public QWaylandCompositorExtensionPrivate + , public QtWaylandServer::ivi_surface +{ + Q_DECLARE_PUBLIC(QWaylandIviSurface) + +public: + QWaylandIviSurfacePrivate(); + static QWaylandIviSurfacePrivate *get(QWaylandIviSurface *iviSurface) { return iviSurface->d_func(); } + +protected: + void ivi_surface_destroy_resource(Resource *resource) Q_DECL_OVERRIDE; + void ivi_surface_destroy(Resource *resource) Q_DECL_OVERRIDE; + +private: + QWaylandIviApplication *m_iviApplication; + QWaylandSurface *m_surface; + uint m_iviId; + + static QWaylandSurfaceRole s_role; +}; + +QT_END_NAMESPACE + +#endif // QWAYLANDIVISURFACE_P_H diff --git a/src/compositor/extensions/qwaylandivisurfaceintegration.cpp b/src/compositor/extensions/qwaylandivisurfaceintegration.cpp new file mode 100644 index 000000000..3a3d9c1c9 --- /dev/null +++ b/src/compositor/extensions/qwaylandivisurfaceintegration.cpp @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWaylandCompositor module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwaylandivisurfaceintegration_p.h" + +#include <QtWaylandCompositor/QWaylandCompositor> +#include <QtWaylandCompositor/QWaylandIviSurface> +#include <QtWaylandCompositor/QWaylandQuickShellSurfaceItem> +#include <QtWaylandCompositor/QWaylandSeat> + +QT_BEGIN_NAMESPACE + +namespace QtWayland { + +IviSurfaceIntegration::IviSurfaceIntegration(QWaylandQuickShellSurfaceItem *item) + : QWaylandQuickShellIntegration(item) + , m_item(item) + , m_shellSurface(qobject_cast<QWaylandIviSurface *>(item->shellSurface())) +{ + m_item->setSurface(m_shellSurface->surface()); + connect(m_shellSurface, &QWaylandIviSurface::destroyed, this, &IviSurfaceIntegration::handleIviSurfaceDestroyed); +} + +void IviSurfaceIntegration::handleIviSurfaceDestroyed() +{ + m_shellSurface = nullptr; +} + +} + +QT_END_NAMESPACE diff --git a/src/compositor/extensions/qwaylandivisurfaceintegration_p.h b/src/compositor/extensions/qwaylandivisurfaceintegration_p.h new file mode 100644 index 000000000..534caf642 --- /dev/null +++ b/src/compositor/extensions/qwaylandivisurfaceintegration_p.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWaylandCompositor module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDIVISURFACEINTEGRATION_H +#define QWAYLANDIVISURFACEINTEGRATION_H + +#include <QtWaylandCompositor/private/qwaylandquickshellsurfaceitem_p.h> + +#include <QtWaylandCompositor/QWaylandIviSurface> + +QT_BEGIN_NAMESPACE + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +namespace QtWayland { + +class IviSurfaceIntegration : public QWaylandQuickShellIntegration +{ + Q_OBJECT +public: + IviSurfaceIntegration(QWaylandQuickShellSurfaceItem *item); + +private Q_SLOTS: + void handleIviSurfaceDestroyed(); + +private: + QWaylandQuickShellSurfaceItem *m_item; + QWaylandIviSurface *m_shellSurface; +}; + +} + +QT_END_NAMESPACE + +#endif // QWAYLANDIVISURFACEINTEGRATION_H diff --git a/src/compositor/extensions/qwaylandwindowmanagerextension.cpp b/src/compositor/extensions/qwaylandqtwindowmanager.cpp index 1e7ed2892..f82a8e46f 100644 --- a/src/compositor/extensions/qwaylandwindowmanagerextension.cpp +++ b/src/compositor/extensions/qwaylandqtwindowmanager.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2016 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtWaylandCompositor module of the Qt Toolkit. @@ -34,115 +35,116 @@ ** ****************************************************************************/ -#include "qwaylandwindowmanagerextension.h" -#include "qwaylandwindowmanagerextension_p.h" +#include <QtCore/QObject> +#include <QtCore/QUrl> #include <QtWaylandCompositor/QWaylandCompositor> #include <QtWaylandCompositor/QWaylandClient> -#include <QtCore/QUrl> +#include "qwaylandqtwindowmanager.h" +#include "qwaylandqtwindowmanager_p.h" QT_BEGIN_NAMESPACE -QWaylandWindowManagerExtension::QWaylandWindowManagerExtension() - : QWaylandCompositorExtensionTemplate<QWaylandWindowManagerExtension>(*new QWaylandWindowManagerExtensionPrivate) +QWaylandQtWindowManagerPrivate::QWaylandQtWindowManagerPrivate() + : QWaylandCompositorExtensionPrivate() + , qt_windowmanager() + , showIsFullScreen(false) { } -QWaylandWindowManagerExtension::QWaylandWindowManagerExtension(QWaylandCompositor *compositor) - : QWaylandCompositorExtensionTemplate<QWaylandWindowManagerExtension>(compositor, *new QWaylandWindowManagerExtensionPrivate) +void QWaylandQtWindowManagerPrivate::windowmanager_bind_resource(Resource *resource) { + send_hints(resource->handle, static_cast<int32_t>(showIsFullScreen)); } -QWaylandWindowManagerExtensionPrivate::QWaylandWindowManagerExtensionPrivate() - : QWaylandCompositorExtensionPrivate() - , QtWaylandServer::qt_windowmanager() - , showIsFullScreen(false) +void QWaylandQtWindowManagerPrivate::windowmanager_destroy_resource(Resource *resource) +{ + urls.remove(resource); +} + +void QWaylandQtWindowManagerPrivate::windowmanager_open_url(Resource *resource, uint32_t remaining, const QString &newUrl) +{ + Q_Q(QWaylandQtWindowManager); + + QWaylandCompositor *compositor = static_cast<QWaylandCompositor *>(q->extensionContainer()); + if (!compositor) { + qWarning() << "Failed to find QWaylandCompositor from QWaylandQtWindowManager::windowmanager_open_url()"; + return; + } + + QString url = urls.value(resource, QString()); + + url.append(newUrl); + + if (remaining) + urls.insert(resource, url); + else { + urls.remove(resource); + q->openUrl(QWaylandClient::fromWlClient(compositor, resource->client()), QUrl(url)); + } +} + +QWaylandQtWindowManager::QWaylandQtWindowManager() + : QWaylandCompositorExtensionTemplate<QWaylandQtWindowManager>(*new QWaylandQtWindowManagerPrivate()) { } -bool QWaylandWindowManagerExtension::showIsFullScreen() const +QWaylandQtWindowManager::QWaylandQtWindowManager(QWaylandCompositor *compositor) + : QWaylandCompositorExtensionTemplate<QWaylandQtWindowManager>(compositor, *new QWaylandQtWindowManagerPrivate()) { - Q_D(const QWaylandWindowManagerExtension); +} + +bool QWaylandQtWindowManager::showIsFullScreen() const +{ + Q_D(const QWaylandQtWindowManager); return d->showIsFullScreen; } -void QWaylandWindowManagerExtension::setShowIsFullScreen(bool value) +void QWaylandQtWindowManager::setShowIsFullScreen(bool value) { - Q_D(QWaylandWindowManagerExtension); + Q_D(QWaylandQtWindowManager); if (d->showIsFullScreen == value) return; d->showIsFullScreen = value; - Q_FOREACH (QWaylandWindowManagerExtensionPrivate::Resource *resource, d->resourceMap().values()) { + Q_FOREACH (QWaylandQtWindowManagerPrivate::Resource *resource, d->resourceMap().values()) { d->send_hints(resource->handle, static_cast<int32_t>(d->showIsFullScreen)); } Q_EMIT showIsFullScreenChanged(); } -void QWaylandWindowManagerExtension::sendQuitMessage(wl_client *client) +void QWaylandQtWindowManager::sendQuitMessage(QWaylandClient *client) { - Q_D(QWaylandWindowManagerExtension); - QWaylandWindowManagerExtensionPrivate::Resource *resource = d->resourceMap().value(client); + Q_D(QWaylandQtWindowManager); + QWaylandQtWindowManagerPrivate::Resource *resource = d->resourceMap().value(client->client()); if (resource) d->send_quit(resource->handle); } -void QWaylandWindowManagerExtension::initialize() +void QWaylandQtWindowManager::initialize() { - Q_D(QWaylandWindowManagerExtension); + Q_D(QWaylandQtWindowManager); QWaylandCompositorExtensionTemplate::initialize(); QWaylandCompositor *compositor = static_cast<QWaylandCompositor *>(extensionContainer()); if (!compositor) { - qWarning() << "Failed to find QWaylandCompositor when initializing QWaylandWindowManagerExtension"; + qWarning() << "Failed to find QWaylandCompositor when initializing QWaylandQtWindowManager"; return; } d->init(compositor->display(), 1); } -void QWaylandWindowManagerExtensionPrivate::windowmanager_bind_resource(Resource *resource) -{ - send_hints(resource->handle, static_cast<int32_t>(showIsFullScreen)); -} - -void QWaylandWindowManagerExtensionPrivate::windowmanager_destroy_resource(Resource *resource) -{ - urls.remove(resource); -} - -void QWaylandWindowManagerExtensionPrivate::windowmanager_open_url(Resource *resource, uint32_t remaining, const QString &newUrl) -{ - Q_Q(QWaylandWindowManagerExtension); - - QWaylandCompositor *compositor = static_cast<QWaylandCompositor *>(q->extensionContainer()); - if (!compositor) { - qWarning() << "Failed to find QWaylandCompositor from QWaylandWindowManagerExtension::windowmanager_open_url()"; - return; - } - - QString url = urls.value(resource, QString()); - - url.append(newUrl); - - if (remaining) - urls.insert(resource, url); - else { - urls.remove(resource); - q->openUrl(QWaylandClient::fromWlClient(compositor, resource->client()), QUrl(url)); - } -} - -const struct wl_interface *QWaylandWindowManagerExtension::interface() +const struct wl_interface *QWaylandQtWindowManager::interface() { - return QWaylandWindowManagerExtensionPrivate::interface(); + return QWaylandQtWindowManagerPrivate::interface(); } -QByteArray QWaylandWindowManagerExtension::interfaceName() +QByteArray QWaylandQtWindowManager::interfaceName() { - return QWaylandWindowManagerExtensionPrivate::interfaceName(); + return QWaylandQtWindowManagerPrivate::interfaceName(); } QT_END_NAMESPACE diff --git a/src/compositor/extensions/qwaylandwindowmanagerextension.h b/src/compositor/extensions/qwaylandqtwindowmanager.h index 184bcc3c5..4d3951025 100644 --- a/src/compositor/extensions/qwaylandwindowmanagerextension.h +++ b/src/compositor/extensions/qwaylandqtwindowmanager.h @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2016 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtWaylandCompositor module of the Qt Toolkit. @@ -34,8 +35,8 @@ ** ****************************************************************************/ -#ifndef WAYLANDWINDOWMANAGERINTEGRATION_H -#define WAYLANDWINDOWMANAGERINTEGRATION_H +#ifndef QWAYLANDQTWINDOWMANAGER_H +#define QWAYLANDQTWINDOWMANAGER_H #include <QtWaylandCompositor/QWaylandCompositorExtension> #include <QtWaylandCompositor/QWaylandClient> @@ -44,23 +45,21 @@ QT_BEGIN_NAMESPACE -class QWaylandCompositor; +class QWaylandQtWindowManagerPrivate; -class QWaylandWindowManagerExtensionPrivate; - -class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandWindowManagerExtension : public QWaylandCompositorExtensionTemplate<QWaylandWindowManagerExtension> +class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandQtWindowManager : public QWaylandCompositorExtensionTemplate<QWaylandQtWindowManager> { Q_OBJECT + Q_DECLARE_PRIVATE(QWaylandQtWindowManager) Q_PROPERTY(bool showIsFullScreen READ showIsFullScreen WRITE setShowIsFullScreen NOTIFY showIsFullScreenChanged) - Q_DECLARE_PRIVATE(QWaylandWindowManagerExtension) public: - QWaylandWindowManagerExtension(); - explicit QWaylandWindowManagerExtension(QWaylandCompositor *compositor); + QWaylandQtWindowManager(); + explicit QWaylandQtWindowManager(QWaylandCompositor *compositor); bool showIsFullScreen() const; void setShowIsFullScreen(bool value); - void sendQuitMessage(wl_client *client); + void sendQuitMessage(QWaylandClient *client); void initialize() Q_DECL_OVERRIDE; @@ -74,4 +73,4 @@ Q_SIGNALS: QT_END_NAMESPACE -#endif // WAYLANDWINDOWMANAGERINTEGRATION_H +#endif // QWAYLANDQTWINDOWMANAGER_H diff --git a/src/compositor/extensions/qwaylandwindowmanagerextension_p.h b/src/compositor/extensions/qwaylandqtwindowmanager_p.h index 9573855d5..a6df2138f 100644 --- a/src/compositor/extensions/qwaylandwindowmanagerextension_p.h +++ b/src/compositor/extensions/qwaylandqtwindowmanager_p.h @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2016 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtWaylandCompositor module of the Qt Toolkit. @@ -34,8 +35,14 @@ ** ****************************************************************************/ -#ifndef QWAYLANDWINDOWMANAGEREXTENSION_P_H -#define QWAYLANDWINDOWMANAGEREXTENSION_P_H +#ifndef QWAYLANDQTWINDOWMANAGER_P_H +#define QWAYLANDQTWINDOWMANAGER_P_H + +#include <QtCore/QMap> + +#include <QtWaylandCompositor/QWaylandQtWindowManager> +#include <QtWaylandCompositor/private/qwaylandcompositorextension_p.h> +#include <QtWaylandCompositor/private/qwayland-server-qt-windowmanager.h> // // W A R N I N G @@ -48,21 +55,15 @@ // We mean it. // -#include <QtWaylandCompositor/private/qwaylandcompositorextension_p.h> - -#include <QtWaylandCompositor/private/qwayland-server-windowmanager.h> - -#include <QMap> - QT_BEGIN_NAMESPACE -class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandWindowManagerExtensionPrivate +class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandQtWindowManagerPrivate : public QWaylandCompositorExtensionPrivate , public QtWaylandServer::qt_windowmanager { - Q_DECLARE_PUBLIC(QWaylandWindowManagerExtension) + Q_DECLARE_PUBLIC(QWaylandQtWindowManager) public: - QWaylandWindowManagerExtensionPrivate(); + QWaylandQtWindowManagerPrivate(); protected: void windowmanager_bind_resource(Resource *resource) Q_DECL_OVERRIDE; @@ -76,4 +77,4 @@ private: QT_END_NAMESPACE -#endif /*QWAYLANDWINDOWMANAGEREXTENSION_P_H*/ +#endif // QWAYLANDQTWINDOWMANAGER_P_H diff --git a/src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp b/src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp index 9cb65fbef..f6a88e434 100644 --- a/src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp +++ b/src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp @@ -45,7 +45,7 @@ QT_BEGIN_NAMESPACE /*! * \qmltype ShellSurfaceItem * \inqmlmodule QtWayland.Compositor - * \preliminary + * \since 5.8 * \brief A Qt Quick item type representing a WlShellSurface. * * This type is used to render \c wl_shell or \c xdg_shell surfaces as part of a Qt Quick @@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE /*! * \class QWaylandQuickShellSurfaceItem * \inmodule QtWaylandCompositor - * \preliminary + * \since 5.8 * \brief The QWaylandQuickShellSurfaceItem class provides a Qt Quick item that represents a QWaylandShellSurface. * * This class is used to render \c wl_shell or \c xdg_shell surfaces as part of a Qt Quick diff --git a/src/compositor/extensions/qwaylandquickshellsurfaceitem.h b/src/compositor/extensions/qwaylandquickshellsurfaceitem.h index e233c99e5..f72b970c2 100644 --- a/src/compositor/extensions/qwaylandquickshellsurfaceitem.h +++ b/src/compositor/extensions/qwaylandquickshellsurfaceitem.h @@ -51,8 +51,6 @@ class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandQuickShellSurfaceItem : public QWaylan Q_DECLARE_PRIVATE(QWaylandQuickShellSurfaceItem) Q_PROPERTY(QWaylandShellSurface *shellSurface READ shellSurface WRITE setShellSurface NOTIFY shellSurfaceChanged) Q_PROPERTY(QQuickItem *moveItem READ moveItem WRITE setMoveItem NOTIFY moveItemChanged) - - QWaylandQuickShellSurfaceItem(QWaylandQuickShellSurfaceItemPrivate &dd, QQuickItem *parent); public: QWaylandQuickShellSurfaceItem(QQuickItem *parent = nullptr); @@ -67,6 +65,8 @@ Q_SIGNALS: void moveItemChanged(); protected: + QWaylandQuickShellSurfaceItem(QWaylandQuickShellSurfaceItemPrivate &dd, QQuickItem *parent); + void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE; void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE; }; diff --git a/src/compositor/extensions/qwaylandquickshellsurfaceitem_p.h b/src/compositor/extensions/qwaylandquickshellsurfaceitem_p.h index c39a1cd08..3cd9bf228 100644 --- a/src/compositor/extensions/qwaylandquickshellsurfaceitem_p.h +++ b/src/compositor/extensions/qwaylandquickshellsurfaceitem_p.h @@ -40,6 +40,8 @@ #include <QtWaylandCompositor/private/qwaylandquickitem_p.h> #include <QtCore/QBasicTimer> +#include <functional> + QT_BEGIN_NAMESPACE // @@ -83,7 +85,7 @@ class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandQuickShellEventFilter : public QObject { Q_OBJECT public: - typedef void (*CallbackFunction)(void); + typedef std::function<void()> CallbackFunction; static void startFilter(QWaylandClient *client, CallbackFunction closePopupCallback); static void cancelFilter(); diff --git a/src/compositor/extensions/qwaylandshell.cpp b/src/compositor/extensions/qwaylandshell.cpp new file mode 100644 index 000000000..7811a1c2a --- /dev/null +++ b/src/compositor/extensions/qwaylandshell.cpp @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWaylandCompositor module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwaylandshell.h" +#include "qwaylandshell_p.h" + +QT_BEGIN_NAMESPACE + +QWaylandShellPrivate::QWaylandShellPrivate() + : focusPolicy(QWaylandShell::AutomaticFocus) +{ +} + +QWaylandShell::QWaylandShell() + : QWaylandCompositorExtension() +{ +} + +QWaylandShell::QWaylandShell(QWaylandObject *waylandObject) + : QWaylandCompositorExtension(waylandObject, *new QWaylandShellPrivate()) +{ +} + +/*! + * \qmlproperty enum QtWaylandCompositor::Shell::focusPolicy + * + * This property holds the focus policy of the Shell. + */ + +/*! + * \enum QWaylandShell::FocusPolicy + * + * This enum type is used to specify the focus policy for shell surfaces. + * + * \value AutomaticFocus Shell surfaces will automatically get keyboard focus when they are created. + * \value ManualFocus The compositor will decide whether shell surfaces should get keyboard focus or not. + */ + +/*! + * \qmlproperty object QtWaylandCompositor::Shell::focusPolicy + * + * This property holds the focus policy of the Shell. + */ + +/*! + * \property QWaylandShell::focusPolicy + * + * This property holds the focus policy of the QWaylandShell. + */ +QWaylandShell::FocusPolicy QWaylandShell::focusPolicy() const +{ + Q_D(const QWaylandShell); + return d->focusPolicy; +} + +void QWaylandShell::setFocusPolicy(QWaylandShell::FocusPolicy focusPolicy) +{ + Q_D(QWaylandShell); + + if (d->focusPolicy == focusPolicy) + return; + + d->focusPolicy = focusPolicy; + emit focusPolicyChanged(); +} + +QT_END_NAMESPACE diff --git a/src/compositor/extensions/qwaylandshell.h b/src/compositor/extensions/qwaylandshell.h new file mode 100644 index 000000000..997573c95 --- /dev/null +++ b/src/compositor/extensions/qwaylandshell.h @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWaylandCompositor module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDSHELL_H +#define QWAYLANDSHELL_H + +#include <QtWaylandCompositor/QWaylandCompositorExtension> + +QT_BEGIN_NAMESPACE + +class QWaylandShellPrivate; + +class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandShell : public QWaylandCompositorExtension +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QWaylandShell) + Q_PROPERTY(FocusPolicy focusPolicy READ focusPolicy WRITE setFocusPolicy NOTIFY focusPolicyChanged) +public: + enum FocusPolicy { + AutomaticFocus, + ManualFocus + }; + Q_ENUM(FocusPolicy) + + QWaylandShell(); + QWaylandShell(QWaylandObject *waylandObject); + + FocusPolicy focusPolicy() const; + void setFocusPolicy(FocusPolicy focusPolicy); + +Q_SIGNALS: + void focusPolicyChanged(); + +protected: + QWaylandShell(QWaylandCompositorExtensionPrivate &dd) : QWaylandCompositorExtension(dd) {} + QWaylandShell(QWaylandObject *container, QWaylandCompositorExtensionPrivate &dd) : QWaylandCompositorExtension(container, dd) {} +}; + +template <typename T> +class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandShellTemplate : public QWaylandShell +{ +public: + QWaylandShellTemplate() + : QWaylandShell() + { } + + QWaylandShellTemplate(QWaylandObject *container) + : QWaylandShell(container) + { } + + const struct wl_interface *extensionInterface() const Q_DECL_OVERRIDE + { + return T::interface(); + } + + static T *findIn(QWaylandObject *container) + { + if (!container) return nullptr; + return qobject_cast<T *>(container->extension(T::interfaceName())); + } + +protected: + QWaylandShellTemplate(QWaylandCompositorExtensionPrivate &dd) + : QWaylandShell(dd) + { } + + QWaylandShellTemplate(QWaylandObject *container, QWaylandCompositorExtensionPrivate &dd) + : QWaylandShell(container,dd) + { } +}; + +QT_END_NAMESPACE + +#endif // QWAYLANDSHELL_H diff --git a/src/compositor/extensions/qwaylandshell_p.h b/src/compositor/extensions/qwaylandshell_p.h new file mode 100644 index 000000000..7f849c76d --- /dev/null +++ b/src/compositor/extensions/qwaylandshell_p.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWaylandCompositor module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDSHELL_P_H +#define QWAYLANDSHELL_P_H + +#include <QtWaylandCompositor/private/qwaylandcompositorextension_p.h> +#include <QtWaylandCompositor/QWaylandShell> + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +QT_BEGIN_NAMESPACE + +class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandShellPrivate : public QWaylandCompositorExtensionPrivate +{ + Q_DECLARE_PUBLIC(QWaylandShell) +public: + QWaylandShellPrivate(); + + QWaylandShell::FocusPolicy focusPolicy; +}; + +QT_END_NAMESPACE + +#endif // QWAYLANDSHELL_P_H diff --git a/src/compositor/extensions/qwaylandshellsurface.h b/src/compositor/extensions/qwaylandshellsurface.h index 1e9fcb5ab..e8c75327c 100644 --- a/src/compositor/extensions/qwaylandshellsurface.h +++ b/src/compositor/extensions/qwaylandshellsurface.h @@ -49,13 +49,20 @@ class QWaylandShellSurfaceTemplatePrivate; class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandShellSurface : public QWaylandCompositorExtension { Q_OBJECT + Q_PROPERTY(Qt::WindowType windowType READ windowType NOTIFY windowTypeChanged) public: +#ifdef QT_WAYLAND_COMPOSITOR_QUICK virtual QWaylandQuickShellIntegration *createIntegration(QWaylandQuickShellSurfaceItem *item) = 0; +#endif QWaylandShellSurface(QWaylandObject *waylandObject) : QWaylandCompositorExtension(waylandObject) {} + virtual Qt::WindowType windowType() const { return Qt::WindowType::Window; } protected: QWaylandShellSurface(QWaylandCompositorExtensionPrivate &dd) : QWaylandCompositorExtension(dd){} QWaylandShellSurface(QWaylandObject *container, QWaylandCompositorExtensionPrivate &dd) : QWaylandCompositorExtension(container, dd) {} + +Q_SIGNALS: + void windowTypeChanged(); }; template <typename T> diff --git a/src/compositor/extensions/qwaylandtextinput.cpp b/src/compositor/extensions/qwaylandtextinput.cpp index 973308f2f..14dafaab0 100644 --- a/src/compositor/extensions/qwaylandtextinput.cpp +++ b/src/compositor/extensions/qwaylandtextinput.cpp @@ -38,7 +38,7 @@ #include "qwaylandtextinput_p.h" #include <QtWaylandCompositor/QWaylandCompositor> -#include <QtWaylandCompositor/private/qwaylandinput_p.h> +#include <QtWaylandCompositor/private/qwaylandseat_p.h> #include "qwaylandsurface.h" #include "qwaylandview.h" diff --git a/src/compositor/extensions/qwaylandtextinputmanager.cpp b/src/compositor/extensions/qwaylandtextinputmanager.cpp index 9dd7ace8f..7be00b6dd 100644 --- a/src/compositor/extensions/qwaylandtextinputmanager.cpp +++ b/src/compositor/extensions/qwaylandtextinputmanager.cpp @@ -38,7 +38,7 @@ #include "qwaylandtextinputmanager_p.h" #include <QtWaylandCompositor/QWaylandCompositor> -#include <QtWaylandCompositor/QWaylandInputDevice> +#include <QtWaylandCompositor/QWaylandSeat> #include "qwaylandtextinput.h" @@ -50,14 +50,14 @@ QWaylandTextInputManagerPrivate::QWaylandTextInputManagerPrivate() { } -void QWaylandTextInputManagerPrivate::zwp_text_input_manager_v2_get_text_input(Resource *resource, uint32_t id, struct ::wl_resource *seat) +void QWaylandTextInputManagerPrivate::zwp_text_input_manager_v2_get_text_input(Resource *resource, uint32_t id, struct ::wl_resource *seatResource) { Q_Q(QWaylandTextInputManager); QWaylandCompositor *compositor = static_cast<QWaylandCompositor *>(q->extensionContainer()); - QWaylandInputDevice *inputDevice = QWaylandInputDevice::fromSeatResource(seat); - QWaylandTextInput *textInput = QWaylandTextInput::findIn(inputDevice); + QWaylandSeat *seat = QWaylandSeat::fromSeatResource(seatResource); + QWaylandTextInput *textInput = QWaylandTextInput::findIn(seat); if (!textInput) { - textInput = new QWaylandTextInput(inputDevice, compositor); + textInput = new QWaylandTextInput(seat, compositor); } textInput->add(resource->client(), id, wl_resource_get_version(resource->handle)); } diff --git a/src/compositor/extensions/qwaylandtextinputmanager_p.h b/src/compositor/extensions/qwaylandtextinputmanager_p.h index 4af717096..955a5cc8a 100644 --- a/src/compositor/extensions/qwaylandtextinputmanager_p.h +++ b/src/compositor/extensions/qwaylandtextinputmanager_p.h @@ -61,7 +61,7 @@ public: QWaylandTextInputManagerPrivate(); protected: - void zwp_text_input_manager_v2_get_text_input(Resource *resource, uint32_t id, struct ::wl_resource *seat) Q_DECL_OVERRIDE; + void zwp_text_input_manager_v2_get_text_input(Resource *resource, uint32_t id, struct ::wl_resource *seatResource) Q_DECL_OVERRIDE; }; QT_END_NAMESPACE diff --git a/src/compositor/extensions/qwaylandwlshell.cpp b/src/compositor/extensions/qwaylandwlshell.cpp index c79ddac7c..3145c6646 100644 --- a/src/compositor/extensions/qwaylandwlshell.cpp +++ b/src/compositor/extensions/qwaylandwlshell.cpp @@ -38,7 +38,9 @@ #include "qwaylandwlshell.h" #include "qwaylandwlshell_p.h" +#ifdef QT_WAYLAND_COMPOSITOR_QUICK #include "qwaylandwlshellintegration_p.h" +#endif #include <QtWaylandCompositor/QWaylandCompositor> #include <QtWaylandCompositor/QWaylandView> @@ -77,16 +79,23 @@ void QWaylandWlShellPrivate::shell_get_shell_surface(Resource *resource, uint32_ if (!surface->setRole(QWaylandWlShellSurface::role(), displayRes, WL_DISPLAY_ERROR_INVALID_OBJECT)) return; - emit q->createShellSurface(surface, shellSurfaceResource); + emit q->wlShellSurfaceRequested(surface, shellSurfaceResource); QWaylandWlShellSurface *shellSurface = QWaylandWlShellSurface::fromResource(shellSurfaceResource.resource()); if (!shellSurface) { - // A QWaylandShellSurface was not created in response to the createShellSurface signal - // we create one as fallback here instead. + // A QWaylandWlShellSurface was not created in response to the wlShellSurfaceRequested + // signal, so we create one as fallback here instead. shellSurface = new QWaylandWlShellSurface(q, surface, shellSurfaceResource); } - emit q->shellSurfaceCreated(shellSurface); + m_shellSurfaces.append(shellSurface); + emit q->wlShellSurfaceCreated(shellSurface); +} + +void QWaylandWlShellPrivate::unregisterShellSurface(QWaylandWlShellSurface *shellSurface) +{ + if (!m_shellSurfaces.removeOne(shellSurface)) + qWarning("Unexpected state. Can't find registered shell surface."); } QWaylandWlShellSurfacePrivate::QWaylandWlShellSurfacePrivate() @@ -94,7 +103,7 @@ QWaylandWlShellSurfacePrivate::QWaylandWlShellSurfacePrivate() , wl_shell_surface() , m_shell(Q_NULLPTR) , m_surface(Q_NULLPTR) - , m_focusPolicy(QWaylandWlShellSurface::DefaultFocus) + , m_windowType(Qt::WindowType::Window) { } @@ -108,6 +117,16 @@ void QWaylandWlShellSurfacePrivate::ping(uint32_t serial) send_ping(serial); } +void QWaylandWlShellSurfacePrivate::setWindowType(Qt::WindowType windowType) +{ + if (m_windowType == windowType) + return; + m_windowType = windowType; + + Q_Q(QWaylandWlShellSurface); + emit q->windowTypeChanged(); +} + void QWaylandWlShellSurfacePrivate::shell_surface_destroy_resource(Resource *) { Q_Q(QWaylandWlShellSurface); @@ -123,7 +142,7 @@ void QWaylandWlShellSurfacePrivate::shell_surface_move(Resource *resource, Q_UNUSED(serial); Q_Q(QWaylandWlShellSurface); - QWaylandInputDevice *input_device = QWaylandInputDevice::fromSeatResource(input_device_super); + QWaylandSeat *input_device = QWaylandSeat::fromSeatResource(input_device_super); emit q->startMove(input_device); } @@ -136,7 +155,7 @@ void QWaylandWlShellSurfacePrivate::shell_surface_resize(Resource *resource, Q_UNUSED(serial); Q_Q(QWaylandWlShellSurface); - QWaylandInputDevice *input_device = QWaylandInputDevice::fromSeatResource(input_device_super); + QWaylandSeat *input_device = QWaylandSeat::fromSeatResource(input_device_super); emit q->startResize(input_device, QWaylandWlShellSurface::ResizeEdge(edges)); } @@ -144,7 +163,7 @@ void QWaylandWlShellSurfacePrivate::shell_surface_set_toplevel(Resource *resourc { Q_UNUSED(resource); Q_Q(QWaylandWlShellSurface); - setFocusPolicy(QWaylandWlShellSurface::DefaultFocus); + setWindowType(Qt::WindowType::Window); emit q->setDefaultToplevel(); } @@ -158,11 +177,8 @@ void QWaylandWlShellSurfacePrivate::shell_surface_set_transient(Resource *resour Q_UNUSED(resource); Q_Q(QWaylandWlShellSurface); QWaylandSurface *parent_surface = QWaylandSurface::fromResource(parent_surface_resource); - QWaylandWlShellSurface::FocusPolicy focusPolicy = - flags & WL_SHELL_SURFACE_TRANSIENT_INACTIVE ? QWaylandWlShellSurface::NoKeyboardFocus - : QWaylandWlShellSurface::DefaultFocus; - setFocusPolicy(focusPolicy); - emit q->setTransient(parent_surface, QPoint(x,y), focusPolicy); + setWindowType(Qt::WindowType::SubWindow); + emit q->setTransient(parent_surface, QPoint(x,y), flags & WL_SHELL_SURFACE_TRANSIENT_INACTIVE); } void QWaylandWlShellSurfacePrivate::shell_surface_set_fullscreen(Resource *resource, @@ -174,10 +190,10 @@ void QWaylandWlShellSurfacePrivate::shell_surface_set_fullscreen(Resource *resou Q_UNUSED(method); Q_UNUSED(framerate); Q_Q(QWaylandWlShellSurface); - setFocusPolicy(QWaylandWlShellSurface::DefaultFocus); QWaylandOutput *output = output_resource ? QWaylandOutput::fromResource(output_resource) : Q_NULLPTR; + setWindowType(Qt::WindowType::Window); emit q->setFullScreen(QWaylandWlShellSurface::FullScreenMethod(method), framerate, output); } @@ -187,9 +203,9 @@ void QWaylandWlShellSurfacePrivate::shell_surface_set_popup(Resource *resource, Q_UNUSED(serial); Q_UNUSED(flags); Q_Q(QWaylandWlShellSurface); - setFocusPolicy(QWaylandWlShellSurface::DefaultFocus); - QWaylandInputDevice *input = QWaylandInputDevice::fromSeatResource(input_device); + QWaylandSeat *input = QWaylandSeat::fromSeatResource(input_device); QWaylandSurface *parentSurface = QWaylandSurface::fromResource(parent); + setWindowType(Qt::WindowType::Popup); emit q->setPopup(input, parentSurface, QPoint(x,y)); } @@ -199,10 +215,10 @@ void QWaylandWlShellSurfacePrivate::shell_surface_set_maximized(Resource *resour { Q_UNUSED(resource); Q_Q(QWaylandWlShellSurface); - setFocusPolicy(QWaylandWlShellSurface::DefaultFocus); QWaylandOutput *output = output_resource ? QWaylandOutput::fromResource(output_resource) : Q_NULLPTR; + setWindowType(Qt::WindowType::Window); emit q->setMaximized(output); } @@ -242,7 +258,7 @@ void QWaylandWlShellSurfacePrivate::shell_surface_set_class(Resource *resource, /*! * \qmltype WlShell * \inqmlmodule QtWayland.Compositor - * \preliminary + * \since 5.8 * \brief Provides an extension for desktop-style user interfaces. * * The WlShell extension provides a way to assiociate a ShellSurface @@ -268,7 +284,7 @@ void QWaylandWlShellSurfacePrivate::shell_surface_set_class(Resource *resource, /*! * \class QWaylandWlShell * \inmodule QtWaylandCompositor - * \preliminary + * \since 5.8 * \brief The QWaylandWlShell class is an extension for desktop-style user interfaces. * * The QWaylandWlShell extension provides a way to assiociate a QWaylandWlShellSurface with @@ -282,14 +298,14 @@ void QWaylandWlShellSurfacePrivate::shell_surface_set_class(Resource *resource, * Constructs a QWaylandWlShell object. */ QWaylandWlShell::QWaylandWlShell() - : QWaylandCompositorExtensionTemplate<QWaylandWlShell>(*new QWaylandWlShellPrivate()) + : QWaylandShellTemplate<QWaylandWlShell>(*new QWaylandWlShellPrivate()) { } /*! * Constructs a QWaylandWlShell object for the provided \a compositor. */ QWaylandWlShell::QWaylandWlShell(QWaylandCompositor *compositor) - : QWaylandCompositorExtensionTemplate<QWaylandWlShell>(compositor, *new QWaylandWlShellPrivate()) + : QWaylandShellTemplate<QWaylandWlShell>(compositor, *new QWaylandWlShellPrivate()) { } @@ -299,8 +315,8 @@ QWaylandWlShell::QWaylandWlShell(QWaylandCompositor *compositor) void QWaylandWlShell::initialize() { Q_D(QWaylandWlShell); - QWaylandCompositorExtensionTemplate::initialize(); - QWaylandCompositor *compositor = static_cast<QWaylandCompositor *>(extensionContainer()); + QWaylandShellTemplate::initialize(); + QWaylandCompositor *compositor = qobject_cast<QWaylandCompositor *>(extensionContainer()); if (!compositor) { qWarning() << "Failed to find QWaylandCompositor when initializing QWaylandWlShell"; return; @@ -308,6 +324,54 @@ void QWaylandWlShell::initialize() d->init(compositor->display(), 1); } +QList<QWaylandWlShellSurface *> QWaylandWlShell::shellSurfaces() const +{ + Q_D(const QWaylandWlShell); + return d->m_shellSurfaces; +} + +QList<QWaylandWlShellSurface *> QWaylandWlShell::shellSurfacesForClient(QWaylandClient *client) const +{ + Q_D(const QWaylandWlShell); + QList<QWaylandWlShellSurface *> surfsForClient; + Q_FOREACH (QWaylandWlShellSurface *shellSurface, d->m_shellSurfaces) { + if (shellSurface->surface()->client() == client) + surfsForClient.append(shellSurface); + } + return surfsForClient; +} + +QList<QWaylandWlShellSurface *> QWaylandWlShell::mappedPopups() const +{ + Q_D(const QWaylandWlShell); + QList<QWaylandWlShellSurface *> popupSurfaces; + Q_FOREACH (QWaylandWlShellSurface *shellSurface, d->m_shellSurfaces) { + if (shellSurface->windowType() == Qt::WindowType::Popup + && shellSurface->surface()->hasContent()) { + popupSurfaces.append(shellSurface); + } + } + return popupSurfaces; +} + +QWaylandClient *QWaylandWlShell::popupClient() const +{ + Q_D(const QWaylandWlShell); + Q_FOREACH (QWaylandWlShellSurface *shellSurface, d->m_shellSurfaces) { + if (shellSurface->windowType() == Qt::WindowType::Popup + && shellSurface->surface()->hasContent()) { + return shellSurface->surface()->client(); + } + } + return nullptr; +} + +void QWaylandWlShell::closeAllPopups() +{ + Q_FOREACH (QWaylandWlShellSurface* shellSurface, mappedPopups()) + shellSurface->sendPopupDone(); +} + /*! * Returns the Wayland interface for the QWaylandWlShell. */ @@ -317,7 +381,7 @@ const struct wl_interface *QWaylandWlShell::interface() } /*! - * \qmlsignal void QtWaylandCompositor::WlShell::createShellSurface(object surface, object client, int id) + * \qmlsignal void QtWaylandCompositor::WlShell::wlShellSurfaceRequested(object surface, object client, int id) * * This signal is emitted when the \a client has requested a \c wl_shell_surface to be associated * with \a surface, which is identified by \a id. The handler for this signal is @@ -326,7 +390,7 @@ const struct wl_interface *QWaylandWlShell::interface() */ /*! - * \fn void QWaylandWlShell::createShellSurface(QWaylandSurface *surface, const QWaylandResource &resource) + * \fn void QWaylandWlShell::wlShellSurfaceRequested(QWaylandSurface *surface, const QWaylandResource &resource) * * Constructs a QWaylandSurface, assigns it to \a surface and initializes it with the given \a resource. */ @@ -342,7 +406,7 @@ QByteArray QWaylandWlShell::interfaceName() /*! * \qmltype WlShellSurface * \inqmlmodule QtWayland.Compositor - * \preliminary + * \since 5.8 * \brief Provides a \c wl_shell_surface that offers desktop-style compositor-specific features to a surface. * * This type is part of the \l{WlShell} extension and provides a way to extend @@ -355,7 +419,7 @@ QByteArray QWaylandWlShell::interfaceName() /*! * \class QWaylandWlShellSurface * \inmodule QtWaylandCompositor - * \preliminary + * \since 5.8 * \brief The QWaylandWlShellSurface class provides desktop-style compositor-specific features to a surface. * * This class is part of the QWaylandWlShell extension and provides a way to extend @@ -382,6 +446,12 @@ QWaylandWlShellSurface::QWaylandWlShellSurface(QWaylandWlShell *shell, QWaylandS initialize(shell, surface, res); } +QWaylandWlShellSurface::~QWaylandWlShellSurface() +{ + Q_D(QWaylandWlShellSurface); + QWaylandWlShellPrivate::get(d->m_shell)->unregisterShellSurface(this); +} + /*! * \qmlmethod void QtWaylandCompositor::WlShellSurface::initialize(object shell, object surface, object client, int id) * @@ -399,6 +469,7 @@ void QWaylandWlShellSurface::initialize(QWaylandWlShell *shell, QWaylandSurface d->init(resource.resource()); setExtensionContainer(surface); emit surfaceChanged(); + emit shellChanged(); QWaylandCompositorExtension::initialize(); } @@ -493,10 +564,12 @@ void QWaylandWlShellSurface::sendPopupDone() d->send_popup_done(); } +#ifdef QT_WAYLAND_COMPOSITOR_QUICK QWaylandQuickShellIntegration *QWaylandWlShellSurface::createIntegration(QWaylandQuickShellSurfaceItem *item) { return new QtWayland::WlShellIntegration(item); } +#endif /*! * \qmlproperty object QtWaylandCompositor::WlShellSurface::surface @@ -516,29 +589,37 @@ QWaylandSurface *QWaylandWlShellSurface::surface() const } /*! - * \enum QWaylandWlShellSurface::FocusPolicy + * \qmlproperty object QtWaylandCompositor::WlShellSurface::shell * - * This enum type is used to specify the focus policy of a shell surface. + * This property holds the shell associated with this WlShellSurface. + */ + +/*! + * \property QWaylandWlShellSurface::shell * - * \value DefaultFocus The default focus policy should be used. - * \value NoKeyboardFocus The shell surface should not get keyboard focus. + * This property holds the shell associated with this QWaylandWlShellSurface. */ +QWaylandWlShell *QWaylandWlShellSurface::shell() const +{ + Q_D(const QWaylandWlShellSurface); + return d->m_shell; +} /*! - * \qmlproperty enum QtWaylandCompositor::WlShellSurface::focusPolicy + * \qmlproperty enum QtWaylandCompositor::WlShellSurface::windowType * - * This property holds the focus policy of the WlShellSurface. + * This property holds the window type of the WlShellSurface. */ /*! - * \property QWaylandWlShellSurface::focusPolicy + * \property QWaylandWlShellSurface::windowType * - * This property holds the focus policy of the QWaylandWlShellSurface. + * This property holds the window type of the QWaylandWlShellSurface. */ -QWaylandWlShellSurface::FocusPolicy QWaylandWlShellSurface::focusPolicy() const +Qt::WindowType QWaylandWlShellSurface::windowType() const { Q_D(const QWaylandWlShellSurface); - return d->m_focusPolicy; + return d->m_windowType; } /*! diff --git a/src/compositor/extensions/qwaylandwlshell.h b/src/compositor/extensions/qwaylandwlshell.h index 5bddd4f7b..7fe07e7a9 100644 --- a/src/compositor/extensions/qwaylandwlshell.h +++ b/src/compositor/extensions/qwaylandwlshell.h @@ -39,6 +39,7 @@ #include <QtWaylandCompositor/QWaylandCompositorExtension> #include <QtWaylandCompositor/QWaylandResource> +#include <QtWaylandCompositor/QWaylandShell> #include <QtWaylandCompositor/QWaylandShellSurface> #include <QtCore/QSize> @@ -49,12 +50,12 @@ class QWaylandWlShellPrivate; class QWaylandWlShellSurfacePrivate; class QWaylandSurface; class QWaylandClient; -class QWaylandInputDevice; +class QWaylandSeat; class QWaylandOutput; class QWaylandSurfaceRole; class QWaylandWlShellSurface; -class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandWlShell : public QWaylandCompositorExtensionTemplate<QWaylandWlShell> +class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandWlShell : public QWaylandShellTemplate<QWaylandWlShell> { Q_OBJECT Q_DECLARE_PRIVATE(QWaylandWlShell) @@ -63,13 +64,20 @@ public: QWaylandWlShell(QWaylandCompositor *compositor); void initialize() Q_DECL_OVERRIDE; + QList<QWaylandWlShellSurface *> shellSurfaces() const; + QList<QWaylandWlShellSurface *> shellSurfacesForClient(QWaylandClient* client) const; + QList<QWaylandWlShellSurface *> mappedPopups() const; + QWaylandClient *popupClient() const; static const struct wl_interface *interface(); static QByteArray interfaceName(); +public Q_SLOTS: + void closeAllPopups(); + Q_SIGNALS: - void createShellSurface(QWaylandSurface *surface, const QWaylandResource &resource); - void shellSurfaceCreated(QWaylandWlShellSurface *shellSurface); + void wlShellSurfaceRequested(QWaylandSurface *surface, const QWaylandResource &resource); + void wlShellSurfaceCreated(QWaylandWlShellSurface *shellSurface); }; class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandWlShellSurface : public QWaylandShellSurfaceTemplate<QWaylandWlShellSurface> @@ -77,9 +85,9 @@ class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandWlShellSurface : public QWaylandShellS Q_OBJECT Q_DECLARE_PRIVATE(QWaylandWlShellSurface) Q_PROPERTY(QWaylandSurface *surface READ surface NOTIFY surfaceChanged) + Q_PROPERTY(QWaylandWlShell *shell READ shell NOTIFY shellChanged) Q_PROPERTY(QString title READ title NOTIFY titleChanged) Q_PROPERTY(QString className READ className NOTIFY classNameChanged) - Q_PROPERTY(FocusPolicy focusPolicy READ focusPolicy NOTIFY focusPolicyChanged) public: enum FullScreenMethod { @@ -103,14 +111,9 @@ public: }; Q_ENUM(ResizeEdge); - enum FocusPolicy{ - DefaultFocus, - NoKeyboardFocus - }; - Q_ENUM(FocusPolicy) - QWaylandWlShellSurface(); QWaylandWlShellSurface(QWaylandWlShell *shell, QWaylandSurface *surface, const QWaylandResource &resource); + virtual ~QWaylandWlShellSurface(); Q_INVOKABLE void initialize(QWaylandWlShell *shell, QWaylandSurface *surface, const QWaylandResource &resource); @@ -118,8 +121,9 @@ public: QString className() const; QWaylandSurface *surface() const; + QWaylandWlShell *shell() const; - FocusPolicy focusPolicy() const; + Qt::WindowType windowType() const override; static const struct wl_interface *interface(); static QByteArray interfaceName(); @@ -131,24 +135,26 @@ public: Q_INVOKABLE void sendConfigure(const QSize &size, ResizeEdge edges); Q_INVOKABLE void sendPopupDone(); +#ifdef QT_WAYLAND_COMPOSITOR_QUICK QWaylandQuickShellIntegration *createIntegration(QWaylandQuickShellSurfaceItem *item) Q_DECL_OVERRIDE; +#endif public Q_SLOTS: void ping(); Q_SIGNALS: void surfaceChanged(); + void shellChanged(); void titleChanged(); void classNameChanged(); - void focusPolicyChanged(); void pong(); - void startMove(QWaylandInputDevice *inputDevice); - void startResize(QWaylandInputDevice *inputDevice, ResizeEdge edges); + void startMove(QWaylandSeat *seat); + void startResize(QWaylandSeat *seat, ResizeEdge edges); void setDefaultToplevel(); - void setTransient(QWaylandSurface *parentSurface, const QPoint &relativeToParent, FocusPolicy focusPolicy); + void setTransient(QWaylandSurface *parentSurface, const QPoint &relativeToParent, bool inactive); void setFullScreen(FullScreenMethod method, uint framerate, QWaylandOutput *output); - void setPopup(QWaylandInputDevice *inputDevice, QWaylandSurface *parentSurface, const QPoint &relativeToParent); + void setPopup(QWaylandSeat *seat, QWaylandSurface *parentSurface, const QPoint &relativeToParent); void setMaximized(QWaylandOutput *output); private: diff --git a/src/compositor/extensions/qwaylandwlshell_p.h b/src/compositor/extensions/qwaylandwlshell_p.h index 39ed645c1..5e8903090 100644 --- a/src/compositor/extensions/qwaylandwlshell_p.h +++ b/src/compositor/extensions/qwaylandwlshell_p.h @@ -41,7 +41,7 @@ #include <QtWaylandCompositor/qwaylandsurface.h> #include <QtWaylandCompositor/private/qwaylandcompositorextension_p.h> #include <QtWaylandCompositor/QWaylandWlShellSurface> -#include <QtWaylandCompositor/QWaylandInputDevice> +#include <QtWaylandCompositor/QWaylandSeat> #include <wayland-server.h> #include <QHash> @@ -70,10 +70,15 @@ class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandWlShellPrivate Q_DECLARE_PUBLIC(QWaylandWlShell) public: QWaylandWlShellPrivate(); + + void unregisterShellSurface(QWaylandWlShellSurface *shellSurface); + static QWaylandWlShellPrivate *get(QWaylandWlShell *shell) { return shell->d_func(); } protected: void shell_get_shell_surface(Resource *resource, uint32_t id, struct ::wl_resource *surface) Q_DECL_OVERRIDE; + + QList<QWaylandWlShellSurface *> m_shellSurfaces; }; class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandWlShellSurfacePrivate @@ -89,14 +94,8 @@ public: void ping(uint32_t serial); - void setFocusPolicy(QWaylandWlShellSurface::FocusPolicy focusPolicy) - { - if (focusPolicy == m_focusPolicy) - return; - Q_Q(QWaylandWlShellSurface); - m_focusPolicy = focusPolicy; - emit q->focusPolicyChanged(); - } + void setWindowType(Qt::WindowType windowType); + private: QWaylandWlShell *m_shell; QWaylandSurface *m_surface; @@ -105,7 +104,7 @@ private: QString m_title; QString m_className; - QWaylandWlShellSurface::FocusPolicy m_focusPolicy; + Qt::WindowType m_windowType; void shell_surface_destroy_resource(Resource *resource) Q_DECL_OVERRIDE; diff --git a/src/compositor/extensions/qwaylandwlshellintegration.cpp b/src/compositor/extensions/qwaylandwlshellintegration.cpp index a1ef5f32a..30e4704af 100644 --- a/src/compositor/extensions/qwaylandwlshellintegration.cpp +++ b/src/compositor/extensions/qwaylandwlshellintegration.cpp @@ -39,7 +39,7 @@ #include <QtWaylandCompositor/QWaylandCompositor> #include <QtWaylandCompositor/QWaylandWlShellSurface> #include <QtWaylandCompositor/QWaylandQuickShellSurfaceItem> -#include <QtWaylandCompositor/QWaylandInputDevice> +#include <QtWaylandCompositor/QWaylandSeat> QT_BEGIN_NAMESPACE @@ -51,37 +51,123 @@ WlShellIntegration::WlShellIntegration(QWaylandQuickShellSurfaceItem *item) , m_shellSurface(qobject_cast<QWaylandWlShellSurface *>(item->shellSurface())) , grabberState(GrabberState::Default) , isPopup(false) + , currentState(State::Windowed) + , nextState(State::Windowed) { m_item->setSurface(m_shellSurface->surface()); connect(m_shellSurface, &QWaylandWlShellSurface::startMove, this, &WlShellIntegration::handleStartMove); connect(m_shellSurface, &QWaylandWlShellSurface::startResize, this, &WlShellIntegration::handleStartResize); + connect(m_shellSurface->surface(), &QWaylandSurface::redraw, this, &WlShellIntegration::handleRedraw); connect(m_shellSurface->surface(), &QWaylandSurface::offsetForNextFrame, this, &WlShellIntegration::adjustOffsetForNextFrame); + connect(m_shellSurface->surface(), &QWaylandSurface::hasContentChanged, this, &WlShellIntegration::handleSurfaceHasContentChanged); + connect(m_shellSurface, &QWaylandWlShellSurface::setDefaultToplevel, this, &WlShellIntegration::handleSetDefaultTopLevel); + connect(m_shellSurface, &QWaylandWlShellSurface::setTransient, this, &WlShellIntegration::handleSetTransient); + connect(m_shellSurface, &QWaylandWlShellSurface::setMaximized, this, &WlShellIntegration::handleSetMaximized); + connect(m_shellSurface, &QWaylandWlShellSurface::setFullScreen, this, &WlShellIntegration::handleSetFullScreen); connect(m_shellSurface, &QWaylandWlShellSurface::setPopup, this, &WlShellIntegration::handleSetPopup); connect(m_shellSurface, &QWaylandWlShellSurface::destroyed, this, &WlShellIntegration::handleShellSurfaceDestroyed); } -void WlShellIntegration::handleStartMove(QWaylandInputDevice *inputDevice) +void WlShellIntegration::handleStartMove(QWaylandSeat *seat) { grabberState = GrabberState::Move; - moveState.inputDevice = inputDevice; + moveState.seat = seat; moveState.initialized = false; } -void WlShellIntegration::handleStartResize(QWaylandInputDevice *inputDevice, QWaylandWlShellSurface::ResizeEdge edges) +void WlShellIntegration::handleStartResize(QWaylandSeat *seat, QWaylandWlShellSurface::ResizeEdge edges) { grabberState = GrabberState::Resize; - resizeState.inputDevice = inputDevice; + resizeState.seat = seat; resizeState.resizeEdges = edges; float scaleFactor = m_item->view()->output()->scaleFactor(); resizeState.initialSize = m_shellSurface->surface()->size() / scaleFactor; resizeState.initialized = false; } -void WlShellIntegration::handleSetPopup(QWaylandInputDevice *inputDevice, QWaylandSurface *parent, const QPoint &relativeToParent) +void WlShellIntegration::handleSetDefaultTopLevel() { - Q_UNUSED(inputDevice); + // Take focus if the policy allows + if (m_shellSurface->shell()->focusPolicy() == QWaylandShell::AutomaticFocus) + m_item->takeFocus(); + + // In order to restore the window state, the client calls setDefaultToplevel() + // so we need to unset the flags here but we save the previous state and move + // to the initial position when redrawing + nextState = State::Windowed; +} + +void WlShellIntegration::handleSetTransient(QWaylandSurface *parentSurface, const QPoint &relativeToParent, bool inactive) +{ + Q_UNUSED(parentSurface) + Q_UNUSED(relativeToParent) + + // Take focus if the policy allows and it's not inactive + if (m_shellSurface->shell()->focusPolicy() == QWaylandShell::AutomaticFocus && !inactive) + m_item->takeFocus(); +} + +void WlShellIntegration::handleSetMaximized(QWaylandOutput *output) +{ + if (!m_item->view()->isPrimary()) + return; + + if (currentState == State::Maximized) + return; + + QWaylandOutput *designatedOutput = output ? output : m_item->view()->output(); + if (!designatedOutput) + return; + + if (currentState == State::Windowed) + normalPosition = m_item->moveItem()->position(); + + nextState = State::Maximized; + finalPosition = designatedOutput->position() + designatedOutput->availableGeometry().topLeft(); + + m_shellSurface->sendConfigure(designatedOutput->availableGeometry().size(), QWaylandWlShellSurface::NoneEdge); +} + +void WlShellIntegration::handleSetFullScreen(QWaylandWlShellSurface::FullScreenMethod method, uint framerate, QWaylandOutput *output) +{ + Q_UNUSED(method); + Q_UNUSED(framerate); + + if (!m_item->view()->isPrimary()) + return; + + if (currentState == State::FullScreen) + return; + + QWaylandOutput *designatedOutput = output ? output : m_item->view()->output(); + if (!designatedOutput) + return; + + if (currentState == State::Windowed) + normalPosition = m_item->moveItem()->position(); + + nextState = State::FullScreen; + finalPosition = designatedOutput->position(); + + m_shellSurface->sendConfigure(designatedOutput->geometry().size(), QWaylandWlShellSurface::NoneEdge); +} + +void WlShellIntegration::handleSetPopup(QWaylandSeat *seat, QWaylandSurface *parent, const QPoint &relativeToParent) +{ + Q_UNUSED(seat); + + // Find the parent item on the same output + QWaylandQuickShellSurfaceItem *parentItem = nullptr; + Q_FOREACH (QWaylandView *view, parent->views()) { + if (view->output() == m_item->view()->output()) { + QWaylandQuickShellSurfaceItem *item = qobject_cast<QWaylandQuickShellSurfaceItem*>(view->renderObject()); + if (item) { + parentItem = item; + break; + } + } + } - QWaylandQuickShellSurfaceItem* parentItem = qobject_cast<QWaylandQuickShellSurfaceItem*>(parent->views().first()->renderObject()); if (parentItem) { // Clear all the transforms for this ShellSurfaceItem. They are not // applicable when the item becomes a child to a surface that has its @@ -96,33 +182,29 @@ void WlShellIntegration::handleSetPopup(QWaylandInputDevice *inputDevice, QWayla } isPopup = true; - QWaylandQuickShellEventFilter::startFilter(m_shellSurface->surface()->client(), &closePopups); + QWaylandQuickShellEventFilter::startFilter(m_shellSurface->surface()->client(), [&]() { + m_shellSurface->shell()->closeAllPopups(); + }); - if (!popupShellSurfaces.contains(m_shellSurface)) { - popupShellSurfaces.append(m_shellSurface); - QObject::connect(m_shellSurface->surface(), &QWaylandSurface::mappedChanged, - this, &WlShellIntegration::handleSurfaceUnmapped); - } + QObject::connect(m_shellSurface->surface(), &QWaylandSurface::hasContentChanged, + this, &WlShellIntegration::handleSurfaceHasContentChanged); } void WlShellIntegration::handlePopupClosed() { handlePopupRemoved(); if (m_shellSurface) - QObject::disconnect(m_shellSurface->surface(), &QWaylandSurface::mappedChanged, - this, &WlShellIntegration::handleSurfaceUnmapped); + QObject::disconnect(m_shellSurface->surface(), &QWaylandSurface::hasContentChanged, + this, &WlShellIntegration::handleSurfaceHasContentChanged); } void WlShellIntegration::handlePopupRemoved() { - if (m_shellSurface) - popupShellSurfaces.removeOne(m_shellSurface); - if (popupShellSurfaces.isEmpty()) + if (m_shellSurface->shell()->mappedPopups().isEmpty()) QWaylandQuickShellEventFilter::cancelFilter(); isPopup = false; } - void WlShellIntegration::handleShellSurfaceDestroyed() { if (isPopup) @@ -130,15 +212,28 @@ void WlShellIntegration::handleShellSurfaceDestroyed() m_shellSurface = nullptr; } -void WlShellIntegration::handleSurfaceUnmapped() +void WlShellIntegration::handleSurfaceHasContentChanged() { - if (!m_shellSurface || !m_shellSurface->surface()->size().isEmpty()) + if (m_shellSurface && m_shellSurface->surface()->size().isEmpty() + && m_shellSurface->windowType() == Qt::WindowType::Popup) { + handlePopupClosed(); + } +} + +void WlShellIntegration::handleRedraw() +{ + if (currentState == nextState) return; - handlePopupClosed(); + + m_item->moveItem()->setPosition(nextState == State::Windowed ? normalPosition : finalPosition); + currentState = nextState; } void WlShellIntegration::adjustOffsetForNextFrame(const QPointF &offset) { + if (!m_item->view()->isPrimary()) + return; + float scaleFactor = m_item->view()->output()->scaleFactor(); QQuickItem *moveItem = m_item->moveItem(); moveItem->setPosition(moveItem->position() + offset * scaleFactor); @@ -147,7 +242,7 @@ void WlShellIntegration::adjustOffsetForNextFrame(const QPointF &offset) bool WlShellIntegration::mouseMoveEvent(QMouseEvent *event) { if (grabberState == GrabberState::Resize) { - Q_ASSERT(resizeState.inputDevice == m_item->compositor()->inputDeviceFor(event)); + Q_ASSERT(resizeState.seat == m_item->compositor()->seatFor(event)); if (!resizeState.initialized) { resizeState.initialMousePos = event->windowPos(); resizeState.initialized = true; @@ -158,7 +253,7 @@ bool WlShellIntegration::mouseMoveEvent(QMouseEvent *event) QSize newSize = m_shellSurface->sizeForResize(resizeState.initialSize, delta, resizeState.resizeEdges); m_shellSurface->sendConfigure(newSize, resizeState.resizeEdges); } else if (grabberState == GrabberState::Move) { - Q_ASSERT(moveState.inputDevice == m_item->compositor()->inputDeviceFor(event)); + Q_ASSERT(moveState.seat == m_item->compositor()->seatFor(event)); QQuickItem *moveItem = m_item->moveItem(); if (!moveState.initialized) { moveState.initialOffset = moveItem->mapFromItem(nullptr, event->windowPos()); @@ -183,18 +278,6 @@ bool WlShellIntegration::mouseReleaseEvent(QMouseEvent *event) return false; } -QVector<QWaylandWlShellSurface*> WlShellIntegration::popupShellSurfaces; - -void WlShellIntegration::closePopups() -{ - if (!popupShellSurfaces.isEmpty()) { - Q_FOREACH (QWaylandWlShellSurface* shellSurface, popupShellSurfaces) { - shellSurface->sendPopupDone(); - } - popupShellSurfaces.clear(); - } -} - } QT_END_NAMESPACE diff --git a/src/compositor/extensions/qwaylandwlshellintegration_p.h b/src/compositor/extensions/qwaylandwlshellintegration_p.h index 3f063af39..bbdfbd733 100644 --- a/src/compositor/extensions/qwaylandwlshellintegration_p.h +++ b/src/compositor/extensions/qwaylandwlshellintegration_p.h @@ -65,11 +65,16 @@ public: bool mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE; private Q_SLOTS: - void handleStartMove(QWaylandInputDevice *inputDevice); - void handleStartResize(QWaylandInputDevice *inputDevice, QWaylandWlShellSurface::ResizeEdge edges); - void handleSetPopup(QWaylandInputDevice *inputDevice, QWaylandSurface *parent, const QPoint &relativeToParent); + void handleStartMove(QWaylandSeat *seat); + void handleStartResize(QWaylandSeat *seat, QWaylandWlShellSurface::ResizeEdge edges); + void handleSetDefaultTopLevel(); + void handleSetTransient(QWaylandSurface *parentSurface, const QPoint &relativeToParent, bool inactive); + void handleSetMaximized(QWaylandOutput *output); + void handleSetFullScreen(QWaylandWlShellSurface::FullScreenMethod method, uint framerate, QWaylandOutput *output); + void handleSetPopup(QWaylandSeat *seat, QWaylandSurface *parent, const QPoint &relativeToParent); void handleShellSurfaceDestroyed(); - void handleSurfaceUnmapped(); + void handleSurfaceHasContentChanged(); + void handleRedraw(); void adjustOffsetForNextFrame(const QPointF &offset); private: @@ -82,26 +87,34 @@ private: void handlePopupClosed(); void handlePopupRemoved(); - static void closePopups(); - QWaylandQuickShellSurfaceItem *m_item; QWaylandWlShellSurface *m_shellSurface; GrabberState grabberState; struct { - QWaylandInputDevice *inputDevice; + QWaylandSeat *seat; QPointF initialOffset; bool initialized; } moveState; struct { - QWaylandInputDevice *inputDevice; + QWaylandSeat *seat; QWaylandWlShellSurface::ResizeEdge resizeEdges; QSizeF initialSize; QPointF initialMousePos; bool initialized; } resizeState; - static QVector<QWaylandWlShellSurface*> popupShellSurfaces; bool isPopup; + + enum class State { + Windowed, + Maximized, + FullScreen + }; + + State currentState; + State nextState; + QPointF normalPosition; + QPointF finalPosition; }; } diff --git a/src/compositor/extensions/qwaylandxdgshell.cpp b/src/compositor/extensions/qwaylandxdgshell.cpp deleted file mode 100644 index dbfcfd625..000000000 --- a/src/compositor/extensions/qwaylandxdgshell.cpp +++ /dev/null @@ -1,1114 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtWaylandCompositor module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** 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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qwaylandxdgshell.h" -#include "qwaylandxdgshell_p.h" -#include "qwaylandxdgshellintegration_p.h" - -#include <QtWaylandCompositor/QWaylandCompositor> -#include <QtWaylandCompositor/QWaylandSurface> -#include <QtWaylandCompositor/QWaylandSurfaceRole> -#include <QtWaylandCompositor/QWaylandResource> -#include <QtWaylandCompositor/QWaylandInputDevice> - -#include <QtCore/QObject> - -#include <algorithm> - -QT_BEGIN_NAMESPACE - -QWaylandSurfaceRole QWaylandXdgSurfacePrivate::s_role("xdg_surface"); -QWaylandSurfaceRole QWaylandXdgPopupPrivate::s_role("xdg_popup"); - -QWaylandXdgShellPrivate::QWaylandXdgShellPrivate() - : QWaylandCompositorExtensionPrivate() - , xdg_shell() -{ -} - -void QWaylandXdgShellPrivate::ping(Resource *resource, uint32_t serial) -{ - m_pings.insert(serial); - send_ping(resource->handle, serial); -} - -void QWaylandXdgShellPrivate::registerSurface(QWaylandXdgSurface *xdgSurface) -{ - m_xdgSurfaces.insert(xdgSurface->surface()->client()->client(), xdgSurface); -} - -void QWaylandXdgShellPrivate::unregisterXdgSurface(QWaylandXdgSurface *xdgSurface) -{ - auto xdgSurfacePrivate = QWaylandXdgSurfacePrivate::get(xdgSurface); - if (!m_xdgSurfaces.remove(xdgSurfacePrivate->resource()->client(), xdgSurface)) - qWarning("%s Unexpected state. Can't find registered xdg surface\n", Q_FUNC_INFO); -} - -void QWaylandXdgShellPrivate::registerXdgPopup(QWaylandXdgPopup *xdgPopup) -{ - m_xdgPopups.insert(xdgPopup->surface()->client()->client(), xdgPopup); -} - -void QWaylandXdgShellPrivate::unregisterXdgPopup(QWaylandXdgPopup *xdgPopup) -{ - auto xdgPopupPrivate = QWaylandXdgPopupPrivate::get(xdgPopup); - if (!m_xdgPopups.remove(xdgPopupPrivate->resource()->client(), xdgPopup)) - qWarning("%s Unexpected state. Can't find registered xdg popup\n", Q_FUNC_INFO); -} - -bool QWaylandXdgShellPrivate::isValidPopupParent(QWaylandSurface *parentSurface) const -{ - QWaylandXdgPopup *topmostPopup = topmostPopupForClient(parentSurface->client()->client()); - if (topmostPopup && topmostPopup->surface() != parentSurface) { - return false; - } - - QWaylandSurfaceRole *parentRole = parentSurface->role(); - if (parentRole != QWaylandXdgSurface::role() && parentRole != QWaylandXdgPopup::role()) { - return false; - } - - return true; -} - -QWaylandXdgPopup *QWaylandXdgShellPrivate::topmostPopupForClient(wl_client *client) const -{ - QList<QWaylandXdgPopup *> clientPopups = m_xdgPopups.values(client); - return clientPopups.empty() ? nullptr : clientPopups.last(); -} - -QWaylandXdgSurface *QWaylandXdgShellPrivate::xdgSurfaceFromSurface(QWaylandSurface *surface) -{ - Q_FOREACH (QWaylandXdgSurface *xdgSurface, m_xdgSurfaces) { - if (surface == xdgSurface->surface()) - return xdgSurface; - } - return nullptr; -} - -void QWaylandXdgShellPrivate::xdg_shell_destroy(Resource *resource) -{ - if (!m_xdgSurfaces.values(resource->client()).empty()) - wl_resource_post_error(resource->handle, XDG_SHELL_ERROR_DEFUNCT_SURFACES, - "xdg_shell was destroyed before children"); - - wl_resource_destroy(resource->handle); -} - -void QWaylandXdgShellPrivate::xdg_shell_get_xdg_surface(Resource *resource, uint32_t id, - wl_resource *surface_res) -{ - Q_Q(QWaylandXdgShell); - QWaylandSurface *surface = QWaylandSurface::fromResource(surface_res); - - if (xdgSurfaceFromSurface(surface)) { - wl_resource_post_error(resource->handle, XDG_SHELL_ERROR_ROLE, - "An active xdg_surface already exists for wl_surface@%d", - wl_resource_get_id(surface->resource())); - return; - } - - if (!surface->setRole(QWaylandXdgSurface::role(), resource->handle, XDG_SHELL_ERROR_ROLE)) - return; - - QWaylandResource xdgSurfaceResource(wl_resource_create(resource->client(), &xdg_surface_interface, - wl_resource_get_version(resource->handle), id)); - - emit q->createXdgSurface(surface, xdgSurfaceResource); - - QWaylandXdgSurface *xdgSurface = QWaylandXdgSurface::fromResource(xdgSurfaceResource.resource()); - if (!xdgSurface) { - // A QWaylandXdgSurface was not created in response to the createXdgSurface signal, so we - // create one as fallback here instead. - xdgSurface = new QWaylandXdgSurface(q, surface, xdgSurfaceResource); - } - - registerSurface(xdgSurface); - emit q->xdgSurfaceCreated(xdgSurface); -} - -void QWaylandXdgShellPrivate::xdg_shell_use_unstable_version(Resource *resource, int32_t version) -{ - if (xdg_shell::version_current != version) { - wl_resource_post_error(resource->handle, WL_DISPLAY_ERROR_INVALID_OBJECT, - "incompatible version, server is %d, but client wants %d", - xdg_shell::version_current, version); - } -} - -void QWaylandXdgShellPrivate::xdg_shell_get_xdg_popup(Resource *resource, uint32_t id, - wl_resource *surface_res, wl_resource *parent, - wl_resource *seat, uint32_t serial, - int32_t x, int32_t y) -{ - Q_UNUSED(serial); - Q_Q(QWaylandXdgShell); - QWaylandSurface *surface = QWaylandSurface::fromResource(surface_res); - QWaylandSurface *parentSurface = QWaylandSurface::fromResource(parent); - - if (!isValidPopupParent(parentSurface)) { - wl_resource_post_error(resource->handle, XDG_SHELL_ERROR_INVALID_POPUP_PARENT, - "the client specified an invalid popup parent surface"); - return; - } - - if (!surface->setRole(QWaylandXdgPopup::role(), resource->handle, XDG_SHELL_ERROR_ROLE)) { - return; - } - - QWaylandResource xdgPopupResource (wl_resource_create(resource->client(), &xdg_popup_interface, - wl_resource_get_version(resource->handle), id)); - QWaylandInputDevice *inputDevice = QWaylandInputDevice::fromSeatResource(seat); - QPoint position(x, y); - emit q->createXdgPopup(surface, parentSurface, inputDevice, position, xdgPopupResource); - - QWaylandXdgPopup *xdgPopup = QWaylandXdgPopup::fromResource(xdgPopupResource.resource()); - if (!xdgPopup) { - // A QWaylandXdgPopup was not created in response to the createXdgPopup signal, so we - // create one as fallback here instead. - xdgPopup = new QWaylandXdgPopup(q, surface, parentSurface, xdgPopupResource); - } - - registerXdgPopup(xdgPopup); - emit q->xdgPopupCreated(xdgPopup); -} - -void QWaylandXdgShellPrivate::xdg_shell_pong(Resource *resource, uint32_t serial) -{ - Q_UNUSED(resource); - Q_Q(QWaylandXdgShell); - if (m_pings.remove(serial)) - emit q->pong(serial); - else - qWarning("Received an unexpected pong!"); -} - -QWaylandXdgSurfacePrivate::QWaylandXdgSurfacePrivate() - : QWaylandCompositorExtensionPrivate() - , xdg_surface() - , m_surface(nullptr) - , m_parentSurface(nullptr) - , m_unsetWindowGeometry(true) - , m_lastAckedConfigure({{}, QSize(0, 0), 0}) -{ -} - -void QWaylandXdgSurfacePrivate::handleFocusLost() -{ - Q_Q(QWaylandXdgSurface); - QWaylandXdgSurfacePrivate::ConfigureEvent current = lastSentConfigure(); - current.states.removeOne(QWaylandXdgSurface::State::ActivatedState); - q->sendConfigure(current.size, current.states); -} - -void QWaylandXdgSurfacePrivate::handleFocusReceived() -{ - Q_Q(QWaylandXdgSurface); - - QWaylandXdgSurfacePrivate::ConfigureEvent current = lastSentConfigure(); - if (!current.states.contains(QWaylandXdgSurface::State::ActivatedState)) { - current.states.push_back(QWaylandXdgSurface::State::ActivatedState); - } - - q->sendConfigure(current.size, current.states); -} - -void QWaylandXdgSurfacePrivate::xdg_surface_destroy_resource(Resource *resource) -{ - Q_UNUSED(resource); - Q_Q(QWaylandXdgSurface); - QWaylandXdgShellPrivate::get(m_xdgShell)->unregisterXdgSurface(q); - delete q; -} - -void QWaylandXdgSurfacePrivate::xdg_surface_destroy(Resource *resource) -{ - wl_resource_destroy(resource->handle); -} - -void QWaylandXdgSurfacePrivate::xdg_surface_move(Resource *resource, wl_resource *seat, uint32_t serial) -{ - Q_UNUSED(resource); - Q_UNUSED(serial); - - Q_Q(QWaylandXdgSurface); - QWaylandInputDevice *input_device = QWaylandInputDevice::fromSeatResource(seat); - emit q->startMove(input_device); -} - -void QWaylandXdgSurfacePrivate::xdg_surface_resize(Resource *resource, wl_resource *seat, - uint32_t serial, uint32_t edges) -{ - Q_UNUSED(resource); - Q_UNUSED(serial); - - Q_Q(QWaylandXdgSurface); - QWaylandInputDevice *input_device = QWaylandInputDevice::fromSeatResource(seat); - emit q->startResize(input_device, QWaylandXdgSurface::ResizeEdge(edges)); -} - -void QWaylandXdgSurfacePrivate::xdg_surface_set_maximized(Resource *resource) -{ - Q_UNUSED(resource); - Q_Q(QWaylandXdgSurface); - emit q->setMaximized(); -} - -void QWaylandXdgSurfacePrivate::xdg_surface_unset_maximized(Resource *resource) -{ - Q_UNUSED(resource); - Q_Q(QWaylandXdgSurface); - emit q->unsetMaximized(); -} - -void QWaylandXdgSurfacePrivate::xdg_surface_set_fullscreen(Resource *resource, wl_resource *output_res) -{ - Q_UNUSED(resource); - Q_Q(QWaylandXdgSurface); - QWaylandOutput *output = output_res ? QWaylandOutput::fromResource(output_res) : nullptr; - emit q->setFullscreen(output); -} - -void QWaylandXdgSurfacePrivate::xdg_surface_unset_fullscreen(Resource *resource) -{ - Q_UNUSED(resource); - Q_Q(QWaylandXdgSurface); - emit q->unsetFullscreen(); -} - -void QWaylandXdgSurfacePrivate::xdg_surface_set_minimized(Resource *resource) -{ - Q_UNUSED(resource); - Q_Q(QWaylandXdgSurface); - emit q->setMinimized(); -} - -void QWaylandXdgSurfacePrivate::xdg_surface_set_parent(Resource *resource, wl_resource *parent) -{ - Q_UNUSED(resource); - QWaylandXdgSurface *parentSurface = nullptr; - if (parent) { - parentSurface = static_cast<QWaylandXdgSurfacePrivate *>( - QWaylandXdgSurfacePrivate::Resource::fromResource(parent)->xdg_surface_object)->q_func(); - } - - if (m_parentSurface == parentSurface) - return; - - Q_Q(QWaylandXdgSurface); - m_parentSurface = parentSurface; - emit q->parentSurfaceChanged(); -} - -void QWaylandXdgSurfacePrivate::xdg_surface_set_app_id(Resource *resource, const QString &app_id) -{ - Q_UNUSED(resource); - if (app_id == m_appId) - return; - Q_Q(QWaylandXdgSurface); - m_appId = app_id; - emit q->appIdChanged(); -} - -void QWaylandXdgSurfacePrivate::xdg_surface_show_window_menu(Resource *resource, wl_resource *seat, - uint32_t serial, int32_t x, int32_t y) -{ - Q_UNUSED(resource); - Q_UNUSED(serial); - QPoint position(x, y); - auto inputDevice = QWaylandInputDevice::fromSeatResource(seat); - Q_Q(QWaylandXdgSurface); - emit q->showWindowMenu(inputDevice, position); -} - -void QWaylandXdgSurfacePrivate::xdg_surface_ack_configure(Resource *resource, uint32_t serial) -{ - Q_UNUSED(resource); - Q_Q(QWaylandXdgSurface); - - ConfigureEvent config; - Q_FOREVER { - if (m_pendingConfigures.empty()) { - qWarning("Received an unexpected ack_configure!"); - return; - } - - config = m_pendingConfigures.takeFirst(); - - if (config.serial == serial) - break; - } - - QVector<uint> changedStates; - std::set_symmetric_difference( - m_lastAckedConfigure.states.begin(), m_lastAckedConfigure.states.end(), - config.states.begin(), config.states.end(), - std::back_inserter(changedStates)); - - m_lastAckedConfigure = config; - - if (!changedStates.empty()) { - Q_FOREACH (uint state, changedStates) { - switch (state) { - case QWaylandXdgSurface::State::MaximizedState: - emit q->maximizedChanged(); - break; - case QWaylandXdgSurface::State::FullscreenState: - emit q->fullscreenChanged(); - break; - case QWaylandXdgSurface::State::ResizingState: - emit q->resizingChanged(); - break; - case QWaylandXdgSurface::State::ActivatedState: - emit q->activatedChanged(); - break; - } - } - emit q->statesChanged(); - } - - emit q->ackConfigure(serial); -} - -void QWaylandXdgSurfacePrivate::xdg_surface_set_title(Resource *resource, const QString &title) -{ - Q_UNUSED(resource); - if (title == m_title) - return; - Q_Q(QWaylandXdgSurface); - m_title = title; - emit q->titleChanged(); -} - -void QWaylandXdgSurfacePrivate::xdg_surface_set_window_geometry(Resource *resource, - int32_t x, int32_t y, - int32_t width, int32_t height) -{ - Q_UNUSED(resource); - - if (width <= 0 || height <= 0) { - qWarning() << "Invalid (non-positive) dimensions received in set_window_geometry"; - return; - } - - m_unsetWindowGeometry = false; - - QRect geometry(x, y, width, height); - - Q_Q(QWaylandXdgSurface); - if ((q->maximized() || q->fullscreen()) && m_lastAckedConfigure.size != geometry.size()) - qWarning() << "Client window geometry did not obey last acked configure"; - - if (geometry == m_windowGeometry) - return; - - m_windowGeometry = geometry; - emit q->windowGeometryChanged(); -} - -QWaylandXdgPopupPrivate::QWaylandXdgPopupPrivate() - : QWaylandCompositorExtensionPrivate() - , xdg_popup() - , m_surface(nullptr) - , m_parentSurface(nullptr) - , m_xdgShell(nullptr) -{ -} - -void QWaylandXdgPopupPrivate::xdg_popup_destroy_resource(Resource *resource) -{ - Q_UNUSED(resource); - Q_Q(QWaylandXdgPopup); - QWaylandXdgShellPrivate::get(m_xdgShell)->unregisterXdgPopup(q); - delete q; -} - -void QWaylandXdgPopupPrivate::xdg_popup_destroy(Resource *resource) -{ - //TODO: post error if not topmost popup - wl_resource_destroy(resource->handle); -} - - -/*! - * \qmltype XdgShell - * \inqmlmodule QtWayland.Compositor - * \preliminary - * \brief Provides an extension for desktop-style user interfaces. - * - * The XdgShell extension provides desktop functionality such as minimize, - * maximize, and resize using the \c xdg-shell protocol. It creates an XdgSurface - * for each Wayland surface. - * - * The following snippet demonstrates how to use the extension: - * \quotefromfile minimal-qml/main.qml - * \skipto import - * \printuntil /^\}$/ - * - */ - -/*! - * \class QWaylandXdgShell - * \inmodule QtWaylandCompositor - * \preliminary - * \brief Provides an extension for desktop-style user interfaces. - * - * The QWaylandXdgShell extension provides desktop functionality such as minimize, - * maximize, and resize using the \c xdg-shell protocol. It creates an QWaylandXdgSurface - * for each Wayland surface. - * - */ - -/*! - * Constructs a QWaylandXdgShell object. - */ -QWaylandXdgShell::QWaylandXdgShell() - : QWaylandCompositorExtensionTemplate<QWaylandXdgShell>(*new QWaylandXdgShellPrivate()) -{ } - -/*! - * Constructs a QWaylandXdgShell object for the provided \a compositor. - */ -QWaylandXdgShell::QWaylandXdgShell(QWaylandCompositor *compositor) - : QWaylandCompositorExtensionTemplate<QWaylandXdgShell>(compositor, *new QWaylandXdgShellPrivate()) -{ } - -/*! - * Initializes the shell extension. - */ -void QWaylandXdgShell::initialize() -{ - Q_D(QWaylandXdgShell); - QWaylandCompositorExtensionTemplate::initialize(); - QWaylandCompositor *compositor = static_cast<QWaylandCompositor *>(extensionContainer()); - if (!compositor) { - qWarning() << "Failed to find QWaylandCompositor when initializing QWaylandXdgShell"; - return; - } - d->init(compositor->display(), 1); - - handleDefaultInputDeviceChanged(compositor->defaultInputDevice(), nullptr); - - connect(compositor, &QWaylandCompositor::defaultInputDeviceChanged, - this, &QWaylandXdgShell::handleDefaultInputDeviceChanged); -} - -/*! - * Returns the Wayland interface for the QWaylandXdgShell. - */ -const struct wl_interface *QWaylandXdgShell::interface() -{ - return QWaylandXdgShellPrivate::interface(); -} - -QByteArray QWaylandXdgShell::interfaceName() -{ - return QWaylandXdgShellPrivate::interfaceName(); -} - -/*! - * \qmlmethod void QtWaylandCompositor::XdgShell::ping(object client) - * - * Sends a ping event to the \a client. If the client replies to the event the - * \l pong signal will be emitted. - */ - -/*! - * Sends a ping event to the client. If the client replies to the event the - * \a pong signal will be emitted. - */ -uint QWaylandXdgShell::ping(QWaylandClient *client) -{ - Q_D(QWaylandXdgShell); - - QWaylandCompositor *compositor = static_cast<QWaylandCompositor *>(extensionContainer()); - Q_ASSERT(compositor); - - uint32_t serial = compositor->nextSerial(); - - QWaylandXdgShellPrivate::Resource *clientResource = d->resourceMap().value(client->client(), nullptr); - Q_ASSERT(clientResource); - - d->ping(clientResource, serial); - return serial; -} - -void QWaylandXdgShell::closeAllPopups() -{ - Q_D(QWaylandXdgShell); - Q_FOREACH (struct wl_client *client, d->m_xdgPopups.keys()) { - QList<QWaylandXdgPopup *> popups = d->m_xdgPopups.values(client); - std::reverse(popups.begin(), popups.end()); - Q_FOREACH (QWaylandXdgPopup *currentTopmostPopup, popups) { - currentTopmostPopup->sendPopupDone(); - } - } -} - -void QWaylandXdgShell::handleDefaultInputDeviceChanged(QWaylandInputDevice *newDevice, QWaylandInputDevice *oldDevice) -{ - if (oldDevice != nullptr) { - disconnect(oldDevice, &QWaylandInputDevice::keyboardFocusChanged, - this, &QWaylandXdgShell::handleFocusChanged); - } - - if (newDevice != nullptr) { - connect(newDevice, &QWaylandInputDevice::keyboardFocusChanged, - this, &QWaylandXdgShell::handleFocusChanged); - } -} - -void QWaylandXdgShell::handleFocusChanged(QWaylandSurface *newSurface, QWaylandSurface *oldSurface) -{ - Q_D(QWaylandXdgShell); - - QWaylandXdgSurface *newXdgSurface = d->xdgSurfaceFromSurface(newSurface); - QWaylandXdgSurface *oldXdgSurface = d->xdgSurfaceFromSurface(oldSurface); - - if (newXdgSurface) - QWaylandXdgSurfacePrivate::get(newXdgSurface)->handleFocusReceived(); - - if (oldXdgSurface) - QWaylandXdgSurfacePrivate::get(oldXdgSurface)->handleFocusLost(); -} -/*! - * \qmltype XdgSurface - * \inqmlmodule QtWayland.Compositor - * \preliminary - * \brief Provides an XDG surface that offers desktop functionality. - * - * XdgSurface is part of the XdgShell extension and provides desktop - * functionality such as minimize, maximize, and resize using the - * \c xdg-shell protocol. - * - */ - -/*! - * \class QWaylandXdgSurface - * \inmodule QtWaylandCompositor - * \preliminary - * \brief The QWaylandXdgSurface class provides desktop functionality. - * - * The QWaylandXdgSurface class is part of the QWaylandXdgShell extension and - * provides a way to extend the functionality of an existing QWaylandSurface with - * features specific to desktop-style compositors, such as resizing and moving the - * surface. - * - * It corresponds to the Wayland interface \c xdg_surface. - */ - -/*! - * Constructs a QWaylandXdgSurface. - */ -QWaylandXdgSurface::QWaylandXdgSurface() - : QWaylandShellSurfaceTemplate<QWaylandXdgSurface>(*new QWaylandXdgSurfacePrivate) -{ -} - -/*! - * Constructs a QWaylandXdgSurface for \a surface and initializes it with the - * given \a xdgShell, \a surface, and resource \a res. - */ -QWaylandXdgSurface::QWaylandXdgSurface(QWaylandXdgShell *xdgShell, QWaylandSurface *surface, const QWaylandResource &res) - : QWaylandShellSurfaceTemplate<QWaylandXdgSurface>(*new QWaylandXdgSurfacePrivate) -{ - initialize(xdgShell, surface, res); -} - -/*! - * \qmlmethod void QtWaylandCompositor::XdgSurface::initialize(object surface, object client, int id) - * - * Initializes the XdgSurface and associates it with the given \a surface, - * \a client, and \a id. - */ - -/*! - * Initializes the QWaylandXdgSurface and associates it with the given \a xdgShell, \a surface, - * and \a resource. - */ -void QWaylandXdgSurface::initialize(QWaylandXdgShell *xdgShell, QWaylandSurface *surface, const QWaylandResource &resource) -{ - Q_D(QWaylandXdgSurface); - d->m_xdgShell = xdgShell; - d->m_surface = surface; - d->init(resource.resource()); - setExtensionContainer(surface); - d->m_windowGeometry = QRect(QPoint(0,0), surface->size()); - connect(surface, &QWaylandSurface::sizeChanged, this, &QWaylandXdgSurface::handleSurfaceSizeChanged); - emit surfaceChanged(); - emit windowGeometryChanged(); - QWaylandCompositorExtension::initialize(); -} - -/*! - * \internal - */ -void QWaylandXdgSurface::initialize() -{ - QWaylandCompositorExtension::initialize(); -} - -QList<int> QWaylandXdgSurface::statesAsInts() const -{ - QList<int> list; - Q_FOREACH (uint state, states()) { - list << static_cast<int>(state); - } - return list; -} - -void QWaylandXdgSurface::handleSurfaceSizeChanged() -{ - Q_D(QWaylandXdgSurface); - if (d->m_unsetWindowGeometry && d->m_windowGeometry.size() != surface()->size()) { - // TODO: The unset window geometry should include subsurfaces as well, so this solution - // won't work too well on those kinds of clients. - d->m_windowGeometry.setSize(surface()->size()); - emit windowGeometryChanged(); - } -} - -/*! - * \qmlproperty object QtWaylandCompositor::XdgSurface::surface - * - * This property holds the surface associated with this XdgSurface. - */ - -/*! - * \property QWaylandXdgSurface::surface - * - * This property holds the surface associated with this QWaylandXdgSurface. - */ -QWaylandSurface *QWaylandXdgSurface::surface() const -{ - Q_D(const QWaylandXdgSurface); - return d->m_surface; -} - -/*! - * \qmlproperty object QtWaylandCompositor::XdgSurface::parentSurface - * - * This property holds the parent of this XdgSurface. - */ - -/*! - * \property QWaylandXdgSurface::parentSurface - * - * This property holds the parent of this XdgSurface. - */ -QWaylandXdgSurface *QWaylandXdgSurface::parentSurface() const -{ - Q_D(const QWaylandXdgSurface); - return d->m_parentSurface; -} - -/*! - * \qmlproperty string QtWaylandCompositor::XdgSurface::title - * - * This property holds the title of the XdgSurface. - */ - -/*! - * \property QWaylandXdgSurface::title - * - * This property holds the title of the QWaylandXdgSurface. - */ -QString QWaylandXdgSurface::title() const -{ - Q_D(const QWaylandXdgSurface); - return d->m_title; -} - -/*! - * \property QWaylandXdgSurface::appId - * - * This property holds the app id of the QWaylandXdgSurface. - */ -QString QWaylandXdgSurface::appId() const -{ - Q_D(const QWaylandXdgSurface); - return d->m_appId; -} - -/*! - * \property QWaylandXdgSurface::windowGeometry - * - * This property holds the window geometry of the QWaylandXdgSurface. The window - * geometry describes the window's visible bounds from the user's perspective. - * The geometry includes title bars and borders if drawn by the client, but - * excludes drop shadows. It is meant to be used for aligning and tiling - * windows. - */ -QRect QWaylandXdgSurface::windowGeometry() const -{ - Q_D(const QWaylandXdgSurface); - return d->m_windowGeometry; -} - -/*! - * \property QWaylandXdgSurface::states - * - * This property holds the last states the client acknowledged for this QWaylandXdgSurface. - */ -QVector<uint> QWaylandXdgSurface::states() const -{ - Q_D(const QWaylandXdgSurface); - return d->m_lastAckedConfigure.states; -} - -bool QWaylandXdgSurface::maximized() const -{ - Q_D(const QWaylandXdgSurface); - return d->m_lastAckedConfigure.states.contains(QWaylandXdgSurface::State::MaximizedState); -} - -bool QWaylandXdgSurface::fullscreen() const -{ - Q_D(const QWaylandXdgSurface); - return d->m_lastAckedConfigure.states.contains(QWaylandXdgSurface::State::FullscreenState); -} - -bool QWaylandXdgSurface::resizing() const -{ - Q_D(const QWaylandXdgSurface); - return d->m_lastAckedConfigure.states.contains(QWaylandXdgSurface::State::ResizingState); -} - -bool QWaylandXdgSurface::activated() const -{ - Q_D(const QWaylandXdgSurface); - return d->m_lastAckedConfigure.states.contains(QWaylandXdgSurface::State::ActivatedState); -} - -/*! - * Returns the Wayland interface for the QWaylandXdgSurface. - */ -const wl_interface *QWaylandXdgSurface::interface() -{ - return QWaylandXdgSurfacePrivate::interface(); -} - -QByteArray QWaylandXdgSurface::interfaceName() -{ - return QWaylandXdgSurfacePrivate::interfaceName(); -} - -/*! - * Returns the surface role for the QWaylandXdgSurface. - */ -QWaylandSurfaceRole *QWaylandXdgSurface::role() -{ - return &QWaylandXdgSurfacePrivate::s_role; -} - -/*! - * Returns the QWaylandXdgSurface corresponding to the \a resource. - */ -QWaylandXdgSurface *QWaylandXdgSurface::fromResource(wl_resource *resource) -{ - auto xsResource = QWaylandXdgSurfacePrivate::Resource::fromResource(resource); - if (!xsResource) - return nullptr; - return static_cast<QWaylandXdgSurfacePrivate *>(xsResource->xdg_surface_object)->q_func(); -} - -QSize QWaylandXdgSurface::sizeForResize(const QSizeF &size, const QPointF &delta, - QWaylandXdgSurface::ResizeEdge edge) -{ - qreal width = size.width(); - qreal height = size.height(); - if (edge & LeftEdge) - width -= delta.x(); - else if (edge & RightEdge) - width += delta.x(); - - if (edge & TopEdge) - height -= delta.y(); - else if (edge & BottomEdge) - height += delta.y(); - - return QSizeF(width, height).toSize(); -} - -/*! - * \qmlmethod int QtWaylandCompositor::XdgSurface::sendConfigure(size size, List<uint>) - * - * Sends a configure event to the client. Known states are enumerated in XdgSurface::State - */ - -/*! - * Sends a configure event to the client. Known states are enumerated in QWaylandXdgSurface::State - */ -uint QWaylandXdgSurface::sendConfigure(const QSize &size, const QVector<uint> &states) -{ - Q_D(QWaylandXdgSurface); - auto statesBytes = QByteArray::fromRawData((char *)states.data(), states.size() * sizeof(State)); - QWaylandCompositor *compositor = static_cast<QWaylandCompositor *>(extensionContainer()); - Q_ASSERT(compositor); - uint32_t serial = compositor->nextSerial(); - d->m_pendingConfigures.append(QWaylandXdgSurfacePrivate::ConfigureEvent{states, size, serial}); - d->send_configure(size.width(), size.height(), statesBytes, serial); - return serial; -} - -uint QWaylandXdgSurface::sendConfigure(const QSize &size, const QVector<QWaylandXdgSurface::State> &states) -{ - QVector<uint> asUints; - Q_FOREACH (QWaylandXdgSurface::State state, states) { - asUints << state; - } - return sendConfigure(size, asUints); -} - -/*! - * \qmlmethod void QtWaylandCompositor::XdgSurface::sendClose() - * - * Sends a close event to the client. - */ - -/*! - * Sends a close event to the client. - */ -void QWaylandXdgSurface::sendClose() -{ - Q_D(QWaylandXdgSurface); - d->send_close(); -} - -uint QWaylandXdgSurface::requestMaximized(const QSize &size) -{ - Q_D(QWaylandXdgSurface); - QWaylandXdgSurfacePrivate::ConfigureEvent conf = d->lastSentConfigure(); - - if (!conf.states.contains(QWaylandXdgSurface::State::MaximizedState)) - conf.states.append(QWaylandXdgSurface::State::MaximizedState); - conf.states.removeOne(QWaylandXdgSurface::State::FullscreenState); - conf.states.removeOne(QWaylandXdgSurface::State::ResizingState); - - return sendConfigure(size, conf.states); -} - -uint QWaylandXdgSurface::requestUnMaximized(const QSize &size) -{ - Q_D(QWaylandXdgSurface); - QWaylandXdgSurfacePrivate::ConfigureEvent conf = d->lastSentConfigure(); - - conf.states.removeOne(QWaylandXdgSurface::State::MaximizedState); - conf.states.removeOne(QWaylandXdgSurface::State::FullscreenState); - conf.states.removeOne(QWaylandXdgSurface::State::ResizingState); - - return sendConfigure(size, conf.states); -} - -uint QWaylandXdgSurface::requestFullscreen(const QSize &size) -{ - Q_D(QWaylandXdgSurface); - QWaylandXdgSurfacePrivate::ConfigureEvent conf = d->lastSentConfigure(); - - if (!conf.states.contains(QWaylandXdgSurface::State::FullscreenState)) - conf.states.append(QWaylandXdgSurface::State::FullscreenState); - conf.states.removeOne(QWaylandXdgSurface::State::MaximizedState); - conf.states.removeOne(QWaylandXdgSurface::State::ResizingState); - - return sendConfigure(size, conf.states); -} - -uint QWaylandXdgSurface::requestResizing(const QSize &maxSize) -{ - Q_D(QWaylandXdgSurface); - QWaylandXdgSurfacePrivate::ConfigureEvent conf = d->lastSentConfigure(); - - if (!conf.states.contains(QWaylandXdgSurface::State::ResizingState)) - conf.states.append(QWaylandXdgSurface::State::ResizingState); - conf.states.removeOne(QWaylandXdgSurface::State::MaximizedState); - conf.states.removeOne(QWaylandXdgSurface::State::FullscreenState); - - return sendConfigure(maxSize, conf.states); -} - -QWaylandQuickShellIntegration *QWaylandXdgSurface::createIntegration(QWaylandQuickShellSurfaceItem *item) -{ - return new QtWayland::XdgShellIntegration(item); -} - -/*! - * \qmltype XdgPopup - * \inqmlmodule QtWayland.Compositor - * \preliminary - * \brief Provides menus for an xdg surface - * - * XdgPopup is part of the XdgShell extension and provides desktop-style - * menus for an XdgSurface. - * - * It corresponds to the Wayland interface \c xdg_popup. - */ - -/*! - * \class QWaylandXdgPopup - * \inmodule QtWaylandCompositor - * \preliminary - * \brief The QWaylandXdgPopup class provides menus for an xdg surface - * - * The QWaylandXdbPopup class is part of the QWaylandXdgShell extension and - * provides a way to extend the functionality of an existing QWaylandSurface - * with features specific to desktop-style menus for an xdg surface. - * - * It corresponds to the Wayland interface \c xdg_popup. - */ - -/*! - * Constructs a QWaylandXdgPopup. - */ -QWaylandXdgPopup::QWaylandXdgPopup() - : QWaylandCompositorExtensionTemplate<QWaylandXdgPopup>(*new QWaylandXdgPopupPrivate) -{ -} - -/*! - * Constructs a QWaylandXdgPopup for \a surface and initializes it with the - * given \a parentSurface and \a resource. - */ -QWaylandXdgPopup::QWaylandXdgPopup(QWaylandXdgShell *xdgShell, QWaylandSurface *surface, - QWaylandSurface *parentSurface, const QWaylandResource &resource) - : QWaylandCompositorExtensionTemplate<QWaylandXdgPopup>(*new QWaylandXdgPopupPrivate) -{ - initialize(xdgShell, surface, parentSurface, resource); -} - -/*! - * \qmlmethod void QtWaylandCompositor::XdgPopup::initialize(object surface, object parentSurface, object resource) - * - * Initializes the xdg popup and associates it with the given \a shell, \a surface, - * \a parentSurface, and \a resource. - */ - -/*! - * Initializes the QWaylandXdgPopup and associates it with the given \a shell \a surface, - * \a parentSurface, and \a resource. - */ -void QWaylandXdgPopup::initialize(QWaylandXdgShell *shell, QWaylandSurface *surface, - QWaylandSurface *parentSurface, const QWaylandResource &resource) -{ - Q_D(QWaylandXdgPopup); - d->m_surface = surface; - d->m_parentSurface = parentSurface; - d->m_xdgShell = shell; - d->init(resource.resource()); - setExtensionContainer(surface); - emit surfaceChanged(); - emit parentSurfaceChanged(); - QWaylandCompositorExtension::initialize(); -} - -/*! - * \qmlproperty object QtWaylandCompositor::XdgPopup::surface - * - * This property holds the surface associated with this XdgPopup. - */ - -/*! - * \property QWaylandXdgPopup::surface - * - * This property holds the surface associated with this QWaylandXdgPopup. - */ -QWaylandSurface *QWaylandXdgPopup::surface() const -{ - Q_D(const QWaylandXdgPopup); - return d->m_surface; -} - -/*! - * \qmlproperty object QtWaylandCompositor::XdgPopup::parentSurface - * - * This property holds the surface associated with the parent of this XdgPopup. - */ - -/*! - * \property QWaylandXdgPopup::parentSurface - * - * This property holds the surface associated with the parent of this - * QWaylandXdgPopup. - */ -QWaylandSurface *QWaylandXdgPopup::parentSurface() const -{ - Q_D(const QWaylandXdgPopup); - return d->m_parentSurface; -} - -/*! - * \internal - */ -void QWaylandXdgPopup::initialize() -{ - QWaylandCompositorExtensionTemplate::initialize(); -} - -/*! - * Returns the Wayland interface for the QWaylandXdgPopup. - */ -const wl_interface *QWaylandXdgPopup::interface() -{ - return QWaylandXdgPopupPrivate::interface(); -} - -QByteArray QWaylandXdgPopup::interfaceName() -{ - return QWaylandXdgPopupPrivate::interfaceName(); -} - -/*! - * Returns the surface role for the QWaylandXdgPopup. - */ -QWaylandSurfaceRole *QWaylandXdgPopup::role() -{ - return &QWaylandXdgPopupPrivate::s_role; -} - -QWaylandXdgPopup *QWaylandXdgPopup::fromResource(wl_resource *resource) -{ - auto popupResource = QWaylandXdgPopupPrivate::Resource::fromResource(resource); - if (!popupResource) - return nullptr; - return static_cast<QWaylandXdgPopupPrivate *>(popupResource->xdg_popup_object)->q_func(); -} - -void QWaylandXdgPopup::sendPopupDone() -{ - Q_D(QWaylandXdgPopup); - d->send_popup_done(); -} - -QT_END_NAMESPACE diff --git a/src/compositor/extensions/qwaylandxdgshellintegration.cpp b/src/compositor/extensions/qwaylandxdgshellintegration.cpp deleted file mode 100644 index ab10011e6..000000000 --- a/src/compositor/extensions/qwaylandxdgshellintegration.cpp +++ /dev/null @@ -1,172 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtWaylandCompositor module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** 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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qwaylandxdgshellintegration_p.h" - -#include <QtWaylandCompositor/QWaylandQuickShellSurfaceItem> -#include <QtWaylandCompositor/QWaylandCompositor> -#include <QtWaylandCompositor/QWaylandInputDevice> -#include <QMouseEvent> - -QT_BEGIN_NAMESPACE - -namespace QtWayland { - -XdgShellIntegration::XdgShellIntegration(QWaylandQuickShellSurfaceItem *item) - : QWaylandQuickShellIntegration(item) - , m_item(item) - , m_xdgSurface(qobject_cast<QWaylandXdgSurface *>(item->shellSurface())) - , grabberState(GrabberState::Default) -{ - m_item->setSurface(m_xdgSurface->surface()); - connect(m_xdgSurface, &QWaylandXdgSurface::startMove, this, &XdgShellIntegration::handleStartMove); - connect(m_xdgSurface, &QWaylandXdgSurface::startResize, this, &XdgShellIntegration::handleStartResize); - connect(m_xdgSurface, &QWaylandXdgSurface::setMaximized, this, &XdgShellIntegration::handleSetMaximized); - connect(m_xdgSurface, &QWaylandXdgSurface::unsetMaximized, this, &XdgShellIntegration::handleUnsetMaximized); - connect(m_xdgSurface, &QWaylandXdgSurface::maximizedChanged, this, &XdgShellIntegration::handleMaximizedChanged); - connect(m_xdgSurface, &QWaylandXdgSurface::activatedChanged, this, &XdgShellIntegration::handleActivatedChanged); - connect(m_xdgSurface->surface(), &QWaylandSurface::sizeChanged, this, &XdgShellIntegration::handleSurfaceSizeChanged); -} - -bool XdgShellIntegration::mouseMoveEvent(QMouseEvent *event) -{ - if (grabberState == GrabberState::Resize) { - Q_ASSERT(resizeState.inputDevice == m_item->compositor()->inputDeviceFor(event)); - if (!resizeState.initialized) { - resizeState.initialMousePos = event->windowPos(); - resizeState.initialized = true; - return true; - } - float scaleFactor = m_item->view()->output()->scaleFactor(); - QPointF delta = (event->windowPos() - resizeState.initialMousePos) / scaleFactor; - QSize newSize = m_xdgSurface->sizeForResize(resizeState.initialWindowSize, delta, resizeState.resizeEdges); - m_xdgSurface->requestResizing(newSize); - } else if (grabberState == GrabberState::Move) { - Q_ASSERT(moveState.inputDevice == m_item->compositor()->inputDeviceFor(event)); - QQuickItem *moveItem = m_item->moveItem(); - if (!moveState.initialized) { - moveState.initialOffset = moveItem->mapFromItem(nullptr, event->windowPos()); - moveState.initialized = true; - return true; - } - if (!moveItem->parentItem()) - return true; - QPointF parentPos = moveItem->parentItem()->mapFromItem(nullptr, event->windowPos()); - moveItem->setPosition(parentPos - moveState.initialOffset); - } - return false; -} - -bool XdgShellIntegration::mouseReleaseEvent(QMouseEvent *event) -{ - Q_UNUSED(event); - - if (grabberState == GrabberState::Resize) { - m_xdgSurface->requestUnMaximized(); - grabberState = GrabberState::Default; - return true; - } else if (grabberState == GrabberState::Move) { - grabberState = GrabberState::Default; - return true; - } - return false; -} - -void XdgShellIntegration::handleStartMove(QWaylandInputDevice *inputDevice) -{ - grabberState = GrabberState::Move; - moveState.inputDevice = inputDevice; - moveState.initialized = false; -} - -void XdgShellIntegration::handleStartResize(QWaylandInputDevice *inputDevice, QWaylandXdgSurface::ResizeEdge edges) -{ - grabberState = GrabberState::Resize; - resizeState.inputDevice = inputDevice; - resizeState.resizeEdges = edges; - resizeState.initialWindowSize = m_xdgSurface->windowGeometry().size(); - resizeState.initialPosition = m_item->position(); - resizeState.initialSurfaceSize = m_item->surface()->size(); - resizeState.initialized = false; -} - -void XdgShellIntegration::handleSetMaximized() -{ - maximizeState.initialWindowSize = m_xdgSurface->windowGeometry().size(); - maximizeState.initialPosition = m_item->position(); - - QWaylandOutput *output = m_item->compositor()->outputs().first(); - m_xdgSurface->requestMaximized(output->geometry().size() / output->scaleFactor()); -} - -void XdgShellIntegration::handleUnsetMaximized() -{ - m_xdgSurface->requestUnMaximized(maximizeState.initialWindowSize); -} - -void XdgShellIntegration::handleMaximizedChanged() -{ - if (m_xdgSurface->maximized()) { - QWaylandOutput *output = m_item->compositor()->outputs().first(); - m_item->setPosition(output->geometry().topLeft()); - } else { - m_item->setPosition(maximizeState.initialPosition); - } -} - -void XdgShellIntegration::handleActivatedChanged() -{ - if (m_xdgSurface->activated()) - m_item->raise(); -} - -void XdgShellIntegration::handleSurfaceSizeChanged() -{ - if (grabberState == GrabberState::Resize) { - qreal x = resizeState.initialPosition.x(); - qreal y = resizeState.initialPosition.y(); - if (resizeState.resizeEdges & QWaylandXdgSurface::ResizeEdge::TopEdge) - y += resizeState.initialSurfaceSize.height() - m_item->surface()->size().height(); - - if (resizeState.resizeEdges & QWaylandXdgSurface::ResizeEdge::LeftEdge) - x += resizeState.initialSurfaceSize.width() - m_item->surface()->size().width(); - m_item->setPosition(QPointF(x, y)); - } -} - -} - -QT_END_NAMESPACE diff --git a/src/compositor/extensions/qwaylandxdgshellv5.cpp b/src/compositor/extensions/qwaylandxdgshellv5.cpp new file mode 100644 index 000000000..fd23865cf --- /dev/null +++ b/src/compositor/extensions/qwaylandxdgshellv5.cpp @@ -0,0 +1,1204 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWaylandCompositor module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwaylandxdgshellv5.h" +#include "qwaylandxdgshellv5_p.h" + +#ifdef QT_WAYLAND_COMPOSITOR_QUICK +#include "qwaylandxdgshellv5integration_p.h" +#endif + +#include <QtWaylandCompositor/QWaylandCompositor> +#include <QtWaylandCompositor/QWaylandSurface> +#include <QtWaylandCompositor/QWaylandSurfaceRole> +#include <QtWaylandCompositor/QWaylandResource> +#include <QtWaylandCompositor/QWaylandSeat> + +#include <QtCore/QObject> + +#include <algorithm> + +QT_BEGIN_NAMESPACE + +QWaylandSurfaceRole QWaylandXdgSurfaceV5Private::s_role("xdg_surface"); +QWaylandSurfaceRole QWaylandXdgPopupV5Private::s_role("xdg_popup"); + +QWaylandXdgShellV5Private::QWaylandXdgShellV5Private() + : QWaylandCompositorExtensionPrivate() + , xdg_shell() +{ +} + +void QWaylandXdgShellV5Private::ping(Resource *resource, uint32_t serial) +{ + m_pings.insert(serial); + send_ping(resource->handle, serial); +} + +void QWaylandXdgShellV5Private::registerSurface(QWaylandXdgSurfaceV5 *xdgSurface) +{ + m_xdgSurfaces.insert(xdgSurface->surface()->client()->client(), xdgSurface); +} + +void QWaylandXdgShellV5Private::unregisterXdgSurface(QWaylandXdgSurfaceV5 *xdgSurface) +{ + auto xdgSurfacePrivate = QWaylandXdgSurfaceV5Private::get(xdgSurface); + if (!m_xdgSurfaces.remove(xdgSurfacePrivate->resource()->client(), xdgSurface)) + qWarning("%s Unexpected state. Can't find registered xdg surface\n", Q_FUNC_INFO); +} + +void QWaylandXdgShellV5Private::registerXdgPopup(QWaylandXdgPopupV5 *xdgPopup) +{ + m_xdgPopups.insert(xdgPopup->surface()->client()->client(), xdgPopup); +} + +void QWaylandXdgShellV5Private::unregisterXdgPopup(QWaylandXdgPopupV5 *xdgPopup) +{ + auto xdgPopupPrivate = QWaylandXdgPopupV5Private::get(xdgPopup); + if (!m_xdgPopups.remove(xdgPopupPrivate->resource()->client(), xdgPopup)) + qWarning("%s Unexpected state. Can't find registered xdg popup\n", Q_FUNC_INFO); +} + +bool QWaylandXdgShellV5Private::isValidPopupParent(QWaylandSurface *parentSurface) const +{ + QWaylandXdgPopupV5 *topmostPopup = topmostPopupForClient(parentSurface->client()->client()); + if (topmostPopup && topmostPopup->surface() != parentSurface) { + return false; + } + + QWaylandSurfaceRole *parentRole = parentSurface->role(); + if (parentRole != QWaylandXdgSurfaceV5::role() && parentRole != QWaylandXdgPopupV5::role()) { + return false; + } + + return true; +} + +QWaylandXdgPopupV5 *QWaylandXdgShellV5Private::topmostPopupForClient(wl_client *client) const +{ + QList<QWaylandXdgPopupV5 *> clientPopups = m_xdgPopups.values(client); + return clientPopups.empty() ? nullptr : clientPopups.last(); +} + +QWaylandXdgSurfaceV5 *QWaylandXdgShellV5Private::xdgSurfaceFromSurface(QWaylandSurface *surface) +{ + Q_FOREACH (QWaylandXdgSurfaceV5 *xdgSurface, m_xdgSurfaces) { + if (surface == xdgSurface->surface()) + return xdgSurface; + } + return nullptr; +} + +void QWaylandXdgShellV5Private::xdg_shell_destroy(Resource *resource) +{ + if (!m_xdgSurfaces.values(resource->client()).empty()) + wl_resource_post_error(resource->handle, XDG_SHELL_ERROR_DEFUNCT_SURFACES, + "xdg_shell was destroyed before children"); + + wl_resource_destroy(resource->handle); +} + +void QWaylandXdgShellV5Private::xdg_shell_get_xdg_surface(Resource *resource, uint32_t id, + wl_resource *surface_res) +{ + Q_Q(QWaylandXdgShellV5); + QWaylandSurface *surface = QWaylandSurface::fromResource(surface_res); + + if (xdgSurfaceFromSurface(surface)) { + wl_resource_post_error(resource->handle, XDG_SHELL_ERROR_ROLE, + "An active xdg_surface already exists for wl_surface@%d", + wl_resource_get_id(surface->resource())); + return; + } + + if (!surface->setRole(QWaylandXdgSurfaceV5::role(), resource->handle, XDG_SHELL_ERROR_ROLE)) + return; + + QWaylandResource xdgSurfaceResource(wl_resource_create(resource->client(), &xdg_surface_interface, + wl_resource_get_version(resource->handle), id)); + + emit q->xdgSurfaceRequested(surface, xdgSurfaceResource); + + QWaylandXdgSurfaceV5 *xdgSurface = QWaylandXdgSurfaceV5::fromResource(xdgSurfaceResource.resource()); + if (!xdgSurface) { + // A QWaylandXdgSurfaceV5 was not created in response to the xdgSurfaceRequested signal, so we + // create one as fallback here instead. + xdgSurface = new QWaylandXdgSurfaceV5(q, surface, xdgSurfaceResource); + } + + registerSurface(xdgSurface); + emit q->xdgSurfaceCreated(xdgSurface); +} + +void QWaylandXdgShellV5Private::xdg_shell_use_unstable_version(Resource *resource, int32_t version) +{ + if (xdg_shell::version_current != version) { + wl_resource_post_error(resource->handle, WL_DISPLAY_ERROR_INVALID_OBJECT, + "incompatible version, server is %d, but client wants %d", + xdg_shell::version_current, version); + } +} + +void QWaylandXdgShellV5Private::xdg_shell_get_xdg_popup(Resource *resource, uint32_t id, + wl_resource *surface_res, wl_resource *parent, + wl_resource *seatResource, uint32_t serial, + int32_t x, int32_t y) +{ + Q_UNUSED(serial); + Q_Q(QWaylandXdgShellV5); + QWaylandSurface *surface = QWaylandSurface::fromResource(surface_res); + QWaylandSurface *parentSurface = QWaylandSurface::fromResource(parent); + + if (!isValidPopupParent(parentSurface)) { + wl_resource_post_error(resource->handle, XDG_SHELL_ERROR_INVALID_POPUP_PARENT, + "the client specified an invalid popup parent surface"); + return; + } + + if (!surface->setRole(QWaylandXdgPopupV5::role(), resource->handle, XDG_SHELL_ERROR_ROLE)) { + return; + } + + QWaylandResource xdgPopupResource (wl_resource_create(resource->client(), &xdg_popup_interface, + wl_resource_get_version(resource->handle), id)); + QWaylandSeat *seat = QWaylandSeat::fromSeatResource(seatResource); + QPoint position(x, y); + emit q->xdgPopupRequested(surface, parentSurface, seat, position, xdgPopupResource); + + QWaylandXdgPopupV5 *xdgPopup = QWaylandXdgPopupV5::fromResource(xdgPopupResource.resource()); + if (!xdgPopup) { + // A QWaylandXdgPopupV5 was not created in response to the xdgPopupRequested signal, so we + // create one as fallback here instead. + xdgPopup = new QWaylandXdgPopupV5(q, surface, parentSurface, position, xdgPopupResource); + } + + registerXdgPopup(xdgPopup); + emit q->xdgPopupCreated(xdgPopup); +} + +void QWaylandXdgShellV5Private::xdg_shell_pong(Resource *resource, uint32_t serial) +{ + Q_UNUSED(resource); + Q_Q(QWaylandXdgShellV5); + if (m_pings.remove(serial)) + emit q->pong(serial); + else + qWarning("Received an unexpected pong!"); +} + +QWaylandXdgSurfaceV5Private::QWaylandXdgSurfaceV5Private() + : QWaylandCompositorExtensionPrivate() + , xdg_surface() + , m_surface(nullptr) + , m_parentSurface(nullptr) + , m_windowType(UnknownWindowType) + , m_unsetWindowGeometry(true) + , m_lastAckedConfigure({{}, QSize(0, 0), 0}) +{ +} + +void QWaylandXdgSurfaceV5Private::handleFocusLost() +{ + Q_Q(QWaylandXdgSurfaceV5); + QWaylandXdgSurfaceV5Private::ConfigureEvent current = lastSentConfigure(); + current.states.removeOne(QWaylandXdgSurfaceV5::State::ActivatedState); + q->sendConfigure(current.size, current.states); +} + +void QWaylandXdgSurfaceV5Private::handleFocusReceived() +{ + Q_Q(QWaylandXdgSurfaceV5); + + QWaylandXdgSurfaceV5Private::ConfigureEvent current = lastSentConfigure(); + if (!current.states.contains(QWaylandXdgSurfaceV5::State::ActivatedState)) { + current.states.push_back(QWaylandXdgSurfaceV5::State::ActivatedState); + } + + q->sendConfigure(current.size, current.states); +} + +QRect QWaylandXdgSurfaceV5Private::calculateFallbackWindowGeometry() const +{ + // TODO: The unset window geometry should include subsurfaces as well, so this solution + // won't work too well on those kinds of clients. + return QRect(QPoint(0, 0), m_surface->size() / m_surface->bufferScale()); +} + +void QWaylandXdgSurfaceV5Private::updateFallbackWindowGeometry() +{ + Q_Q(QWaylandXdgSurfaceV5); + if (!m_unsetWindowGeometry) + return; + + const QRect unsetGeometry = calculateFallbackWindowGeometry(); + if (unsetGeometry == m_windowGeometry) + return; + + m_windowGeometry = unsetGeometry; + emit q->windowGeometryChanged(); +} + +void QWaylandXdgSurfaceV5Private::xdg_surface_destroy_resource(Resource *resource) +{ + Q_UNUSED(resource); + Q_Q(QWaylandXdgSurfaceV5); + QWaylandXdgShellV5Private::get(m_xdgShell)->unregisterXdgSurface(q); + delete q; +} + +void QWaylandXdgSurfaceV5Private::xdg_surface_destroy(Resource *resource) +{ + wl_resource_destroy(resource->handle); +} + +void QWaylandXdgSurfaceV5Private::xdg_surface_move(Resource *resource, wl_resource *seat, uint32_t serial) +{ + Q_UNUSED(resource); + Q_UNUSED(serial); + + Q_Q(QWaylandXdgSurfaceV5); + QWaylandSeat *input_device = QWaylandSeat::fromSeatResource(seat); + emit q->startMove(input_device); +} + +void QWaylandXdgSurfaceV5Private::xdg_surface_resize(Resource *resource, wl_resource *seat, + uint32_t serial, uint32_t edges) +{ + Q_UNUSED(resource); + Q_UNUSED(serial); + + Q_Q(QWaylandXdgSurfaceV5); + QWaylandSeat *input_device = QWaylandSeat::fromSeatResource(seat); + emit q->startResize(input_device, QWaylandXdgSurfaceV5::ResizeEdge(edges)); +} + +void QWaylandXdgSurfaceV5Private::xdg_surface_set_maximized(Resource *resource) +{ + Q_UNUSED(resource); + Q_Q(QWaylandXdgSurfaceV5); + emit q->setMaximized(); +} + +void QWaylandXdgSurfaceV5Private::xdg_surface_unset_maximized(Resource *resource) +{ + Q_UNUSED(resource); + Q_Q(QWaylandXdgSurfaceV5); + emit q->unsetMaximized(); +} + +void QWaylandXdgSurfaceV5Private::xdg_surface_set_fullscreen(Resource *resource, wl_resource *output_res) +{ + Q_UNUSED(resource); + Q_Q(QWaylandXdgSurfaceV5); + QWaylandOutput *output = output_res ? QWaylandOutput::fromResource(output_res) : nullptr; + emit q->setFullscreen(output); +} + +void QWaylandXdgSurfaceV5Private::xdg_surface_unset_fullscreen(Resource *resource) +{ + Q_UNUSED(resource); + Q_Q(QWaylandXdgSurfaceV5); + emit q->unsetFullscreen(); +} + +void QWaylandXdgSurfaceV5Private::xdg_surface_set_minimized(Resource *resource) +{ + Q_UNUSED(resource); + Q_Q(QWaylandXdgSurfaceV5); + emit q->setMinimized(); +} + +void QWaylandXdgSurfaceV5Private::xdg_surface_set_parent(Resource *resource, wl_resource *parent) +{ + Q_UNUSED(resource); + QWaylandXdgSurfaceV5 *parentSurface = nullptr; + if (parent) { + parentSurface = static_cast<QWaylandXdgSurfaceV5Private *>( + QWaylandXdgSurfaceV5Private::Resource::fromResource(parent)->xdg_surface_object)->q_func(); + } + + Q_Q(QWaylandXdgSurfaceV5); + + if (m_parentSurface != parentSurface) { + m_parentSurface = parentSurface; + emit q->parentSurfaceChanged(); + } + + if (m_parentSurface && m_windowType != TransientWindowType) { + // There's a parent now, which means the surface is transient + m_windowType = TransientWindowType; + emit q->setTransient(); + } else if (!m_parentSurface && m_windowType != TopLevelWindowType) { + // When the surface has no parent it is toplevel + m_windowType = TopLevelWindowType; + emit q->setTopLevel(); + } +} + +void QWaylandXdgSurfaceV5Private::xdg_surface_set_app_id(Resource *resource, const QString &app_id) +{ + Q_UNUSED(resource); + if (app_id == m_appId) + return; + Q_Q(QWaylandXdgSurfaceV5); + m_appId = app_id; + emit q->appIdChanged(); +} + +void QWaylandXdgSurfaceV5Private::xdg_surface_show_window_menu(Resource *resource, wl_resource *seatResource, + uint32_t serial, int32_t x, int32_t y) +{ + Q_UNUSED(resource); + Q_UNUSED(serial); + QPoint position(x, y); + auto seat = QWaylandSeat::fromSeatResource(seatResource); + Q_Q(QWaylandXdgSurfaceV5); + emit q->showWindowMenu(seat, position); +} + +void QWaylandXdgSurfaceV5Private::xdg_surface_ack_configure(Resource *resource, uint32_t serial) +{ + Q_UNUSED(resource); + Q_Q(QWaylandXdgSurfaceV5); + + ConfigureEvent config; + Q_FOREVER { + if (m_pendingConfigures.empty()) { + qWarning("Received an unexpected ack_configure!"); + return; + } + + config = m_pendingConfigures.takeFirst(); + + if (config.serial == serial) + break; + } + + QVector<uint> changedStates; + std::set_symmetric_difference( + m_lastAckedConfigure.states.begin(), m_lastAckedConfigure.states.end(), + config.states.begin(), config.states.end(), + std::back_inserter(changedStates)); + + m_lastAckedConfigure = config; + + if (!changedStates.empty()) { + Q_FOREACH (uint state, changedStates) { + switch (state) { + case QWaylandXdgSurfaceV5::State::MaximizedState: + emit q->maximizedChanged(); + break; + case QWaylandXdgSurfaceV5::State::FullscreenState: + emit q->fullscreenChanged(); + break; + case QWaylandXdgSurfaceV5::State::ResizingState: + emit q->resizingChanged(); + break; + case QWaylandXdgSurfaceV5::State::ActivatedState: + emit q->activatedChanged(); + break; + } + } + emit q->statesChanged(); + } + + emit q->ackConfigure(serial); +} + +void QWaylandXdgSurfaceV5Private::xdg_surface_set_title(Resource *resource, const QString &title) +{ + Q_UNUSED(resource); + if (title == m_title) + return; + Q_Q(QWaylandXdgSurfaceV5); + m_title = title; + emit q->titleChanged(); +} + +void QWaylandXdgSurfaceV5Private::xdg_surface_set_window_geometry(Resource *resource, + int32_t x, int32_t y, + int32_t width, int32_t height) +{ + Q_UNUSED(resource); + + if (width <= 0 || height <= 0) { + qWarning() << "Invalid (non-positive) dimensions received in set_window_geometry"; + return; + } + + m_unsetWindowGeometry = false; + + QRect geometry(x, y, width, height); + + Q_Q(QWaylandXdgSurfaceV5); + if ((q->maximized() || q->fullscreen()) && m_lastAckedConfigure.size != geometry.size()) + qWarning() << "Client window geometry did not obey last acked configure"; + + if (geometry == m_windowGeometry) + return; + + m_windowGeometry = geometry; + emit q->windowGeometryChanged(); +} + +QWaylandXdgPopupV5Private::QWaylandXdgPopupV5Private() + : QWaylandCompositorExtensionPrivate() + , xdg_popup() + , m_surface(nullptr) + , m_parentSurface(nullptr) + , m_xdgShell(nullptr) +{ +} + +void QWaylandXdgPopupV5Private::xdg_popup_destroy_resource(Resource *resource) +{ + Q_UNUSED(resource); + Q_Q(QWaylandXdgPopupV5); + QWaylandXdgShellV5Private::get(m_xdgShell)->unregisterXdgPopup(q); + delete q; +} + +void QWaylandXdgPopupV5Private::xdg_popup_destroy(Resource *resource) +{ + //TODO: post error if not topmost popup + wl_resource_destroy(resource->handle); +} + +/*! + * Constructs a QWaylandXdgShellV5 object. + */ +QWaylandXdgShellV5::QWaylandXdgShellV5() + : QWaylandShellTemplate<QWaylandXdgShellV5>(*new QWaylandXdgShellV5Private()) +{ } + +/*! + * Constructs a QWaylandXdgShellV5 object for the provided \a compositor. + */ +QWaylandXdgShellV5::QWaylandXdgShellV5(QWaylandCompositor *compositor) + : QWaylandShellTemplate<QWaylandXdgShellV5>(compositor, *new QWaylandXdgShellV5Private()) +{ } + +/*! + * Initializes the shell extension. + */ +void QWaylandXdgShellV5::initialize() +{ + Q_D(QWaylandXdgShellV5); + QWaylandShellTemplate::initialize(); + QWaylandCompositor *compositor = static_cast<QWaylandCompositor *>(extensionContainer()); + if (!compositor) { + qWarning() << "Failed to find QWaylandCompositor when initializing QWaylandXdgShellV5"; + return; + } + d->init(compositor->display(), 1); + + handleSeatChanged(compositor->defaultSeat(), nullptr); + + connect(compositor, &QWaylandCompositor::defaultSeatChanged, + this, &QWaylandXdgShellV5::handleSeatChanged); +} + +QWaylandClient *QWaylandXdgShellV5::popupClient() const +{ + Q_D(const QWaylandXdgShellV5); + Q_FOREACH (QWaylandXdgPopupV5 *popup, d->m_xdgPopups) { + if (popup->surface()->hasContent()) + return popup->surface()->client(); + } + return nullptr; +} + +/*! + * Returns the Wayland interface for the QWaylandXdgShellV5. + */ +const struct wl_interface *QWaylandXdgShellV5::interface() +{ + return QWaylandXdgShellV5Private::interface(); +} + +QByteArray QWaylandXdgShellV5::interfaceName() +{ + return QWaylandXdgShellV5Private::interfaceName(); +} + +/*! + * \qmlmethod void QtWaylandCompositor::XdgSurface::ping() + * + * Sends a ping event to the client. If the client replies to the event the + * \a pong signal will be emitted. + */ + +/*! + * Sends a ping event to the client. If the client replies to the event the + * \a pong signal will be emitted. + */ +uint QWaylandXdgShellV5::ping(QWaylandClient *client) +{ + Q_D(QWaylandXdgShellV5); + + QWaylandCompositor *compositor = static_cast<QWaylandCompositor *>(extensionContainer()); + Q_ASSERT(compositor); + + uint32_t serial = compositor->nextSerial(); + + QWaylandXdgShellV5Private::Resource *clientResource = d->resourceMap().value(client->client(), nullptr); + Q_ASSERT(clientResource); + + d->ping(clientResource, serial); + return serial; +} + +void QWaylandXdgShellV5::closeAllPopups() +{ + Q_D(QWaylandXdgShellV5); + Q_FOREACH (struct wl_client *client, d->m_xdgPopups.keys()) { + QList<QWaylandXdgPopupV5 *> popups = d->m_xdgPopups.values(client); + std::reverse(popups.begin(), popups.end()); + Q_FOREACH (QWaylandXdgPopupV5 *currentTopmostPopup, popups) { + currentTopmostPopup->sendPopupDone(); + } + } +} + +void QWaylandXdgShellV5::handleSeatChanged(QWaylandSeat *newSeat, QWaylandSeat *oldSeat) +{ + if (oldSeat != nullptr) { + disconnect(oldSeat, &QWaylandSeat::keyboardFocusChanged, + this, &QWaylandXdgShellV5::handleFocusChanged); + } + + if (newSeat != nullptr) { + connect(newSeat, &QWaylandSeat::keyboardFocusChanged, + this, &QWaylandXdgShellV5::handleFocusChanged); + } +} + +void QWaylandXdgShellV5::handleFocusChanged(QWaylandSurface *newSurface, QWaylandSurface *oldSurface) +{ + Q_D(QWaylandXdgShellV5); + + QWaylandXdgSurfaceV5 *newXdgSurface = d->xdgSurfaceFromSurface(newSurface); + QWaylandXdgSurfaceV5 *oldXdgSurface = d->xdgSurfaceFromSurface(oldSurface); + + if (newXdgSurface) + QWaylandXdgSurfaceV5Private::get(newXdgSurface)->handleFocusReceived(); + + if (oldXdgSurface) + QWaylandXdgSurfaceV5Private::get(oldXdgSurface)->handleFocusLost(); +} + +/*! + * \class QWaylandXdgSurfaceV5 + * \inmodule QtWaylandCompositor + * \since 5.8 + * \brief The QWaylandXdgSurfaceV5 class provides desktop-style compositor-specific features to an xdg surface. + * + * This class is part of the QWaylandXdgShellV5 extension and provides a way to + * extend the functionality of an existing QWaylandSurface with features + * specific to desktop-style compositors, such as resizing and moving the + * surface. + * + * It corresponds to the Wayland interface xdg_surface. + */ + +/*! + * \qmlsignal QtWaylandCompositor::XdgSurface::setTopLevel() + * + * This signal is emitted when the parent surface is unset, effectively + * making the window top level. + */ + +/*! + * \qmlsignal QtWaylandCompositor::XdgSurface::setTransient() + * + * This signal is emitted when the parent surface is set, effectively + * making the window transient. + */ + +/*! + * Constructs a QWaylandXdgSurfaceV5. + */ +QWaylandXdgSurfaceV5::QWaylandXdgSurfaceV5() + : QWaylandShellSurfaceTemplate<QWaylandXdgSurfaceV5>(*new QWaylandXdgSurfaceV5Private) +{ +} + +/*! + * Constructs a QWaylandXdgSurfaceV5 for \a surface and initializes it with the + * given \a xdgShell, \a surface, and resource \a res. + */ +QWaylandXdgSurfaceV5::QWaylandXdgSurfaceV5(QWaylandXdgShellV5 *xdgShell, QWaylandSurface *surface, const QWaylandResource &res) + : QWaylandShellSurfaceTemplate<QWaylandXdgSurfaceV5>(*new QWaylandXdgSurfaceV5Private) +{ + initialize(xdgShell, surface, res); +} + +/*! + * \qmlmethod void QtWaylandCompositor::XdgSurface::initialize(object surface, object client, int id) + * + * Initializes the XdgSurface, associating it with the given \a surface, + * \a client, and \a id. + */ + +/*! + * Initializes the QWaylandXdgSurfaceV5, associating it with the given \a xdgShell, \a surface + * and \a resource. + */ +void QWaylandXdgSurfaceV5::initialize(QWaylandXdgShellV5 *xdgShell, QWaylandSurface *surface, const QWaylandResource &resource) +{ + Q_D(QWaylandXdgSurfaceV5); + d->m_xdgShell = xdgShell; + d->m_surface = surface; + d->init(resource.resource()); + setExtensionContainer(surface); + d->m_windowGeometry = d->calculateFallbackWindowGeometry(); + connect(surface, &QWaylandSurface::sizeChanged, this, &QWaylandXdgSurfaceV5::handleSurfaceSizeChanged); + connect(surface, &QWaylandSurface::bufferScaleChanged, this, &QWaylandXdgSurfaceV5::handleBufferScaleChanged); + emit shellChanged(); + emit surfaceChanged(); + emit windowGeometryChanged(); + QWaylandCompositorExtension::initialize(); +} + +/*! + * \internal + */ +void QWaylandXdgSurfaceV5::initialize() +{ + QWaylandCompositorExtension::initialize(); +} + +QList<int> QWaylandXdgSurfaceV5::statesAsInts() const +{ + QList<int> list; + Q_FOREACH (uint state, states()) { + list << static_cast<int>(state); + } + return list; +} + +void QWaylandXdgSurfaceV5::handleSurfaceSizeChanged() +{ + Q_D(QWaylandXdgSurfaceV5); + d->updateFallbackWindowGeometry(); +} + +void QWaylandXdgSurfaceV5::handleBufferScaleChanged() +{ + Q_D(QWaylandXdgSurfaceV5); + d->updateFallbackWindowGeometry(); +} + +/*! + * \qmlproperty object QtWaylandCompositor::XdgSurface::shell + * + * This property holds the shell associated with this XdgSurface. + */ + +/*! + * \property QWaylandXdgSurfaceV5::shell + * + * This property holds the shell associated with this QWaylandXdgSurfaceV5. + */ +QWaylandXdgShellV5 *QWaylandXdgSurfaceV5::shell() const +{ + Q_D(const QWaylandXdgSurfaceV5); + return d->m_xdgShell; +} + +/*! + * \qmlproperty object QtWaylandCompositor::XdgSurface::surface + * + * This property holds the surface associated with this XdgSurface. + */ + +/*! + * \property QWaylandXdgSurfaceV5::surface + * + * This property holds the surface associated with this QWaylandXdgSurfaceV5. + */ +QWaylandSurface *QWaylandXdgSurfaceV5::surface() const +{ + Q_D(const QWaylandXdgSurfaceV5); + return d->m_surface; +} + +/*! + * \qmlproperty object QtWaylandCompositor::XdgSurface::parentSurface + * + * This property holds the XdgSurface parent of this XdgSurface. + * When a parent surface is set, the parentSurfaceChanged() signal + * is guaranteed to be emitted before setTopLevel() and setTransient(). + * + * \sa QtWaylandCompositor::XdgSurface::setTopLevel() + * \sa QtWaylandCompositor::XdgSurface::setTransient() + */ + +/*! + * \property QWaylandXdgSurfaceV5::parentSurface + * + * This property holds the XdgSurface parent of this XdgSurface. + * When a parent surface is set, the parentSurfaceChanged() signal + * is guaranteed to be emitted before setTopLevel() and setTransient(). + * + * \sa QWaylandXdgSurfaceV5::setTopLevel() + * \sa QWaylandXdgSurfaceV5::setTransient() + */ +QWaylandXdgSurfaceV5 *QWaylandXdgSurfaceV5::parentSurface() const +{ + Q_D(const QWaylandXdgSurfaceV5); + return d->m_parentSurface; +} + +/*! + * \qmlproperty string QtWaylandCompositor::XdgSurface::title + * + * This property holds the title of the XdgSurface. + */ + +/*! + * \property QWaylandXdgSurfaceV5::title + * + * This property holds the title of the QWaylandXdgSurfaceV5. + */ +QString QWaylandXdgSurfaceV5::title() const +{ + Q_D(const QWaylandXdgSurfaceV5); + return d->m_title; +} + +/*! + * \property QWaylandXdgSurfaceV5::appId + * + * This property holds the app id of the QWaylandXdgSurfaceV5. + */ +QString QWaylandXdgSurfaceV5::appId() const +{ + Q_D(const QWaylandXdgSurfaceV5); + return d->m_appId; +} + +/*! + * \property QWaylandXdgSurfaceV5::windowGeometry + * + * This property holds the window geometry of the QWaylandXdgSurfaceV5. The window + * geometry describes the window's visible bounds from the user's perspective. + * The geometry includes title bars and borders if drawn by the client, but + * excludes drop shadows. It is meant to be used for aligning and tiling + * windows. + */ +QRect QWaylandXdgSurfaceV5::windowGeometry() const +{ + Q_D(const QWaylandXdgSurfaceV5); + return d->m_windowGeometry; +} + +/*! + * \property QWaylandXdgSurfaceV5::states + * + * This property holds the last states the client acknowledged for this QWaylandXdgSurfaceV5. + */ +QVector<uint> QWaylandXdgSurfaceV5::states() const +{ + Q_D(const QWaylandXdgSurfaceV5); + return d->m_lastAckedConfigure.states; +} + +bool QWaylandXdgSurfaceV5::maximized() const +{ + Q_D(const QWaylandXdgSurfaceV5); + return d->m_lastAckedConfigure.states.contains(QWaylandXdgSurfaceV5::State::MaximizedState); +} + +bool QWaylandXdgSurfaceV5::fullscreen() const +{ + Q_D(const QWaylandXdgSurfaceV5); + return d->m_lastAckedConfigure.states.contains(QWaylandXdgSurfaceV5::State::FullscreenState); +} + +bool QWaylandXdgSurfaceV5::resizing() const +{ + Q_D(const QWaylandXdgSurfaceV5); + return d->m_lastAckedConfigure.states.contains(QWaylandXdgSurfaceV5::State::ResizingState); +} + +bool QWaylandXdgSurfaceV5::activated() const +{ + Q_D(const QWaylandXdgSurfaceV5); + return d->m_lastAckedConfigure.states.contains(QWaylandXdgSurfaceV5::State::ActivatedState); +} + +/*! + * Returns the Wayland interface for the QWaylandXdgSurfaceV5. + */ +const wl_interface *QWaylandXdgSurfaceV5::interface() +{ + return QWaylandXdgSurfaceV5Private::interface(); +} + +QByteArray QWaylandXdgSurfaceV5::interfaceName() +{ + return QWaylandXdgSurfaceV5Private::interfaceName(); +} + +/*! + * Returns the surface role for the QWaylandXdgSurfaceV5. + */ +QWaylandSurfaceRole *QWaylandXdgSurfaceV5::role() +{ + return &QWaylandXdgSurfaceV5Private::s_role; +} + +/*! + * Returns the QWaylandXdgSurfaceV5 corresponding to the \a resource. + */ +QWaylandXdgSurfaceV5 *QWaylandXdgSurfaceV5::fromResource(wl_resource *resource) +{ + auto xsResource = QWaylandXdgSurfaceV5Private::Resource::fromResource(resource); + if (!xsResource) + return nullptr; + return static_cast<QWaylandXdgSurfaceV5Private *>(xsResource->xdg_surface_object)->q_func(); +} + +QSize QWaylandXdgSurfaceV5::sizeForResize(const QSizeF &size, const QPointF &delta, + QWaylandXdgSurfaceV5::ResizeEdge edge) +{ + qreal width = size.width(); + qreal height = size.height(); + if (edge & LeftEdge) + width -= delta.x(); + else if (edge & RightEdge) + width += delta.x(); + + if (edge & TopEdge) + height -= delta.y(); + else if (edge & BottomEdge) + height += delta.y(); + + return QSizeF(width, height).toSize(); +} + +/*! + * \qmlmethod int QtWaylandCompositor::XdgSurface::sendConfigure(size size, list<uint> states) + * + * Sends a configure event to the client. \a size contains the pixel size of the surface. + * Known \a states are enumerated in XdgSurface::State. + */ + +/*! + * Sends a configure event to the client. Parameter \a size contains the pixel size + * of the surface. Known \a states are enumerated in QWaylandXdgSurfaceV5::State. + */ +uint QWaylandXdgSurfaceV5::sendConfigure(const QSize &size, const QVector<uint> &states) +{ + Q_D(QWaylandXdgSurfaceV5); + auto statesBytes = QByteArray::fromRawData((char *)states.data(), states.size() * sizeof(State)); + QWaylandSurface *surface = qobject_cast<QWaylandSurface *>(extensionContainer()); + Q_ASSERT(surface); + QWaylandCompositor *compositor = surface->compositor(); + Q_ASSERT(compositor); + uint32_t serial = compositor->nextSerial(); + d->m_pendingConfigures.append(QWaylandXdgSurfaceV5Private::ConfigureEvent{states, size, serial}); + d->send_configure(size.width(), size.height(), statesBytes, serial); + return serial; +} + +uint QWaylandXdgSurfaceV5::sendConfigure(const QSize &size, const QVector<QWaylandXdgSurfaceV5::State> &states) +{ + QVector<uint> asUints; + Q_FOREACH (QWaylandXdgSurfaceV5::State state, states) { + asUints << state; + } + return sendConfigure(size, asUints); +} + +/*! + * \qmlmethod void QtWaylandCompositor::XdgSurface::sendClose() + * + * Sends a close event to the client. + */ + +/*! + * Sends a close event to the client. + */ +void QWaylandXdgSurfaceV5::sendClose() +{ + Q_D(QWaylandXdgSurfaceV5); + d->send_close(); +} + +uint QWaylandXdgSurfaceV5::sendMaximized(const QSize &size) +{ + Q_D(QWaylandXdgSurfaceV5); + QWaylandXdgSurfaceV5Private::ConfigureEvent conf = d->lastSentConfigure(); + + if (!conf.states.contains(QWaylandXdgSurfaceV5::State::MaximizedState)) + conf.states.append(QWaylandXdgSurfaceV5::State::MaximizedState); + conf.states.removeOne(QWaylandXdgSurfaceV5::State::FullscreenState); + conf.states.removeOne(QWaylandXdgSurfaceV5::State::ResizingState); + + return sendConfigure(size, conf.states); +} + +uint QWaylandXdgSurfaceV5::sendUnmaximized(const QSize &size) +{ + Q_D(QWaylandXdgSurfaceV5); + QWaylandXdgSurfaceV5Private::ConfigureEvent conf = d->lastSentConfigure(); + + conf.states.removeOne(QWaylandXdgSurfaceV5::State::MaximizedState); + conf.states.removeOne(QWaylandXdgSurfaceV5::State::FullscreenState); + conf.states.removeOne(QWaylandXdgSurfaceV5::State::ResizingState); + + return sendConfigure(size, conf.states); +} + +uint QWaylandXdgSurfaceV5::sendFullscreen(const QSize &size) +{ + Q_D(QWaylandXdgSurfaceV5); + QWaylandXdgSurfaceV5Private::ConfigureEvent conf = d->lastSentConfigure(); + + if (!conf.states.contains(QWaylandXdgSurfaceV5::State::FullscreenState)) + conf.states.append(QWaylandXdgSurfaceV5::State::FullscreenState); + conf.states.removeOne(QWaylandXdgSurfaceV5::State::MaximizedState); + conf.states.removeOne(QWaylandXdgSurfaceV5::State::ResizingState); + + return sendConfigure(size, conf.states); +} + +uint QWaylandXdgSurfaceV5::sendResizing(const QSize &maxSize) +{ + Q_D(QWaylandXdgSurfaceV5); + QWaylandXdgSurfaceV5Private::ConfigureEvent conf = d->lastSentConfigure(); + + if (!conf.states.contains(QWaylandXdgSurfaceV5::State::ResizingState)) + conf.states.append(QWaylandXdgSurfaceV5::State::ResizingState); + conf.states.removeOne(QWaylandXdgSurfaceV5::State::MaximizedState); + conf.states.removeOne(QWaylandXdgSurfaceV5::State::FullscreenState); + + return sendConfigure(maxSize, conf.states); +} + +#ifdef QT_WAYLAND_COMPOSITOR_QUICK +QWaylandQuickShellIntegration *QWaylandXdgSurfaceV5::createIntegration(QWaylandQuickShellSurfaceItem *item) +{ + return new QtWayland::XdgShellV5Integration(item); +} +#endif + +/*! + * \class QWaylandXdgPopupV5 + * \inmodule QtWaylandCompositor + * \since 5.8 + * \brief The QWaylandXdgPopupV5 class provides menus for an xdg surface + * + * This class is part of the QWaylandXdgShellV5 extension and provides a way to + * extend the functionality of an existing QWaylandSurface with features + * specific to desktop-style menus for an xdg surface. + * + * It corresponds to the Wayland interface xdg_popup. + */ + +/*! + * Constructs a QWaylandXdgPopupV5. + */ +QWaylandXdgPopupV5::QWaylandXdgPopupV5() + : QWaylandShellSurfaceTemplate<QWaylandXdgPopupV5>(*new QWaylandXdgPopupV5Private) +{ +} + +/*! + * Constructs a QWaylandXdgPopupV5, associating it with \a xdgShell at the specified \a position + * for \a surface and initializes it with the given \a parentSurface and \a resource. + */ +QWaylandXdgPopupV5::QWaylandXdgPopupV5(QWaylandXdgShellV5 *xdgShell, QWaylandSurface *surface, + QWaylandSurface *parentSurface, const QPoint &position, const QWaylandResource &resource) + : QWaylandShellSurfaceTemplate<QWaylandXdgPopupV5>(*new QWaylandXdgPopupV5Private) +{ + initialize(xdgShell, surface, parentSurface, position, resource); +} + +/*! + * \qmlmethod void QtWaylandCompositor::XdgPopup::initialize(object surface, object parentSurface, object resource) + * + * Initializes the xdg popup, associating it with the given \a shell, \a surface, + * \a parentSurface and \a resource. + */ + +/*! + * Initializes the QWaylandXdgPopupV5, associating it with the given \a shell \a surface, + * \a parentSurface and \a resource. + */ +void QWaylandXdgPopupV5::initialize(QWaylandXdgShellV5 *shell, QWaylandSurface *surface, QWaylandSurface *parentSurface, + const QPoint& position, const QWaylandResource &resource) +{ + Q_D(QWaylandXdgPopupV5); + d->m_surface = surface; + d->m_parentSurface = parentSurface; + d->m_xdgShell = shell; + d->m_position = position; + d->init(resource.resource()); + setExtensionContainer(surface); + emit shellChanged(); + emit surfaceChanged(); + emit parentSurfaceChanged(); + QWaylandCompositorExtension::initialize(); +} + +/*! + * \qmlproperty object QtWaylandCompositor::XdgPopup::shell + * + * This property holds the shell associated with this XdgPopup. + */ + +/*! + * \property QWaylandXdgPopupV5::shell + * + * This property holds the shell associated with this QWaylandXdgPopupV5. + */ +QWaylandXdgShellV5 *QWaylandXdgPopupV5::shell() const +{ + Q_D(const QWaylandXdgPopupV5); + return d->m_xdgShell; +} + +/*! + * \qmlproperty object QtWaylandCompositor::XdgPopup::surface + * + * This property holds the surface associated with this XdgPopup. + */ + +/*! + * \property QWaylandXdgPopupV5::surface + * + * This property holds the surface associated with this QWaylandXdgPopupV5. + */ +QWaylandSurface *QWaylandXdgPopupV5::surface() const +{ + Q_D(const QWaylandXdgPopupV5); + return d->m_surface; +} + +/*! + * \qmlproperty object QtWaylandCompositor::XdgPopup::parentSurface + * + * This property holds the surface associated with the parent of this XdgPopup. + */ + +/*! + * \property QWaylandXdgPopupV5::parentSurface + * + * This property holds the surface associated with the parent of this + * QWaylandXdgPopupV5. + */ +QWaylandSurface *QWaylandXdgPopupV5::parentSurface() const +{ + Q_D(const QWaylandXdgPopupV5); + return d->m_parentSurface; +} + + +/*! + * \qmlproperty object QtWaylandCompositor::XdgPopup::position + * + * This property holds the location of the upper left corner of the surface + * relative to the upper left corner of the parent surface, in surface local + * coordinates. + */ + +/*! + * \property QWaylandXdgPopupV5::position + * + * This property holds the location of the upper left corner of the surface + * relative to the upper left corner of the parent surface, in surface local + * coordinates. + */ +QPoint QWaylandXdgPopupV5::position() const +{ + Q_D(const QWaylandXdgPopupV5); + return d->m_position; +} + +/*! + * \internal + */ +void QWaylandXdgPopupV5::initialize() +{ + QWaylandCompositorExtension::initialize(); +} + +/*! + * Returns the Wayland interface for the QWaylandXdgPopupV5. + */ +const wl_interface *QWaylandXdgPopupV5::interface() +{ + return QWaylandXdgPopupV5Private::interface(); +} + +QByteArray QWaylandXdgPopupV5::interfaceName() +{ + return QWaylandXdgPopupV5Private::interfaceName(); +} + +/*! + * Returns the surface role for the QWaylandXdgPopupV5. + */ +QWaylandSurfaceRole *QWaylandXdgPopupV5::role() +{ + return &QWaylandXdgPopupV5Private::s_role; +} + +QWaylandXdgPopupV5 *QWaylandXdgPopupV5::fromResource(wl_resource *resource) +{ + auto popupResource = QWaylandXdgPopupV5Private::Resource::fromResource(resource); + if (!popupResource) + return nullptr; + return static_cast<QWaylandXdgPopupV5Private *>(popupResource->xdg_popup_object)->q_func(); +} + +void QWaylandXdgPopupV5::sendPopupDone() +{ + Q_D(QWaylandXdgPopupV5); + d->send_popup_done(); +} + +#ifdef QT_WAYLAND_COMPOSITOR_QUICK +QWaylandQuickShellIntegration *QWaylandXdgPopupV5::createIntegration(QWaylandQuickShellSurfaceItem *item) +{ + return new QtWayland::XdgPopupV5Integration(item); +} +#endif + +QT_END_NAMESPACE diff --git a/src/compositor/extensions/qwaylandxdgshell.h b/src/compositor/extensions/qwaylandxdgshellv5.h index c11ca1f3a..bcc740c7d 100644 --- a/src/compositor/extensions/qwaylandxdgshell.h +++ b/src/compositor/extensions/qwaylandxdgshellv5.h @@ -34,11 +34,12 @@ ** ****************************************************************************/ -#ifndef QWAYLANDXDGSHELL_H -#define QWAYLANDXDGSHELL_H +#ifndef QWAYLANDXDGSHELLV5_H +#define QWAYLANDXDGSHELLV5_H #include <QtWaylandCompositor/QWaylandCompositorExtension> #include <QtWaylandCompositor/QWaylandResource> +#include <QtWaylandCompositor/QWaylandShell> #include <QtWaylandCompositor/QWaylandShellSurface> #include <QtCore/QRect> @@ -47,27 +48,28 @@ struct wl_resource; QT_BEGIN_NAMESPACE -class QWaylandXdgShellPrivate; -class QWaylandXdgSurface; -class QWaylandXdgSurfacePrivate; -class QWaylandXdgPopup; -class QWaylandXdgPopupPrivate; +class QWaylandXdgShellV5Private; +class QWaylandXdgSurfaceV5; +class QWaylandXdgSurfaceV5Private; +class QWaylandXdgPopupV5; +class QWaylandXdgPopupV5Private; class QWaylandSurface; class QWaylandSurfaceRole; -class QWaylandInputDevice; +class QWaylandSeat; class QWaylandOutput; class QWaylandClient; -class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandXdgShell : public QWaylandCompositorExtensionTemplate<QWaylandXdgShell> +class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandXdgShellV5 : public QWaylandShellTemplate<QWaylandXdgShellV5> { Q_OBJECT - Q_DECLARE_PRIVATE(QWaylandXdgShell) + Q_DECLARE_PRIVATE(QWaylandXdgShellV5) public: - QWaylandXdgShell(); - QWaylandXdgShell(QWaylandCompositor *compositor); + QWaylandXdgShellV5(); + QWaylandXdgShellV5(QWaylandCompositor *compositor); void initialize() Q_DECL_OVERRIDE; + QWaylandClient *popupClient() const; static const struct wl_interface *interface(); static QByteArray interfaceName(); @@ -77,24 +79,25 @@ public Q_SLOTS: void closeAllPopups(); Q_SIGNALS: - void createXdgSurface(QWaylandSurface *surface, const QWaylandResource &resource); - void xdgSurfaceCreated(QWaylandXdgSurface *xdgSurface); - void xdgPopupCreated(QWaylandXdgPopup *xdgPopup); - void createXdgPopup(QWaylandSurface *surface, QWaylandSurface *parent, QWaylandInputDevice *seat, const QPoint &position, const QWaylandResource &resource); + void xdgSurfaceRequested(QWaylandSurface *surface, const QWaylandResource &resource); + void xdgSurfaceCreated(QWaylandXdgSurfaceV5 *xdgSurface); + void xdgPopupCreated(QWaylandXdgPopupV5 *xdgPopup); + void xdgPopupRequested(QWaylandSurface *surface, QWaylandSurface *parent, QWaylandSeat *seat, const QPoint &position, const QWaylandResource &resource); void pong(uint serial); private Q_SLOTS: - void handleDefaultInputDeviceChanged(QWaylandInputDevice *newDevice, QWaylandInputDevice *oldDevice); + void handleSeatChanged(QWaylandSeat *newSeat, QWaylandSeat *oldSeat); void handleFocusChanged(QWaylandSurface *newSurface, QWaylandSurface *oldSurface); }; -class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandXdgSurface : public QWaylandShellSurfaceTemplate<QWaylandXdgSurface> +class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandXdgSurfaceV5 : public QWaylandShellSurfaceTemplate<QWaylandXdgSurfaceV5> { Q_OBJECT - Q_DECLARE_PRIVATE(QWaylandXdgSurface) + Q_DECLARE_PRIVATE(QWaylandXdgSurfaceV5) + Q_PROPERTY(QWaylandXdgShellV5 *shell READ shell NOTIFY shellChanged) Q_PROPERTY(QWaylandSurface *surface READ surface NOTIFY surfaceChanged) - Q_PROPERTY(QWaylandXdgSurface *parentSurface READ parentSurface NOTIFY parentSurfaceChanged) + Q_PROPERTY(QWaylandXdgSurfaceV5 *parentSurface READ parentSurface NOTIFY parentSurfaceChanged) Q_PROPERTY(QString title READ title NOTIFY titleChanged) Q_PROPERTY(QString appId READ appId NOTIFY appIdChanged) Q_PROPERTY(QRect windowGeometry READ windowGeometry NOTIFY windowGeometryChanged) @@ -127,10 +130,10 @@ public: }; Q_ENUM(ResizeEdge) - QWaylandXdgSurface(); - QWaylandXdgSurface(QWaylandXdgShell* xdgShell, QWaylandSurface *surface, const QWaylandResource &resource); + QWaylandXdgSurfaceV5(); + QWaylandXdgSurfaceV5(QWaylandXdgShellV5* xdgShell, QWaylandSurface *surface, const QWaylandResource &resource); - Q_INVOKABLE void initialize(QWaylandXdgShell* xdgShell, QWaylandSurface *surface, const QWaylandResource &resource); + Q_INVOKABLE void initialize(QWaylandXdgShellV5* xdgShell, QWaylandSurface *surface, const QWaylandResource &resource); QString title() const; QString appId() const; @@ -141,27 +144,32 @@ public: bool resizing() const; bool activated() const; + QWaylandXdgShellV5 *shell() const; + QWaylandSurface *surface() const; - QWaylandXdgSurface *parentSurface() const; + QWaylandXdgSurfaceV5 *parentSurface() const; static const struct wl_interface *interface(); static QByteArray interfaceName(); static QWaylandSurfaceRole *role(); - static QWaylandXdgSurface *fromResource(::wl_resource *resource); + static QWaylandXdgSurfaceV5 *fromResource(::wl_resource *resource); Q_INVOKABLE QSize sizeForResize(const QSizeF &size, const QPointF &delta, ResizeEdge edge); Q_INVOKABLE uint sendConfigure(const QSize &size, const QVector<uint> &states); Q_INVOKABLE uint sendConfigure(const QSize &size, const QVector<State> &states); Q_INVOKABLE void sendClose(); - Q_INVOKABLE uint requestMaximized(const QSize &size); - Q_INVOKABLE uint requestUnMaximized(const QSize &size = QSize(0, 0)); - Q_INVOKABLE uint requestFullscreen(const QSize &size); - Q_INVOKABLE uint requestResizing(const QSize &maxSize); + Q_INVOKABLE uint sendMaximized(const QSize &size); + Q_INVOKABLE uint sendUnmaximized(const QSize &size = QSize(0, 0)); + Q_INVOKABLE uint sendFullscreen(const QSize &size); + Q_INVOKABLE uint sendResizing(const QSize &maxSize); +#ifdef QT_WAYLAND_COMPOSITOR_QUICK QWaylandQuickShellIntegration *createIntegration(QWaylandQuickShellSurfaceItem *item) Q_DECL_OVERRIDE; +#endif Q_SIGNALS: + void shellChanged(); void surfaceChanged(); void titleChanged(); void windowGeometryChanged(); @@ -174,9 +182,11 @@ Q_SIGNALS: void resizingChanged(); void activatedChanged(); - void showWindowMenu(QWaylandInputDevice *inputDevice, const QPoint &localSurfacePosition); - void startMove(QWaylandInputDevice *inputDevice); - void startResize(QWaylandInputDevice *inputDevice, ResizeEdge edges); + void showWindowMenu(QWaylandSeat *seat, const QPoint &localSurfacePosition); + void startMove(QWaylandSeat *seat); + void startResize(QWaylandSeat *seat, ResizeEdge edges); + void setTopLevel(); + void setTransient(); void setMaximized(); void unsetMaximized(); void setFullscreen(QWaylandOutput *output); @@ -190,33 +200,47 @@ private: private Q_SLOTS: void handleSurfaceSizeChanged(); + void handleBufferScaleChanged(); }; -class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandXdgPopup : public QWaylandCompositorExtensionTemplate<QWaylandXdgPopup> +class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandXdgPopupV5 : public QWaylandShellSurfaceTemplate<QWaylandXdgPopupV5> { Q_OBJECT - Q_DECLARE_PRIVATE(QWaylandXdgPopup) + Q_DECLARE_PRIVATE(QWaylandXdgPopupV5) + Q_PROPERTY(QWaylandXdgShellV5 *shell READ shell NOTIFY shellChanged) Q_PROPERTY(QWaylandSurface *surface READ surface NOTIFY surfaceChanged) Q_PROPERTY(QWaylandSurface *parentSurface READ parentSurface NOTIFY parentSurfaceChanged) + Q_PROPERTY(QPoint position READ position) public: - QWaylandXdgPopup(); - QWaylandXdgPopup(QWaylandXdgShell *xdgShell, QWaylandSurface *surface, QWaylandSurface *parentSurface, const QWaylandResource &resource); + QWaylandXdgPopupV5(); + QWaylandXdgPopupV5(QWaylandXdgShellV5 *xdgShell, QWaylandSurface *surface, QWaylandSurface *parentSurface, + const QPoint &position, const QWaylandResource &resource); + + Qt::WindowType windowType() const override { return Qt::WindowType::Popup; } + + Q_INVOKABLE void initialize(QWaylandXdgShellV5 *shell, QWaylandSurface *surface, + QWaylandSurface *parentSurface, const QPoint &position, const QWaylandResource &resource); - Q_INVOKABLE void initialize(QWaylandXdgShell *shell, QWaylandSurface *surface, - QWaylandSurface *parentSurface, const QWaylandResource &resource); + QWaylandXdgShellV5 *shell() const; QWaylandSurface *surface() const; QWaylandSurface *parentSurface() const; + QPoint position() const; static const struct wl_interface *interface(); static QByteArray interfaceName(); static QWaylandSurfaceRole *role(); - static QWaylandXdgPopup *fromResource(::wl_resource *resource); + static QWaylandXdgPopupV5 *fromResource(::wl_resource *resource); Q_INVOKABLE void sendPopupDone(); +#ifdef QT_WAYLAND_COMPOSITOR_QUICK + QWaylandQuickShellIntegration *createIntegration(QWaylandQuickShellSurfaceItem *item) Q_DECL_OVERRIDE; +#endif + Q_SIGNALS: + void shellChanged(); void surfaceChanged(); void parentSurfaceChanged(); diff --git a/src/compositor/extensions/qwaylandxdgshell_p.h b/src/compositor/extensions/qwaylandxdgshellv5_p.h index 3165eb7ca..31aa2112c 100644 --- a/src/compositor/extensions/qwaylandxdgshell_p.h +++ b/src/compositor/extensions/qwaylandxdgshellv5_p.h @@ -34,13 +34,13 @@ ** ****************************************************************************/ -#ifndef QWAYLANDXDGSHELL_P_H -#define QWAYLANDXDGSHELL_P_H +#ifndef QWAYLANDXDGSHELLV5_P_H +#define QWAYLANDXDGSHELLV5_P_H #include <QtWaylandCompositor/private/qwaylandcompositorextension_p.h> #include <QtWaylandCompositor/private/qwayland-server-xdg-shell.h> -#include <QtWaylandCompositor/QWaylandXdgShell> +#include <QtWaylandCompositor/QWaylandXdgShellV5> #include <QtCore/QSet> @@ -57,47 +57,53 @@ QT_BEGIN_NAMESPACE -class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandXdgShellPrivate +class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandXdgShellV5Private : public QWaylandCompositorExtensionPrivate , public QtWaylandServer::xdg_shell { - Q_DECLARE_PUBLIC(QWaylandXdgShell) + Q_DECLARE_PUBLIC(QWaylandXdgShellV5) public: - QWaylandXdgShellPrivate(); + QWaylandXdgShellV5Private(); void ping(Resource *resource, uint32_t serial); - void registerSurface(QWaylandXdgSurface *xdgSurface); - void unregisterXdgSurface(QWaylandXdgSurface *xdgSurface); - void registerXdgPopup(QWaylandXdgPopup *xdgPopup); - void unregisterXdgPopup(QWaylandXdgPopup *xdgPopup); - static QWaylandXdgShellPrivate *get(QWaylandXdgShell *xdgShell) { return xdgShell->d_func(); } + void registerSurface(QWaylandXdgSurfaceV5 *xdgSurface); + void unregisterXdgSurface(QWaylandXdgSurfaceV5 *xdgSurface); + void registerXdgPopup(QWaylandXdgPopupV5 *xdgPopup); + void unregisterXdgPopup(QWaylandXdgPopupV5 *xdgPopup); + static QWaylandXdgShellV5Private *get(QWaylandXdgShellV5 *xdgShell) { return xdgShell->d_func(); } bool isValidPopupParent(QWaylandSurface *parentSurface) const; - QWaylandXdgPopup *topmostPopupForClient(struct wl_client* client) const; + QWaylandXdgPopupV5 *topmostPopupForClient(struct wl_client* client) const; -private: QSet<uint32_t> m_pings; - QMultiMap<struct wl_client *, QWaylandXdgSurface *> m_xdgSurfaces; - QMultiMap<struct wl_client *, QWaylandXdgPopup *> m_xdgPopups; + QMultiMap<struct wl_client *, QWaylandXdgSurfaceV5 *> m_xdgSurfaces; + QMultiMap<struct wl_client *, QWaylandXdgPopupV5 *> m_xdgPopups; - QWaylandXdgSurface *xdgSurfaceFromSurface(QWaylandSurface *surface); + QWaylandXdgSurfaceV5 *xdgSurfaceFromSurface(QWaylandSurface *surface); +protected: void xdg_shell_destroy(Resource *resource) Q_DECL_OVERRIDE; void xdg_shell_get_xdg_surface(Resource *resource, uint32_t id, struct ::wl_resource *surface) Q_DECL_OVERRIDE; void xdg_shell_use_unstable_version(Resource *resource, int32_t version) Q_DECL_OVERRIDE; void xdg_shell_get_xdg_popup(Resource *resource, uint32_t id, struct ::wl_resource *surface, - struct ::wl_resource *parent, struct ::wl_resource *seat, + struct ::wl_resource *parent, struct ::wl_resource *seatResource, uint32_t serial, int32_t x, int32_t y) Q_DECL_OVERRIDE; void xdg_shell_pong(Resource *resource, uint32_t serial) Q_DECL_OVERRIDE; }; -class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandXdgSurfacePrivate +class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandXdgSurfaceV5Private : public QWaylandCompositorExtensionPrivate , public QtWaylandServer::xdg_surface { - Q_DECLARE_PUBLIC(QWaylandXdgSurface) + Q_DECLARE_PUBLIC(QWaylandXdgSurfaceV5) public: - QWaylandXdgSurfacePrivate(); - static QWaylandXdgSurfacePrivate *get(QWaylandXdgSurface *xdgSurface) { return xdgSurface->d_func(); } + QWaylandXdgSurfaceV5Private(); + static QWaylandXdgSurfaceV5Private *get(QWaylandXdgSurfaceV5 *xdgSurface) { return xdgSurface->d_func(); } + + enum WindowType { + UnknownWindowType, + TopLevelWindowType, + TransientWindowType + }; struct ConfigureEvent { QVector<uint> states; @@ -107,11 +113,15 @@ public: void handleFocusLost(); void handleFocusReceived(); + QRect calculateFallbackWindowGeometry() const; + void updateFallbackWindowGeometry(); private: - QWaylandXdgShell *m_xdgShell; + QWaylandXdgShellV5 *m_xdgShell; QWaylandSurface *m_surface; - QWaylandXdgSurface *m_parentSurface; + QWaylandXdgSurfaceV5 *m_parentSurface; + + WindowType m_windowType; QString m_title; QString m_appId; @@ -137,7 +147,7 @@ private: void xdg_surface_set_minimized(Resource *resource) Q_DECL_OVERRIDE; void xdg_surface_set_parent(Resource *resource, struct ::wl_resource *parent) Q_DECL_OVERRIDE; void xdg_surface_set_app_id(Resource *resource, const QString &app_id) Q_DECL_OVERRIDE; - void xdg_surface_show_window_menu(Resource *resource, struct ::wl_resource *seat, + void xdg_surface_show_window_menu(Resource *resource, struct ::wl_resource *seatResource, uint32_t serial, int32_t x, int32_t y) Q_DECL_OVERRIDE; void xdg_surface_ack_configure(Resource *resource, uint32_t serial) Q_DECL_OVERRIDE; void xdg_surface_set_title(Resource *resource, const QString &title) Q_DECL_OVERRIDE; @@ -147,20 +157,20 @@ private: static QWaylandSurfaceRole s_role; }; -class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandXdgPopupPrivate +class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandXdgPopupV5Private : public QWaylandCompositorExtensionPrivate , public QtWaylandServer::xdg_popup { - Q_DECLARE_PUBLIC(QWaylandXdgPopup) + Q_DECLARE_PUBLIC(QWaylandXdgPopupV5) public: - QWaylandXdgPopupPrivate(); - static QWaylandXdgPopupPrivate *get(QWaylandXdgPopup *xdgPopup) { return xdgPopup->d_func(); } + QWaylandXdgPopupV5Private(); + static QWaylandXdgPopupV5Private *get(QWaylandXdgPopupV5 *xdgPopup) { return xdgPopup->d_func(); } -private: QWaylandSurface *m_surface; QWaylandSurface *m_parentSurface; - QWaylandXdgShell *m_xdgShell; + QWaylandXdgShellV5 *m_xdgShell; + QPoint m_position; void xdg_popup_destroy_resource(Resource *resource) Q_DECL_OVERRIDE; void xdg_popup_destroy(xdg_popup::Resource *resource) Q_DECL_OVERRIDE; diff --git a/src/compositor/extensions/qwaylandxdgshellv5integration.cpp b/src/compositor/extensions/qwaylandxdgshellv5integration.cpp new file mode 100644 index 000000000..b3170333f --- /dev/null +++ b/src/compositor/extensions/qwaylandxdgshellv5integration.cpp @@ -0,0 +1,215 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWaylandCompositor module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwaylandxdgshellv5integration_p.h" + +#include <QtWaylandCompositor/QWaylandQuickShellSurfaceItem> +#include <QtWaylandCompositor/QWaylandCompositor> +#include <QtWaylandCompositor/QWaylandSeat> +#include <QtWaylandCompositor/private/qwaylandxdgshellv5_p.h> +#include <QMouseEvent> +#include <QGuiApplication> + +QT_BEGIN_NAMESPACE + +namespace QtWayland { + +XdgShellV5Integration::XdgShellV5Integration(QWaylandQuickShellSurfaceItem *item) + : QWaylandQuickShellIntegration(item) + , m_item(item) + , m_xdgSurface(qobject_cast<QWaylandXdgSurfaceV5 *>(item->shellSurface())) + , grabberState(GrabberState::Default) +{ + m_item->setSurface(m_xdgSurface->surface()); + connect(m_xdgSurface, &QWaylandXdgSurfaceV5::startMove, this, &XdgShellV5Integration::handleStartMove); + connect(m_xdgSurface, &QWaylandXdgSurfaceV5::startResize, this, &XdgShellV5Integration::handleStartResize); + connect(m_xdgSurface, &QWaylandXdgSurfaceV5::setTopLevel, this, &XdgShellV5Integration::handleSetTopLevel); + connect(m_xdgSurface, &QWaylandXdgSurfaceV5::setTransient, this, &XdgShellV5Integration::handleSetTransient); + connect(m_xdgSurface, &QWaylandXdgSurfaceV5::setMaximized, this, &XdgShellV5Integration::handleSetMaximized); + connect(m_xdgSurface, &QWaylandXdgSurfaceV5::unsetMaximized, this, &XdgShellV5Integration::handleUnsetMaximized); + connect(m_xdgSurface, &QWaylandXdgSurfaceV5::maximizedChanged, this, &XdgShellV5Integration::handleMaximizedChanged); + connect(m_xdgSurface, &QWaylandXdgSurfaceV5::activatedChanged, this, &XdgShellV5Integration::handleActivatedChanged); + connect(m_xdgSurface->surface(), &QWaylandSurface::sizeChanged, this, &XdgShellV5Integration::handleSurfaceSizeChanged); +} + +bool XdgShellV5Integration::mouseMoveEvent(QMouseEvent *event) +{ + if (grabberState == GrabberState::Resize) { + Q_ASSERT(resizeState.seat == m_item->compositor()->seatFor(event)); + if (!resizeState.initialized) { + resizeState.initialMousePos = event->windowPos(); + resizeState.initialized = true; + return true; + } + QPointF delta = m_item->mapToSurface(event->windowPos() - resizeState.initialMousePos); + QSize newSize = m_xdgSurface->sizeForResize(resizeState.initialWindowSize, delta, resizeState.resizeEdges); + m_xdgSurface->sendResizing(newSize); + } else if (grabberState == GrabberState::Move) { + Q_ASSERT(moveState.seat == m_item->compositor()->seatFor(event)); + QQuickItem *moveItem = m_item->moveItem(); + if (!moveState.initialized) { + moveState.initialOffset = moveItem->mapFromItem(nullptr, event->windowPos()); + moveState.initialized = true; + return true; + } + if (!moveItem->parentItem()) + return true; + QPointF parentPos = moveItem->parentItem()->mapFromItem(nullptr, event->windowPos()); + moveItem->setPosition(parentPos - moveState.initialOffset); + } + return false; +} + +bool XdgShellV5Integration::mouseReleaseEvent(QMouseEvent *event) +{ + Q_UNUSED(event); + + if (grabberState == GrabberState::Resize) { + m_xdgSurface->sendUnmaximized(); + grabberState = GrabberState::Default; + return true; + } else if (grabberState == GrabberState::Move) { + grabberState = GrabberState::Default; + return true; + } + return false; +} + +void XdgShellV5Integration::handleStartMove(QWaylandSeat *seat) +{ + grabberState = GrabberState::Move; + moveState.seat = seat; + moveState.initialized = false; +} + +void XdgShellV5Integration::handleStartResize(QWaylandSeat *seat, QWaylandXdgSurfaceV5::ResizeEdge edges) +{ + grabberState = GrabberState::Resize; + resizeState.seat = seat; + resizeState.resizeEdges = edges; + resizeState.initialWindowSize = m_xdgSurface->windowGeometry().size(); + resizeState.initialPosition = m_item->moveItem()->position(); + resizeState.initialSurfaceSize = m_item->surface()->size(); + resizeState.initialized = false; +} + +void XdgShellV5Integration::handleSetTopLevel() +{ + if (m_xdgSurface->shell()->focusPolicy() == QWaylandShell::AutomaticFocus) + m_item->takeFocus(); +} + +void XdgShellV5Integration::handleSetTransient() +{ + if (m_xdgSurface->shell()->focusPolicy() == QWaylandShell::AutomaticFocus) + m_item->takeFocus(); +} + +void XdgShellV5Integration::handleSetMaximized() +{ + if (!m_item->view()->isPrimary()) + return; + + maximizeState.initialWindowSize = m_xdgSurface->windowGeometry().size(); + maximizeState.initialPosition = m_item->moveItem()->position(); + + QWaylandOutput *output = m_item->view()->output(); + m_xdgSurface->sendMaximized(output->availableGeometry().size() / output->scaleFactor()); +} + +void XdgShellV5Integration::handleUnsetMaximized() +{ + if (!m_item->view()->isPrimary()) + return; + + m_xdgSurface->sendUnmaximized(maximizeState.initialWindowSize); +} + +void XdgShellV5Integration::handleMaximizedChanged() +{ + if (m_xdgSurface->maximized()) { + QWaylandOutput *output = m_item->view()->output(); + m_item->moveItem()->setPosition(output->position() + output->availableGeometry().topLeft()); + } else { + m_item->moveItem()->setPosition(maximizeState.initialPosition); + } +} + +void XdgShellV5Integration::handleActivatedChanged() +{ + if (m_xdgSurface->activated()) + m_item->raise(); +} + +void XdgShellV5Integration::handleSurfaceSizeChanged() +{ + if (grabberState == GrabberState::Resize) { + qreal x = resizeState.initialPosition.x(); + qreal y = resizeState.initialPosition.y(); + if (resizeState.resizeEdges & QWaylandXdgSurfaceV5::ResizeEdge::TopEdge) + y += resizeState.initialSurfaceSize.height() - m_item->surface()->size().height(); + + if (resizeState.resizeEdges & QWaylandXdgSurfaceV5::ResizeEdge::LeftEdge) + x += resizeState.initialSurfaceSize.width() - m_item->surface()->size().width(); + m_item->moveItem()->setPosition(QPointF(x, y)); + } +} + +XdgPopupV5Integration::XdgPopupV5Integration(QWaylandQuickShellSurfaceItem *item) + : QWaylandQuickShellIntegration (item) + , m_xdgPopup(qobject_cast<QWaylandXdgPopupV5 *>(item->shellSurface())) + , m_xdgShell(QWaylandXdgPopupV5Private::get(m_xdgPopup)->m_xdgShell) +{ + item->setSurface(m_xdgPopup->surface()); + item->moveItem()->setPosition(QPointF(m_xdgPopup->position() * item->view()->output()->scaleFactor())); + + QWaylandClient *client = m_xdgPopup->surface()->client(); + QWaylandQuickShellEventFilter::startFilter(client, [&]() { m_xdgShell->closeAllPopups(); }); + + connect(m_xdgPopup, &QWaylandXdgPopupV5::destroyed, this, &XdgPopupV5Integration::handlePopupDestroyed); +} + +void XdgPopupV5Integration::handlePopupDestroyed() +{ + QWaylandXdgShellV5Private *shellPrivate = QWaylandXdgShellV5Private::get(m_xdgShell); + auto popups = shellPrivate->m_xdgPopups; + if (popups.isEmpty()) + QWaylandQuickShellEventFilter::cancelFilter(); +} + +} + +QT_END_NAMESPACE diff --git a/src/compositor/extensions/qwaylandxdgshellintegration_p.h b/src/compositor/extensions/qwaylandxdgshellv5integration_p.h index df2fa8b8d..da4573c76 100644 --- a/src/compositor/extensions/qwaylandxdgshellintegration_p.h +++ b/src/compositor/extensions/qwaylandxdgshellv5integration_p.h @@ -34,11 +34,11 @@ ** ****************************************************************************/ -#ifndef QWAYLANDXDGSHELLINTEGRATION_H -#define QWAYLANDXDGSHELLINTEGRATION_H +#ifndef QWAYLANDXDGSHELLV5INTEGRATION_H +#define QWAYLANDXDGSHELLV5INTEGRATION_H #include <QtWaylandCompositor/private/qwaylandquickshellsurfaceitem_p.h> -#include <QtWaylandCompositor/QWaylandXdgSurface> +#include <QtWaylandCompositor/QWaylandXdgSurfaceV5> QT_BEGIN_NAMESPACE @@ -55,17 +55,19 @@ QT_BEGIN_NAMESPACE namespace QtWayland { -class XdgShellIntegration : public QWaylandQuickShellIntegration +class XdgShellV5Integration : public QWaylandQuickShellIntegration { Q_OBJECT public: - XdgShellIntegration(QWaylandQuickShellSurfaceItem *item); + XdgShellV5Integration(QWaylandQuickShellSurfaceItem *item); bool mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE; bool mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE; private Q_SLOTS: - void handleStartMove(QWaylandInputDevice *inputDevice); - void handleStartResize(QWaylandInputDevice *inputDevice, QWaylandXdgSurface::ResizeEdge edges); + void handleStartMove(QWaylandSeat *seat); + void handleStartResize(QWaylandSeat *seat, QWaylandXdgSurfaceV5::ResizeEdge edges); + void handleSetTopLevel(); + void handleSetTransient(); void handleSetMaximized(); void handleUnsetMaximized(); void handleMaximizedChanged(); @@ -79,18 +81,18 @@ private: Move }; QWaylandQuickShellSurfaceItem *m_item; - QWaylandXdgSurface *m_xdgSurface; + QWaylandXdgSurfaceV5 *m_xdgSurface; GrabberState grabberState; struct { - QWaylandInputDevice *inputDevice; + QWaylandSeat *seat; QPointF initialOffset; bool initialized; } moveState; struct { - QWaylandInputDevice *inputDevice; - QWaylandXdgSurface::ResizeEdge resizeEdges; + QWaylandSeat *seat; + QWaylandXdgSurfaceV5::ResizeEdge resizeEdges; QSizeF initialWindowSize; QPointF initialMousePos; QPointF initialPosition; @@ -104,6 +106,20 @@ private: } maximizeState; }; +class XdgPopupV5Integration : public QWaylandQuickShellIntegration +{ + Q_OBJECT +public: + XdgPopupV5Integration(QWaylandQuickShellSurfaceItem *item); + +private Q_SLOTS: + void handlePopupDestroyed(); + +private: + QWaylandXdgPopupV5 *m_xdgPopup; + QWaylandXdgShellV5 *m_xdgShell; +}; + } QT_END_NAMESPACE diff --git a/src/compositor/extensions/qwlqtkey_p.h b/src/compositor/extensions/qwlqtkey_p.h index 1b9c7391e..a4e67acfe 100644 --- a/src/compositor/extensions/qwlqtkey_p.h +++ b/src/compositor/extensions/qwlqtkey_p.h @@ -48,12 +48,12 @@ // We mean it. // -#include "wayland-util.h" - #include <QtWaylandCompositor/QWaylandCompositorExtensionTemplate> #include <QtWaylandCompositor/QWaylandCompositor> #include <QtWaylandCompositor/private/qwayland-server-qtkey-extension.h> +#include <wayland-util.h> + QT_BEGIN_NAMESPACE class QWaylandSurface; diff --git a/src/compositor/extensions/qwlqttouch.cpp b/src/compositor/extensions/qwlqttouch.cpp index 17246b397..0d1120a4e 100644 --- a/src/compositor/extensions/qwlqttouch.cpp +++ b/src/compositor/extensions/qwlqttouch.cpp @@ -64,14 +64,14 @@ static inline int toFixed(qreal f) return int(f * 10000); } -bool TouchExtensionGlobal::postTouchEvent(QTouchEvent *event, QWaylandView *view) +bool TouchExtensionGlobal::postTouchEvent(QTouchEvent *event, QWaylandSurface *surface) { const QList<QTouchEvent::TouchPoint> points = event->touchPoints(); const int pointCount = points.count(); if (!pointCount) return false; - wl_client *surfaceClient = view->surface()->client()->client(); + wl_client *surfaceClient = surface->client()->client(); uint32_t time = m_compositor->currentTimeMsecs(); const int rescount = m_resources.count(); diff --git a/src/compositor/extensions/qwlqttouch_p.h b/src/compositor/extensions/qwlqttouch_p.h index 32d7658f0..f3697aa83 100644 --- a/src/compositor/extensions/qwlqttouch_p.h +++ b/src/compositor/extensions/qwlqttouch_p.h @@ -51,7 +51,8 @@ #include <QtWaylandCompositor/private/qwayland-server-touch-extension.h> #include <QtWaylandCompositor/QWaylandCompositor> #include <QtWaylandCompositor/QWaylandCompositorExtensionTemplate> -#include "wayland-util.h" + +#include <wayland-util.h> QT_BEGIN_NAMESPACE @@ -76,7 +77,7 @@ public: TouchExtensionGlobal(QWaylandCompositor *compositor); ~TouchExtensionGlobal(); - bool postTouchEvent(QTouchEvent *event, QWaylandView *view); + bool postTouchEvent(QTouchEvent *event, QWaylandSurface *surface); void setBehviorFlags(BehaviorFlags flags); BehaviorFlags behaviorFlags() const { return m_flags; } diff --git a/src/compositor/global/qwaylandcompositorextension.cpp b/src/compositor/global/qwaylandcompositorextension.cpp index ddfd25837..6c7577ffc 100644 --- a/src/compositor/global/qwaylandcompositorextension.cpp +++ b/src/compositor/global/qwaylandcompositorextension.cpp @@ -96,6 +96,12 @@ void QWaylandCompositorExtension::initialize() return; } + if (!d->extension_container && parent()) { + QWaylandObject *parentObj = qobject_cast<QWaylandObject*>(parent()); + if (parentObj) + setExtensionContainer(parentObj); + } + if (!d->extension_container) { qWarning() << "QWaylandCompositorExtension:" << extensionInterface()->name << "requests to initialize with no extension container set"; return; diff --git a/src/compositor/global/qwaylandcompositorextension.h b/src/compositor/global/qwaylandcompositorextension.h index 0ba54c882..d666b4f2a 100644 --- a/src/compositor/global/qwaylandcompositorextension.h +++ b/src/compositor/global/qwaylandcompositorextension.h @@ -52,6 +52,7 @@ class QWaylandCompositorExtensionPrivate; class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandObject : public QObject { + Q_OBJECT public: virtual ~QWaylandObject(); diff --git a/src/compositor/global/qwaylandcompositorextension_p.h b/src/compositor/global/qwaylandcompositorextension_p.h index a9a670d66..d94896a57 100644 --- a/src/compositor/global/qwaylandcompositorextension_p.h +++ b/src/compositor/global/qwaylandcompositorextension_p.h @@ -48,9 +48,10 @@ // We mean it. // -#include "qwaylandcompositorextension.h" #include <QtCore/private/qobject_p.h> +#include <QtWaylandCompositor/QWaylandCompositorExtension> + QT_BEGIN_NAMESPACE class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandCompositorExtensionPrivate : public QObjectPrivate diff --git a/src/compositor/global/qwaylandquickextension.h b/src/compositor/global/qwaylandquickextension.h index 32f4e6527..63c3d135e 100644 --- a/src/compositor/global/qwaylandquickextension.h +++ b/src/compositor/global/qwaylandquickextension.h @@ -50,6 +50,7 @@ QT_BEGIN_NAMESPACE Q_OBJECT \ Q_PROPERTY(QQmlListProperty<QObject> data READ data DESIGNABLE false) \ Q_CLASSINFO("DefaultProperty", "data") \ + Q_INTERFACES(QQmlParserStatus) \ public: \ QQmlListProperty<QObject> data() \ { \ diff --git a/src/compositor/hardware_integration/hardware_integration.pri b/src/compositor/hardware_integration/hardware_integration.pri index 2737a6f07..624190a6e 100644 --- a/src/compositor/hardware_integration/hardware_integration.pri +++ b/src/compositor/hardware_integration/hardware_integration.pri @@ -1,6 +1,4 @@ -isEmpty(QT_WAYLAND_GL_CONFIG):QT_WAYLAND_GL_CONFIG = $$(QT_WAYLAND_GL_CONFIG) - -!isEqual(QT_WAYLAND_GL_CONFIG,nogl) { +contains(QT_CONFIG, opengl) { CONFIG += wayland-scanner WAYLANDSERVERSOURCES += \ ../extensions/server-buffer-extension.xml \ @@ -24,7 +22,7 @@ isEmpty(QT_WAYLAND_GL_CONFIG):QT_WAYLAND_GL_CONFIG = $$(QT_WAYLAND_GL_CONFIG) hardware_integration/qwlserverbufferintegrationplugin.cpp \ hardware_integration/qwlhwintegration.cpp \ - DEFINES += QT_COMPOSITOR_WAYLAND_GL + DEFINES += QT_WAYLAND_COMPOSITOR_GL } else { system(echo "Qt-Compositor configured as raster only compositor") } diff --git a/src/compositor/hardware_integration/qwlclientbufferintegration_p.h b/src/compositor/hardware_integration/qwlclientbufferintegration_p.h index 90762437b..a7de2c0e3 100644 --- a/src/compositor/hardware_integration/qwlclientbufferintegration_p.h +++ b/src/compositor/hardware_integration/qwlclientbufferintegration_p.h @@ -57,6 +57,7 @@ QT_BEGIN_NAMESPACE class QWaylandCompositor; +class QOpenGLTexture; namespace QtWayland { class Display; @@ -68,22 +69,11 @@ public: virtual ~ClientBufferIntegration() { } void setCompositor(QWaylandCompositor *compositor) { m_compositor = compositor; } + QWaylandCompositor *compositor() const { return m_compositor; } virtual void initializeHardware(struct ::wl_display *display) = 0; - virtual void initializeBuffer(struct ::wl_resource *buffer) { Q_UNUSED(buffer); } - virtual QWaylandBufferRef::BufferFormatEgl bufferFormat(struct ::wl_resource *buffer) { Q_UNUSED(buffer); return QWaylandBufferRef::BufferFormatEgl_RGBA; } - virtual uint textureForBuffer(struct ::wl_resource *buffer, int plane) { Q_UNUSED(buffer); Q_UNUSED(plane); return 0; } - - virtual void bindTextureToBuffer(struct ::wl_resource *buffer) = 0; - virtual void updateTextureForBuffer(struct ::wl_resource *buffer) { Q_UNUSED(buffer); } - - virtual QWaylandSurface::Origin origin(struct ::wl_resource *) const { return QWaylandSurface::OriginBottomLeft; } - - virtual void *lockNativeBuffer(struct ::wl_resource *) const { return 0; } - virtual void unlockNativeBuffer(void *) const { return; } - - virtual QSize bufferSize(struct ::wl_resource *) const { return QSize(); } + virtual ClientBuffer *createBufferFor(struct ::wl_resource *buffer) = 0; protected: QWaylandCompositor *m_compositor; diff --git a/src/compositor/wayland_wrapper/qwlbuffermanager.cpp b/src/compositor/wayland_wrapper/qwlbuffermanager.cpp new file mode 100644 index 000000000..765c9a03a --- /dev/null +++ b/src/compositor/wayland_wrapper/qwlbuffermanager.cpp @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWaylandCompositor module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwlbuffermanager_p.h" +#include <QWaylandCompositor> +#include <QtWaylandCompositor/private/qwaylandcompositor_p.h> +#include <QtWaylandCompositor/private/qwlclientbufferintegration_p.h> +#include <QDebug> + +QT_BEGIN_NAMESPACE + +namespace QtWayland { + +BufferManager::BufferManager(QWaylandCompositor *compositor) + : QObject(compositor) + , m_compositor(compositor) +{ + +} + +struct buffer_manager_destroy_listener : wl_listener +{ + buffer_manager_destroy_listener() + : d(0) + { + notify = BufferManager::destroy_listener_callback; + wl_list_init(&this->link); + } + + BufferManager *d; +}; + +ClientBuffer *BufferManager::getBuffer(wl_resource *buffer_resource) +{ + if (!buffer_resource) + return nullptr; + + auto it = m_buffers.find(buffer_resource); + if (it != m_buffers.end()) + return it.value(); + + auto bufferIntegration = QWaylandCompositorPrivate::get(m_compositor)->clientBufferIntegration(); + ClientBuffer *newBuffer = nullptr; + if (bufferIntegration) + newBuffer = bufferIntegration->createBufferFor(buffer_resource); + if (!newBuffer) + newBuffer = new SharedMemoryBuffer(buffer_resource); + m_buffers[buffer_resource] = newBuffer; + + auto *destroy_listener = new buffer_manager_destroy_listener; + destroy_listener->d = this; + wl_signal_add(&buffer_resource->destroy_signal, destroy_listener); + return newBuffer; +} + + +void BufferManager::destroy_listener_callback(wl_listener *listener, void *data) +{ + buffer_manager_destroy_listener *destroy_listener = static_cast<buffer_manager_destroy_listener *>(listener); + BufferManager *self = destroy_listener->d; + struct ::wl_resource *buffer = static_cast<struct ::wl_resource *>(data); + + wl_list_remove(&destroy_listener->link); + delete destroy_listener; + + Q_ASSERT(self); + Q_ASSERT(buffer); + + ClientBuffer *clientBuffer = self->m_buffers.take(buffer); + + if (!clientBuffer) + return; + + clientBuffer->setDestroyed(); +} + +} +QT_END_NAMESPACE diff --git a/src/compositor/wayland_wrapper/qwlbuffermanager_p.h b/src/compositor/wayland_wrapper/qwlbuffermanager_p.h new file mode 100644 index 000000000..e1325ef89 --- /dev/null +++ b/src/compositor/wayland_wrapper/qwlbuffermanager_p.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWaylandCompositor module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWLBUFFERMANAGER_H +#define QWLBUFFERMANAGER_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/QObject> +#include "qwlclientbuffer_p.h" +QT_BEGIN_NAMESPACE + +class QWaylandCompositor; + +namespace QtWayland { + +class ClientBuffer; + +class Q_WAYLAND_COMPOSITOR_EXPORT BufferManager : public QObject +{ +public: + BufferManager(QWaylandCompositor *compositor); + ClientBuffer *getBuffer(struct ::wl_resource *buffer_resource); +private: + friend struct buffer_manager_destroy_listener; + static void destroy_listener_callback(wl_listener *listener, void *data); + + QHash<struct ::wl_resource *, ClientBuffer*> m_buffers; + QWaylandCompositor *m_compositor; +}; + +} +QT_END_NAMESPACE + +#endif // QWLBUFFERMANAGER_H diff --git a/src/compositor/wayland_wrapper/qwlclientbuffer.cpp b/src/compositor/wayland_wrapper/qwlclientbuffer.cpp new file mode 100644 index 000000000..589ab825b --- /dev/null +++ b/src/compositor/wayland_wrapper/qwlclientbuffer.cpp @@ -0,0 +1,189 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWaylandCompositor module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwlclientbuffer_p.h" + +#ifdef QT_WAYLAND_COMPOSITOR_GL +#include "hardware_integration/qwlclientbufferintegration_p.h" +#include <qpa/qplatformopenglcontext.h> +#include <QOpenGLTexture> +#endif + +#include <QtCore/QDebug> + +#include <wayland-server-protocol.h> +#include "qwaylandsharedmemoryformathelper_p.h" + +#include <QtWaylandCompositor/private/qwaylandcompositor_p.h> + +QT_BEGIN_NAMESPACE + +namespace QtWayland { + +ClientBuffer::ClientBuffer(struct ::wl_resource *buffer) + : m_buffer(buffer) + , m_textureDirty(false) + , m_committed(false) + , m_destroyed(false) +{ +} + + +ClientBuffer::~ClientBuffer() +{ + if (m_buffer && m_committed && !m_destroyed) + sendRelease(); +} + +void ClientBuffer::sendRelease() +{ + Q_ASSERT(m_buffer); + wl_buffer_send_release(m_buffer); + m_committed = false; +} + +void ClientBuffer::setDestroyed() +{ + m_destroyed = true; + m_committed = false; + m_buffer = nullptr; + + if (!m_refCount) + delete this; +} + +void ClientBuffer::ref() +{ + m_refCount.ref(); +} + +void ClientBuffer::deref() +{ + if (!m_refCount.deref()) { + if (isCommitted() && m_buffer && !m_destroyed) + sendRelease(); + if (m_destroyed) + delete this; + } +} + +void ClientBuffer::setCommitted(QRegion &damage) +{ + m_damage = damage; + m_committed = true; + m_textureDirty = true; +} + +QWaylandBufferRef::BufferFormatEgl ClientBuffer::bufferFormatEgl() const +{ + return QWaylandBufferRef::BufferFormatEgl_Null; +} + +SharedMemoryBuffer::SharedMemoryBuffer(wl_resource *bufferResource) + : ClientBuffer(bufferResource) + , m_shmTexture(nullptr) +{ + +} + +QSize SharedMemoryBuffer::size() const +{ + if (wl_shm_buffer *shmBuffer = wl_shm_buffer_get(m_buffer)) { + int width = wl_shm_buffer_get_width(shmBuffer); + int height = wl_shm_buffer_get_height(shmBuffer); + return QSize(width, height); + } + return QSize(); +} + +QWaylandSurface::Origin SharedMemoryBuffer::origin() const +{ + return QWaylandSurface::OriginTopLeft; +} + + +// TODO: support different color formats, and try to avoid QImage::convertToFormat() + +QImage SharedMemoryBuffer::image() const +{ + if (wl_shm_buffer *shmBuffer = wl_shm_buffer_get(m_buffer)) { + int width = wl_shm_buffer_get_width(shmBuffer); + int height = wl_shm_buffer_get_height(shmBuffer); + int bytesPerLine = wl_shm_buffer_get_stride(shmBuffer); + uchar *data = static_cast<uchar *>(wl_shm_buffer_get_data(shmBuffer)); + return QImage(data, width, height, bytesPerLine, QImage::Format_ARGB32_Premultiplied); + } + + return QImage(); +} + +#ifdef QT_WAYLAND_COMPOSITOR_GL +QOpenGLTexture *SharedMemoryBuffer::toOpenGlTexture(int plane) +{ + Q_UNUSED(plane); + if (isSharedMemory()) { + if (!m_shmTexture) { + m_shmTexture = new QOpenGLTexture(QOpenGLTexture::Target2D); + m_shmTexture->create(); + } + if (m_textureDirty) { + m_textureDirty = false; + m_shmTexture->bind(); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + // TODO: partial texture upload + QImage image = this->image(); + if (image.hasAlphaChannel()) { + if (image.format() != QImage::Format_RGBA8888) + image = image.convertToFormat(QImage::Format_RGBA8888); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, image.constBits()); + } else { + if (image.format() != QImage::Format_RGBX8888) + image = image.convertToFormat(QImage::Format_RGBX8888); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image.width(), image.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, image.constBits()); + } + //we can release the buffer after uploading, since we have a copy + if (isCommitted()) + sendRelease(); + } + return m_shmTexture; + } + return nullptr; +} +#endif + +} + +QT_END_NAMESPACE diff --git a/src/compositor/wayland_wrapper/qwlsurfacebuffer_p.h b/src/compositor/wayland_wrapper/qwlclientbuffer_p.h index 95e7e8158..78e07ee98 100644 --- a/src/compositor/wayland_wrapper/qwlsurfacebuffer_p.h +++ b/src/compositor/wayland_wrapper/qwlclientbuffer_p.h @@ -34,8 +34,8 @@ ** ****************************************************************************/ -#ifndef SURFACEBUFFER_H -#define SURFACEBUFFER_H +#ifndef QWLCLIENTBUFFER_P_H +#define QWLCLIENTBUFFER_P_H // // W A R N I N G @@ -63,81 +63,85 @@ QT_BEGIN_NAMESPACE class QWaylandClientBufferIntegration; class QWaylandBufferRef; class QWaylandCompositor; +class QOpenGLTexture; namespace QtWayland { struct surface_buffer_destroy_listener { struct wl_listener listener; - class SurfaceBuffer *surfaceBuffer; + class ClientBuffer *surfaceBuffer; }; -class SurfaceBuffer +class Q_WAYLAND_COMPOSITOR_EXPORT ClientBuffer { public: - SurfaceBuffer(QWaylandSurface *surface); + ClientBuffer(struct ::wl_resource *bufferResource); - ~SurfaceBuffer(); + virtual ~ClientBuffer(); - void initialize(struct ::wl_resource *bufferResource); - void destructBufferState(); + virtual QWaylandBufferRef::BufferFormatEgl bufferFormatEgl() const; + virtual QSize size() const = 0; + virtual QWaylandSurface::Origin origin() const = 0; - inline bool isRegisteredWithBuffer() const { return m_is_registered_for_buffer; } + virtual quintptr lockNativeBuffer() { return 0; } + virtual void unlockNativeBuffer(quintptr native_buffer) const { Q_UNUSED(native_buffer); } - void sendRelease(); - void disown(); - - void setDisplayed(); + virtual QImage image() const { return QImage(); } inline bool isCommitted() const { return m_committed; } - inline void setCommitted() { m_committed = true; } - inline bool isDisplayed() const { return m_is_displayed; } - + virtual void setCommitted(QRegion &damage); bool isDestroyed() { return m_destroyed; } inline struct ::wl_resource *waylandBufferHandle() const { return m_buffer; } - void setDestroyIfUnused(bool destroy); + bool isSharedMemory() const { return wl_shm_buffer_get(m_buffer); } - QSize size() const; - QWaylandSurface::Origin origin() const; - bool isShm() const { return wl_shm_buffer_get(m_buffer); } +#ifdef QT_WAYLAND_COMPOSITOR_GL + virtual QOpenGLTexture *toOpenGlTexture(int plane = 0) = 0; +#endif - QImage image() const; - QWaylandBufferRef::BufferFormatEgl bufferFormatEgl() const; - void bindToTexture() const; - uint textureForPlane(int plane) const; - void updateTexture() const; + static bool hasContent(ClientBuffer *buffer) { return buffer && buffer->waylandBufferHandle(); } - static bool hasContent(SurfaceBuffer *buffer) { return buffer && buffer->waylandBufferHandle(); } -private: +protected: void ref(); void deref(); - void destroyIfUnused(); + void sendRelease(); + void setDestroyed(); - QWaylandSurface *m_surface; - QWaylandCompositor *m_compositor; struct ::wl_resource *m_buffer; - int m_bufferScale; - struct surface_buffer_destroy_listener m_destroy_listener; + QRegion m_damage; + bool m_textureDirty; + +private: bool m_committed; - bool m_is_registered_for_buffer; - bool m_surface_has_buffer; bool m_destroyed; - bool m_is_displayed; - QAtomicInt m_refCount; - bool m_used; - bool m_destroyIfUnused; - - static void destroy_listener_callback(wl_listener *listener, void *data); friend class ::QWaylandBufferRef; + friend class BufferManager; +}; + +class Q_WAYLAND_COMPOSITOR_EXPORT SharedMemoryBuffer : public ClientBuffer +{ +public: + SharedMemoryBuffer(struct ::wl_resource *bufferResource); + + QSize size() const Q_DECL_OVERRIDE; + QWaylandSurface::Origin origin() const Q_DECL_OVERRIDE; + QImage image() const; + +#ifdef QT_WAYLAND_COMPOSITOR_GL + QOpenGLTexture *toOpenGlTexture(int plane = 0) Q_DECL_OVERRIDE; + +private: + QOpenGLTexture *m_shmTexture; +#endif }; } QT_END_NAMESPACE -#endif // SURFACEBUFFER_H +#endif // QWLCLIENTBUFFER_P_H diff --git a/src/compositor/wayland_wrapper/qwldatadevice.cpp b/src/compositor/wayland_wrapper/qwldatadevice.cpp index dea72bdcd..0d196b82e 100644 --- a/src/compositor/wayland_wrapper/qwldatadevice.cpp +++ b/src/compositor/wayland_wrapper/qwldatadevice.cpp @@ -45,7 +45,7 @@ #include "qwaylandview.h" #include <QtWaylandCompositor/QWaylandClient> #include <QtWaylandCompositor/private/qwaylandcompositor_p.h> -#include <QtWaylandCompositor/private/qwaylandinput_p.h> +#include <QtWaylandCompositor/private/qwaylandseat_p.h> #include <QtWaylandCompositor/private/qwaylandpointer_p.h> #include <QtCore/QPointF> @@ -55,16 +55,17 @@ QT_BEGIN_NAMESPACE namespace QtWayland { -DataDevice::DataDevice(QWaylandInputDevice *inputDevice) +DataDevice::DataDevice(QWaylandSeat *seat) : wl_data_device() - , m_compositor(inputDevice->compositor()) - , m_inputDevice(inputDevice) + , m_compositor(seat->compositor()) + , m_seat(seat) , m_selectionSource(0) , m_dragClient(0) , m_dragDataSource(0) , m_dragFocus(0) , m_dragFocusResource(0) , m_dragIcon(0) + , m_dragOrigin(nullptr) { } @@ -123,6 +124,11 @@ QWaylandSurface *DataDevice::dragIcon() const return m_dragIcon; } +QWaylandSurface *DataDevice::dragOrigin() const +{ + return m_dragOrigin; +} + void DataDevice::sourceDestroyed(DataSource *source) { if (m_selectionSource == source) @@ -148,6 +154,7 @@ void DataDevice::drop() } else { m_dragDataSource->cancel(); } + m_dragOrigin = nullptr; setDragIcon(nullptr); } @@ -160,11 +167,13 @@ void DataDevice::data_device_start_drag(Resource *resource, struct ::wl_resource { m_dragClient = resource->client(); m_dragDataSource = source ? DataSource::fromResource(source) : 0; + m_dragOrigin = QWaylandSurface::fromResource(origin); + QWaylandDrag *drag = m_seat->drag(); setDragIcon(icon ? QWaylandSurface::fromResource(icon) : nullptr); - Q_EMIT m_inputDevice->drag()->dragStarted(); + Q_EMIT drag->dragStarted(); + Q_EMIT m_dragOrigin->dragStarted(drag); Q_UNUSED(serial); - Q_UNUSED(origin); //### need to verify that we have an implicit grab with this serial } @@ -182,7 +191,7 @@ void DataDevice::data_device_set_selection(Resource *, struct ::wl_resource *sou if (m_selectionSource) m_selectionSource->setDevice(this); - QWaylandClient *focusClient = m_inputDevice->keyboard()->focusClient(); + QWaylandClient *focusClient = m_seat->keyboard()->focusClient(); Resource *resource = focusClient ? resourceMap().value(focusClient->client()) : 0; if (resource && m_selectionSource) { @@ -198,7 +207,7 @@ void DataDevice::setDragIcon(QWaylandSurface *icon) if (icon == m_dragIcon) return; m_dragIcon = icon; - Q_EMIT m_inputDevice->drag()->iconChanged(); + Q_EMIT m_seat->drag()->iconChanged(); } } diff --git a/src/compositor/wayland_wrapper/qwldatadevice_p.h b/src/compositor/wayland_wrapper/qwldatadevice_p.h index 2127603a8..17591ae27 100644 --- a/src/compositor/wayland_wrapper/qwldatadevice_p.h +++ b/src/compositor/wayland_wrapper/qwldatadevice_p.h @@ -49,7 +49,7 @@ // #include <QtWaylandCompositor/private/qwayland-server-wayland.h> -#include <QtWaylandCompositor/QWaylandInputDevice> +#include <QtWaylandCompositor/QWaylandSeat> QT_BEGIN_NAMESPACE @@ -57,19 +57,20 @@ namespace QtWayland { class Compositor; class DataSource; -class InputDevice; +class Seat; class Surface; class DataDevice : public QtWaylandServer::wl_data_device { public: - DataDevice(QWaylandInputDevice *inputDevice); + DataDevice(QWaylandSeat *seat); void setFocus(QWaylandClient *client); void setDragFocus(QWaylandSurface *focus, const QPointF &localPosition); QWaylandSurface *dragIcon() const; + QWaylandSurface *dragOrigin() const; void sourceDestroyed(DataSource *source); @@ -85,7 +86,7 @@ private: void setDragIcon(QWaylandSurface *icon); QWaylandCompositor *m_compositor; - QWaylandInputDevice *m_inputDevice; + QWaylandSeat *m_seat; DataSource *m_selectionSource; @@ -96,6 +97,7 @@ private: Resource *m_dragFocusResource; QWaylandSurface *m_dragIcon; + QWaylandSurface *m_dragOrigin; }; } diff --git a/src/compositor/wayland_wrapper/qwldatadevicemanager.cpp b/src/compositor/wayland_wrapper/qwldatadevicemanager.cpp index 2f40b0e43..5fed6ef18 100644 --- a/src/compositor/wayland_wrapper/qwldatadevicemanager.cpp +++ b/src/compositor/wayland_wrapper/qwldatadevicemanager.cpp @@ -39,7 +39,7 @@ #include <QtWaylandCompositor/QWaylandCompositor> #include <QtWaylandCompositor/private/qwaylandcompositor_p.h> -#include <QtWaylandCompositor/private/qwaylandinput_p.h> +#include <QtWaylandCompositor/private/qwaylandseat_p.h> #include "qwldatadevice_p.h" #include "qwldatasource_p.h" #include "qwldataoffer_p.h" @@ -199,11 +199,11 @@ void DataDeviceManager::overrideSelection(const QMimeData &mimeData) m_compositorOwnsSelection = true; - QWaylandInputDevice *dev = m_compositor->defaultInputDevice(); + QWaylandSeat *dev = m_compositor->defaultSeat(); QWaylandSurface *focusSurface = dev->keyboardFocus(); if (focusSurface) offerFromCompositorToClient( - QWaylandInputDevicePrivate::get(dev)->dataDevice()->resourceMap().value(focusSurface->waylandClient())->handle); + QWaylandSeatPrivate::get(dev)->dataDevice()->resourceMap().value(focusSurface->waylandClient())->handle); } bool DataDeviceManager::offerFromCompositorToClient(wl_resource *clientDataDeviceResource) @@ -243,8 +243,8 @@ void DataDeviceManager::data_device_manager_create_data_source(Resource *resourc void DataDeviceManager::data_device_manager_get_data_device(Resource *resource, uint32_t id, struct ::wl_resource *seat) { - QWaylandInputDevice *input_device = QWaylandInputDevice::fromSeatResource(seat); - QWaylandInputDevicePrivate::get(input_device)->clientRequestedDataDevice(this, resource->client(), id); + QWaylandSeat *input_device = QWaylandSeat::fromSeatResource(seat); + QWaylandSeatPrivate::get(input_device)->clientRequestedDataDevice(this, resource->client(), id); } void DataDeviceManager::comp_accept(wl_client *, wl_resource *, uint32_t, const char *) diff --git a/src/compositor/wayland_wrapper/qwlsurfacebuffer.cpp b/src/compositor/wayland_wrapper/qwlsurfacebuffer.cpp deleted file mode 100644 index 240ce01bc..000000000 --- a/src/compositor/wayland_wrapper/qwlsurfacebuffer.cpp +++ /dev/null @@ -1,251 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtWaylandCompositor module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** 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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qwlsurfacebuffer_p.h" - -#ifdef QT_COMPOSITOR_WAYLAND_GL -#include "hardware_integration/qwlclientbufferintegration_p.h" -#include <qpa/qplatformopenglcontext.h> -#endif - -#include <QtCore/QDebug> - -#include <wayland-server-protocol.h> -#include "qwaylandshmformathelper_p.h" - -#include <QtWaylandCompositor/private/qwaylandcompositor_p.h> - -QT_BEGIN_NAMESPACE - -namespace QtWayland { - -SurfaceBuffer::SurfaceBuffer(QWaylandSurface *surface) - : m_surface(surface) - , m_compositor(surface->compositor()) - , m_buffer(0) - , m_committed(false) - , m_is_registered_for_buffer(false) - , m_surface_has_buffer(false) - , m_destroyed(false) - , m_is_displayed(false) - , m_used(false) - , m_destroyIfUnused(false) -{ -} - -SurfaceBuffer::~SurfaceBuffer() -{ - if (m_is_registered_for_buffer) - destructBufferState(); -} - -void SurfaceBuffer::initialize(struct ::wl_resource *buffer) -{ - m_buffer = buffer; - m_committed = false; - m_is_registered_for_buffer = true; - m_surface_has_buffer = true; - m_is_displayed = false; - m_destroyed = false; - m_destroy_listener.surfaceBuffer = this; - m_destroy_listener.listener.notify = destroy_listener_callback; - if (buffer) { - if (ClientBufferIntegration *integration = QWaylandCompositorPrivate::get(m_compositor)->clientBufferIntegration()) - integration->initializeBuffer(buffer); - wl_signal_add(&buffer->destroy_signal, &m_destroy_listener.listener); - } -} - -void SurfaceBuffer::destructBufferState() -{ - if (m_buffer) { - if (m_committed) - sendRelease(); - wl_list_remove(&m_destroy_listener.listener.link); - } - m_buffer = 0; - m_committed = false; - m_is_registered_for_buffer = false; - m_is_displayed = false; -} - -void SurfaceBuffer::sendRelease() -{ - Q_ASSERT(m_buffer); - wl_buffer_send_release(m_buffer); -} - -void SurfaceBuffer::disown() -{ - m_surface_has_buffer = false; - destructBufferState(); - destroyIfUnused(); -} - -void SurfaceBuffer::setDisplayed() -{ - m_is_displayed = true; -} - -void SurfaceBuffer::destroy_listener_callback(wl_listener *listener, void *data) -{ - Q_UNUSED(data); - struct surface_buffer_destroy_listener *destroy_listener = - reinterpret_cast<struct surface_buffer_destroy_listener *>(listener); - SurfaceBuffer *d = destroy_listener->surfaceBuffer; - - // Mark the buffer as destroyed and clear m_buffer right away to avoid - // touching it before it is properly cleaned up. - d->m_destroyed = true; - d->m_buffer = 0; -} - -void SurfaceBuffer::ref() -{ - m_used = m_refCount.ref(); -} - -void SurfaceBuffer::deref() -{ - m_used = m_refCount.deref(); - if (!m_used) - disown(); -} - -void SurfaceBuffer::setDestroyIfUnused(bool destroy) -{ - m_destroyIfUnused = destroy; - destroyIfUnused(); -} - -void SurfaceBuffer::destroyIfUnused() -{ - if (!m_used && m_destroyIfUnused) - delete this; -} - -QSize SurfaceBuffer::size() const -{ - if (!m_buffer) - return QSize(); - - if (wl_shm_buffer *shmBuffer = wl_shm_buffer_get(m_buffer)) { - int width = wl_shm_buffer_get_width(shmBuffer); - int height = wl_shm_buffer_get_height(shmBuffer); - return QSize(width, height); - } - if (ClientBufferIntegration *integration = QWaylandCompositorPrivate::get(m_compositor)->clientBufferIntegration()) { - return integration->bufferSize(m_buffer); - } - - return QSize(); -} - -QWaylandSurface::Origin SurfaceBuffer::origin() const -{ - if (isShm()) { - return QWaylandSurface::OriginTopLeft; - } - - if (ClientBufferIntegration *integration = QWaylandCompositorPrivate::get(m_compositor)->clientBufferIntegration()) { - return integration->origin(m_buffer); - } - return QWaylandSurface::OriginTopLeft; -} - -QImage SurfaceBuffer::image() const -{ - if (wl_shm_buffer *shmBuffer = wl_shm_buffer_get(m_buffer)) { - int width = wl_shm_buffer_get_width(shmBuffer); - int height = wl_shm_buffer_get_height(shmBuffer); - int bytesPerLine = wl_shm_buffer_get_stride(shmBuffer); - uchar *data = static_cast<uchar *>(wl_shm_buffer_get_data(shmBuffer)); - return QImage(data, width, height, bytesPerLine, QImage::Format_ARGB32_Premultiplied); - } - - return QImage(); -} - -QWaylandBufferRef::BufferFormatEgl SurfaceBuffer::bufferFormatEgl() const -{ - Q_ASSERT(isShm() == false); - - if (QtWayland::ClientBufferIntegration *clientInt = QWaylandCompositorPrivate::get(m_compositor)->clientBufferIntegration()) - return clientInt->bufferFormat(m_buffer); - - return QWaylandBufferRef::BufferFormatEgl_Null; -} - -void SurfaceBuffer::bindToTexture() const -{ - Q_ASSERT(m_compositor); - if (isShm()) { - QImage image = this->image(); - if (image.hasAlphaChannel()) { - if (image.format() != QImage::Format_RGBA8888) { - image = image.convertToFormat(QImage::Format_RGBA8888); - } - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, image.constBits()); - } else { - if (image.format() != QImage::Format_RGBX8888) { - image = image.convertToFormat(QImage::Format_RGBX8888); - } - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image.width(), image.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, image.constBits()); - } - } else { - if (QtWayland::ClientBufferIntegration *clientInt = QWaylandCompositorPrivate::get(m_compositor)->clientBufferIntegration()) { - clientInt->bindTextureToBuffer(m_buffer); - } - } -} - -uint SurfaceBuffer::textureForPlane(int plane) const -{ - if (QtWayland::ClientBufferIntegration *clientInt = QWaylandCompositorPrivate::get(m_compositor)->clientBufferIntegration()) - return clientInt->textureForBuffer(m_buffer, plane); - - return 0; -} - -void SurfaceBuffer::updateTexture() const -{ - if (QtWayland::ClientBufferIntegration *clientInt = QWaylandCompositorPrivate::get(m_compositor)->clientBufferIntegration()) - clientInt->updateTextureForBuffer(m_buffer); -} - -} - -QT_END_NAMESPACE diff --git a/src/compositor/wayland_wrapper/wayland_wrapper.pri b/src/compositor/wayland_wrapper/wayland_wrapper.pri index f338ddc05..fa5d76291 100644 --- a/src/compositor/wayland_wrapper/wayland_wrapper.pri +++ b/src/compositor/wayland_wrapper/wayland_wrapper.pri @@ -3,21 +3,23 @@ WAYLANDSERVERSOURCES += \ ../3rdparty/protocol/wayland.xml \ HEADERS += \ + wayland_wrapper/qwlbuffermanager_p.h \ + wayland_wrapper/qwlclientbuffer_p.h \ wayland_wrapper/qwldatadevice_p.h \ wayland_wrapper/qwldatadevicemanager_p.h \ wayland_wrapper/qwldataoffer_p.h \ wayland_wrapper/qwldatasource_p.h \ wayland_wrapper/qwlregion_p.h \ - wayland_wrapper/qwlsurfacebuffer_p.h \ ../shared/qwaylandxkb_p.h \ SOURCES += \ + wayland_wrapper/qwlbuffermanager.cpp \ + wayland_wrapper/qwlclientbuffer.cpp \ wayland_wrapper/qwldatadevice.cpp \ wayland_wrapper/qwldatadevicemanager.cpp \ wayland_wrapper/qwldataoffer.cpp \ wayland_wrapper/qwldatasource.cpp \ wayland_wrapper/qwlregion.cpp \ - wayland_wrapper/qwlsurfacebuffer.cpp \ ../shared/qwaylandxkb.cpp \ INCLUDEPATH += wayland_wrapper diff --git a/src/extensions/windowmanager.xml b/src/extensions/qt-windowmanager.xml index 3d3bbd7fe..86ddff72e 100644 --- a/src/extensions/windowmanager.xml +++ b/src/extensions/qt-windowmanager.xml @@ -1,4 +1,4 @@ -<protocol name="windowmanager"> +<protocol name="qt_windowmanager"> <copyright> Copyright (C) 2015 The Qt Company Ltd. diff --git a/src/hardwareintegration/client/brcm-egl/qwaylandbrcmeglwindow.cpp b/src/hardwareintegration/client/brcm-egl/qwaylandbrcmeglwindow.cpp index fe7e17e86..4d56d66e6 100644 --- a/src/hardwareintegration/client/brcm-egl/qwaylandbrcmeglwindow.cpp +++ b/src/hardwareintegration/client/brcm-egl/qwaylandbrcmeglwindow.cpp @@ -43,7 +43,7 @@ #include <QtWaylandClient/private/qwaylandscreen_p.h> #include "qwaylandbrcmglcontext.h" -#include <QtPlatformSupport/private/qeglconvenience_p.h> +#include <QtEglSupport/private/qeglconvenience_p.h> #include <QtGui/QWindow> #include <qpa/qwindowsysteminterface.h> diff --git a/src/hardwareintegration/client/brcm-egl/qwaylandbrcmglcontext.cpp b/src/hardwareintegration/client/brcm-egl/qwaylandbrcmglcontext.cpp index a14f6b024..f5480b0ed 100644 --- a/src/hardwareintegration/client/brcm-egl/qwaylandbrcmglcontext.cpp +++ b/src/hardwareintegration/client/brcm-egl/qwaylandbrcmglcontext.cpp @@ -43,7 +43,7 @@ #include <QtWaylandClient/private/qwaylandwindow_p.h> #include "qwaylandbrcmeglwindow.h" -#include <QtPlatformSupport/private/qeglconvenience_p.h> +#include <QtEglSupport/private/qeglconvenience_p.h> #include <qpa/qplatformopenglcontext.h> #include <QtGui/QSurfaceFormat> diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandeglinclude.h b/src/hardwareintegration/client/wayland-egl/qwaylandeglinclude.h index 024809ff6..233ce78bd 100644 --- a/src/hardwareintegration/client/wayland-egl/qwaylandeglinclude.h +++ b/src/hardwareintegration/client/wayland-egl/qwaylandeglinclude.h @@ -46,6 +46,6 @@ #include <wayland-egl.h> #define EGL_EGLEXT_PROTOTYPES -#include <QtPlatformSupport/private/qt_egl_p.h> +#include <QtEglSupport/private/qt_egl_p.h> #endif // QWAYLANDEGLINCLUDE_H diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp b/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp index 417fc75bd..236218e7f 100644 --- a/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp +++ b/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp @@ -42,7 +42,7 @@ #include <QtWaylandClient/private/qwaylandscreen_p.h> #include "qwaylandglcontext.h" -#include <QtPlatformSupport/private/qeglconvenience_p.h> +#include <QtEglSupport/private/qeglconvenience_p.h> #include <QDebug> #include <QtGui/QWindow> diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp index 72e7b0e6a..f70c75a33 100644 --- a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp +++ b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp @@ -47,7 +47,7 @@ #include "qwaylandeglwindow.h" #include <QDebug> -#include <QtPlatformSupport/private/qeglconvenience_p.h> +#include <QtEglSupport/private/qeglconvenience_p.h> #include <QtGui/private/qopenglcontext_p.h> #include <QtGui/private/qopengltexturecache_p.h> #include <QtGui/private/qguiapplication_p.h> diff --git a/src/hardwareintegration/client/wayland-egl/wayland-egl.pri b/src/hardwareintegration/client/wayland-egl/wayland-egl.pri index 520c1eb0f..276b7b54f 100644 --- a/src/hardwareintegration/client/wayland-egl/wayland-egl.pri +++ b/src/hardwareintegration/client/wayland-egl/wayland-egl.pri @@ -8,7 +8,7 @@ INCLUDEPATH += $$PWD DEFINES += QT_EGL_WAYLAND CONFIG += egl -QT += platformsupport-private +QT += egl_support-private SOURCES += $$PWD/qwaylandeglclientbufferintegration.cpp \ $$PWD/qwaylandglcontext.cpp \ diff --git a/src/hardwareintegration/client/xcomposite-egl/qwaylandxcompositeeglclientbufferintegration.cpp b/src/hardwareintegration/client/xcomposite-egl/qwaylandxcompositeeglclientbufferintegration.cpp index 5fca5610a..2a7de6b72 100644 --- a/src/hardwareintegration/client/xcomposite-egl/qwaylandxcompositeeglclientbufferintegration.cpp +++ b/src/hardwareintegration/client/xcomposite-egl/qwaylandxcompositeeglclientbufferintegration.cpp @@ -42,7 +42,7 @@ #include "qwaylandxcompositeeglwindow.h" #include <QtCore/QDebug> -#include <QtPlatformSupport/private/qeglconvenience_p.h> +#include <QtEglSupport/private/qeglconvenience_p.h> #include <QtWaylandClient/private/qwaylanddisplay_p.h> diff --git a/src/hardwareintegration/client/xcomposite-egl/qwaylandxcompositeeglcontext.cpp b/src/hardwareintegration/client/xcomposite-egl/qwaylandxcompositeeglcontext.cpp index 0194878a3..e2e2f5519 100644 --- a/src/hardwareintegration/client/xcomposite-egl/qwaylandxcompositeeglcontext.cpp +++ b/src/hardwareintegration/client/xcomposite-egl/qwaylandxcompositeeglcontext.cpp @@ -44,7 +44,7 @@ #include <QtCore/QDebug> #include <QtGui/QRegion> -#include <QtPlatformSupport/private/qeglconvenience_p.h> +#include <QtEglSupport/private/qeglconvenience_p.h> QT_BEGIN_NAMESPACE diff --git a/src/hardwareintegration/client/xcomposite-egl/qwaylandxcompositeeglcontext.h b/src/hardwareintegration/client/xcomposite-egl/qwaylandxcompositeeglcontext.h index f655dee21..83a643757 100644 --- a/src/hardwareintegration/client/xcomposite-egl/qwaylandxcompositeeglcontext.h +++ b/src/hardwareintegration/client/xcomposite-egl/qwaylandxcompositeeglcontext.h @@ -44,7 +44,7 @@ #include "qwaylandxcompositeeglclientbufferintegration.h" -#include <QtPlatformSupport/private/qeglplatformcontext_p.h> +#include <QtEglSupport/private/qeglplatformcontext_p.h> QT_BEGIN_NAMESPACE diff --git a/src/hardwareintegration/client/xcomposite-egl/qwaylandxcompositeeglwindow.cpp b/src/hardwareintegration/client/xcomposite-egl/qwaylandxcompositeeglwindow.cpp index f9b6fc1de..cfc0cda10 100644 --- a/src/hardwareintegration/client/xcomposite-egl/qwaylandxcompositeeglwindow.cpp +++ b/src/hardwareintegration/client/xcomposite-egl/qwaylandxcompositeeglwindow.cpp @@ -40,8 +40,8 @@ #include "qwaylandxcompositeeglwindow.h" #include "qwaylandxcompositebuffer.h" -#include <QtPlatformSupport/private/qeglconvenience_p.h> -#include <QtPlatformSupport/private/qxlibeglintegration_p.h> +#include <QtEglSupport/private/qeglconvenience_p.h> +#include <QtEglSupport/private/qxlibeglintegration_p.h> #include "wayland-xcomposite-client-protocol.h" diff --git a/src/hardwareintegration/client/xcomposite-egl/xcomposite-egl.pri b/src/hardwareintegration/client/xcomposite-egl/xcomposite-egl.pri index 52653c4ae..3a5fcb543 100644 --- a/src/hardwareintegration/client/xcomposite-egl/xcomposite-egl.pri +++ b/src/hardwareintegration/client/xcomposite-egl/xcomposite-egl.pri @@ -8,7 +8,7 @@ include($$PWD/../xcomposite_share/xcomposite_share.pri) LIBS += -lXcomposite -lX11 } -QT += platformsupport-private +QT += egl_support-private CONFIG += egl SOURCES += \ diff --git a/src/hardwareintegration/client/xcomposite-glx/qwaylandxcompositeglxcontext.h b/src/hardwareintegration/client/xcomposite-glx/qwaylandxcompositeglxcontext.h index 862ed928b..5847ea976 100644 --- a/src/hardwareintegration/client/xcomposite-glx/qwaylandxcompositeglxcontext.h +++ b/src/hardwareintegration/client/xcomposite-glx/qwaylandxcompositeglxcontext.h @@ -43,7 +43,7 @@ #include <qpa/qplatformopenglcontext.h> #include "qwaylandxcompositeglxintegration.h" -#include <QtPlatformSupport/private/qglxconvenience_p.h> +#include <QtGlxSupport/private/qglxconvenience_p.h> QT_BEGIN_NAMESPACE diff --git a/src/hardwareintegration/client/xcomposite-glx/xcomposite-glx.pri b/src/hardwareintegration/client/xcomposite-glx/xcomposite-glx.pri index 11c051728..bc072bf05 100644 --- a/src/hardwareintegration/client/xcomposite-glx/xcomposite-glx.pri +++ b/src/hardwareintegration/client/xcomposite-glx/xcomposite-glx.pri @@ -8,7 +8,7 @@ include ($$PWD/../xcomposite_share/xcomposite_share.pri) LIBS += -lXcomposite -lGL -lX11 } -QT += platformsupport-private +QT += glx_support-private SOURCES += \ $$PWD/qwaylandxcompositeglxcontext.cpp \ diff --git a/src/hardwareintegration/compositor/brcm-egl/brcmeglintegration.cpp b/src/hardwareintegration/compositor/brcm-egl/brcmeglintegration.cpp index 508e88257..940ce82f5 100644 --- a/src/hardwareintegration/compositor/brcm-egl/brcmeglintegration.cpp +++ b/src/hardwareintegration/compositor/brcm-egl/brcmeglintegration.cpp @@ -40,6 +40,7 @@ #include <qpa/qplatformnativeinterface.h> #include <QtGui/QGuiApplication> #include <QtGui/QOpenGLContext> +#include <QOpenGLTexture> #include <qpa/qplatformscreen.h> #include <QtGui/QWindow> @@ -60,6 +61,9 @@ public: : egl_display(EGL_NO_DISPLAY) , valid(false) { } + + static BrcmEglIntegrationPrivate *get(BrcmEglIntegration *integration); + EGLDisplay egl_display; bool valid; PFNEGLQUERYGLOBALIMAGEBRCMPROC eglQueryGlobalImageBRCM; @@ -117,25 +121,46 @@ void BrcmEglIntegration::initializeHardware(struct ::wl_display *display) } } -void BrcmEglIntegration::bindTextureToBuffer(struct ::wl_resource *buffer) +QtWayland::ClientBuffer *BrcmEglIntegration::createBufferFor(wl_resource *buffer) { - Q_D(BrcmEglIntegration); + if (wl_shm_buffer_get(buffer)) + return nullptr; + return new BrcmEglClientBuffer(this, buffer); +} + +BrcmEglIntegrationPrivate *BrcmEglIntegrationPrivate::get(BrcmEglIntegration *integration) +{ + return integration->d_ptr.data(); +} + +QOpenGLTexture *BrcmEglClientBuffer::toOpenGlTexture(int plane) +{ + Q_UNUSED(plane); + + auto d = BrcmEglIntegrationPrivate::get(m_integration); if (!d->valid) { qWarning("bindTextureToBuffer failed!"); - return; + return nullptr; } - BrcmBuffer *brcmBuffer = BrcmBuffer::fromResource(buffer); + BrcmBuffer *brcmBuffer = BrcmBuffer::fromResource(m_buffer); if (!d->eglQueryGlobalImageBRCM(brcmBuffer->handle(), brcmBuffer->handle() + 2)) { qWarning("eglQueryGlobalImageBRCM failed!"); - return; + return nullptr; } EGLImageKHR image = d->eglCreateImageKHR(d->egl_display, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, (EGLClientBuffer)brcmBuffer->handle(), NULL); if (image == EGL_NO_IMAGE_KHR) qWarning("eglCreateImageKHR() failed: %x\n", eglGetError()); + if (!m_texture) { + m_texture = new QOpenGLTexture(QOpenGLTexture::Target2D); + m_texture->create(); + } + + m_texture->bind(); + d->glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -144,6 +169,8 @@ void BrcmEglIntegration::bindTextureToBuffer(struct ::wl_resource *buffer) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); d->eglDestroyImageKHR(d->egl_display, image); + + return m_texture; } void BrcmEglIntegration::brcm_bind_resource(Resource *) @@ -155,11 +182,29 @@ void BrcmEglIntegration::brcm_create_buffer(Resource *resource, uint32_t id, int new BrcmBuffer(resource->client(), id, QSize(width, height), static_cast<EGLint *>(data->data), data->size / sizeof(EGLint)); } -QSize BrcmEglIntegration::bufferSize(struct ::wl_resource *buffer) const +BrcmEglClientBuffer::BrcmEglClientBuffer(BrcmEglIntegration *integration, wl_resource *buffer) + : ClientBuffer(buffer) + , m_integration(integration) + , m_texture(nullptr) +{ +} + +QWaylandBufferRef::BufferFormatEgl BrcmEglClientBuffer::bufferFormatEgl() const { - BrcmBuffer *brcmBuffer = BrcmBuffer::fromResource(buffer); + return QWaylandBufferRef::BufferFormatEgl_RGBA; +} +QSize BrcmEglClientBuffer::size() const +{ + BrcmBuffer *brcmBuffer = BrcmBuffer::fromResource(m_buffer); return brcmBuffer->size(); } +QWaylandSurface::Origin BrcmEglClientBuffer::origin() const +{ + BrcmBuffer *brcmBuffer = BrcmBuffer::fromResource(m_buffer); + return brcmBuffer->isYInverted() ? QWaylandSurface::OriginTopLeft : QWaylandSurface::OriginBottomLeft; +} + + QT_END_NAMESPACE diff --git a/src/hardwareintegration/compositor/brcm-egl/brcmeglintegration.h b/src/hardwareintegration/compositor/brcm-egl/brcmeglintegration.h index 48dd9c42e..a1d39e4fe 100644 --- a/src/hardwareintegration/compositor/brcm-egl/brcmeglintegration.h +++ b/src/hardwareintegration/compositor/brcm-egl/brcmeglintegration.h @@ -42,6 +42,8 @@ #include <QtCore/QScopedPointer> +#include <private/qwlclientbuffer_p.h> + QT_BEGIN_NAMESPACE class BrcmEglIntegrationPrivate; @@ -53,10 +55,7 @@ public: BrcmEglIntegration(); void initializeHardware(struct ::wl_display *display) Q_DECL_OVERRIDE; - - void bindTextureToBuffer(struct ::wl_resource *buffer) Q_DECL_OVERRIDE; - - QSize bufferSize(struct ::wl_resource *buffer) const Q_DECL_OVERRIDE; + QtWayland::ClientBuffer *createBufferFor(wl_resource *buffer) Q_DECL_OVERRIDE; protected: void brcm_bind_resource(Resource *resource) Q_DECL_OVERRIDE; @@ -67,6 +66,21 @@ private: QScopedPointer<BrcmEglIntegrationPrivate> d_ptr; }; +class BrcmEglClientBuffer : public QtWayland::ClientBuffer +{ +public: + BrcmEglClientBuffer(BrcmEglIntegration *integration, wl_resource *buffer); + + QWaylandBufferRef::BufferFormatEgl bufferFormatEgl() const Q_DECL_OVERRIDE; + QSize size() const Q_DECL_OVERRIDE; + QWaylandSurface::Origin origin() const Q_DECL_OVERRIDE; + QOpenGLTexture *toOpenGlTexture(int plane) Q_DECL_OVERRIDE; +private: + BrcmEglIntegration *m_integration; + QOpenGLTexture *m_texture; +}; + + QT_END_NAMESPACE #endif // BRCMEGLINTEGRATION_H diff --git a/src/hardwareintegration/compositor/wayland-egl/wayland-egl.pri b/src/hardwareintegration/compositor/wayland-egl/wayland-egl.pri index 8dacc130b..f36474890 100644 --- a/src/hardwareintegration/compositor/wayland-egl/wayland-egl.pri +++ b/src/hardwareintegration/compositor/wayland-egl/wayland-egl.pri @@ -8,6 +8,7 @@ INCLUDEPATH += $$PWD } CONFIG += egl +QT += egl_support-private SOURCES += \ $$PWD/waylandeglclientbufferintegration.cpp diff --git a/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp b/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp index 4416d103c..8b87db971 100644 --- a/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp +++ b/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp @@ -40,6 +40,7 @@ #include <qpa/qplatformnativeinterface.h> #include <QtGui/QGuiApplication> #include <QtGui/QOpenGLContext> +#include <QtGui/QOpenGLTexture> #include <qpa/qplatformscreen.h> #include <QtGui/QWindow> #include <QtCore/QPointer> @@ -48,7 +49,7 @@ #include <QMutex> #include <QMutexLocker> #include <QtCore/private/qcore_unix_p.h> -#include <QtPlatformSupport/private/qeglstreamconvenience_p.h> +#include <QtEglSupport/private/qeglstreamconvenience_p.h> #ifndef GL_TEXTURE_EXTERNAL_OES #define GL_TEXTURE_EXTERNAL_OES 0x8D65 @@ -90,6 +91,10 @@ #define EGL_TEXTURE_Y_XUXV_WL 0x31D9 #endif +#ifndef EGL_PLATFORM_X11_KHR +#define EGL_PLATFORM_X11_KHR 0x31D5 +#endif + /* Needed for compatibility with Mesa older than 10.0. */ typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYWAYLANDBUFFERWL_compat) (EGLDisplay dpy, struct wl_resource *buffer, EGLint attribute, EGLint *value); @@ -110,17 +115,50 @@ typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenu QT_BEGIN_NAMESPACE +static const char * +egl_error_string(EGLint code) +{ +#define MYERRCODE(x) case x: return #x; + switch (code) { + MYERRCODE(EGL_SUCCESS) + MYERRCODE(EGL_NOT_INITIALIZED) + MYERRCODE(EGL_BAD_ACCESS) + MYERRCODE(EGL_BAD_ALLOC) + MYERRCODE(EGL_BAD_ATTRIBUTE) + MYERRCODE(EGL_BAD_CONTEXT) + MYERRCODE(EGL_BAD_CONFIG) + MYERRCODE(EGL_BAD_CURRENT_SURFACE) + MYERRCODE(EGL_BAD_DISPLAY) + MYERRCODE(EGL_BAD_SURFACE) + MYERRCODE(EGL_BAD_MATCH) + MYERRCODE(EGL_BAD_PARAMETER) + MYERRCODE(EGL_BAD_NATIVE_PIXMAP) + MYERRCODE(EGL_BAD_NATIVE_WINDOW) + MYERRCODE(EGL_CONTEXT_LOST) + default: + return "unknown"; + } +#undef MYERRCODE +} + struct BufferState { BufferState(); + enum EglMode { + ModeNone, + ModeEGLImage, + ModeEGLStream + }; + EGLint egl_format; QVarLengthArray<EGLImageKHR, 3> egl_images; + QOpenGLTexture *textures[3]; EGLStreamKHR egl_stream; - GLuint eglstream_texture; bool isYInverted; QSize size; + EglMode eglMode; }; class WaylandEglClientBufferIntegrationPrivate @@ -128,18 +166,14 @@ class WaylandEglClientBufferIntegrationPrivate public: WaylandEglClientBufferIntegrationPrivate(); - void attach(struct ::wl_resource *buffer); - void attach_egl_texture(struct ::wl_resource *buffer, EGLint format); - void attach_egl_fd_texture(struct ::wl_resource *buffer, EGLNativeFileDescriptorKHR streamFd); + void initBuffer(WaylandEglClientBuffer *buffer); + void init_egl_texture(WaylandEglClientBuffer *buffer, EGLint format); + void init_egl_fd_texture(WaylandEglClientBuffer *buffer, EGLNativeFileDescriptorKHR streamFd); void register_buffer(struct ::wl_resource *buffer, BufferState state); - void bindBuffer(struct ::wl_resource *buffer); - - static void handle_buffer_destroy(wl_listener *listener, void *data); EGLDisplay egl_display; bool valid; bool display_bound; - QHash<struct ::wl_resource *, BufferState> buffers; PFNEGLBINDWAYLANDDISPLAYWL egl_bind_wayland_display; PFNEGLUNBINDWAYLANDDISPLAYWL egl_unbind_wayland_display; @@ -151,25 +185,16 @@ public: PFNGLEGLIMAGETARGETTEXTURE2DOESPROC gl_egl_image_target_texture_2d; QEGLStreamConvenience *funcs; -}; - -struct buffer_destroy_listener : wl_listener -{ - buffer_destroy_listener() - : d(0) - { - notify = WaylandEglClientBufferIntegrationPrivate::handle_buffer_destroy; - wl_list_init(&this->link); + static WaylandEglClientBufferIntegrationPrivate *get(WaylandEglClientBufferIntegration *integration) { + return integration->d_ptr.data(); } - - WaylandEglClientBufferIntegrationPrivate *d; }; BufferState::BufferState() : egl_format(EGL_TEXTURE_RGBA) , egl_stream(EGL_NO_STREAM_KHR) - , eglstream_texture(0) , isYInverted(true) + , eglMode(ModeNone) {} WaylandEglClientBufferIntegrationPrivate::WaylandEglClientBufferIntegrationPrivate() @@ -183,21 +208,21 @@ WaylandEglClientBufferIntegrationPrivate::WaylandEglClientBufferIntegrationPriva , egl_destroy_image(0) , gl_egl_image_target_texture_2d(0) , funcs(Q_NULLPTR) -{} +{ +} -void WaylandEglClientBufferIntegrationPrivate::attach(struct ::wl_resource *buffer) +void WaylandEglClientBufferIntegrationPrivate::initBuffer(WaylandEglClientBuffer *buffer) { EGLint format; - EGLNativeFileDescriptorKHR streamFd = EGL_NO_FILE_DESCRIPTOR_KHR; - if (egl_query_wayland_buffer(egl_display, buffer, EGL_TEXTURE_FORMAT, &format)) - attach_egl_texture(buffer, format); - else if (egl_query_wayland_buffer(egl_display, buffer, EGL_WAYLAND_BUFFER_WL, &streamFd)) - attach_egl_fd_texture(buffer, streamFd); + if (egl_query_wayland_buffer(egl_display, buffer->waylandBufferHandle(), EGL_TEXTURE_FORMAT, &format)) + init_egl_texture(buffer, format); } -void WaylandEglClientBufferIntegrationPrivate::attach_egl_texture(struct ::wl_resource *buffer, EGLint format) +void WaylandEglClientBufferIntegrationPrivate::init_egl_texture(WaylandEglClientBuffer *buffer, EGLint format) { +// Non-streaming case + // Resolving GL functions may need a context current, so do it only here. if (!gl_egl_image_target_texture_2d) gl_egl_image_target_texture_2d = reinterpret_cast<PFNGLEGLIMAGETARGETTEXTURE2DOESPROC>(eglGetProcAddress("glEGLImageTargetTexture2DOES")); @@ -207,12 +232,13 @@ void WaylandEglClientBufferIntegrationPrivate::attach_egl_texture(struct ::wl_re return; } - BufferState state; + BufferState &state = *buffer->d; state.egl_format = format; + state.eglMode = BufferState::ModeEGLImage; #if defined(EGL_WAYLAND_Y_INVERTED_WL) EGLint isYInverted; - EGLBoolean ret = egl_query_wayland_buffer(egl_display, buffer, EGL_WAYLAND_Y_INVERTED_WL, &isYInverted); + EGLBoolean ret = egl_query_wayland_buffer(egl_display, buffer->waylandBufferHandle(), EGL_WAYLAND_Y_INVERTED_WL, &isYInverted); // Yes, this looks strange, but the specification says that EGL_FALSE return // value (not supported) should be treated the same as EGL_TRUE return value // and EGL_TRUE in value. @@ -244,21 +270,21 @@ void WaylandEglClientBufferIntegrationPrivate::attach_egl_texture(struct ::wl_re EGLImageKHR image = egl_create_image(egl_display, EGL_NO_CONTEXT, EGL_WAYLAND_BUFFER_WL, - buffer, + buffer->waylandBufferHandle(), attribs); if (image == EGL_NO_IMAGE_KHR) qWarning("failed to create EGL image for plane %d", i); state.egl_images << image; + state.textures[i] = nullptr; } - - register_buffer(buffer, state); } -void WaylandEglClientBufferIntegrationPrivate::attach_egl_fd_texture(struct ::wl_resource *buffer, EGLNativeFileDescriptorKHR streamFd) +void WaylandEglClientBufferIntegrationPrivate::init_egl_fd_texture(WaylandEglClientBuffer *buffer, EGLNativeFileDescriptorKHR streamFd) { - BufferState state; +//EglStreams case + BufferState &state = *buffer->d; state.egl_format = EGL_TEXTURE_EXTERNAL_WL; state.isYInverted = false; @@ -270,106 +296,37 @@ void WaylandEglClientBufferIntegrationPrivate::attach_egl_fd_texture(struct ::wl qWarning("%s:%d: eglCreateStreamFromFileDescriptorKHR failed: 0x%x", Q_FUNC_INFO, __LINE__, eglGetError()); return; } + state.eglMode = BufferState::ModeEGLStream; if (!QOpenGLContext::currentContext()) qWarning("EglClientBufferIntegration: creating texture with no current context"); //TODO This texture might end up in a different context than the quick item which wants to use it, this needs to be fixed somehow. - glGenTextures(1, &state.eglstream_texture); + + auto texture = new QOpenGLTexture(static_cast<QOpenGLTexture::Target>(GL_TEXTURE_EXTERNAL_OES)); + texture->create(); + state.textures[0] = texture; // TODO: support multiple planes for the streaming case + glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_EXTERNAL_OES, state.eglstream_texture); + texture->create(); + texture->bind(); + glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture->textureId()); + glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - register_buffer(buffer, state); - - bindBuffer(buffer); -} - -void WaylandEglClientBufferIntegrationPrivate::register_buffer(struct ::wl_resource *buffer, BufferState state) -{ - Q_ASSERT(!buffers.contains(buffer)); - - EGLint width, height; - egl_query_wayland_buffer(egl_display, buffer, EGL_WIDTH, &width); - egl_query_wayland_buffer(egl_display, buffer, EGL_HEIGHT, &height); - state.size = QSize(width, height); - - buffers[buffer] = state; - - buffer_destroy_listener *destroy_listener = new buffer_destroy_listener; - destroy_listener->d = this; - wl_signal_add(&buffer->destroy_signal, destroy_listener); -} - -void WaylandEglClientBufferIntegrationPrivate::bindBuffer(struct ::wl_resource *buffer) -{ - if (!valid) { - qWarning("QtCompositor: bindTextureToBuffer() failed"); - return; - } + auto newStream = funcs->stream_consumer_gltexture(egl_display, state.egl_stream); - if (!buffer || !buffers.contains(buffer)) - return; - - const BufferState state = buffers.value(buffer); - - if (state.egl_stream != EGL_NO_STREAM_KHR) { - EGLint stream_state; - funcs->query_stream(egl_display, state.egl_stream, EGL_STREAM_STATE_KHR, &stream_state); - - if (stream_state == EGL_STREAM_STATE_CREATED_KHR) - if (funcs->stream_consumer_gltexture(egl_display, state.egl_stream) != EGL_TRUE) - qWarning("%s:%d: eglStreamConsumerGLTextureExternalKHR failed: 0x%x", Q_FUNC_INFO, __LINE__, eglGetError()); - } else { - GLint previousTexture = GL_TEXTURE0; - glGetIntegerv(GL_ACTIVE_TEXTURE, &previousTexture); - - const GLenum target = (state.egl_format == EGL_TEXTURE_EXTERNAL_WL) ? GL_TEXTURE_EXTERNAL_OES - : GL_TEXTURE_2D; - - for (int i = 0; i < state.egl_images.size(); i++) { - glActiveTexture(GL_TEXTURE0 + i); - glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - gl_egl_image_target_texture_2d(target, state.egl_images[i]); - } - - glActiveTexture(previousTexture); + if (!newStream) { + EGLint code = eglGetError(); + qWarning() << "Could not initialize EGLStream:" << egl_error_string(code) << hex << (long)code; + funcs->destroy_stream(egl_display, state.egl_stream); + state.egl_stream = EGL_NO_STREAM_KHR; } } -void WaylandEglClientBufferIntegrationPrivate::handle_buffer_destroy(wl_listener *listener, void *data) -{ - buffer_destroy_listener *destroy_listener = static_cast<buffer_destroy_listener *>(listener); - WaylandEglClientBufferIntegrationPrivate *self = destroy_listener->d; - struct ::wl_resource *buffer = static_cast<struct ::wl_resource *>(data); - - wl_list_remove(&destroy_listener->link); - delete destroy_listener; - - if (!self->buffers.contains(buffer)) - return; - - Q_ASSERT(self); - Q_ASSERT(buffer); - - BufferState state = self->buffers.take(buffer); - - // We would need to delete the texture of the egl_stream here, but we can't as this breaks the - // texture of the new stream when the window is resized. It seems wayland takes care to delete the texture for us. - - for (int i = 0; i < state.egl_images.size(); i++) - self->egl_destroy_image(self->egl_display, state.egl_images[i]); - - if (state.egl_stream != EGL_NO_STREAM_KHR) - self->funcs->destroy_stream(self->egl_display, state.egl_stream); -} - WaylandEglClientBufferIntegration::WaylandEglClientBufferIntegration() : QtWayland::ClientBufferIntegration() , d_ptr(new WaylandEglClientBufferIntegrationPrivate) @@ -438,17 +395,27 @@ void WaylandEglClientBufferIntegration::initializeHardware(struct wl_display *di d->valid = true; } -void WaylandEglClientBufferIntegration::initializeBuffer(struct ::wl_resource *buffer) +QtWayland::ClientBuffer *WaylandEglClientBufferIntegration::createBufferFor(wl_resource *buffer) { - Q_D(WaylandEglClientBufferIntegration); - if (wl_shm_buffer_get(buffer)) - return; - - if (!buffer || d->buffers.contains(buffer)) - return; + return nullptr; + return new WaylandEglClientBuffer(this, buffer); +} - d->attach(buffer); +WaylandEglClientBuffer::WaylandEglClientBuffer(WaylandEglClientBufferIntegration *integration, wl_resource *buffer) + : ClientBuffer(buffer) + , m_integration(integration) +{ + auto *p = WaylandEglClientBufferIntegrationPrivate::get(m_integration); + d = new BufferState; + if (buffer && !wl_shm_buffer_get(buffer)) { + EGLint width, height; + p->egl_query_wayland_buffer(p->egl_display, buffer, EGL_WIDTH, &width); + p->egl_query_wayland_buffer(p->egl_display, buffer, EGL_HEIGHT, &height); + d->size = QSize(width, height); + + p->initBuffer(this); + } } static QWaylandBufferRef::BufferFormatEgl formatFromEglFormat(EGLint format) { @@ -470,117 +437,92 @@ static QWaylandBufferRef::BufferFormatEgl formatFromEglFormat(EGLint format) { return QWaylandBufferRef::BufferFormatEgl_RGBA; } -QWaylandBufferRef::BufferFormatEgl WaylandEglClientBufferIntegration::bufferFormat(wl_resource *buffer) -{ - Q_D(const WaylandEglClientBufferIntegration); - return formatFromEglFormat(d->buffers.value(buffer).egl_format); -} - -uint WaylandEglClientBufferIntegration::textureForBuffer(wl_resource *buffer, int plane) +QWaylandBufferRef::BufferFormatEgl WaylandEglClientBuffer::bufferFormatEgl() const { - Q_UNUSED(plane) - Q_D(WaylandEglClientBufferIntegration); - if (!buffer) - return 0; - - const BufferState state = d->buffers.value(buffer); - return state.eglstream_texture; -} - -void WaylandEglClientBufferIntegration::bindTextureToBuffer(struct ::wl_resource *buffer) -{ - Q_D(WaylandEglClientBufferIntegration); - d->bindBuffer(buffer); + return formatFromEglFormat(d->egl_format); } -// Update is only needed for the EGLStream path as that requires calling acquire -// on every frame. bindTextureToBuffer() is typically invoked only upon attach -// so that is insufficient. -void WaylandEglClientBufferIntegration::updateTextureForBuffer(struct ::wl_resource *buffer) +QOpenGLTexture *WaylandEglClientBuffer::toOpenGlTexture(int plane) { - Q_D(WaylandEglClientBufferIntegration); - if (!d->valid) { - qWarning("QtCompositor: updateTextureForBuffer() failed"); - return; + if (!m_buffer) + return nullptr; + + auto *p = WaylandEglClientBufferIntegrationPrivate::get(m_integration); + auto texture = d->textures[plane]; + const auto target = static_cast<QOpenGLTexture::Target>((d->eglMode == BufferState::ModeEGLStream || d->egl_format == EGL_TEXTURE_EXTERNAL_WL) ? GL_TEXTURE_EXTERNAL_OES + : GL_TEXTURE_2D); + if (!texture) { + texture = new QOpenGLTexture(target); + texture->create(); + d->textures[plane] = texture; } - if (!buffer) - return; - const BufferState state = d->buffers.value(buffer); + if (d->eglMode == BufferState::ModeEGLStream) { + // EGLStream requires calling acquire on every frame. + if (d->egl_stream != EGL_NO_STREAM_KHR) { - if (state.egl_stream != EGL_NO_STREAM_KHR) { - EGLint stream_state; - d->funcs->query_stream(d->egl_display, state.egl_stream, EGL_STREAM_STATE_KHR, &stream_state); + texture->bind(); - if (stream_state == EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR) { - if (d->funcs->stream_consumer_acquire(d->egl_display, state.egl_stream) != EGL_TRUE) - qWarning("%s:%d: eglStreamConsumerAcquireKHR failed: 0x%x", Q_FUNC_INFO, __LINE__, eglGetError()); + EGLint stream_state; + p->funcs->query_stream(p->egl_display, d->egl_stream, EGL_STREAM_STATE_KHR, &stream_state); + + if (stream_state == EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR) { + if (p->funcs->stream_consumer_acquire(p->egl_display, d->egl_stream) != EGL_TRUE) + qWarning("%s:%d: eglStreamConsumerAcquireKHR failed: 0x%x", Q_FUNC_INFO, __LINE__, eglGetError()); + } } + } else if (m_textureDirty) { + texture->bind(); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + p->gl_egl_image_target_texture_2d(target, d->egl_images[plane]); } + return texture; } -QWaylandSurface::Origin WaylandEglClientBufferIntegration::origin(struct ::wl_resource *buffer) const +void WaylandEglClientBuffer::setCommitted(QRegion &damage) { - Q_D(const WaylandEglClientBufferIntegration); - - if (d->buffers.contains(buffer)) - return d->buffers[buffer].isYInverted ? QWaylandSurface::OriginTopLeft : QWaylandSurface::OriginBottomLeft; - -#if defined(EGL_WAYLAND_Y_INVERTED_WL) - EGLint isYInverted; - EGLBoolean ret = EGL_FALSE; - if (buffer) - ret = d->egl_query_wayland_buffer(d->egl_display, buffer, EGL_WAYLAND_Y_INVERTED_WL, &isYInverted); - // Yes, this looks strange, but the specification says that EGL_FALSE return - // value (not supported) should be treated the same as EGL_TRUE return value - // and EGL_TRUE in value. - if (ret == EGL_FALSE || isYInverted == EGL_TRUE) - return QWaylandSurface::OriginTopLeft; - return QWaylandSurface::OriginBottomLeft; -#endif - - return QtWayland::ClientBufferIntegration::origin(buffer); + ClientBuffer::setCommitted(damage); + if (d->eglMode == BufferState::ModeNone) { + EGLNativeFileDescriptorKHR streamFd = EGL_NO_FILE_DESCRIPTOR_KHR; + auto *p = WaylandEglClientBufferIntegrationPrivate::get(m_integration); + if (p->egl_query_wayland_buffer(p->egl_display, waylandBufferHandle(), EGL_WAYLAND_BUFFER_WL, &streamFd)) + p->init_egl_fd_texture(this, streamFd); + } } +QWaylandSurface::Origin WaylandEglClientBuffer::origin() const +{ + return d->isYInverted ? QWaylandSurface::OriginTopLeft : QWaylandSurface::OriginBottomLeft; +} -void *WaylandEglClientBufferIntegration::lockNativeBuffer(struct ::wl_resource *buffer) const +quintptr WaylandEglClientBuffer::lockNativeBuffer() { - Q_D(const WaylandEglClientBufferIntegration); + auto *p = WaylandEglClientBufferIntegrationPrivate::get(m_integration); - if (d->buffers.contains(buffer) && d->buffers[buffer].egl_stream != EGL_NO_STREAM_KHR) + if (d->egl_stream != EGL_NO_STREAM_KHR) return 0; - EGLImageKHR image = d->egl_create_image(d->egl_display, EGL_NO_CONTEXT, + EGLImageKHR image = p->egl_create_image(p->egl_display, EGL_NO_CONTEXT, EGL_WAYLAND_BUFFER_WL, - buffer, NULL); - return image; + m_buffer, NULL); + return reinterpret_cast<quintptr>(image); } -void WaylandEglClientBufferIntegration::unlockNativeBuffer(void *native_buffer) const +void WaylandEglClientBuffer::unlockNativeBuffer(quintptr native_buffer) const { - Q_D(const WaylandEglClientBufferIntegration); - if (!native_buffer) return; - EGLImageKHR image = static_cast<EGLImageKHR>(native_buffer); - d->egl_destroy_image(d->egl_display, image); + auto *p = WaylandEglClientBufferIntegrationPrivate::get(m_integration); + + EGLImageKHR image = reinterpret_cast<EGLImageKHR>(native_buffer); + p->egl_destroy_image(p->egl_display, image); } -QSize WaylandEglClientBufferIntegration::bufferSize(struct ::wl_resource *buffer) const +QSize WaylandEglClientBuffer::size() const { - Q_D(const WaylandEglClientBufferIntegration); - - if (d->buffers.contains(buffer)) { - return d->buffers[buffer].size; - } else { - int width, height; - d->egl_query_wayland_buffer(d->egl_display, buffer, EGL_WIDTH, &width); - d->egl_query_wayland_buffer(d->egl_display, buffer, EGL_HEIGHT, &height); - - return QSize(width, height); - } + return d->size; } QT_END_NAMESPACE diff --git a/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.h b/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.h index 74cad708d..c93ce1dd8 100644 --- a/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.h +++ b/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.h @@ -39,6 +39,7 @@ #include <QtWaylandCompositor/private/qwlclientbufferintegration_p.h> #include <QtCore/QScopedPointer> +#include <QtWaylandCompositor/private/qwlclientbuffer_p.h> QT_BEGIN_NAMESPACE @@ -52,22 +53,34 @@ public: void initializeHardware(struct ::wl_display *display) Q_DECL_OVERRIDE; - void initializeBuffer(struct ::wl_resource *buffer) Q_DECL_OVERRIDE; - QWaylandBufferRef::BufferFormatEgl bufferFormat(struct ::wl_resource *buffer) Q_DECL_OVERRIDE; - uint textureForBuffer(struct ::wl_resource *buffer, int plane) Q_DECL_OVERRIDE; - void bindTextureToBuffer(struct ::wl_resource *buffer) Q_DECL_OVERRIDE; - void updateTextureForBuffer(struct ::wl_resource *buffer) Q_DECL_OVERRIDE; + QtWayland::ClientBuffer *createBufferFor(wl_resource *buffer); - QWaylandSurface::Origin origin(struct ::wl_resource *) const Q_DECL_OVERRIDE; +private: + Q_DISABLE_COPY(WaylandEglClientBufferIntegration) + QScopedPointer<WaylandEglClientBufferIntegrationPrivate> d_ptr; +}; - void *lockNativeBuffer(struct ::wl_resource *buffer) const Q_DECL_OVERRIDE; - void unlockNativeBuffer(void *native_buffer) const Q_DECL_OVERRIDE; +struct BufferState; - QSize bufferSize(struct ::wl_resource *buffer) const Q_DECL_OVERRIDE; +class WaylandEglClientBuffer : public QtWayland::ClientBuffer +{ +public: + QWaylandBufferRef::BufferFormatEgl bufferFormatEgl() const Q_DECL_OVERRIDE; + QSize size() const Q_DECL_OVERRIDE; + QWaylandSurface::Origin origin() const Q_DECL_OVERRIDE; + quintptr lockNativeBuffer() Q_DECL_OVERRIDE; + void unlockNativeBuffer(quintptr native_buffer) const Q_DECL_OVERRIDE; + QOpenGLTexture *toOpenGlTexture(int plane) Q_DECL_OVERRIDE; + void setCommitted(QRegion &damage) Q_DECL_OVERRIDE; private: - Q_DISABLE_COPY(WaylandEglClientBufferIntegration) - QScopedPointer<WaylandEglClientBufferIntegrationPrivate> d_ptr; + friend class WaylandEglClientBufferIntegration; + friend class WaylandEglClientBufferIntegrationPrivate; + + WaylandEglClientBuffer(WaylandEglClientBufferIntegration* integration, wl_resource *bufferResource); + + BufferState *d; + WaylandEglClientBufferIntegration *m_integration; }; QT_END_NAMESPACE diff --git a/src/hardwareintegration/compositor/xcomposite-egl/xcompositeeglintegration.cpp b/src/hardwareintegration/compositor/xcomposite-egl/xcompositeeglintegration.cpp index e858a8e78..1a478052b 100644 --- a/src/hardwareintegration/compositor/xcomposite-egl/xcompositeeglintegration.cpp +++ b/src/hardwareintegration/compositor/xcomposite-egl/xcompositeeglintegration.cpp @@ -40,6 +40,7 @@ #include <QtWaylandCompositor/QWaylandCompositor> #include <QtGui/QGuiApplication> +#include <QtGui/QOpenGLTexture> #include <qpa/qplatformnativeinterface.h> #include <qpa/qplatformopenglcontext.h> @@ -83,23 +84,38 @@ void XCompositeEglClientBufferIntegration::initializeHardware(struct ::wl_displa } else { qFatal("Platform integration doesn't have native interface"); } - mScreen = XDefaultScreen(mDisplay); new XCompositeHandler(m_compositor, mDisplay); } -void XCompositeEglClientBufferIntegration::bindTextureToBuffer(struct ::wl_resource *buffer) +QtWayland::ClientBuffer *XCompositeEglClientBufferIntegration::createBufferFor(wl_resource *buffer) { - XCompositeBuffer *compositorBuffer = XCompositeBuffer::fromResource(buffer); - Pixmap pixmap = XCompositeNameWindowPixmap(mDisplay, compositorBuffer->window()); + if (wl_shm_buffer_get(buffer)) + return nullptr; + return new XCompositeEglClientBuffer(this, buffer); +} + + +XCompositeEglClientBuffer::XCompositeEglClientBuffer(XCompositeEglClientBufferIntegration *integration, wl_resource *bufferResource) + : QtWayland::ClientBuffer(bufferResource) + , m_texture(nullptr) + , m_integration(integration) +{ +} + +QOpenGLTexture *XCompositeEglClientBuffer::toOpenGlTexture(int plane) +{ + Q_UNUSED(plane); + XCompositeBuffer *compositorBuffer = XCompositeBuffer::fromResource(m_buffer); + Pixmap pixmap = XCompositeNameWindowPixmap(m_integration->xDisplay(), compositorBuffer->window()); QVector<EGLint> eglConfigSpec = eglbuildSpec(); EGLint matching = 0; EGLConfig config; - bool matched = eglChooseConfig(mEglDisplay,eglConfigSpec.constData(),&config,1,&matching); + bool matched = eglChooseConfig(m_integration->eglDisplay(),eglConfigSpec.constData(),&config,1,&matching); if (!matched || !matching) { qWarning("Could not retrieve a suitable EGL config"); - return; + return nullptr; } QVector<EGLint> attribList; @@ -110,29 +126,37 @@ void XCompositeEglClientBufferIntegration::bindTextureToBuffer(struct ::wl_resou attribList.append(EGL_TEXTURE_2D); attribList.append(EGL_NONE); - EGLSurface surface = eglCreatePixmapSurface(mEglDisplay,config,pixmap,attribList.constData()); + EGLSurface surface = eglCreatePixmapSurface(m_integration->eglDisplay(),config,pixmap,attribList.constData()); if (surface == EGL_NO_SURFACE) { qDebug() << "Failed to create eglsurface" << pixmap << compositorBuffer->window(); } compositorBuffer->setOrigin(QWaylandSurface::OriginTopLeft); - if (!eglBindTexImage(mEglDisplay,surface,EGL_BACK_BUFFER)) { - qDebug() << "Failed to bind"; + if (!m_texture) { + m_texture = new QOpenGLTexture(QOpenGLTexture::Target2D); + m_texture->create(); + } + m_texture->bind(); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + if (!eglBindTexImage(m_integration->eglDisplay(),surface,EGL_BACK_BUFFER)) { + qWarning() << "Failed to bind"; } // eglDestroySurface(mEglDisplay,surface); + return m_texture; } -QWaylandSurface::Origin XCompositeEglClientBufferIntegration::origin(struct ::wl_resource *buffer) const + +QWaylandSurface::Origin XCompositeEglClientBuffer::origin() const { - XCompositeBuffer *compositorBuffer = XCompositeBuffer::fromResource(buffer); + XCompositeBuffer *compositorBuffer = XCompositeBuffer::fromResource(m_buffer); return compositorBuffer->origin(); } -QSize XCompositeEglClientBufferIntegration::bufferSize(struct ::wl_resource *buffer) const +QSize XCompositeEglClientBuffer::size() const { - XCompositeBuffer *compositorBuffer = XCompositeBuffer::fromResource(buffer); + XCompositeBuffer *compositorBuffer = XCompositeBuffer::fromResource(m_buffer); return compositorBuffer->size(); } diff --git a/src/hardwareintegration/compositor/xcomposite-egl/xcompositeeglintegration.h b/src/hardwareintegration/compositor/xcomposite-egl/xcompositeeglintegration.h index c14e582ed..ec4ea284b 100644 --- a/src/hardwareintegration/compositor/xcomposite-egl/xcompositeeglintegration.h +++ b/src/hardwareintegration/compositor/xcomposite-egl/xcompositeeglintegration.h @@ -40,7 +40,7 @@ #include <QtWaylandCompositor/private/qwlclientbufferintegration_p.h> #include <QtWaylandCompositor/QWaylandCompositor> - +#include <QtWaylandCompositor/private/qwlclientbuffer_p.h> #include "xlibinclude.h" #include <EGL/egl.h> @@ -53,16 +53,30 @@ public: XCompositeEglClientBufferIntegration(); void initializeHardware(struct ::wl_display *display) Q_DECL_OVERRIDE; - - void bindTextureToBuffer(struct ::wl_resource *buffer) Q_DECL_OVERRIDE; - QWaylandSurface::Origin origin(struct ::wl_resource *) const Q_DECL_OVERRIDE; - - QSize bufferSize(struct ::wl_resource *buffer) const Q_DECL_OVERRIDE; + QtWayland::ClientBuffer *createBufferFor(wl_resource *buffer) Q_DECL_OVERRIDE; + inline Display *xDisplay() const { return mDisplay; } + inline EGLDisplay eglDisplay() const { return mEglDisplay; } private: Display *mDisplay; EGLDisplay mEglDisplay; - int mScreen; +}; + +class XCompositeEglClientBuffer : public QtWayland::ClientBuffer +{ +public: + XCompositeEglClientBuffer(XCompositeEglClientBufferIntegration *integration, wl_resource *bufferResource); + + QSize size() const; + QWaylandSurface::Origin origin() const; + QOpenGLTexture *toOpenGlTexture(int plane) Q_DECL_OVERRIDE; + QWaylandBufferRef::BufferFormatEgl bufferFormatEgl() const Q_DECL_OVERRIDE { + return QWaylandBufferRef::BufferFormatEgl_RGBA; + } + +private: + QOpenGLTexture *m_texture; + XCompositeEglClientBufferIntegration *m_integration; }; QT_END_NAMESPACE diff --git a/src/hardwareintegration/compositor/xcomposite-glx/xcompositeglxintegration.cpp b/src/hardwareintegration/compositor/xcomposite-glx/xcompositeglxintegration.cpp index 6f70d2bbf..0b11c2630 100644 --- a/src/hardwareintegration/compositor/xcomposite-glx/xcompositeglxintegration.cpp +++ b/src/hardwareintegration/compositor/xcomposite-glx/xcompositeglxintegration.cpp @@ -41,6 +41,7 @@ #include <qpa/qplatformnativeinterface.h> #include <qpa/qplatformintegration.h> #include <QtGui/QOpenGLContext> +#include <QtGui/QOpenGLTexture> #include "xcompositebuffer.h" #include "xcompositehandler.h" @@ -109,14 +110,31 @@ void XCompositeGLXClientBufferIntegration::initializeHardware(struct ::wl_displa delete glContext; } -void XCompositeGLXClientBufferIntegration::bindTextureToBuffer(struct ::wl_resource *buffer) +QtWayland::ClientBuffer *XCompositeGLXClientBufferIntegration::createBufferFor(wl_resource *buffer) { - XCompositeBuffer *compositorBuffer = XCompositeBuffer::fromResource(buffer); - Pixmap pixmap = XCompositeNameWindowPixmap(mDisplay, compositorBuffer->window()); + if (wl_shm_buffer_get(buffer)) + return nullptr; + return new XCompositeGLXClientBuffer(this, buffer); +} + +XCompositeGLXClientBuffer::XCompositeGLXClientBuffer(XCompositeGLXClientBufferIntegration *integration, wl_resource *bufferResource) + : QtWayland::ClientBuffer(bufferResource) + , m_texture(nullptr) + , m_integration(integration) + , m_glxPixmap(0) +{ +} + + +QOpenGLTexture *XCompositeGLXClientBuffer::toOpenGlTexture(int plane) +{ + Q_UNUSED(plane); + XCompositeBuffer *compositorBuffer = XCompositeBuffer::fromResource(m_buffer); + Pixmap pixmap = XCompositeNameWindowPixmap(m_integration->xDisplay(), compositorBuffer->window()); QVector<int> glxConfigSpec = qglx_buildSpec(); int numberOfConfigs; - GLXFBConfig *configs = glXChooseFBConfig(mDisplay,mScreen,glxConfigSpec.constData(),&numberOfConfigs); + GLXFBConfig *configs = glXChooseFBConfig(m_integration->xDisplay(),m_integration->xScreen(),glxConfigSpec.constData(),&numberOfConfigs); QVector<int> attribList; attribList.append(GLX_TEXTURE_FORMAT_EXT); @@ -124,28 +142,40 @@ void XCompositeGLXClientBufferIntegration::bindTextureToBuffer(struct ::wl_resou attribList.append(GLX_TEXTURE_TARGET_EXT); attribList.append(GLX_TEXTURE_2D_EXT); attribList.append(0); - GLXPixmap glxPixmap = glXCreatePixmap(mDisplay,*configs,pixmap,attribList.constData()); + + if (!m_glxPixmap) + m_glxPixmap = glXCreatePixmap(m_integration->xDisplay(), *configs, pixmap, attribList.constData()); uint inverted = 0; - glXQueryDrawable(mDisplay, glxPixmap, GLX_Y_INVERTED_EXT,&inverted); + glXQueryDrawable(m_integration->xDisplay(), m_glxPixmap, GLX_Y_INVERTED_EXT,&inverted); compositorBuffer->setOrigin(inverted ? QWaylandSurface::OriginBottomLeft : QWaylandSurface::OriginTopLeft); XFree(configs); + auto tex = m_texture; + if (!m_texture) { + tex = new QOpenGLTexture(QOpenGLTexture::Target2D); + tex->create(); + m_texture = tex; + } + tex->bind(); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + m_integration->m_glxBindTexImageEXT(m_integration->xDisplay(),m_glxPixmap,GLX_FRONT_EXT, 0); - m_glxBindTexImageEXT(mDisplay,glxPixmap,GLX_FRONT_EXT, 0); - //Do we need to change the api so that we do bind and release in the painevent? - //The specification states that when deleting the texture the color buffer is deleted -// m_glxReleaseTexImageEXT(mDisplay,glxPixmap,GLX_FRONT_EXT); + // TODO: release in the destructor? + // m_glxReleaseTexImageEXT(mDisplay,glxPixmap,GLX_FRONT_EXT); + return tex; } -QWaylandSurface::Origin XCompositeGLXClientBufferIntegration::origin(struct ::wl_resource *buffer) const + +QWaylandSurface::Origin XCompositeGLXClientBuffer::origin() const { - return XCompositeBuffer::fromResource(buffer)->origin(); + XCompositeBuffer *compositorBuffer = XCompositeBuffer::fromResource(m_buffer); + return compositorBuffer->origin(); } -QSize XCompositeGLXClientBufferIntegration::bufferSize(struct ::wl_resource *buffer) const +QSize XCompositeGLXClientBuffer::size() const { - XCompositeBuffer *compositorBuffer = XCompositeBuffer::fromResource(buffer); + XCompositeBuffer *compositorBuffer = XCompositeBuffer::fromResource(m_buffer); return compositorBuffer->size(); } diff --git a/src/hardwareintegration/compositor/xcomposite-glx/xcompositeglxintegration.h b/src/hardwareintegration/compositor/xcomposite-glx/xcompositeglxintegration.h index 9caeb4645..7b63f976e 100644 --- a/src/hardwareintegration/compositor/xcomposite-glx/xcompositeglxintegration.h +++ b/src/hardwareintegration/compositor/xcomposite-glx/xcompositeglxintegration.h @@ -38,7 +38,7 @@ #define XCOMPOSITEGLXINTEGRATION_H #include <QtWaylandCompositor/private/qwlclientbufferintegration_p.h> - +#include <QtWaylandCompositor/private/qwlclientbuffer_p.h> #include "xlibinclude.h" #define GLX_GLXEXT_PROTOTYPES @@ -56,21 +56,38 @@ public: ~XCompositeGLXClientBufferIntegration(); void initializeHardware(struct ::wl_display *display) Q_DECL_OVERRIDE; + QtWayland::ClientBuffer *createBufferFor(wl_resource *buffer) Q_DECL_OVERRIDE; - void bindTextureToBuffer(struct ::wl_resource *buffer) Q_DECL_OVERRIDE; - QWaylandSurface::Origin origin(struct ::wl_resource *) const Q_DECL_OVERRIDE; - - QSize bufferSize(struct ::wl_resource *buffer) const Q_DECL_OVERRIDE; + inline Display *xDisplay() const { return mDisplay; } + inline int xScreen() const { return mScreen; } -private: PFNGLXBINDTEXIMAGEEXTPROC m_glxBindTexImageEXT; PFNGLXRELEASETEXIMAGEEXTPROC m_glxReleaseTexImageEXT; +private: Display *mDisplay; int mScreen; XCompositeHandler *mHandler; }; +class XCompositeGLXClientBuffer : public QtWayland::ClientBuffer +{ +public: + XCompositeGLXClientBuffer(XCompositeGLXClientBufferIntegration *integration, wl_resource *bufferResource); + + QSize size() const; + QWaylandSurface::Origin origin() const; + QOpenGLTexture *toOpenGlTexture(int plane) Q_DECL_OVERRIDE; + QWaylandBufferRef::BufferFormatEgl bufferFormatEgl() const Q_DECL_OVERRIDE { + return QWaylandBufferRef::BufferFormatEgl_RGBA; + } + +private: + QOpenGLTexture *m_texture; + XCompositeGLXClientBufferIntegration *m_integration; + GLXPixmap m_glxPixmap; +}; + QT_END_NAMESPACE #endif // XCOMPOSITEGLXINTEGRATION_H diff --git a/src/imports/compositor/WaylandCursorItem.qml b/src/imports/compositor/WaylandCursorItem.qml index 9eacff9be..931acbb08 100644 --- a/src/imports/compositor/WaylandCursorItem.qml +++ b/src/imports/compositor/WaylandCursorItem.qml @@ -39,17 +39,19 @@ import QtWayland.Compositor 1.0 WaylandQuickItem { id: cursorItem - property QtObject inputDevice + property QtObject seat property int hotspotX: 0 property int hotspotY: 0 visible: cursorItem.surface != null inputEventsEnabled: false + enabled: false + transform: Translate { x: -hotspotX; y: -hotspotY } - onInputDeviceChanged: { - if (!inputDevice) + onSeatChanged: { + if (!seat) return; - inputDevice.cursorSurfaceRequest.connect(setCursorSurface); + seat.cursorSurfaceRequest.connect(setCursorSurface); } function setCursorSurface(surface, hotspotX, hotspotY) { @@ -57,4 +59,19 @@ WaylandQuickItem { cursorItem.hotspotX = hotspotX; cursorItem.hotspotY = hotspotY; } + + WaylandQuickItem { + id: dragIcon + property point offset + + x: cursorItem.hotspotX + offset.x + y: cursorItem.hotspotY + offset.y + z: -1 + surface: cursorItem.seat.drag.icon + + Connections { + target: dragIcon.surface + onOffsetForNextFrame: dragIcon.offset = offset; + } + } } diff --git a/src/imports/compositor/plugins.qmltypes b/src/imports/compositor/plugins.qmltypes index 8d07403c0..c88b3b479 100644 --- a/src/imports/compositor/plugins.qmltypes +++ b/src/imports/compositor/plugins.qmltypes @@ -14,6 +14,7 @@ Module { exports: ["QtWayland.Compositor/WaylandClient 1.0"] isCreatable: false exportMetaObjectRevisions: [0] + Property { name: "compositor"; type: "QWaylandCompositor"; isReadonly: true; isPointer: true } Property { name: "userId"; type: "qlonglong"; isReadonly: true } Property { name: "groupId"; type: "qlonglong"; isReadonly: true } Property { name: "processId"; type: "qlonglong"; isReadonly: true } @@ -26,22 +27,26 @@ Module { } Component { name: "QWaylandCompositor" - prototype: "QObject" + prototype: "QWaylandObject" exports: ["QtWayland.Compositor/WaylandCompositorBase 1.0"] isCreatable: false exportMetaObjectRevisions: [0] Property { name: "socketName"; type: "QByteArray" } + Property { name: "created"; type: "bool"; isReadonly: true } Property { name: "retainedSelection"; type: "bool" } Property { name: "defaultOutput"; type: "QWaylandOutput"; isPointer: true } Property { name: "useHardwareIntegrationExtension"; type: "bool" } - Property { - name: "defaultInputDevice" - type: "QWaylandInputDevice" - isReadonly: true - isPointer: true + Property { name: "defaultSeat"; type: "QWaylandSeat"; isReadonly: true; isPointer: true } + Signal { + name: "socketNameChanged" + Parameter { name: "socketName"; type: "QByteArray" } } Signal { - name: "createSurface" + name: "retainedSelectionChanged" + Parameter { name: "retainedSelection"; type: "bool" } + } + Signal { + name: "surfaceRequested" Parameter { name: "client"; type: "QWaylandClient"; isPointer: true } Parameter { name: "id"; type: "uint" } Parameter { name: "version"; type: "int" } @@ -60,9 +65,17 @@ Module { Parameter { name: "parent"; type: "QWaylandSurface"; isPointer: true } } Signal { - name: "defaultInputDeviceChanged" - Parameter { name: "newDevice"; type: "QWaylandInputDevice"; isPointer: true } - Parameter { name: "oldDevice"; type: "QWaylandInputDevice"; isPointer: true } + name: "defaultSeatChanged" + Parameter { name: "newDevice"; type: "QWaylandSeat"; isPointer: true } + Parameter { name: "oldDevice"; type: "QWaylandSeat"; isPointer: true } + } + Signal { + name: "outputAdded" + Parameter { name: "output"; type: "QWaylandOutput"; isPointer: true } + } + Signal { + name: "outputRemoved" + Parameter { name: "output"; type: "QWaylandOutput"; isPointer: true } } Method { name: "processWaylandEvents" } Method { @@ -81,42 +94,79 @@ Module { } Component { name: "QWaylandCompositorExtension" - prototype: "QObject" + prototype: "QWaylandObject" exports: ["QtWayland.Compositor/WaylandExtension 1.0"] isCreatable: false exportMetaObjectRevisions: [0] } Component { - name: "QWaylandInputDevice" + name: "QWaylandDrag" prototype: "QObject" - exports: ["QtWayland.Compositor/WaylandInputDevice 1.0"] + exports: ["QtWayland.Compositor/WaylandDrag 1.0"] isCreatable: false exportMetaObjectRevisions: [0] - Enum { - name: "CapabilityFlags" - values: { - "Pointer": 1, - "Keyboard": 2, - "Touch": 4, - "DefaultCapabilities": 7 - } + Property { name: "icon"; type: "QWaylandSurface"; isReadonly: true; isPointer: true } + Property { name: "visible"; type: "bool"; isReadonly: true } + Signal { name: "dragStarted" } + Method { + name: "dragMove" + Parameter { name: "target"; type: "QWaylandSurface"; isPointer: true } + Parameter { name: "pos"; type: "QPointF" } } + Method { name: "drop" } + Method { name: "cancelDrag" } + } + Component { + name: "QWaylandIviApplication" + prototype: "QWaylandCompositorExtension" Signal { - name: "mouseFocusChanged" - Parameter { name: "newFocus"; type: "QWaylandView"; isPointer: true } - Parameter { name: "oldFocus"; type: "QWaylandView"; isPointer: true } + name: "iviSurfaceRequested" + Parameter { name: "surface"; type: "QWaylandSurface"; isPointer: true } + Parameter { name: "iviId"; type: "uint" } + Parameter { name: "resource"; type: "QWaylandResource" } } Signal { - name: "keyboardFocusChanged" - Parameter { name: "newFocus"; type: "QWaylandSurface"; isPointer: true } - Parameter { name: "oldFocus"; type: "QWaylandSurface"; isPointer: true } + name: "iviSurfaceCreated" + Parameter { name: "iviSurface"; type: "QWaylandIviSurface"; isPointer: true } } - Signal { - name: "cursorSurfaceRequest" + } + Component { + name: "QWaylandIviApplicationQuickExtension" + defaultProperty: "data" + prototype: "QWaylandIviApplication" + exports: ["QtWayland.Compositor/IviApplication 1.0"] + exportMetaObjectRevisions: [0] + Property { name: "data"; type: "QObject"; isList: true; isReadonly: true } + } + Component { + name: "QWaylandIviSurface" + prototype: "QWaylandShellSurface" + exports: ["QtWayland.Compositor/IviSurface 1.0"] + exportMetaObjectRevisions: [0] + Property { name: "surface"; type: "QWaylandSurface"; isReadonly: true; isPointer: true } + Property { name: "iviId"; type: "uint"; isReadonly: true } + Method { + name: "initialize" + Parameter { name: "iviApplication"; type: "QWaylandIviApplication"; isPointer: true } Parameter { name: "surface"; type: "QWaylandSurface"; isPointer: true } - Parameter { name: "hotspotX"; type: "int" } - Parameter { name: "hotspotY"; type: "int" } + Parameter { name: "iviId"; type: "uint" } + Parameter { name: "resource"; type: "QWaylandResource" } } + Method { + name: "sendConfigure" + Parameter { name: "size"; type: "QSize" } + } + } + Component { + name: "QWaylandKeymap" + prototype: "QObject" + exports: ["QtWayland.Compositor/WaylandKeymap 1.0"] + exportMetaObjectRevisions: [0] + Property { name: "layout"; type: "string" } + Property { name: "variant"; type: "string" } + Property { name: "options"; type: "string" } + Property { name: "rules"; type: "string" } + Property { name: "model"; type: "string" } } Component { name: "QWaylandMouseTracker" @@ -127,12 +177,16 @@ Module { Property { name: "mouseX"; type: "double"; isReadonly: true } Property { name: "mouseY"; type: "double"; isReadonly: true } Property { name: "containsMouse"; type: "bool"; isReadonly: true } - Property { name: "enableWSCursor"; type: "bool" } + Property { name: "windowSystemCursorEnabled"; type: "bool" } Signal { name: "hoveredChanged" } } + Component { name: "QWaylandObject"; prototype: "QObject" } Component { name: "QWaylandOutput" - prototype: "QObject" + prototype: "QWaylandObject" + exports: ["QtWayland.Compositor/WaylandOutputBase 1.0"] + isCreatable: false + exportMetaObjectRevisions: [0] Enum { name: "Subpixel" values: { @@ -162,7 +216,6 @@ Module { Property { name: "manufacturer"; type: "string" } Property { name: "model"; type: "string" } Property { name: "position"; type: "QPoint" } - Property { name: "mode"; type: "QWaylandOutput::Mode" } Property { name: "geometry"; type: "QRect"; isReadonly: true } Property { name: "availableGeometry"; type: "QRect" } Property { name: "physicalSize"; type: "QSize" } @@ -170,9 +223,29 @@ Module { Property { name: "transform"; type: "QWaylandOutput::Transform" } Property { name: "scaleFactor"; type: "int" } Property { name: "sizeFollowsWindow"; type: "bool" } + Signal { name: "modeAdded" } + Signal { name: "currentModeChanged" } Signal { name: "physicalSizeFollowsSizeChanged" } Signal { name: "windowDestroyed" } } + Component { + name: "QWaylandQtWindowManager" + prototype: "QWaylandCompositorExtension" + Property { name: "showIsFullScreen"; type: "bool" } + Signal { + name: "openUrl" + Parameter { name: "client"; type: "QWaylandClient"; isPointer: true } + Parameter { name: "url"; type: "QUrl" } + } + } + Component { + name: "QWaylandQtWindowManagerQuickExtension" + defaultProperty: "data" + prototype: "QWaylandQtWindowManager" + exports: ["QtWayland.Compositor/QtWindowManager 1.0"] + exportMetaObjectRevisions: [0] + Property { name: "data"; type: "QObject"; isList: true; isReadonly: true } + } Component { name: "QWaylandQuickCompositor"; prototype: "QWaylandCompositor" } Component { name: "QWaylandQuickCompositorQuickExtensionContainer" @@ -194,7 +267,6 @@ Module { prototype: "QQuickItem" exports: ["QtWayland.Compositor/WaylandQuickItem 1.0"] exportMetaObjectRevisions: [0] - Property { name: "view"; type: "QWaylandView"; isReadonly: true; isPointer: true } Property { name: "compositor"; type: "QWaylandCompositor"; isReadonly: true; isPointer: true } Property { name: "surface"; type: "QWaylandSurface"; isPointer: true } Property { name: "paintEnabled"; type: "bool" } @@ -204,6 +276,9 @@ Module { Property { name: "focusOnClick"; type: "bool" } Property { name: "sizeFollowsSurface"; type: "bool" } Property { name: "subsurfaceHandler"; type: "QObject"; isPointer: true } + Property { name: "output"; type: "QWaylandOutput"; isPointer: true } + Property { name: "bufferLocked"; type: "bool" } + Property { name: "allowDiscardFrontBuffer"; type: "bool" } Signal { name: "surfaceDestroyed" } Signal { name: "mouseMove" @@ -212,7 +287,7 @@ Module { Signal { name: "mouseRelease" } Method { name: "takeFocus" - Parameter { name: "device"; type: "QWaylandInputDevice"; isPointer: true } + Parameter { name: "device"; type: "QWaylandSeat"; isPointer: true } } Method { name: "takeFocus" } Method { @@ -222,6 +297,11 @@ Module { Method { name: "raise" } Method { name: "lower" } Method { + name: "mapToSurface" + type: "QPointF" + Parameter { name: "point"; type: "QPointF" } + } + Method { name: "inputMethodQuery" type: "QVariant" Parameter { name: "query"; type: "Qt::InputMethodQuery" } @@ -260,15 +340,65 @@ Module { exportMetaObjectRevisions: [0] } Component { + name: "QWaylandSeat" + prototype: "QWaylandObject" + exports: ["QtWayland.Compositor/WaylandSeat 1.0"] + isCreatable: false + exportMetaObjectRevisions: [0] + Enum { + name: "CapabilityFlags" + values: { + "Pointer": 1, + "Keyboard": 2, + "Touch": 4, + "DefaultCapabilities": 7 + } + } + Property { name: "drag"; type: "QWaylandDrag"; isReadonly: true; isPointer: true } + Property { name: "keymap"; type: "QWaylandKeymap"; isReadonly: true; isPointer: true } + Signal { + name: "mouseFocusChanged" + Parameter { name: "newFocus"; type: "QWaylandView"; isPointer: true } + Parameter { name: "oldFocus"; type: "QWaylandView"; isPointer: true } + } + Signal { + name: "keyboardFocusChanged" + Parameter { name: "newFocus"; type: "QWaylandSurface"; isPointer: true } + Parameter { name: "oldFocus"; type: "QWaylandSurface"; isPointer: true } + } + Signal { + name: "cursorSurfaceRequest" + Parameter { name: "surface"; type: "QWaylandSurface"; isPointer: true } + Parameter { name: "hotspotX"; type: "int" } + Parameter { name: "hotspotY"; type: "int" } + } + } + Component { + name: "QWaylandShell" + prototype: "QWaylandCompositorExtension" + exports: ["QtWayland.Compositor/Shell 1.0"] + isCreatable: false + exportMetaObjectRevisions: [0] + Enum { + name: "FocusPolicy" + values: { + "AutomaticFocus": 0, + "ManualFocus": 1 + } + } + Property { name: "focusPolicy"; type: "FocusPolicy" } + } + Component { name: "QWaylandShellSurface" prototype: "QWaylandCompositorExtension" exports: ["QtWayland.Compositor/ShellSurface 1.0"] isCreatable: false exportMetaObjectRevisions: [0] + Property { name: "windowType"; type: "Qt::WindowType"; isReadonly: true } } Component { name: "QWaylandSurface" - prototype: "QObject" + prototype: "QWaylandObject" exports: ["QtWayland.Compositor/WaylandSurfaceBase 1.0"] isCreatable: false exportMetaObjectRevisions: [0] @@ -284,9 +414,8 @@ Module { Property { name: "bufferScale"; type: "int"; isReadonly: true } Property { name: "contentOrientation"; type: "Qt::ScreenOrientation"; isReadonly: true } Property { name: "origin"; type: "QWaylandSurface::Origin"; isReadonly: true } - Property { name: "isMapped"; type: "bool"; isReadonly: true } + Property { name: "hasContent"; type: "bool"; isReadonly: true } Property { name: "cursorSurface"; type: "bool" } - Signal { name: "mappedChanged" } Signal { name: "damaged" Parameter { name: "rect"; type: "QRegion" } @@ -318,6 +447,10 @@ Module { Parameter { name: "sibling"; type: "QWaylandSurface"; isPointer: true } } Signal { + name: "dragStarted" + Parameter { name: "drag"; type: "QWaylandDrag"; isPointer: true } + } + Signal { name: "configure" Parameter { name: "hasBuffer"; type: "bool" } } @@ -345,48 +478,18 @@ Module { Property { name: "data"; type: "QObject"; isList: true; isReadonly: true } } Component { - name: "QWaylandView" - prototype: "QObject" - exports: ["QtWayland.Compositor/WaylandView 1.0"] - isCreatable: false - exportMetaObjectRevisions: [0] - Property { name: "renderObject"; type: "QObject"; isReadonly: true; isPointer: true } - Property { name: "surface"; type: "QWaylandSurface"; isPointer: true } - Property { name: "output"; type: "QWaylandOutput"; isPointer: true } - Property { name: "bufferLock"; type: "bool" } - Property { name: "discardFrontBuffers"; type: "bool" } - Signal { name: "surfaceDestroyed" } - } - Component { - name: "QWaylandWindowManagerExtension" - prototype: "QWaylandCompositorExtension" - Property { name: "showIsFullScreen"; type: "bool" } - Signal { - name: "openUrl" - Parameter { name: "client"; type: "QWaylandClient"; isPointer: true } - Parameter { name: "url"; type: "QUrl" } - } - } - Component { - name: "QWaylandWindowManagerExtensionQuickExtension" - defaultProperty: "data" - prototype: "QWaylandWindowManagerExtension" - exports: ["QtWayland.Compositor/WindowManager 1.0"] - exportMetaObjectRevisions: [0] - Property { name: "data"; type: "QObject"; isList: true; isReadonly: true } - } - Component { name: "QWaylandWlShell" - prototype: "QWaylandCompositorExtension" + prototype: "QWaylandShell" Signal { - name: "createShellSurface" + name: "wlShellSurfaceRequested" Parameter { name: "surface"; type: "QWaylandSurface"; isPointer: true } Parameter { name: "resource"; type: "QWaylandResource" } } Signal { - name: "shellSurfaceCreated" + name: "wlShellSurfaceCreated" Parameter { name: "shellSurface"; type: "QWaylandWlShellSurface"; isPointer: true } } + Method { name: "closeAllPopups" } } Component { name: "QWaylandWlShellQuickExtension" @@ -399,12 +502,8 @@ Module { Component { name: "QWaylandWlShellSurface" prototype: "QWaylandShellSurface" - exports: [ - "QtWayland.Compositor/WlShellSurface 1.0", - "QtWayland.Compositor/WlShellSurfaceBase 1.0" - ] - isCreatable: false - exportMetaObjectRevisions: [0, 0] + exports: ["QtWayland.Compositor/WlShellSurface 1.0"] + exportMetaObjectRevisions: [0] Enum { name: "FullScreenMethod" values: { @@ -428,25 +527,18 @@ Module { "BottomRightEdge": 10 } } - Enum { - name: "FocusPolicy" - values: { - "DefaultFocus": 0, - "NoKeyboardFocus": 1 - } - } Property { name: "surface"; type: "QWaylandSurface"; isReadonly: true; isPointer: true } + Property { name: "shell"; type: "QWaylandWlShell"; isReadonly: true; isPointer: true } Property { name: "title"; type: "string"; isReadonly: true } Property { name: "className"; type: "string"; isReadonly: true } - Property { name: "focusPolicy"; type: "FocusPolicy"; isReadonly: true } Signal { name: "pong" } Signal { name: "startMove" - Parameter { name: "inputDevice"; type: "QWaylandInputDevice"; isPointer: true } + Parameter { name: "seat"; type: "QWaylandSeat"; isPointer: true } } Signal { name: "startResize" - Parameter { name: "inputDevice"; type: "QWaylandInputDevice"; isPointer: true } + Parameter { name: "seat"; type: "QWaylandSeat"; isPointer: true } Parameter { name: "edges"; type: "ResizeEdge" } } Signal { name: "setDefaultToplevel" } @@ -454,7 +546,7 @@ Module { name: "setTransient" Parameter { name: "parentSurface"; type: "QWaylandSurface"; isPointer: true } Parameter { name: "relativeToParent"; type: "QPoint" } - Parameter { name: "focusPolicy"; type: "FocusPolicy" } + Parameter { name: "inactive"; type: "bool" } } Signal { name: "setFullScreen" @@ -464,7 +556,7 @@ Module { } Signal { name: "setPopup" - Parameter { name: "inputDevice"; type: "QWaylandInputDevice"; isPointer: true } + Parameter { name: "seat"; type: "QWaylandSeat"; isPointer: true } Parameter { name: "parentSurface"; type: "QWaylandSurface"; isPointer: true } Parameter { name: "relativeToParent"; type: "QPoint" } } @@ -494,26 +586,26 @@ Module { Method { name: "sendPopupDone" } } Component { - name: "QWaylandXdgShell" - prototype: "QWaylandCompositorExtension" + name: "QWaylandXdgShellV5" + prototype: "QWaylandShell" Signal { - name: "createXdgSurface" + name: "xdgSurfaceRequested" Parameter { name: "surface"; type: "QWaylandSurface"; isPointer: true } Parameter { name: "resource"; type: "QWaylandResource" } } Signal { name: "xdgSurfaceCreated" - Parameter { name: "xdgSurface"; type: "QWaylandXdgSurface"; isPointer: true } + Parameter { name: "xdgSurface"; type: "QWaylandXdgSurfaceV5"; isPointer: true } } Signal { name: "xdgPopupCreated" - Parameter { name: "xdgPopup"; type: "QWaylandXdgPopup"; isPointer: true } + Parameter { name: "xdgPopup"; type: "QWaylandXdgPopupV5"; isPointer: true } } Signal { - name: "createXdgPopup" + name: "xdgPopupRequested" Parameter { name: "surface"; type: "QWaylandSurface"; isPointer: true } Parameter { name: "parent"; type: "QWaylandSurface"; isPointer: true } - Parameter { name: "seat"; type: "QWaylandInputDevice"; isPointer: true } + Parameter { name: "seat"; type: "QWaylandSeat"; isPointer: true } Parameter { name: "position"; type: "QPoint" } Parameter { name: "resource"; type: "QWaylandResource" } } @@ -529,22 +621,18 @@ Module { Method { name: "closeAllPopups" } } Component { - name: "QWaylandXdgShellQuickExtension" + name: "QWaylandXdgShellV5QuickExtension" defaultProperty: "data" - prototype: "QWaylandXdgShell" - exports: ["QtWayland.Compositor/XdgShell 1.0"] + prototype: "QWaylandXdgShellV5" + exports: ["QtWayland.Compositor/XdgShellV5 1.0"] exportMetaObjectRevisions: [0] Property { name: "data"; type: "QObject"; isList: true; isReadonly: true } } Component { - name: "QWaylandXdgSurface" + name: "QWaylandXdgSurfaceV5" prototype: "QWaylandShellSurface" - exports: [ - "QtWayland.Compositor/XdgSurface 1.0", - "QtWayland.Compositor/XdgSurfaceBase 1.0" - ] - isCreatable: false - exportMetaObjectRevisions: [0, 0] + exports: ["QtWayland.Compositor/XdgSurfaceV5 1.0"] + exportMetaObjectRevisions: [0] Enum { name: "State" values: { @@ -568,8 +656,14 @@ Module { "BottomRightEdge": 10 } } + Property { name: "shell"; type: "QWaylandXdgShellV5"; isReadonly: true; isPointer: true } Property { name: "surface"; type: "QWaylandSurface"; isReadonly: true; isPointer: true } - Property { name: "parentSurface"; type: "QWaylandXdgSurface"; isReadonly: true; isPointer: true } + Property { + name: "parentSurface" + type: "QWaylandXdgSurfaceV5" + isReadonly: true + isPointer: true + } Property { name: "title"; type: "string"; isReadonly: true } Property { name: "appId"; type: "string"; isReadonly: true } Property { name: "windowGeometry"; type: "QRect"; isReadonly: true } @@ -580,18 +674,20 @@ Module { Property { name: "activated"; type: "bool"; isReadonly: true } Signal { name: "showWindowMenu" - Parameter { name: "inputDevice"; type: "QWaylandInputDevice"; isPointer: true } + Parameter { name: "seat"; type: "QWaylandSeat"; isPointer: true } Parameter { name: "localSurfacePosition"; type: "QPoint" } } Signal { name: "startMove" - Parameter { name: "inputDevice"; type: "QWaylandInputDevice"; isPointer: true } + Parameter { name: "seat"; type: "QWaylandSeat"; isPointer: true } } Signal { name: "startResize" - Parameter { name: "inputDevice"; type: "QWaylandInputDevice"; isPointer: true } + Parameter { name: "seat"; type: "QWaylandSeat"; isPointer: true } Parameter { name: "edges"; type: "ResizeEdge" } } + Signal { name: "setTopLevel" } + Signal { name: "setTransient" } Signal { name: "setMaximized" } Signal { name: "unsetMaximized" } Signal { @@ -606,7 +702,7 @@ Module { } Method { name: "initialize" - Parameter { name: "xdgShell"; type: "QWaylandXdgShell"; isPointer: true } + Parameter { name: "xdgShell"; type: "QWaylandXdgShellV5"; isPointer: true } Parameter { name: "surface"; type: "QWaylandSurface"; isPointer: true } Parameter { name: "resource"; type: "QWaylandResource" } } @@ -631,23 +727,23 @@ Module { } Method { name: "sendClose" } Method { - name: "requestMaximized" + name: "sendMaximized" type: "uint" Parameter { name: "size"; type: "QSize" } } Method { - name: "requestUnMaximized" + name: "sendUnmaximized" type: "uint" Parameter { name: "size"; type: "QSize" } } - Method { name: "requestUnMaximized"; type: "uint" } + Method { name: "sendUnmaximized"; type: "uint" } Method { - name: "requestFullscreen" + name: "sendFullscreen" type: "uint" Parameter { name: "size"; type: "QSize" } } Method { - name: "requestResizing" + name: "sendResizing" type: "uint" Parameter { name: "maxSize"; type: "QSize" } } @@ -659,7 +755,7 @@ Module { exportMetaObjectRevisions: [0] isComposite: true defaultProperty: "data" - Property { name: "inputDevice"; type: "QObject"; isPointer: true } + Property { name: "seat"; type: "QObject"; isPointer: true } Property { name: "hotspotX"; type: "int" } Property { name: "hotspotY"; type: "int" } Method { @@ -669,7 +765,6 @@ Module { Parameter { name: "hotspotX"; type: "QVariant" } Parameter { name: "hotspotY"; type: "QVariant" } } - Property { name: "view"; type: "QWaylandView"; isReadonly: true; isPointer: true } Property { name: "compositor"; type: "QWaylandCompositor"; isReadonly: true; isPointer: true } Property { name: "surface"; type: "QWaylandSurface"; isPointer: true } Property { name: "paintEnabled"; type: "bool" } @@ -679,6 +774,9 @@ Module { Property { name: "focusOnClick"; type: "bool" } Property { name: "sizeFollowsSurface"; type: "bool" } Property { name: "subsurfaceHandler"; type: "QObject"; isPointer: true } + Property { name: "output"; type: "QWaylandOutput"; isPointer: true } + Property { name: "bufferLocked"; type: "bool" } + Property { name: "allowDiscardFrontBuffer"; type: "bool" } Signal { name: "surfaceDestroyed" } Signal { name: "mouseMove" @@ -687,7 +785,7 @@ Module { Signal { name: "mouseRelease" } Method { name: "takeFocus" - Parameter { name: "device"; type: "QWaylandInputDevice"; isPointer: true } + Parameter { name: "device"; type: "QWaylandSeat"; isPointer: true } } Method { name: "takeFocus" } Method { @@ -697,6 +795,11 @@ Module { Method { name: "raise" } Method { name: "lower" } Method { + name: "mapToSurface" + type: "QPointF" + Parameter { name: "point"; type: "QPointF" } + } + Method { name: "inputMethodQuery" type: "QVariant" Parameter { name: "query"; type: "Qt::InputMethodQuery" } diff --git a/src/imports/compositor/qwaylandmousetracker.cpp b/src/imports/compositor/qwaylandmousetracker.cpp index a77d6b1a0..489dc7b55 100644 --- a/src/imports/compositor/qwaylandmousetracker.cpp +++ b/src/imports/compositor/qwaylandmousetracker.cpp @@ -45,7 +45,7 @@ class QWaylandMouseTrackerPrivate : public QQuickItemPrivate Q_DECLARE_PUBLIC(QWaylandMouseTracker) public: QWaylandMouseTrackerPrivate() - : enableWSCursor(false) + : windowSystemCursorEnabled(false) , hovered(false) { QImage cursorImage(64,64,QImage::Format_ARGB32); @@ -76,7 +76,7 @@ public: } QPointF mousePos; - bool enableWSCursor; + bool windowSystemCursorEnabled; QPixmap cursorPixmap; bool hovered; }; @@ -102,24 +102,24 @@ qreal QWaylandMouseTracker::mouseY() const return d->mousePos.y(); } -void QWaylandMouseTracker::setEnableWSCursor(bool enable) +void QWaylandMouseTracker::setWindowSystemCursorEnabled(bool enable) { Q_D(QWaylandMouseTracker); - if (d->enableWSCursor != enable) { - d->enableWSCursor = enable; + if (d->windowSystemCursorEnabled != enable) { + d->windowSystemCursorEnabled = enable; if (enable) { unsetCursor(); } else { setCursor(QCursor(d->cursorPixmap)); } - emit enableWSCursorChanged(); + emit windowSystemCursorEnabledChanged(); } } -bool QWaylandMouseTracker::enableWSCursor() const +bool QWaylandMouseTracker::windowSystemCursorEnabled() const { Q_D(const QWaylandMouseTracker); - return d->enableWSCursor; + return d->windowSystemCursorEnabled; } bool QWaylandMouseTracker::hovered() const diff --git a/src/imports/compositor/qwaylandmousetracker_p.h b/src/imports/compositor/qwaylandmousetracker_p.h index 1bc37a5e2..d90b037ff 100644 --- a/src/imports/compositor/qwaylandmousetracker_p.h +++ b/src/imports/compositor/qwaylandmousetracker_p.h @@ -53,21 +53,21 @@ class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandMouseTracker : public QQuickItem Q_PROPERTY(qreal mouseY READ mouseY NOTIFY mouseYChanged) Q_PROPERTY(bool containsMouse READ hovered NOTIFY hoveredChanged) - Q_PROPERTY(bool enableWSCursor READ enableWSCursor WRITE setEnableWSCursor NOTIFY enableWSCursorChanged) + Q_PROPERTY(bool windowSystemCursorEnabled READ windowSystemCursorEnabled WRITE setWindowSystemCursorEnabled NOTIFY windowSystemCursorEnabledChanged) public: QWaylandMouseTracker(QQuickItem *parent = 0); qreal mouseX() const; qreal mouseY() const; - void setEnableWSCursor(bool enable); - bool enableWSCursor() const; + void setWindowSystemCursorEnabled(bool enable); + bool windowSystemCursorEnabled() const; bool hovered() const; signals: void mouseXChanged(); void mouseYChanged(); - void enableWSCursorChanged(); + void windowSystemCursorEnabledChanged(); void hoveredChanged(); protected: diff --git a/src/imports/compositor/qwaylandquickcompositorplugin.cpp b/src/imports/compositor/qwaylandquickcompositorplugin.cpp index c992d3fcb..28c517fd5 100644 --- a/src/imports/compositor/qwaylandquickcompositorplugin.cpp +++ b/src/imports/compositor/qwaylandquickcompositorplugin.cpp @@ -46,14 +46,18 @@ #include <QtWaylandCompositor/QWaylandQuickOutput> #include <QtWaylandCompositor/QWaylandCompositorExtension> #include <QtWaylandCompositor/QWaylandQuickExtension> -#include <QtWaylandCompositor/QWaylandInputDevice> +#include <QtWaylandCompositor/QWaylandSeat> +#include <QtWaylandCompositor/QWaylandDrag> +#include <QtWaylandCompositor/QWaylandKeymap> #include <QtWaylandCompositor/QWaylandQuickShellSurfaceItem> #include <QtWaylandCompositor/QWaylandResource> -#include <QtWaylandCompositor/QWaylandWindowManagerExtension> +#include <QtWaylandCompositor/QWaylandQtWindowManager> #include <QtWaylandCompositor/QWaylandWlShell> #include <QtWaylandCompositor/QWaylandTextInputManager> -#include <QtWaylandCompositor/QWaylandXdgShell> +#include <QtWaylandCompositor/QWaylandXdgShellV5> +#include <QtWaylandCompositor/QWaylandIviApplication> +#include <QtWaylandCompositor/QWaylandIviSurface> #include <QtWaylandCompositor/qwaylandexport.h> #include "qwaylandmousetracker_p.h" @@ -61,9 +65,10 @@ QT_BEGIN_NAMESPACE Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CONTAINER_CLASS(QWaylandQuickCompositor) -Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandWindowManagerExtension) +Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandQtWindowManager) +Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandIviApplication) Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandWlShell) -Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandXdgShell) +Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandXdgShellV5) Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandTextInputManager) class QmlUrlResolver @@ -91,7 +96,7 @@ private: class QWaylandCompositorPlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0") + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: virtual void registerTypes(const char *uri) { @@ -116,25 +121,28 @@ public: qmlRegisterType<QWaylandMouseTracker>(uri, 1, 0, "WaylandMouseTracker"); qmlRegisterType<QWaylandQuickOutput>(uri, 1, 0, "WaylandOutput"); qmlRegisterType<QWaylandQuickSurface>(uri, 1, 0, "WaylandSurface"); + qmlRegisterType<QWaylandKeymap>(uri, 1, 0, "WaylandKeymap"); qmlRegisterUncreatableType<QWaylandCompositorExtension>(uri, 1, 0, "WaylandExtension", QObject::tr("Cannot create instance of WaylandExtension")); qmlRegisterUncreatableType<QWaylandClient>(uri, 1, 0, "WaylandClient", QObject::tr("Cannot create instance of WaylandClient")); - qmlRegisterUncreatableType<QWaylandView>(uri, 1, 0, "WaylandView", QObject::tr("Cannot create instance of WaylandView, it can be retrieved by accessor on WaylandQuickItem")); - qmlRegisterUncreatableType<QWaylandInputDevice>(uri, 1, 0, "WaylandInputDevice", QObject::tr("Cannot create instance of WaylandInputDevice")); + qmlRegisterUncreatableType<QWaylandOutput>(uri, 1, 0, "WaylandOutputBase", QObject::tr("Cannot create instance of WaylandOutputBase, use WaylandOutput instead")); + qmlRegisterUncreatableType<QWaylandSeat>(uri, 1, 0, "WaylandSeat", QObject::tr("Cannot create instance of WaylandSeat")); + qmlRegisterUncreatableType<QWaylandDrag>(uri, 1, 0, "WaylandDrag", QObject::tr("Cannot create instance of WaylandDrag")); qmlRegisterUncreatableType<QWaylandCompositor>(uri, 1, 0, "WaylandCompositorBase", QObject::tr("Cannot create instance of WaylandCompositorBase, use WaylandCompositor instead")); qmlRegisterUncreatableType<QWaylandSurface>(uri, 1, 0, "WaylandSurfaceBase", QObject::tr("Cannot create instance of WaylandSurfaceBase, use WaylandSurface instead")); + qmlRegisterUncreatableType<QWaylandShell>(uri, 1, 0, "Shell", QObject::tr("Cannot create instance of Shell")); qmlRegisterUncreatableType<QWaylandShellSurface>(uri, 1, 0, "ShellSurface", QObject::tr("Cannot create instance of ShellSurface")); - qmlRegisterUncreatableType<QWaylandWlShellSurface>(uri, 1, 0, "WlShellSurfaceBase", QObject::tr("Cannot create instance of WlShellSurfaceBase, use WlShellSurface instead")); - qmlRegisterUncreatableType<QWaylandXdgSurface>(uri, 1, 0, "XdgSurfaceBase", QObject::tr("Cannot create instance of XdgSurfaceBase, use XdgSurface instead")); qmlRegisterUncreatableType<QWaylandResource>(uri, 1, 0, "WaylandResource", QObject::tr("Cannot create instance of WaylandResource")); //This should probably be somewhere else - qmlRegisterType<QWaylandWindowManagerExtensionQuickExtension>(uri, 1, 0, "WindowManager"); + qmlRegisterType<QWaylandQtWindowManagerQuickExtension>(uri, 1, 0, "QtWindowManager"); + qmlRegisterType<QWaylandIviApplicationQuickExtension>(uri, 1, 0, "IviApplication"); + qmlRegisterType<QWaylandIviSurface>(uri, 1, 0, "IviSurface"); qmlRegisterType<QWaylandWlShellQuickExtension>(uri, 1, 0, "WlShell"); qmlRegisterType<QWaylandWlShellSurface>(uri, 1, 0, "WlShellSurface"); qmlRegisterType<QWaylandQuickShellSurfaceItem>(uri, 1, 0, "ShellSurfaceItem"); - qmlRegisterType<QWaylandXdgShellQuickExtension>(uri, 1, 0, "XdgShell"); - qmlRegisterType<QWaylandXdgSurface>(uri, 1, 0, "XdgSurface"); + qmlRegisterType<QWaylandXdgShellV5QuickExtension>(uri, 1, 0, "XdgShellV5"); + qmlRegisterType<QWaylandXdgSurfaceV5>(uri, 1, 0, "XdgSurfaceV5"); qmlRegisterType<QWaylandTextInputManagerQuickExtension>(uri, 1, 0, "TextInputManager"); } }; diff --git a/src/plugins/hardwareintegration/compositor/wayland-egl/wayland-egl.pro b/src/plugins/hardwareintegration/compositor/wayland-egl/wayland-egl.pro index 7374a5982..9ddd961c7 100644 --- a/src/plugins/hardwareintegration/compositor/wayland-egl/wayland-egl.pro +++ b/src/plugins/hardwareintegration/compositor/wayland-egl/wayland-egl.pro @@ -1,4 +1,4 @@ -QT = waylandcompositor waylandcompositor-private core-private gui-private platformsupport-private +QT = waylandcompositor waylandcompositor-private core-private gui-private OTHER_FILES += wayland-egl.json diff --git a/src/shared/qwaylandshmformathelper_p.h b/src/shared/qwaylandsharedmemoryformathelper_p.h index 58db42e26..7f2f77cc3 100644 --- a/src/shared/qwaylandshmformathelper_p.h +++ b/src/shared/qwaylandsharedmemoryformathelper_p.h @@ -37,8 +37,8 @@ ** ****************************************************************************/ -#ifndef QWAYLANDSHMFORMATHELPER_H -#define QWAYLANDSHMFORMATHELPER_H +#ifndef QWAYLANDSHAREDMEMORYFORMATHELPER_H +#define QWAYLANDSHAREDMEMORYFORMATHELPER_H #include <QtGui/QImage> @@ -47,7 +47,7 @@ QT_BEGIN_NAMESPACE -class QWaylandShmFormatHelper +class QWaylandSharedMemoryFormatHelper { public: static inline wl_shm_format fromQImageFormat(QImage::Format format); @@ -100,7 +100,7 @@ private: } }; -wl_shm_format QWaylandShmFormatHelper::fromQImageFormat(QImage::Format format) +wl_shm_format QWaylandSharedMemoryFormatHelper::fromQImageFormat(QImage::Format format) { Array array = getData(); if (array.size <= size_t(format)) @@ -108,7 +108,7 @@ wl_shm_format QWaylandShmFormatHelper::fromQImageFormat(QImage::Format format) return array.data[format]; } -QImage::Format QWaylandShmFormatHelper::fromWaylandShmFormat(wl_shm_format format) +QImage::Format QWaylandSharedMemoryFormatHelper::fromWaylandShmFormat(wl_shm_format format) { Array array = getData(); for (size_t i = 0; i < array.size; i++) { @@ -118,7 +118,7 @@ QImage::Format QWaylandShmFormatHelper::fromWaylandShmFormat(wl_shm_format forma return QImage::Format_Invalid; } -QVector<wl_shm_format> QWaylandShmFormatHelper::supportedWaylandFormats() +QVector<wl_shm_format> QWaylandSharedMemoryFormatHelper::supportedWaylandFormats() { QVector<wl_shm_format> retFormats; Array array = getData(); @@ -133,4 +133,4 @@ QVector<wl_shm_format> QWaylandShmFormatHelper::supportedWaylandFormats() QT_END_NAMESPACE -#endif //QWAYLANDSHMFORMATHELPER_H +#endif //QWAYLANDSHAREDMEMORYFORMATHELPER_H |