From 7a279522a8cdc2105efef01264241fea7588b8cf Mon Sep 17 00:00:00 2001 From: Aleix Pol Date: Wed, 27 Apr 2022 18:39:08 +0200 Subject: [PATCH] Provide an xdgactivationtest Adds a test that has two windows and one activates the other. There are two versions: qt5 and qt6. The Qt 6 code is vastly different since Qt 6 knows about xdg_activation_v1, so it makes sense to have both for now. --- tests/CMakeLists.txt | 17 +++++++ tests/xdgactivationtest-qt5.cpp | 90 +++++++++++++++++++++++++++++++++ tests/xdgactivationtest-qt6.cpp | 27 ++++++++++ 3 files changed, 134 insertions(+) create mode 100644 tests/xdgactivationtest-qt5.cpp create mode 100644 tests/xdgactivationtest-qt6.cpp diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index e56541c396..d877fb67b1 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,3 +1,6 @@ +find_package(Qt5 REQUIRED COMPONENTS WaylandClient) +find_package(Qt6 OPTIONAL_COMPONENTS Widgets) + if (XCB_ICCCM_FOUND) set(normalhintsbasesizetest_SRCS normalhintsbasesizetest.cpp) add_executable(normalhintsbasesizetest ${normalhintsbasesizetest_SRCS}) @@ -36,3 +39,17 @@ add_executable(cursorhotspottest cursorhotspottest.cpp) target_link_libraries(cursorhotspottest Qt::Widgets) include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +add_executable(xdgactivationtest-qt5 xdgactivationtest-qt5.cpp) +target_link_libraries(xdgactivationtest-qt5 Qt::Widgets Qt::WaylandClient Qt::WaylandClientPrivate Wayland::Client) +if (QT_MAJOR_VERSION EQUAL "5") + ecm_add_qtwayland_client_protocol(xdgactivationtest-qt5 + PROTOCOL ${WaylandProtocols_DATADIR}/staging/xdg-activation/xdg-activation-v1.xml + BASENAME xdg-activation-v1 + ) +endif() + +if (TARGET Qt6::Gui) + add_executable(xdgactivationtest-qt6 xdgactivationtest-qt6.cpp) + target_link_libraries(xdgactivationtest-qt6 Qt6::Widgets) +endif() diff --git a/tests/xdgactivationtest-qt5.cpp b/tests/xdgactivationtest-qt5.cpp new file mode 100644 index 0000000000..f65ce8b7d8 --- /dev/null +++ b/tests/xdgactivationtest-qt5.cpp @@ -0,0 +1,90 @@ +/* + SPDX-FileCopyrightText: 2022 Aleix Pol Gonzalez + SPDX-FileCopyrightText: 2022 Ilya Fedin + + SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL +*/ + +#include "qwayland-xdg-activation-v1.h" +#include +#include +#include + +class WaylandXdgActivationTokenV1 : public QObject, public QtWayland::xdg_activation_token_v1 +{ + Q_OBJECT +public: + void xdg_activation_token_v1_done(const QString &token) override + { + Q_EMIT done(token); + } + +Q_SIGNALS: + void done(const QString &token); +}; + +class WaylandXdgActivationV1 : public QWaylandClientExtensionTemplate, public QtWayland::xdg_activation_v1 +{ +public: + WaylandXdgActivationV1() + : QWaylandClientExtensionTemplate(1) + { + // QWaylandClientExtensionTemplate invokes this with a QueuedConnection but we want shortcuts + // to be inhibited immediately. + QMetaObject::invokeMethod(this, "addRegistryListener"); + } + + WaylandXdgActivationTokenV1 *requestXdgActivationToken(wl_seat *seat, struct ::wl_surface *surface, uint32_t serial, const QString &app_id) + { + auto wl = get_activation_token(); + auto provider = new WaylandXdgActivationTokenV1; + provider->init(wl); + if (surface) { + provider->set_surface(surface); + } + + if (!app_id.isEmpty()) { + provider->set_app_id(app_id); + } + + if (seat) { + provider->set_serial(serial, seat); + } + provider->commit(); + return provider; + } +}; + +int main(int argc, char *argv[]) +{ + + QApplication app(argc, argv); + QWidget window1(nullptr, Qt::Window); + window1.setWindowTitle("Window 1"); + window1.setLayout(new QVBoxLayout); + QPushButton p("Raise the Window 2"); + window1.layout()->addWidget(&p); + window1.show(); + + QWidget window2(nullptr, Qt::Window); + window2.setWindowTitle("Window 2"); + window2.show(); + + WaylandXdgActivationV1 activation; + QObject::connect(&p, &QPushButton::clicked, &app, [&] { + QPlatformNativeInterface *native = qGuiApp->platformNativeInterface(); + auto seat = static_cast(native->nativeResourceForIntegration("wl_seat")); + wl_surface *surface = reinterpret_cast(native->nativeResourceForWindow(QByteArrayLiteral("surface"), window1.windowHandle())); + auto req = activation.requestXdgActivationToken(seat, surface, 0, {}); + QObject::connect(req, &WaylandXdgActivationTokenV1::done, &app, [&activation, &window2](const QString &token) { + window2.show(); + QPlatformNativeInterface *native = qGuiApp->platformNativeInterface(); + wl_surface *surface = reinterpret_cast(native->nativeResourceForWindow(QByteArrayLiteral("surface"), window2.windowHandle())); + activation.activate(token, surface); + }); + }); + + return app.exec(); +} + +#include "xdgactivationtest-qt5.moc" diff --git a/tests/xdgactivationtest-qt6.cpp b/tests/xdgactivationtest-qt6.cpp new file mode 100644 index 0000000000..f250d531c6 --- /dev/null +++ b/tests/xdgactivationtest-qt6.cpp @@ -0,0 +1,27 @@ +/* + SPDX-FileCopyrightText: 2022 Aleix Pol Gonzalez + SPDX-FileCopyrightText: 2022 Ilya Fedin + + SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL +*/ + +#include + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + QWidget window1(nullptr, Qt::Window); + window1.setWindowTitle("Window 1"); + window1.setLayout(new QVBoxLayout); + QPushButton p("Raise the Window 2"); + window1.layout()->addWidget(&p); + window1.show(); + + QWidget window2(nullptr, Qt::Window); + window2.setWindowTitle("Window 2"); + window2.show(); + + QObject::connect(&p, &QPushButton::clicked, window2.windowHandle(), &QWindow::requestActivate); + + return app.exec(); +}