summaryrefslogtreecommitdiffstats
path: root/tests/auto/qml/windowproperties/apps/wp-app-native
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/qml/windowproperties/apps/wp-app-native')
-rw-r--r--tests/auto/qml/windowproperties/apps/wp-app-native/CMakeLists.txt26
-rw-r--r--tests/auto/qml/windowproperties/apps/wp-app-native/info.yaml6
-rw-r--r--tests/auto/qml/windowproperties/apps/wp-app-native/waylandqtamclientextension_v2.cpp127
-rw-r--r--tests/auto/qml/windowproperties/apps/wp-app-native/waylandqtamclientextension_v2_p.h45
-rw-r--r--tests/auto/qml/windowproperties/apps/wp-app-native/wp-app.cpp33
5 files changed, 237 insertions, 0 deletions
diff --git a/tests/auto/qml/windowproperties/apps/wp-app-native/CMakeLists.txt b/tests/auto/qml/windowproperties/apps/wp-app-native/CMakeLists.txt
new file mode 100644
index 00000000..8bc20ddf
--- /dev/null
+++ b/tests/auto/qml/windowproperties/apps/wp-app-native/CMakeLists.txt
@@ -0,0 +1,26 @@
+
+qt_internal_add_executable(wp-app-native
+ OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/"
+ SOURCES
+ wp-app.cpp
+ waylandqtamclientextension_v2.cpp
+ waylandqtamclientextension_v2_p.h
+ LIBRARIES
+ Qt::Core
+ Qt::Gui
+ Qt::Quick
+ Qt::Qml
+ Qt::WaylandClient
+ Qt::WaylandClientPrivate
+)
+
+qt_internal_set_exceptions_flags(wp-app-native TRUE)
+
+qt_autogen_tools_initial_setup(wp-app-native)
+
+qt6_generate_wayland_protocol_client_sources(wp-app-native
+ FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/wayland-extensions/qtam-extension.xml
+)
+
+qt_internal_add_autogen_sync_header_dependencies(wp-app-native WaylandClient)
diff --git a/tests/auto/qml/windowproperties/apps/wp-app-native/info.yaml b/tests/auto/qml/windowproperties/apps/wp-app-native/info.yaml
new file mode 100644
index 00000000..c145f0c1
--- /dev/null
+++ b/tests/auto/qml/windowproperties/apps/wp-app-native/info.yaml
@@ -0,0 +1,6 @@
+formatVersion: 1
+formatType: am-application
+---
+id: 'wp-app-native'
+code: 'wp-app-native'
+runtime: 'native'
diff --git a/tests/auto/qml/windowproperties/apps/wp-app-native/waylandqtamclientextension_v2.cpp b/tests/auto/qml/windowproperties/apps/wp-app-native/waylandqtamclientextension_v2.cpp
new file mode 100644
index 00000000..62f122da
--- /dev/null
+++ b/tests/auto/qml/windowproperties/apps/wp-app-native/waylandqtamclientextension_v2.cpp
@@ -0,0 +1,127 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "waylandqtamclientextension_v2_p.h"
+
+#include <QWindow>
+#include <QGuiApplication>
+#include <QEvent>
+#include <QExposeEvent>
+#include <qpa/qplatformnativeinterface.h>
+#include <QJSValue>
+#include <QCborValue>
+
+
+// This is a copy of the built-in class WaylandQtAMClientExtension (version 1). Not all
+// functionality is actually used for the test, but it makes it easier to keep the code in sync
+// this way, as they share ~90% of the implementation.
+
+WaylandQtAMClientExtensionV2::WaylandQtAMClientExtensionV2()
+ : QWaylandClientExtensionTemplate(2)
+{
+ qApp->installEventFilter(this);
+}
+
+WaylandQtAMClientExtensionV2::~WaylandQtAMClientExtensionV2()
+{
+ qApp->removeEventFilter(this);
+}
+
+bool WaylandQtAMClientExtensionV2::eventFilter(QObject *o, QEvent *e)
+{
+ if (e->type() == QEvent::Expose) {
+ if (!isActive()) {
+ qWarning() << "WaylandQtAMClientExtensionV2 is not active";
+ } else {
+ QWindow *window = qobject_cast<QWindow *>(o);
+ Q_ASSERT(window);
+
+ // we're only interested in the first expose to setup our mapping
+ if (!m_windowToSurface.contains(window)) {
+ auto surface = static_cast<struct ::wl_surface *>
+ (QGuiApplication::platformNativeInterface()->nativeResourceForWindow("surface", window));
+ if (surface) {
+ m_windowToSurface.insert(window, surface);
+ const QVariantMap wp = windowProperties(window);
+ for (auto it = wp.cbegin(); it != wp.cend(); ++it)
+ sendPropertyToServer(surface, it.key(), it.value());
+ }
+ // pointers can be reused, so we have to remove the old mappings
+ connect(window, &QObject::destroyed, this, [this, window]() {
+ m_windowToSurface.remove(window);
+ m_windowProperties.remove(window);
+ });
+ }
+ }
+ } else if (e->type() == QEvent::Hide) {
+ m_windowToSurface.remove(qobject_cast<QWindow *>(o));
+ }
+
+ return QWaylandClientExtensionTemplate<WaylandQtAMClientExtensionV2>::eventFilter(o, e);
+}
+
+QVariantMap WaylandQtAMClientExtensionV2::windowProperties(QWindow *window) const
+{
+ return m_windowProperties.value(window);
+}
+
+void WaylandQtAMClientExtensionV2::sendPropertyToServer(struct ::wl_surface *surface, const QString &name,
+ const QVariant &value)
+{
+ if (int(qtam_extension::version()) != QWaylandClientExtension::version()) {
+ qWarning() << "Unsupported qtam_extension version:" << qtam_extension::version();
+ return;
+ }
+ const QByteArray data = QCborValue::fromVariant(value).toCbor();
+ set_window_property(surface, name, data);
+}
+
+bool WaylandQtAMClientExtensionV2::setWindowProperty(QWindow *window, const QString &name, const QVariant &value)
+{
+ if (setWindowPropertyHelper(window, name, value) && m_windowToSurface.contains(window)) {
+ auto surface = static_cast<struct ::wl_surface *>
+ (QGuiApplication::platformNativeInterface()->nativeResourceForWindow("surface", window));
+ if (surface) {
+ sendPropertyToServer(surface, name, value);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool WaylandQtAMClientExtensionV2::setWindowPropertyHelper(QWindow *window, const QString &name, const QVariant &value)
+{
+ auto it = m_windowProperties.find(window);
+ if ((it == m_windowProperties.end()) || (it.value().value(name) != value)) {
+ if (it == m_windowProperties.end())
+ m_windowProperties[window].insert(name, value);
+ else
+ it.value().insert(name, value);
+
+ emit windowPropertyChanged(window, name, value);
+ return true;
+ }
+ return false;
+}
+
+void WaylandQtAMClientExtensionV2::clearWindowPropertyCache(QWindow *window)
+{
+ m_windowProperties.remove(window);
+}
+
+void WaylandQtAMClientExtensionV2::qtam_extension_window_property_changed(wl_surface *surface, const QString &name,
+ wl_array *value)
+{
+ if (int(qtam_extension::version()) != QWaylandClientExtension::version()) {
+ qWarning() << "Unsupported qtam_extension version:" << qtam_extension::version();
+ return;
+ }
+
+ if (QWindow *window = m_windowToSurface.key(surface)) {
+ const auto data = QByteArray::fromRawData(static_cast<const char *>(value->data), qsizetype(value->size));
+ const QVariant variantValue = QCborValue::fromCbor(data).toVariant();
+ setWindowPropertyHelper(window, name, variantValue);
+ }
+}
+
+#include "moc_waylandqtamclientextension_v2_p.cpp"
diff --git a/tests/auto/qml/windowproperties/apps/wp-app-native/waylandqtamclientextension_v2_p.h b/tests/auto/qml/windowproperties/apps/wp-app-native/waylandqtamclientextension_v2_p.h
new file mode 100644
index 00000000..04251073
--- /dev/null
+++ b/tests/auto/qml/windowproperties/apps/wp-app-native/waylandqtamclientextension_v2_p.h
@@ -0,0 +1,45 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef WAYLANDQTAMCLIENTEXTENSION_V2_P_H
+#define WAYLANDQTAMCLIENTEXTENSION_V2_P_H
+
+#include <QVariantMap>
+#include <QtWaylandClient/QWaylandClientExtensionTemplate>
+#include "qwayland-qtam-extension.h"
+
+QT_FORWARD_DECLARE_CLASS(QWindow)
+
+// This is a copy of the built-in class WaylandQtAMClientExtension (version 1). Not all
+// functionality is actually used for the test, but it makes it easier to keep the code in sync
+// this way, as they share ~90% of the implementation.
+
+class WaylandQtAMClientExtensionV2 : public QWaylandClientExtensionTemplate<WaylandQtAMClientExtensionV2>,
+ public ::QtWayland::qtam_extension
+{
+ Q_OBJECT
+
+public:
+ WaylandQtAMClientExtensionV2();
+ ~WaylandQtAMClientExtensionV2() override;
+
+ QVariantMap windowProperties(QWindow *window) const;
+ bool setWindowProperty(QWindow *window, const QString &name, const QVariant &value);
+ void clearWindowPropertyCache(QWindow *window);
+
+signals:
+ void windowPropertyChanged(QWindow *window, const QString &name, const QVariant &value);
+
+protected:
+ bool eventFilter(QObject *o, QEvent *e) override;
+
+private:
+ bool setWindowPropertyHelper(QWindow *window, const QString &name, const QVariant &value);
+ void sendPropertyToServer(::wl_surface *surface, const QString &name, const QVariant &value);
+ void qtam_extension_window_property_changed(wl_surface *surface, const QString &name, wl_array *value) override;
+
+ QMap<QWindow *, QVariantMap> m_windowProperties; // AXIVION Line Qt-QMapWithPointerKey: cleared on destroyed signal
+ QMap<QWindow *, ::wl_surface *> m_windowToSurface; // AXIVION Line Qt-QMapWithPointerKey: cleared on destroyed signal
+};
+
+#endif // WAYLANDQTAMCLIENTEXTENSION_V2_P_H
diff --git a/tests/auto/qml/windowproperties/apps/wp-app-native/wp-app.cpp b/tests/auto/qml/windowproperties/apps/wp-app-native/wp-app.cpp
new file mode 100644
index 00000000..207aef6b
--- /dev/null
+++ b/tests/auto/qml/windowproperties/apps/wp-app-native/wp-app.cpp
@@ -0,0 +1,33 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QGuiApplication>
+#include <QQuickView>
+
+#include "waylandqtamclientextension_v2_p.h"
+
+using namespace Qt::StringLiterals;
+
+int main(int argc, char **argv)
+{
+ QGuiApplication app(argc, argv);
+ auto qtamExtension = new WaylandQtAMClientExtensionV2();
+ QQuickView w;
+ w.setGeometry(0, 0, 100, 100);
+ w.show();
+
+ qsizetype expectedSize = 0;
+
+ const auto args = app.arguments();
+ if (auto pos = args.indexOf(u"--start-argument"_s); pos >= 0)
+ expectedSize = args.at(pos + 1).toInt();
+
+ QObject::connect(qtamExtension, &WaylandQtAMClientExtensionV2::windowPropertyChanged,
+ &app, [&](QWindow *, const QString &, const QVariant &) {
+ auto allProperties = qtamExtension->windowProperties(&w);
+ if (allProperties.size() == expectedSize)
+ qtamExtension->setWindowProperty(&w, u"BACKCHANNEL"_s, allProperties);
+ });
+
+ return app.exec();
+}