diff options
Diffstat (limited to 'tests')
224 files changed, 7736 insertions, 6096 deletions
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 000000000..fd2887624 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,28 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +# Generated from tests.pro. + +# special case begin +# TODO: Prepare for removal, once Platform brings in Threads. +if(NOT TARGET Threads::Threads) + qt_find_package(Threads REQUIRED) +endif() +# special case end + +if(QT_BUILD_STANDALONE_TESTS) + # Add qt_find_package calls for extra dependencies that need to be found when building + # the standalone tests here. + # special case begin + qt_find_package(Qt6 ${PROJECT_VERSION} OPTIONAL_COMPONENTS WaylandCompositor WaylandClient) + + if (NOT Qt6WaylandScannerTools_FOUND) + message(WARNING "QtWaylandTests is missing required components, nothing will be built. \ + Although this could be considered an error, the configuration will still pass as coin (Qt's \ + continuous integration system) will fail the build if configure fails, but will still try to \ + configure the module on targets that are missing dependencies.") + return() + endif() + # special case end +endif() +qt_build_tests() diff --git a/tests/auto/CMakeLists.txt b/tests/auto/CMakeLists.txt new file mode 100644 index 000000000..87e83b552 --- /dev/null +++ b/tests/auto/CMakeLists.txt @@ -0,0 +1,14 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +# Generated from auto.pro. + +if(TARGET Qt::WaylandClient) + add_subdirectory(client) +endif() +if(TARGET Qt::WaylandClient AND TARGET Qt::WaylandCompositor) + add_subdirectory(cmake) +endif() +if(TARGET Qt::WaylandCompositor) + add_subdirectory(compositor) +endif() diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro deleted file mode 100644 index 032ae47a4..000000000 --- a/tests/auto/auto.pro +++ /dev/null @@ -1,11 +0,0 @@ -TEMPLATE=subdirs -QT_FOR_CONFIG += waylandclient-private - -qtHaveModule(waylandclient): \ - SUBDIRS += client - -qtHaveModule(waylandclient):qtHaveModule(waylandcompositor): \ - SUBDIRS += cmake - -qtHaveModule(waylandcompositor): \ - SUBDIRS += compositor diff --git a/tests/auto/client/CMakeLists.txt b/tests/auto/client/CMakeLists.txt new file mode 100644 index 000000000..79bcd442e --- /dev/null +++ b/tests/auto/client/CMakeLists.txt @@ -0,0 +1,36 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +# Generated from client.pro. + +add_subdirectory(shared) + +# webOS has a modified version of QtWayland and does not support e.g. multiple window creation +# in a single client, attempting to do so will cause a segmentation fault +if (NOT WEBOS) + add_subdirectory(client) + add_subdirectory(clientextension) + add_subdirectory(cursor) + add_subdirectory(datadevicev1) + add_subdirectory(fullscreenshellv1) + add_subdirectory(iviapplication) + add_subdirectory(nooutput) + add_subdirectory(output) + add_subdirectory(primaryselectionv1) + add_subdirectory(reconnect) + add_subdirectory(seatv4) + add_subdirectory(seatv7) + add_subdirectory(seat) + add_subdirectory(surface) + add_subdirectory(tabletv2) + add_subdirectory(wl_connect) + add_subdirectory(xdgdecorationv1) + add_subdirectory(xdgoutput) + add_subdirectory(xdgshell) + add_subdirectory(scaling) +endif() +add_subdirectory(multithreaded) + +if(QT_FEATURE_im) + add_subdirectory(inputcontext) +endif() diff --git a/tests/auto/client/client.pro b/tests/auto/client/client.pro deleted file mode 100644 index 4b1eb2458..000000000 --- a/tests/auto/client/client.pro +++ /dev/null @@ -1,19 +0,0 @@ -TEMPLATE=subdirs - -SUBDIRS += \ - client \ - datadevicev1 \ - fullscreenshellv1 \ - iviapplication \ - output \ - primaryselectionv1 \ - seatv4 \ - seatv5 \ - surface \ - wl_connect \ - xdgdecorationv1 \ - xdgoutput \ - xdgshell \ - xdgshellv6 - -qtConfig(im): SUBDIRS += inputcontext diff --git a/tests/auto/client/client/CMakeLists.txt b/tests/auto/client/client/CMakeLists.txt new file mode 100644 index 000000000..c6495eb6b --- /dev/null +++ b/tests/auto/client/client/CMakeLists.txt @@ -0,0 +1,18 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +# Generated from client.pro. + +##################################################################### +## tst_client Test: +##################################################################### + +qt_internal_add_test(tst_client + SOURCES + tst_client.cpp + LIBRARIES + SharedClientTest +) + +#### Keys ignored in scope 1:.:.:client.pro:<TRUE>: +# check.commands = "$(TESTRUNNER)" "$${PWD}/run-with-all-shells.sh" "$(TESTARGS)" diff --git a/tests/auto/client/client/client.pro b/tests/auto/client/client/client.pro deleted file mode 100644 index 7c3a934d0..000000000 --- a/tests/auto/client/client/client.pro +++ /dev/null @@ -1,6 +0,0 @@ -include (../shared_old/shared_old.pri) - -TARGET = tst_client -SOURCES += tst_client.cpp - -check.commands = $(TESTRUNNER) $${PWD}/run-with-all-shells.sh $(TESTARGS) diff --git a/tests/auto/client/client/run-with-all-shells.sh b/tests/auto/client/client/run-with-all-shells.sh index 41f383900..5acd85a46 100755 --- a/tests/auto/client/client/run-with-all-shells.sh +++ b/tests/auto/client/client/run-with-all-shells.sh @@ -3,4 +3,3 @@ set -ex $@ env QT_WAYLAND_SHELL_INTEGRATION=wl-shell $@ env QT_WAYLAND_SHELL_INTEGRATION=ivi-shell $@ -env QT_WAYLAND_SHELL_INTEGRATION=xdg-shell-v6 $@ diff --git a/tests/auto/client/client/tst_client.cpp b/tests/auto/client/client/tst_client.cpp index 499a93a1d..253a98b73 100644 --- a/tests/auto/client/client/tst_client.cpp +++ b/tests/auto/client/client/tst_client.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "mockcompositor.h" @@ -44,7 +19,21 @@ #include <QtWaylandClient/private/qwaylandintegration_p.h> #include <QtGui/private/qguiapplication_p.h> -static const QSize screenSize(1600, 1200); +using namespace MockCompositor; + +constexpr int dataDeviceVersion = 1; + +class TestCompositor : public WlShellCompositor { +public: + explicit TestCompositor() + { + exec([this] { + m_config.autoConfigure = true; + add<DataDeviceManager>(dataDeviceVersion); + }); + } + DataDevice *dataDevice() { return get<DataDeviceManager>()->deviceFor(get<Seat>()); } +}; class TestWindow : public QWindow { @@ -81,7 +70,7 @@ public: void mousePressEvent(QMouseEvent *event) override { ++mousePressEventCount; - mousePressPos = event->pos(); + mousePressPos = event->position().toPoint(); } void mouseReleaseEvent(QMouseEvent *) override @@ -141,36 +130,14 @@ void TestGlWindow::paintGL() } #endif // QT_CONFIG(opengl) -class tst_WaylandClient : public QObject +class tst_WaylandClient : public QObject, private TestCompositor { Q_OBJECT -public: - tst_WaylandClient(MockCompositor *c) - : compositor(c) - { - QSocketNotifier *notifier = new QSocketNotifier(compositor->waylandFileDescriptor(), QSocketNotifier::Read, this); - connect(notifier, SIGNAL(activated(int)), this, SLOT(processWaylandEvents())); - // connect to the event dispatcher to make sure to flush out the outgoing message queue - connect(QCoreApplication::eventDispatcher(), &QAbstractEventDispatcher::awake, this, &tst_WaylandClient::processWaylandEvents); - connect(QCoreApplication::eventDispatcher(), &QAbstractEventDispatcher::aboutToBlock, this, &tst_WaylandClient::processWaylandEvents); - } - -public slots: - void processWaylandEvents() - { - compositor->processWaylandEvents(); - } - - void cleanup() - { - // make sure the surfaces from the last test are properly cleaned up - // and don't show up as false positives in the next test - QTRY_VERIFY(!compositor->surface()); - QTRY_VERIFY(!compositor->iviSurface()); - QTRY_VERIFY(!compositor->xdgToplevelV6()); - } private slots: + void cleanup() { + QTRY_VERIFY2(isClean(), qPrintable(dirtyMessage())); + } void createDestroyWindow(); void activeWindowFollowsKeyboardFocus(); void events(); @@ -185,9 +152,6 @@ private slots: #endif // QT_CONFIG(opengl) void longWindowTitle(); void longWindowTitleWithUtf16Characters(); - -private: - MockCompositor *compositor = nullptr; }; void tst_WaylandClient::createDestroyWindow() @@ -195,10 +159,10 @@ void tst_WaylandClient::createDestroyWindow() TestWindow window; window.show(); - QTRY_VERIFY(compositor->surface()); + QCOMPOSITOR_TRY_VERIFY(surface()); window.destroy(); - QTRY_VERIFY(!compositor->surface()); + QCOMPOSITOR_TRY_VERIFY(!surface()); } void tst_WaylandClient::activeWindowFollowsKeyboardFocus() @@ -206,24 +170,27 @@ void tst_WaylandClient::activeWindowFollowsKeyboardFocus() TestWindow window; window.show(); - QSharedPointer<MockSurface> surface; - QTRY_VERIFY(surface = compositor->surface()); - compositor->sendShellSurfaceConfigure(surface); - - QTRY_VERIFY(window.isExposed()); + Surface *s = nullptr; + QCOMPOSITOR_TRY_VERIFY(s = surface()); + exec([&] { + sendShellSurfaceConfigure(s); + }); - if (compositor->xdgToplevelV6()) - QSKIP("On xdg-shell v6 focus is handled by configure events"); + QCOMPOSITOR_TRY_VERIFY(window.isExposed()); QCOMPARE(window.focusInEventCount, 0); - compositor->setKeyboardFocus(surface); + exec([&] { + keyboard()->sendEnter(s); + }); QTRY_COMPARE(window.focusInEventCount, 1); - QTRY_COMPARE(QGuiApplication::focusWindow(), &window); + QCOMPARE(QGuiApplication::focusWindow(), &window); QCOMPARE(window.focusOutEventCount, 0); - compositor->setKeyboardFocus(QSharedPointer<MockSurface>(nullptr)); + exec([&] { + keyboard()->sendLeave(s); // or implement setFocus in Keyboard + }); QTRY_COMPARE(window.focusOutEventCount, 1); - QTRY_COMPARE(QGuiApplication::focusWindow(), static_cast<QWindow *>(nullptr)); + QCOMPARE(QGuiApplication::focusWindow(), static_cast<QWindow *>(nullptr)); } void tst_WaylandClient::events() @@ -231,46 +198,78 @@ void tst_WaylandClient::events() TestWindow window; window.show(); - QSharedPointer<MockSurface> surface; - QTRY_VERIFY(surface = compositor->surface()); - compositor->sendShellSurfaceConfigure(surface); + Surface *s = nullptr; + QCOMPOSITOR_TRY_VERIFY(s = surface()); + exec([&] { + sendShellSurfaceConfigure(s); + }); - QTRY_VERIFY(window.isExposed()); + QCOMPOSITOR_TRY_VERIFY(window.isExposed()); - compositor->setKeyboardFocus(surface); - QTRY_COMPARE(window.focusInEventCount, 1); - QTRY_COMPARE(QGuiApplication::focusWindow(), &window); + QCOMPARE(window.focusInEventCount, 0); + exec([&] { + keyboard()->sendEnter(s); + }); + QTRY_COMPARE(window.focusInEventCount, 1); + QCOMPARE(QGuiApplication::focusWindow(), &window); + + // See also https://wayland.app/protocols/wayland#wl_keyboard:enum:keymap_format + // wl_keyboard::keymap_format + // keymap_format { no_keymap, xkb_v1 } + // Argument Value Description + // no_keymap 0 no keymap; client must understand how to interpret the raw keycode + // xkb_v1 1 libxkbcommon compatible; to determine the xkb keycode, clients must add 8 to the key event keycode uint keyCode = 80; // arbitrarily chosen QCOMPARE(window.keyPressEventCount, 0); - compositor->sendKeyPress(surface, keyCode); + exec([&] { + keyboard()->sendKey(client(), keyCode - 8, Keyboard::key_state_pressed); // related with native scan code + }); QTRY_COMPARE(window.keyPressEventCount, 1); - QTRY_COMPARE(window.keyCode, keyCode); + QCOMPARE(window.keyCode, keyCode); QCOMPARE(window.keyReleaseEventCount, 0); - compositor->sendKeyRelease(surface, keyCode); + exec([&] { + keyboard()->sendKey(client(), keyCode - 8, Keyboard::key_state_released); // related with native scan code + }); QTRY_COMPARE(window.keyReleaseEventCount, 1); QCOMPARE(window.keyCode, keyCode); const int touchId = 0; - compositor->sendTouchDown(surface, window.frameOffset() + QPoint(10, 10), touchId); + exec([&] { + touch()->sendDown(s, window.frameOffset() + QPoint(10, 10), touchId); + }); // Note: wl_touch.frame should not be the last event in a test until QTBUG-66563 is fixed. // See also: QTBUG-66537 - compositor->sendTouchFrame(surface); + exec([&] { + touch()->sendFrame(client()); + }); QTRY_COMPARE(window.touchEventCount, 1); - compositor->sendTouchUp(surface, touchId); - compositor->sendTouchFrame(surface); + exec([&] { + touch()->sendUp(client(), touchId); + touch()->sendFrame(client()); + }); QTRY_COMPARE(window.touchEventCount, 2); QPoint mousePressPos(16, 16); QCOMPARE(window.mousePressEventCount, 0); - compositor->sendMousePress(surface, window.frameOffset() + mousePressPos); + exec([&] { + pointer()->sendEnter(s, window.frameOffset() + mousePressPos); + pointer()->sendFrame(client()); + pointer()->sendMotion(client(), window.frameOffset() + mousePressPos); + pointer()->sendFrame(client()); + pointer()->sendButton(client(), BTN_LEFT, Pointer::button_state_pressed); + pointer()->sendFrame(client()); + }); QTRY_COMPARE(window.mousePressEventCount, 1); QTRY_COMPARE(window.mousePressPos, mousePressPos); QCOMPARE(window.mouseReleaseEventCount, 0); - compositor->sendMouseRelease(surface); + exec([&] { + pointer()->sendButton(client(), BTN_LEFT, Pointer::button_state_released); + pointer()->sendFrame(client()); + }); QTRY_COMPARE(window.mouseReleaseEventCount, 1); } @@ -279,9 +278,11 @@ void tst_WaylandClient::backingStore() TestWindow window; window.show(); - QSharedPointer<MockSurface> surface; - QTRY_VERIFY(surface = compositor->surface()); - compositor->sendShellSurfaceConfigure(surface); + Surface *s = nullptr; + QCOMPOSITOR_TRY_VERIFY(s = surface()); + exec([&] { + sendShellSurfaceConfigure(s); + }); QRect rect(QPoint(), window.size()); @@ -298,17 +299,17 @@ void tst_WaylandClient::backingStore() backingStore.endPaint(); - QVERIFY(surface->image.isNull()); + QVERIFY(s->m_image.isNull()); backingStore.flush(rect); - QTRY_COMPARE(surface->image.size(), window.frameGeometry().size()); - QTRY_COMPARE(surface->image.pixel(window.frameMargins().left(), window.frameMargins().top()), color.rgba()); + QTRY_COMPARE(s->m_image.size(), window.frameGeometry().size()); + QTRY_COMPARE(s->m_image.pixel(window.frameMargins().left(), window.frameMargins().top()), color.rgba()); window.hide(); // hiding the window should destroy the surface - QTRY_VERIFY(!compositor->surface()); + QCOMPOSITOR_TRY_VERIFY(!surface()); } class DndWindow : public QWindow @@ -347,29 +348,76 @@ private: QPixmap m_dragIcon; }; +class DNDTest : public QObject +{ + Q_OBJECT + +public: + DNDTest(QObject *parent = nullptr) + : QObject(parent) {} + + Surface *m_surface = nullptr; + TestCompositor *m_compositor = nullptr; + QPoint m_frameOffset; + +public slots: + void finishMouseDrag(); + void touchDrag(); +}; + +void DNDTest::finishMouseDrag() +{ + m_compositor->exec([&] { + m_compositor->dataDevice()->sendDrop(m_surface); + m_compositor->dataDevice()->sendLeave(m_surface); + }); +} + +void DNDTest::touchDrag() +{ + m_compositor->exec([&] { + m_compositor->dataDevice()->sendDataOffer(m_surface->resource()->client()); + m_compositor->dataDevice()->sendEnter(m_surface, m_frameOffset + QPoint(20, 20)); + m_compositor->dataDevice()->sendMotion(m_surface, m_frameOffset + QPoint(21, 21)); + m_compositor->dataDevice()->sendDrop(m_surface); + m_compositor->dataDevice()->sendLeave(m_surface); + }); +} + void tst_WaylandClient::touchDrag() { DndWindow window; window.show(); - QSharedPointer<MockSurface> surface; - QTRY_VERIFY(surface = compositor->surface()); - compositor->sendShellSurfaceConfigure(surface); - - compositor->setKeyboardFocus(surface); + Surface *s = nullptr; + QCOMPOSITOR_TRY_VERIFY(s = surface()); + exec([&] { + sendShellSurfaceConfigure(s); + }); + + DNDTest test; + test.m_surface = s; + test.m_compositor = this; + test.m_frameOffset = window.frameOffset(); + + exec([&] { + QObject::connect(dataDevice(), &DataDevice::dragStarted, + &test, &DNDTest::touchDrag); + }); + + exec([&] { + keyboard()->sendEnter(s); + }); QTRY_COMPARE(QGuiApplication::focusWindow(), &window); - const int id = 0; - compositor->sendTouchDown(surface, window.frameOffset() + QPoint(10, 10), id); - compositor->sendTouchFrame(surface); - compositor->sendTouchMotion(surface, window.frameOffset() + QPoint(20, 20), id); - compositor->sendTouchFrame(surface); - compositor->waitForStartDrag(); - compositor->sendDataDeviceDataOffer(surface); - compositor->sendDataDeviceEnter(surface, window.frameOffset() + QPoint(20, 20)); - compositor->sendDataDeviceMotion(window.frameOffset() + QPoint(21, 21)); - compositor->sendDataDeviceDrop(surface); - compositor->sendDataDeviceLeave(surface); + const int touchId = 0; + exec([&] { + touch()->sendDown(s, window.frameOffset() + QPoint(10, 10), touchId); + touch()->sendFrame(client()); + touch()->sendMotion(client(), window.frameOffset() + QPoint(20, 20), touchId); + touch()->sendFrame(client()); + }); + QTRY_VERIFY(window.dragStarted); } @@ -378,20 +426,40 @@ void tst_WaylandClient::mouseDrag() DndWindow window; window.show(); - QSharedPointer<MockSurface> surface; - QTRY_VERIFY(surface = compositor->surface()); - compositor->sendShellSurfaceConfigure(surface); + Surface *s = nullptr; + QCOMPOSITOR_TRY_VERIFY(s = surface()); + exec([&] { + sendShellSurfaceConfigure(s); + }); + + DNDTest test; + test.m_surface = s; + test.m_compositor = this; - compositor->setKeyboardFocus(surface); + exec([&] { + QObject::connect(dataDevice(), &DataDevice::dragStarted, + &test, &DNDTest::finishMouseDrag); + }); + + exec([&] { + keyboard()->sendEnter(s); + }); QTRY_COMPARE(QGuiApplication::focusWindow(), &window); - compositor->sendMousePress(surface, window.frameOffset() + QPoint(10, 10)); - compositor->sendDataDeviceDataOffer(surface); - compositor->sendDataDeviceEnter(surface, window.frameOffset() + QPoint(20, 20)); - compositor->sendDataDeviceMotion(window.frameOffset() + QPoint(21, 21)); - compositor->waitForStartDrag(); - compositor->sendDataDeviceDrop(surface); - compositor->sendDataDeviceLeave(surface); + QPoint mousePressPos(16, 16); + exec([&] { + pointer()->sendEnter(s, window.frameOffset() + mousePressPos); + pointer()->sendFrame(client()); + pointer()->sendMotion(client(), window.frameOffset() + mousePressPos); + pointer()->sendFrame(client()); + pointer()->sendButton(client(), BTN_LEFT, Pointer::button_state_pressed); + pointer()->sendFrame(client()); + + dataDevice()->sendDataOffer(s->resource()->client()); + dataDevice()->sendEnter(s, window.frameOffset() + QPoint(20, 20)); + dataDevice()->sendMotion(s, window.frameOffset() + QPoint(21, 21)); + }); + QTRY_VERIFY(window.dragStarted); } @@ -416,10 +484,11 @@ void tst_WaylandClient::dontCrashOnMultipleCommits() backingStore.flush(rect); backingStore.flush(rect); - compositor->processWaylandEvents(); + QCOMPOSITOR_TRY_VERIFY(surface()); } delete window; + QCOMPOSITOR_TRY_VERIFY(!surface()); } void tst_WaylandClient::hiddenTransientParent() @@ -430,15 +499,14 @@ void tst_WaylandClient::hiddenTransientParent() transient.setTransientParent(&parent); parent.show(); - QTRY_VERIFY(compositor->surface()); + QCOMPOSITOR_TRY_VERIFY(surface()); parent.hide(); - QTRY_VERIFY(!compositor->surface()); + QCOMPOSITOR_TRY_VERIFY(!surface()); transient.show(); - QTRY_VERIFY(compositor->surface()); + QCOMPOSITOR_TRY_VERIFY(surface()); } - void tst_WaylandClient::hiddenPopupParent() { TestWindow toplevel; @@ -446,12 +514,23 @@ void tst_WaylandClient::hiddenPopupParent() // wl_shell relies on a mouse event in order to send a serial and seat // with the set_popup request. - QSharedPointer<MockSurface> surface; - QTRY_VERIFY(surface = compositor->surface()); - compositor->sendShellSurfaceConfigure(surface); + Surface *s = nullptr; + QCOMPOSITOR_TRY_VERIFY(s = surface()); + exec([&] { + sendShellSurfaceConfigure(s); + }); + QCOMPOSITOR_TRY_VERIFY(toplevel.isExposed()); + QPoint mousePressPos(16, 16); QCOMPARE(toplevel.mousePressEventCount, 0); - compositor->sendMousePress(surface, toplevel.frameOffset() + mousePressPos); + exec([&] { + pointer()->sendEnter(s, toplevel.frameOffset() + mousePressPos); + pointer()->sendFrame(client()); + pointer()->sendMotion(client(), toplevel.frameOffset() + mousePressPos); + pointer()->sendFrame(client()); + pointer()->sendButton(client(), BTN_LEFT, Pointer::button_state_pressed); + pointer()->sendFrame(client()); + }); QTRY_COMPARE(toplevel.mousePressEventCount, 1); QWindow popup; @@ -459,10 +538,10 @@ void tst_WaylandClient::hiddenPopupParent() popup.setFlag(Qt::Popup, true); toplevel.hide(); - QTRY_VERIFY(!compositor->surface()); + QCOMPOSITOR_TRY_VERIFY(!surface()); popup.show(); - QTRY_VERIFY(compositor->surface()); + QCOMPOSITOR_TRY_VERIFY(surface()); } #if QT_CONFIG(opengl) @@ -472,9 +551,11 @@ void tst_WaylandClient::glWindow() QScopedPointer<TestGlWindow> testWindow(new TestGlWindow); testWindow->show(); - QSharedPointer<MockSurface> surface; - QTRY_VERIFY(surface = compositor->surface()); - compositor->sendShellSurfaceConfigure(surface); + Surface *s = nullptr; + QCOMPOSITOR_TRY_VERIFY(s = surface()); + exec([&] { + sendShellSurfaceConfigure(s); + }); QTRY_COMPARE(testWindow->paintGLCalled, 1); @@ -489,7 +570,7 @@ void tst_WaylandClient::glWindow() //confirm we don't crash when we delete an already hidden GL window //QTBUG-65553 testWindow->setVisible(false); - QTRY_VERIFY(!compositor->surface()); + QCOMPOSITOR_TRY_VERIFY(!surface()); } #endif // QT_CONFIG(opengl) @@ -500,17 +581,17 @@ void tst_WaylandClient::longWindowTitle() QString absurdlyLongTitle(10000, QLatin1Char('z')); window.setTitle(absurdlyLongTitle); window.show(); - QTRY_VERIFY(compositor->surface()); + QCOMPOSITOR_TRY_VERIFY(surface()); } void tst_WaylandClient::longWindowTitleWithUtf16Characters() { QWindow window; QString absurdlyLongTitle = QString("三").repeated(10000); - Q_ASSERT(absurdlyLongTitle.length() == 10000); // just making sure the test isn't broken + Q_ASSERT(absurdlyLongTitle.size() == 10000); // just making sure the test isn't broken window.setTitle(absurdlyLongTitle); window.show(); - QTRY_VERIFY(compositor->surface()); + QCOMPOSITOR_TRY_VERIFY(surface()); } int main(int argc, char **argv) @@ -518,22 +599,15 @@ int main(int argc, char **argv) QTemporaryDir tmpRuntimeDir; setenv("XDG_RUNTIME_DIR", tmpRuntimeDir.path().toLocal8Bit(), 1); setenv("QT_QPA_PLATFORM", "wayland", 1); // force QGuiApplication to use wayland plugin + QString shell = QString::fromLocal8Bit(qgetenv("QT_WAYLAND_SHELL_INTEGRATION")); + if (shell.isEmpty()) + setenv("QT_WAYLAND_SHELL_INTEGRATION", "wl-shell", 1); - MockCompositor compositor; - compositor.setOutputMode(screenSize); - + tst_WaylandClient tc; QGuiApplication app(argc, argv); - - // Initializing some client buffer integrations (i.e. eglInitialize) may block while waiting - // for a wayland sync. So we call clientBufferIntegration prior to applicationInitialized - // (while the compositor processes events without waiting) in order to avoid hanging later. - auto *waylandIntegration = static_cast<QtWaylandClient::QWaylandIntegration *>(QGuiApplicationPrivate::platformIntegration()); - waylandIntegration->clientBufferIntegration(); - - compositor.applicationInitialized(); - - tst_WaylandClient tc(&compositor); + QTEST_SET_MAIN_SOURCE_PATH return QTest::qExec(&tc, argc, argv); } #include <tst_client.moc> + diff --git a/tests/auto/client/clientextension/CMakeLists.txt b/tests/auto/client/clientextension/CMakeLists.txt new file mode 100644 index 000000000..4997b7d77 --- /dev/null +++ b/tests/auto/client/clientextension/CMakeLists.txt @@ -0,0 +1,17 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +qt_internal_add_test(tst_clientextension + SOURCES + tst_clientextension.cpp + LIBRARIES + SharedClientTest +) + +qt6_generate_wayland_protocol_client_sources(tst_clientextension + FILES ${CMAKE_CURRENT_SOURCE_DIR}/test.xml +) + +qt6_generate_wayland_protocol_server_sources(tst_clientextension + FILES ${CMAKE_CURRENT_SOURCE_DIR}/test.xml +) diff --git a/tests/auto/client/clientextension/test.xml b/tests/auto/client/clientextension/test.xml new file mode 100644 index 000000000..f8d5b4eac --- /dev/null +++ b/tests/auto/client/clientextension/test.xml @@ -0,0 +1,6 @@ +<protocol name="test"> + <interface name="test_interface" version="1"> + <request name="release" type="destructor" /> + </interface> +</protocol> + diff --git a/tests/auto/client/clientextension/tst_clientextension.cpp b/tests/auto/client/clientextension/tst_clientextension.cpp new file mode 100644 index 000000000..8dd4e0d98 --- /dev/null +++ b/tests/auto/client/clientextension/tst_clientextension.cpp @@ -0,0 +1,134 @@ +// Copyright (C) 2021 David Redondo <qt@david-redondo.de> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include <QSignalSpy> +#include <QtGui/private/qguiapplication_p.h> +#include <QtWaylandClient/private/qwayland-wayland.h> +#include <QtWaylandClient/private/qwaylanddisplay_p.h> +#include <QtWaylandClient/private/qwaylandintegration_p.h> +#include <QtWaylandClient/qwaylandclientextension.h> +#include <qwayland-server-test.h> +#include <qwayland-test.h> +#include "mockcompositor.h" +#include "coreprotocol.h" + +using namespace MockCompositor; + +class TestExtension + : public QWaylandClientExtensionTemplate<TestExtension, &QtWayland::test_interface::release>, + public QtWayland::test_interface +{ +public: + TestExtension() : QWaylandClientExtensionTemplate(1){}; + void initialize() { QWaylandClientExtension::initialize(); } +}; + +class TestGlobal : public Global, public QtWaylandServer::test_interface +{ + Q_OBJECT +public: + explicit TestGlobal(CoreCompositor *compositor) + : QtWaylandServer::test_interface(compositor->m_display, 1) + { + } +}; + +class tst_clientextension : public QObject, private CoreCompositor +{ + Q_OBJECT +private: + QtWaylandClient::QWaylandDisplay *display() + { + return static_cast<QtWaylandClient::QWaylandIntegration *>( + QGuiApplicationPrivate::platformIntegration()) + ->display(); + } +private slots: + void cleanup() + { + display()->flushRequests(); + dispatch(); + exec([this] { removeAll<TestGlobal>(); }); + QTRY_COMPARE(display()->globals().size(), 0); + } + void createWithoutGlobal(); + void createWithGlobalAutomatic(); + void createWithGlobalManual(); + void globalBecomesAvailable(); + void globalRemoved(); +}; + +void tst_clientextension::createWithoutGlobal() +{ + TestExtension extension; + QSignalSpy spy(&extension, &QWaylandClientExtension::activeChanged); + QVERIFY(spy.isValid()); + QVERIFY(!extension.isActive()); + QCOMPARE(spy.size(), 0); + extension.initialize(); + QVERIFY(!extension.isActive()); + QCOMPARE(spy.size(), 0); +} + +void tst_clientextension::createWithGlobalAutomatic() +{ + exec([this] { add<TestGlobal>(); }); + QTRY_COMPARE(display()->globals().size(), 1); + TestExtension extension; + QSignalSpy spy(&extension, &QWaylandClientExtension::activeChanged); + QVERIFY(spy.isValid()); + QTRY_VERIFY(extension.isActive()); + QCOMPARE(spy.size(), 1); +} + +void tst_clientextension::createWithGlobalManual() +{ + exec([this] { add<TestGlobal>(); }); + QTRY_COMPARE(display()->globals().size(), 1); + // Wait for the display to have the global + TestExtension extension; + QSignalSpy spy(&extension, &QWaylandClientExtension::activeChanged); + QVERIFY(spy.isValid()); + extension.initialize(); + QVERIFY(extension.isActive()); + QCOMPARE(spy.size(), 1); +} + +void tst_clientextension::globalBecomesAvailable() +{ + TestExtension extension; + QSignalSpy spy(&extension, &QWaylandClientExtension::activeChanged); + QVERIFY(spy.isValid()); + exec([this] { add<TestGlobal>(); }); + QTRY_VERIFY(extension.isActive()); + QCOMPARE(spy.size(), 1); +} + +void tst_clientextension::globalRemoved() +{ + exec([this] { add<TestGlobal>(); }); + TestExtension extension; + QTRY_VERIFY(extension.isActive()); + QSignalSpy spy(&extension, &QWaylandClientExtension::activeChanged); + QVERIFY(spy.isValid()); + QCOMPOSITOR_TRY_COMPARE(get<TestGlobal>()->resourceMap().size(), 1); + + exec([this] { removeAll<TestGlobal>(); }); + QTRY_VERIFY(!extension.isActive()); + QCOMPARE(spy.size(), 1); +} + +int main(int argc, char **argv) +{ + QTemporaryDir tmpRuntimeDir; + setenv("XDG_RUNTIME_DIR", tmpRuntimeDir.path().toLocal8Bit(), 1); + setenv("QT_QPA_PLATFORM", "wayland", 1); + setenv("QT_WAYLAND_DONT_CHECK_SHELL_INTEGRATION", "1", 1); + + tst_clientextension tc; + QGuiApplication app(argc, argv); + QTEST_SET_MAIN_SOURCE_PATH + return QTest::qExec(&tc, argc, argv); +} + +#include "tst_clientextension.moc" diff --git a/tests/auto/client/cursor/CMakeLists.txt b/tests/auto/client/cursor/CMakeLists.txt new file mode 100644 index 000000000..a7814a2c2 --- /dev/null +++ b/tests/auto/client/cursor/CMakeLists.txt @@ -0,0 +1,11 @@ +##################################################################### +## tst_cursor Test: +##################################################################### + +qt_internal_add_test(tst_wayland_cursor + SOURCES + tst_cursor.cpp + cursorshapev1.cpp + LIBRARIES + SharedClientTest +) diff --git a/tests/auto/client/cursor/cursorshapev1.cpp b/tests/auto/client/cursor/cursorshapev1.cpp new file mode 100644 index 000000000..93750df95 --- /dev/null +++ b/tests/auto/client/cursor/cursorshapev1.cpp @@ -0,0 +1,47 @@ +// Copyright (C) 2023 David Edmundson <davidedmundson@kde.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "cursorshapev1.h" + +namespace MockCompositor { + +CursorShapeManager::CursorShapeManager(CoreCompositor *compositor, int version) + : QtWaylandServer::wp_cursor_shape_manager_v1(compositor->m_display, version) +{ +} + +void CursorShapeManager::wp_cursor_shape_manager_v1_get_pointer(Resource *resource, uint32_t id, wl_resource *pointer) +{ + auto *p = fromResource<Pointer>(pointer); + auto *cursorShape = new CursorShapeDevice(p, resource->client(), id, resource->version()); + connect(cursorShape, &QObject::destroyed, this, [this, cursorShape]() { + m_cursorDevices.removeOne(cursorShape); + }); + m_cursorDevices << cursorShape; +} + +CursorShapeDevice::CursorShapeDevice(Pointer *pointer, wl_client *client, int id, int version) + : QtWaylandServer::wp_cursor_shape_device_v1(client, id, version) + , m_pointer(pointer) +{ +} + +void CursorShapeDevice::wp_cursor_shape_device_v1_destroy_resource(Resource *resource) +{ + Q_UNUSED(resource) + delete this; +} + +void CursorShapeDevice::wp_cursor_shape_device_v1_destroy(Resource *resource) +{ + wl_resource_destroy(resource->handle); +} + +void CursorShapeDevice::wp_cursor_shape_device_v1_set_shape(Resource *resource, uint32_t serial, uint32_t shape) +{ + Q_UNUSED(resource); + m_currentShape = static_cast<CursorShapeDevice::shape>(shape); + emit setCursor(serial); +} + +} diff --git a/tests/auto/client/cursor/cursorshapev1.h b/tests/auto/client/cursor/cursorshapev1.h new file mode 100644 index 000000000..0befc3223 --- /dev/null +++ b/tests/auto/client/cursor/cursorshapev1.h @@ -0,0 +1,44 @@ +// Copyright (C) 2023 David Edmundson <davidedmundson@kde.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#ifndef MOCKCOMPOSITOR_CURSORSHAPE_H +#define MOCKCOMPOSITOR_CURSORSHAPE_H + +#include "coreprotocol.h" +#include <qwayland-server-cursor-shape-v1.h> + +namespace MockCompositor { + +class CursorShapeDevice; + +class CursorShapeManager : public Global, public QtWaylandServer::wp_cursor_shape_manager_v1 +{ + Q_OBJECT +public: + explicit CursorShapeManager(CoreCompositor *compositor, int version = 1); + QList<CursorShapeDevice *> m_cursorDevices; + +protected: + void wp_cursor_shape_manager_v1_get_pointer(Resource *resource, uint32_t id, wl_resource *pointer) override; +}; + +class CursorShapeDevice : public QObject, public QtWaylandServer::wp_cursor_shape_device_v1 +{ + Q_OBJECT +public: + explicit CursorShapeDevice(Pointer *pointer, wl_client *client, int id, int version); + Pointer *m_pointer; + shape m_currentShape = shape_default; + +Q_SIGNALS: + void setCursor(uint serial); + +protected: + void wp_cursor_shape_device_v1_destroy_resource(Resource *resource) override; + void wp_cursor_shape_device_v1_destroy(Resource *resource) override; + void wp_cursor_shape_device_v1_set_shape(Resource *resource, uint32_t serial, uint32_t shape) override; +}; + +} + +#endif diff --git a/tests/auto/client/cursor/tst_cursor.cpp b/tests/auto/client/cursor/tst_cursor.cpp new file mode 100644 index 000000000..070e062f6 --- /dev/null +++ b/tests/auto/client/cursor/tst_cursor.cpp @@ -0,0 +1,103 @@ +// Copyright (C) 2023 David Edmundson <davidedmundson@kde.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "mockcompositor.h" +#include <QtGui/QRasterWindow> +#include <QtGui/qpa/qplatformnativeinterface.h> +#include <QtWaylandClient/private/wayland-wayland-client-protocol.h> +#include <QtWaylandClient/private/qwaylandwindow_p.h> + +#include "cursorshapev1.h" + +using namespace MockCompositor; + +class tst_cursor : public QObject, private DefaultCompositor +{ + Q_OBJECT +public: + tst_cursor(); + CursorShapeDevice* cursorShape(); +private slots: + void init(); + void cleanup() { QTRY_VERIFY2(isClean(), qPrintable(dirtyMessage())); } + void setCursor(); +}; + +tst_cursor::tst_cursor() +{ + exec([this] { + m_config.autoConfigure = true; + add<CursorShapeManager>(1); + }); +} + +CursorShapeDevice* tst_cursor::cursorShape() +{ + auto manager = get<CursorShapeManager>(); + if (!manager->m_cursorDevices.count()) + return nullptr; + return manager->m_cursorDevices[0]; +} + +void tst_cursor::init() +{ + setenv("QT_WAYLAND_DISABLE_WINDOWDECORATION", "1", 1); +} + +void tst_cursor::setCursor() +{ + QCOMPOSITOR_TRY_VERIFY(cursorShape()); + QSignalSpy setCursorSpy(exec([&] { return pointer(); }), &Pointer::setCursor); + QSignalSpy setCursorShapeSpy(exec([&] { return cursorShape(); }), &CursorShapeDevice::setCursor); + + QRasterWindow window; + window.resize(64, 64); + window.show(); + QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial); + + uint enterSerial = exec([&] { + return pointer()->sendEnter(xdgSurface()->m_surface, {32, 32}); + }); + setCursorShapeSpy.wait(); + // verify we got given a cursor on enter + QCOMPOSITOR_COMPARE(cursorShape()->m_currentShape, CursorShapeDevice::shape_default); + QVERIFY(setCursorSpy.isEmpty()); + QCOMPARE(setCursorShapeSpy.takeFirst().at(0).toUInt(), enterSerial); + + // client sets a different shape + window.setCursor(QCursor(Qt::WaitCursor)); + QVERIFY(setCursorShapeSpy.wait()); + QCOMPOSITOR_COMPARE(cursorShape()->m_currentShape, CursorShapeDevice::shape_wait); + + setCursorShapeSpy.clear(); + + // client hides the cursor + // CursorShape will not be used, instead, it uses the old path + window.setCursor(QCursor(Qt::BlankCursor)); + QVERIFY(setCursorSpy.wait()); + QVERIFY(setCursorShapeSpy.isEmpty()); + QCOMPOSITOR_VERIFY(!pointer()->cursorSurface()); + + // same for bitmaps + QPixmap myCustomPixmap(10, 10); + myCustomPixmap.fill(Qt::red); + window.setCursor(QCursor(myCustomPixmap)); + QVERIFY(setCursorSpy.wait()); + QVERIFY(setCursorShapeSpy.isEmpty()); + + // set a shape again + window.setCursor(QCursor(Qt::BusyCursor)); + QVERIFY(setCursorShapeSpy.wait()); + QCOMPOSITOR_COMPARE(cursorShape()->m_currentShape, CursorShapeDevice::shape_progress); + + setCursorShapeSpy.clear(); + + // set the same bitmap again, make sure switching from new to old path works + // even if the bitmap cursor's properties haven't changed + window.setCursor(QCursor(myCustomPixmap)); + QVERIFY(setCursorSpy.wait()); + QVERIFY(setCursorShapeSpy.isEmpty()); +} + +QCOMPOSITOR_TEST_MAIN(tst_cursor) +#include "tst_cursor.moc" diff --git a/tests/auto/client/datadevicev1/CMakeLists.txt b/tests/auto/client/datadevicev1/CMakeLists.txt new file mode 100644 index 000000000..cfc2f5beb --- /dev/null +++ b/tests/auto/client/datadevicev1/CMakeLists.txt @@ -0,0 +1,15 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +# Generated from datadevicev1.pro. + +##################################################################### +## tst_datadevicev1 Test: +##################################################################### + +qt_internal_add_test(tst_datadevicev1 + SOURCES + tst_datadevicev1.cpp + LIBRARIES + SharedClientTest +) diff --git a/tests/auto/client/datadevicev1/datadevicev1.pro b/tests/auto/client/datadevicev1/datadevicev1.pro deleted file mode 100644 index b3c687c4d..000000000 --- a/tests/auto/client/datadevicev1/datadevicev1.pro +++ /dev/null @@ -1,4 +0,0 @@ -include (../shared/shared.pri) - -TARGET = tst_datadevicev1 -SOURCES += tst_datadevicev1.cpp diff --git a/tests/auto/client/datadevicev1/tst_datadevicev1.cpp b/tests/auto/client/datadevicev1/tst_datadevicev1.cpp index 1568b3b96..50d78130a 100644 --- a/tests/auto/client/datadevicev1/tst_datadevicev1.cpp +++ b/tests/auto/client/datadevicev1/tst_datadevicev1.cpp @@ -1,41 +1,15 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "mockcompositor.h" #include <QtGui/QRasterWindow> -#include <QtGui/QOpenGLWindow> #include <QtGui/QClipboard> #include <QtGui/QDrag> using namespace MockCompositor; -constexpr int dataDeviceVersion = 1; +constexpr int dataDeviceVersion = 3; class DataDeviceCompositor : public DefaultCompositor { public: @@ -57,6 +31,8 @@ private slots: void initTestCase(); void pasteAscii(); void pasteUtf8(); + void pasteMozUrl(); + void pasteSingleUtf8MozUrl(); void destroysPreviousSelection(); void destroysSelectionWithSurface(); void destroysSelectionOnLeave(); @@ -66,9 +42,6 @@ private slots: void tst_datadevicev1::initTestCase() { QCOMPOSITOR_TRY_VERIFY(pointer()); - QCOMPOSITOR_TRY_VERIFY(!pointer()->resourceMap().empty()); - QCOMPOSITOR_TRY_COMPARE(pointer()->resourceMap().first()->version(), 5); - QCOMPOSITOR_TRY_VERIFY(keyboard()); QCOMPOSITOR_TRY_VERIFY(dataDevice()); @@ -92,13 +65,13 @@ void tst_datadevicev1::pasteAscii() exec([&] { auto *client = xdgSurface()->resource()->client(); auto *offer = dataDevice()->sendDataOffer(client, {"text/plain"}); - connect(offer, &DataOffer::receive, [](QString mimeType, int fd) { + connect(offer, &DataOffer::receive, offer, [](QString mimeType, int fd) { QFile file; file.open(fd, QIODevice::WriteOnly, QFile::FileHandleFlag::AutoCloseHandle); QCOMPARE(mimeType, "text/plain"); file.write(QByteArray("normal ascii")); file.close(); - }); + }, Qt::DirectConnection); dataDevice()->sendSelection(offer); auto *surface = xdgSurface()->m_surface; @@ -130,13 +103,13 @@ void tst_datadevicev1::pasteUtf8() exec([&] { auto *client = xdgSurface()->resource()->client(); auto *offer = dataDevice()->sendDataOffer(client, {"text/plain", "text/plain;charset=utf-8"}); - connect(offer, &DataOffer::receive, [](QString mimeType, int fd) { + connect(offer, &DataOffer::receive, offer, [](QString mimeType, int fd) { QFile file; file.open(fd, QIODevice::WriteOnly, QFile::FileHandleFlag::AutoCloseHandle); QCOMPARE(mimeType, "text/plain;charset=utf-8"); file.write(QByteArray("face with tears of joy: 😂")); file.close(); - }); + }, Qt::DirectConnection); dataDevice()->sendSelection(offer); auto *surface = xdgSurface()->m_surface; @@ -152,6 +125,90 @@ void tst_datadevicev1::pasteUtf8() QTRY_COMPARE(window.m_text, "face with tears of joy: 😂"); } +void tst_datadevicev1::pasteMozUrl() +{ + class Window : public QRasterWindow { + public: + void mousePressEvent(QMouseEvent *) override { m_urls = QGuiApplication::clipboard()->mimeData()->urls(); } + QList<QUrl> m_urls; + }; + + Window window; + window.resize(64, 64); + window.show(); + + QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial); + exec([&] { + auto *client = xdgSurface()->resource()->client(); + auto *offer = dataDevice()->sendDataOffer(client, {"text/x-moz-url"}); + connect(offer, &DataOffer::receive, offer, [](QString mimeType, int fd) { + QFile file; + file.open(fd, QIODevice::WriteOnly, QFile::FileHandleFlag::AutoCloseHandle); + QCOMPARE(mimeType, "text/x-moz-url"); + const QString content("https://www.qt.io/\nQt\nhttps://www.example.com/\nExample Website"); + // Need UTF-16. + file.write(reinterpret_cast<const char *>(content.data()), content.size() * 2); + file.close(); + }, Qt::DirectConnection); + dataDevice()->sendSelection(offer); + + auto *surface = xdgSurface()->m_surface; + keyboard()->sendEnter(surface); // Need to set keyboard focus according to protocol + + pointer()->sendEnter(surface, {32, 32}); + pointer()->sendFrame(client); + pointer()->sendButton(client, BTN_LEFT, 1); + pointer()->sendFrame(client); + pointer()->sendButton(client, BTN_LEFT, 0); + pointer()->sendFrame(client); + }); + + QTRY_COMPARE(window.m_urls.count(), 2); + QCOMPARE(window.m_urls.at(0), QUrl("https://www.qt.io/")); + QCOMPARE(window.m_urls.at(1), QUrl("https://www.example.com/")); +} + +void tst_datadevicev1::pasteSingleUtf8MozUrl() +{ + class Window : public QRasterWindow { + public: + void mousePressEvent(QMouseEvent *) override { m_urls = QGuiApplication::clipboard()->mimeData()->urls(); } + QList<QUrl> m_urls; + }; + + Window window; + window.resize(64, 64); + window.show(); + + QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial); + exec([&] { + auto *client = xdgSurface()->resource()->client(); + auto *offer = dataDevice()->sendDataOffer(client, {"text/x-moz-url"}); + connect(offer, &DataOffer::receive, offer, [](QString mimeType, int fd) { + QFile file; + file.open(fd, QIODevice::WriteOnly, QFile::FileHandleFlag::AutoCloseHandle); + QCOMPARE(mimeType, "text/x-moz-url"); + const QString content("https://www.qt.io/"); + file.write(content.toUtf8()); + file.close(); + }, Qt::DirectConnection); + dataDevice()->sendSelection(offer); + + auto *surface = xdgSurface()->m_surface; + keyboard()->sendEnter(surface); // Need to set keyboard focus according to protocol + + pointer()->sendEnter(surface, {32, 32}); + pointer()->sendFrame(client); + pointer()->sendButton(client, BTN_LEFT, 1); + pointer()->sendFrame(client); + pointer()->sendButton(client, BTN_LEFT, 0); + pointer()->sendFrame(client); + }); + + QTRY_COMPARE(window.m_urls.count(), 1); + QCOMPARE(window.m_urls.at(0), QUrl("https://www.qt.io/")); +} + void tst_datadevicev1::destroysPreviousSelection() { QRasterWindow window; @@ -241,7 +298,7 @@ void tst_datadevicev1::destroysSelectionOnLeave() keyboard()->sendLeave(surface); }); - QTRY_COMPARE(dataChangedSpy.count(), 1); + QTRY_COMPARE(dataChangedSpy.size(), 1); QVERIFY(!QGuiApplication::clipboard()->mimeData(QClipboard::Clipboard)->hasText()); } diff --git a/tests/auto/client/fullscreenshellv1/CMakeLists.txt b/tests/auto/client/fullscreenshellv1/CMakeLists.txt new file mode 100644 index 000000000..7bc14c50d --- /dev/null +++ b/tests/auto/client/fullscreenshellv1/CMakeLists.txt @@ -0,0 +1,15 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +# Generated from fullscreenshellv1.pro. + +##################################################################### +## tst_client_fullscreenshellv1 Test: +##################################################################### + +qt_internal_add_test(tst_client_fullscreenshellv1 + SOURCES + tst_fullscreenshellv1.cpp + LIBRARIES + SharedClientTest +) diff --git a/tests/auto/client/fullscreenshellv1/fullscreenshellv1.pro b/tests/auto/client/fullscreenshellv1/fullscreenshellv1.pro deleted file mode 100644 index c4006cdd8..000000000 --- a/tests/auto/client/fullscreenshellv1/fullscreenshellv1.pro +++ /dev/null @@ -1,4 +0,0 @@ -include (../shared_old/shared_old.pri) - -TARGET = tst_client_fullscreenshellv1 -SOURCES += tst_fullscreenshellv1.cpp diff --git a/tests/auto/client/fullscreenshellv1/tst_fullscreenshellv1.cpp b/tests/auto/client/fullscreenshellv1/tst_fullscreenshellv1.cpp index 55158474c..ba897d53f 100644 --- a/tests/auto/client/fullscreenshellv1/tst_fullscreenshellv1.cpp +++ b/tests/auto/client/fullscreenshellv1/tst_fullscreenshellv1.cpp @@ -1,94 +1,35 @@ -/**************************************************************************** -** -** Copyright (C) 2018 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2021 David Edmundson <davidedmundson@kde.org> +// Copyright (C) 2018 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "mockcompositor.h" -#include <QWindow> +#include <QRasterWindow> #include <QtTest/QtTest> -static const QSize screenSize(1600, 1200); +using namespace MockCompositor; -class TestWindow : public QWindow -{ -public: - TestWindow() - { - setSurfaceType(QSurface::RasterSurface); - setGeometry(0, 0, 800, 600); - create(); - } -}; - -class tst_WaylandClientFullScreenShellV1 : public QObject +class tst_WaylandClientFullScreenShellV1 : public QObject, private DefaultCompositor { Q_OBJECT -public: - tst_WaylandClientFullScreenShellV1(MockCompositor *c) - : m_compositor(c) - { - QSocketNotifier *notifier = new QSocketNotifier(m_compositor->waylandFileDescriptor(), QSocketNotifier::Read, this); - connect(notifier, &QSocketNotifier::activated, this, &tst_WaylandClientFullScreenShellV1::processWaylandEvents); - // connect to the event dispatcher to make sure to flush out the outgoing message queue - connect(QCoreApplication::eventDispatcher(), &QAbstractEventDispatcher::awake, this, &tst_WaylandClientFullScreenShellV1::processWaylandEvents); - connect(QCoreApplication::eventDispatcher(), &QAbstractEventDispatcher::aboutToBlock, this, &tst_WaylandClientFullScreenShellV1::processWaylandEvents); - } - -public slots: - void processWaylandEvents() - { - m_compositor->processWaylandEvents(); - } - - void cleanup() - { - // make sure the surfaces from the last test are properly cleaned up - // and don't show up as false positives in the next test - QTRY_VERIFY(!m_compositor->fullScreenShellV1Surface()); - } private slots: void createDestroyWindow(); - -private: - MockCompositor *m_compositor = nullptr; }; void tst_WaylandClientFullScreenShellV1::createDestroyWindow() { - TestWindow window; + QRasterWindow window; + window.resize(800, 600); window.show(); - QTRY_VERIFY(m_compositor->fullScreenShellV1Surface()); + QCOMPOSITOR_TRY_VERIFY(fullScreenShellV1()->surfaces().size() == 1); + QCOMPOSITOR_VERIFY(surface(0)); window.destroy(); - QTRY_VERIFY(!m_compositor->fullScreenShellV1Surface()); + QCOMPOSITOR_TRY_VERIFY(!surface(0)); } int main(int argc, char **argv) @@ -99,13 +40,9 @@ int main(int argc, char **argv) setenv("QT_WAYLAND_SHELL_INTEGRATION", "fullscreen-shell-v1", 1); setenv("QT_WAYLAND_DISABLE_WINDOWDECORATION", "1", 1); // window decorations don't make much sense here - MockCompositor compositor; - compositor.setOutputMode(screenSize); - + tst_WaylandClientFullScreenShellV1 tc; QGuiApplication app(argc, argv); - compositor.applicationInitialized(); - - tst_WaylandClientFullScreenShellV1 tc(&compositor); + QTEST_SET_MAIN_SOURCE_PATH return QTest::qExec(&tc, argc, argv); } diff --git a/tests/auto/client/inputcontext/CMakeLists.txt b/tests/auto/client/inputcontext/CMakeLists.txt new file mode 100644 index 000000000..66e5ca825 --- /dev/null +++ b/tests/auto/client/inputcontext/CMakeLists.txt @@ -0,0 +1,15 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +# Generated from inputcontext.pro. + +##################################################################### +## tst_inputcontext Test: +##################################################################### + +qt_internal_add_test(tst_inputcontext + SOURCES + tst_inputcontext.cpp + LIBRARIES + SharedClientTest +) diff --git a/tests/auto/client/inputcontext/inputcontext.pro b/tests/auto/client/inputcontext/inputcontext.pro deleted file mode 100644 index 1971d455e..000000000 --- a/tests/auto/client/inputcontext/inputcontext.pro +++ /dev/null @@ -1,4 +0,0 @@ -include (../shared/shared.pri) - -TARGET = tst_inputcontext -SOURCES += tst_inputcontext.cpp diff --git a/tests/auto/client/inputcontext/tst_inputcontext.cpp b/tests/auto/client/inputcontext/tst_inputcontext.cpp index 1f07eb520..47a453bb5 100644 --- a/tests/auto/client/inputcontext/tst_inputcontext.cpp +++ b/tests/auto/client/inputcontext/tst_inputcontext.cpp @@ -1,33 +1,9 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2019 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "mockcompositor.h" #include "textinput.h" +#include "qttextinput.h" #include <QtCore/QString> #include <QtCore/QByteArray> @@ -48,16 +24,41 @@ private slots: void initTestCase(); void selectingInputContext_data(); void selectingInputContext(); + void selectingTextInputProtocol_data(); + void selectingTextInputProtocol(); void inputContextReconfigurationWhenTogglingTextInputExtension(); private: QByteArray inputContextName() const; - void ensureTextInputPresentOnCompositor(); - void ensureTextInputNotPresentOnCompositor(); + + template<typename arg_type> + void ensurePresentOnCompositor() + { + exec([&] { + QList<arg_type *> extensions = getAll<arg_type>(); + if (extensions.size() > 1) + QFAIL("Requested type is a singleton, hence there should not be more then one object returned"); + if (extensions.size() == 0) + add<arg_type>(); + }); + } + + template<typename arg_type> + void ensureNotPresentOnCompositor() + { + exec([&] { + QList<arg_type *> extensions = getAll<arg_type>(); + if (extensions.size() > 1) + QFAIL("Requested type is a singleton, hence there should not be more then one object returned"); + if (extensions.size() == 1) + remove(extensions.first()); + }); + } QByteArray mComposeModule = QByteArray("QComposeInputContext"); // default input context QByteArray mIbusModule = QByteArray("QIBusPlatformInputContext"); - QByteArray mWaylandModule = QByteArray("QtWaylandClient::QWaylandInputContext"); + QByteArray mTextInputModule = QByteArray("QtWaylandClient::QWaylandInputContext"); + QByteArray mQtTextInputModule = QByteArray("QtWaylandClient::QWaylandInputMethodContext"); }; void tst_inputcontext::initTestCase() @@ -82,28 +83,6 @@ QByteArray tst_inputcontext::inputContextName() const return QByteArray(""); } -void tst_inputcontext::ensureTextInputPresentOnCompositor() -{ - exec([&] { - QVector<TextInputManager *> extensions = getAll<TextInputManager>(); - if (extensions.length() > 1) - QFAIL("TextInputManager is a singleton, hence there should not be more then one object returned"); - if (extensions.length() == 0) - add<TextInputManager>(); - }); -} - -void tst_inputcontext::ensureTextInputNotPresentOnCompositor() -{ - exec([&] { - QVector<TextInputManager *> extensions = getAll<TextInputManager>(); - if (extensions.length() > 1) - QFAIL("TextInputManager is a singleton, hence there should not be more then one object returned"); - if (extensions.length() == 1) - remove(extensions.first()); - }); -} - void tst_inputcontext::selectingInputContext_data() { QTest::addColumn<QByteArray>("requestedModule"); @@ -119,8 +98,9 @@ void tst_inputcontext::selectingInputContext_data() // Test compositor with Text Input extension QTest::newRow("ibus:text-input") << QByteArray("ibus") << mIbusModule; QTest::newRow("compose:text-input") << QByteArray("compose") << mComposeModule; - QTest::newRow("empty:text-input") << QByteArray("") << mComposeModule; - QTest::newRow("null:text-input") << QByteArray() << mWaylandModule; + QTest::newRow("empty:text-input") << QByteArray("") << mTextInputModule; + QTest::newRow("null:text-input") << QByteArray() << mTextInputModule; + QTest::newRow("wayland:text-input") << QByteArray("wayland") << mTextInputModule; QTest::newRow("fake:text-input") << QByteArray("fake") << mComposeModule; } @@ -137,9 +117,76 @@ void tst_inputcontext::selectingInputContext() const bool withTextInputAtCompositorSide = QByteArray(QTest::currentDataTag()).endsWith(":text-input"); if (withTextInputAtCompositorSide) - ensureTextInputPresentOnCompositor(); + ensurePresentOnCompositor<TextInputManager>(); + else + ensureNotPresentOnCompositor<TextInputManager>(); + + int argc = 0; + QGuiApplication app(argc, nullptr); // loads the platform plugin + + QCOMPARE(inputContextName(), expectedModule); +} + +void tst_inputcontext::selectingTextInputProtocol_data() +{ + QTest::addColumn<bool>("requestQtTextInput"); + QTest::addColumn<bool>("requestTextInput"); + QTest::addColumn<QByteArray>("clientProtocol"); + QTest::addColumn<QByteArray>("expectedModule"); + + QTest::newRow("1-1") << true << true << QByteArray() << mQtTextInputModule; + QTest::newRow("1-2") << true << false << QByteArray() << mQtTextInputModule; + QTest::newRow("1-3") << false << true << QByteArray() << mTextInputModule; + QTest::newRow("1-4") << false << false << QByteArray() << mComposeModule; + + QTest::newRow("2-1") << true << true << QByteArray("zwp_text_input_v2") << mTextInputModule; + QTest::newRow("2-2") << true << false << QByteArray("zwp_text_input_v2") << mComposeModule; + QTest::newRow("2-3") << false << true << QByteArray("zwp_text_input_v2") << mTextInputModule; + QTest::newRow("2-4") << false << false << QByteArray("zwp_text_input_v2") << mComposeModule; + + QTest::newRow("3-1") << true << true << QByteArray("qt_text_input_method_v1") << mQtTextInputModule; + QTest::newRow("3-2") << true << false << QByteArray("qt_text_input_method_v1") << mQtTextInputModule; + QTest::newRow("3-3") << false << true << QByteArray("qt_text_input_method_v1") << mComposeModule; + QTest::newRow("3-4") << false << false << QByteArray("qt_text_input_method_v1") << mComposeModule; + + QTest::newRow("4-1") << true << true << QByteArray("qt_text_input_method_v1;zwp_text_input_v2") << mQtTextInputModule; + QTest::newRow("4-2") << true << false << QByteArray("qt_text_input_method_v1;zwp_text_input_v2") << mQtTextInputModule; + QTest::newRow("4-3") << false << true << QByteArray("qt_text_input_method_v1;zwp_text_input_v2") << mTextInputModule; + QTest::newRow("4-4") << false << false << QByteArray("qt_text_input_method_v1;zwp_text_input_v2") << mComposeModule; + + QTest::newRow("5-1") << true << true << QByteArray("zwp_text_input_v2;qt_text_input_method_v1") << mTextInputModule; + QTest::newRow("5-2") << true << false << QByteArray("zwp_text_input_v2;qt_text_input_method_v1") << mQtTextInputModule; + QTest::newRow("5-3") << false << true << QByteArray("zwp_text_input_v2;qt_text_input_method_v1") << mTextInputModule; + QTest::newRow("5-4") << false << false << QByteArray("zwp_text_input_v2;qt_text_input_method_v1") << mComposeModule; +} + +void tst_inputcontext::selectingTextInputProtocol() +{ + QFETCH(bool, requestQtTextInput); + QFETCH(bool, requestTextInput); + QFETCH(QByteArray, clientProtocol); + QFETCH(QByteArray, expectedModule); + + exec([] { + qputenv("QT_IM_MODULE", "qtvirtualkeyboard"); + }); + + qunsetenv("QT_IM_MODULE"); + + if (clientProtocol.isNull()) + qunsetenv("QT_WAYLAND_TEXT_INPUT_PROTOCOL"); + else + qputenv("QT_WAYLAND_TEXT_INPUT_PROTOCOL", clientProtocol); + + if (requestTextInput) + ensurePresentOnCompositor<TextInputManager>(); + else + ensureNotPresentOnCompositor<TextInputManager>(); + + if (requestQtTextInput) + ensurePresentOnCompositor<QtTextInputManager>(); else - ensureTextInputNotPresentOnCompositor(); + ensureNotPresentOnCompositor<QtTextInputManager>(); int argc = 0; QGuiApplication app(argc, nullptr); // loads the platform plugin @@ -151,22 +198,22 @@ void tst_inputcontext::inputContextReconfigurationWhenTogglingTextInputExtension { qunsetenv("QT_IM_MODULE"); - ensureTextInputPresentOnCompositor(); + ensurePresentOnCompositor<TextInputManager>(); int argc = 0; QGuiApplication app(argc, nullptr); // loads the platform plugin - QCOMPARE(inputContextName(), mWaylandModule); + QCOMPARE(inputContextName(), mTextInputModule); // remove text input extension after the platform plugin has been loaded - ensureTextInputNotPresentOnCompositor(); + ensureNotPresentOnCompositor<TextInputManager>(); // QTRY_* because we need to spin the event loop for wayland QPA plugin // to handle registry_global_remove() QTRY_COMPARE(inputContextName(), mComposeModule); // add text input extension after the platform plugin has been loaded - ensureTextInputPresentOnCompositor(); + ensurePresentOnCompositor<TextInputManager>(); // QTRY_* because we need to spin the event loop for wayland QPA plugin // to handle registry_global() - QTRY_COMPARE(inputContextName(), mWaylandModule); + QTRY_COMPARE(inputContextName(), mTextInputModule); } int main(int argc, char *argv[]) diff --git a/tests/auto/client/iviapplication/CMakeLists.txt b/tests/auto/client/iviapplication/CMakeLists.txt new file mode 100644 index 000000000..a138d3429 --- /dev/null +++ b/tests/auto/client/iviapplication/CMakeLists.txt @@ -0,0 +1,15 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +# Generated from iviapplication.pro. + +##################################################################### +## tst_client_iviapplication Test: +##################################################################### + +qt_internal_add_test(tst_client_iviapplication + SOURCES + tst_iviapplication.cpp + LIBRARIES + SharedClientTest +) diff --git a/tests/auto/client/iviapplication/iviapplication.pro b/tests/auto/client/iviapplication/iviapplication.pro deleted file mode 100644 index f2d596e6c..000000000 --- a/tests/auto/client/iviapplication/iviapplication.pro +++ /dev/null @@ -1,5 +0,0 @@ -include (../shared_old/shared_old.pri) - -TARGET = tst_client_iviapplication -SOURCES += tst_iviapplication.cpp - diff --git a/tests/auto/client/iviapplication/tst_iviapplication.cpp b/tests/auto/client/iviapplication/tst_iviapplication.cpp index 8d6ea6484..082149f36 100644 --- a/tests/auto/client/iviapplication/tst_iviapplication.cpp +++ b/tests/auto/client/iviapplication/tst_iviapplication.cpp @@ -1,125 +1,70 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "mockcompositor.h" -#include <QWindow> +#include <QRasterWindow> #include <QtTest/QtTest> -static const QSize screenSize(1600, 1200); +using namespace MockCompositor; -class TestWindow : public QWindow -{ -public: - TestWindow() - { - setSurfaceType(QSurface::RasterSurface); - setGeometry(0, 0, 32, 32); - create(); - } -}; - -class tst_WaylandClientIviApplication : public QObject +class tst_WaylandClientIviApplication : public QObject, private DefaultCompositor { Q_OBJECT -public: - tst_WaylandClientIviApplication(MockCompositor *c) - : m_compositor(c) - { - QSocketNotifier *notifier = new QSocketNotifier(m_compositor->waylandFileDescriptor(), QSocketNotifier::Read, this); - connect(notifier, &QSocketNotifier::activated, this, &tst_WaylandClientIviApplication::processWaylandEvents); - // connect to the event dispatcher to make sure to flush out the outgoing message queue - connect(QCoreApplication::eventDispatcher(), &QAbstractEventDispatcher::awake, this, &tst_WaylandClientIviApplication::processWaylandEvents); - connect(QCoreApplication::eventDispatcher(), &QAbstractEventDispatcher::aboutToBlock, this, &tst_WaylandClientIviApplication::processWaylandEvents); - } - -public slots: - void processWaylandEvents() - { - m_compositor->processWaylandEvents(); - } - - void cleanup() - { - // make sure the surfaces from the last test are properly cleaned up - // and don't show up as false positives in the next test - QTRY_VERIFY(!m_compositor->surface()); - QTRY_VERIFY(!m_compositor->iviSurface()); - } private slots: void createDestroyWindow(); void configure(); void uniqueIviIds(); - -private: - MockCompositor *m_compositor = nullptr; }; void tst_WaylandClientIviApplication::createDestroyWindow() { - TestWindow window; + QRasterWindow window; + window.resize(32, 32); window.show(); - QTRY_VERIFY(m_compositor->surface()); - QTRY_VERIFY(m_compositor->iviSurface()); + QCOMPOSITOR_TRY_VERIFY(surface()); + QCOMPOSITOR_TRY_VERIFY(iviSurface()); window.destroy(); - QTRY_VERIFY(!m_compositor->surface()); - QTRY_VERIFY(!m_compositor->iviSurface()); + QCOMPOSITOR_TRY_VERIFY(!surface()); + QCOMPOSITOR_TRY_VERIFY(!iviSurface()); } void tst_WaylandClientIviApplication::configure() { - TestWindow window; + QRasterWindow window; + window.resize(32, 32); window.show(); - QSharedPointer<MockIviSurface> iviSurface; - QTRY_VERIFY(iviSurface = m_compositor->iviSurface()); + QCOMPOSITOR_TRY_VERIFY(iviSurface()); // Unconfigured ivi surfaces decide their own size QTRY_COMPARE(window.frameGeometry(), QRect(QPoint(), QSize(32, 32))); - m_compositor->sendIviSurfaceConfigure(iviSurface, {123, 456}); + exec([&] { + iviSurface()->send_configure(123, 456); + }); QTRY_COMPARE(window.frameGeometry(), QRect(QPoint(), QSize(123, 456))); + window.destroy(); + QCOMPOSITOR_TRY_VERIFY(!iviSurface()); } void tst_WaylandClientIviApplication::uniqueIviIds() { - TestWindow windowA, windowB; + QRasterWindow windowA, windowB; + windowA.resize(32, 32); windowA.show(); + windowB.resize(32, 32); windowB.show(); - QSharedPointer<MockIviSurface> iviSurface0, iviSurface1; - QTRY_VERIFY(iviSurface0 = m_compositor->iviSurface(0)); - QTRY_VERIFY(iviSurface1 = m_compositor->iviSurface(1)); - QTRY_VERIFY(iviSurface0->iviId != iviSurface1->iviId); + QCOMPOSITOR_TRY_VERIFY(iviSurface(0)); + QCOMPOSITOR_TRY_VERIFY(iviSurface(1)); + exec([&] { + QVERIFY(iviSurface(0)->m_iviId != iviSurface(1)->m_iviId); + }); } int main(int argc, char **argv) @@ -130,13 +75,9 @@ int main(int argc, char **argv) setenv("QT_WAYLAND_SHELL_INTEGRATION", "ivi-shell", 1); setenv("QT_WAYLAND_DISABLE_WINDOWDECORATION", "1", 1); // window decorations don't make much sense on ivi-application - MockCompositor compositor; - compositor.setOutputMode(screenSize); - + tst_WaylandClientIviApplication tc; QGuiApplication app(argc, argv); - compositor.applicationInitialized(); - - tst_WaylandClientIviApplication tc(&compositor); + QTEST_SET_MAIN_SOURCE_PATH return QTest::qExec(&tc, argc, argv); } diff --git a/tests/auto/client/multithreaded/CMakeLists.txt b/tests/auto/client/multithreaded/CMakeLists.txt new file mode 100644 index 000000000..62d935905 --- /dev/null +++ b/tests/auto/client/multithreaded/CMakeLists.txt @@ -0,0 +1,15 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +# Generated from multithreaded.pro. + +##################################################################### +## tst_multithreaded Test: +##################################################################### + +qt_internal_add_test(tst_multithreaded + SOURCES + tst_multithreaded.cpp + LIBRARIES + SharedClientTest +) diff --git a/tests/auto/client/multithreaded/tst_multithreaded.cpp b/tests/auto/client/multithreaded/tst_multithreaded.cpp new file mode 100644 index 000000000..a1a7d367e --- /dev/null +++ b/tests/auto/client/multithreaded/tst_multithreaded.cpp @@ -0,0 +1,140 @@ +// Copyright (C) 2018 The Qt Company Ltd. +// Copyright (C) 2020 UBports Foundataion. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include <unistd.h> +#include <poll.h> + +#include <wayland-client-core.h> + +#include <QtGui/QScreen> +#include <QAbstractEventDispatcher> +#include <qpa/qplatformnativeinterface.h> + +#include "mockcompositor.h" + +using namespace MockCompositor; + +/* + * This class simulate a thread from another library which use poll() to wait + * for data from Wayland compositor. + */ + +class ExternalWaylandReaderThread : public QThread +{ +public: + ExternalWaylandReaderThread(struct wl_display *disp) + : QThread() + , m_disp(disp) + { + setObjectName(QStringLiteral("ExternalWaylandReader")); + } + + ~ExternalWaylandReaderThread() + { + if (m_pipefd[1] != -1 && write(m_pipefd[1], "q", 1) == -1) + qWarning("Failed to write to the pipe: %s.", strerror(errno)); + + wait(); + } + +protected: + void run() override + { + // we use this pipe to make the loop exit otherwise if we simply used a flag on the loop condition, if stop() gets + // called while poll() is blocking the thread will never quit since there are no wayland messages coming anymore. + struct Pipe + { + Pipe(int *fds) + : fds(fds) + { + if (::pipe(fds) != 0) + qWarning("Pipe creation failed. Quitting may hang."); + } + ~Pipe() + { + if (fds[0] != -1) { + close(fds[0]); + close(fds[1]); + } + } + + int *fds; + } pipe(m_pipefd); + + struct wl_event_queue *a_queue = wl_display_create_queue(m_disp); + struct pollfd fds[2] = { { wl_display_get_fd(m_disp), POLLIN, 0 }, + { m_pipefd[0], POLLIN, 0 } }; + + while (true) { + // No wl_proxy is assigned to this queue, thus guaranteed to be always empty. + Q_ASSERT(wl_display_prepare_read_queue(m_disp, a_queue) == 0); + wl_display_flush(m_disp); + + // Wakeup every 10 seconds so that if Qt blocks in _read_events(), + // it won't last forever. + poll(fds, /* nfds */ 2, 10000); + + if (fds[0].revents & POLLIN) { + wl_display_read_events(m_disp); + } else { + wl_display_cancel_read(m_disp); + } + + if (fds[1].revents & POLLIN) { + char pipeIn; + read(m_pipefd[0], &pipeIn, 1); + if (pipeIn == 'q') + break; + } + } + + wl_event_queue_destroy(a_queue); + } + +private: + struct wl_display *m_disp; + int m_pipefd[2] = { -1, -1 }; +}; + +class tst_multithreaded : public QObject, private DefaultCompositor +{ + Q_OBJECT +private slots: + void initTestCase() + { + m_config.autoConfigure = true; + m_config.autoEnter = false; + } + void init() + { + // a test case is given new simulated thread. + QPlatformNativeInterface *native = QGuiApplication::platformNativeInterface(); + struct wl_display *wl_dpy = + (struct wl_display *)native->nativeResourceForWindow("display", NULL); + + m_extThread.reset(new ExternalWaylandReaderThread(wl_dpy)); + m_extThread->start(); + } + void cleanup() + { + QTRY_VERIFY2(isClean(), qPrintable(dirtyMessage())); + } + + void mainThreadIsNotBlocked(); + +public: + QScopedPointer<ExternalWaylandReaderThread> m_extThread; +}; + +void tst_multithreaded::mainThreadIsNotBlocked() +{ + QElapsedTimer timer; + timer.start(); + + QTest::qWait(100); + QVERIFY(timer.elapsed() < 200); +} + +QCOMPOSITOR_TEST_MAIN(tst_multithreaded) +#include "tst_multithreaded.moc" diff --git a/tests/auto/client/nooutput/CMakeLists.txt b/tests/auto/client/nooutput/CMakeLists.txt new file mode 100644 index 000000000..eeee57909 --- /dev/null +++ b/tests/auto/client/nooutput/CMakeLists.txt @@ -0,0 +1,15 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +# Generated from nooutput.pro. + +##################################################################### +## tst_nooutput Test: +##################################################################### + +qt_internal_add_test(tst_nooutput + SOURCES + tst_nooutput.cpp + LIBRARIES + SharedClientTest +) diff --git a/tests/auto/client/nooutput/tst_nooutput.cpp b/tests/auto/client/nooutput/tst_nooutput.cpp new file mode 100644 index 000000000..1d8a838f3 --- /dev/null +++ b/tests/auto/client/nooutput/tst_nooutput.cpp @@ -0,0 +1,53 @@ +// Copyright (C) 2019 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "mockcompositor.h" +#include <QtGui/QScreen> +#include <QtGui/QRasterWindow> + +using namespace MockCompositor; + +class NoOutputCompositor : public DefaultCompositor { +public: + NoOutputCompositor() + { + exec([this] { removeAll<Output>(); }); + m_config.autoConfigure = false; + } +}; + +class tst_nooutput : public QObject, private NoOutputCompositor +{ + Q_OBJECT +private slots: + void cleanup() + { + // There should be no wl_outputs in this test + QCOMPOSITOR_COMPARE(getAll<Output>().size(), 0); + QTRY_VERIFY2(isClean(), qPrintable(dirtyMessage())); + } + void noScreens(); +}; + +void tst_nooutput::noScreens() +{ + QRasterWindow window; + window.resize(16, 16); + window.show(); + + QCOMPOSITOR_TRY_VERIFY(xdgToplevel()); + + QTRY_VERIFY(window.isVisible()); + // The window should not be exposed before the first xdg_surface configure event + QTRY_VERIFY(!window.isExposed()); + + exec([&] { + xdgToplevel()->sendConfigure({0, 0}, {}); // Let the window decide the size + xdgSurface()->sendConfigure(nextSerial()); + }); + + QTRY_VERIFY(window.isExposed()); +} + +QCOMPOSITOR_TEST_MAIN(tst_nooutput) +#include "tst_nooutput.moc" diff --git a/tests/auto/client/output/CMakeLists.txt b/tests/auto/client/output/CMakeLists.txt new file mode 100644 index 000000000..a9c5cea3c --- /dev/null +++ b/tests/auto/client/output/CMakeLists.txt @@ -0,0 +1,15 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +# Generated from output.pro. + +##################################################################### +## tst_output Test: +##################################################################### + +qt_internal_add_test(tst_output + SOURCES + tst_output.cpp + LIBRARIES + SharedClientTest +) diff --git a/tests/auto/client/output/output.pro b/tests/auto/client/output/output.pro deleted file mode 100644 index d1dc672f0..000000000 --- a/tests/auto/client/output/output.pro +++ /dev/null @@ -1,5 +0,0 @@ -include (../shared/shared.pri) - -TARGET = tst_output -SOURCES += tst_output.cpp - diff --git a/tests/auto/client/output/tst_output.cpp b/tests/auto/client/output/tst_output.cpp index 29c773cf6..2129e167b 100644 --- a/tests/auto/client/output/tst_output.cpp +++ b/tests/auto/client/output/tst_output.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2019 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "mockcompositor.h" #include <QtGui/QScreen> @@ -53,6 +28,7 @@ private slots: void windowScreens(); void removePrimaryScreen(); void screenOrder(); + void removeAllScreens(); }; void tst_output::primaryScreen() @@ -72,7 +48,7 @@ void tst_output::primaryScreen() void tst_output::secondaryHiDpiScreen() { - exec([=] { + exec([&] { OutputData d; d.position = {1920, 0}; // in global compositor space (not pixels) d.mode.resolution = {800, 640}; @@ -98,15 +74,15 @@ void tst_output::secondaryHiDpiScreen() QCOMPARE(screen->geometry(), QRect(QPoint(1920, 0), QSize(400, 320))); QCOMPARE(screen->virtualGeometry(), QRect(QPoint(0, 0), QSize(1920 + 800 / 2, 1080))); - exec([=] { remove(output(1)); }); + exec([&] { remove(output(1)); }); } // QTBUG-62044 void tst_output::addScreenWithGeometryChange() { - const QPoint initialPosition = exec([=] { return output(0)->m_data.position; }); + const QPoint initialPosition = exec([&] { return output(0)->m_data.position; }); - exec([=] { + exec([&] { auto *oldOutput = output(0); auto *newOutput = add<Output>(); newOutput->m_data.mode.resolution = {1280, 720}; @@ -122,7 +98,7 @@ void tst_output::addScreenWithGeometryChange() QTRY_COMPARE(QGuiApplication::primaryScreen()->geometry(), QRect(QPoint(1280, 0), QSize(1920, 1080))); // Remove the extra output and move the old one back - exec([=] { + exec([&] { remove(output(1)); output()->m_data.position = initialPosition; output()->sendGeometry(); @@ -143,7 +119,7 @@ void tst_output::windowScreens() QScreen *primaryScreen = QGuiApplication::screens().first(); QCOMPARE(window.screen(), primaryScreen); - exec([=] { add<Output>(); }); + exec([&] { add<Output>(); }); QTRY_COMPARE(QGuiApplication::screens().size(), 2); QScreen *secondaryScreen = QGuiApplication::screens().at(1); @@ -152,19 +128,19 @@ void tst_output::windowScreens() window.setScreen(secondaryScreen); QCOMPARE(window.screen(), secondaryScreen); - exec([=] { + exec([&] { xdgToplevel()->surface()->sendEnter(output(0)); xdgToplevel()->surface()->sendEnter(output(1)); }); QTRY_COMPARE(window.screen(), primaryScreen); - exec([=] { + exec([&] { xdgToplevel()->surface()->sendLeave(output(0)); }); QTRY_COMPARE(window.screen(), secondaryScreen); - exec([=] { + exec([&] { remove(output(1)); }); QTRY_COMPARE(QGuiApplication::screens().size(), 1); @@ -210,7 +186,7 @@ void tst_output::removePrimaryScreen() // QTBUG-72828 void tst_output::screenOrder() { - exec([=] { + exec([&] { add<Output>()->m_data.model = "Screen 1"; add<Output>()->m_data.model = "Screen 2"; }); @@ -221,11 +197,53 @@ void tst_output::screenOrder() QCOMPARE(screens[1]->model(), "Screen 1"); QCOMPARE(screens[2]->model(), "Screen 2"); - exec([=] { + exec([&] { remove(output(2)); remove(output(1)); }); } +// This is different from tst_nooutput::noScreens because here we have a screen at platform +// integration initialization, which we then remove. +void tst_output::removeAllScreens() +{ + QRasterWindow window1; + window1.resize(400, 320); + window1.show(); + QCOMPOSITOR_TRY_VERIFY(xdgSurface(0) && xdgSurface(0)->m_committedConfigureSerial); + + const QString wlOutputPrimaryScreenModel = QGuiApplication::primaryScreen()->model(); + + // Get screen info so we can restore it after + auto screenInfo = exec([&] { return output()->m_data; }); + exec([&] { remove(output()); }); + + // Make sure the wl_output is actually removed before we continue + QTRY_VERIFY(!QGuiApplication::primaryScreen() || QGuiApplication::primaryScreen()->model() != wlOutputPrimaryScreenModel); + + // Adding a window while there are no screens should also work + QRasterWindow window2; + window2.resize(400, 320); + window2.show(); + + exec([&] { add<Output>(screenInfo); }); + + // Things should be back to normal + QTRY_VERIFY(QGuiApplication::primaryScreen()); + QTRY_COMPARE(QGuiApplication::primaryScreen()->model(), wlOutputPrimaryScreenModel); + + // Test that we don't leave any fake screens around after we get a wl_output back. + QTRY_COMPARE(QGuiApplication::screens().size(), 1); + + // Qt may choose to recreate/hide windows in response to changing screens, so give the client + // some time to potentially mess up before we verify that the windows are visible. + xdgPingAndWaitForPong(); + + // Windows should be visible after we've reconnected the screen + QCOMPOSITOR_TRY_VERIFY(xdgToplevel(0) && xdgToplevel(0)->m_xdgSurface->m_committedConfigureSerial); + QCOMPOSITOR_TRY_VERIFY(xdgToplevel(1) && xdgToplevel(1)->m_xdgSurface->m_committedConfigureSerial); + +} + QCOMPOSITOR_TEST_MAIN(tst_output) #include "tst_output.moc" diff --git a/tests/auto/client/primaryselectionv1/CMakeLists.txt b/tests/auto/client/primaryselectionv1/CMakeLists.txt new file mode 100644 index 000000000..0235ae33e --- /dev/null +++ b/tests/auto/client/primaryselectionv1/CMakeLists.txt @@ -0,0 +1,15 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +# Generated from primaryselectionv1.pro. + +##################################################################### +## tst_primaryselectionv1 Test: +##################################################################### + +qt_internal_add_test(tst_primaryselectionv1 + SOURCES + tst_primaryselectionv1.cpp + LIBRARIES + SharedClientTest +) diff --git a/tests/auto/client/primaryselectionv1/primaryselectionv1.pro b/tests/auto/client/primaryselectionv1/primaryselectionv1.pro deleted file mode 100644 index 9d00562df..000000000 --- a/tests/auto/client/primaryselectionv1/primaryselectionv1.pro +++ /dev/null @@ -1,7 +0,0 @@ -include (../shared/shared.pri) - -WAYLANDSERVERSOURCES += \ - $$PWD/../../../../src/3rdparty/protocol/wp-primary-selection-unstable-v1.xml - -TARGET = tst_primaryselectionv1 -SOURCES += tst_primaryselectionv1.cpp diff --git a/tests/auto/client/primaryselectionv1/tst_primaryselectionv1.cpp b/tests/auto/client/primaryselectionv1/tst_primaryselectionv1.cpp index ee9fa110e..53a048a35 100644 --- a/tests/auto/client/primaryselectionv1/tst_primaryselectionv1.cpp +++ b/tests/auto/client/primaryselectionv1/tst_primaryselectionv1.cpp @@ -1,37 +1,11 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "mockcompositor.h" #include <qwayland-server-wp-primary-selection-unstable-v1.h> #include <QtGui/QRasterWindow> -#include <QtGui/QOpenGLWindow> #include <QtGui/QClipboard> #include <QtCore/private/qcore_unix_p.h> @@ -140,7 +114,7 @@ public: PrimarySelectionDeviceManagerV1 *m_manager = nullptr; Seat *m_seat = nullptr; - QVector<PrimarySelectionOfferV1 *> m_sentSelectionOffers; + QList<PrimarySelectionOfferV1 *> m_sentSelectionOffers; PrimarySelectionSourceV1 *m_selectionSource = nullptr; uint m_serial = 0; @@ -155,11 +129,6 @@ protected: { wl_resource_destroy(resource->handle); } - void zwp_primary_selection_device_v1_destroy_resource(Resource *resource) override - { - Q_UNUSED(resource); - delete this; - } }; class PrimarySelectionDeviceManagerV1 : public Global, public QtWaylandServer::zwp_primary_selection_device_manager_v1 @@ -170,9 +139,13 @@ public: : QtWaylandServer::zwp_primary_selection_device_manager_v1(compositor->m_display, version) , m_version(version) {} + ~PrimarySelectionDeviceManagerV1() override + { + qDeleteAll(m_devices); + } bool isClean() override { - for (auto *device : qAsConst(m_devices)) { + for (auto *device : std::as_const(m_devices)) { // The client should not leak selection offers, i.e. if this fails, there is a missing // zwp_primary_selection_offer_v1.destroy request if (!device->m_sentSelectionOffers.empty()) @@ -194,7 +167,7 @@ public: int m_version = 1; // TODO: Remove on libwayland upgrade QMap<Seat *, PrimarySelectionDeviceV1 *> m_devices; - QVector<PrimarySelectionSourceV1 *> m_sources; + QList<PrimarySelectionSourceV1 *> m_sources; protected: void zwp_primary_selection_device_manager_v1_destroy(Resource *resource) override { @@ -268,9 +241,6 @@ private slots: void tst_primaryselectionv1::initTestCase() { QCOMPOSITOR_TRY_VERIFY(pointer()); - QCOMPOSITOR_TRY_VERIFY(!pointer()->resourceMap().empty()); - QCOMPOSITOR_TRY_COMPARE(pointer()->resourceMap().first()->version(), 5); - QCOMPOSITOR_TRY_VERIFY(keyboard()); } @@ -290,7 +260,7 @@ void tst_primaryselectionv1::createsPrimaryDevice() void tst_primaryselectionv1::createsPrimaryDeviceForNewSeats() { - exec([=] { add<Seat>(); }); + exec([&] { add<Seat>(); }); QCOMPOSITOR_TRY_VERIFY(primarySelectionDevice(1)); } @@ -320,13 +290,13 @@ void tst_primaryselectionv1::pasteAscii() auto *device = primarySelectionDevice(); auto *offer = device->sendDataOffer({"text/plain"}); - connect(offer, &PrimarySelectionOfferV1::receive, [](QString mimeType, int fd) { + connect(offer, &PrimarySelectionOfferV1::receive, offer, [](QString mimeType, int fd) { QFile file; file.open(fd, QIODevice::WriteOnly, QFile::FileHandleFlag::AutoCloseHandle); QCOMPARE(mimeType, "text/plain"); file.write(QByteArray("normal ascii")); file.close(); - }); + }, Qt::DirectConnection); device->sendSelection(offer); pointer()->sendEnter(surface, {32, 32}); @@ -366,13 +336,13 @@ void tst_primaryselectionv1::pasteUtf8() auto *device = primarySelectionDevice(); auto *offer = device->sendDataOffer({"text/plain", "text/plain;charset=utf-8"}); - connect(offer, &PrimarySelectionOfferV1::receive, [](QString mimeType, int fd) { + connect(offer, &PrimarySelectionOfferV1::receive, offer, [](QString mimeType, int fd) { QFile file; file.open(fd, QIODevice::WriteOnly, QFile::FileHandleFlag::AutoCloseHandle); QCOMPARE(mimeType, "text/plain;charset=utf-8"); file.write(QByteArray("face with tears of joy: 😂")); file.close(); - }); + }, Qt::DirectConnection); device->sendSelection(offer); pointer()->sendEnter(surface, {32, 32}); @@ -437,7 +407,7 @@ void tst_primaryselectionv1::destroysSelectionOnLeave() keyboard()->sendLeave(surface); }); - QTRY_COMPARE(selectionChangedSpy.count(), 1); + QTRY_COMPARE(selectionChangedSpy.size(), 1); QVERIFY(!QGuiApplication::clipboard()->mimeData(QClipboard::Selection)->hasText()); } @@ -459,7 +429,7 @@ void tst_primaryselectionv1::copy() window.show(); QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial); - QVector<uint> mouseSerials; + QList<uint> mouseSerials; exec([&] { auto *surface = xdgSurface()->m_surface; keyboard()->sendEnter(surface); // Need to set keyboard focus according to protocol @@ -494,7 +464,7 @@ void tst_primaryselectionv1::copy() pastedBuf.append(buf, n); } }); - }); + }, Qt::DirectConnection); }); QCOMPOSITOR_TRY_VERIFY(pastedBuf.size()); // this assumes we got everything in one read diff --git a/tests/auto/client/reconnect/CMakeLists.txt b/tests/auto/client/reconnect/CMakeLists.txt new file mode 100644 index 000000000..07d4c7143 --- /dev/null +++ b/tests/auto/client/reconnect/CMakeLists.txt @@ -0,0 +1,11 @@ +##################################################################### +## tst_wl_reconnect Test: +##################################################################### + +qt_internal_add_test(tst_wl_reconnect + SOURCES + wl-socket.c + tst_reconnect.cpp + LIBRARIES + SharedClientTest +) diff --git a/tests/auto/client/reconnect/tst_reconnect.cpp b/tests/auto/client/reconnect/tst_reconnect.cpp new file mode 100644 index 000000000..ff806af6a --- /dev/null +++ b/tests/auto/client/reconnect/tst_reconnect.cpp @@ -0,0 +1,253 @@ +// Copyright (C) 2023 David Edmundson <davidedmundson@kde.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "mockcompositor.h" + +#include <QBackingStore> +#include <QPainter> +#include <QScreen> +#include <QWindow> +#include <QMimeData> +#include <QPixmap> +#include <QDrag> +#include <QWindow> +#if QT_CONFIG(opengl) +#include <QOpenGLWindow> +#endif +#include <QRasterWindow> + +#include <QtTest/QtTest> +#include <QtWaylandClient/private/qwaylandintegration_p.h> +#include <QtGui/private/qguiapplication_p.h> + +#include "wl-socket.h" + +using namespace MockCompositor; + +class TestWindow : public QRasterWindow +{ +public: + TestWindow() + { + } + + void focusInEvent(QFocusEvent *) override + { + ++focusInEventCount; + } + + void focusOutEvent(QFocusEvent *) override + { + ++focusOutEventCount; + } + + void keyPressEvent(QKeyEvent *event) override + { + ++keyPressEventCount; + keyCode = event->nativeScanCode(); + } + + void keyReleaseEvent(QKeyEvent *event) override + { + ++keyReleaseEventCount; + keyCode = event->nativeScanCode(); + } + + void mousePressEvent(QMouseEvent *event) override + { + ++mousePressEventCount; + mousePressPos = event->position().toPoint(); + } + + void mouseReleaseEvent(QMouseEvent *) override + { + ++mouseReleaseEventCount; + } + + void touchEvent(QTouchEvent *event) override + { + Q_UNUSED(event); + ++touchEventCount; + } + + QPoint frameOffset() const { return QPoint(frameMargins().left(), frameMargins().top()); } + + int focusInEventCount = 0; + int focusOutEventCount = 0; + int keyPressEventCount = 0; + int keyReleaseEventCount = 0; + int mousePressEventCount = 0; + int mouseReleaseEventCount = 0; + int touchEventCount = 0; + + uint keyCode = 0; + QPoint mousePressPos; +}; + +class tst_WaylandReconnect : public QObject +{ + Q_OBJECT +public: + tst_WaylandReconnect(); + void triggerReconnect(); + + template<typename function_type, typename... arg_types> + auto exec(function_type func, arg_types&&... args) -> decltype(func()) + { + return m_comp->exec(func, std::forward<arg_types>(args)...); + } + +private Q_SLOTS: +//core + void cleanup() { QTRY_VERIFY2(m_comp->isClean(), qPrintable(m_comp->dirtyMessage())); } + void basicWindow(); + void multipleScreens(); + +//input + void keyFocus(); + +private: + void configureWindow(); + QScopedPointer<DefaultCompositor> m_comp; + wl_socket *m_socket; +}; + +tst_WaylandReconnect::tst_WaylandReconnect() +{ + m_socket = wl_socket_create(); + QVERIFY(m_socket); + const int socketFd = wl_socket_get_fd(m_socket); + const QByteArray socketName = wl_socket_get_display_name(m_socket); + qputenv("WAYLAND_DISPLAY", socketName); + + m_comp.reset(new DefaultCompositor(CoreCompositor::Default, dup(socketFd))); +} + +void tst_WaylandReconnect::triggerReconnect() +{ + const int socketFd = wl_socket_get_fd(m_socket); + m_comp.reset(new DefaultCompositor(CoreCompositor::Default, dup(socketFd))); + QTest::qWait(50); //we need to spin the main loop to actually reconnect +} + +void tst_WaylandReconnect::basicWindow() +{ + QRasterWindow window; + window.resize(64, 48); + window.show(); + QCOMPOSITOR_TRY_VERIFY(m_comp->xdgToplevel()); + + triggerReconnect(); + + QCOMPOSITOR_TRY_VERIFY(m_comp->xdgToplevel()); +} + +void tst_WaylandReconnect::multipleScreens() +{ + + exec([this] { m_comp->add<Output>(); }); + QRasterWindow window1; + window1.resize(64, 48); + window1.show(); + QRasterWindow window2; + window2.resize(64, 48); + window2.show(); + QCOMPOSITOR_TRY_VERIFY(m_comp->xdgToplevel(0)); + QCOMPOSITOR_TRY_VERIFY(m_comp->xdgToplevel(1)); + + // ensure they are on different outputs + exec([this] { + m_comp->surface(0)->sendEnter(m_comp->output(0)); + m_comp->surface(1)->sendEnter(m_comp->output(1)); + }); + QTRY_VERIFY(window1.screen() != window2.screen()); + + auto originalScreens = QGuiApplication::screens(); + + QSignalSpy screenRemovedSpy(qGuiApp, &QGuiApplication::screenRemoved); + QVERIFY(screenRemovedSpy.isValid()); + + triggerReconnect(); + + // All screens plus temporary placeholder screen removed + QCOMPARE(screenRemovedSpy.count(), originalScreens.count() + 1); + for (const auto &screen : std::as_const(screenRemovedSpy)) { + originalScreens.removeOne(screen[0].value<QScreen *>()); + } + QVERIFY(originalScreens.isEmpty()); + + QCOMPOSITOR_TRY_VERIFY(m_comp->xdgToplevel(0)); + QCOMPOSITOR_TRY_VERIFY(m_comp->xdgToplevel(1)); + QVERIFY(window1.screen()); + QVERIFY(window2.screen()); + QVERIFY(QGuiApplication::screens().contains(window1.screen())); + QVERIFY(QGuiApplication::screens().contains(window2.screen())); +} + +void tst_WaylandReconnect::keyFocus() +{ + TestWindow window; + window.resize(64, 48); + window.show(); + + configureWindow(); + QTRY_VERIFY(window.isExposed()); + exec([&] { + m_comp->keyboard()->sendEnter(m_comp->surface()); + }); + QTRY_COMPARE(window.focusInEventCount, 1); + + uint keyCode = 80; + QCOMPARE(window.keyPressEventCount, 0); + exec([&] { + m_comp->keyboard()->sendKey(m_comp->client(), keyCode - 8, Keyboard::key_state_pressed); + }); + QTRY_COMPARE(window.keyPressEventCount, 1); + QCOMPARE(QGuiApplication::focusWindow(), &window); + + triggerReconnect(); + configureWindow(); + + // on reconnect our knowledge of focus is reset to a clean slate + QCOMPARE(QGuiApplication::focusWindow(), nullptr); + QTRY_COMPARE(window.focusOutEventCount, 1); + + // fake the user explicitly focussing this window afterwards + exec([&] { + m_comp->keyboard()->sendEnter(m_comp->surface()); + }); + exec([&] { + m_comp->keyboard()->sendKey(m_comp->client(), keyCode - 8, Keyboard::key_state_pressed); + }); + QTRY_COMPARE(window.focusInEventCount, 2); + QTRY_COMPARE(window.keyPressEventCount, 2); +} + + +void tst_WaylandReconnect::configureWindow() +{ + QCOMPOSITOR_TRY_VERIFY(m_comp->xdgToplevel()); + m_comp->exec([&] { + m_comp->xdgToplevel()->sendConfigure({0, 0}, {}); + const uint serial = m_comp->nextSerial(); // Let the window decide the size + m_comp->xdgSurface()->sendConfigure(serial); + }); +} + +int main(int argc, char **argv) +{ + // Note when debugging that a failing reconnect will exit this + // test rather than fail. Making sure it finishes is important! + + QTemporaryDir tmpRuntimeDir; + setenv("QT_QPA_PLATFORM", "wayland", 1); // force QGuiApplication to use wayland plugin + setenv("QT_WAYLAND_RECONNECT", "1", 1); + setenv("XDG_CURRENT_DESKTOP", "qtwaylandtests", 1); + + tst_WaylandReconnect tc; + QGuiApplication app(argc, argv); + QTEST_SET_MAIN_SOURCE_PATH + return QTest::qExec(&tc, argc, argv); +} + +#include "tst_reconnect.moc" diff --git a/tests/auto/client/reconnect/wl-socket.c b/tests/auto/client/reconnect/wl-socket.c new file mode 100644 index 000000000..3d4491622 --- /dev/null +++ b/tests/auto/client/reconnect/wl-socket.c @@ -0,0 +1,166 @@ +// Copyright (C) 2023 David Edmundson <davidedmundson@kde.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#define _DEFAULT_SOURCE +#include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/file.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/un.h> +#include <unistd.h> + +/* This is the size of the char array in struct sock_addr_un. + * No Wayland socket can be created with a path longer than this, + * including the null terminator. + */ +#ifndef UNIX_PATH_MAX +#define UNIX_PATH_MAX 108 +#endif + +#define LOCK_SUFFIX ".lock" +#define LOCK_SUFFIXLEN 5 + +struct wl_socket { + int fd; + int fd_lock; + struct sockaddr_un addr; + char lock_addr[UNIX_PATH_MAX + LOCK_SUFFIXLEN]; + char display_name[16]; +}; + +static struct wl_socket *wl_socket_alloc(void) +{ + struct wl_socket *s; + + s = malloc(sizeof *s); + if (!s) + return NULL; + + s->fd = -1; + s->fd_lock = -1; + + return s; +} + +static int wl_socket_lock(struct wl_socket *socket) +{ + struct stat socket_stat; + + snprintf(socket->lock_addr, sizeof socket->lock_addr, "%s%s", socket->addr.sun_path, LOCK_SUFFIX); + + // differening from kwin, we're back to setting CLOEXEC as we're all in process + socket->fd_lock = open(socket->lock_addr, O_CREAT | O_RDWR | O_CLOEXEC, (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)); + + if (socket->fd_lock < 0) { + printf("unable to open lockfile %s check permissions\n", socket->lock_addr); + goto err; + } + + if (flock(socket->fd_lock, LOCK_EX | LOCK_NB) < 0) { + printf("unable to lock lockfile %s, maybe another compositor is running\n", socket->lock_addr); + goto err_fd; + } + + if (lstat(socket->addr.sun_path, &socket_stat) < 0) { + if (errno != ENOENT) { + printf("did not manage to stat file %s\n", socket->addr.sun_path); + goto err_fd; + } + } else if (socket_stat.st_mode & S_IWUSR || socket_stat.st_mode & S_IWGRP) { + unlink(socket->addr.sun_path); + } + + return 0; +err_fd: + close(socket->fd_lock); + socket->fd_lock = -1; +err: + *socket->lock_addr = 0; + /* we did not set this value here, but without lock the + * socket won't be created anyway. This prevents the + * wl_socket_destroy from unlinking already existing socket + * created by other compositor */ + *socket->addr.sun_path = 0; + + return -1; +} + +void wl_socket_destroy(struct wl_socket *s) +{ + if (s->addr.sun_path[0]) + unlink(s->addr.sun_path); + if (s->fd >= 0) + close(s->fd); + if (s->lock_addr[0]) + unlink(s->lock_addr); + if (s->fd_lock >= 0) + close(s->fd_lock); + + free(s); +} + +const char *wl_socket_get_display_name(struct wl_socket *s) +{ + return s->display_name; +} + +int wl_socket_get_fd(struct wl_socket *s) +{ + return s->fd; +} + +struct wl_socket *wl_socket_create() +{ + struct wl_socket *s; + int displayno = 0; + int name_size; + + /* A reasonable number of maximum default sockets. If + * you need more than this, use the explicit add_socket API. */ + const int MAX_DISPLAYNO = 32; + const char *runtime_dir = getenv("XDG_RUNTIME_DIR"); + if (!runtime_dir) { + printf("XDG_RUNTIME_DIR not set"); + return NULL; + } + + s = wl_socket_alloc(); + if (s == NULL) + return NULL; + + do { + snprintf(s->display_name, sizeof s->display_name, "wayland-%d", displayno); + s->addr.sun_family = AF_LOCAL; + name_size = snprintf(s->addr.sun_path, sizeof s->addr.sun_path, "%s/%s", runtime_dir, s->display_name) + 1; + assert(name_size > 0); + + if (name_size > (int)sizeof s->addr.sun_path) { + goto fail; + } + + if (wl_socket_lock(s) < 0) + continue; + + s->fd = socket(PF_LOCAL, SOCK_STREAM, 0); + + int size = SUN_LEN(&s->addr); + int ret = bind(s->fd, (struct sockaddr*)&s->addr, size); + if (ret < 0) { + goto fail; + } + ret = listen(s->fd, 128); + if (ret < 0) { + goto fail; + } + return s; + } while (displayno++ < MAX_DISPLAYNO); + +fail: + wl_socket_destroy(s); + return NULL; +} diff --git a/tests/auto/client/reconnect/wl-socket.h b/tests/auto/client/reconnect/wl-socket.h new file mode 100644 index 000000000..c2e68120f --- /dev/null +++ b/tests/auto/client/reconnect/wl-socket.h @@ -0,0 +1,34 @@ +// Copyright (C) 2023 David Edmundson <davidedmundson@kde.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Allocate and create a socket + * It is bound and accepted + */ +struct wl_socket *wl_socket_create(); + +/** + * Returns the file descriptor for the socket + */ +int wl_socket_get_fd(struct wl_socket *); + +/** + * Returns the name of the socket, i.e "wayland-0" + */ +char *wl_socket_get_display_name(struct wl_socket *); + +/** + * Cleanup resources and close the FD + */ +void wl_socket_destroy(struct wl_socket *socket); + +#ifdef __cplusplus +} +#endif diff --git a/tests/auto/client/scaling/CMakeLists.txt b/tests/auto/client/scaling/CMakeLists.txt new file mode 100644 index 000000000..e58981388 --- /dev/null +++ b/tests/auto/client/scaling/CMakeLists.txt @@ -0,0 +1,10 @@ +##################################################################### +## tst_scaling Test: +##################################################################### + +qt_internal_add_test(tst_scaling + SOURCES + tst_scaling.cpp + LIBRARIES + SharedClientTest +) diff --git a/tests/auto/client/scaling/tst_scaling.cpp b/tests/auto/client/scaling/tst_scaling.cpp new file mode 100644 index 000000000..b4d2995ea --- /dev/null +++ b/tests/auto/client/scaling/tst_scaling.cpp @@ -0,0 +1,134 @@ +// Copyright (C) 2022 David Edmundson <davidedmundson@kde.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "mockcompositor.h" +#include <QtGui/QRasterWindow> +#include <QtGui/qpa/qplatformnativeinterface.h> +#include <QtWaylandClient/private/wayland-wayland-client-protocol.h> +#include <QtWaylandClient/private/qwaylandwindow_p.h> + +using namespace MockCompositor; + +class tst_scaling : public QObject, private DefaultCompositor +{ + Q_OBJECT +private slots: + void init(); + void cleanup() { QTRY_VERIFY2(isClean(), qPrintable(dirtyMessage())); } + void scaledWindow(); + void roundingPolicy_data(); + void roundingPolicy(); + +}; + +void tst_scaling::init() +{ + setenv("QT_WAYLAND_DISABLE_WINDOWDECORATION", "1", 1); +} + +void tst_scaling::scaledWindow() +{ + QRasterWindow window; + window.resize(100, 100); + window.show(); + QCOMPOSITOR_TRY_VERIFY(xdgToplevel()); + + QSignalSpy configureSpy(exec([&] { return xdgSurface(); }), &XdgSurface::configureCommitted); + QSignalSpy surfaceCommitSpy(exec([&] { return surface(); }), &Surface::commit); + + const QSize configureSize(100, 100); + + exec([&] { + QVERIFY(fractionalScale()); + fractionalScale()->send_preferred_scale(1.5 * 120); + xdgToplevel()->sendCompleteConfigure(configureSize); + }); + + QTRY_COMPARE(configureSpy.count(), 1); + QCOMPARE(window.devicePixelRatio(), 1.5); + + exec([&] { + Buffer *buffer = xdgToplevel()->surface()->m_committed.buffer; + QVERIFY(buffer); + QCOMPARE(buffer->size(), QSize(150, 150)); + Viewport *vp = viewport(); + QVERIFY(vp); + QCOMPARE(vp->m_destination, QSize(100, 100)); + }); + + // resize the window + window.resize(200,200); + QCOMPARE(window.size(), QSize(200,200)); + + QVERIFY(surfaceCommitSpy.wait()); + exec([&] { + Buffer *buffer = xdgToplevel()->surface()->m_committed.buffer; + QVERIFY(buffer); + QCOMPARE(buffer->size(), QSize(300, 300)); + Viewport *vp = viewport(); + QVERIFY(vp); + QCOMPARE(vp->m_destination, QSize(200, 200)); + }); + + // dynamic scale change + exec([&] { + QVERIFY(fractionalScale()); + fractionalScale()->send_preferred_scale(2.5 * 120); + }); + QTRY_COMPARE(window.devicePixelRatio(), 2.5); + QCOMPARE(window.size(), QSize(200,200)); + + QVERIFY(surfaceCommitSpy.wait()); + exec([&] { + Buffer *buffer = xdgToplevel()->surface()->m_committed.buffer; + QVERIFY(buffer); + QCOMPARE(buffer->size(), QSize(500, 500)); + Viewport *vp = viewport(); + QVERIFY(vp); + QCOMPARE(vp->m_destination, QSize(200, 200)); + }); +} + +void tst_scaling::roundingPolicy_data() +{ + QTest::addColumn<QSize>("windowSize"); + QTest::addColumn<qreal>("scale"); + QTest::addColumn<QSize>("expectedBufferSize"); + + QTest::newRow("1.125 - round down") << QSize(10, 10) << 1.125 << QSize(11,11); + QTest::newRow("1.25 - round up") << QSize(10, 10) << 1.25 << QSize(13,13); + QTest::newRow("1.5 - don't round") << QSize(10, 10) << 1.5 << QSize(15,15); +} + +void tst_scaling::roundingPolicy() +{ + QFETCH(QSize, windowSize); + QFETCH(qreal, scale); + QFETCH(QSize, expectedBufferSize); + + + QRasterWindow window; + window.resize(windowSize); + window.show(); + QCOMPOSITOR_TRY_VERIFY(xdgToplevel()); + + QSignalSpy surfaceCommitSpy(exec([&] { return surface(); }), &Surface::commit); + + exec([&] { + QVERIFY(fractionalScale()); + fractionalScale()->send_preferred_scale(scale * 120); + xdgToplevel()->sendCompleteConfigure(); + }); + + QVERIFY(surfaceCommitSpy.wait()); + + exec([&] { + Buffer *buffer = xdgToplevel()->surface()->m_committed.buffer; + QVERIFY(buffer); + QCOMPARE(buffer->size(), expectedBufferSize); + }); +} + + +QCOMPOSITOR_TEST_MAIN(tst_scaling) +#include "tst_scaling.moc" diff --git a/tests/auto/client/seat/CMakeLists.txt b/tests/auto/client/seat/CMakeLists.txt new file mode 100644 index 000000000..0ac9ec49f --- /dev/null +++ b/tests/auto/client/seat/CMakeLists.txt @@ -0,0 +1,15 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +# Generated from seatv5.pro. + +##################################################################### +## tst_seatv5 Test: +##################################################################### + +qt_internal_add_test(tst_seat + SOURCES + tst_seat.cpp + LIBRARIES + SharedClientTest +) diff --git a/tests/auto/client/seatv5/tst_seatv5.cpp b/tests/auto/client/seat/tst_seat.cpp index 636f26081..45ae7251c 100644 --- a/tests/auto/client/seatv5/tst_seatv5.cpp +++ b/tests/auto/client/seat/tst_seat.cpp @@ -1,40 +1,15 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "mockcompositor.h" #include <QtGui/QRasterWindow> -#include <QtGui/QOpenGLWindow> +#include <QtGui/QEventPoint> using namespace MockCompositor; -class SeatV5Compositor : public DefaultCompositor { +class SeatCompositor : public DefaultCompositor { public: - explicit SeatV5Compositor() + explicit SeatCompositor() { exec([this] { m_config.autoConfigure = true; @@ -42,13 +17,13 @@ public: removeAll<Seat>(); uint capabilities = MockCompositor::Seat::capability_pointer | MockCompositor::Seat::capability_touch; - int version = 5; + int version = 9; add<Seat>(capabilities, version); }); } }; -class tst_seatv5 : public QObject, private SeatV5Compositor +class tst_seat : public QObject, private SeatCompositor { Q_OBJECT private slots: @@ -63,7 +38,8 @@ private slots: void simpleAxis(); void fingerScroll(); void fingerScrollSlow(); - void wheelDiscreteScroll(); + void continuousScroll(); + void highResolutionScroll(); // Touch tests void createsTouch(); @@ -71,28 +47,30 @@ private slots: void singleTapFloat(); void multiTouch(); void multiTouchUpAndMotionFrame(); + void tapAndMoveInSameFrame(); + void cancelTouch(); }; -void tst_seatv5::bindsToSeat() +void tst_seat::bindsToSeat() { QCOMPOSITOR_COMPARE(get<Seat>()->resourceMap().size(), 1); - QCOMPOSITOR_COMPARE(get<Seat>()->resourceMap().first()->version(), 5); + QCOMPOSITOR_COMPARE(get<Seat>()->resourceMap().first()->version(), 9); } -void tst_seatv5::createsPointer() +void tst_seat::createsPointer() { QCOMPOSITOR_TRY_COMPARE(pointer()->resourceMap().size(), 1); - QCOMPOSITOR_TRY_COMPARE(pointer()->resourceMap().first()->version(), 5); + QCOMPOSITOR_TRY_COMPARE(pointer()->resourceMap().first()->version(), 9); } -void tst_seatv5::setsCursorOnEnter() +void tst_seat::setsCursorOnEnter() { QRasterWindow window; window.resize(64, 64); window.show(); QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial); - exec([=] { + exec([&] { auto *surface = xdgSurface()->m_surface; pointer()->sendEnter(surface, {0, 0}); pointer()->sendFrame(surface->resource()->client()); @@ -101,20 +79,20 @@ void tst_seatv5::setsCursorOnEnter() QCOMPOSITOR_TRY_VERIFY(pointer()->cursorSurface()); } -void tst_seatv5::usesEnterSerial() +void tst_seat::usesEnterSerial() { - QSignalSpy setCursorSpy(exec([=] { return pointer(); }), &Pointer::setCursor); + QSignalSpy setCursorSpy(exec([&] { return pointer(); }), &Pointer::setCursor); QRasterWindow window; window.resize(64, 64); window.show(); QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial); - uint enterSerial = exec([=] { + uint enterSerial = exec([&] { return pointer()->sendEnter(xdgSurface()->m_surface, {0, 0}); }); QCOMPOSITOR_TRY_VERIFY(pointer()->cursorSurface()); - QTRY_COMPARE(setCursorSpy.count(), 1); + QTRY_COMPARE(setCursorSpy.size(), 1); QCOMPARE(setCursorSpy.takeFirst().at(0).toUInt(), enterSerial); } @@ -136,10 +114,6 @@ public: QCOMPARE(event->pixelDelta(), QPoint(0, 0)); } - // The axis vector of the event is already in surface space, so there is now way to tell - // whether it is inverted or not. - QCOMPARE(event->inverted(), false); - // We didn't press any buttons QCOMPARE(event->buttons(), Qt::NoButton); @@ -153,40 +127,51 @@ public: , pixelDelta(event->pixelDelta()) , angleDelta(event->angleDelta()) , source(event->source()) + , inverted(event->inverted()) { } - const Qt::ScrollPhase phase{}; - const QPoint pixelDelta; - const QPoint angleDelta; // eights of a degree, positive is upwards, left - const Qt::MouseEventSource source{}; + Qt::ScrollPhase phase{}; + QPoint pixelDelta; + QPoint angleDelta; // eights of a degree, positive is upwards, left + Qt::MouseEventSource source{}; + bool inverted = false; }; - QVector<Event> m_events; + QList<Event> m_events; }; -void tst_seatv5::simpleAxis_data() +void tst_seat::simpleAxis_data() { QTest::addColumn<uint>("axis"); QTest::addColumn<qreal>("value"); QTest::addColumn<QPoint>("angleDelta"); + QTest::addColumn<bool>("inverted"); // Directions in regular windows/linux terms (no "natural" scrolling) - QTest::newRow("down") << uint(Pointer::axis_vertical_scroll) << 1.0 << QPoint{0, -12}; - QTest::newRow("up") << uint(Pointer::axis_vertical_scroll) << -1.0 << QPoint{0, 12}; - QTest::newRow("left") << uint(Pointer::axis_horizontal_scroll) << 1.0 << QPoint{-12, 0}; - QTest::newRow("right") << uint(Pointer::axis_horizontal_scroll) << -1.0 << QPoint{12, 0}; - QTest::newRow("up big") << uint(Pointer::axis_vertical_scroll) << -10.0 << QPoint{0, 120}; + QTest::newRow("down") << uint(Pointer::axis_vertical_scroll) << 1.0 << QPoint{0, -12} << false; + QTest::newRow("up") << uint(Pointer::axis_vertical_scroll) << -1.0 << QPoint{0, 12} << false; + QTest::newRow("left") << uint(Pointer::axis_horizontal_scroll) << 1.0 << QPoint{-12, 0} << false; + QTest::newRow("right") << uint(Pointer::axis_horizontal_scroll) << -1.0 << QPoint{12, 0} << false; + QTest::newRow("up big") << uint(Pointer::axis_vertical_scroll) << -10.0 << QPoint{0, 120} << false; + + // (natural) scrolling + QTest::newRow("down inverted") << uint(Pointer::axis_vertical_scroll) << 1.0 << QPoint{0, -12} << true; + QTest::newRow("up inverted") << uint(Pointer::axis_vertical_scroll) << -1.0 << QPoint{0, 12} << true; + QTest::newRow("left inverted") << uint(Pointer::axis_horizontal_scroll) << 1.0 << QPoint{-12, 0} << true; + QTest::newRow("right inverted") << uint(Pointer::axis_horizontal_scroll) << -1.0 << QPoint{12, 0} << true; + QTest::newRow("up big inverted") << uint(Pointer::axis_vertical_scroll) << -10.0 << QPoint{0, 120} << true; } -void tst_seatv5::simpleAxis() +void tst_seat::simpleAxis() { QFETCH(uint, axis); QFETCH(qreal, value); QFETCH(QPoint, angleDelta); + QFETCH(bool, inverted); WheelWindow window; QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial); - exec([=] { + exec([&] { auto *p = pointer(); p->sendEnter(xdgToplevel()->surface(), {32, 32}); p->sendFrame(client()); @@ -195,6 +180,8 @@ void tst_seatv5::simpleAxis() Pointer::axis(axis), value // Length of vector in surface-local space. i.e. positive is downwards ); + auto direction = inverted ? Pointer::axis_relative_direction_inverted : Pointer::axis_relative_direction_identical; + p->sendAxisRelativeDirection(client(), Pointer::axis(axis), direction); p->sendFrame(client()); }); @@ -208,17 +195,19 @@ void tst_seatv5::simpleAxis() // Documentation says not synthesized is appropriate in such cases QCOMPARE(e.source, Qt::MouseEventNotSynthesized); QCOMPARE(e.angleDelta, angleDelta); + + QCOMPARE(e.inverted, inverted); } // Sending axis_stop is not mandatory when axis source != finger } -void tst_seatv5::fingerScroll() +void tst_seat::fingerScroll() { WheelWindow window; QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial); - exec([=] { + exec([&] { auto *p = pointer(); auto *c = client(); p->sendEnter(xdgToplevel()->surface(), {32, 32}); @@ -251,14 +240,14 @@ void tst_seatv5::fingerScroll() QCOMPARE(e.phase, Qt::ScrollUpdate); QVERIFY(qAbs(e.angleDelta.x()) <= qAbs(e.angleDelta.y())); // Vertical scroll // QCOMPARE(e.angleDelta, angleDelta); // TODO: what should this be? - QCOMPARE(e.pixelDelta, QPoint(0, 10)); + QCOMPARE(e.pixelDelta, QPoint(0, -10)); QCOMPARE(e.source, Qt::MouseEventSynthesizedBySystem); // A finger is not a wheel } QTRY_VERIFY(window.m_events.empty()); // Scroll horizontally as well - exec([=] { + exec([&] { pointer()->sendAxisSource(client(), Pointer::axis_source_finger); pointer()->sendAxis(client(), Pointer::axis_horizontal_scroll, 10); pointer()->sendFrame(client()); @@ -268,12 +257,12 @@ void tst_seatv5::fingerScroll() auto e = window.m_events.takeFirst(); QCOMPARE(e.phase, Qt::ScrollUpdate); QVERIFY(qAbs(e.angleDelta.x()) > qAbs(e.angleDelta.y())); // Horizontal scroll - QCOMPARE(e.pixelDelta, QPoint(10, 0)); + QCOMPARE(e.pixelDelta, QPoint(-10, 0)); QCOMPARE(e.source, Qt::MouseEventSynthesizedBySystem); // A finger is not a wheel } // Scroll diagonally - exec([=] { + exec([&] { pointer()->sendAxisSource(client(), Pointer::axis_source_finger); pointer()->sendAxis(client(), Pointer::axis_horizontal_scroll, 10); pointer()->sendAxis(client(), Pointer::axis_vertical_scroll, 10); @@ -283,7 +272,7 @@ void tst_seatv5::fingerScroll() { auto e = window.m_events.takeFirst(); QCOMPARE(e.phase, Qt::ScrollUpdate); - QCOMPARE(e.pixelDelta, QPoint(10, 10)); + QCOMPARE(e.pixelDelta, QPoint(-10, -10)); QCOMPARE(e.source, Qt::MouseEventSynthesizedBySystem); // A finger is not a wheel } @@ -297,7 +286,7 @@ void tst_seatv5::fingerScroll() QVERIFY(window.m_events.empty()); // Sending axis_stop is mandatory when axis source == finger - exec([=] { + exec([&] { pointer()->sendAxisStop(client(), Pointer::axis_vertical_scroll); pointer()->sendFrame(client()); }); @@ -310,12 +299,12 @@ void tst_seatv5::fingerScroll() } -void tst_seatv5::fingerScrollSlow() +void tst_seat::fingerScrollSlow() { WheelWindow window; QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial); - exec([=] { + exec([&] { auto *p = pointer(); auto *c = client(); p->sendEnter(xdgToplevel()->surface(), {32, 32}); @@ -337,21 +326,22 @@ void tst_seatv5::fingerScrollSlow() accumulated += e.pixelDelta; QTRY_VERIFY(!window.m_events.empty()); } - QCOMPARE(accumulated.y(), 1); + QCOMPARE(accumulated.y(), -1); } -void tst_seatv5::wheelDiscreteScroll() + +void tst_seat::highResolutionScroll() { WheelWindow window; QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial); - exec([=] { + exec([&] { auto *p = pointer(); auto *c = client(); p->sendEnter(xdgToplevel()->surface(), {32, 32}); p->sendFrame(c); p->sendAxisSource(c, Pointer::axis_source_wheel); - p->sendAxisDiscrete(c, Pointer::axis_vertical_scroll, 1); // 1 click downwards - p->sendAxis(c, Pointer::axis_vertical_scroll, 1.0); + p->sendAxisValue120(c, Pointer::axis_vertical_scroll, 30); // quarter of a click + p->sendAxis(c, Pointer::axis_vertical_scroll, 3.75); p->sendFrame(c); }); @@ -360,19 +350,63 @@ void tst_seatv5::wheelDiscreteScroll() auto e = window.m_events.takeFirst(); QCOMPARE(e.phase, Qt::NoScrollPhase); QVERIFY(qAbs(e.angleDelta.x()) <= qAbs(e.angleDelta.y())); // Vertical scroll - // According to the docs the angle delta is in eights of a degree and most mice have - // 1 click = 15 degrees. The angle delta should therefore be: - // 15 degrees / (1/8 eights per degrees) = 120 eights of degrees. - QCOMPARE(e.angleDelta, QPoint(0, -120)); + QCOMPARE(e.angleDelta, QPoint(0, -30)); // Click scrolls are not continuous and should not have a pixel delta QCOMPARE(e.pixelDelta, QPoint(0, 0)); } + + exec([&] { + auto *p = pointer(); + auto *c = client(); + p->sendAxisSource(c, Pointer::axis_source_wheel); + p->sendAxisValue120(c, Pointer::axis_vertical_scroll, 90); // complete the click + p->sendAxis(c, Pointer::axis_vertical_scroll, 11.25); + p->sendFrame(c); + }); + + QTRY_VERIFY(!window.m_events.empty()); + { + auto e = window.m_events.takeFirst(); + QCOMPARE(e.phase, Qt::NoScrollPhase); + QVERIFY(qAbs(e.angleDelta.x()) <= qAbs(e.angleDelta.y())); // Vertical scroll + QCOMPARE(e.angleDelta, QPoint(0, -90)); + // Click scrolls are not continuous and should not have a pixel delta + QCOMPARE(e.pixelDelta, QPoint(0, 0)); + } +} + +void tst_seat::continuousScroll() +{ + WheelWindow window; + QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial); + + exec([&] { + auto *p = pointer(); + auto *c = client(); + p->sendEnter(xdgToplevel()->surface(), {32, 32}); + p->sendFrame(c); + p->sendAxisSource(c, Pointer::axis_source_continuous); + p->sendAxis(c, Pointer::axis_vertical_scroll, 10); + p->sendAxis(c, Pointer::axis_horizontal_scroll, -5); + p->sendFrame(c); + }); + + QTRY_VERIFY(!window.m_events.empty()); + { + auto e = window.m_events.takeFirst(); + QCOMPARE(e.phase, Qt::NoScrollPhase); + QCOMPARE(e.pixelDelta, QPoint(5, -10)); + QCOMPARE(e.source, Qt::MouseEventSynthesizedBySystem); // touchpads are not wheels + QCOMPARE(e.inverted, false); + + } + // Sending axis_stop is not mandatory when axis source != finger } -void tst_seatv5::createsTouch() +void tst_seat::createsTouch() { QCOMPOSITOR_TRY_COMPARE(touch()->resourceMap().size(), 1); - QCOMPOSITOR_TRY_COMPARE(touch()->resourceMap().first()->version(), 5); + QCOMPOSITOR_TRY_COMPARE(touch()->resourceMap().first()->version(), 9); } class TouchWindow : public QRasterWindow { @@ -393,22 +427,22 @@ public: explicit Event(const QTouchEvent *event) : type(event->type()) , touchPointStates(event->touchPointStates()) - , touchPoints(event->touchPoints()) + , touchPoints(event->points()) { } - const QEvent::Type type{}; - const Qt::TouchPointStates touchPointStates{}; - const QList<QTouchEvent::TouchPoint> touchPoints; + QEvent::Type type{}; + QEventPoint::States touchPointStates{}; + QList<QTouchEvent::TouchPoint> touchPoints; }; - QVector<Event> m_events; + QList<Event> m_events; }; -void tst_seatv5::singleTap() +void tst_seat::singleTap() { TouchWindow window; QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial); - exec([=] { + exec([&] { auto *t = touch(); auto *c = client(); t->sendDown(xdgToplevel()->surface(), {32, 32}, 1); @@ -421,25 +455,25 @@ void tst_seatv5::singleTap() { auto e = window.m_events.takeFirst(); QCOMPARE(e.type, QEvent::TouchBegin); - QCOMPARE(e.touchPointStates, Qt::TouchPointState::TouchPointPressed); - QCOMPARE(e.touchPoints.length(), 1); - QCOMPARE(e.touchPoints.first().pos(), QPointF(32-window.frameMargins().left(), 32-window.frameMargins().top())); + QCOMPARE(e.touchPointStates, QEventPoint::State::Pressed); + QCOMPARE(e.touchPoints.size(), 1); + QCOMPARE(e.touchPoints.first().position(), QPointF(32-window.frameMargins().left(), 32-window.frameMargins().top())); } { auto e = window.m_events.takeFirst(); QCOMPARE(e.type, QEvent::TouchEnd); - QCOMPARE(e.touchPointStates, Qt::TouchPointState::TouchPointReleased); - QCOMPARE(e.touchPoints.length(), 1); - QCOMPARE(e.touchPoints.first().pos(), QPointF(32-window.frameMargins().left(), 32-window.frameMargins().top())); + QCOMPARE(e.touchPointStates, QEventPoint::State::Released); + QCOMPARE(e.touchPoints.size(), 1); + QCOMPARE(e.touchPoints.first().position(), QPointF(32-window.frameMargins().left(), 32-window.frameMargins().top())); } } -void tst_seatv5::singleTapFloat() +void tst_seat::singleTapFloat() { TouchWindow window; QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial); - exec([=] { + exec([&] { auto *t = touch(); auto *c = client(); t->sendDown(xdgToplevel()->surface(), {32.75, 32.25}, 1); @@ -452,25 +486,25 @@ void tst_seatv5::singleTapFloat() { auto e = window.m_events.takeFirst(); QCOMPARE(e.type, QEvent::TouchBegin); - QCOMPARE(e.touchPointStates, Qt::TouchPointState::TouchPointPressed); - QCOMPARE(e.touchPoints.length(), 1); - QCOMPARE(e.touchPoints.first().pos(), QPointF(32.75-window.frameMargins().left(), 32.25-window.frameMargins().top())); + QCOMPARE(e.touchPointStates, QEventPoint::State::Pressed); + QCOMPARE(e.touchPoints.size(), 1); + QCOMPARE(e.touchPoints.first().position(), QPointF(32.75-window.frameMargins().left(), 32.25-window.frameMargins().top())); } { auto e = window.m_events.takeFirst(); QCOMPARE(e.type, QEvent::TouchEnd); - QCOMPARE(e.touchPointStates, Qt::TouchPointState::TouchPointReleased); - QCOMPARE(e.touchPoints.length(), 1); - QCOMPARE(e.touchPoints.first().pos(), QPointF(32.75-window.frameMargins().left(), 32.25-window.frameMargins().top())); + QCOMPARE(e.touchPointStates, QEventPoint::State::Released); + QCOMPARE(e.touchPoints.size(), 1); + QCOMPARE(e.touchPoints.first().position(), QPointF(32.75-window.frameMargins().left(), 32.25-window.frameMargins().top())); } } -void tst_seatv5::multiTouch() +void tst_seat::multiTouch() { TouchWindow window; QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial); - exec([=] { + exec([&] { auto *t = touch(); auto *c = client(); @@ -478,7 +512,7 @@ void tst_seatv5::multiTouch() t->sendDown(xdgToplevel()->surface(), {48, 48}, 1); t->sendFrame(c); - // Compositor event order should not change the order of the QTouchEvent::touchPoints() + // Compositor event order should not change the order of the QTouchEvent::points() // See QTBUG-77014 t->sendMotion(c, {49, 48}, 1); t->sendMotion(c, {33, 32}, 0); @@ -495,54 +529,54 @@ void tst_seatv5::multiTouch() { auto e = window.m_events.takeFirst(); QCOMPARE(e.type, QEvent::TouchBegin); - QCOMPARE(e.touchPointStates, Qt::TouchPointState::TouchPointPressed); - QCOMPARE(e.touchPoints.length(), 2); + QCOMPARE(e.touchPointStates, QEventPoint::State::Pressed); + QCOMPARE(e.touchPoints.size(), 2); - QCOMPARE(e.touchPoints[0].state(), Qt::TouchPointState::TouchPointPressed); - QCOMPARE(e.touchPoints[0].pos(), QPointF(32-window.frameMargins().left(), 32-window.frameMargins().top())); + QCOMPARE(e.touchPoints[0].state(), QEventPoint::State::Pressed); + QCOMPARE(e.touchPoints[0].position(), QPointF(32-window.frameMargins().left(), 32-window.frameMargins().top())); - QCOMPARE(e.touchPoints[1].state(), Qt::TouchPointState::TouchPointPressed); - QCOMPARE(e.touchPoints[1].pos(), QPointF(48-window.frameMargins().left(), 48-window.frameMargins().top())); + QCOMPARE(e.touchPoints[1].state(), QEventPoint::State::Pressed); + QCOMPARE(e.touchPoints[1].position(), QPointF(48-window.frameMargins().left(), 48-window.frameMargins().top())); } { auto e = window.m_events.takeFirst(); QCOMPARE(e.type, QEvent::TouchUpdate); - QCOMPARE(e.touchPoints.length(), 2); + QCOMPARE(e.touchPoints.size(), 2); - QCOMPARE(e.touchPoints[0].state(), Qt::TouchPointState::TouchPointMoved); - QCOMPARE(e.touchPoints[0].pos(), QPointF(33-window.frameMargins().left(), 32-window.frameMargins().top())); + QCOMPARE(e.touchPoints[0].state(), QEventPoint::State::Updated); + QCOMPARE(e.touchPoints[0].position(), QPointF(33-window.frameMargins().left(), 32-window.frameMargins().top())); - QCOMPARE(e.touchPoints[1].state(), Qt::TouchPointState::TouchPointMoved); - QCOMPARE(e.touchPoints[1].pos(), QPointF(49-window.frameMargins().left(), 48-window.frameMargins().top())); + QCOMPARE(e.touchPoints[1].state(), QEventPoint::State::Updated); + QCOMPARE(e.touchPoints[1].position(), QPointF(49-window.frameMargins().left(), 48-window.frameMargins().top())); } { auto e = window.m_events.takeFirst(); QCOMPARE(e.type, QEvent::TouchUpdate); - QCOMPARE(e.touchPointStates, Qt::TouchPointState::TouchPointReleased | Qt::TouchPointState::TouchPointStationary); - QCOMPARE(e.touchPoints.length(), 2); + QCOMPARE(e.touchPointStates, QEventPoint::State::Released | QEventPoint::State::Stationary); + QCOMPARE(e.touchPoints.size(), 2); - QCOMPARE(e.touchPoints[0].state(), Qt::TouchPointState::TouchPointReleased); - QCOMPARE(e.touchPoints[0].pos(), QPointF(33-window.frameMargins().left(), 32-window.frameMargins().top())); + QCOMPARE(e.touchPoints[0].state(), QEventPoint::State::Released); + QCOMPARE(e.touchPoints[0].position(), QPointF(33-window.frameMargins().left(), 32-window.frameMargins().top())); - QCOMPARE(e.touchPoints[1].state(), Qt::TouchPointState::TouchPointStationary); - QCOMPARE(e.touchPoints[1].pos(), QPointF(49-window.frameMargins().left(), 48-window.frameMargins().top())); + QCOMPARE(e.touchPoints[1].state(), QEventPoint::State::Stationary); + QCOMPARE(e.touchPoints[1].position(), QPointF(49-window.frameMargins().left(), 48-window.frameMargins().top())); } { auto e = window.m_events.takeFirst(); QCOMPARE(e.type, QEvent::TouchEnd); - QCOMPARE(e.touchPointStates, Qt::TouchPointState::TouchPointReleased); - QCOMPARE(e.touchPoints.length(), 1); - QCOMPARE(e.touchPoints[0].state(), Qt::TouchPointState::TouchPointReleased); - QCOMPARE(e.touchPoints[0].pos(), QPointF(49-window.frameMargins().left(), 48-window.frameMargins().top())); + QCOMPARE(e.touchPointStates, QEventPoint::State::Released); + QCOMPARE(e.touchPoints.size(), 1); + QCOMPARE(e.touchPoints[0].state(), QEventPoint::State::Released); + QCOMPARE(e.touchPoints[0].position(), QPointF(49-window.frameMargins().left(), 48-window.frameMargins().top())); } } -void tst_seatv5::multiTouchUpAndMotionFrame() +void tst_seat::multiTouchUpAndMotionFrame() { TouchWindow window; QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial); - exec([=] { + exec([&] { auto *t = touch(); auto *c = client(); @@ -567,24 +601,85 @@ void tst_seatv5::multiTouchUpAndMotionFrame() { auto e = window.m_events.takeFirst(); QCOMPARE(e.type, QEvent::TouchBegin); - QCOMPARE(e.touchPoints[0].state(), Qt::TouchPointState::TouchPointPressed); - QCOMPARE(e.touchPoints[1].state(), Qt::TouchPointState::TouchPointPressed); + QCOMPARE(e.touchPoints[0].state(), QEventPoint::State::Pressed); + QCOMPARE(e.touchPoints[1].state(), QEventPoint::State::Pressed); } { auto e = window.m_events.takeFirst(); QCOMPARE(e.type, QEvent::TouchUpdate); - QCOMPARE(e.touchPoints.length(), 2); - QCOMPARE(e.touchPoints[0].state(), Qt::TouchPointState::TouchPointReleased); - QCOMPARE(e.touchPoints[1].state(), Qt::TouchPointState::TouchPointMoved); + QCOMPARE(e.touchPoints.size(), 2); + QCOMPARE(e.touchPoints[0].state(), QEventPoint::State::Released); + QCOMPARE(e.touchPoints[1].state(), QEventPoint::State::Updated); } { auto e = window.m_events.takeFirst(); QCOMPARE(e.type, QEvent::TouchEnd); - QCOMPARE(e.touchPoints.length(), 1); - QCOMPARE(e.touchPoints[0].state(), Qt::TouchPointState::TouchPointReleased); + QCOMPARE(e.touchPoints.size(), 1); + QCOMPARE(e.touchPoints[0].state(), QEventPoint::State::Released); } QVERIFY(window.m_events.empty()); } -QCOMPOSITOR_TEST_MAIN(tst_seatv5) -#include "tst_seatv5.moc" +void tst_seat::tapAndMoveInSameFrame() +{ + TouchWindow window; + QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial); + + exec([&] { + auto *t = touch(); + auto *c = client(); + + t->sendDown(xdgToplevel()->surface(), {32, 32}, 0); + t->sendMotion(c, {33, 33}, 0); + t->sendFrame(c); + + // Don't leave touch in a weird state + t->sendUp(c, 0); + t->sendFrame(c); + }); + + QTRY_VERIFY(!window.m_events.empty()); + { + auto e = window.m_events.takeFirst(); + QCOMPARE(e.type, QEvent::TouchBegin); + QCOMPARE(e.touchPoints.size(), 1); + QCOMPARE(e.touchPoints[0].state(), QEventPoint::State::Pressed); + // Position isn't that important, we just want to make sure we actually get the pressed event + } + + // Make sure we eventually release + QTRY_VERIFY(!window.m_events.empty()); + QTRY_COMPARE(window.m_events.last().touchPoints.first().state(), QEventPoint::State::Released); +} + +void tst_seat::cancelTouch() +{ + TouchWindow window; + QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial); + + exec([&] { + auto *t = touch(); + auto *c = client(); + t->sendDown(xdgToplevel()->surface(), {32, 32}, 1); + t->sendFrame(c); + t->sendCancel(c); + t->sendFrame(c); + }); + + QTRY_VERIFY(!window.m_events.empty()); + { + auto e = window.m_events.takeFirst(); + QCOMPARE(e.type, QEvent::TouchBegin); + QCOMPARE(e.touchPointStates, QEventPoint::State::Pressed); + QCOMPARE(e.touchPoints.size(), 1); + QCOMPARE(e.touchPoints.first().position(), QPointF(32-window.frameMargins().left(), 32-window.frameMargins().top())); + } + { + auto e = window.m_events.takeFirst(); + QCOMPARE(e.type, QEvent::TouchCancel); + QCOMPARE(e.touchPoints.size(), 0); + } +} + +QCOMPOSITOR_TEST_MAIN(tst_seat) +#include "tst_seat.moc" diff --git a/tests/auto/client/seatv4/BLACKLIST b/tests/auto/client/seatv4/BLACKLIST deleted file mode 100644 index 1c761a74e..000000000 --- a/tests/auto/client/seatv4/BLACKLIST +++ /dev/null @@ -1,2 +0,0 @@ -[animatedCursor] -b2qt diff --git a/tests/auto/client/seatv4/CMakeLists.txt b/tests/auto/client/seatv4/CMakeLists.txt new file mode 100644 index 000000000..c4e3ecba1 --- /dev/null +++ b/tests/auto/client/seatv4/CMakeLists.txt @@ -0,0 +1,24 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +# Generated from seatv4.pro. + +##################################################################### +## tst_seatv4 Test: +##################################################################### + +qt_internal_add_test(tst_seatv4 + SOURCES + tst_seatv4.cpp + LIBRARIES + SharedClientTest +) + +## Scopes: +##################################################################### + +qt_internal_extend_target(tst_seatv4 CONDITION QT_FEATURE_cursor + LIBRARIES + Qt::GuiPrivate + Wayland::Cursor +) diff --git a/tests/auto/client/seatv4/seatv4.pro b/tests/auto/client/seatv4/seatv4.pro deleted file mode 100644 index 7a86cbf03..000000000 --- a/tests/auto/client/seatv4/seatv4.pro +++ /dev/null @@ -1,9 +0,0 @@ -include (../shared/shared.pri) - -qtConfig(cursor) { - QMAKE_USE += wayland-cursor - QT += gui-private -} - -TARGET = tst_seatv4 -SOURCES += tst_seatv4.cpp diff --git a/tests/auto/client/seatv4/tst_seatv4.cpp b/tests/auto/client/seatv4/tst_seatv4.cpp index 2e17bef87..cc1cf0afd 100644 --- a/tests/auto/client/seatv4/tst_seatv4.cpp +++ b/tests/auto/client/seatv4/tst_seatv4.cpp @@ -1,35 +1,9 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "mockcompositor.h" #include <QtGui/QRasterWindow> -#include <QtGui/QOpenGLWindow> #if QT_CONFIG(cursor) #include <wayland-cursor.h> #include <QtGui/private/qguiapplication_p.h> @@ -49,6 +23,7 @@ public: { exec([this] { m_config.autoConfigure = true; + m_config.autoFrameCallback = false; // for cursor animation test removeAll<Seat>(); @@ -63,6 +38,7 @@ class tst_seatv4 : public QObject, private SeatV4Compositor { Q_OBJECT private slots: + void init(); void cleanup(); void bindsToSeat(); void keyboardKeyPress(); @@ -85,6 +61,12 @@ private slots: #endif }; +void tst_seatv4::init() +{ + // Remove the extra outputs to clean up for the next test + exec([&] { while (auto *o = output(1)) remove(o); }); +} + void tst_seatv4::cleanup() { QTRY_VERIFY2(isClean(), qPrintable(dirtyMessage())); @@ -135,42 +117,42 @@ void tst_seatv4::setsCursorOnEnter() window.show(); QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial); - exec([=] { pointer()->sendEnter(xdgSurface()->m_surface, {32, 32}); }); + exec([&] { pointer()->sendEnter(xdgSurface()->m_surface, {24, 24}); }); QCOMPOSITOR_TRY_VERIFY(cursorSurface()); } void tst_seatv4::usesEnterSerial() { - QSignalSpy setCursorSpy(exec([=] { return pointer(); }), &Pointer::setCursor); + QSignalSpy setCursorSpy(exec([&] { return pointer(); }), &Pointer::setCursor); QRasterWindow window; window.resize(64, 64); window.show(); QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial); - uint enterSerial = exec([=] { + uint enterSerial = exec([&] { return pointer()->sendEnter(xdgSurface()->m_surface, {32, 32}); }); QCOMPOSITOR_TRY_VERIFY(cursorSurface()); - QTRY_COMPARE(setCursorSpy.count(), 1); + QTRY_COMPARE(setCursorSpy.size(), 1); QCOMPARE(setCursorSpy.takeFirst().at(0).toUInt(), enterSerial); } void tst_seatv4::focusDestruction() { - QSignalSpy setCursorSpy(exec([=] { return pointer(); }), &Pointer::setCursor); + QSignalSpy setCursorSpy(exec([&] { return pointer(); }), &Pointer::setCursor); QRasterWindow window; window.resize(64, 64); window.show(); QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial); // Setting a cursor now is not allowed since there has been no enter event - QCOMPARE(setCursorSpy.count(), 0); + QCOMPARE(setCursorSpy.size(), 0); - uint enterSerial = exec([=] { + uint enterSerial = exec([&] { return pointer()->sendEnter(xdgSurface()->m_surface, {32, 32}); }); QCOMPOSITOR_TRY_VERIFY(cursorSurface()); - QTRY_COMPARE(setCursorSpy.count(), 1); + QTRY_COMPARE(setCursorSpy.size(), 1); QCOMPARE(setCursorSpy.takeFirst().at(0).toUInt(), enterSerial); // Destroy the focus @@ -184,7 +166,7 @@ void tst_seatv4::focusDestruction() // Setting a cursor now is not allowed since there has been no enter event xdgPingAndWaitForPong(); - QCOMPARE(setCursorSpy.count(), 0); + QCOMPARE(setCursorSpy.size(), 0); } void tst_seatv4::mousePress() @@ -213,7 +195,7 @@ void tst_seatv4::mousePressFloat() { class Window : public QRasterWindow { public: - void mousePressEvent(QMouseEvent *e) override { m_position = e->localPos(); } + void mousePressEvent(QMouseEvent *e) override { m_position = e->position(); } QPointF m_position; }; @@ -287,18 +269,16 @@ void tst_seatv4::simpleAxis() } struct Event // Because I didn't find a convenient way to copy it entirely { - Event() = default; - - const QPoint pixelDelta; - const QPoint angleDelta; // eights of a degree, positive is upwards, left + QPoint pixelDelta; + QPoint angleDelta; // eights of a degree, positive is upwards, left }; - QVector<Event> m_events; + QList<Event> m_events; }; WheelWindow window; QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial); - exec([=] { + exec([&] { Surface *surface = xdgSurface()->m_surface; pointer()->sendEnter(surface, {32, 32}); wl_client *client = surface->resource()->client(); @@ -322,7 +302,7 @@ void tst_seatv4::invalidPointerEvents() window.show(); QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial); - exec([=] { + exec([&] { auto *p = pointer(); auto *c = client(); // Purposefully send events without a wl_pointer.enter @@ -351,18 +331,18 @@ static bool supportsCursorSize(uint size, wl_shm *shm) return false; } -static bool supportsCursorSizes(const QVector<uint> &sizes) +static bool supportsCursorSizes(const QList<uint> &sizes) { auto *waylandIntegration = static_cast<QtWaylandClient::QWaylandIntegration *>(QGuiApplicationPrivate::platformIntegration()); wl_shm *shm = waylandIntegration->display()->shm()->object(); - return std::all_of(sizes.begin(), sizes.end(), [=](uint size) { + return std::all_of(sizes.begin(), sizes.end(), [&](uint size) { return supportsCursorSize(size, shm); }); } static uint defaultCursorSize() { const int xCursorSize = qEnvironmentVariableIntValue("XCURSOR_SIZE"); - return xCursorSize > 0 ? uint(xCursorSize) : 32; + return xCursorSize > 0 ? uint(xCursorSize) : 24; } void tst_seatv4::scaledCursor() @@ -384,15 +364,15 @@ void tst_seatv4::scaledCursor() window.show(); QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial); - exec([=] { pointer()->sendEnter(xdgSurface()->m_surface, {32, 32}); }); + exec([&] { pointer()->sendEnter(xdgSurface()->m_surface, {32, 32}); }); QCOMPOSITOR_TRY_VERIFY(cursorSurface()); QCOMPOSITOR_TRY_VERIFY(cursorSurface()->m_committed.buffer); QCOMPOSITOR_TRY_COMPARE(cursorSurface()->m_committed.bufferScale, 1); - QSize unscaledPixelSize = exec([=] { + QSize unscaledPixelSize = exec([&] { return cursorSurface()->m_committed.buffer->size(); }); - exec([=] { + exec([&] { auto *surface = cursorSurface(); surface->sendEnter(getAll<Output>()[1]); surface->sendLeave(getAll<Output>()[0]); @@ -412,7 +392,7 @@ void tst_seatv4::unscaledFallbackCursor() const int screens = 4; // with scales 1, 2, 4, 8 - exec([=] { + exec([&] { for (int i = 1; i < screens; ++i) { OutputData d; d.scale = int(qPow(2, i)); @@ -425,11 +405,11 @@ void tst_seatv4::unscaledFallbackCursor() window.resize(64, 64); window.show(); QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial); - exec([=] { pointer()->sendEnter(xdgSurface()->m_surface, {32, 32}); }); + exec([&] { pointer()->sendEnter(xdgSurface()->m_surface, {32, 32}); }); QCOMPOSITOR_TRY_VERIFY(cursorSurface()); QCOMPOSITOR_TRY_VERIFY(cursorSurface()->m_committed.buffer); QCOMPOSITOR_TRY_COMPARE(cursorSurface()->m_committed.bufferScale, 1); - QSize unscaledPixelSize = exec([=] { + QSize unscaledPixelSize = exec([&] { return cursorSurface()->m_committed.buffer->size(); }); @@ -437,7 +417,7 @@ void tst_seatv4::unscaledFallbackCursor() QCOMPARE(unscaledPixelSize.height(), int(defaultSize)); for (int i = 1; i < screens; ++i) { - exec([=] { + exec([&] { auto *surface = cursorSurface(); surface->sendEnter(getAll<Output>()[i]); surface->sendLeave(getAll<Output>()[i-1]); @@ -475,14 +455,14 @@ void tst_seatv4::bitmapCursor() window.show(); QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial); - exec([=] { pointer()->sendEnter(xdgSurface()->m_surface, {32, 32}); }); + exec([&] { pointer()->sendEnter(xdgSurface()->m_surface, {32, 32}); }); QCOMPOSITOR_TRY_VERIFY(cursorSurface()); QCOMPOSITOR_TRY_VERIFY(cursorSurface()->m_committed.buffer); QCOMPOSITOR_COMPARE(cursorSurface()->m_committed.buffer->size(), QSize(24, 24)); QCOMPOSITOR_COMPARE(cursorSurface()->m_committed.bufferScale, 1); QCOMPOSITOR_COMPARE(pointer()->m_hotspot, QPoint(12, 12)); - exec([=] { + exec([&] { auto *surface = cursorSurface(); surface->sendEnter(getAll<Output>()[1]); surface->sendLeave(getAll<Output>()[0]); @@ -521,14 +501,14 @@ void tst_seatv4::hidpiBitmapCursor() window.show(); QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial); - exec([=] { pointer()->sendEnter(xdgSurface()->m_surface, {32, 32}); }); + exec([&] { pointer()->sendEnter(xdgSurface()->m_surface, {32, 32}); }); QCOMPOSITOR_TRY_VERIFY(cursorSurface()); QCOMPOSITOR_TRY_VERIFY(cursorSurface()->m_committed.buffer); QCOMPOSITOR_COMPARE(cursorSurface()->m_committed.buffer->size(), QSize(48, 48)); QCOMPOSITOR_COMPARE(cursorSurface()->m_committed.bufferScale, 2); QCOMPOSITOR_COMPARE(pointer()->m_hotspot, QPoint(12, 12)); - exec([=] { + exec([&] { auto *surface = cursorSurface(); surface->sendEnter(getAll<Output>()[1]); surface->sendLeave(getAll<Output>()[0]); @@ -558,7 +538,7 @@ void tst_seatv4::hidpiBitmapCursorNonInt() window.show(); QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial); - exec([=] { pointer()->sendEnter(xdgSurface()->m_surface, {32, 32}); }); + exec([&] { pointer()->sendEnter(xdgSurface()->m_surface, {32, 32}); }); QCOMPOSITOR_TRY_VERIFY(cursorSurface()); QCOMPOSITOR_TRY_VERIFY(cursorSurface()->m_committed.buffer); QCOMPOSITOR_COMPARE(cursorSurface()->m_committed.buffer->size(), QSize(100, 100)); @@ -576,12 +556,12 @@ void tst_seatv4::animatedCursor() window.show(); QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial); - exec([=] { pointer()->sendEnter(xdgSurface()->m_surface, {32, 32}); }); + exec([&] { pointer()->sendEnter(xdgSurface()->m_surface, {32, 32}); }); QCOMPOSITOR_TRY_VERIFY(cursorSurface()); // We should get the first buffer without waiting for a frame callback QCOMPOSITOR_TRY_VERIFY(cursorSurface()->m_committed.buffer); - QSignalSpy bufferSpy(exec([=] { return cursorSurface(); }), &Surface::bufferCommitted); + QSignalSpy bufferSpy(exec([&] { return cursorSurface(); }), &Surface::bufferCommitted); exec([&] { // Make sure no extra buffers have arrived @@ -595,7 +575,7 @@ void tst_seatv4::animatedCursor() }); // Verify that we get a new cursor buffer - QTRY_COMPARE(bufferSpy.count(), 1); + QTRY_COMPARE(bufferSpy.size(), 1); } #endif // QT_CONFIG(cursor) diff --git a/tests/auto/client/seatv5/seatv5.pro b/tests/auto/client/seatv5/seatv5.pro deleted file mode 100644 index 2081845ef..000000000 --- a/tests/auto/client/seatv5/seatv5.pro +++ /dev/null @@ -1,4 +0,0 @@ -include (../shared/shared.pri) - -TARGET = tst_seatv5 -SOURCES += tst_seatv5.cpp diff --git a/tests/auto/client/seatv7/CMakeLists.txt b/tests/auto/client/seatv7/CMakeLists.txt new file mode 100644 index 000000000..cf3ade8c7 --- /dev/null +++ b/tests/auto/client/seatv7/CMakeLists.txt @@ -0,0 +1,13 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## tst_seatv7 Test: +##################################################################### + +qt_internal_add_test(tst_seatv7 + SOURCES + tst_seatv7.cpp + LIBRARIES + SharedClientTest +) diff --git a/tests/auto/client/seatv7/tst_seatv7.cpp b/tests/auto/client/seatv7/tst_seatv7.cpp new file mode 100644 index 000000000..f82b84b58 --- /dev/null +++ b/tests/auto/client/seatv7/tst_seatv7.cpp @@ -0,0 +1,129 @@ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "mockcompositor.h" +#include <QtGui/QRasterWindow> +#include <QtGui/QEventPoint> + +using namespace MockCompositor; + +class SeatCompositor : public DefaultCompositor { +public: + explicit SeatCompositor() + { + exec([this] { + m_config.autoConfigure = true; + + removeAll<Seat>(); + + uint capabilities = MockCompositor::Seat::capability_pointer | MockCompositor::Seat::capability_touch; + int version = 7; + add<Seat>(capabilities, version); + }); + } +}; + +class tst_seatv7 : public QObject, private SeatCompositor +{ + Q_OBJECT +private slots: + void cleanup() { QTRY_VERIFY2(isClean(), qPrintable(dirtyMessage())); } + void bindsToSeat(); + + // Pointer tests + void wheelDiscreteScroll_data(); + void wheelDiscreteScroll(); +}; + +void tst_seatv7::bindsToSeat() +{ + QCOMPOSITOR_COMPARE(get<Seat>()->resourceMap().size(), 1); + QCOMPOSITOR_COMPARE(get<Seat>()->resourceMap().first()->version(), 7); +} + +class WheelWindow : QRasterWindow { +public: + WheelWindow() + { + resize(64, 64); + show(); + } + void wheelEvent(QWheelEvent *event) override + { + QRasterWindow::wheelEvent(event); +// qDebug() << event << "angleDelta" << event->angleDelta() << "pixelDelta" << event->pixelDelta(); + + if (event->phase() != Qt::ScrollUpdate && event->phase() != Qt::NoScrollPhase) { + // Shouldn't have deltas in the these phases + QCOMPARE(event->angleDelta(), QPoint(0, 0)); + QCOMPARE(event->pixelDelta(), QPoint(0, 0)); + } + + // The axis vector of the event is already in surface space, so there is now way to tell + // whether it is inverted or not. + QCOMPARE(event->inverted(), false); + + // We didn't press any buttons + QCOMPARE(event->buttons(), Qt::NoButton); + + m_events.append(Event{event}); + } + struct Event // Because I didn't find a convenient way to copy it entirely + { + explicit Event() = default; + explicit Event(const QWheelEvent *event) + : phase(event->phase()) + , pixelDelta(event->pixelDelta()) + , angleDelta(event->angleDelta()) + , source(event->source()) + { + } + Qt::ScrollPhase phase{}; + QPoint pixelDelta; + QPoint angleDelta; // eights of a degree, positive is upwards, left + Qt::MouseEventSource source{}; + }; + QList<Event> m_events; +}; + +void tst_seatv7::wheelDiscreteScroll_data() +{ + QTest::addColumn<uint>("source"); + QTest::newRow("wheel") << uint(Pointer::axis_source_wheel); + QTest::newRow("wheel tilt") << uint(Pointer::axis_source_wheel_tilt); +} + +void tst_seatv7::wheelDiscreteScroll() +{ + WheelWindow window; + QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial); + + QFETCH(uint, source); + + exec([&] { + auto *p = pointer(); + auto *c = client(); + p->sendEnter(xdgToplevel()->surface(), {32, 32}); + p->sendFrame(c); + p->sendAxisSource(c, Pointer::axis_source(source)); + p->sendAxisDiscrete(c, Pointer::axis_vertical_scroll, 1); // 1 click downwards + p->sendAxis(c, Pointer::axis_vertical_scroll, 1.0); + p->sendFrame(c); + }); + + QTRY_VERIFY(!window.m_events.empty()); + { + auto e = window.m_events.takeFirst(); + QCOMPARE(e.phase, Qt::NoScrollPhase); + QVERIFY(qAbs(e.angleDelta.x()) <= qAbs(e.angleDelta.y())); // Vertical scroll + // According to the docs the angle delta is in eights of a degree and most mice have + // 1 click = 15 degrees. The angle delta should therefore be: + // 15 degrees / (1/8 eights per degrees) = 120 eights of degrees. + QCOMPARE(e.angleDelta, QPoint(0, -120)); + // Click scrolls are not continuous and should not have a pixel delta + QCOMPARE(e.pixelDelta, QPoint(0, 0)); + } +} + +QCOMPOSITOR_TEST_MAIN(tst_seatv7) +#include "tst_seatv7.moc" diff --git a/tests/auto/client/shared/CMakeLists.txt b/tests/auto/client/shared/CMakeLists.txt new file mode 100644 index 000000000..1d64f2956 --- /dev/null +++ b/tests/auto/client/shared/CMakeLists.txt @@ -0,0 +1,73 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +##Client test shared components: +##################################################################### + +qt_manual_moc(moc_files + mockcompositor.h + coreprotocol.h + corecompositor.h + datadevice.h + fullscreenshellv1.h + fractionalscalev1.h + iviapplication.h + textinput.h + qttextinput.h + viewport.h + xdgdialog.h + xdgoutputv1.h + xdgshell.h +) + +add_library(SharedClientTest + OBJECT + corecompositor.cpp corecompositor.h + coreprotocol.cpp coreprotocol.h + datadevice.cpp datadevice.h + fullscreenshellv1.cpp fullscreenshellv1.h + fractionalscalev1.cpp fractionalscalev1.h + iviapplication.cpp iviapplication.h + mockcompositor.cpp mockcompositor.h + textinput.cpp textinput.h + qttextinput.cpp qttextinput.h + xdgoutputv1.cpp xdgoutputv1.h + xdgshell.cpp xdgshell.h + xdgdialog.cpp xdgdialog.h + viewport.cpp viewport.h + ${moc_files} +) + +qt6_generate_wayland_protocol_server_sources(SharedClientTest + FILES + ${PROJECT_SOURCE_DIR}/src/3rdparty/protocol/cursor-shape-v1.xml + ${PROJECT_SOURCE_DIR}/src/3rdparty/protocol/fullscreen-shell-unstable-v1.xml + ${PROJECT_SOURCE_DIR}/src/3rdparty/protocol/ivi-application.xml + ${PROJECT_SOURCE_DIR}/src/3rdparty/protocol/wp-primary-selection-unstable-v1.xml + ${PROJECT_SOURCE_DIR}/src/3rdparty/protocol/tablet-unstable-v2.xml + ${PROJECT_SOURCE_DIR}/src/3rdparty/protocol/text-input-unstable-v2.xml + ${PROJECT_SOURCE_DIR}/src/extensions/qt-text-input-method-unstable-v1.xml + ${PROJECT_SOURCE_DIR}/src/3rdparty/protocol/fractional-scale-v1.xml + ${PROJECT_SOURCE_DIR}/src/3rdparty/protocol/viewporter.xml + ${PROJECT_SOURCE_DIR}/src/3rdparty/protocol/wayland.xml + ${PROJECT_SOURCE_DIR}/src/3rdparty/protocol/xdg-decoration-unstable-v1.xml + ${PROJECT_SOURCE_DIR}/src/3rdparty/protocol/xdg-dialog-v1.xml + ${PROJECT_SOURCE_DIR}/src/3rdparty/protocol/xdg-output-unstable-v1.xml + ${PROJECT_SOURCE_DIR}/src/3rdparty/protocol/xdg-shell.xml +) + +if(QT_FEATURE_opengl) + set(optional_libraries Qt::OpenGL) +endif() + +target_link_libraries(SharedClientTest + PUBLIC + Qt::Gui + ${optional_libraries} + Qt::WaylandClientPrivate + Wayland::Server + Threads::Threads # special case +) + +target_include_directories(SharedClientTest PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/tests/auto/client/shared/corecompositor.cpp b/tests/auto/client/shared/corecompositor.cpp index 5c6c83baa..d110768ec 100644 --- a/tests/auto/client/shared/corecompositor.cpp +++ b/tests/auto/client/shared/corecompositor.cpp @@ -1,38 +1,14 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "corecompositor.h" +#include <thread> namespace MockCompositor { -CoreCompositor::CoreCompositor() - : m_display(wl_display_create()) - , m_socketName(wl_display_add_socket_auto(m_display)) +CoreCompositor::CoreCompositor(CompositorType t, int socketFd) + : m_type(t) + , m_display(wl_display_create()) , m_eventLoop(wl_display_get_event_loop(m_display)) // Start dispatching @@ -43,7 +19,12 @@ CoreCompositor::CoreCompositor() } }) { - qputenv("WAYLAND_DISPLAY", m_socketName); + if (socketFd == -1) { + QByteArray socketName = wl_display_add_socket_auto(m_display); + qputenv("WAYLAND_DISPLAY", socketName); + } else { + wl_display_add_socket_fd(m_display, socketFd); + } m_timer.start(); Q_ASSERT(isClean()); } @@ -52,13 +33,15 @@ CoreCompositor::~CoreCompositor() { m_running = false; m_dispatchThread.join(); + wl_display_destroy_clients(m_display); wl_display_destroy(m_display); + qDebug() << "cleanup"; } bool CoreCompositor::isClean() { Lock lock(this); - for (auto *global : qAsConst(m_globals)) { + for (auto *global : std::as_const(m_globals)) { if (!global->isClean()) return false; } @@ -69,18 +52,17 @@ QString CoreCompositor::dirtyMessage() { Lock lock(this); QStringList messages; - for (auto *global : qAsConst(m_globals)) { + for (auto *global : std::as_const(m_globals)) { if (!global->isClean()) messages << (global->metaObject()->className() % QLatin1String(": ") % global->dirtyMessage()); } return messages.join(", "); } -void CoreCompositor::dispatch() +void CoreCompositor::dispatch(int timeout) { Lock lock(this); wl_display_flush_clients(m_display); - constexpr int timeout = 0; // immediate return wl_event_loop_dispatch(m_eventLoop, timeout); } diff --git a/tests/auto/client/shared/corecompositor.h b/tests/auto/client/shared/corecompositor.h index 254465ee6..2df1b5758 100644 --- a/tests/auto/client/shared/corecompositor.h +++ b/tests/auto/client/shared/corecompositor.h @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef MOCKCOMPOSITOR_CORECOMPOSITOR_H #define MOCKCOMPOSITOR_CORECOMPOSITOR_H @@ -48,11 +23,18 @@ public: class CoreCompositor { public: - explicit CoreCompositor(); + enum CompositorType { + Default, + Legacy // wl-shell + }; + + CompositorType m_type = Default; + explicit CoreCompositor(CompositorType t = Default, int socketFd = -1); + ~CoreCompositor(); bool isClean(); QString dirtyMessage(); - void dispatch(); + void dispatch(int timeout = 0); template<typename function_type, typename... arg_types> auto exec(function_type func, arg_types&&... args) -> decltype(func()) @@ -117,7 +99,7 @@ public: global_type *get() { warnIfNotLockedByThread(Q_FUNC_INFO); - for (auto *global : qAsConst(m_globals)) { + for (auto *global : std::as_const(m_globals)) { if (auto *casted = qobject_cast<global_type *>(global)) return casted; } @@ -131,7 +113,7 @@ public: global_type *get(int index) { warnIfNotLockedByThread(Q_FUNC_INFO); - for (auto *global : qAsConst(m_globals)) { + for (auto *global : std::as_const(m_globals)) { if (auto *casted = qobject_cast<global_type *>(global)) { if (index--) continue; @@ -145,11 +127,11 @@ public: * \brief Returns all globals with the given type, if any */ template<typename global_type> - QVector<global_type *> getAll() + QList<global_type *> getAll() { warnIfNotLockedByThread(Q_FUNC_INFO); - QVector<global_type *> matching; - for (auto *global : qAsConst(m_globals)) { + QList<global_type *> matching; + for (auto *global : std::as_const(m_globals)) { if (auto *casted = qobject_cast<global_type *>(global)) matching.append(casted); } @@ -164,6 +146,7 @@ public: public: // Only use this carefully from the test thread (i.e. lock first) wl_display *m_display = nullptr; + protected: class Lock { public: @@ -196,10 +179,9 @@ protected: CoreCompositor *m_compositor = nullptr; std::thread::id m_threadId; }; - QByteArray m_socketName; wl_event_loop *m_eventLoop = nullptr; bool m_running = true; - QVector<Global *> m_globals; + QList<Global *> m_globals; QElapsedTimer m_timer; private: diff --git a/tests/auto/client/shared/coreprotocol.cpp b/tests/auto/client/shared/coreprotocol.cpp index b0be2cb4e..833ad4b09 100644 --- a/tests/auto/client/shared/coreprotocol.cpp +++ b/tests/auto/client/shared/coreprotocol.cpp @@ -1,36 +1,26 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "coreprotocol.h" #include "datadevice.h" namespace MockCompositor { +Surface::Surface(WlCompositor *wlCompositor, wl_client *client, int id, int version) + : QtWaylandServer::wl_surface(client, id, version) + , m_wlCompositor(wlCompositor) + , m_wlshell(wlCompositor->m_compositor->m_type == CoreCompositor::CompositorType::Legacy) +{ +} + +Surface::~Surface() +{ + // TODO: maybe make sure buffers are released? + qDeleteAll(m_commits); + if (m_wlShellSurface) + m_wlShellSurface->m_surface = nullptr; +} + void Surface::sendFrameCallbacks() { uint time = m_wlCompositor->m_compositor->currentTimeMilliseconds(); @@ -55,6 +45,11 @@ void Surface::sendLeave(Output *output) wl_surface::send_leave(resource()->handle, outputResource->handle); } +void Surface::map() +{ + m_mapped = true; +} + void Surface::surface_destroy_resource(Resource *resource) { Q_UNUSED(resource); @@ -65,14 +60,29 @@ void Surface::surface_destroy_resource(Resource *resource) delete this; } +void Surface::surface_destroy(Resource *resource) +{ + if (m_wlShellSurface) // on wl-shell the shell surface is automatically destroyed with the surface + wl_resource_destroy(m_wlShellSurface->resource()->handle); + Q_ASSERT(!m_wlShellSurface); + wl_resource_destroy(resource->handle); +} + void Surface::surface_attach(Resource *resource, wl_resource *buffer, int32_t x, int32_t y) { Q_UNUSED(resource); - QPoint offset(x, y); - m_pending.buffer = fromResource<Buffer>(buffer); - m_pending.commitSpecific.attachOffset = offset; - m_pending.commitSpecific.attached = true; - emit attach(buffer, offset); + if (m_wlshell) { + m_buffer = buffer; + if (!buffer) + m_image = QImage(); + } else { + QPoint offset(x, y); + m_pending.buffer = fromResource<Buffer>(buffer); + m_pending.commitSpecific.attachOffset = offset; + m_pending.commitSpecific.attached = true; + + emit attach(buffer, offset); + } } void Surface::surface_set_buffer_scale(QtWaylandServer::wl_surface::Resource *resource, int32_t scale) @@ -84,32 +94,63 @@ void Surface::surface_set_buffer_scale(QtWaylandServer::wl_surface::Resource *re void Surface::surface_commit(Resource *resource) { Q_UNUSED(resource); - m_committed = m_pending; - m_commits.append(new DoubleBufferedState(m_committed)); - if (auto *frame = m_pending.commitSpecific.frame) - m_waitingFrameCallbacks.append(frame); + if (m_wlshell) { + if (m_buffer) { + struct ::wl_shm_buffer *shm_buffer = wl_shm_buffer_get(m_buffer); + if (shm_buffer) { + int stride = wl_shm_buffer_get_stride(shm_buffer); + uint format = wl_shm_buffer_get_format(shm_buffer); + Q_UNUSED(format); + void *data = wl_shm_buffer_get_data(shm_buffer); + const uchar *char_data = static_cast<const uchar *>(data); + QImage img(char_data, wl_shm_buffer_get_width(shm_buffer), wl_shm_buffer_get_height(shm_buffer), stride, QImage::Format_ARGB32_Premultiplied); + m_image = img; + } + } + + for (wl_resource *frameCallback : std::exchange(m_frameCallbackList, {})) { + auto time = m_wlCompositor->m_compositor->currentTimeMilliseconds(); + wl_callback_send_done(frameCallback, time); + wl_resource_destroy(frameCallback); + } + } else { + m_committed = m_pending; + m_commits.append(new DoubleBufferedState(m_committed)); + + if (auto *frame = m_pending.commitSpecific.frame) + m_waitingFrameCallbacks.append(frame); - m_pending.commitSpecific = PerCommitData(); - emit commit(); - if (m_committed.commitSpecific.attached) - emit bufferCommitted(); + m_pending.commitSpecific = PerCommitData(); + emit commit(); + if (m_committed.commitSpecific.attached) + emit bufferCommitted(); + } } void Surface::surface_frame(Resource *resource, uint32_t callback) { - // Although valid, there is really no point having multiple frame requests in the same commit. - // Make sure we don't do it - QCOMPARE(m_pending.commitSpecific.frame, nullptr); + if (m_wlshell) { + wl_resource *frameCallback = wl_resource_create(resource->client(), &wl_callback_interface, 1, callback); + m_frameCallbackList << frameCallback; + } else { + // Although valid, there is really no point having multiple frame requests in the same commit. + // Make sure we don't do it + QCOMPARE(m_pending.commitSpecific.frame, nullptr); - auto *frame = new Callback(resource->client(), callback, 1); - m_pending.commitSpecific.frame = frame; + auto *frame = new Callback(resource->client(), callback, 1); + m_pending.commitSpecific.frame = frame; + } } bool WlCompositor::isClean() { - for (auto *surface : qAsConst(m_surfaces)) { - if (!CursorRole::fromSurface(surface)) - return false; + for (auto *surface : std::as_const(m_surfaces)) { + if (!CursorRole::fromSurface(surface)) { + if (m_compositor->m_type != CoreCompositor::CompositorType::Legacy) + return false; + if (surface->isMapped()) + return false; + } } return true; } @@ -119,7 +160,7 @@ QString WlCompositor::dirtyMessage() if (isClean()) return "clean"; QStringList messages; - for (auto *s : qAsConst(m_surfaces)) { + for (auto *s : std::as_const(m_surfaces)) { QString role = s->m_role ? s->m_role->staticMetaObject.className(): "none/unknown"; messages << "Surface with role: " + role; } @@ -158,6 +199,14 @@ void Output::sendScale(Resource *resource) wl_output::send_scale(resource->handle, m_data.scale); } +void Output::sendDone(wl_client *client) +{ + Q_ASSERT(m_version >= WL_OUTPUT_DONE_SINCE_VERSION); + auto resources = resourceMap().values(client); + for (auto *r : resources) + wl_output::send_done(r->handle); +} + void Output::sendDone() { Q_ASSERT(m_version >= WL_OUTPUT_DONE_SINCE_VERSION); @@ -177,6 +226,8 @@ void Output::output_bind_resource(QtWaylandServer::wl_output::Resource *resource if (m_version >= WL_OUTPUT_DONE_SINCE_VERSION) wl_output::send_done(resource->handle); + + Q_EMIT outputBound(resource); } // Seat stuff @@ -287,12 +338,13 @@ uint Pointer::sendEnter(Surface *surface, const QPointF &position) uint serial = m_seat->m_compositor->nextSerial(); m_enterSerials << serial; - m_cursorRole = nullptr; // According to the protocol, the pointer image is undefined after enter + m_cursorRole.clear(); // According to the protocol, the pointer image is undefined after enter wl_client *client = surface->resource()->client(); const auto pointerResources = resourceMap().values(client); - for (auto *r : pointerResources) + for (auto *r : pointerResources) { wl_pointer::send_enter(r->handle, serial, surface->resource()->handle, x ,y); + } return serial; } @@ -373,18 +425,36 @@ void Pointer::sendFrame(wl_client *client) send_frame(r->handle); } +void Pointer::sendAxisValue120(wl_client *client, QtWaylandServer::wl_pointer::axis axis, int value120) +{ + const auto pointerResources = resourceMap().values(client); + for (auto *r : pointerResources) + send_axis_value120(r->handle, axis, value120); +} + +void Pointer::sendAxisRelativeDirection(wl_client *client, QtWaylandServer::wl_pointer::axis axis, QtWaylandServer::wl_pointer::axis_relative_direction direction) +{ + const auto pointerResources = resourceMap().values(client); + for (auto *r : pointerResources) + send_axis_relative_direction(r->handle, axis, direction); +} + void Pointer::pointer_set_cursor(Resource *resource, uint32_t serial, wl_resource *surface, int32_t hotspot_x, int32_t hotspot_y) { Q_UNUSED(resource); - auto *s = fromResource<Surface>(surface); - QVERIFY(s); - if (s->m_role) { - m_cursorRole = CursorRole::fromSurface(s); - QVERIFY(m_cursorRole); + if (!surface) { + m_cursorRole = nullptr; } else { - m_cursorRole = new CursorRole(s); //TODO: make sure we don't leak CursorRole - s->m_role = m_cursorRole; + auto *s = fromResource<Surface>(surface); + QVERIFY(s); + if (s->m_role) { + m_cursorRole = CursorRole::fromSurface(s); + QVERIFY(m_cursorRole); + } else { + m_cursorRole = new CursorRole(s); //TODO: make sure we don't leak CursorRole + s->m_role = m_cursorRole; + } } // Directly checking the last serial would be racy, we may just have sent leaves/enters which @@ -443,6 +513,13 @@ void Touch::sendFrame(wl_client *client) send_frame(r->handle); } +void Touch::sendCancel(wl_client *client) +{ + const auto touchResources = resourceMap().values(client); + for (auto *r : touchResources) + send_cancel(r->handle); +} + uint Keyboard::sendEnter(Surface *surface) { auto serial = m_seat->m_compositor->nextSerial(); @@ -471,13 +548,14 @@ uint Keyboard::sendKey(wl_client *client, uint key, uint state) auto time = m_seat->m_compositor->currentTimeMilliseconds(); uint serial = m_seat->m_compositor->nextSerial(); const auto pointerResources = resourceMap().values(client); - for (auto *r : pointerResources) + for (auto *r : pointerResources) { send_key(r->handle, serial, time, key, state); + } return serial; } // Shm implementation -Shm::Shm(CoreCompositor *compositor, QVector<format> formats, int version) +Shm::Shm(CoreCompositor *compositor, QList<format> formats, int version) : QtWaylandServer::wl_shm(compositor->m_display, version) , m_compositor(compositor) , m_formats(formats) @@ -489,7 +567,7 @@ Shm::Shm(CoreCompositor *compositor, QVector<format> formats, int version) bool Shm::isClean() { -// for (ShmPool *pool : qAsConst(m_pools)) { +// for (ShmPool *pool : std::as_const(m_pools)) { // //TODO: return false if not cursor buffer // if (pool->m_buffers.isEmpty()) { // return false; @@ -526,4 +604,38 @@ void ShmPool::shm_pool_destroy_resource(Resource *resource) delete this; } +WlShell::WlShell(CoreCompositor *compositor, int version) + : QtWaylandServer::wl_shell(compositor->m_display, version) + , m_compositor(compositor) +{ +} + +void WlShell::shell_get_shell_surface(Resource *resource, uint32_t id, wl_resource *surface) +{ + auto *s = fromResource<Surface>(surface); + auto *wlShellSurface = new WlShellSurface(this, resource->client(), id, s); + m_wlShellSurfaces << wlShellSurface; + emit wlShellSurfaceCreated(wlShellSurface); +} + +WlShellSurface::WlShellSurface(WlShell *wlShell, wl_client *client, int id, Surface *surface) + : QtWaylandServer::wl_shell_surface(client, id, 1) + , m_wlShell(wlShell) + , m_surface(surface) +{ + surface->m_wlShellSurface = this; + surface->map(); +} + +WlShellSurface::~WlShellSurface() +{ + if (m_surface) + m_surface->m_wlShellSurface = nullptr; +} + +void WlShellSurface::sendConfigure(uint32_t edges, int32_t width, int32_t height) +{ + wl_shell_surface::send_configure(edges, width, height); +} + } // namespace MockCompositor diff --git a/tests/auto/client/shared/coreprotocol.h b/tests/auto/client/shared/coreprotocol.h index a12d22d36..0f59441a3 100644 --- a/tests/auto/client/shared/coreprotocol.h +++ b/tests/auto/client/shared/coreprotocol.h @@ -1,41 +1,20 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef MOCKCOMPOSITOR_COREPROTOCOL_H #define MOCKCOMPOSITOR_COREPROTOCOL_H #include "corecompositor.h" +#include <QtCore/qpointer.h> + #include <qwayland-server-wayland.h> namespace MockCompositor { class WlCompositor; +class WlShell; +class WlShellSurface; class Output; class Pointer; class Touch; @@ -96,18 +75,18 @@ class Surface : public QObject, public QtWaylandServer::wl_surface { Q_OBJECT public: - explicit Surface(WlCompositor *wlCompositor, wl_client *client, int id, int version) - : QtWaylandServer::wl_surface(client, id, version) - , m_wlCompositor(wlCompositor) - { - } - ~Surface() override { qDeleteAll(m_commits); } // TODO: maybe make sure buffers are released? + explicit Surface(WlCompositor *wlCompositor, wl_client *client, int id, int version); + ~Surface() override; void sendFrameCallbacks(); void sendEnter(Output *output); void send_enter(::wl_resource *output) = delete; void sendLeave(Output *output); void send_leave(::wl_resource *output) = delete; + void map(); + bool isMapped() const { return m_mapped; } + WlShellSurface *wlShellSurface() const { return m_wlShellSurface; } + WlCompositor *m_wlCompositor; struct PerCommitData { Callback *frame = nullptr; @@ -120,11 +99,19 @@ public: uint configureSerial = 0; int bufferScale = 1; } m_pending, m_committed; - QVector<DoubleBufferedState *> m_commits; - QVector<Callback *> m_waitingFrameCallbacks; - QVector<Output *> m_outputs; + QList<DoubleBufferedState *> m_commits; + QList<Callback *> m_waitingFrameCallbacks; + QList<Output *> m_outputs; SurfaceRole *m_role = nullptr; + WlShellSurface *m_wlShellSurface = nullptr; + bool m_mapped = false; + QList<wl_resource *> m_frameCallbackList; + + wl_resource *m_buffer = nullptr; + QImage m_image; // checking backingStore + bool m_wlshell = false; + signals: void attach(void *buffer, QPoint offset); void commit(); @@ -132,24 +119,39 @@ signals: protected: void surface_destroy_resource(Resource *resource) override; - void surface_destroy(Resource *resource) override { wl_resource_destroy(resource->handle); } + void surface_destroy(Resource *resource) override; void surface_attach(Resource *resource, wl_resource *buffer, int32_t x, int32_t y) override; void surface_set_buffer_scale(Resource *resource, int32_t scale) override; void surface_commit(Resource *resource) override; void surface_frame(Resource *resource, uint32_t callback) override; }; +class Region : public QtWaylandServer::wl_region +{ +public: + explicit Region(wl_client *client, int id, int version) + : QtWaylandServer::wl_region(client, id, version) + { + } + + void region_destroy_resource(Resource *resource) override + { + Q_UNUSED(resource); + delete this; + } +}; + class WlCompositor : public Global, public QtWaylandServer::wl_compositor { Q_OBJECT public: - explicit WlCompositor(CoreCompositor *compositor, int version = 3) + explicit WlCompositor(CoreCompositor *compositor, int version = 4) : QtWaylandServer::wl_compositor(compositor->m_display, version) , m_compositor(compositor) {} bool isClean() override; QString dirtyMessage() override; - QVector<Surface *> m_surfaces; + QList<Surface *> m_surfaces; CoreCompositor *m_compositor = nullptr; signals: @@ -162,6 +164,41 @@ protected: m_surfaces.append(surface); emit surfaceCreated(surface); } + + void compositor_create_region(Resource *resource, uint32_t id) override + { + new Region(resource->client(), id, resource->version()); + } +}; + +class WlShell : public Global, public QtWaylandServer::wl_shell +{ + Q_OBJECT +public: + explicit WlShell(CoreCompositor *compositor, int version = 1); + QList<WlShellSurface *> m_wlShellSurfaces; + CoreCompositor *m_compositor = nullptr; + +signals: + void wlShellSurfaceCreated(WlShellSurface *wlShellSurface); + +protected: + void shell_get_shell_surface(Resource *resource, uint32_t id, ::wl_resource *surface) override; +}; + +class WlShellSurface : public QObject, public QtWaylandServer::wl_shell_surface +{ + Q_OBJECT +public: + explicit WlShellSurface(WlShell *wlShell, wl_client *client, int id, Surface *surface); + ~WlShellSurface() override; + void sendConfigure(uint32_t edges, int32_t width, int32_t height); + void send_configure(uint32_t edges, int32_t width, int32_t height) = delete; + + void shell_surface_destroy_resource(Resource *) override { delete this; } + + WlShell *m_wlShell = nullptr; + Surface *m_surface = nullptr; }; class Subsurface : public QObject, public QtWaylandServer::wl_subsurface @@ -181,7 +218,7 @@ public: explicit SubCompositor(CoreCompositor *compositor, int version = 1) : QtWaylandServer::wl_subcompositor(compositor->m_display, version) {} - QVector<Subsurface *> m_subsurfaces; + QList<Subsurface *> m_subsurfaces; signals: void subsurfaceCreated(Subsurface *subsurface); @@ -245,6 +282,7 @@ public: void sendScale(int factor); void sendScale(Resource *resource); // Sends current scale to only one client + void sendDone(wl_client *client); void sendDone(); int scale() const { return m_data.scale; } @@ -252,6 +290,9 @@ public: OutputData m_data; int m_version = 1; // TODO: remove on libwayland upgrade +Q_SIGNALS: + void outputBound(Resource *resource); + protected: void output_bind_resource(Resource *resource) override; }; @@ -260,7 +301,7 @@ class Seat : public Global, public QtWaylandServer::wl_seat { Q_OBJECT public: - explicit Seat(CoreCompositor *compositor, uint capabilities = Seat::capability_pointer | Seat::capability_keyboard | Seat::capability_touch, int version = 5); + explicit Seat(CoreCompositor *compositor, uint capabilities = Seat::capability_pointer | Seat::capability_keyboard | Seat::capability_touch, int version = 9); ~Seat() override; void send_capabilities(Resource *resource, uint capabilities) = delete; // Use wrapper instead void send_capabilities(uint capabilities) = delete; // Use wrapper instead @@ -269,13 +310,13 @@ public: CoreCompositor *m_compositor = nullptr; Pointer* m_pointer = nullptr; - QVector<Pointer *> m_oldPointers; + QList<Pointer *> m_oldPointers; Touch* m_touch = nullptr; - QVector<Touch *> m_oldTouchs; + QList<Touch *> m_oldTouchs; Keyboard* m_keyboard = nullptr; - QVector<Keyboard *> m_oldKeyboards; + QList<Keyboard *> m_oldKeyboards; uint m_capabilities = 0; @@ -298,7 +339,7 @@ class Pointer : public QObject, public QtWaylandServer::wl_pointer public: explicit Pointer(Seat *seat) : m_seat(seat) {} Surface *cursorSurface(); - CursorRole* m_cursorRole = nullptr; //TODO: cleanup + QPointer<CursorRole> m_cursorRole; void send_enter() = delete; uint sendEnter(Surface *surface, const QPointF &position); void send_leave() = delete; @@ -310,9 +351,11 @@ public: void sendAxisSource(wl_client *client, axis_source source); void sendAxisStop(wl_client *client, axis axis); void sendFrame(wl_client *client); + void sendAxisValue120(wl_client *client, axis axis, int value120); + void sendAxisRelativeDirection(wl_client *client, axis axis, axis_relative_direction direction); Seat *m_seat = nullptr; - QVector<uint> m_enterSerials; + QList<uint> m_enterSerials; QPoint m_hotspot; signals: @@ -329,6 +372,7 @@ public: explicit CursorRole(Surface *surface) // TODO: needs some more args : m_surface(surface) { + connect(m_surface, &QObject::destroyed, this, &QObject::deleteLater); } static CursorRole *fromSurface(Surface *surface) { return qobject_cast<CursorRole *>(surface->m_role); } Surface *m_surface = nullptr; @@ -343,6 +387,7 @@ public: uint sendUp(wl_client *client, int id); void sendMotion(wl_client *client, const QPointF &position, int id); void sendFrame(wl_client *client); + void sendCancel(wl_client *client); Seat *m_seat = nullptr; }; @@ -364,17 +409,17 @@ class Shm : public Global, public QtWaylandServer::wl_shm { Q_OBJECT public: - explicit Shm(CoreCompositor *compositor, QVector<format> formats = {format_argb8888, format_xrgb8888, format_rgb888}, int version = 1); + explicit Shm(CoreCompositor *compositor, QList<format> formats = {format_argb8888, format_xrgb8888, format_rgb888}, int version = 1); bool isClean() override; CoreCompositor *m_compositor = nullptr; - QVector<ShmPool *> m_pools; - const QVector<format> m_formats; + QList<ShmPool *> m_pools; + const QList<format> m_formats; protected: void shm_create_pool(Resource *resource, uint32_t id, int32_t fd, int32_t size) override; void shm_bind_resource(Resource *resource) override { - for (auto format : qAsConst(m_formats)) + for (auto format : std::as_const(m_formats)) send_format(resource->handle, format); } }; @@ -385,7 +430,7 @@ class ShmPool : QObject, public QtWaylandServer::wl_shm_pool public: explicit ShmPool(Shm *shm, wl_client *client, int id, int version = 1); Shm *m_shm = nullptr; - QVector<ShmBuffer *> m_buffers; + QList<ShmBuffer *> m_buffers; protected: void shm_pool_create_buffer(Resource *resource, uint32_t id, int32_t offset, int32_t width, int32_t height, int32_t stride, uint32_t format) override; diff --git a/tests/auto/client/shared/datadevice.cpp b/tests/auto/client/shared/datadevice.cpp index dfa18952c..efb88d0b1 100644 --- a/tests/auto/client/shared/datadevice.cpp +++ b/tests/auto/client/shared/datadevice.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "datadevice.h" @@ -32,7 +7,7 @@ namespace MockCompositor { bool DataDeviceManager::isClean() { - for (auto *device : qAsConst(m_dataDevices)) { + for (auto *device : std::as_const(m_dataDevices)) { // The client should not leak selection offers, i.e. if this fails, there is a missing // data_offer.destroy request if (!device->m_sentSelectionOffers.empty()) @@ -60,6 +35,11 @@ void DataDeviceManager::data_device_manager_get_data_device(Resource *resource, device->add(resource->client(), id, resource->version()); } +void DataDeviceManager::data_device_manager_create_data_source(Resource *resource, uint32_t id) +{ + new QtWaylandServer::wl_data_source(resource->client(), id, 1); +} + DataDevice::~DataDevice() { // If the client(s) hasn't deleted the wayland object, just ignore subsequent events @@ -71,6 +51,7 @@ DataOffer *DataDevice::sendDataOffer(wl_client *client, const QStringList &mimeT { Q_ASSERT(client); auto *offer = new DataOffer(this, client, m_manager->m_version); + m_offer = offer; for (auto *resource : resourceMap().values(client)) wl_data_device::send_data_offer(resource->handle, offer->resource()->handle); for (const auto &mimeType : mimeTypes) @@ -86,6 +67,33 @@ void DataDevice::sendSelection(DataOffer *offer) m_sentSelectionOffers << offer; } +void DataDevice::sendEnter(Surface *surface, const QPoint &position) +{ + uint serial = m_manager->m_compositor->nextSerial(); + Resource *resource = resourceMap().value(surface->resource()->client()); + if (m_offer) + wl_data_device::send_enter(resource->handle, serial, surface->resource()->handle, position.x(), position.y(), m_offer->resource()->handle); +} + +void DataDevice::sendMotion(Surface *surface, const QPoint &position) +{ + uint32_t time = m_manager->m_compositor->nextSerial(); + Resource *resource = resourceMap().value(surface->resource()->client()); + wl_data_device::send_motion(resource->handle, time, position.x(), position.y()); +} + +void DataDevice::sendDrop(Surface *surface) +{ + Resource *resource = resourceMap().value(surface->resource()->client()); + wl_data_device::send_drop(resource->handle); +} + +void DataDevice::sendLeave(Surface *surface) +{ + Resource *resource = resourceMap().value(surface->resource()->client()); + wl_data_device::send_leave(resource->handle); +} + void DataOffer::data_offer_destroy_resource(Resource *resource) { Q_UNUSED(resource); @@ -100,8 +108,7 @@ void DataOffer::data_offer_receive(Resource *resource, const QString &mime_type, void DataOffer::data_offer_destroy(QtWaylandServer::wl_data_offer::Resource *resource) { - bool removed = m_dataDevice->m_sentSelectionOffers.removeOne(this); - QVERIFY(removed); + m_dataDevice->m_sentSelectionOffers.removeOne(this); wl_resource_destroy(resource->handle); } diff --git a/tests/auto/client/shared/datadevice.h b/tests/auto/client/shared/datadevice.h index 98e780b22..356dfa74a 100644 --- a/tests/auto/client/shared/datadevice.h +++ b/tests/auto/client/shared/datadevice.h @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef MOCKCOMPOSITOR_DATADEVICE_H #define MOCKCOMPOSITOR_DATADEVICE_H @@ -43,6 +18,7 @@ public: explicit DataDeviceManager(CoreCompositor *compositor, int version = 1) : QtWaylandServer::wl_data_device_manager(compositor->m_display, version) , m_version(version) + , m_compositor(compositor) {} ~DataDeviceManager() override { qDeleteAll(m_dataDevices); } bool isClean() override; @@ -50,13 +26,16 @@ public: int m_version = 1; // TODO: remove on libwayland upgrade QMap<Seat *, DataDevice *> m_dataDevices; + CoreCompositor *m_compositor; protected: void data_device_manager_get_data_device(Resource *resource, uint32_t id, ::wl_resource *seatResource) override; + void data_device_manager_create_data_source(Resource *resource, uint32_t id) override; }; -class DataDevice : public QtWaylandServer::wl_data_device +class DataDevice : public QObject, public QtWaylandServer::wl_data_device { + Q_OBJECT public: explicit DataDevice(DataDeviceManager *manager, Seat *seat) : m_manager(manager) @@ -69,11 +48,37 @@ public: void send_selection(::wl_resource *resource) = delete; void sendSelection(DataOffer *offer); + void send_enter(uint32_t serial, ::wl_resource *surface, wl_fixed_t x, wl_fixed_t y, ::wl_resource *id) = delete; + void sendEnter(Surface *surface, const QPoint& position); + + void send_motion(uint32_t time, wl_fixed_t x, wl_fixed_t y) = delete; + void sendMotion(Surface *surface, const QPoint &position); + + void send_drop(::wl_resource *resource) = delete; + void sendDrop(Surface *surface); + + void send_leave(::wl_resource *resource) = delete; + void sendLeave(Surface *surface); + DataDeviceManager *m_manager = nullptr; Seat *m_seat = nullptr; - QVector<DataOffer *> m_sentSelectionOffers; + QList<DataOffer *> m_sentSelectionOffers; + QPointer<DataOffer> m_offer; + +signals: + void dragStarted(); protected: + void data_device_start_drag(Resource *resource, ::wl_resource *source, ::wl_resource *origin, ::wl_resource *icon, uint32_t serial) override + { + Q_UNUSED(resource); + Q_UNUSED(source); + Q_UNUSED(origin); + Q_UNUSED(icon); + Q_UNUSED(serial); + emit dragStarted(); + } + void data_device_release(Resource *resource) override { int removed = m_manager->m_dataDevices.remove(m_seat); diff --git a/tests/auto/client/shared/fractionalscalev1.cpp b/tests/auto/client/shared/fractionalscalev1.cpp new file mode 100644 index 000000000..28c778025 --- /dev/null +++ b/tests/auto/client/shared/fractionalscalev1.cpp @@ -0,0 +1,40 @@ +// Copyright (C) 2022 David Edmundson <davidedmundson@kde.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "fractionalscalev1.h" + +namespace MockCompositor { + +FractionalScaleManager::FractionalScaleManager(CoreCompositor *compositor, int version) + : QtWaylandServer::wp_fractional_scale_manager_v1(compositor->m_display, version) +{ +} + +void FractionalScaleManager::wp_fractional_scale_manager_v1_get_fractional_scale(Resource *resource, uint32_t id, wl_resource *surface) +{ + auto *s = fromResource<Surface>(surface); + auto *scaler = new FractionalScale(s, resource->client(), id, resource->version()); + connect(scaler, &QObject::destroyed, this, [this, scaler]() { + m_fractionalScales.removeOne(scaler); + }); + m_fractionalScales << scaler; +} + +FractionalScale::FractionalScale(Surface *surface, wl_client *client, int id, int version) + : QtWaylandServer::wp_fractional_scale_v1(client, id, version) + , m_surface(surface) +{ +} + +void FractionalScale::wp_fractional_scale_v1_destroy_resource(Resource *resource) +{ + Q_UNUSED(resource) + delete this; +} + +void FractionalScale::wp_fractional_scale_v1_destroy(Resource *resource) +{ + wl_resource_destroy(resource->handle); +} + +} diff --git a/tests/auto/client/shared/fractionalscalev1.h b/tests/auto/client/shared/fractionalscalev1.h new file mode 100644 index 000000000..1ae2fad1f --- /dev/null +++ b/tests/auto/client/shared/fractionalscalev1.h @@ -0,0 +1,39 @@ +// Copyright (C) 2022 David Edmundson <davidedmundson@kde.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#ifndef MOCKCOMPOSITOR_FRACTIONALSCALE_H +#define MOCKCOMPOSITOR_FRACTIONALSCALE_H + +#include "coreprotocol.h" +#include <qwayland-server-fractional-scale-v1.h> + +namespace MockCompositor { + +class FractionalScale; + +class FractionalScaleManager : public Global, public QtWaylandServer::wp_fractional_scale_manager_v1 +{ + Q_OBJECT +public: + explicit FractionalScaleManager(CoreCompositor *compositor, int version = 1); + QList<FractionalScale *> m_fractionalScales; + +protected: + void wp_fractional_scale_manager_v1_get_fractional_scale(Resource *resource, uint32_t id, wl_resource *surface) override; +}; + +class FractionalScale : public QObject, public QtWaylandServer::wp_fractional_scale_v1 +{ + Q_OBJECT +public: + explicit FractionalScale(Surface *surface, wl_client *client, int id, int version); + Surface *m_surface; + +protected: + void wp_fractional_scale_v1_destroy_resource(Resource *resource) override; + void wp_fractional_scale_v1_destroy(Resource *resource) override; +}; + +} + +#endif diff --git a/tests/auto/client/shared/fullscreenshellv1.cpp b/tests/auto/client/shared/fullscreenshellv1.cpp new file mode 100644 index 000000000..24468e14b --- /dev/null +++ b/tests/auto/client/shared/fullscreenshellv1.cpp @@ -0,0 +1,22 @@ +// Copyright (C) 2021 David Edmundson <davidedmundson@kde.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "fullscreenshellv1.h" + +namespace MockCompositor { + +FullScreenShellV1::FullScreenShellV1(CoreCompositor *compositor) +{ + init(compositor->m_display, 1); +} + +void FullScreenShellV1::zwp_fullscreen_shell_v1_present_surface(Resource *resource, struct ::wl_resource *surface, uint32_t method, struct ::wl_resource *output) +{ + Q_UNUSED(resource); + Q_UNUSED(method); + Q_UNUSED(output); + + m_surfaces.append(fromResource<Surface>(surface)); +} + +} // namespace MockCompositor diff --git a/tests/auto/client/shared/fullscreenshellv1.h b/tests/auto/client/shared/fullscreenshellv1.h new file mode 100644 index 000000000..02ebf1e0c --- /dev/null +++ b/tests/auto/client/shared/fullscreenshellv1.h @@ -0,0 +1,34 @@ +// Copyright (C) 2021 David Edmundson <davidedmundson@kde.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#ifndef MOCKCOMPOSITOR_FULLSCREENSHELLV1_H +#define MOCKCOMPOSITOR_FULLSCREENSHELLV1_H + +#include "coreprotocol.h" +#include <qwayland-server-fullscreen-shell-unstable-v1.h> + +#include <QList> + +namespace MockCompositor { + +class Surface; +class FullScreenShellV1; + +class FullScreenShellV1 : public Global, public QtWaylandServer::zwp_fullscreen_shell_v1 +{ + Q_OBJECT +public: + explicit FullScreenShellV1(CoreCompositor *compositor); + + QList<Surface *> surfaces() const { return m_surfaces; } + +protected: + void zwp_fullscreen_shell_v1_present_surface(Resource *resource, struct ::wl_resource *surface, uint32_t method, struct ::wl_resource *output) override; + +private: + QList<Surface *> m_surfaces; +}; + +} // namespace MockCompositor + +#endif // MOCKCOMPOSITOR_FULLSCREENSHELLV1_H diff --git a/tests/auto/client/shared/iviapplication.cpp b/tests/auto/client/shared/iviapplication.cpp new file mode 100644 index 000000000..f4f167600 --- /dev/null +++ b/tests/auto/client/shared/iviapplication.cpp @@ -0,0 +1,45 @@ +// Copyright (C) 2021 David Edmundson <davidedmundson@kde.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "iviapplication.h" + +namespace MockCompositor { + +IviApplication::IviApplication(CoreCompositor *compositor) +{ + init(compositor->m_display, 1); +} + +void IviApplication::ivi_application_surface_create(Resource *resource, uint32_t ivi_id, struct ::wl_resource *surface, uint32_t id) +{ + auto *s = fromResource<Surface>(surface); + auto *iviSurface = new IviSurface(this, s, ivi_id, resource->client(), id, resource->version()); + m_iviSurfaces << iviSurface; + qDebug() << "count is " << m_iviSurfaces.size(); +} + +IviSurface::IviSurface(IviApplication *iviApplication, Surface *surface, uint32_t ivi_id, wl_client *client, int id, int version) + : QtWaylandServer::ivi_surface(client, id, version) + , m_iviId(ivi_id) + , m_iviApplication(iviApplication) + , m_surface(surface) +{ + surface->map(); +} + +void IviSurface::ivi_surface_destroy_resource(Resource *resource) +{ + Q_UNUSED(resource); + bool removed = m_iviApplication->m_iviSurfaces.removeOne(this); + Q_ASSERT(removed); + qDebug() << "destroy"; + + delete this; +} + +void IviSurface::ivi_surface_destroy(QtWaylandServer::ivi_surface::Resource *resource) +{ + wl_resource_destroy(resource->handle); +} + +} // namespace MockCompositor diff --git a/tests/auto/client/shared/iviapplication.h b/tests/auto/client/shared/iviapplication.h new file mode 100644 index 000000000..1644d0cfd --- /dev/null +++ b/tests/auto/client/shared/iviapplication.h @@ -0,0 +1,50 @@ +// Copyright (C) 2021 David Edmundson <davidedmundson@kde.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#ifndef MOCKCOMPOSITOR_IVIAPPLICATION_H +#define MOCKCOMPOSITOR_IVIAPPLICATION_H + +#include "coreprotocol.h" +#include <qwayland-server-ivi-application.h> + +#include <QList> + +namespace MockCompositor { + +class Surface; +class IviApplication; +class IviSurface; + +class IviApplication : public Global, public QtWaylandServer::ivi_application +{ + Q_OBJECT +public: + explicit IviApplication(CoreCompositor *compositor); + + QList<IviSurface *> m_iviSurfaces; +protected: + void ivi_application_surface_create(Resource *resource, uint32_t ivi_id, struct ::wl_resource *surface, uint32_t id) override; + +}; + +class IviSurface : public QObject, public QtWaylandServer::ivi_surface +{ + Q_OBJECT +public: + IviSurface(IviApplication *iviApplication, Surface *surface, uint32_t ivi_id, wl_client *client, int id, int version); + + Surface *surface() const { return m_surface; } + + void ivi_surface_destroy_resource(Resource *resource) override; + void ivi_surface_destroy(Resource *resource) override; + + const uint m_iviId = 0; +private: + IviApplication *m_iviApplication; + Surface *m_surface = nullptr; +}; + + +} // namespace MockCompositor + +#endif // MOCKCOMPOSITOR_IVIAPPLICATION_H diff --git a/tests/auto/client/shared/mockcompositor.cpp b/tests/auto/client/shared/mockcompositor.cpp index 5f2d89078..bbf406d64 100644 --- a/tests/auto/client/shared/mockcompositor.cpp +++ b/tests/auto/client/shared/mockcompositor.cpp @@ -1,36 +1,13 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2021 David Edmundson <davidedmundson@kde.org> +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "mockcompositor.h" namespace MockCompositor { -DefaultCompositor::DefaultCompositor() +DefaultCompositor::DefaultCompositor(CompositorType t, int socketFd) + : CoreCompositor(t, socketFd) { { Lock l(this); @@ -42,33 +19,71 @@ DefaultCompositor::DefaultCompositor() auto *output = add<Output>(); output->m_data.physicalSize = output->m_data.mode.physicalSizeForDpi(96); add<Seat>(Seat::capability_pointer | Seat::capability_keyboard | Seat::capability_touch); + add<WlShell>(); add<XdgWmBase>(); - add<Shm>(); + add<FractionalScaleManager>(); + add<Viewporter>(); + add<XdgWmDialog>(); + + switch (m_type) { + case CompositorType::Default: + add<Shm>(); + break; + case CompositorType::Legacy: + wl_display_init_shm(m_display); + break; + } + add<FullScreenShellV1>(); + add<IviApplication>(); + // TODO: other shells, viewporter, xdgoutput etc - QObject::connect(get<WlCompositor>(), &WlCompositor::surfaceCreated, [&] (Surface *surface){ - QObject::connect(surface, &Surface::bufferCommitted, [=] { + QObject::connect(get<WlCompositor>(), &WlCompositor::surfaceCreated, [this] (Surface *surface){ + QObject::connect(surface, &Surface::bufferCommitted, [this, surface] { if (m_config.autoRelease) { // Pretend we made a copy of the buffer and just release it immediately surface->m_committed.buffer->send_release(); } - if (m_config.autoEnter && surface->m_outputs.empty()) + if (m_config.autoFrameCallback) { + surface->sendFrameCallbacks(); + } + if (m_config.autoEnter && get<Output>() && surface->m_outputs.empty()) surface->sendEnter(get<Output>()); wl_display_flush_clients(m_display); }); }); - QObject::connect(get<XdgWmBase>(), &XdgWmBase::toplevelCreated, [&] (XdgToplevel *toplevel) { - // Needed because lambdas don't support Qt::DirectConnection - exec([&]{ - if (m_config.autoConfigure) - toplevel->sendCompleteConfigure(); - }); - }); + QObject::connect(get<XdgWmBase>(), &XdgWmBase::toplevelCreated, get<XdgWmBase>(), [this] (XdgToplevel *toplevel) { + if (m_config.autoConfigure) + toplevel->sendCompleteConfigure(); + }, Qt::DirectConnection); } Q_ASSERT(isClean()); } +Surface *DefaultCompositor::surface(int i) +{ + QList<Surface *> surfaces; + switch (m_type) { + case CompositorType::Default: + return get<WlCompositor>()->m_surfaces.value(i, nullptr); + case CompositorType::Legacy: { + QList<Surface *> msurfaces = get<WlCompositor>()->m_surfaces; + for (Surface *surface : msurfaces) { + if (surface->isMapped()) { + surfaces << surface; + } + } + } + break; + } + + if (i >= 0 && i < surfaces.size()) + return surfaces[i]; + + return nullptr; +} + uint DefaultCompositor::sendXdgShellPing() { warnIfNotLockedByThread(Q_FUNC_INFO); @@ -82,10 +97,47 @@ uint DefaultCompositor::sendXdgShellPing() void DefaultCompositor::xdgPingAndWaitForPong() { - QSignalSpy pongSpy(exec([=] { return get<XdgWmBase>(); }), &XdgWmBase::pong); - uint serial = exec([=] { return sendXdgShellPing(); }); - QTRY_COMPARE(pongSpy.count(), 1); + QSignalSpy pongSpy(exec([&] { return get<XdgWmBase>(); }), &XdgWmBase::pong); + uint serial = exec([&] { return sendXdgShellPing(); }); + QTRY_COMPARE(pongSpy.size(), 1); QTRY_COMPARE(pongSpy.first().at(0).toUInt(), serial); } +void DefaultCompositor::sendShellSurfaceConfigure(Surface *surface) +{ + switch (m_type) { + case CompositorType::Default: + break; + case CompositorType::Legacy: { + if (auto wlShellSurface = surface->wlShellSurface()) { + wlShellSurface->sendConfigure(0, 0, 0); + return; + } + break; + } + } + + qWarning() << "The mocking framework doesn't know how to send a configure event for this surface"; +} + +WlShellCompositor::WlShellCompositor(CompositorType t) + : DefaultCompositor(t) +{ +} + +Surface *DefaultCompositor::wlSurface(int i) +{ + QList<Surface *> surfaces, msurfaces; + msurfaces = get<WlCompositor>()->m_surfaces; + for (Surface *surface : msurfaces) { + if (surface->isMapped()) + surfaces << surface; + } + + if (i >=0 && i < surfaces.size()) + return surfaces[i]; + + return nullptr; +} + } // namespace MockCompositor diff --git a/tests/auto/client/shared/mockcompositor.h b/tests/auto/client/shared/mockcompositor.h index deef1f909..9a2c06a17 100644 --- a/tests/auto/client/shared/mockcompositor.h +++ b/tests/auto/client/shared/mockcompositor.h @@ -1,30 +1,6 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2021 David Edmundson <davidedmundson@kde.org> +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef MOCKCOMPOSITOR_H #define MOCKCOMPOSITOR_H @@ -32,7 +8,12 @@ #include "corecompositor.h" #include "coreprotocol.h" #include "datadevice.h" +#include "fullscreenshellv1.h" +#include "iviapplication.h" #include "xdgshell.h" +#include "viewport.h" +#include "fractionalscalev1.h" +#include "xdgdialog.h" #include <QtGui/QGuiApplication> @@ -52,11 +33,13 @@ namespace MockCompositor { class DefaultCompositor : public CoreCompositor { public: - explicit DefaultCompositor(); + explicit DefaultCompositor(CompositorType t = CompositorType::Default, int socketFd = -1); // Convenience functions Output *output(int i = 0) { return getAll<Output>().value(i, nullptr); } - Surface *surface(int i = 0) { return get<WlCompositor>()->m_surfaces.value(i, nullptr); } + Surface *surface(int i = 0); Subsurface *subSurface(int i = 0) { return get<SubCompositor>()->m_subsurfaces.value(i, nullptr); } + WlShellSurface *wlShellSurface(int i = 0) { return get<WlShell>()->m_wlShellSurfaces.value(i, nullptr); } + Surface *wlSurface(int i = 0); XdgSurface *xdgSurface(int i = 0) { return get<XdgWmBase>()->m_xdgSurfaces.value(i, nullptr); } XdgToplevel *xdgToplevel(int i = 0) { return get<XdgWmBase>()->toplevel(i); } XdgPopup *xdgPopup(int i = 0) { return get<XdgWmBase>()->popup(i); } @@ -64,17 +47,33 @@ public: Touch *touch() { auto *seat = get<Seat>(); Q_ASSERT(seat); return seat->m_touch; } Surface *cursorSurface() { auto *p = pointer(); return p ? p->cursorSurface() : nullptr; } Keyboard *keyboard() { auto *seat = get<Seat>(); Q_ASSERT(seat); return seat->m_keyboard; } + FullScreenShellV1 *fullScreenShellV1() {return get<FullScreenShellV1>();}; + IviSurface *iviSurface(int i = 0) { return get<IviApplication>()->m_iviSurfaces.value(i, nullptr); } + FractionalScale *fractionalScale(int i = 0) {return get<FractionalScaleManager>()->m_fractionalScales.value(i, nullptr); } + Viewport *viewport(int i = 0) {return get<Viewporter>()->m_viewports.value(i, nullptr); } + XdgDialog *xdgDialog(int i = 0) { return get<XdgWmDialog>()->m_dialogs.value(i, nullptr); } + uint sendXdgShellPing(); void xdgPingAndWaitForPong(); + + void sendShellSurfaceConfigure(Surface *surface); + // Things that can be changed run-time without confusing the client (i.e. don't require separate tests) struct Config { bool autoEnter = true; bool autoRelease = true; bool autoConfigure = false; + bool autoFrameCallback = true; } m_config; void resetConfig() { exec([&] { m_config = Config{}; }); } }; +class WlShellCompositor : public DefaultCompositor +{ +public: + explicit WlShellCompositor(CompositorType t = CompositorType::Legacy); +}; + } // namespace MockCompositor #define QCOMPOSITOR_VERIFY(expr) QVERIFY(exec([&]{ return expr; })) @@ -91,6 +90,7 @@ int main(int argc, char **argv) \ setenv("QT_QPA_PLATFORM", "wayland", 1); \ test tc; \ QGuiApplication app(argc, argv); \ + QTEST_SET_MAIN_SOURCE_PATH \ return QTest::qExec(&tc, argc, argv); \ } \ diff --git a/tests/auto/client/shared/qttextinput.cpp b/tests/auto/client/shared/qttextinput.cpp new file mode 100644 index 000000000..1fb5ef1c4 --- /dev/null +++ b/tests/auto/client/shared/qttextinput.cpp @@ -0,0 +1,20 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "qttextinput.h" + +namespace MockCompositor { + +QtTextInputManager::QtTextInputManager(CoreCompositor *compositor) +{ + init(compositor->m_display, 1); +} + +void QtTextInputManager::text_input_method_manager_v1_get_text_input_method(Resource *resource, uint32_t id, wl_resource *seatResource) +{ + Q_UNUSED(resource); + Q_UNUSED(id); + Q_UNUSED(seatResource); +} + +} // namespace MockCompositor diff --git a/tests/auto/client/shared/qttextinput.h b/tests/auto/client/shared/qttextinput.h new file mode 100644 index 000000000..047cec7d3 --- /dev/null +++ b/tests/auto/client/shared/qttextinput.h @@ -0,0 +1,26 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#ifndef MOCKCOMPOSITOR_QTTEXTINPUT_H +#define MOCKCOMPOSITOR_QTTEXTINPUT_H + +#include "coreprotocol.h" +#include <qwayland-server-qt-text-input-method-unstable-v1.h> + +#include <QtGui/qpa/qplatformnativeinterface.h> + +namespace MockCompositor { + +class QtTextInputManager : public Global, public QtWaylandServer::qt_text_input_method_manager_v1 +{ + Q_OBJECT +public: + QtTextInputManager(CoreCompositor *compositor); + +protected: + void text_input_method_manager_v1_get_text_input_method(Resource *resource, uint32_t id, struct ::wl_resource *seatResource) override; +}; + +} // namespace MockCompositor + +#endif // MOCKCOMPOSITOR_QTTEXTINPUT_H diff --git a/tests/auto/client/shared/shared.pri b/tests/auto/client/shared/shared.pri index c86183b3d..97202e787 100644 --- a/tests/auto/client/shared/shared.pri +++ b/tests/auto/client/shared/shared.pri @@ -1,9 +1,10 @@ -QT += testlib waylandclient-private +QT += testlib waylandclient-private opengl CONFIG += testcase wayland-scanner QMAKE_USE += wayland-server WAYLANDSERVERSOURCES += \ $$PWD/../../../../src/3rdparty/protocol/wayland.xml \ + $$PWD/../../../../src/3rdparty/protocol/xdg-output-unstable-v1.xml \ $$PWD/../../../../src/3rdparty/protocol/xdg-shell.xml \ $$PWD/../../../../src/3rdparty/protocol/text-input-unstable-v2.xml @@ -14,6 +15,7 @@ HEADERS += \ $$PWD/coreprotocol.h \ $$PWD/datadevice.h \ $$PWD/mockcompositor.h \ + $$PWD/xdgoutputv1.h \ $$PWD/xdgshell.h \ $$PWD/textinput.h @@ -22,5 +24,6 @@ SOURCES += \ $$PWD/coreprotocol.cpp \ $$PWD/datadevice.cpp \ $$PWD/mockcompositor.cpp \ + $$PWD/xdgoutputv1.cpp \ $$PWD/xdgshell.cpp \ $$PWD/textinput.cpp diff --git a/tests/auto/client/shared/textinput.cpp b/tests/auto/client/shared/textinput.cpp index f9fd287bb..fc4865d71 100644 --- a/tests/auto/client/shared/textinput.cpp +++ b/tests/auto/client/shared/textinput.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2019 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "textinput.h" @@ -37,9 +12,8 @@ TextInputManager::TextInputManager(CoreCompositor *compositor) void TextInputManager::zwp_text_input_manager_v2_get_text_input(Resource *resource, uint32_t id, wl_resource *seatResource) { - Q_UNUSED(resource); - Q_UNUSED(id); Q_UNUSED(seatResource); + add(resource->client(), id, resource->version()); } } // namespace MockCompositor diff --git a/tests/auto/client/shared/textinput.h b/tests/auto/client/shared/textinput.h index 85072e74b..ca20ddbad 100644 --- a/tests/auto/client/shared/textinput.h +++ b/tests/auto/client/shared/textinput.h @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2019 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef MOCKCOMPOSITOR_TEXTINPUT_H #define MOCKCOMPOSITOR_TEXTINPUT_H diff --git a/tests/auto/client/shared/viewport.cpp b/tests/auto/client/shared/viewport.cpp new file mode 100644 index 000000000..df6bbb336 --- /dev/null +++ b/tests/auto/client/shared/viewport.cpp @@ -0,0 +1,58 @@ +// Copyright (C) 2022 David Edmundson <davidedmundson@kde.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "viewport.h" + +namespace MockCompositor { + +Viewporter::Viewporter(CoreCompositor *compositor, int version) + : QtWaylandServer::wp_viewporter(compositor->m_display, version) +{ +} + +void Viewporter::wp_viewporter_get_viewport(Resource *resource, uint32_t id, wl_resource *surface) +{ + auto *s = fromResource<Surface>(surface); + auto *viewport = new Viewport(s, resource->client(), id, resource->version()); + connect(viewport, &QObject::destroyed, this, [this, viewport]() { + m_viewports.removeOne(viewport); + }); + m_viewports << viewport; +} + +Viewport::Viewport(Surface *surface, wl_client *client, int id, int version) + : QtWaylandServer::wp_viewport(client, id, version) + , m_surface(surface) +{ +} + +void Viewport::wp_viewport_set_source(Resource *resource, wl_fixed_t x, wl_fixed_t y, wl_fixed_t width, wl_fixed_t height) +{ + Q_UNUSED(resource) + m_source = QRectF(wl_fixed_to_double(x), + wl_fixed_to_double(y), + wl_fixed_to_double(width), + wl_fixed_to_double(height)); + Q_EMIT sourceChanged(); +} + +void Viewport::wp_viewport_set_destination(Resource *resource, int32_t width, int32_t height) +{ + Q_UNUSED(resource) + + m_destination = QSize(width, height); + Q_EMIT destinationChanged(); +} + +void Viewport::wp_viewport_destroy_resource(Resource *resource) +{ + Q_UNUSED(resource) + delete this; +} + +void Viewport::wp_viewport_destroy(Resource *resource) +{ + wl_resource_destroy(resource->handle); +} + +} diff --git a/tests/auto/client/shared/viewport.h b/tests/auto/client/shared/viewport.h new file mode 100644 index 000000000..ddc4297db --- /dev/null +++ b/tests/auto/client/shared/viewport.h @@ -0,0 +1,50 @@ +// Copyright (C) 2022 David Edmundson <davidedmundson@kde.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#ifndef MOCKCOMPOSITOR_VIEWPORT_H +#define MOCKCOMPOSITOR_VIEWPORT_H + +#include "coreprotocol.h" +#include <qwayland-server-viewporter.h> + +namespace MockCompositor { + +class Viewport; + +class Viewporter : public Global, public QtWaylandServer::wp_viewporter +{ + Q_OBJECT +public: + explicit Viewporter(CoreCompositor *compositor, int version = 1); + QList<Viewport *> m_viewports; + +protected: + void wp_viewporter_get_viewport(Resource *resource, uint32_t id, wl_resource *surface) override; +}; + +class Viewport : public QObject, public QtWaylandServer::wp_viewport +{ + Q_OBJECT +public: + explicit Viewport(Surface *surface, wl_client *client, int id, int version); + + QRectF m_source; + QSize m_destination; + + Surface* m_surface; + +Q_SIGNALS: + void sourceChanged(); + void destinationChanged(); + +protected: + void wp_viewport_set_source(Resource *resource, wl_fixed_t x, wl_fixed_t y, wl_fixed_t width, wl_fixed_t height) override; + void wp_viewport_set_destination(Resource *resource, int32_t width, int32_t height) override; + + void wp_viewport_destroy_resource(Resource *resource) override; + void wp_viewport_destroy(Resource *resource) override; +}; + +} + +#endif diff --git a/tests/auto/client/shared/xdgdialog.cpp b/tests/auto/client/shared/xdgdialog.cpp new file mode 100644 index 000000000..b973415bd --- /dev/null +++ b/tests/auto/client/shared/xdgdialog.cpp @@ -0,0 +1,59 @@ +// Copyright (C) 2024 David Redondo <kde@david-redondo.de> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only +#include "xdgdialog.h" + +#include "xdgshell.h" + +namespace MockCompositor { + +XdgDialog::XdgDialog(XdgWmDialog *wm, XdgToplevel *toplevel, wl_client *client, int id, int version) + : QtWaylandServer::xdg_dialog_v1(client, id, version), + toplevel(toplevel), + modal(false), + m_wm(wm) +{ +} + +void XdgDialog::xdg_dialog_v1_set_modal(Resource *resource) +{ + Q_UNUSED(resource) + modal = true; +} + +void XdgDialog::xdg_dialog_v1_unset_modal(Resource *resource) +{ + Q_UNUSED(resource) + modal = false; +} + +void XdgDialog::xdg_dialog_v1_destroy(Resource *resource) +{ + wl_resource_destroy(resource->handle); +} + +void XdgDialog::xdg_dialog_v1_destroy_resource(Resource *resource) +{ + Q_UNUSED(resource) + m_wm->m_dialogs.removeOne(this); + delete this; +} + +XdgWmDialog::XdgWmDialog(CoreCompositor *compositor, int version) + : QtWaylandServer::xdg_wm_dialog_v1(compositor->m_display, version) +{ +} + +void XdgWmDialog::xdg_wm_dialog_v1_destroy(Resource *resource) +{ + wl_resource_destroy(resource->handle); +} + +void XdgWmDialog::xdg_wm_dialog_v1_get_xdg_dialog(Resource *resource, uint32_t id, + struct ::wl_resource *toplevel) +{ + auto *t = fromResource<XdgToplevel>(toplevel); + auto *dialog = new XdgDialog(this, t, resource->client(), id, resource->version()); + m_dialogs.push_back(dialog); +} + +} // namespace MockCompositor diff --git a/tests/auto/client/shared/xdgdialog.h b/tests/auto/client/shared/xdgdialog.h new file mode 100644 index 000000000..d9e3de996 --- /dev/null +++ b/tests/auto/client/shared/xdgdialog.h @@ -0,0 +1,49 @@ +// Copyright (C) 2024 David Redondo <kde@david-redondo.de> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#ifndef MOCKCOMPOSITOR_XDG_DIALOG_H +#define MOCKCOMPOSITOR_XDG_DIALOG_H + +#include "corecompositor.h" +#include <qwayland-server-xdg-dialog-v1.h> + +namespace MockCompositor { + +class XdgToplevel; +class XdgWmDialog; + +class XdgDialog : public QtWaylandServer::xdg_dialog_v1 +{ +public: + explicit XdgDialog(XdgWmDialog *wm, XdgToplevel *toplevel, wl_client *client, int id, + int version); + XdgToplevel *toplevel; + bool modal; + +protected: + void xdg_dialog_v1_set_modal(Resource *resource) override; + void xdg_dialog_v1_unset_modal(Resource *resource) override; + void xdg_dialog_v1_destroy(Resource *resource) override; + void xdg_dialog_v1_destroy_resource(Resource *resource) override; + +private: + XdgWmDialog *m_wm; +}; + +class XdgWmDialog : public Global, public QtWaylandServer::xdg_wm_dialog_v1 +{ + Q_OBJECT +public: + explicit XdgWmDialog(CoreCompositor *compositor, int version = 1); + ~XdgWmDialog() = default; + QList<XdgDialog *> m_dialogs; + +protected: + void xdg_wm_dialog_v1_destroy(Resource *resource) override; + void xdg_wm_dialog_v1_get_xdg_dialog(Resource *resource, uint32_t id, + struct ::wl_resource *toplevel) override; +}; + +} // namespace MockCompositor + +#endif diff --git a/tests/auto/client/shared/xdgoutputv1.cpp b/tests/auto/client/shared/xdgoutputv1.cpp new file mode 100644 index 000000000..af72ae2eb --- /dev/null +++ b/tests/auto/client/shared/xdgoutputv1.cpp @@ -0,0 +1,34 @@ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "xdgoutputv1.h" + +namespace MockCompositor { + +int XdgOutputV1::s_nextId = 1; + +void XdgOutputV1::sendLogicalSize(const QSize &size) +{ + m_logicalGeometry.setSize(size); + for (auto *resource : resourceMap()) + zxdg_output_v1::send_logical_size(resource->handle, size.width(), size.height()); +} + +void XdgOutputV1::addResource(wl_client *client, int id, int version) +{ + auto *resource = add(client, id, version)->handle; + zxdg_output_v1::send_logical_size(resource, m_logicalGeometry.width(), m_logicalGeometry.height()); + send_logical_position(resource, m_logicalGeometry.x(), m_logicalGeometry.y()); + if (version >= ZXDG_OUTPUT_V1_NAME_SINCE_VERSION) + send_name(resource, m_name); + if (version >= ZXDG_OUTPUT_V1_DESCRIPTION_SINCE_VERSION) + send_description(resource, m_description); + + if (version < 3) // zxdg_output_v1.done has been deprecated + zxdg_output_v1::send_done(resource); + else { + m_output->sendDone(client); + } +} + +} // namespace MockCompositor diff --git a/tests/auto/client/shared/xdgoutputv1.h b/tests/auto/client/shared/xdgoutputv1.h new file mode 100644 index 000000000..8c6276741 --- /dev/null +++ b/tests/auto/client/shared/xdgoutputv1.h @@ -0,0 +1,63 @@ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#ifndef MOCKCOMPOSITOR_XDGOUTPUTV1_H +#define MOCKCOMPOSITOR_XDGOUTPUTV1_H + +#include "coreprotocol.h" + +#include <qwayland-server-xdg-output-unstable-v1.h> + +namespace MockCompositor { + +class XdgOutputV1 : public QObject, public QtWaylandServer::zxdg_output_v1 +{ +public: + explicit XdgOutputV1(Output *output) + : m_output(output) + , m_logicalGeometry(m_output->m_data.position, QSize(m_output->m_data.mode.resolution / m_output->m_data.scale)) + , m_name(QString("WL-%1").arg(s_nextId++)) + {} + + void send_logical_size(int32_t width, int32_t height) = delete; + void sendLogicalSize(const QSize &size); + + void send_done() = delete; // zxdg_output_v1.done has been deprecated (in protocol version 3) + + void addResource(wl_client *client, int id, int version); + Output *m_output = nullptr; + QRect m_logicalGeometry; + QString m_name; + QString m_description = "This is an Xdg Output description"; + static int s_nextId; +}; + +class XdgOutputManagerV1 : public Global, public QtWaylandServer::zxdg_output_manager_v1 +{ + Q_OBJECT +public: + explicit XdgOutputManagerV1(CoreCompositor *compositor, int version = 3) + : QtWaylandServer::zxdg_output_manager_v1(compositor->m_display, version) + , m_version(version) + {} + int m_version = 1; // TODO: remove on libwayland upgrade + QMap<Output *, XdgOutputV1 *> m_xdgOutputs; + XdgOutputV1 *getXdgOutput(Output *output) + { + if (auto *xdgOutput = m_xdgOutputs.value(output)) + return xdgOutput; + return m_xdgOutputs[output] = new XdgOutputV1(output); // TODO: free memory + } + +protected: + void zxdg_output_manager_v1_get_xdg_output(Resource *resource, uint32_t id, wl_resource *outputResource) override + { + auto *output = fromResource<Output>(outputResource); + auto *xdgOutput = getXdgOutput(output); + xdgOutput->addResource(resource->client(), id, resource->version()); + } +}; + +} // namespace MockCompositor + +#endif // MOCKCOMPOSITOR_XDGOUTPUTV1_H diff --git a/tests/auto/client/shared/xdgshell.cpp b/tests/auto/client/shared/xdgshell.cpp index 13acc01e2..2c1639851 100644 --- a/tests/auto/client/shared/xdgshell.cpp +++ b/tests/auto/client/shared/xdgshell.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "xdgshell.h" @@ -39,7 +14,7 @@ XdgWmBase::XdgWmBase(CoreCompositor *compositor, int version) XdgToplevel *XdgWmBase::toplevel(int i) { int j = 0; - for (auto *xdgSurface : qAsConst(m_xdgSurfaces)) { + for (auto *xdgSurface : std::as_const(m_xdgSurfaces)) { if (auto *toplevel = xdgSurface->m_toplevel) { if (j == i) return toplevel; @@ -52,7 +27,7 @@ XdgToplevel *XdgWmBase::toplevel(int i) XdgPopup *XdgWmBase::popup(int i) { int j = 0; - for (auto *xdgSurface : qAsConst(m_xdgSurfaces)) { + for (auto *xdgSurface : std::as_const(m_xdgSurfaces)) { if (auto *popup = xdgSurface->m_popup) { if (j == i) return popup; @@ -83,7 +58,7 @@ XdgSurface::XdgSurface(XdgWmBase *xdgWmBase, Surface *surface, wl_client *client { QVERIFY(!surface->m_pending.buffer); QVERIFY(!surface->m_committed.buffer); - connect(this, &XdgSurface::toplevelCreated, xdgWmBase, &XdgWmBase::toplevelCreated); + connect(this, &XdgSurface::toplevelCreated, xdgWmBase, &XdgWmBase::toplevelCreated, Qt::DirectConnection); connect(surface, &Surface::attach, this, &XdgSurface::verifyConfigured); connect(surface, &Surface::commit, this, [this] { m_committed = m_pending; @@ -168,12 +143,17 @@ XdgToplevel::XdgToplevel(XdgSurface *xdgSurface, int id, int version) connect(surface(), &Surface::commit, this, [this] { m_committed = m_pending; }); } -void XdgToplevel::sendConfigure(const QSize &size, const QVector<uint> &states) +void XdgToplevel::sendConfigureBounds(const QSize &size) +{ + send_configure_bounds(size.width(), size.height()); +} + +void XdgToplevel::sendConfigure(const QSize &size, const QList<uint> &states) { send_configure(size.width(), size.height(), toByteArray(states)); } -uint XdgToplevel::sendCompleteConfigure(const QSize &size, const QVector<uint> &states) +uint XdgToplevel::sendCompleteConfigure(const QSize &size, const QList<uint> &states) { sendConfigure(size, states); return m_xdgSurface->sendConfigure(); diff --git a/tests/auto/client/shared/xdgshell.h b/tests/auto/client/shared/xdgshell.h index 618babde7..3959e0668 100644 --- a/tests/auto/client/shared/xdgshell.h +++ b/tests/auto/client/shared/xdgshell.h @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef MOCKCOMPOSITOR_XDGSHELL_H #define MOCKCOMPOSITOR_XDGSHELL_H @@ -43,12 +18,12 @@ class XdgWmBase : public Global, public QtWaylandServer::xdg_wm_base { Q_OBJECT public: - explicit XdgWmBase(CoreCompositor *compositor, int version = 1); + explicit XdgWmBase(CoreCompositor *compositor, int version = 4); using QtWaylandServer::xdg_wm_base::send_ping; void send_ping(uint32_t) = delete; // It's a global, use resource specific instead bool isClean() override { return m_xdgSurfaces.empty(); } QString dirtyMessage() override { return m_xdgSurfaces.empty() ? "clean" : "remaining xdg surfaces"; } - QVector<XdgSurface *> m_xdgSurfaces; + QList<XdgSurface *> m_xdgSurfaces; XdgToplevel *toplevel(int i = 0); XdgPopup *popup(int i = 0); XdgPopup *m_topmostGrabbingPopup = nullptr; @@ -86,13 +61,13 @@ public: XdgWmBase *m_xdgWmBase = nullptr; Surface *m_surface = nullptr; bool m_configureSent = false; - QVector<uint> m_pendingConfigureSerials; + QList<uint> m_pendingConfigureSerials; uint m_ackedConfigureSerial = 0; uint m_committedConfigureSerial = 0; struct DoubleBufferedState { QRect windowGeometry = {0, 0, 0, 0}; } m_pending, m_committed; - QVector<XdgPopup *> m_popups; + QList<XdgPopup *> m_popups; public slots: void verifyConfigured() { QVERIFY(m_configureSent); } @@ -115,8 +90,9 @@ class XdgToplevel : public QObject, public QtWaylandServer::xdg_toplevel Q_OBJECT public: explicit XdgToplevel(XdgSurface *xdgSurface, int id, int version = 1); - void sendConfigure(const QSize &size = {0, 0}, const QVector<uint> &states = {}); - uint sendCompleteConfigure(const QSize &size = {0, 0}, const QVector<uint> &states = {}); + void sendConfigureBounds(const QSize &size); + void sendConfigure(const QSize &size = {0, 0}, const QList<uint> &states = {}); + uint sendCompleteConfigure(const QSize &size = {0, 0}, const QList<uint> &states = {}); Surface *surface() { return m_xdgSurface->m_surface; } XdgSurface *m_xdgSurface = nullptr; diff --git a/tests/auto/client/shared_old/mockcompositor.cpp b/tests/auto/client/shared_old/mockcompositor.cpp deleted file mode 100644 index 9553076dd..000000000 --- a/tests/auto/client/shared_old/mockcompositor.cpp +++ /dev/null @@ -1,489 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "mockcompositor.h" -#include "mockinput.h" -#include "mockoutput.h" -#include "mocksurface.h" -#include "mockwlshell.h" -#include "mockxdgshellv6.h" -#include "mockiviapplication.h" - -#include <wayland-xdg-shell-unstable-v6-server-protocol.h> - -#include <stdio.h> -MockCompositor::MockCompositor() -{ - pthread_create(&m_thread, 0, run, this); - - m_mutex.lock(); - m_waitCondition.wait(&m_mutex); - m_mutex.unlock(); -} - -MockCompositor::~MockCompositor() -{ - m_alive = false; - m_waitCondition.wakeOne(); - pthread_join(m_thread, 0); -} - -void MockCompositor::lock() -{ - m_mutex.lock(); -} - -void MockCompositor::unlock() -{ - m_mutex.unlock(); -} - -void MockCompositor::applicationInitialized() -{ - m_ready = true; -} - -int MockCompositor::waylandFileDescriptor() const -{ - return m_compositor->fileDescriptor(); -} - -void MockCompositor::processWaylandEvents() -{ - m_waitCondition.wakeOne(); -} - -void MockCompositor::setOutputMode(const QSize &size) -{ - Command command = makeCommand(Impl::Compositor::setOutputMode, m_compositor); - command.parameters << size; - processCommand(command); -} - -void MockCompositor::setKeyboardFocus(const QSharedPointer<MockSurface> &surface) -{ - Command command = makeCommand(Impl::Compositor::setKeyboardFocus, m_compositor); - command.parameters << QVariant::fromValue(surface); - processCommand(command); -} - -void MockCompositor::sendMousePress(const QSharedPointer<MockSurface> &surface, const QPoint &pos) -{ - Command command = makeCommand(Impl::Compositor::sendMousePress, m_compositor); - command.parameters << QVariant::fromValue(surface) << pos; - processCommand(command); -} - -void MockCompositor::sendMouseRelease(const QSharedPointer<MockSurface> &surface) -{ - Command command = makeCommand(Impl::Compositor::sendMouseRelease, m_compositor); - command.parameters << QVariant::fromValue(surface); - processCommand(command); -} - -void MockCompositor::sendKeyPress(const QSharedPointer<MockSurface> &surface, uint code) -{ - Command command = makeCommand(Impl::Compositor::sendKeyPress, m_compositor); - command.parameters << QVariant::fromValue(surface) << code; - processCommand(command); -} - -void MockCompositor::sendKeyRelease(const QSharedPointer<MockSurface> &surface, uint code) -{ - Command command = makeCommand(Impl::Compositor::sendKeyRelease, m_compositor); - command.parameters << QVariant::fromValue(surface) << code; - processCommand(command); -} - -void MockCompositor::sendTouchDown(const QSharedPointer<MockSurface> &surface, const QPoint &position, int id) -{ - Command command = makeCommand(Impl::Compositor::sendTouchDown, m_compositor); - command.parameters << QVariant::fromValue(surface) << position << id; - processCommand(command); -} - -void MockCompositor::sendTouchMotion(const QSharedPointer<MockSurface> &surface, const QPoint &position, int id) -{ - Command command = makeCommand(Impl::Compositor::sendTouchMotion, m_compositor); - command.parameters << QVariant::fromValue(surface) << position << id; - processCommand(command); -} - -void MockCompositor::sendTouchUp(const QSharedPointer<MockSurface> &surface, int id) -{ - Command command = makeCommand(Impl::Compositor::sendTouchUp, m_compositor); - command.parameters << QVariant::fromValue(surface) << id; - processCommand(command); -} - -void MockCompositor::sendTouchFrame(const QSharedPointer<MockSurface> &surface) -{ - Command command = makeCommand(Impl::Compositor::sendTouchFrame, m_compositor); - command.parameters << QVariant::fromValue(surface); - processCommand(command); -} - -void MockCompositor::sendDataDeviceDataOffer(const QSharedPointer<MockSurface> &surface) -{ - Command command = makeCommand(Impl::Compositor::sendDataDeviceDataOffer, m_compositor); - command.parameters << QVariant::fromValue(surface); - processCommand(command); -} - -void MockCompositor::sendDataDeviceEnter(const QSharedPointer<MockSurface> &surface, const QPoint& position) -{ - Command command = makeCommand(Impl::Compositor::sendDataDeviceEnter, m_compositor); - command.parameters << QVariant::fromValue(surface) << QVariant::fromValue(position); - processCommand(command); -} - -void MockCompositor::sendDataDeviceMotion(const QPoint &position) -{ - Command command = makeCommand(Impl::Compositor::sendDataDeviceMotion, m_compositor); - command.parameters << QVariant::fromValue(position); - processCommand(command); -} - -void MockCompositor::sendDataDeviceDrop(const QSharedPointer<MockSurface> &surface) -{ - Command command = makeCommand(Impl::Compositor::sendDataDeviceDrop, m_compositor); - command.parameters << QVariant::fromValue(surface); - processCommand(command); -} - -void MockCompositor::sendDataDeviceLeave(const QSharedPointer<MockSurface> &surface) -{ - Command command = makeCommand(Impl::Compositor::sendDataDeviceLeave, m_compositor); - command.parameters << QVariant::fromValue(surface); - processCommand(command); -} - -void MockCompositor::sendShellSurfaceConfigure(const QSharedPointer<MockSurface> surface, const QSize &size) -{ - Command command = makeCommand(Impl::Compositor::sendShellSurfaceConfigure, m_compositor); - command.parameters << QVariant::fromValue(surface); - command.parameters << QVariant::fromValue(size); - processCommand(command); -} - -void MockCompositor::sendIviSurfaceConfigure(const QSharedPointer<MockIviSurface> iviSurface, const QSize &size) -{ - Command command = makeCommand(Impl::Compositor::sendIviSurfaceConfigure, m_compositor); - command.parameters << QVariant::fromValue(iviSurface); - command.parameters << QVariant::fromValue(size); - processCommand(command); -} - -void MockCompositor::sendXdgToplevelV6Configure(const QSharedPointer<MockXdgToplevelV6> toplevel, const QSize &size, const QVector<uint> &states) -{ - Command command = makeCommand(Impl::Compositor::sendXdgToplevelV6Configure, m_compositor); - command.parameters << QVariant::fromValue(toplevel); - command.parameters << QVariant::fromValue(size); - QByteArray statesBytes(reinterpret_cast<const char *>(states.data()), - states.size() * static_cast<int>(sizeof(uint))); - command.parameters << statesBytes; - processCommand(command); -} - -void MockCompositor::waitForStartDrag() -{ - Command command = makeCommand(Impl::Compositor::waitForStartDrag, m_compositor); - processCommand(command); -} - -QSharedPointer<MockSurface> MockCompositor::surface() -{ - QSharedPointer<MockSurface> result; - lock(); - { - const QVector<Impl::Surface *> surfaces = m_compositor->surfaces(); - for (Impl::Surface *surface : surfaces) { - // we don't want to mistake the cursor surface for a window surface - if (surface->isMapped()) { - result = surface->mockSurface(); - break; - } - } - } - unlock(); - return result; -} - -QSharedPointer<MockOutput> MockCompositor::output(int index) -{ - QSharedPointer<MockOutput> result; - lock(); - if (Impl::Output *output = m_compositor->outputs().value(index, nullptr)) - result = output->mockOutput(); - unlock(); - return result; -} - -QSharedPointer<MockIviSurface> MockCompositor::iviSurface(int index) -{ - QSharedPointer<MockIviSurface> result; - lock(); - if (Impl::IviSurface *toplevel = m_compositor->iviApplication()->iviSurfaces().value(index, nullptr)) - result = toplevel->mockIviSurface(); - unlock(); - return result; -} - -QSharedPointer<MockXdgToplevelV6> MockCompositor::xdgToplevelV6(int index) -{ - QSharedPointer<MockXdgToplevelV6> result; - lock(); - if (Impl::XdgToplevelV6 *toplevel = m_compositor->xdgShellV6()->toplevels().value(index, nullptr)) - result = toplevel->mockToplevel(); - unlock(); - return result; -} - -QSharedPointer<MockSurface> MockCompositor::fullScreenShellV1Surface(int index) -{ - QSharedPointer<MockSurface> result; - lock(); - if (Impl::Surface *surface = m_compositor->fullScreenShellV1()->surfaces().value(index, nullptr)) - result = surface->mockSurface(); - unlock(); - return result; -} - -MockCompositor::Command MockCompositor::makeCommand(Command::Callback callback, void *target) -{ - Command command; - command.callback = callback; - command.target = target; - return command; -} - -void MockCompositor::processCommand(const Command &command) -{ - lock(); - m_commandQueue << command; - unlock(); - - m_waitCondition.wakeOne(); -} - -void MockCompositor::dispatchCommands() -{ - lock(); - int count = m_commandQueue.length(); - unlock(); - - for (int i = 0; i < count; ++i) { - lock(); - const Command command = m_commandQueue.takeFirst(); - unlock(); - command.callback(command.target, command.parameters); - } -} - -void *MockCompositor::run(void *data) -{ - MockCompositor *controller = static_cast<MockCompositor *>(data); - - Impl::Compositor compositor(controller); - - controller->m_compositor = &compositor; - - while (!controller->m_ready) { - controller->m_waitCondition.wakeOne(); - controller->dispatchCommands(); - compositor.dispatchEvents(20); - } - - while (controller->m_alive) { - { - QMutexLocker locker(&controller->m_mutex); - if (controller->m_commandQueue.isEmpty()) - controller->m_waitCondition.wait(&controller->m_mutex); - } - controller->dispatchCommands(); - compositor.dispatchEvents(20); - } - - return 0; -} - -namespace Impl { - -Compositor::Compositor(MockCompositor *mockCompositor) - : m_mockCompositor(mockCompositor), m_display(wl_display_create()) -{ - if (wl_display_add_socket(m_display, 0)) { - fprintf(stderr, "Fatal: Failed to open server socket\n"); - exit(EXIT_FAILURE); - } - - wl_global_create(m_display, &wl_compositor_interface, 1, this, bindCompositor); - - m_data_device_manager.reset(new DataDeviceManager(this, m_display)); - - wl_display_init_shm(m_display); - - m_seat.reset(new Seat(this, m_display)); - m_pointer = m_seat->pointer(); - m_keyboard = m_seat->keyboard(); - m_touch = m_seat->touch(); - - m_outputs.append(new Output(m_display, QSize(1920, 1080), QPoint(0, 0))); - m_iviApplication.reset(new IviApplication(m_display)); - m_wlShell.reset(new WlShell(m_display)); - m_xdgShellV6.reset(new XdgShellV6(m_display)); - m_fullScreenShellV1.reset(new FullScreenShellV1(m_display)); - - m_loop = wl_display_get_event_loop(m_display); - m_fd = wl_event_loop_get_fd(m_loop); -} - -Compositor::~Compositor() -{ - wl_display_destroy(m_display); -} - -void Compositor::dispatchEvents(int timeout) -{ - wl_display_flush_clients(m_display); - wl_event_loop_dispatch(m_loop, timeout); -} - -static void compositor_create_surface(wl_client *client, wl_resource *compositorResource, uint32_t id) -{ - Compositor *compositor = static_cast<Compositor *>(wl_resource_get_user_data(compositorResource)); - compositor->addSurface(new Surface(client, id, wl_resource_get_version(compositorResource), compositor)); -} - -static void compositor_create_region(wl_client *client, wl_resource *compositorResource, uint32_t id) -{ - Q_UNUSED(client); - Q_UNUSED(compositorResource); - Q_UNUSED(id); -} - -void Compositor::bindCompositor(wl_client *client, void *compositorData, uint32_t version, uint32_t id) -{ - static const struct wl_compositor_interface compositorInterface = { - compositor_create_surface, - compositor_create_region - }; - - wl_resource *resource = wl_resource_create(client, &wl_compositor_interface, static_cast<int>(version), id); - wl_resource_set_implementation(resource, &compositorInterface, compositorData, nullptr); -} - -static void unregisterResourceCallback(wl_listener *listener, void *data) -{ - struct wl_resource *resource = reinterpret_cast<struct wl_resource *>(data); - wl_list_remove(wl_resource_get_link(resource)); - delete listener; -} - -void registerResource(wl_list *list, wl_resource *resource) -{ - wl_list_insert(list, wl_resource_get_link(resource)); - - wl_listener *listener = new wl_listener; - listener->notify = unregisterResourceCallback; - - wl_resource_add_destroy_listener(resource, listener); -} - -QVector<Surface *> Compositor::surfaces() const -{ - return m_surfaces; -} - -QVector<Output *> Compositor::outputs() const -{ - return m_outputs; -} - -IviApplication *Compositor::iviApplication() const -{ - return m_iviApplication.data(); -} - -XdgShellV6 *Compositor::xdgShellV6() const -{ - return m_xdgShellV6.data(); -} - -FullScreenShellV1 *Compositor::fullScreenShellV1() const -{ - return m_fullScreenShellV1.data(); -} - -uint32_t Compositor::nextSerial() -{ - return wl_display_next_serial(m_display); -} - -void Compositor::addSurface(Surface *surface) -{ - m_mockCompositor->lock(); - m_surfaces << surface; - m_mockCompositor->unlock(); -} - -void Compositor::removeSurface(Surface *surface) -{ - m_mockCompositor->lock(); - m_surfaces.removeOne(surface); - m_keyboard->handleSurfaceDestroyed(surface); - m_pointer->handleSurfaceDestroyed(surface); - m_fullScreenShellV1->removeSurface(surface); - m_mockCompositor->unlock(); -} - -Surface *Compositor::resolveSurface(const QVariant &v) -{ - QSharedPointer<MockSurface> mockSurface = v.value<QSharedPointer<MockSurface> >(); - return mockSurface ? mockSurface->handle() : nullptr; -} - -Output *Compositor::resolveOutput(const QVariant &v) -{ - QSharedPointer<MockOutput> mockOutput = v.value<QSharedPointer<MockOutput> >(); - return mockOutput ? mockOutput->handle() : nullptr; -} - -IviSurface *Compositor::resolveIviSurface(const QVariant &v) -{ - QSharedPointer<MockIviSurface> mockIviSurface = v.value<QSharedPointer<MockIviSurface>>(); - return mockIviSurface ? mockIviSurface->handle() : nullptr; -} - -XdgToplevelV6 *Compositor::resolveToplevel(const QVariant &v) -{ - QSharedPointer<MockXdgToplevelV6> mockToplevel = v.value<QSharedPointer<MockXdgToplevelV6>>(); - return mockToplevel ? mockToplevel->handle() : nullptr; -} - -} diff --git a/tests/auto/client/shared_old/mockcompositor.h b/tests/auto/client/shared_old/mockcompositor.h deleted file mode 100644 index 2433ac005..000000000 --- a/tests/auto/client/shared_old/mockcompositor.h +++ /dev/null @@ -1,285 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef MOCKCOMPOSITOR_H -#define MOCKCOMPOSITOR_H - -#include "mockxdgshellv6.h" -#include "mockiviapplication.h" -#include "mockfullscreenshellv1.h" - -#include <pthread.h> -#include <qglobal.h> -#include <wayland-server-core.h> - -#include <QImage> -#include <QMutex> -#include <QRect> -#include <QSharedPointer> -#include <QVariant> -#include <QVector> -#include <QWaitCondition> - -class MockCompositor; - -namespace Impl { - -typedef void (**Implementation)(void); - -class Keyboard; -class Pointer; -class Touch; -class Seat; -class DataDeviceManager; -class Surface; -class Output; -class IviApplication; -class WlShell; -class XdgShellV6; - -class Compositor -{ -public: - Compositor(MockCompositor *mockCompositor); - ~Compositor(); - - int fileDescriptor() const { return m_fd; } - void dispatchEvents(int timeout = 0); - - uint32_t nextSerial(); - uint32_t time() { return ++m_time; } - - QVector<Surface *> surfaces() const; - QVector<Output *> outputs() const; - - IviApplication *iviApplication() const; - XdgShellV6 *xdgShellV6() const; - FullScreenShellV1 *fullScreenShellV1() const; - - void addSurface(Surface *surface); - void removeSurface(Surface *surface); - - static void setKeyboardFocus(void *data, const QList<QVariant> ¶meters); - static void sendMousePress(void *data, const QList<QVariant> ¶meters); - static void sendMouseRelease(void *data, const QList<QVariant> ¶meters); - static void sendKeyPress(void *data, const QList<QVariant> ¶meters); - static void sendKeyRelease(void *data, const QList<QVariant> ¶meters); - static void sendTouchDown(void *data, const QList<QVariant> ¶meters); - static void sendTouchUp(void *data, const QList<QVariant> ¶meters); - static void sendTouchMotion(void *data, const QList<QVariant> ¶meters); - static void sendTouchFrame(void *data, const QList<QVariant> ¶meters); - static void sendDataDeviceDataOffer(void *data, const QList<QVariant> ¶meters); - static void sendDataDeviceEnter(void *data, const QList<QVariant> ¶meters); - static void sendDataDeviceMotion(void *data, const QList<QVariant> ¶meters); - static void sendDataDeviceDrop(void *data, const QList<QVariant> ¶meters); - static void sendDataDeviceLeave(void *data, const QList<QVariant> ¶meters); - static void waitForStartDrag(void *data, const QList<QVariant> ¶meters); - static void setOutputMode(void *compositor, const QList<QVariant> ¶meters); - static void sendShellSurfaceConfigure(void *data, const QList<QVariant> ¶meters); - static void sendIviSurfaceConfigure(void *data, const QList<QVariant> ¶meters); - static void sendXdgToplevelV6Configure(void *data, const QList<QVariant> ¶meters); - -public: - bool m_startDragSeen = false; - -private: - static void bindCompositor(wl_client *client, void *data, uint32_t version, uint32_t id); - static Surface *resolveSurface(const QVariant &v); - static Output *resolveOutput(const QVariant &v); - static IviSurface *resolveIviSurface(const QVariant &v); - static XdgToplevelV6 *resolveToplevel(const QVariant &v); - - void initShm(); - - MockCompositor *m_mockCompositor = nullptr; - QRect m_outputGeometry; - - wl_display *m_display = nullptr; - wl_event_loop *m_loop = nullptr; - int m_fd = -1; - - uint32_t m_time = 0; - - QScopedPointer<Seat> m_seat; - Pointer *m_pointer = nullptr; - Keyboard *m_keyboard = nullptr; - Touch *m_touch = nullptr; - QScopedPointer<DataDeviceManager> m_data_device_manager; - QVector<Surface *> m_surfaces; - QVector<Output *> m_outputs; - QScopedPointer<IviApplication> m_iviApplication; - QScopedPointer<WlShell> m_wlShell; - QScopedPointer<XdgShellV6> m_xdgShellV6; - QScopedPointer<FullScreenShellV1> m_fullScreenShellV1; -}; - -void registerResource(wl_list *list, wl_resource *resource); - -} - -class MockSurface -{ -public: - Impl::Surface *handle() const { return m_surface; } - - QImage image; - -private: - MockSurface(Impl::Surface *surface); - friend class Impl::Compositor; - friend class Impl::Surface; - - Impl::Surface *m_surface = nullptr; -}; - -Q_DECLARE_METATYPE(QSharedPointer<MockSurface>) - -class MockIviSurface -{ -public: - Impl::IviSurface *handle() const { return m_iviSurface; } - const uint iviId; - -private: - MockIviSurface(Impl::IviSurface *iviSurface) : iviId(iviSurface->iviId()), m_iviSurface(iviSurface) {} - friend class Impl::Compositor; - friend class Impl::IviSurface; - - Impl::IviSurface *m_iviSurface; -}; - -Q_DECLARE_METATYPE(QSharedPointer<MockIviSurface>) - -class MockXdgToplevelV6 : public QObject -{ - Q_OBJECT -public: - Impl::XdgToplevelV6 *handle() const { return m_toplevel; } - - void sendConfigure(const QSharedPointer<MockXdgToplevelV6> toplevel); - -signals: - uint setMinimizedRequested(); - uint setMaximizedRequested(); - uint unsetMaximizedRequested(); - uint setFullscreenRequested(); - uint unsetFullscreenRequested(); - void windowGeometryRequested(QRect geometry); // NOTE: This is really an xdg surface event - -private: - MockXdgToplevelV6(Impl::XdgToplevelV6 *toplevel) : m_toplevel(toplevel) {} - friend class Impl::Compositor; - friend class Impl::XdgToplevelV6; - - Impl::XdgToplevelV6 *m_toplevel; -}; - -Q_DECLARE_METATYPE(QSharedPointer<MockXdgToplevelV6>) - -class MockOutput { -public: - Impl::Output *handle() const { return m_output; } - MockOutput(Impl::Output *output); -private: - Impl::Output *m_output = nullptr; -}; - -Q_DECLARE_METATYPE(QSharedPointer<MockOutput>) - -class MockCompositor -{ -public: - MockCompositor(); - ~MockCompositor(); - - void applicationInitialized(); - - int waylandFileDescriptor() const; - void processWaylandEvents(); - - void setOutputMode(const QSize &size); - void setKeyboardFocus(const QSharedPointer<MockSurface> &surface); - void sendMousePress(const QSharedPointer<MockSurface> &surface, const QPoint &pos); - void sendMouseRelease(const QSharedPointer<MockSurface> &surface); - void sendKeyPress(const QSharedPointer<MockSurface> &surface, uint code); - void sendKeyRelease(const QSharedPointer<MockSurface> &surface, uint code); - void sendTouchDown(const QSharedPointer<MockSurface> &surface, const QPoint &position, int id); - void sendTouchMotion(const QSharedPointer<MockSurface> &surface, const QPoint &position, int id); - void sendTouchUp(const QSharedPointer<MockSurface> &surface, int id); - void sendTouchFrame(const QSharedPointer<MockSurface> &surface); - void sendDataDeviceDataOffer(const QSharedPointer<MockSurface> &surface); - void sendDataDeviceEnter(const QSharedPointer<MockSurface> &surface, const QPoint &position); - void sendDataDeviceMotion(const QPoint &position); - void sendDataDeviceDrop(const QSharedPointer<MockSurface> &surface); - void sendDataDeviceLeave(const QSharedPointer<MockSurface> &surface); - void sendSurfaceEnter(const QSharedPointer<MockSurface> &surface, QSharedPointer<MockOutput> &output); - void sendSurfaceLeave(const QSharedPointer<MockSurface> &surface, QSharedPointer<MockOutput> &output); - void sendShellSurfaceConfigure(const QSharedPointer<MockSurface> surface, const QSize &size = QSize(0, 0)); - void sendIviSurfaceConfigure(const QSharedPointer<MockIviSurface> iviSurface, const QSize &size); - void sendXdgToplevelV6Configure(const QSharedPointer<MockXdgToplevelV6> toplevel, const QSize &size = QSize(0, 0), - const QVector<uint> &states = { ZXDG_TOPLEVEL_V6_STATE_ACTIVATED }); - void waitForStartDrag(); - - QSharedPointer<MockSurface> surface(); - QSharedPointer<MockOutput> output(int index = 0); - QSharedPointer<MockIviSurface> iviSurface(int index = 0); - QSharedPointer<MockXdgToplevelV6> xdgToplevelV6(int index = 0); - QSharedPointer<MockSurface> fullScreenShellV1Surface(int index = 0); - - void lock(); - void unlock(); - -private: - struct Command - { - typedef void (*Callback)(void *target, const QList<QVariant> ¶meters); - - Callback callback; - void *target = nullptr; - QList<QVariant> parameters; - }; - - static Command makeCommand(Command::Callback callback, void *target); - - void processCommand(const Command &command); - void dispatchCommands(); - - static void *run(void *data); - - bool m_alive = true; - bool m_ready = false; - pthread_t m_thread; - QMutex m_mutex; - QWaitCondition m_waitCondition; - - Impl::Compositor *m_compositor = nullptr; - - QList<Command> m_commandQueue; -}; - -#endif diff --git a/tests/auto/client/shared_old/mockfullscreenshellv1.cpp b/tests/auto/client/shared_old/mockfullscreenshellv1.cpp deleted file mode 100644 index 22c49cde6..000000000 --- a/tests/auto/client/shared_old/mockfullscreenshellv1.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "mockfullscreenshellv1.h" -#include "mocksurface.h" - -namespace Impl { - -void FullScreenShellV1::zwp_fullscreen_shell_v1_present_surface(Resource *resource, struct ::wl_resource *surface, uint32_t method, struct ::wl_resource *output) -{ - Q_UNUSED(resource) - Q_UNUSED(method) - Q_UNUSED(output) - - m_surfaces.append(Surface::fromResource(surface)); -} - -} // namespace Impl diff --git a/tests/auto/client/shared_old/mockfullscreenshellv1.h b/tests/auto/client/shared_old/mockfullscreenshellv1.h deleted file mode 100644 index 819bbc186..000000000 --- a/tests/auto/client/shared_old/mockfullscreenshellv1.h +++ /dev/null @@ -1,58 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef MOCKFULLSCREENSHELLV1_H -#define MOCKFULLSCREENSHELLV1_H - -#include <qwayland-server-fullscreen-shell-unstable-v1.h> - -#include <QVector> - -namespace Impl { - -class Surface; -class FullScreenShellV1; - -class FullScreenShellV1 : public QtWaylandServer::zwp_fullscreen_shell_v1 -{ -public: - explicit FullScreenShellV1(::wl_display *display) : zwp_fullscreen_shell_v1(display, 1) {} - - QVector<Surface *> surfaces() const { return m_surfaces; } - void removeSurface(Surface *surface) { m_surfaces.removeOne(surface); } - -protected: - void zwp_fullscreen_shell_v1_present_surface(Resource *resource, struct ::wl_resource *surface, uint32_t method, struct ::wl_resource *output) override; - -private: - QVector<Surface *> m_surfaces; -}; - -} // namespace Impl - -#endif // MOCKFULLSCREENSHELLV1_H diff --git a/tests/auto/client/shared_old/mockinput.cpp b/tests/auto/client/shared_old/mockinput.cpp deleted file mode 100644 index 8b7592824..000000000 --- a/tests/auto/client/shared_old/mockinput.cpp +++ /dev/null @@ -1,474 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "mockcompositor.h" -#include "mockinput.h" -#include "mocksurface.h" - -namespace Impl { - -void Compositor::setKeyboardFocus(void *data, const QList<QVariant> ¶meters) -{ - Compositor *compositor = static_cast<Compositor *>(data); - compositor->m_keyboard->setFocus(resolveSurface(parameters.first())); -} - -void Compositor::sendMousePress(void *data, const QList<QVariant> ¶meters) -{ - Compositor *compositor = static_cast<Compositor *>(data); - Surface *surface = resolveSurface(parameters.first()); - if (!surface) - return; - - QPoint pos = parameters.last().toPoint(); - compositor->m_pointer->setFocus(surface, pos); - compositor->m_pointer->sendMotion(pos); - compositor->m_pointer->sendButton(0x110, 1); -} - -void Compositor::sendMouseRelease(void *data, const QList<QVariant> ¶meters) -{ - Compositor *compositor = static_cast<Compositor *>(data); - Surface *surface = resolveSurface(parameters.first()); - if (!surface) - return; - - compositor->m_pointer->sendButton(0x110, 0); -} - -void Compositor::sendKeyPress(void *data, const QList<QVariant> ¶meters) -{ - Compositor *compositor = static_cast<Compositor *>(data); - Surface *surface = resolveSurface(parameters.first()); - if (!surface) - return; - - compositor->m_keyboard->sendKey(parameters.last().toUInt() - 8, 1); -} - -void Compositor::sendKeyRelease(void *data, const QList<QVariant> ¶meters) -{ - Compositor *compositor = static_cast<Compositor *>(data); - Surface *surface = resolveSurface(parameters.first()); - if (!surface) - return; - - compositor->m_keyboard->sendKey(parameters.last().toUInt() - 8, 0); -} - -void Compositor::sendTouchDown(void *data, const QList<QVariant> ¶meters) -{ - Compositor *compositor = static_cast<Compositor *>(data); - Surface *surface = resolveSurface(parameters.first()); - - Q_ASSERT(compositor); - Q_ASSERT(surface); - - QPoint position = parameters.at(1).toPoint(); - int id = parameters.at(2).toInt(); - - compositor->m_touch->sendDown(surface, position, id); -} - -void Compositor::sendTouchUp(void *data, const QList<QVariant> ¶meters) -{ - Compositor *compositor = static_cast<Compositor *>(data); - Surface *surface = resolveSurface(parameters.first()); - - Q_ASSERT(compositor); - Q_ASSERT(surface); - - int id = parameters.at(1).toInt(); - - compositor->m_touch->sendUp(surface, id); -} - -void Compositor::sendTouchMotion(void *data, const QList<QVariant> ¶meters) -{ - Compositor *compositor = static_cast<Compositor *>(data); - Surface *surface = resolveSurface(parameters.first()); - - Q_ASSERT(compositor); - Q_ASSERT(surface); - - QPoint position = parameters.at(1).toPoint(); - int id = parameters.at(2).toInt(); - - compositor->m_touch->sendMotion(surface, position, id); -} - -void Compositor::sendTouchFrame(void *data, const QList<QVariant> ¶meters) -{ - Compositor *compositor = static_cast<Compositor *>(data); - Surface *surface = resolveSurface(parameters.first()); - - Q_ASSERT(compositor); - Q_ASSERT(surface); - - compositor->m_touch->sendFrame(surface); -} - -void Compositor::sendDataDeviceDataOffer(void *data, const QList<QVariant> ¶meters) -{ - Compositor *compositor = static_cast<Compositor *>(data); - Surface *surface = resolveSurface(parameters.first()); - - Q_ASSERT(compositor); - Q_ASSERT(surface); - - compositor->m_data_device_manager->dataDevice()->sendDataOffer(surface->resource()->client()); -} - -void Compositor::sendDataDeviceEnter(void *data, const QList<QVariant> ¶meters) -{ - Compositor *compositor = static_cast<Compositor *>(data); - Surface *surface = resolveSurface(parameters.first()); - QPoint position = parameters.at(1).toPoint(); - - Q_ASSERT(compositor); - Q_ASSERT(surface); - - compositor->m_data_device_manager->dataDevice()->sendEnter(surface, position); -} - -void Compositor::sendDataDeviceMotion(void *data, const QList<QVariant> ¶meters) -{ - Compositor *compositor = static_cast<Compositor *>(data); - Q_ASSERT(compositor); - QPoint position = parameters.first().toPoint(); - compositor->m_data_device_manager->dataDevice()->sendMotion(position); -} - -void Compositor::sendDataDeviceDrop(void *data, const QList<QVariant> ¶meters) -{ - Compositor *compositor = static_cast<Compositor *>(data); - Surface *surface = resolveSurface(parameters.first()); - - Q_ASSERT(compositor); - Q_ASSERT(surface); - - compositor->m_data_device_manager->dataDevice()->sendDrop(surface); -} - -void Compositor::sendDataDeviceLeave(void *data, const QList<QVariant> ¶meters) -{ - Compositor *compositor = static_cast<Compositor *>(data); - Surface *surface = resolveSurface(parameters.first()); - - Q_ASSERT(compositor); - Q_ASSERT(surface); - - compositor->m_data_device_manager->dataDevice()->sendLeave(surface); -} - -void Compositor::waitForStartDrag(void *data, const QList<QVariant> ¶meters) -{ - Q_UNUSED(parameters); - Compositor *compositor = static_cast<Compositor *>(data); - Q_ASSERT(compositor); - while (!compositor->m_startDragSeen) { - wl_display_flush_clients(compositor->m_display); - wl_event_loop_dispatch(compositor->m_loop, 100); - } - compositor->m_startDragSeen = false; -} - -Seat::Seat(Compositor *compositor, struct ::wl_display *display) - : wl_seat(display, 2) - , m_compositor(compositor) - , m_keyboard(new Keyboard(compositor)) - , m_pointer(new Pointer(compositor)) - , m_touch(new Touch(compositor)) -{ -} - -Seat::~Seat() -{ -} - -void Seat::seat_bind_resource(Resource *resource) -{ - send_capabilities(resource->handle, capability_keyboard | capability_pointer | capability_touch); -} - -void Seat::seat_get_keyboard(Resource *resource, uint32_t id) -{ - m_keyboard->add(resource->client(), id, resource->version()); -} - -void Seat::seat_get_pointer(Resource *resource, uint32_t id) -{ - m_pointer->add(resource->client(), id, resource->version()); -} - -void Seat::seat_get_touch(Resource *resource, uint32_t id) -{ - m_touch->add(resource->client(), id, resource->version()); -} - -Keyboard::Keyboard(Compositor *compositor) - : m_compositor(compositor) -{ -} - -Keyboard::~Keyboard() -{ -} - -void Keyboard::setFocus(Surface *surface) -{ - if (m_focusResource && m_focus != surface) { - uint32_t serial = m_compositor->nextSerial(); - send_leave(m_focusResource->handle, serial, m_focus->resource()->handle); - } - - Resource *resource = surface ? resourceMap().value(surface->resource()->client()) : 0; - - if (resource && (m_focus != surface || m_focusResource != resource)) { - uint32_t serial = m_compositor->nextSerial(); - send_modifiers(resource->handle, serial, 0, 0, 0, 0); - send_enter(resource->handle, serial, surface->resource()->handle, QByteArray()); - } - - m_focusResource = resource; - m_focus = surface; -} - -void Keyboard::handleSurfaceDestroyed(Surface *surface) -{ - if (surface == m_focus) { - m_focusResource = nullptr; - m_focus = nullptr; - } -} - -void Keyboard::sendKey(uint32_t key, uint32_t state) -{ - if (m_focusResource) { - uint32_t serial = m_compositor->nextSerial(); - send_key(m_focusResource->handle, serial, m_compositor->time(), key, state); - } -} - - -void Keyboard::keyboard_destroy_resource(wl_keyboard::Resource *resource) -{ - if (m_focusResource == resource) - m_focusResource = 0; -} - -Pointer::Pointer(Compositor *compositor) - : m_compositor(compositor) -{ -} - -Pointer::~Pointer() -{ - -} - -void Pointer::setFocus(Surface *surface, const QPoint &pos) -{ - if (m_focusResource && m_focus != surface) { - uint32_t serial = m_compositor->nextSerial(); - send_leave(m_focusResource->handle, serial, m_focus->resource()->handle); - } - - Resource *resource = surface ? resourceMap().value(surface->resource()->client()) : 0; - - if (resource && (m_focus != surface || resource != m_focusResource)) { - uint32_t serial = m_compositor->nextSerial(); - send_enter(resource->handle, serial, surface->resource()->handle, - wl_fixed_from_int(pos.x()), wl_fixed_from_int(pos.y())); - } - - m_focusResource = resource; - m_focus = surface; -} - -void Pointer::handleSurfaceDestroyed(Surface *surface) -{ - if (m_focus == surface) { - m_focus = nullptr; - m_focusResource = nullptr; - } -} - -void Pointer::sendMotion(const QPoint &pos) -{ - if (m_focusResource) - send_motion(m_focusResource->handle, m_compositor->time(), - wl_fixed_from_int(pos.x()), wl_fixed_from_int(pos.y())); -} - -void Pointer::sendButton(uint32_t button, uint32_t state) -{ - if (m_focusResource) { - uint32_t serial = m_compositor->nextSerial(); - send_button(m_focusResource->handle, serial, m_compositor->time(), - button, state); - } -} - -void Pointer::pointer_destroy_resource(wl_pointer::Resource *resource) -{ - if (m_focusResource == resource) - m_focusResource = 0; -} - -Touch::Touch(Compositor *compositor) - : wl_touch() - , m_compositor(compositor) -{ -} - -void Touch::sendDown(Surface *surface, const QPoint &position, int id) -{ - uint32_t serial = m_compositor->nextSerial(); - uint32_t time = m_compositor->time(); - Q_ASSERT(surface); - Resource *resource = resourceMap().value(surface->resource()->client()); - Q_ASSERT(resource); - auto x = wl_fixed_from_int(position.x()); - auto y = wl_fixed_from_int(position.y()); - wl_touch_send_down(resource->handle, serial, time, surface->resource()->handle, id, x, y); -} - -void Touch::sendUp(Surface *surface, int id) -{ - Resource *resource = resourceMap().value(surface->resource()->client()); - wl_touch_send_up(resource->handle, m_compositor->nextSerial(), m_compositor->time(), id); -} - -void Touch::sendMotion(Surface *surface, const QPoint &position, int id) -{ - Resource *resource = resourceMap().value(surface->resource()->client()); - uint32_t time = m_compositor->time(); - auto x = wl_fixed_from_int(position.x()); - auto y = wl_fixed_from_int(position.y()); - wl_touch_send_motion(resource->handle, time, id, x, y); -} - -void Touch::sendFrame(Surface *surface) -{ - Resource *resource = resourceMap().value(surface->resource()->client()); - wl_touch_send_frame(resource->handle); -} - -DataOffer::DataOffer() - : wl_data_offer() -{ - -} - -DataDevice::DataDevice(Compositor *compositor) - : m_compositor(compositor) -{ - -} - -void DataDevice::sendDataOffer(wl_client *client) -{ - m_dataOffer = new QtWaylandServer::wl_data_offer(client, 0, 1); - Resource *resource = resourceMap().value(client); - send_data_offer(resource->handle, m_dataOffer->resource()->handle); -} - -void DataDevice::sendEnter(Surface *surface, const QPoint& position) -{ - uint serial = m_compositor->nextSerial(); - m_focus = surface; - Resource *resource = resourceMap().value(surface->resource()->client()); - send_enter(resource->handle, serial, surface->resource()->handle, position.x(), position.y(), m_dataOffer->resource()->handle); -} - -void DataDevice::sendMotion(const QPoint &position) -{ - uint32_t time = m_compositor->time(); - Resource *resource = resourceMap().value(m_focus->resource()->client()); - send_motion(resource->handle, time, position.x(), position.y()); -} - -void DataDevice::sendDrop(Surface *surface) -{ - Resource *resource = resourceMap().value(surface->resource()->client()); - send_drop(resource->handle); -} - -void DataDevice::sendLeave(Surface *surface) -{ - Resource *resource = resourceMap().value(surface->resource()->client()); - send_leave(resource->handle); -} - -DataDevice::~DataDevice() -{ - -} - -void DataDevice::data_device_start_drag(QtWaylandServer::wl_data_device::Resource *resource, wl_resource *source, wl_resource *origin, wl_resource *icon, uint32_t serial) -{ - Q_UNUSED(resource); - Q_UNUSED(source); - Q_UNUSED(origin); - Q_UNUSED(icon); - Q_UNUSED(serial); - m_compositor->m_startDragSeen = true; -} - -DataDeviceManager::DataDeviceManager(Compositor *compositor, wl_display *display) - : wl_data_device_manager(display, 1) - , m_compositor(compositor) -{ - -} - -DataDeviceManager::~DataDeviceManager() -{ - -} - -DataDevice *DataDeviceManager::dataDevice() const -{ - return m_data_device.data(); -} - -void DataDeviceManager::data_device_manager_get_data_device(Resource *resource, uint32_t id, struct ::wl_resource *seat) -{ - Q_UNUSED(seat); - if (!m_data_device) - m_data_device.reset(new DataDevice(m_compositor)); - m_data_device->add(resource->client(), id, 1); -} - -void DataDeviceManager::data_device_manager_create_data_source(QtWaylandServer::wl_data_device_manager::Resource *resource, uint32_t id) -{ - new QtWaylandServer::wl_data_source(resource->client(), id, 1); -} - -} diff --git a/tests/auto/client/shared_old/mockinput.h b/tests/auto/client/shared_old/mockinput.h deleted file mode 100644 index d9adb3621..000000000 --- a/tests/auto/client/shared_old/mockinput.h +++ /dev/null @@ -1,172 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2016 Klarälvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef MOCKINPUT_H -#define MOCKINPUT_H - -#include <qglobal.h> - -#include "qwayland-server-wayland.h" - -#include "mockcompositor.h" - -namespace Impl { - -class Keyboard; -class Pointer; - -class Seat : public QtWaylandServer::wl_seat -{ -public: - Seat(Compositor *compositor, struct ::wl_display *display); - ~Seat(); - - Compositor *compositor() const { return m_compositor; } - - Keyboard *keyboard() const { return m_keyboard.data(); } - Pointer *pointer() const { return m_pointer.data(); } - Touch *touch() const { return m_touch.data(); } - -protected: - void seat_bind_resource(Resource *resource) override; - void seat_get_keyboard(Resource *resource, uint32_t id) override; - void seat_get_pointer(Resource *resource, uint32_t id) override; - void seat_get_touch(Resource *resource, uint32_t id) override; - -private: - Compositor *m_compositor = nullptr; - - QScopedPointer<Keyboard> m_keyboard; - QScopedPointer<Pointer> m_pointer; - QScopedPointer<Touch> m_touch; -}; - -class Keyboard : public QtWaylandServer::wl_keyboard -{ -public: - Keyboard(Compositor *compositor); - ~Keyboard(); - - Surface *focus() const { return m_focus; } - void setFocus(Surface *surface); - void handleSurfaceDestroyed(Surface *surface); - - void sendKey(uint32_t key, uint32_t state); - -protected: - void keyboard_destroy_resource(wl_keyboard::Resource *resource) override; - -private: - Compositor *m_compositor = nullptr; - - Resource *m_focusResource = nullptr; - Surface *m_focus = nullptr; -}; - -class Pointer : public QtWaylandServer::wl_pointer -{ -public: - Pointer(Compositor *compositor); - ~Pointer(); - - Surface *focus() const { return m_focus; } - - void setFocus(Surface *surface, const QPoint &pos); - void handleSurfaceDestroyed(Surface *surface); - void sendMotion(const QPoint &pos); - void sendButton(uint32_t button, uint32_t state); - -protected: - void pointer_destroy_resource(wl_pointer::Resource *resource) override; - -private: - Compositor *m_compositor = nullptr; - - Resource *m_focusResource = nullptr; - Surface *m_focus = nullptr; -}; - -class Touch : public QtWaylandServer::wl_touch -{ -public: - Touch(Compositor *compositor); - void sendDown(Surface *surface, const QPoint &position, int id); - void sendUp(Surface *surface, int id); - void sendMotion(Surface *surface, const QPoint &position, int id); - void sendFrame(Surface *surface); -private: - Compositor *m_compositor = nullptr; -}; - -class DataOffer : public QtWaylandServer::wl_data_offer -{ -public: - DataOffer(); -}; - -class DataDevice : public QtWaylandServer::wl_data_device -{ -public: - DataDevice(Compositor *compositor); - void sendDataOffer(wl_client *client); - void sendEnter(Surface *surface, const QPoint &position); - void sendMotion(const QPoint &position); - void sendDrop(Surface *surface); - void sendLeave(Surface *surface); - ~DataDevice(); - -protected: - void data_device_start_drag(Resource *resource, struct ::wl_resource *source, struct ::wl_resource *origin, struct ::wl_resource *icon, uint32_t serial) override; - -private: - Compositor *m_compositor = nullptr; - QtWaylandServer::wl_data_offer *m_dataOffer = nullptr; - Surface* m_focus = nullptr; -}; - -class DataDeviceManager : public QtWaylandServer::wl_data_device_manager -{ -public: - DataDeviceManager(Compositor *compositor, struct ::wl_display *display); - ~DataDeviceManager(); - DataDevice *dataDevice() const; - -protected: - void data_device_manager_get_data_device(Resource *resource, uint32_t id, struct ::wl_resource *seat) override; - void data_device_manager_create_data_source(Resource *resource, uint32_t id) override; - -private: - Compositor *m_compositor = nullptr; - - QScopedPointer<DataDevice> m_data_device; -}; - -} - -#endif // MOCKINPUT_H diff --git a/tests/auto/client/shared_old/mockiviapplication.cpp b/tests/auto/client/shared_old/mockiviapplication.cpp deleted file mode 100644 index 29a308993..000000000 --- a/tests/auto/client/shared_old/mockiviapplication.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "mockiviapplication.h" -#include "mocksurface.h" -#include "mockcompositor.h" - -namespace Impl { - -void Compositor::sendIviSurfaceConfigure(void *data, const QList<QVariant> ¶meters) -{ - Q_UNUSED(data); - IviSurface *iviSurface = resolveIviSurface(parameters.at(0)); - Q_ASSERT(iviSurface && iviSurface->resource()); - QSize size = parameters.at(1).toSize(); - Q_ASSERT(!size.isEmpty()); - iviSurface->send_configure(size.width(), size.height()); -} - -IviSurface::IviSurface(IviApplication *iviApplication, Surface *surface, uint iviId, wl_client *client, uint32_t id) - : QtWaylandServer::ivi_surface(client, id, 1) - , m_surface(surface) - , m_iviApplication(iviApplication) - , m_iviId(iviId) - , m_mockIviSurface(new MockIviSurface(this)) -{ - iviApplication->addIviSurface(this); - surface->map(); -} - -IviSurface::~IviSurface() -{ - m_iviApplication->removeIviSurface(this); - m_mockIviSurface->m_iviSurface = nullptr; -} - -void IviSurface::ivi_surface_destroy(Resource *resource) -{ - wl_resource_destroy(resource->handle); -} - -void IviApplication::ivi_application_surface_create(Resource *resource, uint32_t ivi_id, ::wl_resource *surface, uint32_t id) -{ - new IviSurface(this, Surface::fromResource(surface), ivi_id, resource->client(), id); -} - -} // namespace Impl diff --git a/tests/auto/client/shared_old/mockiviapplication.h b/tests/auto/client/shared_old/mockiviapplication.h deleted file mode 100644 index 4d65eeaba..000000000 --- a/tests/auto/client/shared_old/mockiviapplication.h +++ /dev/null @@ -1,85 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef MOCKIVIAPPLICATION_H -#define MOCKIVIAPPLICATION_H - -#include <qwayland-server-ivi-application.h> - -#include <QSharedPointer> -#include <QVector> - -class MockIviSurface; - -namespace Impl { - -class Surface; -class IviApplication; - -class IviSurface : public QtWaylandServer::ivi_surface -{ -public: - IviSurface(IviApplication *iviApplication, Surface *surface, uint iviId, wl_client *client, uint32_t id); - ~IviSurface() override; - IviApplication *iviApplication() const { return m_iviApplication; } - Surface *surface() const { return m_surface; } - uint iviId() const { return m_iviId; } - - QSharedPointer<MockIviSurface> mockIviSurface() const { return m_mockIviSurface; } - -protected: - void ivi_surface_destroy_resource(Resource *) override { delete this; } - void ivi_surface_destroy(Resource *resource) override; - -private: - Surface *m_surface = nullptr; - IviApplication *m_iviApplication = nullptr; - const uint m_iviId = 0; - QSharedPointer<MockIviSurface> m_mockIviSurface; -}; - -class IviApplication : public QtWaylandServer::ivi_application -{ -public: - explicit IviApplication(::wl_display *display) : ivi_application(display, 1) {} - QVector<IviSurface *> iviSurfaces() const { return m_iviSurfaces; } - -protected: - void ivi_application_surface_create(Resource *resource, uint32_t ivi_id, ::wl_resource *surface, uint32_t id) override; - -private: - void addIviSurface(IviSurface *iviSurface) { m_iviSurfaces.append(iviSurface); } - void removeIviSurface(IviSurface *iviSurface) { m_iviSurfaces.removeOne(iviSurface); } - QVector<IviSurface *> m_iviSurfaces; - - friend class IviSurface; -}; - -} // namespace Impl - -#endif // MOCKIVIAPPLICATION_H diff --git a/tests/auto/client/shared_old/mockoutput.cpp b/tests/auto/client/shared_old/mockoutput.cpp deleted file mode 100644 index cb7285959..000000000 --- a/tests/auto/client/shared_old/mockoutput.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "mockcompositor.h" -#include "mockoutput.h" - -#include <QDebug> - -namespace Impl { - -void Compositor::setOutputMode(void *data, const QList<QVariant> ¶meters) -{ - Compositor *compositor = static_cast<Compositor *>(data); - QSize size = parameters.first().toSize(); - Output *output = compositor->m_outputs.first(); - Q_ASSERT(output); - output->setCurrentMode(size); -} - -Output::Output(wl_display *display, const QSize &resolution, const QPoint &position) - : wl_output(display, 2) - , m_size(resolution) - , m_position(position) - , m_physicalSize(520, 320) - , m_mockOutput(new MockOutput(this)) -{ -} - -void Output::setCurrentMode(const QSize &size) -{ - m_size = size; - for (Resource *resource : resourceMap()) { - sendCurrentMode(resource); - send_done(resource->handle); - } -} - -void Output::output_bind_resource(QtWaylandServer::wl_output::Resource *resource) -{ - sendGeometry(resource); - sendCurrentMode(resource); - send_done(resource->handle); -} - -void Output::sendGeometry(Resource *resource) -{ - const int subPixel = 0; - const int transform = 0; - - send_geometry(resource->handle, - m_position.x(), m_position.y(), - m_physicalSize.width(), m_physicalSize.height(), - subPixel, "", "", transform ); -} - -void Output::sendCurrentMode(Resource *resource) -{ - send_mode(resource->handle, - WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED, - m_size.width(), m_size.height(), 60000); -} - -} // Impl - -MockOutput::MockOutput(Impl::Output *output) - : m_output(output) -{ -} diff --git a/tests/auto/client/shared_old/mockoutput.h b/tests/auto/client/shared_old/mockoutput.h deleted file mode 100644 index d5a2bb56b..000000000 --- a/tests/auto/client/shared_old/mockoutput.h +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef MOCKOUTPUT_H -#define MOCKOUTPUT_H - -#include <qglobal.h> - -#include "qwayland-server-wayland.h" - -#include "mockcompositor.h" - -namespace Impl { - -class Output : public QtWaylandServer::wl_output -{ -public: - Output(::wl_display *display, const QSize &resolution, const QPoint &position); - - QSharedPointer<MockOutput> mockOutput() const { return m_mockOutput; } - void setCurrentMode(const QSize &size); - -protected: - void output_bind_resource(Resource *resource) override; - -private: - void sendGeometry(Resource *resource); - void sendCurrentMode(Resource *resource); - QSize m_size; - QPoint m_position; - const QSize m_physicalSize; - QSharedPointer<MockOutput> m_mockOutput; -}; - -} - -#endif // MOCKOUTPUT_H diff --git a/tests/auto/client/shared_old/mocksurface.cpp b/tests/auto/client/shared_old/mocksurface.cpp deleted file mode 100644 index e9df5f907..000000000 --- a/tests/auto/client/shared_old/mocksurface.cpp +++ /dev/null @@ -1,162 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "mocksurface.h" -#include "mockoutput.h" -#include "mockcompositor.h" -#include "mockwlshell.h" - -#include <QDebug> - -namespace Impl { - -void Compositor::sendShellSurfaceConfigure(void *data, const QList<QVariant> ¶meters) -{ - Compositor *compositor = static_cast<Compositor *>(data); - Surface *surface = resolveSurface(parameters.at(0)); - QSize size = parameters.at(1).toSize(); - Q_ASSERT(size.isValid()); - if (auto toplevel = surface->xdgToplevelV6()) { - QVector<uint> states = { ZXDG_TOPLEVEL_V6_STATE_ACTIVATED }; - auto statesBytes = QByteArray::fromRawData(reinterpret_cast<const char *>(states.data()), - states.size() * static_cast<int>(sizeof(uint))); - toplevel->send_configure(size.width(), size.height(), statesBytes); - toplevel->xdgSurface()->sendConfigure(compositor->nextSerial()); - } else if (auto wlShellSurface = surface->wlShellSurface()) { - const uint edges = 0; - wlShellSurface->send_configure(edges, size.width(), size.height()); - } else { - qWarning() << "The mocking framework doesn't know how to send a configure event for this surface"; - } -} - -Surface::Surface(wl_client *client, uint32_t id, int v, Compositor *compositor) - : QtWaylandServer::wl_surface(client, id, v) - , m_compositor(compositor) - , m_mockSurface(new MockSurface(this)) -{ -} - -Surface::~Surface() -{ - m_mockSurface->m_surface = 0; -} - -void Surface::map() -{ - m_mapped = true; -} - -bool Surface::isMapped() const -{ - return m_mapped; -} - -Surface *Surface::fromResource(struct ::wl_resource *resource) -{ - if (auto *r = Resource::fromResource(resource)) - return static_cast<Surface *>(r->surface_object); - return nullptr; -} - -void Surface::surface_destroy_resource(Resource *) -{ - compositor()->removeSurface(this); - delete this; -} - -void Surface::surface_destroy(Resource *resource) -{ - if (m_wlShellSurface) // on wl-shell the shell surface is automatically destroyed with the surface - wl_resource_destroy(m_wlShellSurface->resource()->handle); - Q_ASSERT(!m_wlShellSurface); - Q_ASSERT(!m_xdgSurfaceV6); - wl_resource_destroy(resource->handle); -} - -void Surface::surface_attach(Resource *resource, struct wl_resource *buffer, int x, int y) -{ - if (m_xdgSurfaceV6) { - // It's a protocol error to attach a buffer to an xdgSurface that's not configured - Q_ASSERT(xdgSurfaceV6()->configureSent()); - } - - Q_UNUSED(resource); - Q_UNUSED(x); - Q_UNUSED(y); - m_buffer = buffer; - - if (!buffer) - m_mockSurface->image = QImage(); -} - -void Surface::surface_damage(Resource *resource, - int32_t x, int32_t y, int32_t width, int32_t height) -{ - Q_UNUSED(resource); - Q_UNUSED(x); - Q_UNUSED(y); - Q_UNUSED(width); - Q_UNUSED(height); -} - -void Surface::surface_frame(Resource *resource, - uint32_t callback) -{ - wl_resource *frameCallback = wl_resource_create(resource->client(), &wl_callback_interface, 1, callback); - m_frameCallbackList << frameCallback; -} - -void Surface::surface_commit(Resource *resource) -{ - Q_UNUSED(resource); - - if (m_buffer) { - struct ::wl_shm_buffer *shm_buffer = wl_shm_buffer_get(m_buffer); - if (shm_buffer) { - int stride = wl_shm_buffer_get_stride(shm_buffer); - uint format = wl_shm_buffer_get_format(shm_buffer); - Q_UNUSED(format); - void *data = wl_shm_buffer_get_data(shm_buffer); - const uchar *char_data = static_cast<const uchar *>(data); - QImage img(char_data, wl_shm_buffer_get_width(shm_buffer), wl_shm_buffer_get_height(shm_buffer), stride, QImage::Format_ARGB32_Premultiplied); - m_mockSurface->image = img; - } - } - - for (wl_resource *frameCallback : qExchange(m_frameCallbackList, {})) { - wl_callback_send_done(frameCallback, m_compositor->time()); - wl_resource_destroy(frameCallback); - } -} - -} -MockSurface::MockSurface(Impl::Surface *surface) - : m_surface(surface) -{ -} diff --git a/tests/auto/client/shared_old/mocksurface.h b/tests/auto/client/shared_old/mocksurface.h deleted file mode 100644 index 949dc23dd..000000000 --- a/tests/auto/client/shared_old/mocksurface.h +++ /dev/null @@ -1,87 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef MOCKSURFACE_H -#define MOCKSURFACE_H - -#include <qglobal.h> - -#include "qwayland-server-wayland.h" - -#include "mockcompositor.h" - -namespace Impl { - -class XdgToplevelV6; -class WlShellSurface; - -class Surface : public QtWaylandServer::wl_surface -{ -public: - Surface(wl_client *client, uint32_t id, int v, Compositor *compositor); - ~Surface(); - - Compositor *compositor() const { return m_compositor; } - static Surface *fromResource(struct ::wl_resource *resource); - void map(); - bool isMapped() const; - XdgSurfaceV6 *xdgSurfaceV6() const { return m_xdgSurfaceV6; } - XdgToplevelV6 *xdgToplevelV6() const { return m_xdgSurfaceV6 ? m_xdgSurfaceV6->toplevel() : nullptr; } - WlShellSurface *wlShellSurface() const { return m_wlShellSurface; } - - QSharedPointer<MockSurface> mockSurface() const { return m_mockSurface; } - -protected: - - void surface_destroy_resource(Resource *resource) override; - - void surface_destroy(Resource *resource) override; - void surface_attach(Resource *resource, - struct wl_resource *buffer, int x, int y) override; - void surface_damage(Resource *resource, - int32_t x, int32_t y, int32_t width, int32_t height) override; - void surface_frame(Resource *resource, - uint32_t callback) override; - void surface_commit(Resource *resource) override; -private: - wl_resource *m_buffer = nullptr; - XdgSurfaceV6 *m_xdgSurfaceV6 = nullptr; - WlShellSurface *m_wlShellSurface = nullptr; - - Compositor *m_compositor = nullptr; - QSharedPointer<MockSurface> m_mockSurface; - QList<wl_resource *> m_frameCallbackList; - bool m_mapped = false; - - friend class XdgSurfaceV6; - friend class WlShellSurface; -}; - -} - -#endif // MOCKSURFACE_H diff --git a/tests/auto/client/shared_old/mockwlshell.cpp b/tests/auto/client/shared_old/mockwlshell.cpp deleted file mode 100644 index 50e539932..000000000 --- a/tests/auto/client/shared_old/mockwlshell.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "mockwlshell.h" -#include "mocksurface.h" - -namespace Impl { - -WlShellSurface::WlShellSurface(wl_client *client, int id, Surface *surface) - : QtWaylandServer::wl_shell_surface(client, id, 1) - , m_surface(surface) -{ - surface->m_wlShellSurface = this; - surface->map(); -} - -WlShellSurface::~WlShellSurface() -{ - m_surface->m_wlShellSurface = nullptr; -} - -void WlShell::shell_get_shell_surface(QtWaylandServer::wl_shell::Resource *resource, uint32_t id, wl_resource *surface) -{ - new WlShellSurface(resource->client(), id, Surface::fromResource(surface)); -} - -} // namespace Impl diff --git a/tests/auto/client/shared_old/mockwlshell.h b/tests/auto/client/shared_old/mockwlshell.h deleted file mode 100644 index 3da586ca8..000000000 --- a/tests/auto/client/shared_old/mockwlshell.h +++ /dev/null @@ -1,58 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <qwayland-server-wayland.h> - -#ifndef MOCKWLSHELL_H -#define MOCKWLSHELL_H - -namespace Impl { - -class Surface; - -class WlShellSurface : public QtWaylandServer::wl_shell_surface -{ -public: - explicit WlShellSurface(::wl_client *client, int id, Surface *surface); - ~WlShellSurface() override; - void shell_surface_destroy_resource(Resource *) override { delete this; } - -private: - Surface *m_surface = nullptr; -}; - -class WlShell : public QtWaylandServer::wl_shell -{ -public: - explicit WlShell(::wl_display *display) : wl_shell(display, 1) {} - void shell_get_shell_surface(Resource *resource, uint32_t id, ::wl_resource *surface) override; -}; - -} // namespace Impl - -#endif // MOCKWLSHELL_H diff --git a/tests/auto/client/shared_old/mockxdgshellv6.cpp b/tests/auto/client/shared_old/mockxdgshellv6.cpp deleted file mode 100644 index 05eff74ad..000000000 --- a/tests/auto/client/shared_old/mockxdgshellv6.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "mockxdgshellv6.h" -#include "mocksurface.h" -#include "mockcompositor.h" - -namespace Impl { - -void Compositor::sendXdgToplevelV6Configure(void *data, const QList<QVariant> ¶meters) -{ - Compositor *compositor = static_cast<Compositor *>(data); - XdgToplevelV6 *toplevel = resolveToplevel(parameters.at(0)); - Q_ASSERT(toplevel && toplevel->resource()); - QSize size = parameters.at(1).toSize(); - Q_ASSERT(size.isValid()); - auto statesBytes = parameters.at(2).toByteArray(); - toplevel->send_configure(size.width(), size.height(), statesBytes); - toplevel->xdgSurface()->send_configure(compositor->nextSerial()); -} - -XdgSurfaceV6::XdgSurfaceV6(XdgShellV6 *shell, Surface *surface, wl_client *client, uint32_t id) - : QtWaylandServer::zxdg_surface_v6(client, id, 1) - , m_surface(surface) - , m_shell(shell) -{ - m_surface->m_xdgSurfaceV6 = this; -} - -XdgSurfaceV6::~XdgSurfaceV6() -{ - m_surface->m_xdgSurfaceV6 = nullptr; -} - -void XdgSurfaceV6::sendConfigure(uint32_t serial) -{ - send_configure(serial); - m_configureSent = true; -} - -void XdgSurfaceV6::zxdg_surface_v6_get_toplevel(QtWaylandServer::zxdg_surface_v6::Resource *resource, uint32_t id) -{ - int version = wl_resource_get_version(resource->handle); - m_toplevel = new XdgToplevelV6(this, resource->client(), id, version); -} - -void XdgSurfaceV6::zxdg_surface_v6_set_window_geometry(QtWaylandServer::zxdg_surface_v6::Resource *resource, int32_t x, int32_t y, int32_t width, int32_t height) -{ - Q_UNUSED(resource); - if (m_toplevel) { - QRect geometry(x, y, width, height); - emit m_toplevel->mockToplevel()->windowGeometryRequested(geometry); - } -} - -void XdgSurfaceV6::zxdg_surface_v6_destroy(QtWaylandServer::zxdg_surface_v6::Resource *resource) -{ - Q_ASSERT(!m_toplevel); - wl_resource_destroy(resource->handle); -} - -XdgToplevelV6::XdgToplevelV6(XdgSurfaceV6 *xdgSurface, wl_client *client, uint32_t id, int version) - : QtWaylandServer::zxdg_toplevel_v6(client, id, version) - , m_xdgSurface(xdgSurface) - , m_mockToplevel(new MockXdgToplevelV6(this)) -{ - auto *surface = m_xdgSurface->surface(); - m_xdgSurface->shell()->addToplevel(this); - surface->map(); -} - -XdgToplevelV6::~XdgToplevelV6() -{ - m_xdgSurface->shell()->removeToplevel(this); - m_mockToplevel->m_toplevel = nullptr; -} - -void XdgToplevelV6::zxdg_toplevel_v6_destroy(QtWaylandServer::zxdg_toplevel_v6::Resource *resource) -{ - m_xdgSurface->m_toplevel = nullptr; - wl_resource_destroy(resource->handle); -} - -void XdgToplevelV6::zxdg_toplevel_v6_set_minimized(QtWaylandServer::zxdg_toplevel_v6::Resource *resource) -{ - Q_UNUSED(resource); - emit m_mockToplevel->setMinimizedRequested(); -} - -void XdgToplevelV6::zxdg_toplevel_v6_set_maximized(QtWaylandServer::zxdg_toplevel_v6::Resource *resource) -{ - Q_UNUSED(resource); - emit m_mockToplevel->setMaximizedRequested(); -} - -void XdgToplevelV6::zxdg_toplevel_v6_unset_maximized(QtWaylandServer::zxdg_toplevel_v6::Resource *resource) -{ - Q_UNUSED(resource); - emit m_mockToplevel->unsetMaximizedRequested(); -} - -void XdgToplevelV6::zxdg_toplevel_v6_set_fullscreen(QtWaylandServer::zxdg_toplevel_v6::Resource *resource, wl_resource *output) -{ - Q_UNUSED(resource); - Q_UNUSED(output); - emit m_mockToplevel->setFullscreenRequested(); -} - -void XdgToplevelV6::zxdg_toplevel_v6_unset_fullscreen(QtWaylandServer::zxdg_toplevel_v6::Resource *resource) -{ - Q_UNUSED(resource); - emit m_mockToplevel->unsetFullscreenRequested(); -} - -void Impl::XdgShellV6::zxdg_shell_v6_get_xdg_surface(QtWaylandServer::zxdg_shell_v6::Resource *resource, uint32_t id, wl_resource *surface) -{ - new XdgSurfaceV6(this, Surface::fromResource(surface), resource->client(), id); -} - -} // namespace Impl diff --git a/tests/auto/client/shared_old/mockxdgshellv6.h b/tests/auto/client/shared_old/mockxdgshellv6.h deleted file mode 100644 index a238fa562..000000000 --- a/tests/auto/client/shared_old/mockxdgshellv6.h +++ /dev/null @@ -1,114 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <qwayland-server-xdg-shell-unstable-v6.h> - -#include <QSharedPointer> -#include <QVector> - -#ifndef MOCKXDGSHELLV6_H -#define MOCKXDGSHELLV6_H - -class MockXdgToplevelV6; - -namespace Impl { - -class XdgToplevelV6; -class XdgShellV6; -class Surface; - -class XdgSurfaceV6 : public QtWaylandServer::zxdg_surface_v6 -{ -public: - XdgSurfaceV6(XdgShellV6 *shell, Surface *surface, wl_client *client, uint32_t id); - ~XdgSurfaceV6() override; - XdgShellV6 *shell() const { return m_shell; } - Surface *surface() const { return m_surface; } - XdgToplevelV6 *toplevel() const { return m_toplevel; } - - void sendConfigure(uint32_t serial); - bool configureSent() const { return m_configureSent; } - -protected: - void zxdg_surface_v6_destroy_resource(Resource *) override { delete this; } - void zxdg_surface_v6_get_toplevel(Resource *resource, uint32_t id) override; - void zxdg_surface_v6_set_window_geometry(Resource *resource, int32_t x, int32_t y, int32_t width, int32_t height) override; - void zxdg_surface_v6_destroy(Resource *resource) override; - -private: - Surface *m_surface = nullptr; - XdgToplevelV6 *m_toplevel = nullptr; - XdgShellV6 *m_shell = nullptr; - bool m_configureSent = false; - - friend class XdgToplevelV6; -}; - -class XdgToplevelV6 : public QtWaylandServer::zxdg_toplevel_v6 -{ -public: - XdgToplevelV6(XdgSurfaceV6 *xdgSurface, wl_client *client, uint32_t id, int version); - ~XdgToplevelV6() override; - XdgSurfaceV6 *xdgSurface() const { return m_xdgSurface; } - - QSharedPointer<MockXdgToplevelV6> mockToplevel() const { return m_mockToplevel; } - -protected: - void zxdg_toplevel_v6_destroy_resource(Resource *) override { delete this; } - void zxdg_toplevel_v6_destroy(Resource *resource) override; - void zxdg_toplevel_v6_set_minimized(Resource *resource) override; - void zxdg_toplevel_v6_set_maximized(Resource *resource) override; - void zxdg_toplevel_v6_unset_maximized(Resource *resource) override; - void zxdg_toplevel_v6_set_fullscreen(Resource *resource, struct ::wl_resource *output) override; - void zxdg_toplevel_v6_unset_fullscreen(Resource *resource) override; - -private: - XdgSurfaceV6 *m_xdgSurface = nullptr; - QSharedPointer<MockXdgToplevelV6> m_mockToplevel; -}; - -class XdgShellV6 : public QtWaylandServer::zxdg_shell_v6 -{ -public: - explicit XdgShellV6(::wl_display *display) : zxdg_shell_v6(display, 1) {} - QVector<XdgToplevelV6 *> toplevels() const { return m_toplevels; } - -protected: - void zxdg_shell_v6_get_xdg_surface(Resource *resource, uint32_t id, ::wl_resource *surface) override; - -private: - void addToplevel(XdgToplevelV6 *toplevel) { m_toplevels.append(toplevel); } - void removeToplevel(XdgToplevelV6 *toplevel) { m_toplevels.removeOne(toplevel); } - QVector<XdgToplevelV6 *> m_toplevels; - - friend class XdgToplevelV6; -}; - -} // namespace Impl - -#endif // MOCKXDGSHELLV6_H diff --git a/tests/auto/client/shared_old/shared_old.pri b/tests/auto/client/shared_old/shared_old.pri deleted file mode 100644 index 467e98115..000000000 --- a/tests/auto/client/shared_old/shared_old.pri +++ /dev/null @@ -1,34 +0,0 @@ -CONFIG += testcase link_pkgconfig -QT += testlib -QT += core-private gui-private waylandclient-private - -QMAKE_USE += wayland-client wayland-server - -CONFIG += wayland-scanner -WAYLANDSERVERSOURCES += \ - ../../../../src/3rdparty/protocol/ivi-application.xml \ - ../../../../src/3rdparty/protocol/wayland.xml \ - ../../../../src/3rdparty/protocol/xdg-shell-unstable-v6.xml \ - ../../../../src/3rdparty/protocol/fullscreen-shell-unstable-v1.xml - -INCLUDEPATH += ../shared_old - -SOURCES += \ - ../shared_old/mockcompositor.cpp \ - ../shared_old/mockfullscreenshellv1.cpp \ - ../shared_old/mockinput.cpp \ - ../shared_old/mockiviapplication.cpp \ - ../shared_old/mockwlshell.cpp \ - ../shared_old/mockxdgshellv6.cpp \ - ../shared_old/mocksurface.cpp \ - ../shared_old/mockoutput.cpp - -HEADERS += \ - ../shared_old/mockcompositor.h \ - ../shared_old/mockfullscreenshellv1.h \ - ../shared_old/mockinput.h \ - ../shared_old/mockiviapplication.h \ - ../shared_old/mockwlshell.h \ - ../shared_old/mockxdgshellv6.h \ - ../shared_old/mocksurface.h \ - ../shared_old/mockoutput.h diff --git a/tests/auto/client/surface/CMakeLists.txt b/tests/auto/client/surface/CMakeLists.txt new file mode 100644 index 000000000..b175a5331 --- /dev/null +++ b/tests/auto/client/surface/CMakeLists.txt @@ -0,0 +1,15 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +# Generated from surface.pro. + +##################################################################### +## tst_surface Test: +##################################################################### + +qt_internal_add_test(tst_surface + SOURCES + tst_surface.cpp + LIBRARIES + SharedClientTest +) diff --git a/tests/auto/client/surface/surface.pro b/tests/auto/client/surface/surface.pro deleted file mode 100644 index 36882aa2d..000000000 --- a/tests/auto/client/surface/surface.pro +++ /dev/null @@ -1,5 +0,0 @@ -include (../shared/shared.pri) - -TARGET = tst_surface -SOURCES += tst_surface.cpp - diff --git a/tests/auto/client/surface/tst_surface.cpp b/tests/auto/client/surface/tst_surface.cpp index b8a65f159..06e625155 100644 --- a/tests/auto/client/surface/tst_surface.cpp +++ b/tests/auto/client/surface/tst_surface.cpp @@ -1,35 +1,10 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "mockcompositor.h" #include <QtGui/QRasterWindow> #if QT_CONFIG(opengl) -#include <QtGui/QOpenGLWindow> +#include <QtOpenGL/QOpenGLWindow> #endif using namespace MockCompositor; @@ -37,6 +12,8 @@ using namespace MockCompositor; class tst_surface : public QObject, private DefaultCompositor { Q_OBJECT +public: + explicit tst_surface(); private slots: void cleanup() { QTRY_VERIFY2(isClean(), qPrintable(dirtyMessage())); } void createDestroySurface(); @@ -51,6 +28,11 @@ private slots: void createSubsurfaceForHiddenParent(); }; +tst_surface::tst_surface() +{ + m_config.autoFrameCallback = false; +} + void tst_surface::createDestroySurface() { QWindow window; @@ -64,7 +46,6 @@ void tst_surface::createDestroySurface() void tst_surface::waitForFrameCallbackRaster() { - QSKIP("TODO: This currently fails, needs a fix"); class TestWindow : public QRasterWindow { public: explicit TestWindow() { resize(40, 40); } @@ -77,11 +58,11 @@ void tst_surface::waitForFrameCallbackRaster() TestWindow window; window.show(); QCOMPOSITOR_TRY_VERIFY(xdgToplevel()); - QSignalSpy bufferSpy(exec([=] { return xdgSurface()->m_surface; }), &Surface::bufferCommitted); - exec([=] { xdgToplevel()->sendCompleteConfigure(); }); + QSignalSpy bufferSpy(exec([&] { return xdgSurface()->m_surface; }), &Surface::bufferCommitted); + exec([&] { xdgToplevel()->sendCompleteConfigure(); }); // We should get the first buffer without waiting for a frame callback - QTRY_COMPARE(bufferSpy.count(), 1); + QTRY_COMPARE(bufferSpy.size(), 1); bufferSpy.removeFirst(); // Make sure we follow frame callbacks for some frames @@ -92,7 +73,7 @@ void tst_surface::waitForFrameCallbackRaster() QVERIFY(!xdgToplevel()->surface()->m_waitingFrameCallbacks.empty()); xdgToplevel()->surface()->sendFrameCallbacks(); }); - QTRY_COMPARE(bufferSpy.count(), 1); + QTRY_COMPARE(bufferSpy.size(), 1); bufferSpy.removeFirst(); } } @@ -100,7 +81,6 @@ void tst_surface::waitForFrameCallbackRaster() #if QT_CONFIG(opengl) void tst_surface::waitForFrameCallbackGl() { - QSKIP("TODO: This currently fails, needs a fix"); class TestWindow : public QOpenGLWindow { public: explicit TestWindow() @@ -119,22 +99,26 @@ void tst_surface::waitForFrameCallbackGl() TestWindow window; window.show(); QCOMPOSITOR_TRY_VERIFY(xdgToplevel()); - QSignalSpy bufferSpy(exec([=] { return xdgSurface()->m_surface; }), &Surface::bufferCommitted); - exec([=] { xdgToplevel()->sendCompleteConfigure(); }); + QSignalSpy bufferSpy(exec([&] { return xdgSurface()->m_surface; }), &Surface::bufferCommitted); + exec([&] { xdgToplevel()->sendCompleteConfigure(); }); // We should get the first buffer without waiting for a frame callback - QTRY_COMPARE(bufferSpy.count(), 1); + QTRY_COMPARE(bufferSpy.size(), 1); bufferSpy.removeFirst(); // Make sure we follow frame callbacks for some frames for (int i = 0; i < 5; ++i) { xdgPingAndWaitForPong(); // Make sure things have happened on the client + if (!qEnvironmentVariableIntValue("QT_WAYLAND_DISABLE_WINDOWDECORATION") && i == 0) { + QCOMPARE(bufferSpy.size(), 1); + bufferSpy.removeFirst(); + } exec([&] { QVERIFY(bufferSpy.empty()); // Make sure no extra buffers have arrived QVERIFY(!xdgToplevel()->surface()->m_waitingFrameCallbacks.empty()); xdgToplevel()->surface()->sendFrameCallbacks(); }); - QTRY_COMPARE(bufferSpy.count(), 1); + QTRY_COMPARE(bufferSpy.size(), 1); bufferSpy.removeFirst(); } } @@ -151,8 +135,8 @@ void tst_surface::negotiateShmFormat() window.resize(64, 48); window.show(); QCOMPOSITOR_TRY_VERIFY(xdgToplevel()); - QSignalSpy bufferSpy(exec([=] { return xdgSurface()->m_surface; }), &Surface::bufferCommitted); - const uint serial = exec([=] { return xdgToplevel()->sendCompleteConfigure(); }); + QSignalSpy bufferSpy(exec([&] { return xdgSurface()->m_surface; }), &Surface::bufferCommitted); + const uint serial = exec([&] { return xdgToplevel()->sendCompleteConfigure(); }); QCOMPOSITOR_TRY_COMPARE(xdgSurface()->m_committedConfigureSerial, serial); exec([&] { Buffer *buffer = xdgToplevel()->surface()->m_committed.buffer; @@ -167,17 +151,40 @@ void tst_surface::negotiateShmFormat() void tst_surface::createSubsurface() { QRasterWindow window; - window.resize(64, 64); - window.show(); - QCOMPOSITOR_TRY_VERIFY(xdgToplevel()); - exec([=] { xdgToplevel()->sendCompleteConfigure(); }); - QCOMPOSITOR_TRY_VERIFY(xdgSurface()->m_committedConfigureSerial); + window.setObjectName("main"); + window.resize(200, 200); QRasterWindow subWindow; + subWindow.setObjectName("subwindow"); subWindow.setParent(&window); subWindow.resize(64, 64); + + window.show(); subWindow.show(); + QCOMPOSITOR_TRY_VERIFY(subSurface()); + QCOMPOSITOR_TRY_VERIFY(xdgToplevel()); + exec([&] { xdgToplevel()->sendCompleteConfigure(); }); + QCOMPOSITOR_TRY_VERIFY(xdgSurface()->m_committedConfigureSerial); + + const Surface *mainSurface = exec([&] {return surface(0);}); + const Surface *childSurface = exec([&] {return surface(1);}); + QSignalSpy mainSurfaceCommitSpy(mainSurface, &Surface::commit); + QSignalSpy childSurfaceCommitSpy(childSurface, &Surface::commit); + + // Move subsurface. The parent should redraw and commit + subWindow.setGeometry(100, 100, 64, 64); + // the toplevel should commit to indicate the subsurface moved + QCOMPOSITOR_TRY_COMPARE(mainSurfaceCommitSpy.size(), 1); + mainSurfaceCommitSpy.clear(); + childSurfaceCommitSpy.clear(); + + // Move and resize the subSurface. The parent should redraw and commit + // The child should also redraw + subWindow.setGeometry(50, 50, 80, 80); + QCOMPOSITOR_TRY_COMPARE(mainSurfaceCommitSpy.size(), 1); + QCOMPOSITOR_TRY_COMPARE(childSurfaceCommitSpy.size(), 1); + } // Used to cause a crash in libwayland (QTBUG-79674) @@ -187,7 +194,7 @@ void tst_surface::createSubsurfaceForHiddenParent() window.resize(64, 64); window.show(); QCOMPOSITOR_TRY_VERIFY(xdgToplevel()); - exec([=] { xdgToplevel()->sendCompleteConfigure(); }); + exec([&] { xdgToplevel()->sendCompleteConfigure(); }); QCOMPOSITOR_TRY_VERIFY(xdgSurface()->m_committedConfigureSerial); window.hide(); @@ -199,6 +206,10 @@ void tst_surface::createSubsurfaceForHiddenParent() // Make sure the client doesn't quit before it has a chance to crash xdgPingAndWaitForPong(); + + // Make sure the subsurface was actually created + const Subsurface *subsurface = exec([&] {return subSurface(0);}); + QVERIFY(subsurface); } QCOMPOSITOR_TEST_MAIN(tst_surface) diff --git a/tests/auto/client/tabletv2/CMakeLists.txt b/tests/auto/client/tabletv2/CMakeLists.txt new file mode 100644 index 000000000..1400a511a --- /dev/null +++ b/tests/auto/client/tabletv2/CMakeLists.txt @@ -0,0 +1,15 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +# Generated from tabletv2.pro. + +##################################################################### +## tst_tabletv2 Test: +##################################################################### + +qt_internal_add_test(tst_tabletv2 + SOURCES + tst_tabletv2.cpp + LIBRARIES + SharedClientTest +) diff --git a/tests/auto/client/tabletv2/tst_tabletv2.cpp b/tests/auto/client/tabletv2/tst_tabletv2.cpp new file mode 100644 index 000000000..85df099f9 --- /dev/null +++ b/tests/auto/client/tabletv2/tst_tabletv2.cpp @@ -0,0 +1,893 @@ +// Copyright (C) 2019 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "mockcompositor.h" + +#include <qwayland-server-tablet-unstable-v2.h> + +#include <QtGui/QRasterWindow> + +using namespace MockCompositor; + +constexpr int tabletVersion = 1; // protocol VERSION, not the name suffix (_v2) + +class TabletManagerV2; +class TabletSeatV2; + +class TabletV2 : public QObject, public QtWaylandServer::zwp_tablet_v2 +{ + Q_OBJECT +public: + explicit TabletV2(TabletSeatV2 *tabletSeat) + : m_tabletSeat(tabletSeat) + { + } + + void send_removed() = delete; + void send_removed(struct ::wl_resource *resource) = delete; + void sendRemoved(); + + QPointer<TabletSeatV2> m_tabletSeat; // destroy order is not guaranteed +protected: + void zwp_tablet_v2_destroy(Resource *resource) override; +}; + +class TabletToolV2 : public QObject, public QtWaylandServer::zwp_tablet_tool_v2 +{ + Q_OBJECT +public: + using ToolType = QtWaylandServer::zwp_tablet_tool_v2::type; + explicit TabletToolV2(TabletSeatV2 *tabletSeat, ToolType toolType, quint64 hardwareSerial) + : m_tabletSeat(tabletSeat) + , m_toolType(toolType) + , m_hardwareSerial(hardwareSerial) + { + } + + wl_resource *toolResource() // for convenience + { + Q_ASSERT(resourceMap().size() == 1); + // Strictly speaking, there may be more than one resource for the tool, for intsance if + // if there are multiple clients, or a client has called get_tablet_seat multiple times. + // For now we'll pretend there can only be one resource. + return resourceMap().first()->handle; + } + + void send_removed() = delete; + void send_removed(struct ::wl_resource *resource) = delete; + void sendRemoved(); + + uint sendProximityIn(TabletV2 *tablet, Surface *surface); + void sendProximityOut(); + void sendMotion(QPointF position) + { + Q_ASSERT(m_proximitySurface); + for (auto *resource : resourceMap()) + send_motion(resource->handle, wl_fixed_from_double(position.x()), wl_fixed_from_double(position.y())); + } + uint sendDown(); + void sendUp() { send_up(toolResource()); } + void sendPressure(uint pressure); + void sendTilt(qreal tiltX, qreal tiltY) { send_tilt(toolResource(), wl_fixed_from_double(tiltX), wl_fixed_from_double(tiltY)); } + void sendRotation(qreal rotation) { send_rotation(toolResource(), wl_fixed_from_double(rotation)); } + uint sendButton(uint button, bool pressed); + uint sendFrame(); + + QPointer<TabletSeatV2> m_tabletSeat; // destruction order is not guaranteed + ToolType m_toolType = ToolType::type_pen; + quint64 m_hardwareSerial = 0; + QPointer<Surface> m_proximitySurface; +protected: + void zwp_tablet_tool_v2_destroy(Resource *resource) override; +}; + +class TabletPadV2 : public QObject, public QtWaylandServer::zwp_tablet_pad_v2 +{ + Q_OBJECT +public: + explicit TabletPadV2(TabletSeatV2 *tabletSeat) + : m_tabletSeat(tabletSeat) + { + } + + void send_removed() = delete; + void send_removed(struct ::wl_resource *resource) = delete; + void sendRemoved(); + + QPointer<TabletSeatV2> m_tabletSeat; // destroy order is not guaranteed +protected: + void zwp_tablet_pad_v2_destroy(Resource *resource) override; +}; + +class TabletSeatV2 : public QObject, public QtWaylandServer::zwp_tablet_seat_v2 +{ + Q_OBJECT +public: + explicit TabletSeatV2(TabletManagerV2 *manager, Seat *seat) + : m_manager(manager) + , m_seat(seat) + {} + TabletV2 *addTablet() + { + auto *tablet = new TabletV2(this); + m_tablets.append(tablet); + for (auto *resource : resourceMap()) + sendTabletAdded(resource, tablet); + return tablet; + } + + void sendTabletAdded(Resource *resource, TabletV2 *tablet) + { + // Although, not necessarily correct, assuming just one tablet_seat per client + auto *tabletResource = tablet->add(resource->client(), resource->version()); + zwp_tablet_seat_v2::send_tablet_added(resource->handle, tabletResource->handle); + // TODO: send extra stuff before done? + tablet->send_done(tabletResource->handle); + } + + using ToolType = QtWaylandServer::zwp_tablet_tool_v2::type; + TabletToolV2 *addTool(ToolType toolType = ToolType::type_pen, quint64 hardwareSerial = 0) + { + auto *tool = new TabletToolV2(this, toolType, hardwareSerial); + m_tools.append(tool); + for (auto *resource : resourceMap()) + sendToolAdded(resource, tool); + return tool; + } + + void sendToolAdded(Resource *resource, TabletToolV2 *tool) + { + // Although, not necessarily correct, assuming just one tablet_seat per client + auto *toolResource = tool->add(resource->client(), resource->version())->handle; + zwp_tablet_seat_v2::send_tool_added(resource->handle, toolResource); + tool->send_type(toolResource, tool->m_toolType); + if (tool->m_hardwareSerial) { + const uint hi = tool->m_hardwareSerial >> 32; + const uint lo = tool->m_hardwareSerial & 0xffffffff; + tool->send_hardware_serial(toolResource, hi, lo); + } + tool->send_done(toolResource); + } + + TabletPadV2 *addPad() + { + auto *pad = new TabletPadV2(this); + m_pads.append(pad); + for (auto *resource : resourceMap()) + sendPadAdded(resource, pad); + return pad; + } + + void sendPadAdded(Resource *resource, TabletPadV2 *pad) + { + // Although, not necessarily correct, assuming just one tablet_seat per client + auto *padResource = pad->add(resource->client(), resource->version())->handle; + zwp_tablet_seat_v2::send_pad_added(resource->handle, padResource); + pad->send_done(padResource); + } + + void removeAll() + { + const auto tools = m_tools; + for (auto *tool : tools) + tool->sendRemoved(); + + const auto tablets = m_tablets; + for (auto *tablet : tablets) + tablet->sendRemoved(); + + const auto pads = m_pads; + for (auto *pad : pads) + pad->sendRemoved(); + } + + TabletManagerV2 *m_manager = nullptr; + Seat *m_seat = nullptr; + QList<TabletV2 *> m_tablets; + QList<TabletV2 *> m_tabletsWaitingForDestroy; + QList<TabletToolV2 *> m_tools; + QList<TabletToolV2 *> m_toolsWaitingForDestroy; + QList<TabletPadV2 *> m_pads; + QList<TabletPadV2 *> m_padsWaitingForDestroy; + +protected: + void zwp_tablet_seat_v2_bind_resource(Resource *resource) override + { + for (auto *tablet : m_tablets) + sendTabletAdded(resource, tablet); + for (auto *tool : m_tools) + sendToolAdded(resource, tool); + for (auto *pad : m_pads) + sendPadAdded(resource, pad); + } +}; + +class TabletManagerV2 : public Global, public QtWaylandServer::zwp_tablet_manager_v2 +{ + Q_OBJECT +public: + explicit TabletManagerV2(CoreCompositor *compositor, int version = 1) + : QtWaylandServer::zwp_tablet_manager_v2(compositor->m_display, version) + , m_version(version) + {} + bool isClean() override + { + for (auto *seat : m_tabletSeats) { + if (!seat->m_tabletsWaitingForDestroy.empty()) + return false; + if (!seat->m_toolsWaitingForDestroy.empty()) + return false; + if (!seat->m_padsWaitingForDestroy.empty()) + return false; + } + return true; + } + + TabletSeatV2 *tabletSeatFor(Seat *seat) + { + Q_ASSERT(seat); + if (auto *tabletSeat = m_tabletSeats.value(seat, nullptr)) + return tabletSeat; + + auto *tabletSeat = new TabletSeatV2(this, seat); + m_tabletSeats[seat] = tabletSeat; + return tabletSeat; + } + + int m_version = 1; // TODO: Remove on libwayland upgrade + QMap<Seat *, TabletSeatV2 *> m_tabletSeats; + +protected: + void zwp_tablet_manager_v2_destroy(Resource *resource) override + { + // tablet_seats created from this object are unaffected and should be destroyed separately. + wl_resource_destroy(resource->handle); + } + + void zwp_tablet_manager_v2_get_tablet_seat(Resource *resource, uint32_t id, ::wl_resource *seatResource) override + { + auto *seat = fromResource<Seat>(seatResource); + QVERIFY(seat); + auto *tabletSeat = tabletSeatFor(seat); + tabletSeat->add(resource->client(), id, resource->version()); + } +}; + +void TabletV2::sendRemoved() +{ + for (auto *resource : resourceMap()) + zwp_tablet_v2_send_removed(resource->handle); + bool removed = m_tabletSeat->m_tablets.removeOne(this); + QVERIFY(removed); + m_tabletSeat->m_tabletsWaitingForDestroy.append(this); +} + +void TabletV2::zwp_tablet_v2_destroy(QtWaylandServer::zwp_tablet_v2::Resource *resource) +{ + Q_UNUSED(resource); + if (m_tabletSeat) { + bool removed = m_tabletSeat->m_tabletsWaitingForDestroy.removeOne(this); + QVERIFY(removed); + } + wl_resource_destroy(resource->handle); +} + +void TabletToolV2::sendRemoved() +{ + for (auto *resource : resourceMap()) + zwp_tablet_tool_v2_send_removed(resource->handle); + bool removed = m_tabletSeat->m_tools.removeOne(this); + QVERIFY(removed); + m_tabletSeat->m_toolsWaitingForDestroy.append(this); +} + +uint TabletToolV2::sendProximityIn(TabletV2 *tablet, Surface *surface) +{ + Q_ASSERT(!m_proximitySurface); + m_proximitySurface = surface; + uint serial = m_tabletSeat->m_seat->m_compositor->nextSerial(); + auto *client = surface->resource()->client(); + auto tabletResource = tablet->resourceMap().value(client)->handle; + send_proximity_in(toolResource(), serial, tabletResource, surface->resource()->handle); + return serial; +} + +void TabletToolV2::sendProximityOut() +{ + Q_ASSERT(m_proximitySurface); + send_proximity_out(toolResource()); + m_proximitySurface = nullptr; +} + +uint TabletToolV2::sendDown() +{ + uint serial = m_tabletSeat->m_seat->m_compositor->nextSerial(); + send_down(toolResource(), serial); + return serial; +} + +void TabletToolV2::sendPressure(uint pressure) +{ + Q_ASSERT(m_proximitySurface); + auto *client = m_proximitySurface->resource()->client(); + auto toolResource = resourceMap().value(client)->handle; + send_pressure(toolResource, pressure); +} + +uint TabletToolV2::sendButton(uint button, bool pressed) +{ + button_state state = pressed ? button_state_pressed : button_state_released; + uint serial = m_tabletSeat->m_seat->m_compositor->nextSerial(); + send_button(toolResource(), serial, button, state); + return serial; +} + +uint TabletToolV2::sendFrame() +{ + uint time = m_tabletSeat->m_seat->m_compositor->currentTimeMilliseconds(); + for (auto *resource : resourceMap()) + send_frame(resource->handle, time); + return time; +} + +void TabletToolV2::zwp_tablet_tool_v2_destroy(QtWaylandServer::zwp_tablet_tool_v2::Resource *resource) +{ + if (m_tabletSeat) { + bool removed = m_tabletSeat->m_toolsWaitingForDestroy.removeOne(this); + QVERIFY(removed); + } + wl_resource_destroy(resource->handle); +} + +void TabletPadV2::sendRemoved() +{ + for (auto *resource : resourceMap()) + zwp_tablet_pad_v2_send_removed(resource->handle); + bool removed = m_tabletSeat->m_pads.removeOne(this); + QVERIFY(removed); + m_tabletSeat->m_padsWaitingForDestroy.append(this); +} + +void TabletPadV2::zwp_tablet_pad_v2_destroy(QtWaylandServer::zwp_tablet_pad_v2::Resource *resource) +{ + if (m_tabletSeat) { + bool removed = m_tabletSeat->m_padsWaitingForDestroy.removeOne(this); + QVERIFY(removed); + } + wl_resource_destroy(resource->handle); +} + +class TabletCompositor : public DefaultCompositor { +public: + explicit TabletCompositor() + { + exec([this] { + m_config.autoConfigure = true; + add<TabletManagerV2>(tabletVersion); + }); + } + TabletSeatV2 *tabletSeat(int i = 0) + { + return get<TabletManagerV2>()->tabletSeatFor(get<Seat>(i)); + } + TabletV2 *tablet(int i = 0, int iSeat = 0) + { + if (auto *ts = tabletSeat(iSeat)) + return ts->m_tablets.value(i, nullptr); + return nullptr; + } + TabletToolV2 *tabletTool(int i = 0, int iSeat = 0) + { + if (auto *ts = tabletSeat(iSeat)) + return ts->m_tools.value(i, nullptr); + return nullptr; + } + TabletPadV2 *tabletPad(int i = 0, int iSeat = 0) + { + if (auto *ts = tabletSeat(iSeat)) + return ts->m_pads.value(i, nullptr); + return nullptr; + } +}; + +Q_DECLARE_METATYPE(QtWaylandServer::zwp_tablet_tool_v2::type); +Q_DECLARE_METATYPE(QPointingDevice::PointerType); +Q_DECLARE_METATYPE(Qt::MouseButton); + +class tst_tabletv2 : public QObject, private TabletCompositor +{ + using ToolType = QtWaylandServer::zwp_tablet_tool_v2::type; + Q_OBJECT +private slots: + void cleanup(); + void bindsToManager(); + void createsTabletSeat(); + void destroysTablet(); + void destroysTool(); + void destroysPad(); + void proximityEvents(); + void moveEvent(); + void pointerType_data(); + void pointerType(); + void hardwareSerial(); + void buttons_data(); + void buttons(); + void tabletEvents(); +}; + +class ProximityFilter : public QObject { + Q_OBJECT +public: + ProximityFilter() { qApp->installEventFilter(this); } + ~ProximityFilter() override { qDeleteAll(m_events); } + QList<QTabletEvent *> m_events; + + int nextEventIndex = 0; + int numEvents() const { return m_events.size() - nextEventIndex; } + QTabletEvent *popEvent() + { + auto *event = m_events.value(nextEventIndex, nullptr); + if (event) + ++nextEventIndex; + return event; + } + +protected: + bool eventFilter(QObject *object, QEvent *event) override + { + Q_UNUSED(object); + switch (event->type()) { + case QEvent::TabletEnterProximity: + case QEvent::TabletLeaveProximity: { + auto *e = static_cast<QTabletEvent *>(event); + auto *ev = new QTabletEvent(e->type(), e->pointingDevice(), e->position(), e->globalPosition(), + e->pressure(), e->xTilt(), e->yTilt(), + e->tangentialPressure(), e->rotation(), e->z(), + Qt::KeyboardModifier::NoModifier, + e->button(), e->buttons()); + m_events << ev; + break; + } + default: + break; + } + return false; + } +}; + +void tst_tabletv2::cleanup() +{ + exec([&] { + tabletSeat()->removeAll(); + }); + QCOMPOSITOR_COMPARE(get<TabletManagerV2>()->m_tabletSeats.size(), 1); + QCOMPOSITOR_COMPARE(tabletSeat()->m_tablets.size(), 0); + QCOMPOSITOR_COMPARE(tabletSeat()->m_tools.size(), 0); + QCOMPOSITOR_COMPARE(tabletSeat()->m_pads.size(), 0); + + QTRY_VERIFY2(isClean(), qPrintable(dirtyMessage())); +} + +void tst_tabletv2::bindsToManager() +{ + QCOMPOSITOR_TRY_COMPARE(get<TabletManagerV2>()->resourceMap().size(), 1); + QCOMPOSITOR_TRY_COMPARE(get<TabletManagerV2>()->resourceMap().first()->version(), tabletVersion); +} + +void tst_tabletv2::createsTabletSeat() +{ + QCOMPOSITOR_TRY_VERIFY(tabletSeat()); + QCOMPOSITOR_TRY_VERIFY(tabletSeat()->resourceMap().contains(client())); + QCOMPOSITOR_TRY_COMPARE(tabletSeat()->resourceMap().value(client())->version(), tabletVersion); + //TODO: Maybe also assert some capability reported though qt APIs? +} + +void tst_tabletv2::destroysTablet() +{ + QCOMPOSITOR_TRY_VERIFY(tabletSeat()); + exec([&] { + tabletSeat()->addTablet(); + }); + QCOMPOSITOR_TRY_VERIFY(tablet()); + + exec([&] { + tablet()->sendRemoved(); + }); + + QCOMPOSITOR_TRY_VERIFY(!tablet()); + QCOMPOSITOR_TRY_VERIFY(tabletSeat()->m_tabletsWaitingForDestroy.empty()); +} + +void tst_tabletv2::destroysTool() +{ + QCOMPOSITOR_TRY_VERIFY(tabletSeat()); + exec([&] { + tabletSeat()->addTool(); + }); + QCOMPOSITOR_TRY_VERIFY(tabletTool()); + + exec([&] { + tabletTool()->sendRemoved(); + }); + + QCOMPOSITOR_TRY_VERIFY(!tabletTool()); + QCOMPOSITOR_TRY_VERIFY(tabletSeat()->m_toolsWaitingForDestroy.empty()); +} + +void tst_tabletv2::destroysPad() +{ + QCOMPOSITOR_TRY_VERIFY(tabletSeat()); + exec([&] { + tabletSeat()->addPad(); + }); + QCOMPOSITOR_TRY_VERIFY(tabletPad()); + + exec([&] { + tabletPad()->sendRemoved(); + }); + + QCOMPOSITOR_TRY_VERIFY(!tabletPad()); + QCOMPOSITOR_TRY_VERIFY(tabletSeat()->m_padsWaitingForDestroy.empty()); +} + +void tst_tabletv2::proximityEvents() +{ + ProximityFilter filter; + + QCOMPOSITOR_TRY_VERIFY(tabletSeat()); + exec([&] { + tabletSeat()->addTablet(); + tabletSeat()->addTool(); + }); + + QRasterWindow window; + window.resize(64, 64); + window.show(); + QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial); + + QCOMPOSITOR_TRY_VERIFY(tablet()); + exec([&] { + auto *surface = xdgSurface()->m_surface; + auto *tool = tabletTool(); + tool->sendProximityIn(tablet(), surface); + tool->sendFrame(); + }); + + QTRY_COMPARE(filter.numEvents(), 1); + QTabletEvent *enterEvent = filter.popEvent(); + QCOMPARE(enterEvent->type(), QEvent::TabletEnterProximity); + + exec([&] { + auto *tool = tabletTool(); + tool->sendProximityOut(); + tool->sendFrame(); + }); + + QTRY_COMPARE(filter.numEvents(), 1); + QTabletEvent *leaveEvent = filter.popEvent(); + QCOMPARE(leaveEvent->type(), QEvent::TabletLeaveProximity); +} + +class TabletWindow : public QRasterWindow { + Q_OBJECT +public: + ~TabletWindow() override { qDeleteAll(m_events); } + + void tabletEvent(QTabletEvent *e) override + { + m_events << new QTabletEvent(e->type(), e->pointingDevice(), e->position(), e->globalPosition(), + e->pressure(), e->xTilt(), e->yTilt(), + e->tangentialPressure(), e->rotation(), e->z(), + Qt::KeyboardModifier::NoModifier, + e->button(), e->buttons()); + emit tabletEventReceived(m_events.last()); + } + int nextEventIndex = 0; + int numEvents() const { return m_events.size() - nextEventIndex; } + QTabletEvent *popEvent() + { + auto *event = m_events.value(nextEventIndex, nullptr); + if (event) + ++nextEventIndex; + return event; + } + +signals: + void tabletEventReceived(QTabletEvent *event); + +private: + QList<QTabletEvent *> m_events; +}; + +void tst_tabletv2::moveEvent() +{ + QCOMPOSITOR_TRY_VERIFY(tabletSeat()); + exec([&] { + tabletSeat()->addTablet(); + tabletSeat()->addTool(); + }); + + TabletWindow window; + window.resize(64, 64); + window.show(); + QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial); + + QCOMPOSITOR_TRY_VERIFY(tablet()); + exec([&] { + auto *surface = xdgSurface()->m_surface; + auto *tool = tabletTool(); + tool->sendProximityIn(tablet(), surface); + QMargins margins = window.frameMargins(); + tool->sendMotion(QPointF(12 + margins.left(), 34 + margins.top())); + tool->sendFrame(); + }); + QTRY_VERIFY(window.numEvents()); + QTabletEvent *event = window.popEvent(); + QCOMPARE(event->type(), QEvent::TabletMove); + QCOMPARE(event->pressure(), 0); + QCOMPARE(event->position(), QPointF(12, 34)); +} + +void tst_tabletv2::pointerType_data() +{ + QTest::addColumn<ToolType>("toolType"); + QTest::addColumn<QPointingDevice::PointerType>("pointerType"); + QTest::addColumn<QInputDevice::DeviceType>("tabletDevice"); + + QTest::newRow("pen") << ToolType::type_pen << QPointingDevice::PointerType::Pen << QInputDevice::DeviceType::Stylus; + QTest::newRow("eraser") << ToolType::type_eraser << QPointingDevice::PointerType::Eraser << QInputDevice::DeviceType::Stylus; + QTest::newRow("pencil") << ToolType::type_pencil << QPointingDevice::PointerType::Pen << QInputDevice::DeviceType::Stylus; + QTest::newRow("airbrush") << ToolType::type_airbrush << QPointingDevice::PointerType::Pen << QInputDevice::DeviceType::Airbrush; + QTest::newRow("brush") << ToolType::type_brush << QPointingDevice::PointerType::Pen << QInputDevice::DeviceType::Stylus; // TODO: is TabletDevice::Stylus the right thing? + QTest::newRow("lens") << ToolType::type_lens << QPointingDevice::PointerType::Cursor << QInputDevice::DeviceType::Puck; + // TODO: also add tests for FourDMouse and RotationStylus (also need to send capabilities) + + // TODO: should these rather be mapped to touch/mouse events? + QTest::newRow("finger") << ToolType::type_finger << QPointingDevice::PointerType::Unknown << QInputDevice::DeviceType::Unknown; + QTest::newRow("mouse") << ToolType::type_mouse << QPointingDevice::PointerType::Cursor << QInputDevice::DeviceType::Unknown; +} + +void tst_tabletv2::pointerType() +{ + using ToolType = QtWaylandServer::zwp_tablet_tool_v2::type; + QFETCH(ToolType, toolType); + QFETCH(QPointingDevice::PointerType, pointerType); + QFETCH(QInputDevice::DeviceType, tabletDevice); + + ProximityFilter filter; + + QCOMPOSITOR_TRY_VERIFY(tabletSeat()); + exec([&] { + tabletSeat()->addTablet(); + tabletSeat()->addTool(toolType); + }); + + TabletWindow window; + window.resize(64, 64); + window.show(); + QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial); + + QCOMPOSITOR_TRY_VERIFY(tablet()); + exec([&] { + auto *surface = xdgSurface()->m_surface; + auto *tool = tabletTool(); + tool->sendProximityIn(tablet(), surface); + QMargins margins = window.frameMargins(); + tool->sendMotion(QPointF(12 + margins.left(), 34 + margins.top())); + tool->sendFrame(); + }); + + QTRY_COMPARE(filter.numEvents(), 1); + QTabletEvent *event = filter.popEvent(); + QCOMPARE(event->pointerType(), pointerType); + QCOMPARE(event->deviceType(), tabletDevice); + + QTRY_VERIFY(window.numEvents()); + event = window.popEvent(); + QCOMPARE(event->pointerType(), pointerType); + QCOMPARE(event->deviceType(), tabletDevice); + + exec([&] { + tabletTool()->sendProximityOut(); + tabletTool()->sendFrame(); + }); + + QTRY_VERIFY(filter.numEvents()); + event = filter.popEvent(); + QCOMPARE(event->pointerType(), pointerType); + QCOMPARE(event->deviceType(), tabletDevice); +} + +void tst_tabletv2::hardwareSerial() +{ + ProximityFilter filter; + const QPointingDeviceUniqueId uid = QPointingDeviceUniqueId::fromNumericId(0xbaba15dead15f00d); + + QCOMPOSITOR_TRY_VERIFY(tabletSeat()); + exec([&] { + tabletSeat()->addTablet(); + tabletSeat()->addTool(ToolType::type_pen, uid.numericId()); + }); + + TabletWindow window; + window.resize(64, 64); + window.show(); + QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial); + + QCOMPOSITOR_TRY_VERIFY(tablet()); + exec([&] { + auto *surface = xdgSurface()->m_surface; + auto *tool = tabletTool(); + tool->sendProximityIn(tablet(), surface); + QMargins margins = window.frameMargins(); + tool->sendMotion(QPointF(12 + margins.left(), 34 + margins.top())); + tool->sendFrame(); + }); + + QTRY_COMPARE(filter.numEvents(), 1); + QTabletEvent *event = filter.popEvent(); + QCOMPARE(event->pointingDevice()->uniqueId(), uid); + + QTRY_VERIFY(window.numEvents()); + event = window.popEvent(); + QCOMPARE(event->pointingDevice()->uniqueId(), uid); + + exec([&] { + tabletTool()->sendProximityOut(); + tabletTool()->sendFrame(); + }); + + QTRY_VERIFY(filter.numEvents()); + event = filter.popEvent(); + QCOMPARE(event->pointingDevice()->uniqueId(), uid); +} + +// As defined in linux/input-event-codes.h +#ifndef BTN_STYLUS +#define BTN_STYLUS 0x14b +#endif +#ifndef BTN_STYLUS2 +#define BTN_STYLUS2 0x14c +#endif + +void tst_tabletv2::buttons_data() +{ + QTest::addColumn<uint>("tabletButton"); + QTest::addColumn<Qt::MouseButton>("mouseButton"); + + QTest::newRow("BTN_STYLUS2") << uint(BTN_STYLUS2) << Qt::MouseButton::RightButton; + QTest::newRow("BTN_STYLUS") << uint(BTN_STYLUS) << Qt::MouseButton::MiddleButton; +} + +void tst_tabletv2::buttons() +{ + QFETCH(uint, tabletButton); + QFETCH(Qt::MouseButton, mouseButton); + + QCOMPOSITOR_TRY_VERIFY(tabletSeat()); + exec([&] { + tabletSeat()->addTablet(); + tabletSeat()->addTool(); + }); + + TabletWindow window; + window.resize(64, 64); + window.show(); + QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial); + + QCOMPOSITOR_TRY_VERIFY(tablet()); + exec([&] { + tabletTool()->sendProximityIn(tablet(), xdgSurface()->m_surface); + QMargins margins = window.frameMargins(); + tabletTool()->sendMotion(QPointF(12 + margins.left(), 34 + margins.top())); + tabletTool()->sendFrame(); + }); + + QTRY_VERIFY(window.numEvents()); + window.popEvent(); + + QCOMPOSITOR_TRY_VERIFY(tablet()); + exec([&] { + tabletTool()->sendButton(tabletButton, true); + tabletTool()->sendFrame(); + tabletTool()->sendButton(tabletButton, false); + tabletTool()->sendFrame(); + }); + + QTRY_VERIFY(window.numEvents()); + QTabletEvent *event = window.popEvent(); + QCOMPARE(event->buttons(), mouseButton); + + exec([&] { + tabletTool()->sendProximityOut(); + tabletTool()->sendFrame(); + }); +} + +void tst_tabletv2::tabletEvents() +{ + QCOMPOSITOR_TRY_VERIFY(tabletSeat()); + exec([&] { + tabletSeat()->addTablet(); + tabletSeat()->addTool(); + }); + + TabletWindow window; + window.resize(64, 64); + window.show(); + QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial); + + const QPointF insideDecorations(window.frameMargins().left(), window.frameMargins().top()); + + QCOMPOSITOR_TRY_VERIFY(tablet()); + exec([&] { + auto *surface = xdgSurface()->m_surface; + auto *tool = tabletTool(); + // TODO: encapsulate this into a helper function? + tool->sendProximityIn(tablet(), surface); + tool->sendMotion(QPointF(12, 34) + insideDecorations); + tool->sendDown(); + tool->sendPressure(65535); + tool->sendFrame(); + }); + + QTRY_VERIFY(window.numEvents()); + QTabletEvent *event = window.popEvent(); + QCOMPARE(event->type(), QEvent::TabletPress); + QCOMPARE(event->pressure(), 1.0); + QCOMPARE(event->position(), QPointF(12, 34)); + + // Values we didn't send should be 0 + QCOMPARE(event->rotation(), 0); + QCOMPARE(event->xTilt(), 0); + QCOMPARE(event->yTilt(), 0); + + exec([&] { + tabletTool()->sendMotion(QPointF(45, 56) + insideDecorations); + tabletTool()->sendPressure(65535/2); + tabletTool()->sendRotation(90); + tabletTool()->sendTilt(13, 37); + tabletTool()->sendFrame(); + }); + + QTRY_VERIFY(window.numEvents()); + event = window.popEvent(); + QCOMPARE(event->type(), QEvent::TabletMove); + QVERIFY(qAbs(event->pressure() - 0.5) < 0.01); + QVERIFY(qAbs(event->rotation() - 90) < 0.01); + QVERIFY(qAbs(event->xTilt() - 13) < 0.01); + QVERIFY(qAbs(event->yTilt() - 37) < 0.01); + QCOMPARE(event->position(), QPointF(45, 56)); + + // Verify that the values stay the same if we don't update them + exec([&] { + tabletTool()->sendMotion(QPointF(10, 11) + insideDecorations); // Change position only + tabletTool()->sendFrame(); + }); + QTRY_VERIFY(window.numEvents()); + event = window.popEvent(); + QCOMPARE(event->type(), QEvent::TabletMove); + QVERIFY(qAbs(event->pressure() - 0.5) < 0.01); + QVERIFY(qAbs(event->rotation() - 90) < 0.01); + QVERIFY(qAbs(event->xTilt() - 13) < 0.01); + QVERIFY(qAbs(event->yTilt() - 37) < 0.01); + QCOMPARE(event->position(), QPointF(10, 11)); + + exec([&] { + tabletTool()->sendPressure(0); + tabletTool()->sendUp(); + tabletTool()->sendFrame(); + + tabletTool()->sendProximityOut(); + tabletTool()->sendFrame(); + }); + + QTRY_VERIFY(window.numEvents()); + event = window.popEvent(); + QCOMPARE(event->type(), QEvent::TabletRelease); + QCOMPARE(event->pressure(), 0); + QCOMPARE(event->position(), QPointF(10, 11)); +} + +QCOMPOSITOR_TEST_MAIN(tst_tabletv2) +#include "tst_tabletv2.moc" diff --git a/tests/auto/client/wl_connect/CMakeLists.txt b/tests/auto/client/wl_connect/CMakeLists.txt new file mode 100644 index 000000000..fff3835bb --- /dev/null +++ b/tests/auto/client/wl_connect/CMakeLists.txt @@ -0,0 +1,16 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +# Generated from wl_connect.pro. + +##################################################################### +## tst_wlconnect Test: +##################################################################### + +qt_internal_add_test(tst_wlconnect + SOURCES + tst_wlconnect.cpp + LIBRARIES + Qt::Gui + Qt::GuiPrivate +) diff --git a/tests/auto/client/wl_connect/tst_wlconnect.cpp b/tests/auto/client/wl_connect/tst_wlconnect.cpp index 661f7ad62..d66d0ad6a 100644 --- a/tests/auto/client/wl_connect/tst_wlconnect.cpp +++ b/tests/auto/client/wl_connect/tst_wlconnect.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QtTest/QtTest> #include <QGuiApplication> diff --git a/tests/auto/client/wl_connect/wl_connect.pro b/tests/auto/client/wl_connect/wl_connect.pro deleted file mode 100644 index 28723beee..000000000 --- a/tests/auto/client/wl_connect/wl_connect.pro +++ /dev/null @@ -1,5 +0,0 @@ -CONFIG += testcase -QT += gui-private testlib - -SOURCES += tst_wlconnect.cpp -TARGET = tst_wlconnect diff --git a/tests/auto/client/xdgdecorationv1/CMakeLists.txt b/tests/auto/client/xdgdecorationv1/CMakeLists.txt new file mode 100644 index 000000000..0f727aaca --- /dev/null +++ b/tests/auto/client/xdgdecorationv1/CMakeLists.txt @@ -0,0 +1,15 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +# Generated from xdgdecorationv1.pro. + +##################################################################### +## tst_xdgdecorationv1 Test: +##################################################################### + +qt_internal_add_test(tst_xdgdecorationv1 + SOURCES + tst_xdgdecorationv1.cpp + LIBRARIES + SharedClientTest +) diff --git a/tests/auto/client/xdgdecorationv1/tst_xdgdecorationv1.cpp b/tests/auto/client/xdgdecorationv1/tst_xdgdecorationv1.cpp index 386713cf5..54b15b3bf 100644 --- a/tests/auto/client/xdgdecorationv1/tst_xdgdecorationv1.cpp +++ b/tests/auto/client/xdgdecorationv1/tst_xdgdecorationv1.cpp @@ -1,37 +1,11 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "mockcompositor.h" #include <qwayland-server-xdg-decoration-unstable-v1.h> #include <QtGui/QRasterWindow> -#include <QtGui/QOpenGLWindow> #include <QtGui/QClipboard> #include <QtCore/private/qcore_unix_p.h> @@ -153,6 +127,8 @@ private slots: void initTestCase(); void cleanup() { QTRY_VERIFY2(isClean(), qPrintable(dirtyMessage())); } void clientSidePreferredByCompositor(); + void initialFramelessWindowHint(); + void delayedFramelessWindowHint(); }; void tst_xdgdecorationv1::initTestCase() @@ -175,12 +151,48 @@ void tst_xdgdecorationv1::clientSidePreferredByCompositor() QCOMPOSITOR_TRY_VERIFY(xdgToplevel()); QCOMPOSITOR_TRY_VERIFY(toplevelDecoration()->m_unsetModeRequested); QVERIFY(window.frameMargins().isNull()); // We're still waiting for a configure - exec([=] { + exec([&] { toplevelDecoration()->sendConfigure(XdgToplevelDecorationV1::mode_client_side); xdgToplevel()->sendCompleteConfigure(); }); QTRY_VERIFY(!window.frameMargins().isNull()); } +void tst_xdgdecorationv1::initialFramelessWindowHint() +{ + QRasterWindow window; + window.setFlag(Qt::FramelessWindowHint, true); + window.show(); + QCOMPOSITOR_TRY_COMPARE(get<XdgDecorationManagerV1>()->resourceMap().size(), 1); + QCOMPOSITOR_TRY_VERIFY(xdgToplevel()); + exec([&]{ + xdgToplevel()->sendCompleteConfigure(); + }); + QCOMPOSITOR_TRY_VERIFY(xdgSurface()->m_committedConfigureSerial); + + // The client should not have create a decoration object, because that allows the compositor + // to override our decision and add server side decorations to our window. + QCOMPOSITOR_TRY_VERIFY(!toplevelDecoration()); +} + +void tst_xdgdecorationv1::delayedFramelessWindowHint() +{ + QRasterWindow window; + window.show(); + QCOMPOSITOR_TRY_COMPARE(get<XdgDecorationManagerV1>()->resourceMap().size(), 1); + QCOMPOSITOR_TRY_VERIFY(xdgToplevel()); + exec([&]{ + xdgToplevel()->sendCompleteConfigure(); + }); + QCOMPOSITOR_TRY_VERIFY(xdgSurface()->m_committedConfigureSerial); + QCOMPOSITOR_TRY_VERIFY(toplevelDecoration()); + + window.setFlag(Qt::FramelessWindowHint, true); + + // The client should now destroy the decoration object, so the compositor is no longer + // able to force window decorations + QCOMPOSITOR_TRY_VERIFY(!toplevelDecoration()); +} + QCOMPOSITOR_TEST_MAIN(tst_xdgdecorationv1) #include "tst_xdgdecorationv1.moc" diff --git a/tests/auto/client/xdgdecorationv1/xdgdecorationv1.pro b/tests/auto/client/xdgdecorationv1/xdgdecorationv1.pro deleted file mode 100644 index 0b5537205..000000000 --- a/tests/auto/client/xdgdecorationv1/xdgdecorationv1.pro +++ /dev/null @@ -1,7 +0,0 @@ -include (../shared/shared.pri) - -WAYLANDSERVERSOURCES += \ - $$PWD/../../../../src/3rdparty/protocol/xdg-decoration-unstable-v1.xml - -TARGET = tst_xdgdecorationv1 -SOURCES += tst_xdgdecorationv1.cpp diff --git a/tests/auto/client/xdgoutput/CMakeLists.txt b/tests/auto/client/xdgoutput/CMakeLists.txt new file mode 100644 index 000000000..123a78f8e --- /dev/null +++ b/tests/auto/client/xdgoutput/CMakeLists.txt @@ -0,0 +1,15 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +# Generated from xdgoutput.pro. + +##################################################################### +## tst_xdgoutput Test: +##################################################################### + +qt_internal_add_test(tst_xdgoutput + SOURCES + tst_xdgoutput.cpp + LIBRARIES + SharedClientTest +) diff --git a/tests/auto/client/xdgoutput/tst_xdgoutput.cpp b/tests/auto/client/xdgoutput/tst_xdgoutput.cpp index a628810d1..d021e3883 100644 --- a/tests/auto/client/xdgoutput/tst_xdgoutput.cpp +++ b/tests/auto/client/xdgoutput/tst_xdgoutput.cpp @@ -1,102 +1,20 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only +#include "xdgoutputv1.h" #include "mockcompositor.h" + #include <QtGui/QRasterWindow> -#include <QtGui/QOpenGLWindow> #include <QtGui/QScreen> -#include <qwayland-server-xdg-output-unstable-v1.h> - using namespace MockCompositor; -// TODO: move to shared folder? -class XdgOutputV1 : public QObject, public QtWaylandServer::zxdg_output_v1 -{ -public: - explicit XdgOutputV1(Output *output) - : m_output(output) - , m_logicalGeometry(m_output->m_data.position, QSize(m_output->m_data.mode.resolution / m_output->m_data.scale)) - , m_name(QString("WL-%1").arg(s_nextId++)) - {} - - void addResource(wl_client *client, int id, int version) - { - auto *resource = add(client, id, version)->handle; - send_logical_size(resource, m_logicalGeometry.width(), m_logicalGeometry.height()); - send_logical_position(resource, m_logicalGeometry.x(), m_logicalGeometry.y()); - if (version >= ZXDG_OUTPUT_V1_NAME_SINCE_VERSION) - send_name(resource, m_name); - if (version >= ZXDG_OUTPUT_V1_DESCRIPTION_SINCE_VERSION) - send_description(resource, m_description); - send_done(resource); - } - Output *m_output = nullptr; - QRect m_logicalGeometry; - QString m_name; - QString m_description = "This is an Xdg Output description"; - static int s_nextId; -}; - -int XdgOutputV1::s_nextId = 1; - -class XdgOutputManagerV1 : public Global, public QtWaylandServer::zxdg_output_manager_v1 -{ - Q_OBJECT -public: - explicit XdgOutputManagerV1(CoreCompositor *compositor, int version = 2) - : QtWaylandServer::zxdg_output_manager_v1(compositor->m_display, version) - , m_version(version) - {} - int m_version = 1; // TODO: remove on libwayland upgrade - QMap<Output *, XdgOutputV1 *> m_xdgOutputs; - XdgOutputV1 *getXdgOutput(Output *output) - { - if (auto *xdgOutput = m_xdgOutputs.value(output)) - return xdgOutput; - return m_xdgOutputs[output] = new XdgOutputV1(output); // TODO: free memory - } - -protected: - void zxdg_output_manager_v1_get_xdg_output(Resource *resource, uint32_t id, wl_resource *outputResource) override - { - auto *output = fromResource<Output>(outputResource); - auto *xdgOutput = getXdgOutput(output); - xdgOutput->addResource(resource->client(), id, resource->version()); - } -}; - class XdgOutputV1Compositor : public DefaultCompositor { public: explicit XdgOutputV1Compositor() { exec([this] { - int version = 2; // version 2 of of unstable-v1 + int version = 3; // version 3 of of unstable-v1 add<XdgOutputManagerV1>(version); }); } @@ -110,11 +28,14 @@ private slots: void cleanup(); void primaryScreen(); void overrideGeometry(); + void changeGeometry(); + void outputCreateEnterRace(); }; void tst_xdgoutput::cleanup() { QCOMPOSITOR_COMPARE(getAll<Output>().size(), 1); // Only the default output should be left + QTRY_COMPARE(QGuiApplication::screens().size(), 1); QTRY_VERIFY2(isClean(), qPrintable(dirtyMessage())); } @@ -122,9 +43,10 @@ void tst_xdgoutput::primaryScreen() { // Verify that the client has bound to the global QCOMPOSITOR_TRY_COMPARE(get<XdgOutputManagerV1>()->resourceMap().size(), 1); - exec([=] { + exec([&] { auto *resource = xdgOutput()->resourceMap().value(client()); - QCOMPARE(resource->version(), 2); + QCOMPARE(resource->version(), 3); + QCOMPARE(xdgOutput()->m_logicalGeometry.size(), QSize(1920, 1080)); }); auto *s = QGuiApplication::primaryScreen(); QTRY_COMPARE(s->size(), QSize(1920, 1080)); @@ -134,7 +56,7 @@ void tst_xdgoutput::primaryScreen() void tst_xdgoutput::overrideGeometry() { - exec([=] { + exec([&] { auto *output = add<Output>(); auto *xdgOutput = get<XdgOutputManagerV1>()->getXdgOutput(output); xdgOutput->m_logicalGeometry = QRect(10, 20, 800, 1200); @@ -146,7 +68,79 @@ void tst_xdgoutput::overrideGeometry() QTRY_COMPARE(s->size(), QSize(800, 1200)); QTRY_COMPARE(s->geometry().topLeft(), QPoint(10, 20)); - exec([=] { remove(output(1)); }); + exec([&] { remove(output(1)); }); +} + +void tst_xdgoutput::changeGeometry() +{ + auto *xdgOutput = exec([&] { + auto *output = add<Output>(); + auto *xdgOutput = get<XdgOutputManagerV1>()->getXdgOutput(output); + xdgOutput->m_logicalGeometry = QRect(10, 20, 800, 1200); + return xdgOutput; + }); + + QTRY_COMPARE(QGuiApplication::screens().size(), 2); + auto *screen = QGuiApplication::screens()[1]; + QTRY_COMPARE(screen->size(), QSize(800, 1200)); + + exec([&] { + xdgOutput->sendLogicalSize(QSize(1024, 768)); + }); + + // Now we want to check that the client doesn't apply the size immediately, but waits for the + // done event. If we TRY_COMPARE immediately, we risk that the client just hasn't handled the + // logical_size request yet, so we add a screen and verify it on the client side just to give + // the client a chance to mess up. + exec([&] { add<Output>(); }); + QTRY_COMPARE(QGuiApplication::screens().size(), 3); + exec([&] { remove(output(2)); }); + + // The logical_size event should have been handled by now, but state should not have been applied yet. + QTRY_COMPARE(screen->size(), QSize(800, 1200)); + + exec([&] { + xdgOutput->m_output->sendDone(); + }); + + // Finally, the size should change + QTRY_COMPARE(screen->size(), QSize(1024, 768)); + + exec([&] { remove(output(1)); }); +} + +void tst_xdgoutput::outputCreateEnterRace() +{ + m_config.autoConfigure = true; + m_config.autoEnter = false; + QRasterWindow window; + QSignalSpy screenChanged(&window, &QWindow::screenChanged); + window.resize(400, 320); + window.show(); + QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial); + exec([&] { xdgToplevel()->surface()->sendEnter(output(0));}); + + QTRY_COMPARE(QGuiApplication::screens().size(), 1); + QScreen *primaryScreen = QGuiApplication::screens().first(); + QCOMPARE(window.screen(), primaryScreen); + + auto *out = exec([&] { + return add<Output>(); + }); + + // In Compositor Thread + connect(out, &Output::outputBound, this, [this](QtWaylandServer::wl_output::Resource *resource){ + auto surface = xdgToplevel()->surface(); + surface->sendLeave(output(0)); + surface->QtWaylandServer::wl_surface::send_enter(surface->resource()->handle, resource->handle); + }, Qt::DirectConnection); + + QTRY_COMPARE(QGuiApplication::screens().size(), 2); + QTRY_COMPARE(window.screen(), QGuiApplication::screens()[1]); + + exec([&] { remove(out); }); + m_config.autoConfigure = false; + m_config.autoEnter = true; } QCOMPOSITOR_TEST_MAIN(tst_xdgoutput) diff --git a/tests/auto/client/xdgoutput/xdgoutput.pro b/tests/auto/client/xdgoutput/xdgoutput.pro deleted file mode 100644 index 3cfbb6a76..000000000 --- a/tests/auto/client/xdgoutput/xdgoutput.pro +++ /dev/null @@ -1,8 +0,0 @@ -include (../shared/shared.pri) - -WAYLANDSERVERSOURCES += \ - $$PWD/../../../../src/3rdparty/protocol/xdg-output-unstable-v1.xml - -TARGET = tst_xdgoutput -SOURCES += tst_xdgoutput.cpp - diff --git a/tests/auto/client/xdgshell/CMakeLists.txt b/tests/auto/client/xdgshell/CMakeLists.txt new file mode 100644 index 000000000..fa7590249 --- /dev/null +++ b/tests/auto/client/xdgshell/CMakeLists.txt @@ -0,0 +1,15 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +# Generated from xdgshell.pro. + +##################################################################### +## tst_xdgshell Test: +##################################################################### + +qt_internal_add_test(tst_xdgshell + SOURCES + tst_xdgshell.cpp + LIBRARIES + SharedClientTest +) diff --git a/tests/auto/client/xdgshell/tst_xdgshell.cpp b/tests/auto/client/xdgshell/tst_xdgshell.cpp index ac5c24988..1dc57e280 100644 --- a/tests/auto/client/xdgshell/tst_xdgshell.cpp +++ b/tests/auto/client/xdgshell/tst_xdgshell.cpp @@ -1,36 +1,12 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// Copyright (C) 2023 David Edmundson <davidedmundson@kde.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "mockcompositor.h" #include <QtGui/QRasterWindow> -#include <QtGui/QOpenGLWindow> #include <QtGui/qpa/qplatformnativeinterface.h> #include <QtWaylandClient/private/wayland-wayland-client-protocol.h> +#include <QtWaylandClient/private/qwaylandwindow_p.h> using namespace MockCompositor; @@ -38,23 +14,36 @@ class tst_xdgshell : public QObject, private DefaultCompositor { Q_OBJECT private slots: + void init(); void cleanup() { QTRY_VERIFY2(isClean(), qPrintable(dirtyMessage())); } void showMinimized(); void basicConfigure(); void configureSize(); void configureStates(); + void configureBounds(); void popup(); void tooltipOnPopup(); + void tooltipAndSiblingPopup(); void switchPopups(); + void hidePopupParent(); void pongs(); + void minMaxSize_data(); void minMaxSize(); void windowGeometry(); void foreignSurface(); + void nativeResources(); + void suspended(); + void initiallySuspended(); + void modality(); }; +void tst_xdgshell::init() +{ + setenv("QT_WAYLAND_DISABLE_WINDOWDECORATION", "1", 1); +} + void tst_xdgshell::showMinimized() { - QSKIP("TODO: This currently fails, needs a fix"); // On xdg-shell there's really no way for the compositor to tell the window if it's minimized // There are wl_surface.enter events and so on, but there's really no way to differentiate // between a window preview and an unminimized window. @@ -76,13 +65,13 @@ void tst_xdgshell::basicConfigure() window.show(); QCOMPOSITOR_TRY_VERIFY(xdgToplevel()); - QSignalSpy configureSpy(exec([=] { return xdgSurface(); }), &XdgSurface::configureCommitted); + QSignalSpy configureSpy(exec([&] { return xdgSurface(); }), &XdgSurface::configureCommitted); QTRY_VERIFY(window.isVisible()); // The window should not be exposed before the first xdg_surface configure event QTRY_VERIFY(!window.isExposed()); - exec([=] { + exec([&] { xdgToplevel()->sendConfigure({0, 0}, {}); // Let the window decide the size }); @@ -90,9 +79,9 @@ void tst_xdgshell::basicConfigure() QTRY_VERIFY(!window.isExposed()); //Window should not be exposed before the first configure event QVERIFY(configureSpy.isEmpty()); - const uint serial = exec([=] { return nextSerial(); }); + const uint serial = exec([&] { return nextSerial(); }); - exec([=] { + exec([&] { xdgSurface()->sendConfigure(serial); }); @@ -100,7 +89,7 @@ void tst_xdgshell::basicConfigure() QTRY_VERIFY(window.isExposed()); // The client is now going to ack the configure - QTRY_COMPARE(configureSpy.count(), 1); + QTRY_COMPARE(configureSpy.size(), 1); QCOMPARE(configureSpy.takeFirst().at(0).toUInt(), serial); // And attach a buffer @@ -118,17 +107,17 @@ void tst_xdgshell::configureSize() window.show(); QCOMPOSITOR_TRY_VERIFY(xdgToplevel()); - QSignalSpy configureSpy(exec([=] { return xdgSurface(); }), &XdgSurface::configureCommitted); + QSignalSpy configureSpy(exec([&] { return xdgSurface(); }), &XdgSurface::configureCommitted); const QSize configureSize(60, 40); - exec([=] { + exec([&] { xdgToplevel()->sendCompleteConfigure(configureSize); }); - QTRY_COMPARE(configureSpy.count(), 1); + QTRY_COMPARE(configureSpy.size(), 1); - exec([=] { + exec([&] { Buffer *buffer = xdgToplevel()->surface()->m_committed.buffer; QVERIFY(buffer); QCOMPARE(buffer->size(), configureSize); @@ -137,13 +126,14 @@ void tst_xdgshell::configureSize() void tst_xdgshell::configureStates() { + QVERIFY(qputenv("QT_WAYLAND_FRAME_CALLBACK_TIMEOUT", "0")); QRasterWindow window; window.resize(64, 48); window.show(); QCOMPOSITOR_TRY_VERIFY(xdgToplevel()); const QSize windowedSize(320, 240); - const uint windowedSerial = exec([=] { + const uint windowedSerial = exec([&] { return xdgToplevel()->sendCompleteConfigure(windowedSize, { XdgToplevel::state_activated }); }); QCOMPOSITOR_TRY_COMPARE(xdgSurface()->m_committedConfigureSerial, windowedSerial); @@ -153,12 +143,15 @@ void tst_xdgshell::configureStates() // Toplevel windows don't know their position on xdg-shell // QCOMPARE(window.frameGeometry().topLeft(), QPoint()); // TODO: this doesn't currently work when window decorations are enabled -// QEXPECT_FAIL("", "configure has already been acked, we shouldn't have to wait for isActive", Continue); -// QVERIFY(window.isActive()); - QTRY_VERIFY(window.isActive()); // Just make sure it eventually get's set correctly + // window.windowstate() is driven by keyboard focus, however for decorations we want to follow + // XDGShell this is internal to QtWayland so it is queried directly + auto waylandWindow = static_cast<QtWaylandClient::QWaylandWindow *>(window.handle()); + Q_ASSERT(waylandWindow); + QTRY_VERIFY(waylandWindow->windowStates().testFlag( + Qt::WindowActive)); // Just make sure it eventually get's set correctly const QSize screenSize(640, 480); - const uint maximizedSerial = exec([=] { + const uint maximizedSerial = exec([&] { return xdgToplevel()->sendCompleteConfigure(screenSize, { XdgToplevel::state_activated, XdgToplevel::state_maximized }); }); QCOMPOSITOR_TRY_COMPARE(xdgSurface()->m_committedConfigureSerial, maximizedSerial); @@ -167,7 +160,7 @@ void tst_xdgshell::configureStates() QCOMPARE(window.frameGeometry().size(), screenSize); // QCOMPARE(window.frameGeometry().topLeft(), QPoint()); // TODO: this doesn't currently work when window decorations are enabled - const uint fullscreenSerial = exec([=] { + const uint fullscreenSerial = exec([&] { return xdgToplevel()->sendCompleteConfigure(screenSize, { XdgToplevel::state_activated, XdgToplevel::state_fullscreen }); }); QCOMPOSITOR_TRY_COMPARE(xdgSurface()->m_committedConfigureSerial, fullscreenSerial); @@ -177,7 +170,7 @@ void tst_xdgshell::configureStates() // QCOMPARE(window.frameGeometry().topLeft(), QPoint()); // TODO: this doesn't currently work when window decorations are enabled // The window should remember its original size - const uint restoreSerial = exec([=] { + const uint restoreSerial = exec([&] { return xdgToplevel()->sendCompleteConfigure({0, 0}, { XdgToplevel::state_activated }); }); QCOMPOSITOR_TRY_COMPARE(xdgSurface()->m_committedConfigureSerial, restoreSerial); @@ -185,6 +178,31 @@ void tst_xdgshell::configureStates() QCOMPARE(window.windowStates(), Qt::WindowNoState); QCOMPARE(window.frameGeometry().size(), windowedSize); // QCOMPARE(window.frameGeometry().topLeft(), QPoint()); // TODO: this doesn't currently work when window decorations are enabled + QVERIFY(qunsetenv("QT_WAYLAND_FRAME_CALLBACK_TIMEOUT")); +} + +void tst_xdgshell::configureBounds() +{ + QRasterWindow window; + window.resize(1280, 1024); + window.show(); + QCOMPOSITOR_TRY_VERIFY(xdgToplevel()); + + // Take xdg_toplevel.configure_bounds into account only if the configure event has 0x0 size. + const uint serial1 = exec([&] { + xdgToplevel()->sendConfigureBounds(QSize(800, 600)); + return xdgToplevel()->sendCompleteConfigure(QSize(0, 0), { XdgToplevel::state_activated }); + }); + QCOMPOSITOR_TRY_COMPARE(xdgSurface()->m_committedConfigureSerial, serial1); + QCOMPARE(window.frameGeometry().size(), QSize(800, 600)); + + // Window size in xdg_toplevel configure events takes precedence over the configure bounds. + const uint serial2 = exec([&] { + xdgToplevel()->sendConfigureBounds(QSize(800, 600)); + return xdgToplevel()->sendCompleteConfigure(QSize(1600, 900), { XdgToplevel::state_activated }); + }); + QCOMPOSITOR_TRY_COMPARE(xdgSurface()->m_committedConfigureSerial, serial2); + QCOMPARE(window.frameGeometry().size(), QSize(1600, 900)); } void tst_xdgshell::popup() @@ -207,11 +225,11 @@ void tst_xdgshell::popup() window.show(); QCOMPOSITOR_TRY_VERIFY(xdgToplevel()); - QSignalSpy toplevelConfigureSpy(exec([=] { return xdgSurface(); }), &XdgSurface::configureCommitted); - exec([=] { xdgToplevel()->sendCompleteConfigure(); }); - QTRY_COMPARE(toplevelConfigureSpy.count(), 1); + QSignalSpy toplevelConfigureSpy(exec([&] { return xdgSurface(); }), &XdgSurface::configureCommitted); + exec([&] { xdgToplevel()->sendCompleteConfigure(); }); + QTRY_COMPARE(toplevelConfigureSpy.size(), 1); - uint clickSerial = exec([=] { + uint clickSerial = exec([&] { auto *surface = xdgToplevel()->surface(); auto *p = pointer(); auto *c = client(); @@ -219,27 +237,27 @@ void tst_xdgshell::popup() p->sendFrame(c); uint serial = p->sendButton(client(), BTN_LEFT, Pointer::button_state_pressed); p->sendButton(c, BTN_LEFT, Pointer::button_state_released); - return serial; p->sendFrame(c); + return serial; }); QTRY_VERIFY(window.m_popup); QCOMPOSITOR_TRY_VERIFY(xdgPopup()); - QSignalSpy popupConfigureSpy(exec([=] { return xdgPopup()->m_xdgSurface; }), &XdgSurface::configureCommitted); + QSignalSpy popupConfigureSpy(exec([&] { return xdgPopup()->m_xdgSurface; }), &XdgSurface::configureCommitted); QCOMPOSITOR_TRY_VERIFY(xdgPopup()->m_grabbed); QCOMPOSITOR_TRY_COMPARE(xdgPopup()->m_grabSerial, clickSerial); QRasterWindow *popup = window.m_popup.get(); QVERIFY(!popup->isExposed()); // wait for configure - //TODO: Verify it works with a different configure window geometry - exec([=] { xdgPopup()->sendConfigure(QRect(100, 100, 100, 100)); }); + QRect rect1 = QRect(100, 100, 100, 100); + exec([&] { xdgPopup()->sendConfigure(rect1); }); // Nothing should happen before the *xdg_surface* configure QTRY_VERIFY(!popup->isExposed()); // Popup shouldn't be exposed before the first configure event QVERIFY(popupConfigureSpy.isEmpty()); - const uint configureSerial = exec([=] { + const uint configureSerial = exec([&] { return xdgPopup()->m_xdgSurface->sendConfigure(); }); @@ -247,8 +265,20 @@ void tst_xdgshell::popup() QTRY_VERIFY(popup->isExposed()); // The client is now going to ack the configure - QTRY_COMPARE(popupConfigureSpy.count(), 1); + QTRY_COMPARE(popupConfigureSpy.size(), 1); QCOMPARE(popupConfigureSpy.takeFirst().at(0).toUInt(), configureSerial); + QCOMPARE(popup->geometry(), rect1); + + QRect rect2 = QRect(50, 50, 150, 150); + exec([&] { xdgPopup()->sendConfigure(rect2); }); + + const uint configureSerial2 = exec([&] { + return xdgPopup()->m_xdgSurface->sendConfigure(); + }); + + QTRY_COMPARE(popupConfigureSpy.size(), 1); + QCOMPARE(popupConfigureSpy.takeFirst().at(0).toUInt(), configureSerial2); + QCOMPARE(popup->geometry(), rect2); // And attach a buffer exec([&] { @@ -293,10 +323,10 @@ void tst_xdgshell::tooltipOnPopup() window.show(); QCOMPOSITOR_TRY_VERIFY(xdgToplevel()); - exec([=] { xdgToplevel()->sendCompleteConfigure(); }); + exec([&] { xdgToplevel()->sendCompleteConfigure(); }); QCOMPOSITOR_TRY_VERIFY(xdgToplevel()->m_xdgSurface->m_committedConfigureSerial); - exec([=] { + exec([&] { auto *surface = xdgToplevel()->surface(); auto *p = pointer(); auto *c = client(); @@ -310,11 +340,11 @@ void tst_xdgshell::tooltipOnPopup() }); QCOMPOSITOR_TRY_VERIFY(xdgPopup()); - exec([=] { xdgPopup()->sendCompleteConfigure(QRect(100, 100, 100, 100)); }); + exec([&] { xdgPopup()->sendCompleteConfigure(QRect(100, 100, 100, 100)); }); QCOMPOSITOR_TRY_VERIFY(xdgPopup()->m_xdgSurface->m_committedConfigureSerial); QCOMPOSITOR_TRY_VERIFY(xdgPopup()->m_grabbed); - exec([=] { + exec([&] { auto *surface = xdgPopup()->surface(); auto *p = pointer(); auto *c = client(); @@ -326,7 +356,7 @@ void tst_xdgshell::tooltipOnPopup() }); QCOMPOSITOR_TRY_VERIFY(xdgPopup(1)); - exec([=] { xdgPopup(1)->sendCompleteConfigure(QRect(100, 100, 100, 100)); }); + exec([&] { xdgPopup(1)->sendCompleteConfigure(QRect(100, 100, 100, 100)); }); QCOMPOSITOR_TRY_VERIFY(xdgPopup(1)->m_xdgSurface->m_committedConfigureSerial); QCOMPOSITOR_TRY_VERIFY(!xdgPopup(1)->m_grabbed); @@ -339,6 +369,92 @@ void tst_xdgshell::tooltipOnPopup() QCOMPOSITOR_TRY_COMPARE(xdgPopup(0), nullptr); } +void tst_xdgshell::tooltipAndSiblingPopup() +{ + class ToolTip : public QRasterWindow { + public: + explicit ToolTip(QWindow *parent) { + setTransientParent(parent); + setFlags(Qt::ToolTip); + resize(100, 100); + show(); + } + void mousePressEvent(QMouseEvent *event) override { + QRasterWindow::mousePressEvent(event); + m_popup = new QRasterWindow; + m_popup->setTransientParent(transientParent()); + m_popup->setFlags(Qt::Popup); + m_popup->resize(100, 100); + m_popup->show(); + } + + QRasterWindow *m_popup = nullptr; + }; + + class Window : public QRasterWindow { + public: + void mousePressEvent(QMouseEvent *event) override { + QRasterWindow::mousePressEvent(event); + m_tooltip = new ToolTip(this); + } + ToolTip *m_tooltip = nullptr; + }; + + Window window; + window.resize(200, 200); + window.show(); + + QCOMPOSITOR_TRY_VERIFY(xdgToplevel()); + exec([&] { xdgToplevel()->sendCompleteConfigure(); }); + QCOMPOSITOR_TRY_VERIFY(xdgToplevel()->m_xdgSurface->m_committedConfigureSerial); + + exec([&] { + auto *surface = xdgToplevel()->surface(); + auto *p = pointer(); + auto *c = client(); + p->sendEnter(surface, {100, 100}); + p->sendFrame(c); + p->sendButton(client(), BTN_LEFT, Pointer::button_state_pressed); + p->sendButton(client(), BTN_LEFT, Pointer::button_state_released); + p->sendFrame(c); + p->sendLeave(surface); + p->sendFrame(c); + }); + + QCOMPOSITOR_TRY_VERIFY(xdgPopup()); + exec([&] { xdgPopup()->sendCompleteConfigure(QRect(100, 100, 100, 100)); }); + QCOMPOSITOR_TRY_VERIFY(xdgPopup()->m_xdgSurface->m_committedConfigureSerial); + QCOMPOSITOR_TRY_VERIFY(!xdgPopup()->m_grabbed); + + exec([&] { + auto *surface = xdgPopup()->surface(); + auto *p = pointer(); + auto *c = client(); + p->sendEnter(surface, {100, 100}); + p->sendFrame(c); + p->sendButton(client(), BTN_LEFT, Pointer::button_state_pressed); + p->sendButton(client(), BTN_LEFT, Pointer::button_state_released); + p->sendFrame(c); + }); + + QCOMPOSITOR_TRY_VERIFY(xdgPopup(1)); + exec([&] { xdgPopup(1)->sendCompleteConfigure(QRect(100, 100, 100, 100)); }); + QCOMPOSITOR_TRY_VERIFY(xdgPopup(1)->m_xdgSurface->m_committedConfigureSerial); + QCOMPOSITOR_TRY_VERIFY(xdgPopup(1)->m_grabbed); + + // Close the middle tooltip (it should not close the sibling popup) + window.m_tooltip->close(); + + QCOMPOSITOR_TRY_COMPARE(xdgPopup(1), nullptr); + // Verify the remaining xdg surface is a grab popup.. + QCOMPOSITOR_TRY_VERIFY(xdgPopup(0)); + QCOMPOSITOR_TRY_VERIFY(xdgPopup(0)->m_grabbed); + + window.m_tooltip->m_popup->close(); + QCOMPOSITOR_TRY_COMPARE(xdgPopup(1), nullptr); + QCOMPOSITOR_TRY_COMPARE(xdgPopup(0), nullptr); +} + // QTBUG-65680 void tst_xdgshell::switchPopups() { @@ -369,7 +485,7 @@ void tst_xdgshell::switchPopups() m_popups << new Popup(this); } ~Window() override { qDeleteAll(m_popups); } - QVector<Popup *> m_popups; + QList<Popup *> m_popups; }; Window window; @@ -377,10 +493,10 @@ void tst_xdgshell::switchPopups() window.show(); QCOMPOSITOR_TRY_VERIFY(xdgToplevel()); - exec([=] { xdgToplevel()->sendCompleteConfigure(); }); + exec([&] { xdgToplevel()->sendCompleteConfigure(); }); QCOMPOSITOR_TRY_VERIFY(xdgToplevel()->m_xdgSurface->m_committedConfigureSerial); - exec([=] { + exec([&] { auto *surface = xdgToplevel()->surface(); auto *p = pointer(); auto *c = client(); @@ -394,13 +510,13 @@ void tst_xdgshell::switchPopups() }); QCOMPOSITOR_TRY_VERIFY(xdgPopup()); - exec([=] { xdgPopup()->sendCompleteConfigure(QRect(100, 100, 100, 100)); }); + exec([&] { xdgPopup()->sendCompleteConfigure(QRect(100, 100, 100, 100)); }); QCOMPOSITOR_TRY_VERIFY(xdgPopup()->m_xdgSurface->m_committedConfigureSerial); QCOMPOSITOR_TRY_VERIFY(xdgPopup()->m_grabbed); - QSignalSpy firstDestroyed(exec([=] { return xdgPopup(); }), &XdgPopup::destroyRequested); + QSignalSpy firstDestroyed(exec([&] { return xdgPopup(); }), &XdgPopup::destroyRequested); - exec([=] { + exec([&] { auto *surface = xdgToplevel()->surface(); auto *p = pointer(); auto *c = client(); @@ -425,10 +541,54 @@ void tst_xdgshell::switchPopups() QCOMPOSITOR_TRY_VERIFY(xdgPopup()->m_parentXdgSurface == xdgToplevel()->m_xdgSurface); // For good measure just check that configuring works as usual - exec([=] { xdgPopup()->sendCompleteConfigure(QRect(100, 100, 100, 100)); }); + exec([&] { xdgPopup()->sendCompleteConfigure(QRect(100, 100, 100, 100)); }); QCOMPOSITOR_TRY_VERIFY(xdgPopup()->m_xdgSurface->m_committedConfigureSerial); } +void tst_xdgshell::hidePopupParent() +{ + class Window : public QRasterWindow { + public: + void mousePressEvent(QMouseEvent *event) override + { + QRasterWindow::mousePressEvent(event); + m_popup.reset(new QRasterWindow); + m_popup->setTransientParent(this); + m_popup->setFlags(Qt::Popup); + m_popup->resize(100, 100); + m_popup->show(); + } + QScopedPointer<QRasterWindow> m_popup; + }; + Window window; + window.resize(200, 200); + window.show(); + + QCOMPOSITOR_TRY_VERIFY(xdgToplevel()); + exec([&] { xdgToplevel()->sendCompleteConfigure(); }); + QCOMPOSITOR_TRY_VERIFY(xdgToplevel()->m_xdgSurface->m_committedConfigureSerial); + + exec([&] { + auto *surface = xdgToplevel()->surface(); + auto *p = pointer(); + auto *c = client(); + p->sendEnter(surface, {100, 100}); + p->sendFrame(c); + p->sendButton(c, BTN_LEFT, Pointer::button_state_pressed); + p->sendButton(c, BTN_LEFT, Pointer::button_state_released); + p->sendFrame(c); + }); + QCOMPOSITOR_TRY_VERIFY(xdgPopup()); + exec([&] { + xdgPopup()->sendConfigure(QRect(100, 100, 100, 100)); + xdgPopup()->m_xdgSurface->sendConfigure(); + }); + QCOMPOSITOR_TRY_VERIFY(xdgPopup()->m_xdgSurface->m_committedConfigureSerial); + + window.hide(); + QCOMPOSITOR_TRY_VERIFY(!xdgToplevel()); +} + void tst_xdgshell::pongs() { // Create and show a window to trigger shell integration initialzation, @@ -440,36 +600,80 @@ void tst_xdgshell::pongs() // Verify that the client has bound to the global QCOMPOSITOR_TRY_COMPARE(get<XdgWmBase>()->resourceMap().size(), 1); - QSignalSpy pongSpy(exec([=] { return get<XdgWmBase>(); }), &XdgWmBase::pong); - const uint serial = exec([=] { return nextSerial(); }); - exec([=] { + QSignalSpy pongSpy(exec([&] { return get<XdgWmBase>(); }), &XdgWmBase::pong); + const uint serial = exec([&] { return nextSerial(); }); + exec([&] { auto *base = get<XdgWmBase>(); wl_resource *resource = base->resourceMap().first()->handle; base->send_ping(resource, serial); }); - QTRY_COMPARE(pongSpy.count(), 1); + QTRY_COMPARE(pongSpy.size(), 1); QCOMPARE(pongSpy.first().at(0).toUInt(), serial); } +void tst_xdgshell::minMaxSize_data() +{ + QTest::addColumn<QSize>("initialMinSize"); + QTest::addColumn<QSize>("initialMaxSize"); + QTest::addColumn<QSize>("nextMinSize"); + QTest::addColumn<QSize>("nextMaxSize"); + QTest::addColumn<QSize>("expectedInitialMinSize"); + QTest::addColumn<QSize>("expectedInitialMaxSize"); + QTest::addColumn<QSize>("expectedNextMinSize"); + QTest::addColumn<QSize>("expectedNextMaxSize"); + + QTest::newRow("onlyMinSize") << QSize(50, 60) << QSize() << QSize(500, 600) << QSize() + << QSize(50, 60) << QSize(0, 0) << QSize(500, 600) << QSize(0, 0); + + QTest::newRow("onlyMaxSize") << QSize() << QSize(70, 80) << QSize() << QSize(700, 800) + << QSize(0,0 ) << QSize(70, 80) << QSize(0, 0) << QSize(700, 800); + + QTest::newRow("maxIsSentAsZero") << QSize() << QSize(QWINDOWSIZE_MAX, QWINDOWSIZE_MAX) << QSize() << QSize() + << QSize(0,0 ) << QSize(0, 0) << QSize(0, 0) << QSize(0, 0); + + + QTest::newRow("fullHints") << QSize(50, 60) << QSize(700, 800) << QSize(500, 600) << QSize(710, 810) + << QSize(50, 60) << QSize(700, 800) << QSize(500, 600) << QSize(710, 810); + + // setting a minimum above the maximum is not allowed, we should no-op + QTest::newRow("invalidResize") << QSize(50, 60) << QSize(100, 100) << QSize(500, 600) << QSize(100, 100) + << QSize(50, 60) << QSize(100, 100) << QSize(50, 60) << QSize(100, 100);} + void tst_xdgshell::minMaxSize() { + QFETCH(QSize, initialMinSize); + QFETCH(QSize, initialMaxSize); + + QFETCH(QSize, expectedInitialMinSize); + QFETCH(QSize, expectedInitialMaxSize); + QRasterWindow window; - window.setMinimumSize(QSize(100, 100)); - window.setMaximumSize(QSize(1000, 1000)); - window.resize(400, 320); + if (initialMinSize.isValid()) + window.setMinimumSize(initialMinSize); + if (initialMaxSize.isValid()) + window.setMaximumSize(initialMaxSize); window.show(); QCOMPOSITOR_TRY_VERIFY(xdgToplevel()); - exec([=] { xdgToplevel()->sendCompleteConfigure(); }); + exec([&] { xdgToplevel()->sendCompleteConfigure(); }); - QCOMPOSITOR_TRY_COMPARE(xdgToplevel()->m_committed.minSize, QSize(100, 100)); - QCOMPOSITOR_TRY_COMPARE(xdgToplevel()->m_committed.maxSize, QSize(1000, 1000)); + // we don't roundtrip with our configuration the initial commit should be correct - window.setMaximumSize(QSize(500, 400)); - QCOMPOSITOR_TRY_COMPARE(xdgToplevel()->m_committed.maxSize, QSize(500, 400)); + QCOMPOSITOR_TRY_COMPARE(xdgToplevel()->m_committed.minSize, expectedInitialMinSize); + QCOMPOSITOR_TRY_COMPARE(xdgToplevel()->m_committed.maxSize, expectedInitialMaxSize); - window.setMinimumSize(QSize(50, 40)); - QCOMPOSITOR_TRY_COMPARE(xdgToplevel()->m_committed.minSize, QSize(50, 40)); + QFETCH(QSize, nextMinSize); + QFETCH(QSize, expectedNextMinSize); + window.setMinimumSize(nextMinSize); + window.update(); + QCOMPOSITOR_TRY_COMPARE(xdgToplevel()->m_committed.minSize, expectedNextMinSize); + + QFETCH(QSize, nextMaxSize); + QFETCH(QSize, expectedNextMaxSize); + + window.setMaximumSize(nextMaxSize); + window.update(); + QCOMPOSITOR_TRY_COMPARE(xdgToplevel()->m_committed.maxSize, expectedNextMaxSize); } void tst_xdgshell::windowGeometry() @@ -479,7 +683,7 @@ void tst_xdgshell::windowGeometry() window.show(); QCOMPOSITOR_TRY_VERIFY(xdgToplevel()); - exec([=] { xdgToplevel()->sendCompleteConfigure(); }); + exec([&] { xdgToplevel()->sendCompleteConfigure(); }); QSize marginsSize; marginsSize.setWidth(window.frameMargins().left() + window.frameMargins().right()); @@ -511,12 +715,95 @@ void tst_xdgshell::foreignSurface() // Just do something to make sure we don't destroy the surface before // the pointer events above are handled. - QSignalSpy spy(exec([=] { return surface(newSurfaceIndex); }), &Surface::commit); + QSignalSpy spy(exec([&] { return surface(newSurfaceIndex); }), &Surface::commit); wl_surface_commit(foreignSurface); - QTRY_COMPARE(spy.count(), 1); + QTRY_COMPARE(spy.size(), 1); wl_surface_destroy(foreignSurface); } +void tst_xdgshell::nativeResources() +{ + QRasterWindow window; + window.resize(400, 320); + window.show(); + QCOMPOSITOR_TRY_VERIFY(xdgToplevel()); + + auto *ni = QGuiApplication::platformNativeInterface(); + auto *xdg_surface_proxy = static_cast<::wl_proxy *>(ni->nativeResourceForWindow("xdg_surface", &window)); + QCOMPARE(wl_proxy_get_class(xdg_surface_proxy), "xdg_surface"); + + auto *xdg_toplevel_proxy = static_cast<::wl_proxy *>(ni->nativeResourceForWindow("xdg_toplevel", &window)); + QCOMPARE(wl_proxy_get_class(xdg_toplevel_proxy), "xdg_toplevel"); + + auto *xdg_popup_proxy = static_cast<::wl_proxy *>(ni->nativeResourceForWindow("xdg_popup", &window)); + QCOMPARE(xdg_popup_proxy, nullptr); +} + +void tst_xdgshell::suspended() +{ + QRasterWindow window; + window.resize(400, 320); + window.show(); + QVERIFY(!window.isExposed()); // not exposed until we're configured + QCOMPOSITOR_TRY_VERIFY(xdgToplevel()); + + exec([=] { xdgToplevel()->sendCompleteConfigure(); }); + QCOMPOSITOR_TRY_VERIFY(xdgToplevel()->m_xdgSurface->m_committedConfigureSerial); + QTRY_VERIFY(window.isExposed()); + + exec([=] { xdgToplevel()->sendCompleteConfigure(QSize(), {XdgToplevel::state_suspended}); }); + QTRY_VERIFY(!window.isExposed()); + + exec([=] { xdgToplevel()->sendCompleteConfigure(QSize(), {}); }); + QTRY_VERIFY(window.isExposed()); +} + +void tst_xdgshell::initiallySuspended() +{ + QRasterWindow window; + window.resize(400, 320); + window.show(); + QVERIFY(!window.isExposed()); + QCOMPOSITOR_TRY_VERIFY(xdgToplevel()); + exec([=] { xdgToplevel()->sendCompleteConfigure(QSize(), {XdgToplevel::state_suspended}); }); + QVERIFY(!window.isExposed()); +} + +void tst_xdgshell::modality() +{ + QRasterWindow parent; + parent.resize(400, 320); + parent.show(); + + QRasterWindow child; + child.resize(400, 320); + child.setTransientParent(&parent); + child.show(); + QCOMPOSITOR_TRY_VERIFY(xdgToplevel(1)); + QCOMPOSITOR_VERIFY(!xdgDialog()); + + child.hide(); + child.setModality(Qt::WindowModal); + child.show(); + QCOMPOSITOR_TRY_VERIFY(xdgDialog()); + QCOMPOSITOR_VERIFY(xdgDialog()->modal); + + child.hide(); + QCOMPOSITOR_TRY_VERIFY(!xdgDialog()); + + child.setModality(Qt::ApplicationModal); + child.show(); + QCOMPOSITOR_TRY_VERIFY(xdgDialog()); + QCOMPOSITOR_VERIFY(xdgDialog()->modal); + + child.hide(); + QCOMPOSITOR_TRY_VERIFY(!xdgDialog()); + + child.show(); + child.setModality(Qt::NonModal); + QCOMPOSITOR_TRY_VERIFY(!xdgDialog()); +} + QCOMPOSITOR_TEST_MAIN(tst_xdgshell) #include "tst_xdgshell.moc" diff --git a/tests/auto/client/xdgshell/xdgshell.pro b/tests/auto/client/xdgshell/xdgshell.pro deleted file mode 100644 index d7c3f9df6..000000000 --- a/tests/auto/client/xdgshell/xdgshell.pro +++ /dev/null @@ -1,5 +0,0 @@ -include (../shared/shared.pri) - -TARGET = tst_xdgshell -SOURCES += tst_xdgshell.cpp - diff --git a/tests/auto/client/xdgshellv6/tst_xdgshellv6.cpp b/tests/auto/client/xdgshellv6/tst_xdgshellv6.cpp deleted file mode 100644 index e44475de7..000000000 --- a/tests/auto/client/xdgshellv6/tst_xdgshellv6.cpp +++ /dev/null @@ -1,445 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "mockcompositor.h" - -#include <QBackingStore> -#include <QPainter> -#include <QScreen> -#include <QWindow> -#include <QMimeData> -#include <QPixmap> -#include <QDrag> - -#include <QtTest/QtTest> - -static const QSize screenSize(1600, 1200); - -class TestWindow : public QWindow -{ - Q_OBJECT -public: - TestWindow() - { - setSurfaceType(QSurface::RasterSurface); - setGeometry(0, 0, 32, 32); - create(); - } - - bool event(QEvent *event) override - { - if (event->type() == QEvent::WindowStateChange) - emit windowStateChangeEventReceived(static_cast<QWindowStateChangeEvent *>(event)->oldState()); - return QWindow::event(event); - } - - void exposeEvent(QExposeEvent *event) override - { - ++exposeEventCount; - QWindow::exposeEvent(event); - } - - int exposeEventCount = 0; - -signals: - void windowStateChangeEventReceived(uint oldState); -}; - -class tst_WaylandClientXdgShellV6 : public QObject -{ - Q_OBJECT -public: - tst_WaylandClientXdgShellV6(MockCompositor *c) - : m_compositor(c) - { - qRegisterMetaType<Qt::WindowState>(); - QSocketNotifier *notifier = new QSocketNotifier(m_compositor->waylandFileDescriptor(), QSocketNotifier::Read, this); - connect(notifier, &QSocketNotifier::activated, this, &tst_WaylandClientXdgShellV6::processWaylandEvents); - // connect to the event dispatcher to make sure to flush out the outgoing message queue - connect(QCoreApplication::eventDispatcher(), &QAbstractEventDispatcher::awake, this, &tst_WaylandClientXdgShellV6::processWaylandEvents); - connect(QCoreApplication::eventDispatcher(), &QAbstractEventDispatcher::aboutToBlock, this, &tst_WaylandClientXdgShellV6::processWaylandEvents); - } - -public slots: - void processWaylandEvents() - { - m_compositor->processWaylandEvents(); - } - - void cleanup() - { - // make sure the surfaces from the last test are properly cleaned up - // and don't show up as false positives in the next test - QTRY_VERIFY(!m_compositor->surface()); - QTRY_VERIFY(!m_compositor->xdgToplevelV6()); - } - -private slots: - void createDestroyWindow(); - void configure(); - void showMinimized(); - void setMinimized(); - void unsetMaximized(); - void focusWindowFollowsConfigure(); - void windowStateChangedEvents(); - void windowGeometrySimple(); - void windowGeometryFixed(); - void flushUnconfiguredXdgSurface(); - void dontSpamExposeEvents(); - -private: - MockCompositor *m_compositor = nullptr; -}; - -void tst_WaylandClientXdgShellV6::createDestroyWindow() -{ - TestWindow window; - window.show(); - - QTRY_VERIFY(m_compositor->surface()); - - window.destroy(); - QTRY_VERIFY(!m_compositor->surface()); -} - -void tst_WaylandClientXdgShellV6::configure() -{ - QSharedPointer<MockOutput> output; - QTRY_VERIFY(output = m_compositor->output()); - - TestWindow window; - window.show(); - - QSharedPointer<MockSurface> surface; - QTRY_VERIFY(surface = m_compositor->surface()); - - m_compositor->processWaylandEvents(); - QTRY_VERIFY(window.isVisible()); - QTRY_VERIFY(!window.isExposed()); //Window should not be exposed before the first configure event - - //TODO: according to xdg-shell protocol, a buffer should not be attached to a the surface - //until it's configured. Ensure this in the test! - - QSharedPointer<MockXdgToplevelV6> toplevel; - QTRY_VERIFY(toplevel = m_compositor->xdgToplevelV6()); - - const QSize newSize(123, 456); - m_compositor->sendXdgToplevelV6Configure(toplevel, newSize); - QTRY_VERIFY(window.isExposed()); - QTRY_COMPARE(window.visibility(), QWindow::Windowed); - QTRY_COMPARE(window.windowStates(), Qt::WindowNoState); - QTRY_COMPARE(window.frameGeometry(), QRect(QPoint(), newSize)); - - m_compositor->sendXdgToplevelV6Configure(toplevel, screenSize, { ZXDG_TOPLEVEL_V6_STATE_ACTIVATED, ZXDG_TOPLEVEL_V6_STATE_MAXIMIZED }); - QTRY_COMPARE(window.visibility(), QWindow::Maximized); - QTRY_COMPARE(window.windowStates(), Qt::WindowMaximized); - QTRY_COMPARE(window.frameGeometry(), QRect(QPoint(), screenSize)); - - m_compositor->sendXdgToplevelV6Configure(toplevel, screenSize, { ZXDG_TOPLEVEL_V6_STATE_ACTIVATED, ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN }); - QTRY_COMPARE(window.visibility(), QWindow::FullScreen); - QTRY_COMPARE(window.windowStates(), Qt::WindowFullScreen); - QTRY_COMPARE(window.frameGeometry(), QRect(QPoint(), screenSize)); - - //The window should remember it's original size - m_compositor->sendXdgToplevelV6Configure(toplevel, QSize(0, 0), { ZXDG_TOPLEVEL_V6_STATE_ACTIVATED }); - QTRY_COMPARE(window.visibility(), QWindow::Windowed); - QTRY_COMPARE(window.windowStates(), Qt::WindowNoState); - QTRY_COMPARE(window.frameGeometry(), QRect(QPoint(), newSize)); -} - -void tst_WaylandClientXdgShellV6::showMinimized() -{ - // On xdg-shell v6 there's really no way for the compositor to tell the window if it's minimized - // There are wl_surface.enter events and so on, but there's really no way to differentiate - // between a window preview and an unminimized window. - TestWindow window; - window.showMinimized(); - QCOMPARE(window.windowStates(), Qt::WindowMinimized); // should return minimized until - QTRY_COMPARE(window.windowStates(), Qt::WindowNoState); // rejected by handleWindowStateChanged - - // Make sure the window on the compositor side is/was created here, and not after the test - // finishes, as that may mess up for later tests. - QTRY_VERIFY(m_compositor->xdgToplevelV6()); -} - -void tst_WaylandClientXdgShellV6::setMinimized() -{ - TestWindow window; - window.show(); - - QSharedPointer<MockXdgToplevelV6> toplevel; - QTRY_VERIFY(toplevel = m_compositor->xdgToplevelV6()); - - m_compositor->sendXdgToplevelV6Configure(toplevel); - QTRY_COMPARE(window.visibility(), QWindow::Windowed); - QTRY_COMPARE(window.windowStates(), Qt::WindowNoState); - - QSignalSpy setMinimizedSpy(toplevel.data(), SIGNAL(setMinimizedRequested())); - QSignalSpy windowStateChangeSpy(&window, SIGNAL(windowStateChangeEventReceived(uint))); - - window.setVisibility(QWindow::Minimized); - QCOMPARE(window.visibility(), QWindow::Minimized); - QCOMPARE(window.windowStates(), Qt::WindowMinimized); - QTRY_COMPARE(setMinimizedSpy.count(), 1); - { - QTRY_VERIFY(windowStateChangeSpy.count() > 0); - Qt::WindowStates oldStates(windowStateChangeSpy.takeFirst().at(0).toUInt()); - QCOMPARE(oldStates, Qt::WindowNoState); - } - - // In the meantime the compositor may minimize, do nothing or reshow the window without - // telling us. - - QTRY_COMPARE(window.visibility(), QWindow::Windowed); // verify that we don't know anything - QTRY_COMPARE(window.windowStates(), Qt::WindowNoState); - { - QTRY_COMPARE(windowStateChangeSpy.count(), 1); - Qt::WindowStates oldStates(windowStateChangeSpy.takeFirst().at(0).toUInt()); - QCOMPARE(oldStates, Qt::WindowNoState); // because the window never was minimized - } - - // Setting visibility again should send another set_minimized request - window.setVisibility(QWindow::Minimized); - QTRY_COMPARE(setMinimizedSpy.count(), 2); -} - -void tst_WaylandClientXdgShellV6::unsetMaximized() -{ - TestWindow window; - window.show(); - - QSharedPointer<MockXdgToplevelV6> toplevel; - QTRY_VERIFY(toplevel = m_compositor->xdgToplevelV6()); - - QSignalSpy unsetMaximizedSpy(toplevel.data(), SIGNAL(unsetMaximizedRequested())); - - QSignalSpy windowStateChangedSpy(&window, SIGNAL(windowStateChanged(Qt::WindowState))); - - m_compositor->sendXdgToplevelV6Configure(toplevel, screenSize, { ZXDG_TOPLEVEL_V6_STATE_MAXIMIZED }); - - QTRY_COMPARE(windowStateChangedSpy.count(), 1); - QCOMPARE(windowStateChangedSpy.takeFirst().at(0).toUInt(), Qt::WindowMaximized); - - window.setWindowStates(Qt::WindowNoState); - - QTRY_COMPARE(unsetMaximizedSpy.count(), 1); - QTRY_COMPARE(windowStateChangedSpy.count(), 1); - QCOMPARE(windowStateChangedSpy.takeFirst().at(0).toUInt(), Qt::WindowNoState); - - m_compositor->sendXdgToplevelV6Configure(toplevel, QSize(0, 0), {}); - - QTRY_COMPARE(windowStateChangedSpy.count(), 1); - QCOMPARE(windowStateChangedSpy.takeFirst().at(0).toUInt(), Qt::WindowNoState); -} - -void tst_WaylandClientXdgShellV6::focusWindowFollowsConfigure() -{ - TestWindow window; - window.show(); - - QSharedPointer<MockXdgToplevelV6> toplevel; - QTRY_VERIFY(toplevel = m_compositor->xdgToplevelV6()); - QTRY_VERIFY(!window.isActive()); - - QSignalSpy windowStateChangeSpy(&window, SIGNAL(windowStateChangeEventReceived(uint))); - - m_compositor->sendXdgToplevelV6Configure(toplevel, QSize(0, 0), { ZXDG_TOPLEVEL_V6_STATE_ACTIVATED }); - QTRY_VERIFY(window.isActive()); - - m_compositor->sendXdgToplevelV6Configure(toplevel, QSize(0, 0), {}); - QTRY_VERIFY(!window.isActive()); -} - -void tst_WaylandClientXdgShellV6::windowStateChangedEvents() -{ - TestWindow window; - window.show(); - - QSharedPointer<MockXdgToplevelV6> toplevel; - QTRY_VERIFY(toplevel = m_compositor->xdgToplevelV6()); - - QSignalSpy eventSpy(&window, SIGNAL(windowStateChangeEventReceived(uint))); - QSignalSpy signalSpy(&window, SIGNAL(windowStateChanged(Qt::WindowState))); - - m_compositor->sendXdgToplevelV6Configure(toplevel, screenSize, { ZXDG_TOPLEVEL_V6_STATE_MAXIMIZED }); - - QTRY_COMPARE(window.windowStates(), Qt::WindowMaximized); - QTRY_COMPARE(window.windowState(), Qt::WindowMaximized); - { - QTRY_COMPARE(eventSpy.count(), 1); - Qt::WindowStates oldStates(eventSpy.takeFirst().at(0).toUInt()); - QCOMPARE(oldStates, Qt::WindowNoState); - - QTRY_COMPARE(signalSpy.count(), 1); - uint newState = signalSpy.takeFirst().at(0).toUInt(); - QCOMPARE(newState, Qt::WindowMaximized); - } - - m_compositor->sendXdgToplevelV6Configure(toplevel, screenSize, { ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN }); - - QTRY_COMPARE(window.windowStates(), Qt::WindowFullScreen); - QTRY_COMPARE(window.windowState(), Qt::WindowFullScreen); - { - QTRY_COMPARE(eventSpy.count(), 1); - Qt::WindowStates oldStates(eventSpy.takeFirst().at(0).toUInt()); - QCOMPARE(oldStates, Qt::WindowMaximized); - - QTRY_COMPARE(signalSpy.count(), 1); - uint newState = signalSpy.takeFirst().at(0).toUInt(); - QCOMPARE(newState, Qt::WindowFullScreen); - } - - m_compositor->sendXdgToplevelV6Configure(toplevel, QSize(0, 0), {}); - - QTRY_COMPARE(window.windowStates(), Qt::WindowNoState); - QTRY_COMPARE(window.windowState(), Qt::WindowNoState); - { - QTRY_COMPARE(eventSpy.count(), 1); - Qt::WindowStates oldStates(eventSpy.takeFirst().at(0).toUInt()); - QCOMPARE(oldStates, Qt::WindowFullScreen); - - QTRY_COMPARE(signalSpy.count(), 1); - uint newState = signalSpy.takeFirst().at(0).toUInt(); - QCOMPARE(newState, Qt::WindowNoState); - } -} - -void tst_WaylandClientXdgShellV6::windowGeometrySimple() -{ - QSKIP("TODO: This test is flaky, figure out why."); - QWindow window; - window.show(); - - QSharedPointer<MockXdgToplevelV6> toplevel; - QTRY_VERIFY(toplevel = m_compositor->xdgToplevelV6()); - QSignalSpy geometrySpy(toplevel.data(), SIGNAL(windowGeometryRequested(QRect))); - - m_compositor->sendXdgToplevelV6Configure(toplevel); - QTRY_COMPARE(geometrySpy.count(), 1); - QCOMPARE(geometrySpy.takeFirst().at(0).toRect().size(), window.frameGeometry().size()); - - m_compositor->sendXdgToplevelV6Configure(toplevel, QSize(123, 456)); - QTRY_COMPARE(geometrySpy.count(), 1); - QCOMPARE(geometrySpy.takeFirst().at(0).toRect().size(), QSize(123, 456)); -} - -void tst_WaylandClientXdgShellV6::windowGeometryFixed() -{ - QSKIP("TODO: This test is flaky, figure out why."); - QWindow window; - window.resize(QSize(1337, 137)); - window.setMaximumSize(window.size()); - window.setMinimumSize(window.size()); - window.show(); - - QSharedPointer<MockXdgToplevelV6> toplevel; - QTRY_VERIFY(toplevel = m_compositor->xdgToplevelV6()); - QSignalSpy geometrySpy(toplevel.data(), SIGNAL(windowGeometryRequested(QRect))); - - m_compositor->sendXdgToplevelV6Configure(toplevel); - QTRY_COMPARE(geometrySpy.count(), 1); - QRect initialWindowGeometry = geometrySpy.takeFirst().at(0).toRect(); - QCOMPARE(initialWindowGeometry.size(), window.frameGeometry().size()); - - m_compositor->sendXdgToplevelV6Configure(toplevel, QSize(123, 456)); - QTRY_COMPARE(geometrySpy.count(), 1); - // Configuring the window should not change the window geometry - QCOMPARE(geometrySpy.takeFirst().at(0).toRect().size(), initialWindowGeometry.size()); -} - -void tst_WaylandClientXdgShellV6::flushUnconfiguredXdgSurface() -{ - TestWindow window; - window.show(); - - QSharedPointer<MockSurface> surface; - QTRY_VERIFY(surface = m_compositor->surface()); - - // Paint and flush some magenta - QBackingStore backingStore(&window); - QRect rect(QPoint(), window.size()); - backingStore.resize(rect.size()); - backingStore.beginPaint(rect); - QColor color = Qt::magenta; - QPainter p(backingStore.paintDevice()); - p.fillRect(rect, color); - p.end(); - backingStore.endPaint(); - backingStore.flush(rect); - - // We're not allowed to send buffer on this surface since it isn't yet configured. - // So, from the compositor's point of view there should be no buffer data yet. - m_compositor->processWaylandEvents(); - QVERIFY(surface->image.isNull()); - QVERIFY(!window.isExposed()); - - // Finally sending the configure should trigger an attach and commit with the - // right buffer. - m_compositor->sendShellSurfaceConfigure(surface); - QTRY_COMPARE(surface->image.size(), window.frameGeometry().size()); - QTRY_COMPARE(surface->image.pixel(window.frameMargins().left(), window.frameMargins().top()), color.rgba()); - QVERIFY(window.isExposed()); -} - -void tst_WaylandClientXdgShellV6::dontSpamExposeEvents() -{ - TestWindow window; - window.show(); - - QSharedPointer<MockSurface> surface; - QTRY_VERIFY(surface = m_compositor->surface()); - QTRY_COMPARE(window.exposeEventCount, 0); - - m_compositor->sendShellSurfaceConfigure(surface); - QTRY_VERIFY(window.isExposed()); - QTRY_COMPARE(window.exposeEventCount, 1); -} - -int main(int argc, char **argv) -{ - QTemporaryDir tmpRuntimeDir; - setenv("XDG_RUNTIME_DIR", tmpRuntimeDir.path().toLocal8Bit(), 1); - setenv("QT_QPA_PLATFORM", "wayland", 1); // force QGuiApplication to use wayland plugin - setenv("QT_WAYLAND_SHELL_INTEGRATION", "xdg-shell-v6", 1); - - // wayland-egl hangs in the test setup when we try to initialize. Until it gets - // figured out, avoid clientBufferIntegration() from being called in - // QWaylandWindow::createDecorations(). - setenv("QT_WAYLAND_DISABLE_WINDOWDECORATION", "1", 1); - - MockCompositor compositor; - compositor.setOutputMode(screenSize); - - QGuiApplication app(argc, argv); - compositor.applicationInitialized(); - - tst_WaylandClientXdgShellV6 tc(&compositor); - return QTest::qExec(&tc, argc, argv); -} - -#include <tst_xdgshellv6.moc> diff --git a/tests/auto/client/xdgshellv6/xdgshellv6.pro b/tests/auto/client/xdgshellv6/xdgshellv6.pro deleted file mode 100644 index cc8a22d83..000000000 --- a/tests/auto/client/xdgshellv6/xdgshellv6.pro +++ /dev/null @@ -1,5 +0,0 @@ -include (../shared_old/shared_old.pri) - -TARGET = tst_client_xdgshellv6 -SOURCES += tst_xdgshellv6.cpp - diff --git a/tests/auto/cmake/CMakeLists.txt b/tests/auto/cmake/CMakeLists.txt index 270d11aa6..ec8a54567 100644 --- a/tests/auto/cmake/CMakeLists.txt +++ b/tests/auto/cmake/CMakeLists.txt @@ -1,18 +1,19 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause -cmake_minimum_required(VERSION 2.8) - -project(qmake_cmake_files) +cmake_minimum_required(VERSION 3.16) +project(qtwayland_cmake_tests) enable_testing() -find_package(Qt5Core REQUIRED) -set(Qt5_MODULE_TEST_DEPENDS Quick) +find_package(Qt6Core REQUIRED) +set(Qt6_MODULE_TEST_DEPENDS Quick) -include("${_Qt5CTestMacros}") +include("${_Qt6CTestMacros}") -test_module_includes( +_qt_internal_test_module_includes( WaylandCompositor QWaylandBufferRef ) -# Can't test in `test_module_includes`, WaylandClient has no public headers -expect_pass(test_waylandclient) +# Can't test in `_qt_internal_test_module_includes`, WaylandClient has no public headers +_qt_internal_test_expect_pass(test_waylandclient) diff --git a/tests/auto/cmake/cmake.pro b/tests/auto/cmake/cmake.pro deleted file mode 100644 index 5098c2ce4..000000000 --- a/tests/auto/cmake/cmake.pro +++ /dev/null @@ -1,6 +0,0 @@ -# Cause make to do nothing. -TEMPLATE = subdirs - -CMAKE_QT_MODULES_UNDER_TEST = waylandclient - -CONFIG += ctest_testcase diff --git a/tests/auto/cmake/test_waylandclient/CMakeLists.txt b/tests/auto/cmake/test_waylandclient/CMakeLists.txt index 3788a4927..cad8d45d3 100644 --- a/tests/auto/cmake/test_waylandclient/CMakeLists.txt +++ b/tests/auto/cmake/test_waylandclient/CMakeLists.txt @@ -1,12 +1,11 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + project(test_plugins) -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 3.16) cmake_policy(SET CMP0056 NEW) -find_package(Qt5WaylandClient REQUIRED) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Core_EXECUTABLE_COMPILE_FLAGS}") - -include_directories(${Qt5WaylandClient_PRIVATE_INCLUDE_DIRS}) +find_package(Qt6WaylandClient REQUIRED) add_executable(test_waylandclient_exe main.cpp) -target_link_libraries(test_waylandclient_exe Qt5::WaylandClient) +target_link_libraries(test_waylandclient_exe Qt6::WaylandClientPrivate) diff --git a/tests/auto/compositor/CMakeLists.txt b/tests/auto/compositor/CMakeLists.txt new file mode 100644 index 000000000..3a6dfedb3 --- /dev/null +++ b/tests/auto/compositor/CMakeLists.txt @@ -0,0 +1,6 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +# Generated from compositor.pro. + +add_subdirectory(compositor) diff --git a/tests/auto/compositor/compositor.pro b/tests/auto/compositor/compositor.pro deleted file mode 100644 index 6bf2aef6c..000000000 --- a/tests/auto/compositor/compositor.pro +++ /dev/null @@ -1,3 +0,0 @@ -TEMPLATE=subdirs - -SUBDIRS += compositor diff --git a/tests/auto/compositor/compositor/CMakeLists.txt b/tests/auto/compositor/compositor/CMakeLists.txt new file mode 100644 index 000000000..5cb18b2aa --- /dev/null +++ b/tests/auto/compositor/compositor/CMakeLists.txt @@ -0,0 +1,47 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +# Generated from compositor.pro. + +##################################################################### +## tst_compositor Test: +##################################################################### + +qt_internal_add_test(tst_compositor + SOURCES + mockclient.cpp mockclient.h + mockkeyboard.cpp mockkeyboard.h + mockpointer.cpp mockpointer.h + mockseat.cpp mockseat.h + mockxdgoutputv1.cpp mockxdgoutputv1.h + testcompositor.cpp testcompositor.h + testkeyboardgrabber.cpp testkeyboardgrabber.h + testseat.cpp testseat.h + tst_compositor.cpp + LIBRARIES + Qt::CorePrivate + Qt::Gui + Qt::GuiPrivate + Qt::WaylandCompositor + Qt::WaylandCompositorPrivate + Wayland::Client + Wayland::Server +) + +qt6_generate_wayland_protocol_client_sources(tst_compositor + FILES + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/3rdparty/protocol/idle-inhibit-unstable-v1.xml + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/3rdparty/protocol/ivi-application.xml + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/3rdparty/protocol/viewporter.xml + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/3rdparty/protocol/wayland.xml + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/3rdparty/protocol/xdg-output-unstable-v1.xml + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/3rdparty/protocol/xdg-shell.xml +) + +## Scopes: +##################################################################### + +qt_internal_extend_target(tst_compositor CONDITION QT_FEATURE_xkbcommon + LIBRARIES + XKB::XKB +) diff --git a/tests/auto/compositor/compositor/compositor.pro b/tests/auto/compositor/compositor/compositor.pro deleted file mode 100644 index 270016597..000000000 --- a/tests/auto/compositor/compositor/compositor.pro +++ /dev/null @@ -1,40 +0,0 @@ -CONFIG += testcase link_pkgconfig -CONFIG += wayland-scanner -TARGET = tst_compositor - -QT += testlib -QT += core-private gui-private waylandcompositor waylandcompositor-private - -QMAKE_USE += wayland-client wayland-server - -qtConfig(xkbcommon): \ - QMAKE_USE += xkbcommon - -WAYLANDCLIENTSOURCES += \ - ../../../../src/3rdparty/protocol/ivi-application.xml \ - ../../../../src/3rdparty/protocol/wayland.xml \ - ../../../../src/3rdparty/protocol/xdg-shell.xml \ - ../../../../src/3rdparty/protocol/viewporter.xml \ - ../../../../src/3rdparty/protocol/idle-inhibit-unstable-v1.xml \ - ../../../../src/3rdparty/protocol/xdg-output-unstable-v1.xml - -SOURCES += \ - tst_compositor.cpp \ - testcompositor.cpp \ - testkeyboardgrabber.cpp \ - mockclient.cpp \ - mockseat.cpp \ - testseat.cpp \ - mockkeyboard.cpp \ - mockpointer.cpp \ - mockxdgoutputv1.cpp - -HEADERS += \ - testcompositor.h \ - testkeyboardgrabber.h \ - mockclient.h \ - mockseat.h \ - testseat.h \ - mockkeyboard.h \ - mockpointer.h \ - mockxdgoutputv1.h diff --git a/tests/auto/compositor/compositor/mockclient.cpp b/tests/auto/compositor/compositor/mockclient.cpp index 27d1eed89..6465f9931 100644 --- a/tests/auto/compositor/compositor/mockclient.cpp +++ b/tests/auto/compositor/compositor/mockclient.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "mockclient.h" #include "mockseat.h" @@ -57,7 +32,7 @@ MockClient::MockClient() fd = wl_display_get_fd(display); QSocketNotifier *readNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, this); - connect(readNotifier, SIGNAL(activated(int)), this, SLOT(readEvents())); + connect(readNotifier, SIGNAL(activated(QSocketDescriptor)), this, SLOT(readEvents())); QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::eventDispatcher; connect(dispatcher, SIGNAL(awake()), this, SLOT(flushDisplay())); @@ -76,7 +51,9 @@ const wl_output_listener MockClient::outputListener = { MockClient::outputGeometryEvent, MockClient::outputModeEvent, MockClient::outputDone, - MockClient::outputScale + MockClient::outputScale, + MockClient::outputName, + MockClient::outputDesc }; MockClient::~MockClient() @@ -123,6 +100,16 @@ void MockClient::outputScale(void *, wl_output *, int) } +void MockClient::outputName(void *, wl_output *, const char *) +{ + +} + +void MockClient::outputDesc(void *, wl_output *, const char *) +{ + +} + void MockClient::readEvents() { if (error) @@ -166,7 +153,7 @@ void MockClient::handleGlobalRemove(void *data, wl_registry *wl_registry, uint32 void MockClient::handleGlobal(uint32_t id, const QByteArray &interface) { if (interface == "wl_compositor") { - compositor = static_cast<wl_compositor *>(wl_registry_bind(registry, id, &wl_compositor_interface, 3)); + compositor = static_cast<wl_compositor *>(wl_registry_bind(registry, id, &wl_compositor_interface, 4)); } else if (interface == "wl_output") { auto output = static_cast<wl_output *>(wl_registry_bind(registry, id, &wl_output_interface, 2)); m_outputs.insert(id, output); diff --git a/tests/auto/compositor/compositor/mockclient.h b/tests/auto/compositor/compositor/mockclient.h index 89d0a0b3f..2f6d9046e 100644 --- a/tests/auto/compositor/compositor/mockclient.h +++ b/tests/auto/compositor/compositor/mockclient.h @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "wayland-wayland-client-protocol.h" #include <qwayland-xdg-shell.h> @@ -128,6 +103,8 @@ private: int refreshRate); static void outputDone(void *data, wl_output *output); static void outputScale(void *data, wl_output *output, int factor); + static void outputName(void *data, wl_output *output, const char *name); + static void outputDesc(void *data, wl_output *output, const char *desc); void handleGlobal(uint32_t id, const QByteArray &interface); void handleGlobalRemove(uint32_t id); diff --git a/tests/auto/compositor/compositor/mockkeyboard.cpp b/tests/auto/compositor/compositor/mockkeyboard.cpp index e5f5f8d36..b3055ffa9 100644 --- a/tests/auto/compositor/compositor/mockkeyboard.cpp +++ b/tests/auto/compositor/compositor/mockkeyboard.cpp @@ -1,33 +1,11 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "mockkeyboard.h" +QT_WARNING_DISABLE_GCC("-Wmissing-field-initializers") +QT_WARNING_DISABLE_CLANG("-Wmissing-field-initializers") + void keyboardKeymap(void *keyboard, struct wl_keyboard *wl_keyboard, uint32_t format, int32_t fd, uint32_t size) { Q_UNUSED(keyboard); diff --git a/tests/auto/compositor/compositor/mockkeyboard.h b/tests/auto/compositor/compositor/mockkeyboard.h index fd7f06aee..093586bb3 100644 --- a/tests/auto/compositor/compositor/mockkeyboard.h +++ b/tests/auto/compositor/compositor/mockkeyboard.h @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef MOCKKEYBOARD_H #define MOCKKEYBOARD_H diff --git a/tests/auto/compositor/compositor/mockpointer.cpp b/tests/auto/compositor/compositor/mockpointer.cpp index 6c51d8bd1..65a8b9ce7 100644 --- a/tests/auto/compositor/compositor/mockpointer.cpp +++ b/tests/auto/compositor/compositor/mockpointer.cpp @@ -1,33 +1,11 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "mockpointer.h" +QT_WARNING_DISABLE_GCC("-Wmissing-field-initializers") +QT_WARNING_DISABLE_CLANG("-Wmissing-field-initializers") + static void pointerEnter(void *pointer, struct wl_pointer *wlPointer, uint serial, struct wl_surface *surface, wl_fixed_t x, wl_fixed_t y) { Q_UNUSED(wlPointer); diff --git a/tests/auto/compositor/compositor/mockpointer.h b/tests/auto/compositor/compositor/mockpointer.h index db6b2b69c..db5c6a0af 100644 --- a/tests/auto/compositor/compositor/mockpointer.h +++ b/tests/auto/compositor/compositor/mockpointer.h @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef MOCKPOINTER_H #define MOCKPOINTER_H diff --git a/tests/auto/compositor/compositor/mockseat.cpp b/tests/auto/compositor/compositor/mockseat.cpp index ce873c129..88b1c94e4 100644 --- a/tests/auto/compositor/compositor/mockseat.cpp +++ b/tests/auto/compositor/compositor/mockseat.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 LG Electronics Ltd., author: <mikko.levonmaa@lge.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 LG Electronics Ltd., author: <mikko.levonmaa@lge.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "mockseat.h" diff --git a/tests/auto/compositor/compositor/mockseat.h b/tests/auto/compositor/compositor/mockseat.h index 0d0f4074c..12a14c727 100644 --- a/tests/auto/compositor/compositor/mockseat.h +++ b/tests/auto/compositor/compositor/mockseat.h @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 LG Electronics Ltd., author: <mikko.levonmaa@lge.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 LG Electronics Ltd., author: <mikko.levonmaa@lge.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef MOCKSEAT #define MOCKSEAT diff --git a/tests/auto/compositor/compositor/mockxdgoutputv1.cpp b/tests/auto/compositor/compositor/mockxdgoutputv1.cpp index eebc55bbb..9349e62d6 100644 --- a/tests/auto/compositor/compositor/mockxdgoutputv1.cpp +++ b/tests/auto/compositor/compositor/mockxdgoutputv1.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2019 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2019 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "mockxdgoutputv1.h" diff --git a/tests/auto/compositor/compositor/mockxdgoutputv1.h b/tests/auto/compositor/compositor/mockxdgoutputv1.h index db5820698..4e3a05c91 100644 --- a/tests/auto/compositor/compositor/mockxdgoutputv1.h +++ b/tests/auto/compositor/compositor/mockxdgoutputv1.h @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2019 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2019 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef MOCKXDGOUTPUTV1_H #define MOCKXDGOUTPUTV1_H diff --git a/tests/auto/compositor/compositor/testcompositor.cpp b/tests/auto/compositor/compositor/testcompositor.cpp index d5967a416..d2f454a93 100644 --- a/tests/auto/compositor/compositor/testcompositor.cpp +++ b/tests/auto/compositor/compositor/testcompositor.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "testcompositor.h" #include "testseat.h" diff --git a/tests/auto/compositor/compositor/testcompositor.h b/tests/auto/compositor/compositor/testcompositor.h index 7829f1a65..0e11def13 100644 --- a/tests/auto/compositor/compositor/testcompositor.h +++ b/tests/auto/compositor/compositor/testcompositor.h @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "qwaylandcompositor.h" #include "qwaylandsurface.h" diff --git a/tests/auto/compositor/compositor/testkeyboardgrabber.cpp b/tests/auto/compositor/compositor/testkeyboardgrabber.cpp index a3aa42ac2..73592dd4f 100644 --- a/tests/auto/compositor/compositor/testkeyboardgrabber.cpp +++ b/tests/auto/compositor/compositor/testkeyboardgrabber.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 LG Electronics, Inc., author: <mikko.levonmaa@lge.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 LG Electronics, Inc., author: <mikko.levonmaa@lge.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "testkeyboardgrabber.h" diff --git a/tests/auto/compositor/compositor/testkeyboardgrabber.h b/tests/auto/compositor/compositor/testkeyboardgrabber.h index 7f0f2c86c..2e2f44df4 100644 --- a/tests/auto/compositor/compositor/testkeyboardgrabber.h +++ b/tests/auto/compositor/compositor/testkeyboardgrabber.h @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 LG Electronics, Inc., author: <mikko.levonmaa@lge.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 LG Electronics, Inc., author: <mikko.levonmaa@lge.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "qwaylandkeyboard.h" diff --git a/tests/auto/compositor/compositor/testseat.cpp b/tests/auto/compositor/compositor/testseat.cpp index 38227872b..21e2bffe5 100644 --- a/tests/auto/compositor/compositor/testseat.cpp +++ b/tests/auto/compositor/compositor/testseat.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 LG Electronics, Inc., author: <mikko.levonmaa@lge.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 LG Electronics, Inc., author: <mikko.levonmaa@lge.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "testseat.h" #include <QMouseEvent> @@ -49,7 +24,8 @@ bool TestSeat::isOwner(QInputEvent *event) const QList<QMouseEvent *> TestSeat::createMouseEvents(int count) { for (int i = 0; i < count; i++) { - m_events.append(new QMouseEvent(QEvent::MouseMove, QPointF(10 + i, 10 + i), Qt::NoButton, Qt::NoButton, Qt::NoModifier)); + m_events.append(new QMouseEvent(QEvent::MouseMove, QPointF(10 + i, 10 + i), + QPointF(10 + i, 10 + i), Qt::NoButton, Qt::NoButton, Qt::NoModifier)); } return m_events; } diff --git a/tests/auto/compositor/compositor/testseat.h b/tests/auto/compositor/compositor/testseat.h index f4449f144..a71abc122 100644 --- a/tests/auto/compositor/compositor/testseat.h +++ b/tests/auto/compositor/compositor/testseat.h @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 LG Electronics, Inc., author: <mikko.levonmaa@lge.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 LG Electronics, Inc., author: <mikko.levonmaa@lge.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QWaylandSeat> #include <QList> diff --git a/tests/auto/compositor/compositor/tst_compositor.cpp b/tests/auto/compositor/compositor/tst_compositor.cpp index e87fab2a8..c3c0c35fb 100644 --- a/tests/auto/compositor/compositor/tst_compositor.cpp +++ b/tests/auto/compositor/compositor/tst_compositor.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "mockclient.h" #include "mockseat.h" @@ -40,7 +15,6 @@ #include <QtGui/QScreen> #include <QtWaylandCompositor/QWaylandXdgShell> -#include <QtWaylandCompositor/private/qwaylandxdgshellv6_p.h> #include <QtWaylandCompositor/private/qwaylandkeyboard_p.h> #include <QtWaylandCompositor/QWaylandIviApplication> #include <QtWaylandCompositor/QWaylandIviSurface> @@ -101,9 +75,6 @@ private slots: void sendsIviConfigure(); void destroysIviSurfaces(); - void convertsXdgEdgesToQtEdges(); - void xdgShellV6Positioner(); - void viewporterGlobal(); void viewportDestination(); void viewportSource(); @@ -341,14 +312,14 @@ void tst_WaylandCompositor::keyboardGrab() //QSignalSpy grabModifierSpy(grab, SIGNAL(modifiersCalled())); seat->setKeyboardFocus(waylandSurface); - QTRY_COMPARE(grabFocusSpy.count(), 1); + QTRY_COMPARE(grabFocusSpy.size(), 1); QKeyEvent ke(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier, 30, 0, 0); QKeyEvent ke1(QEvent::KeyRelease, Qt::Key_A, Qt::NoModifier, 30, 0, 0); seat->sendFullKeyEvent(&ke); seat->sendFullKeyEvent(&ke1); - QTRY_COMPARE(grabKeyPressSpy.count(), 1); - QTRY_COMPARE(grabKeyReleaseSpy.count(), 1); + QTRY_COMPARE(grabKeyPressSpy.size(), 1); + QTRY_COMPARE(grabKeyReleaseSpy.size(), 1); QKeyEvent ke2(QEvent::KeyPress, Qt::Key_Shift, Qt::NoModifier, 50, 0, 0); QKeyEvent ke3(QEvent::KeyRelease, Qt::Key_Shift, Qt::NoModifier, 50, 0, 0); @@ -356,14 +327,14 @@ void tst_WaylandCompositor::keyboardGrab() seat->sendFullKeyEvent(&ke3); //QTRY_COMPARE(grabModifierSpy.count(), 2); // Modifiers are also keys - QTRY_COMPARE(grabKeyPressSpy.count(), 2); - QTRY_COMPARE(grabKeyReleaseSpy.count(), 2); + QTRY_COMPARE(grabKeyPressSpy.size(), 2); + QTRY_COMPARE(grabKeyReleaseSpy.size(), 2); // Stop grabbing seat->setKeyboardFocus(nullptr); seat->sendFullKeyEvent(&ke); seat->sendFullKeyEvent(&ke1); - QTRY_COMPARE(grabKeyPressSpy.count(), 2); + QTRY_COMPARE(grabKeyPressSpy.size(), 2); } void tst_WaylandCompositor::geometry() @@ -495,7 +466,7 @@ void tst_WaylandCompositor::mapSurface() wl_surface_damage(surface, 0, 0, size.width(), size.height()); wl_surface_commit(surface); - QTRY_COMPARE(hasContentSpy.count(), 1); + QTRY_COMPARE(hasContentSpy.size(), 1); QCOMPARE(waylandSurface->hasContent(), true); QCOMPARE(waylandSurface->bufferSize(), size); QCOMPARE(waylandSurface->destinationSize(), size); @@ -534,32 +505,30 @@ void tst_WaylandCompositor::mapSurfaceHiDpi() QCOMPARE(waylandSurface->hasContent(), true); }; - QObject::connect(waylandSurface, &QWaylandSurface::damaged, [=] (const QRegion &damage) { - // Currently, QWaylandSurface::size returns the size in pixels. - // Should be fixed or removed for Qt 6. + QObject::connect(waylandSurface, &QWaylandSurface::damaged, this, [=] (const QRegion &damage) { QCOMPARE(damage, QRect(QPoint(), surfaceSize)); verifyComittedState(); }); QSignalSpy damagedSpy(waylandSurface, SIGNAL(damaged(const QRegion &))); - QObject::connect(waylandSurface, &QWaylandSurface::hasContentChanged, verifyComittedState); + QObject::connect(waylandSurface, &QWaylandSurface::hasContentChanged, + this, verifyComittedState); QSignalSpy hasContentSpy(waylandSurface, SIGNAL(hasContentChanged())); -#if QT_DEPRECATED_SINCE(5, 13) - QObject::connect(waylandSurface, &QWaylandSurface::sizeChanged, verifyComittedState); - QSignalSpy sizeSpy(waylandSurface, SIGNAL(sizeChanged())); -#endif - - QObject::connect(waylandSurface, &QWaylandSurface::bufferSizeChanged, verifyComittedState); + QObject::connect(waylandSurface, &QWaylandSurface::bufferSizeChanged, + this, verifyComittedState); QSignalSpy bufferSizeSpy(waylandSurface, SIGNAL(bufferSizeChanged())); - QObject::connect(waylandSurface, &QWaylandSurface::destinationSizeChanged, verifyComittedState); + QObject::connect(waylandSurface, &QWaylandSurface::destinationSizeChanged, + this, verifyComittedState); QSignalSpy destinationSizeSpy(waylandSurface, SIGNAL(destinationSizeChanged())); - QObject::connect(waylandSurface, &QWaylandSurface::bufferScaleChanged, verifyComittedState); + QObject::connect(waylandSurface, &QWaylandSurface::bufferScaleChanged, + this, verifyComittedState); QSignalSpy bufferScaleSpy(waylandSurface, SIGNAL(bufferScaleChanged())); - QObject::connect(waylandSurface, &QWaylandSurface::offsetForNextFrame, [=](const QPoint &offset) { + QObject::connect(waylandSurface, &QWaylandSurface::offsetForNextFrame, + this, [=](const QPoint &offset) { QCOMPARE(offset, attachOffset); verifyComittedState(); }); @@ -570,18 +539,21 @@ void tst_WaylandCompositor::mapSurfaceHiDpi() QCOMPARE(waylandSurface->destinationSize(), QSize()); QCOMPARE(waylandSurface->hasContent(), false); QCOMPARE(waylandSurface->bufferScale(), 1); - QCOMPARE(offsetSpy.count(), 0); + QCOMPARE(offsetSpy.size(), 0); wl_surface_commit(surface); - QTRY_COMPARE(hasContentSpy.count(), 1); -#if QT_DEPRECATED_SINCE(5, 13) - QTRY_COMPARE(sizeSpy.count(), 1); -#endif - QTRY_COMPARE(bufferSizeSpy.count(), 1); - QTRY_COMPARE(destinationSizeSpy.count(), 1); - QTRY_COMPARE(bufferScaleSpy.count(), 1); - QTRY_COMPARE(offsetSpy.count(), 1); + QTRY_COMPARE(hasContentSpy.size(), 1); + QTRY_COMPARE(bufferSizeSpy.size(), 1); + QTRY_COMPARE(destinationSizeSpy.size(), 1); + QTRY_COMPARE(bufferScaleSpy.size(), 1); + QTRY_COMPARE(offsetSpy.size(), 1); + QTRY_COMPARE(damagedSpy.size(), 1); + + // Now verify that wl_surface_damage_buffer gets mapped properly + wl_surface_damage_buffer(surface, 0, 0, bufferSize.width(), bufferSize.height()); + wl_surface_commit(surface); + QTRY_COMPARE(damagedSpy.size(), 2); wl_surface_destroy(surface); } @@ -650,7 +622,7 @@ void tst_WaylandCompositor::frameCallback() wl_surface_commit(surface); QTRY_COMPARE(waylandSurface->hasContent(), true); - QTRY_COMPARE(damagedSpy.count(), i + 1); + QTRY_COMPARE(damagedSpy.size(), i + 1); QCOMPARE(static_cast<BufferView*>(waylandSurface->views().first())->image(), buffer.image); compositor.defaultOutput()->frameStarted(); @@ -706,18 +678,18 @@ void tst_WaylandCompositor::outputs() window.resize(800, 600); auto output = new QWaylandOutput(&compositor, &window); - QTRY_COMPARE(outputAddedSpy.count(), 1); + QTRY_COMPARE(outputAddedSpy.size(), 1); compositor.setDefaultOutput(output); - QTRY_COMPARE(defaultOutputSpy.count(), 2); + QTRY_COMPARE(defaultOutputSpy.size(), 2); MockClient client; QTRY_COMPARE(client.m_outputs.size(), 2); delete output; - QTRY_COMPARE(outputRemovedSpy.count(), 1); + QTRY_COMPARE(outputRemovedSpy.size(), 1); QEXPECT_FAIL("", "FIXME: defaultOutputChanged() is not emitted when the default output is removed", Continue); - QTRY_COMPARE(defaultOutputSpy.count(), 3); + QTRY_COMPARE(defaultOutputSpy.size(), 3); compositor.flushClients(); QTRY_COMPARE(client.m_outputs.size(), 1); } @@ -993,13 +965,12 @@ void tst_WaylandCompositor::createsXdgSurfaces() QSignalSpy xdgSurfaceCreatedSpy(&compositor.xdgShell, &QWaylandXdgShell::xdgSurfaceCreated); QWaylandXdgSurface *xdgSurface = nullptr; - QObject::connect(&compositor.xdgShell, &QWaylandXdgShell::xdgSurfaceCreated, [&](QWaylandXdgSurface *s) { - xdgSurface = s; - }); + QObject::connect(&compositor.xdgShell, &QWaylandXdgShell::xdgSurfaceCreated, + this, [&](QWaylandXdgSurface *s) { xdgSurface = s; }); wl_surface *surface = client.createSurface(); xdg_surface *clientXdgSurface = client.createXdgSurface(surface); - QTRY_COMPARE(xdgSurfaceCreatedSpy.count(), 1); + QTRY_COMPARE(xdgSurfaceCreatedSpy.size(), 1); QTRY_VERIFY(xdgSurface); QTRY_VERIFY(xdgSurface->surface()); @@ -1013,9 +984,8 @@ void tst_WaylandCompositor::reportsXdgSurfaceWindowGeometry() compositor.create(); QWaylandXdgSurface *xdgSurface = nullptr; - QObject::connect(&compositor.xdgShell, &QWaylandXdgShell::xdgSurfaceCreated, [&](QWaylandXdgSurface *s) { - xdgSurface = s; - }); + QObject::connect(&compositor.xdgShell, &QWaylandXdgShell::xdgSurfaceCreated, + this, [&](QWaylandXdgSurface *s) { xdgSurface = s; }); MockClient client; wl_surface *surface = client.createSurface(); @@ -1050,9 +1020,8 @@ void tst_WaylandCompositor::setsXdgAppId() compositor.create(); QWaylandXdgToplevel *toplevel = nullptr; - QObject::connect(&compositor.xdgShell, &QWaylandXdgShell::toplevelCreated, [&](QWaylandXdgToplevel *t) { - toplevel = t; - }); + QObject::connect(&compositor.xdgShell, &QWaylandXdgShell::toplevelCreated, + this, [&](QWaylandXdgToplevel *t) { toplevel = t; }); MockClient client; wl_surface *surface = client.createSurface(); @@ -1096,9 +1065,8 @@ void tst_WaylandCompositor::sendsXdgConfigure() compositor.create(); QWaylandXdgToplevel *toplevel = nullptr; - QObject::connect(&compositor.xdgShell, &QWaylandXdgShell::toplevelCreated, [&](QWaylandXdgToplevel *t) { - toplevel = t; - }); + QObject::connect(&compositor.xdgShell, &QWaylandXdgShell::toplevelCreated, + this, [&](QWaylandXdgToplevel *t) { toplevel = t; }); MockClient client; wl_surface *surface = client.createSurface(); @@ -1115,7 +1083,7 @@ void tst_WaylandCompositor::sendsXdgConfigure() QTRY_VERIFY(!toplevel->fullscreen()); QTRY_VERIFY(!toplevel->resizing()); - toplevel->sendConfigure(QSize(10, 20), QVector<QWaylandXdgToplevel::State>{QWaylandXdgToplevel::State::ActivatedState}); + toplevel->sendConfigure(QSize(10, 20), QList<QWaylandXdgToplevel::State>{QWaylandXdgToplevel::State::ActivatedState}); compositor.flushClients(); QTRY_COMPARE(mockToplevel.configureStates, QList<uint>{QWaylandXdgToplevel::State::ActivatedState}); QTRY_COMPARE(mockToplevel.configureSize, QSize(10, 20)); @@ -1162,7 +1130,7 @@ void tst_WaylandCompositor::sendsXdgConfigure() QTRY_VERIFY(mockToplevel.configureStates.contains(QWaylandXdgToplevel::State::ActivatedState)); QTRY_VERIFY(!mockToplevel.configureStates.contains(QWaylandXdgToplevel::State::FullscreenState)); - toplevel->sendConfigure(QSize(0, 0), QVector<QWaylandXdgToplevel::State>{}); + toplevel->sendConfigure(QSize(0, 0), QList<QWaylandXdgToplevel::State>{}); compositor.flushClients(); QTRY_VERIFY(!mockToplevel.configureStates.contains(QWaylandXdgToplevel::State::ActivatedState)); @@ -1210,13 +1178,12 @@ void tst_WaylandCompositor::createsIviSurfaces() QSignalSpy iviSurfaceCreatedSpy(&compositor.iviApplication, &QWaylandIviApplication::iviSurfaceRequested); QWaylandIviSurface *iviSurface = nullptr; - QObject::connect(&compositor.iviApplication, &QWaylandIviApplication::iviSurfaceCreated, [&](QWaylandIviSurface *s) { - iviSurface = s; - }); + QObject::connect(&compositor.iviApplication, &QWaylandIviApplication::iviSurfaceCreated, + this, [&](QWaylandIviSurface *s) { iviSurface = s; }); wl_surface *surface = client.createSurface(); client.createIviSurface(surface, 123); - QTRY_COMPARE(iviSurfaceCreatedSpy.count(), 1); + QTRY_COMPARE(iviSurfaceCreatedSpy.size(), 1); QTRY_VERIFY(iviSurface); QTRY_VERIFY(iviSurface->surface()); QTRY_COMPARE(iviSurface->iviId(), 123u); @@ -1232,9 +1199,10 @@ void tst_WaylandCompositor::emitsErrorOnSameIviId() QTRY_VERIFY(&firstClient.iviApplication); QWaylandIviSurface *firstIviSurface = nullptr; - QObject::connect(&compositor.iviApplication, &QWaylandIviApplication::iviSurfaceCreated, [&](QWaylandIviSurface *s) { - firstIviSurface = s; - }); + auto connection = QObject::connect(&compositor.iviApplication, + &QWaylandIviApplication::iviSurfaceCreated, + this, + [&](QWaylandIviSurface *s) { firstIviSurface = s; }); firstClient.createIviSurface(firstClient.createSurface(), 123); QTRY_VERIFY(firstIviSurface); @@ -1243,7 +1211,7 @@ void tst_WaylandCompositor::emitsErrorOnSameIviId() { MockClient secondClient; QTRY_VERIFY(&secondClient.iviApplication); - QTRY_COMPARE(compositor.clients().count(), 2); + QTRY_COMPARE(compositor.clients().size(), 2); secondClient.createIviSurface(secondClient.createSurface(), 123); compositor.flushClients(); @@ -1251,8 +1219,9 @@ void tst_WaylandCompositor::emitsErrorOnSameIviId() QTRY_COMPARE(secondClient.error, EPROTO); QTRY_COMPARE(secondClient.protocolError.interface, &ivi_application_interface); QTRY_COMPARE(static_cast<ivi_application_error>(secondClient.protocolError.code), IVI_APPLICATION_ERROR_IVI_ID); - QTRY_COMPARE(compositor.clients().count(), 1); + QTRY_COMPARE(compositor.clients().size(), 1); } + QObject::disconnect(connection); } // The other clients have passed out of scope and have been destroyed, @@ -1261,9 +1230,8 @@ void tst_WaylandCompositor::emitsErrorOnSameIviId() QTRY_VERIFY(&thirdClient.iviApplication); QWaylandIviSurface *thirdIviSurface = nullptr; - QObject::connect(&compositor.iviApplication, &QWaylandIviApplication::iviSurfaceCreated, [&](QWaylandIviSurface *s) { - thirdIviSurface = s; - }); + QObject::connect(&compositor.iviApplication, &QWaylandIviApplication::iviSurfaceCreated, + this, [&](QWaylandIviSurface *s) { thirdIviSurface = s; }); thirdClient.createIviSurface(thirdClient.createSurface(), 123); compositor.flushClients(); @@ -1292,9 +1260,8 @@ void tst_WaylandCompositor::sendsIviConfigure() QTRY_VERIFY(client.iviApplication); QWaylandIviSurface *iviSurface = nullptr; - QObject::connect(&compositor.iviApplication, &QWaylandIviApplication::iviSurfaceCreated, [&](QWaylandIviSurface *s) { - iviSurface = s; - }); + QObject::connect(&compositor.iviApplication, &QWaylandIviApplication::iviSurfaceCreated, + this, [&](QWaylandIviSurface *s) { iviSurface = s; }); wl_surface *surface = client.createSurface(); ivi_surface *clientIviSurface = client.createIviSurface(surface, 123); @@ -1316,60 +1283,15 @@ void tst_WaylandCompositor::destroysIviSurfaces() QTRY_VERIFY(client.iviApplication); QWaylandIviSurface *iviSurface = nullptr; - QObject::connect(&compositor.iviApplication, &QWaylandIviApplication::iviSurfaceCreated, [&](QWaylandIviSurface *s) { - iviSurface = s; - }); + QObject::connect(&compositor.iviApplication, &QWaylandIviApplication::iviSurfaceCreated, + this, [&](QWaylandIviSurface *s) { iviSurface = s; }); QtWayland::ivi_surface mockIviSurface(client.createIviSurface(client.createSurface(), 123)); QTRY_VERIFY(iviSurface); QSignalSpy destroySpy(iviSurface, SIGNAL(destroyed())); mockIviSurface.destroy(); - QTRY_VERIFY(destroySpy.count() == 1); -} - -void tst_WaylandCompositor::convertsXdgEdgesToQtEdges() -{ - const uint wlLeft = ZXDG_POSITIONER_V6_ANCHOR_LEFT; - QCOMPARE(QWaylandXdgShellV6Private::convertToEdges(wlLeft), Qt::LeftEdge); - - const uint wlRight = ZXDG_POSITIONER_V6_ANCHOR_RIGHT; - QCOMPARE(QWaylandXdgShellV6Private::convertToEdges(wlRight), Qt::RightEdge); - - const uint wlTop = ZXDG_POSITIONER_V6_ANCHOR_TOP; - QCOMPARE(QWaylandXdgShellV6Private::convertToEdges(wlTop), Qt::TopEdge); - - const uint wlBottom = ZXDG_POSITIONER_V6_ANCHOR_BOTTOM; - QCOMPARE(QWaylandXdgShellV6Private::convertToEdges(wlBottom), Qt::BottomEdge); - - QCOMPARE(QWaylandXdgShellV6Private::convertToEdges(wlBottom | wlLeft), Qt::Edges(Qt::BottomEdge | Qt::LeftEdge)); - QCOMPARE(QWaylandXdgShellV6Private::convertToEdges(wlTop | wlRight), Qt::Edges(Qt::TopEdge | Qt::RightEdge)); -} - -void tst_WaylandCompositor::xdgShellV6Positioner() -{ - QWaylandXdgPositionerV6Data p; - QVERIFY(!p.isComplete()); - - p.size = QSize(100, 50); - p.anchorRect = QRect(QPoint(1, 2), QSize(800, 600)); - QVERIFY(p.isComplete()); - - p.anchorEdges = Qt::TopEdge | Qt::LeftEdge; - p.gravityEdges = Qt::BottomEdge | Qt::RightEdge; - QCOMPARE(p.unconstrainedPosition(), QPoint(1, 2)); - - p.anchorEdges = Qt::RightEdge; - QCOMPARE(p.unconstrainedPosition(), QPoint(1 + 800, 2 + 600 / 2)); - - p.gravityEdges = Qt::BottomEdge; - QCOMPARE(p.unconstrainedPosition(), QPoint(1 + 800 - 100 / 2, 2 + 600 / 2)); - - p.gravityEdges = Qt::TopEdge; - QCOMPARE(p.unconstrainedPosition(), QPoint(1 + 800 - 100 / 2, 2 + 600 / 2 - 50)); - - p.offset = QPoint(4, 8); - QCOMPARE(p.unconstrainedPosition(), QPoint(1 + 800 - 100 / 2 + 4, 2 + 600 / 2 - 50 + 8)); + QTRY_VERIFY(destroySpy.size() == 1); } class ViewporterTestCompositor: public TestCompositor { @@ -1805,7 +1727,7 @@ void tst_WaylandCompositor::idleInhibit() QVERIFY(idleInhibitor); QTRY_COMPARE(waylandSurfacePrivate->idleInhibitors.size(), 1); QCOMPARE(waylandSurface->inhibitsIdle(), true); - QTRY_COMPARE(changedSpy.count(), 1); + QTRY_COMPARE(changedSpy.size(), 1); } class XdgOutputCompositor : public TestCompositor diff --git a/tests/manual/CMakeLists.txt b/tests/manual/CMakeLists.txt new file mode 100644 index 000000000..87ae459fd --- /dev/null +++ b/tests/manual/CMakeLists.txt @@ -0,0 +1,19 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +if(TARGET Qt::WaylandClient) + add_subdirectory(qmlclient) + add_subdirectory(subsurface) + add_subdirectory(texture-sharing/cpp-client) + add_subdirectory(texture-sharing-2) +endif() + +if(TARGET Qt::WaylandCompositor) + #add_subdirectory(wip-cpp-compositor) + add_subdirectory(scaling-compositor) + add_subdirectory(hwlayer-compositor) +endif() + +if(QT_FEATURE_opengl AND TARGET Qt::Quick AND TARGET Qt::WaylandClient) + add_subdirectory(server-buffer) +endif() diff --git a/tests/manual/hwlayer-compositor/.gitignore b/tests/manual/hwlayer-compositor/.gitignore new file mode 100644 index 000000000..83a421caf --- /dev/null +++ b/tests/manual/hwlayer-compositor/.gitignore @@ -0,0 +1 @@ +hwlayer-compositor diff --git a/tests/manual/hwlayer-compositor/CMakeLists.txt b/tests/manual/hwlayer-compositor/CMakeLists.txt new file mode 100644 index 000000000..729bae99b --- /dev/null +++ b/tests/manual/hwlayer-compositor/CMakeLists.txt @@ -0,0 +1,48 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(hwlayer-compositor LANGUAGES CXX) + +set(CMAKE_AUTOMOC ON) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/wayland/hwlayer-compositor") + +find_package(Qt6 REQUIRED COMPONENTS Core Gui Qml) + +qt_add_executable(hwlayer-compositor + main.cpp +) + +set_target_properties(hwlayer-compositor PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(hwlayer-compositor PUBLIC + Qt::Core + Qt::Gui + Qt::Qml +) + +# Resources: +set(hwlayer-compositor_resource_files + "main.qml" +) + +qt6_add_resources(hwlayer-compositor "hwlayer-compositor" + PREFIX + "/" + FILES + ${hwlayer-compositor_resource_files} +) + +install(TARGETS hwlayer-compositor + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/tests/manual/hwlayer-compositor/hwlayer-compositor.pro b/tests/manual/hwlayer-compositor/hwlayer-compositor.pro new file mode 100644 index 000000000..a6eed9079 --- /dev/null +++ b/tests/manual/hwlayer-compositor/hwlayer-compositor.pro @@ -0,0 +1,14 @@ +QT += gui qml + +SOURCES += \ + main.cpp + +OTHER_FILES = \ + main.qml + +RESOURCES += hwlayer-compositor.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/wayland/hwlayer-compositor +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS hwlayer-compositor.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/wayland/hwlayer-compositor +INSTALLS += target sources diff --git a/tests/manual/hwlayer-compositor/hwlayer-compositor.qrc b/tests/manual/hwlayer-compositor/hwlayer-compositor.qrc new file mode 100644 index 000000000..5f6483ac3 --- /dev/null +++ b/tests/manual/hwlayer-compositor/hwlayer-compositor.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/"> + <file>main.qml</file> + </qresource> +</RCC> diff --git a/tests/manual/hwlayer-compositor/main.cpp b/tests/manual/hwlayer-compositor/main.cpp new file mode 100644 index 000000000..85cab3cec --- /dev/null +++ b/tests/manual/hwlayer-compositor/main.cpp @@ -0,0 +1,17 @@ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include <QtCore/QUrl> +#include <QtCore/QDebug> + +#include <QtGui/QGuiApplication> +#include <QQmlContext> + +#include <QtQml/QQmlApplicationEngine> + +int main(int argc, char *argv[]) +{ + QGuiApplication app(argc, argv); + QQmlApplicationEngine appEngine(QUrl("qrc:///main.qml")); + return app.exec(); +} diff --git a/tests/manual/hwlayer-compositor/main.qml b/tests/manual/hwlayer-compositor/main.qml new file mode 100644 index 000000000..32a197ac1 --- /dev/null +++ b/tests/manual/hwlayer-compositor/main.qml @@ -0,0 +1,117 @@ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick +import QtQuick.Window +import QtQuick.Controls +import QtWayland.Compositor +import QtWayland.Compositor.XdgShell +import QtWayland.Compositor.WlShell +import QtWayland.Compositor.IviApplication + +WaylandCompositor { + WaylandOutput { + sizeFollowsWindow: true + window: Window { + color: "tomato" + id: win + width: 1024 + height: 768 + visible: true + Rectangle { + color: "lightgreen" + anchors.centerIn: parent + width: parent.width / 3 + height: parent.width / 3 + NumberAnimation on rotation { + id: rotationAnimation + running: false + from: 0 + to: 90 + loops: Animation.Infinite + duration: 1000 + } + } + Repeater { + model: shellSurfaces + ShellSurfaceItem { + id: waylandItem + onSurfaceDestroyed: shellSurfaces.remove(index) + shellSurface: shSurface + WaylandHardwareLayer { + stackingLevel: level + Component.onCompleted: console.log("Added hardware layer with stacking level", stackingLevel); + } + Component.onCompleted: console.log("Added wayland quick item"); + Behavior on x { + PropertyAnimation { + easing.type: Easing.OutBounce + duration: 1000 + } + } + Timer { + interval: 2000; running: animatePosition; repeat: true + onTriggered: waylandItem.x = waylandItem.x === 0 ? win.width - waylandItem.width : 0 + } + Behavior on opacity { + PropertyAnimation { + duration: 1000 + } + } + Timer { + interval: 2000; running: animateOpacity; repeat: true + onTriggered: waylandItem.opacity = waylandItem.opacity === 1 ? 0 : 1 + } + } + } + Column { + anchors.bottom: parent.bottom + Repeater { + model: shellSurfaces + Row { + Label { + anchors.verticalCenter: parent.verticalCenter + leftPadding: 15 + rightPadding: 15 + text: "Surface " + index + } + CheckBox { + text: "Animate position" + checked: animatePosition + onClicked: animatePosition = !animatePosition + } + CheckBox { + text: "Animate Opacity" + checked: animateOpacity + onClicked: animateOpacity = !animateOpacity + } + Label { + text: "Stacking level" + } + SpinBox { + value: level + onValueModified: level = value; + } + Button { + text: "Kill" + onClicked: shSurface.surface.client.kill() + } + } + } + CheckBox { + text: "Rotation" + checked: rotationAnimation.running + onClicked: rotationAnimation.running = !rotationAnimation.running + padding: 30 + } + } + } + } + ListModel { id: shellSurfaces } + function addShellSurface(shellSurface) { + shellSurfaces.append({shSurface: shellSurface, animatePosition: false, animateOpacity: false, level: 0}); + } + XdgShell { onToplevelCreated: (toplevel, xdgSurface) => addShellSurface(xdgSurface) } + IviApplication { onIviSurfaceCreated: (iviSurface) => addShellSurface(iviSurface) } + WlShell { onWlShellSurfaceCreated: (shellSurface) => addShellSurface(shellSurface) } +} diff --git a/tests/manual/keymap/keymapcompositor.qml b/tests/manual/keymap/keymapcompositor.qml index 77111c815..7d8bcda7c 100644 --- a/tests/manual/keymap/keymapcompositor.qml +++ b/tests/manual/keymap/keymapcompositor.qml @@ -1,55 +1,9 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick 2.0 import QtWayland.Compositor 1.0 +import QtWayland.Compositor.WlShell import QtQuick.Window 2.2 WaylandCompositor { @@ -91,7 +45,4 @@ WaylandCompositor { WlShell { onWlShellSurfaceCreated: chromeComponent.createObject(surfaceArea, { "shellSurface": shellSurface } ); } - XdgShellV5 { - onXdgSurfaceCreated: chromeComponent.createObject(surfaceArea, { "shellSurface": xdgSurface } ); - } } diff --git a/tests/manual/qmlclient/CMakeLists.txt b/tests/manual/qmlclient/CMakeLists.txt new file mode 100644 index 000000000..7dedc67bf --- /dev/null +++ b/tests/manual/qmlclient/CMakeLists.txt @@ -0,0 +1,36 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +# Generated from qmlclient.pro. + +##################################################################### +## qmlclient Binary: +##################################################################### + +qt_internal_add_manual_test(qmlclient + GUI + SOURCES + main.cpp + LIBRARIES + Qt::CorePrivate + Qt::Gui + Qt::GuiPrivate + Qt::Quick + Qt::WaylandClient +) + +# Resources: +set(qml_resource_files + "main.qml" +) + +qt_internal_add_resource(qmlclient "qml" + PREFIX + "/" + FILES + ${qml_resource_files} +) + + +#### Keys ignored in scope 1:.:.:qmlclient.pro:<TRUE>: +# TEMPLATE = "app" diff --git a/tests/manual/qmlclient/main.cpp b/tests/manual/qmlclient/main.cpp index 9e0774b13..673359b52 100644 --- a/tests/manual/qmlclient/main.cpp +++ b/tests/manual/qmlclient/main.cpp @@ -1,52 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QtGui/QGuiApplication> #include <QtQml/QQmlApplicationEngine> diff --git a/tests/manual/qmlclient/main.qml b/tests/manual/qmlclient/main.qml index 5ee63955b..b5061c182 100644 --- a/tests/manual/qmlclient/main.qml +++ b/tests/manual/qmlclient/main.qml @@ -1,52 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick 2.2 import QtQuick.Window 2.2 diff --git a/tests/manual/qt-shell/CMakeLists.txt b/tests/manual/qt-shell/CMakeLists.txt new file mode 100644 index 000000000..daf8fb25d --- /dev/null +++ b/tests/manual/qt-shell/CMakeLists.txt @@ -0,0 +1,46 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +cmake_minimum_required(VERSION 3.14) +project(qt-shell LANGUAGES CXX) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) + +find_package(Qt6 COMPONENTS Core) +find_package(Qt6 COMPONENTS Gui) +find_package(Qt6 COMPONENTS Qml) + +qt_add_executable(qt-shell + main.cpp +) +set_target_properties(qt-shell PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) +target_link_libraries(qt-shell PUBLIC + Qt::Core + Qt::Gui + Qt::Qml +) + + +# Resources: +set(qt-shell_resource_files + "images/background.jpg" + "qml/Chrome.qml" + "qml/HandleHandler.qml" + "qml/CompositorScreen.qml" + "qml/Keyboard.qml" + "qml/main.qml" +) + +qt6_add_resources(qt-shell "qt-shell" + PREFIX + "/" + FILES + ${qt-shell_resource_files} +) diff --git a/tests/manual/qt-shell/images/background.jpg b/tests/manual/qt-shell/images/background.jpg Binary files differnew file mode 100644 index 000000000..445567fbd --- /dev/null +++ b/tests/manual/qt-shell/images/background.jpg diff --git a/tests/manual/qt-shell/main.cpp b/tests/manual/qt-shell/main.cpp new file mode 100644 index 000000000..31bd58fae --- /dev/null +++ b/tests/manual/qt-shell/main.cpp @@ -0,0 +1,21 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include <QtCore/QUrl> +#include <QtCore/QDebug> + +#include <QtGui/QGuiApplication> + +#include <QtQml/QQmlApplicationEngine> + +int main(int argc, char *argv[]) +{ + // ShareOpenGLContexts is needed for using the threaded renderer + // on Nvidia EGLStreams + QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts, true); + QGuiApplication app(argc, argv); + + QQmlApplicationEngine appEngine(QUrl("qrc:///qml/main.qml")); + + return app.exec(); +} diff --git a/tests/manual/qt-shell/qml/Chrome.qml b/tests/manual/qt-shell/qml/Chrome.qml new file mode 100644 index 000000000..9eb2f1965 --- /dev/null +++ b/tests/manual/qt-shell/qml/Chrome.qml @@ -0,0 +1,458 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import QtWayland.Compositor + +Item { + id: chrome + + property bool positionSet: false + + x: shellSurface.windowGeometry.x - leftResizeHandle.width + y: shellSurface.windowGeometry.y - topResizeHandle.height - titleBar.height + width: shellSurface.windowGeometry.width + leftResizeHandle.width + rightResizeHandle.width + height: shellSurface.windowGeometry.height + topResizeHandle.height + titleBar.height + bottomResizeHandle.height + + property rect oldGeometry: Qt.rect(0, 0, 100, 100) + property bool isChild: parent.shellSurface !== undefined + property alias shellSurface: shellSurfaceItem.shellSurface + + property int windowState: Qt.WindowNoState + + signal destroyAnimationFinished + signal activated + signal deactivated + + property int windowFlags: shellSurface.windowFlags !== Qt.Window + ? shellSurface.windowFlags + : defaultFlags + onDecorationsShowingChanged:{ + shellSurfaceItem.updateFrameMargins() + } + + Component.onCompleted: { + shellSurface.active = true + } + + property int defaultFlags: (Qt.Window + | Qt.WindowMaximizeButtonHint + | Qt.WindowMinimizeButtonHint + | Qt.WindowCloseButtonHint) + + property bool frameless: (chrome.windowFlags & Qt.FramelessWindowHint) != 0 + || (chrome.windowState & Qt.WindowFullScreen) != 0 + || ((chrome.windowFlags & Qt.Popup) == Qt.Popup + && (chrome.windowFlags & Qt.Tool) != Qt.Tool) + + property bool decorationsShowing: (chrome.windowFlags & Qt.Window) != 0 && !frameless + + transform: [ + Scale { + id: scaleTransform + origin.x: chrome.width / 2 + origin.y: chrome.height / 2 + } + ] + + Rectangle { + id: leftResizeHandle + color: "gray" + width: visible ? 5 : 0 + anchors.left: parent.left + anchors.top: parent.top + anchors.bottom: parent.bottom + visible: decorationsShowing + + HandleHandler { + enabled: (chrome.windowState & (Qt.WindowMinimized|Qt.WindowMaximized)) == 0 + flags: westBound + } + } + + Rectangle { + id: rightResizeHandle + color: "gray" + width: visible ? 5 : 0 + anchors.right: parent.right + anchors.top: parent.top + anchors.bottom: parent.bottom + visible: decorationsShowing + + HandleHandler { + enabled: (chrome.windowState & (Qt.WindowMinimized|Qt.WindowMaximized)) == 0 + flags: eastBound + } + } + + Rectangle { + id: topResizeHandle + color: "gray" + height: visible ? 5 : 0 + anchors.left: parent.left + anchors.top: parent.top + anchors.right: parent.right + visible: decorationsShowing + + HandleHandler { + enabled: (chrome.windowState & (Qt.WindowMinimized|Qt.WindowMaximized)) == 0 + flags: northBound + } + } + + Rectangle { + id: bottomResizeHandle + color: "gray" + height: visible ? 5 : 0 + anchors.left: parent.left + anchors.bottom: parent.bottom + anchors.right: parent.right + visible: decorationsShowing + + HandleHandler { + enabled: (chrome.windowState & (Qt.WindowMinimized|Qt.WindowMaximized)) == 0 + flags: southBound + } + } + + Rectangle { + id: topLeftResizeHandle + color: "gray" + height: 5 + width: 5 + anchors.left: parent.left + anchors.top: parent.top + visible: decorationsShowing + + HandleHandler { + enabled: (chrome.windowState & (Qt.WindowMinimized|Qt.WindowMaximized)) == 0 + flags: westBound | northBound + } + } + + Rectangle { + id: topRightResizeHandle + color: "gray" + height: 5 + width: 5 + anchors.right: parent.right + anchors.top: parent.top + visible: decorationsShowing + + HandleHandler { + enabled: (chrome.windowState & (Qt.WindowMinimized|Qt.WindowMaximized)) == 0 + flags: eastBound | northBound + } + } + + Rectangle { + id: bottomLeftResizeHandle + color: "gray" + height: 5 + width: 5 + anchors.left: parent.left + anchors.bottom: parent.bottom + visible: decorationsShowing + + HandleHandler { + enabled: (chrome.windowState & (Qt.WindowMinimized|Qt.WindowMaximized)) == 0 + flags: westBound | southBound + } + } + + Rectangle { + id: bottomRightResizeHandle + color: "gray" + height: 5 + width: 5 + anchors.right: parent.right + anchors.bottom: parent.bottom + visible: decorationsShowing + + HandleHandler { + enabled: (chrome.windowState & (Qt.WindowMinimized|Qt.WindowMaximized)) == 0 + flags: eastBound | southBound + } + } + + function constrainPoint(mousePos) { + var x0 = usableArea.x + var y0 = usableArea.y + var x1 = x0 + usableArea.width + var y1 = y0 + usableArea.height + return Qt.point(Math.min(Math.max(x0,mousePos.x), x1), + Math.min(Math.max(y0,mousePos.y), y1)) + } + + function maxContentRect() { + var x0 = usableArea.x + leftResizeHandle.width + var x1 = usableArea.x + usableArea.width - rightResizeHandle.width + var y0 = usableArea.y + topResizeHandle.height + titleBar.height + var y1 = usableArea.y + usableArea.height - bottomResizeHandle.height + return Qt.rect(x0, y0, x1 - x0, y1 - y0) + } + + function randomPos(windowSize, screenSize) { + var res = (windowSize >= screenSize) ? 0 : Math.floor(Math.random() * (screenSize - windowSize)) + return res + } + + function activate() + { + shellSurface.active = true + shellSurfaceItem.raise() + activated() + } + + function deactivate() + { + shellSurface.active = true + deactivated() + } + + function setWindowState(nextState) { + var currentState = chrome.windowState + if (currentState === nextState) + return + + console.log("setWindowState", nextState.toString(16)) + + if ((currentState & (Qt.WindowMinimized | Qt.WindowMaximized | Qt.WindowFullScreen)) == 0) + chrome.oldGeometry = chrome.shellSurface.windowGeometry + + chrome.windowState = nextState + + if ((nextState & Qt.WindowMinimized) != 0) { + console.log("MINIMIZE") + chrome.shellSurface.requestWindowGeometry(nextState, Qt.rect(0, 0, 1, 1)) + shellSurfaceItem.visible = false + } else if ((nextState & Qt.WindowFullScreen) != 0) { + console.log("FULLSCREENIZE") + chrome.shellSurface.requestWindowGeometry(nextState, Qt.rect(0, 0, output.window.width, output.window.height)) + shellSurfaceItem.visible = true + } else if ((nextState & Qt.WindowMaximized) != 0) { + console.log("MAXIMIZE") + chrome.shellSurface.requestWindowGeometry(nextState, maxContentRect()) + shellSurfaceItem.visible = true + } else { + console.log("NORMALIZE", chrome.oldGeometry) + chrome.shellSurface.requestWindowGeometry(nextState, chrome.oldGeometry) + shellSurfaceItem.visible = true + } + } + + Rectangle { + id: titleBar + anchors.top: topResizeHandle.bottom + anchors.left: leftResizeHandle.right + anchors.right: rightResizeHandle.left + height: visible ? xButton.height + 10 : 0 + color: shellSurface.active ? "cornflowerblue" : "lightgray" + visible: !frameless + + Text { + anchors.left: parent.left + anchors.right: rowLayout.left + anchors.verticalCenter: parent.verticalCenter + + font.pixelSize: xButton.height + text: shellSurface.windowTitle + fontSizeMode: Text.Fit + } + + RowLayout { + id: rowLayout + anchors.right: parent.right + anchors.rightMargin: 5 + + ToolButton { + text: "-" + Layout.margins: 5 + visible: (chrome.windowFlags & Qt.WindowMinimizeButtonHint) != 0 + onClicked: { + var newState + if ((shellSurface.windowState & Qt.WindowMinimized) != 0) + newState = chrome.windowState & ~Qt.WindowMinimized + else + newState = chrome.windowState | Qt.WindowMinimized + + if ((newState & Qt.WindowMaximized) != 0) + newState &= ~Qt.WindowMaximized + + setWindowState(newState) + } + } + + ToolButton { + text: "+" + Layout.margins: 5 + visible: (chrome.windowFlags & Qt.WindowMaximizeButtonHint) != 0 + onClicked: { + var newState + if ((shellSurface.windowState & Qt.WindowMaximized) != 0) + newState = shellSurface.windowState & ~Qt.WindowMaximized + else + newState = shellSurface.windowState | Qt.WindowMaximized + + if ((newState & Qt.WindowMinimized) != 0) + newState &= ~Qt.WindowMinimized + + setWindowState(newState) + } + } + + ToolButton { + id: xButton + text: "X" + Layout.margins: 5 + visible: (chrome.windowFlags & Qt.WindowCloseButtonHint) != 0 + onClicked: shellSurface.sendClose() + } + } + + DragHandler { + target: null + property real xOffset: -1.0 + property real yOffset: -1.0 + property bool started: false + enabled: (shellSurface.windowState & (Qt.WindowMinimized|Qt.WindowMaximized)) == 0 + + onGrabChanged: { + started = false + activate() + } + + onCentroidChanged: { + if (!active) + return + + if (!started) { + xOffset = shellSurface.windowPosition.x - centroid.scenePressPosition.x + yOffset = shellSurface.windowPosition.y - centroid.scenePressPosition.y + started = true + chrome.positionAutomatic = false + } + + var pos = chrome.constrainPoint(centroid.scenePosition) + shellSurface.windowPosition = Qt.point(pos.x + xOffset, pos.y + yOffset) + } + } + } + + ShellSurfaceItem { + id: shellSurfaceItem + anchors.top: titleBar.bottom + anchors.bottom: bottomResizeHandle.top + anchors.left: leftResizeHandle.right + anchors.right: rightResizeHandle.left + + moveItem: chrome + + staysOnBottom: shellSurface.windowFlags & Qt.WindowStaysOnBottomHint + staysOnTop: !staysOnBottom && shellSurface.windowFlags & Qt.WindowStaysOnTopHint + function updateFrameMargins() + { + shellSurface.frameMarginLeft = (decorationsShowing ? leftResizeHandle.width : 0) + shellSurface.frameMarginRight = (decorationsShowing ? rightResizeHandle.width : 0) + shellSurface.frameMarginTop = (decorationsShowing ? topResizeHandle.height : 0) + + (!frameless ? titleBar.height : 0) + shellSurface.frameMarginBottom = (decorationsShowing ? bottomResizeHandle.height : 0) + } + + Component.onCompleted: { + updateFrameMargins() + } + + onSurfaceDestroyed: { + bufferLocked = true; + destroyAnimation.start(); + } + + Connections { + target: shellSurface + function onWindowFlagsChanged() { + console.log("FLAGS", shellSurface.windowFlags.toString(16)) + shellSurfaceItem.updateFrameMargins() + } + + function onWindowStateChanged() { + setWindowState(shellSurface.windowState) + } + + function onActiveChanged() { + if (shellSurface.active) { + shellSurfaceItem.raise() + activated() + } else { + deactivated() + } + } + + function onStartResize() { + console.log("START SYSTEM RESIZE") + } + function onStartMove() { + console.log("START SYSTEM MOVE") + } + + function onRaiseRequested() { + console.log("RAISE") + shellSurfaceItem.raise() + } + function onLowerRequested() { + console.log("LOWER") + shellSurfaceItem.lower() + } + + function onWindowGeometryChanged() { + console.log("GEOM CHANGE", shellSurface.windowGeometry) + } + } + + Connections { + target: shellSurface.surface + function onHasContentChanged() { + if (!chrome.positionSet) { + var rect = shellSurface.windowGeometry + var w = rect.width + var h = rect.height + + var space = maxContentRect() + + var randomize = shellSurface.positionAutomatic + var xpos = randomize ? randomPos(w, space.width) + space.x : Math.max(rect.x, space.x) + var ypos = randomize ? randomPos(h, space.height) + space.y : Math.max(rect.y, space.y) + shellSurface.windowPosition = Qt.point(xpos, ypos) + } + chrome.positionSet = true + } + } + + SequentialAnimation { + id: destroyAnimation + + ParallelAnimation { + NumberAnimation { target: scaleTransform; property: "yScale"; to: 2/height; duration: 150 } + NumberAnimation { target: scaleTransform; property: "xScale"; to: 0.4; duration: 150 } + NumberAnimation { target: chrome; property: "opacity"; to: chrome.isChild ? 0 : 1; duration: 150 } + } + NumberAnimation { target: scaleTransform; property: "xScale"; to: 0; duration: 150 } + ScriptAction { script: chrome.destroyAnimationFinished() } + } + + SequentialAnimation { + id: receivedFocusAnimation + + ParallelAnimation { + NumberAnimation { target: scaleTransform; property: "yScale"; to: 1.02; duration: 100; easing.type: Easing.OutQuad } + NumberAnimation { target: scaleTransform; property: "xScale"; to: 1.02; duration: 100; easing.type: Easing.OutQuad } + } + ParallelAnimation { + NumberAnimation { target: scaleTransform; property: "yScale"; to: 1; duration: 100; easing.type: Easing.InOutQuad } + NumberAnimation { target: scaleTransform; property: "xScale"; to: 1; duration: 100; easing.type: Easing.InOutQuad } + } + } + } +} diff --git a/tests/manual/qt-shell/qml/CompositorScreen.qml b/tests/manual/qt-shell/qml/CompositorScreen.qml new file mode 100644 index 000000000..92b75b348 --- /dev/null +++ b/tests/manual/qt-shell/qml/CompositorScreen.qml @@ -0,0 +1,144 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick +import QtQuick.Window +import QtQuick.Controls +import QtWayland.Compositor + +WaylandOutput { + id: output + + property ListModel shellSurfaces: ListModel {} + property bool isNestedCompositor: Qt.platform.pluginName.startsWith("wayland") || Qt.platform.pluginName === "xcb" + property int currentActiveWindow: -1 + + function handleShellSurface(shellSurface) { + shellSurfaces.append({shellSurface: shellSurface}); + } + + // During development, it can be useful to start the compositor inside X11 or + // another Wayland compositor. In such cases, set sizeFollowsWindow to true to + // enable resizing of the compositor window to be forwarded to the Wayland clients + // as the output (screen) changing resolution. Consider setting it to false if you + // are running the compositor using eglfs, linuxfb or similar QPA backends. + sizeFollowsWindow: output.isNestedCompositor + + window: Window { + width: 1920 + height: 1080 + visible: true + + WaylandMouseTracker { + id: mouseTracker + + anchors.fill: parent + + // Set this to false to disable the outer mouse cursor when running nested + // compositors. Otherwise you would see two mouse cursors, one for each compositor. + windowSystemCursorEnabled: output.isNestedCompositor + + Image { + id: background + + anchors.fill: parent + fillMode: Image.Tile + source: "qrc:/images/background.jpg" + smooth: true + + Repeater { + id: chromeRepeater + model: output.shellSurfaces + // Chrome displays a shell surface on the screen (See Chrome.qml) + Chrome { + shellSurface: modelData + onDestroyAnimationFinished: + { + if (currentActiveWindow > index) { + --currentActiveWindow + } else if (currentActiveWindow === index) { + currentActiveWindow = index - 1 + if (currentActiveWindow >= 0) { + var nextActiveSurface = output.shellSurfaces.get(currentActiveWindow).shellSurface + if (nextActiveSurface !== undefined) // More than one surface can get destroyed at the same time + nextActiveSurface.active = true + } + } + output.shellSurfaces.remove(index) + } + + onDeactivated: { + if (index === currentActiveWindow) + currentActiveWindow = -1 + } + + onActivated: { + if (index !== currentActiveWindow && currentActiveWindow >= 0) { + // This may already have been destroyed + if (output.shellSurfaces.get(currentActiveWindow).shellSurface !== undefined) + output.shellSurfaces.get(currentActiveWindow).shellSurface.active = false + } + + currentActiveWindow = index + } + } + } + } + + Rectangle { + anchors.fill: taskbar + color: "lavenderblush" + } + + Row { + id: taskbar + height: 40 + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: parent.bottom + + Repeater { + anchors.fill: parent + model: output.shellSurfaces + + ToolButton { + anchors.verticalCenter: parent.verticalCenter + text: modelData.windowTitle + onClicked: { + modelData.requestWindowGeometry(modelData.windowState & ~Qt.WindowMinimized, + modelData.windowGeometry) + chromeRepeater.itemAt(index).activate() + } + } + } + } + + Item { + id: usableArea + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: taskbar.top + } + + // Virtual Keyboard + Loader { + anchors.fill: parent + source: "Keyboard.qml" + } + + // Draws the mouse cursor for a given Wayland seat + WaylandCursorItem { + inputEventsEnabled: false + x: mouseTracker.mouseX + y: mouseTracker.mouseY + seat: output.compositor.defaultSeat + } + } + + Shortcut { + sequence: "Ctrl+Alt+Backspace" + onActivated: Qt.quit() + } + } +} diff --git a/tests/manual/qt-shell/qml/HandleHandler.qml b/tests/manual/qt-shell/qml/HandleHandler.qml new file mode 100644 index 000000000..7b31ad4d5 --- /dev/null +++ b/tests/manual/qt-shell/qml/HandleHandler.qml @@ -0,0 +1,86 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick + +DragHandler { + target: null + + function selectCursor(f) + { + switch (f) { + case (southBound | eastBound): + case (northBound | westBound): + return Qt.SizeFDiagCursor + case (southBound | westBound): + case (northBound | eastBound): + return Qt.SizeBDiagCursor + case westBound: + case eastBound: + return Qt.SizeHorCursor + default: + return Qt.SizeVerCursor + } + } + + property int flags: WestBound + readonly property int westBound: 1 + readonly property int eastBound: 2 + readonly property int northBound: 4 + readonly property int southBound: 8 + + cursorShape: selectCursor(flags) + + property rect geom + property real startX: -1.0 + property real startY: -1.0 + property bool started: false + onGrabChanged: { + started = false + } + onCentroidChanged: { + if (!active) + return + if (!started) { + geom = shellSurface.windowGeometry + startX = centroid.scenePressPosition.x + startY = centroid.scenePressPosition.y + started = true + } + + var pos = chrome.constrainPoint(centroid.scenePosition) + var dx = pos.x - startX + var dy = pos.y - startY + + var minWidth = Math.max(0, shellSurface.minimumSize.width) + var minHeight = Math.max(0, shellSurface.minimumSize.height) + + var maxWidth = shellSurface.maximumSize.width > 0 ? shellSurface.maximumSize.width : Number.MAX_VALUE + var maxHeight = shellSurface.maximumSize.height > 0 ? shellSurface.maximumSize.height : Number.MAX_VALUE + + var newLeft = geom.left + if (flags & westBound) + newLeft = Math.max(geom.right - maxWidth, Math.min(geom.right - minWidth, newLeft + dx)); + + var newTop = geom.top + if (flags & northBound) + newTop = Math.max(geom.bottom - maxHeight, Math.min(geom.bottom - minHeight, newTop + dy)); + + var newRight = geom.right + if (flags & eastBound) + newRight = Math.max(geom.left, newRight + dx); + + var newBottom = geom.bottom + if (flags & southBound) + newBottom = Math.max(geom.top, newBottom + dy); + + console.log("RESIZE HANDLER", shellSurface.windowGeometry, geom, dy, newTop) + + + shellSurface.requestWindowGeometry(shellSurface.windowState, + Qt.rect(newLeft, + newTop, + newRight - newLeft, + newBottom - newTop)) + } +} diff --git a/tests/manual/qt-shell/qml/Keyboard.qml b/tests/manual/qt-shell/qml/Keyboard.qml new file mode 100644 index 000000000..a6e1bec30 --- /dev/null +++ b/tests/manual/qt-shell/qml/Keyboard.qml @@ -0,0 +1,12 @@ +// Copyright (C) 2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick +import QtQuick.VirtualKeyboard + +InputPanel { + visible: active + y: active ? parent.height - height : parent.height + anchors.left: parent.left + anchors.right: parent.right +} diff --git a/tests/manual/qt-shell/qml/main.qml b/tests/manual/qt-shell/qml/main.qml new file mode 100644 index 000000000..986e0a490 --- /dev/null +++ b/tests/manual/qt-shell/qml/main.qml @@ -0,0 +1,22 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick +import QtWayland.Compositor +import QtWayland.Compositor.QtShell + +WaylandCompositor { + id: waylandCompositor + + CompositorScreen { id: screen; compositor: waylandCompositor } + + // Shell surface extension. Needed to provide a window concept for Wayland clients. + // I.e. requests and events for maximization, minimization, resizing, closing etc. + + QtShell { + onQtShellSurfaceCreated: screen.handleShellSurface(qtShellSurface) + } + + // Extension for Input Method (QT_IM_MODULE) support at compositor-side + QtTextInputMethodManager {} +} diff --git a/tests/manual/qt-shell/qt-shell.pro b/tests/manual/qt-shell/qt-shell.pro new file mode 100644 index 000000000..c7e2cd912 --- /dev/null +++ b/tests/manual/qt-shell/qt-shell.pro @@ -0,0 +1,13 @@ +QT += gui qml + +SOURCES += \ + main.cpp + +OTHER_FILES = \ + qml/main.qml \ + qml/CompositorScreen.qml \ + qml/Chrome.qml \ + qml/Keyboard.qml \ + images/background.jpg \ + +RESOURCES += qt-shell.qrc diff --git a/tests/manual/qt-shell/qt-shell.qrc b/tests/manual/qt-shell/qt-shell.qrc new file mode 100644 index 000000000..3120382fd --- /dev/null +++ b/tests/manual/qt-shell/qt-shell.qrc @@ -0,0 +1,10 @@ +<RCC> + <qresource prefix="/"> + <file>images/background.jpg</file> + <file>qml/main.qml</file> + <file>qml/CompositorScreen.qml</file> + <file>qml/Chrome.qml</file> + <file>qml/Keyboard.qml</file> + <file>qml/HandleHandler.qml</file> + </qresource> +</RCC> diff --git a/tests/manual/scaling-compositor/CMakeLists.txt b/tests/manual/scaling-compositor/CMakeLists.txt new file mode 100644 index 000000000..2ee7d96bc --- /dev/null +++ b/tests/manual/scaling-compositor/CMakeLists.txt @@ -0,0 +1,33 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +# Generated from scaling-compositor.pro. + +##################################################################### +## scaling-compositor Binary: +##################################################################### + +qt_internal_add_manual_test(scaling-compositor + GUI + SOURCES + main.cpp + LIBRARIES + Qt::Gui + Qt::Qml +) + +# Resources: +set(qml_resource_files + "main.qml" +) + +qt_internal_add_resource(scaling-compositor "qml" + PREFIX + "/" + FILES + ${qml_resource_files} +) + + +#### Keys ignored in scope 1:.:.:scaling-compositor.pro:<TRUE>: +# TEMPLATE = "app" diff --git a/tests/manual/scaling-compositor/main.cpp b/tests/manual/scaling-compositor/main.cpp index b5c7dd688..e972b9ca6 100644 --- a/tests/manual/scaling-compositor/main.cpp +++ b/tests/manual/scaling-compositor/main.cpp @@ -1,52 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QtGui/QGuiApplication> #include <QtQml/QQmlApplicationEngine> diff --git a/tests/manual/scaling-compositor/main.qml b/tests/manual/scaling-compositor/main.qml index 056af4e5b..f173de3a0 100644 --- a/tests/manual/scaling-compositor/main.qml +++ b/tests/manual/scaling-compositor/main.qml @@ -1,57 +1,11 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only -import QtQuick 2.2 +import QtQuick 2.15 import QtQuick.Window 2.2 -import QtQuick.Controls 2.0 -import QtWayland.Compositor 1.0 +import QtWayland.Compositor 1.3 +import QtWayland.Compositor.WlShell +import QtWayland.Compositor.XdgShell WaylandCompositor { id: comp @@ -66,16 +20,7 @@ WaylandCompositor { height: 500 visible: true title: "Scaling compositor x" + output.scaleFactor - Button { - id: incrementButton - text: "+" - onClicked: ++output.scaleFactor - } - Button { - text: "-" - onClicked: output.scaleFactor = Math.max(1, output.scaleFactor - 1) - anchors.left: incrementButton.right - } + Repeater { model: shellSurfaces ShellSurfaceItem { @@ -83,6 +28,33 @@ WaylandCompositor { onSurfaceDestroyed: shellSurfaces.remove(index); } } + + Rectangle { + id: incrementButton + color: "#c0f0d0" + Text { + text: "+" + } + width: 100 + height: 30 + TapHandler { + onTapped: ++output.scaleFactor + } + } + + Rectangle { + id: decrementButton + color: "#f0d0c0" + Text { + text: "-" + } + width: 100 + height: 30 + TapHandler { + onTapped: output.scaleFactor = Math.max(1, output.scaleFactor - 1) + } + anchors.left: incrementButton.right + } } } @@ -91,4 +63,8 @@ WaylandCompositor { WlShell { onWlShellSurfaceCreated: shellSurfaces.append({shellSurface: shellSurface}); } + XdgShell { + onToplevelCreated: + shellSurfaces.append({shellSurface: xdgSurface}); + } } diff --git a/tests/manual/scaling-compositor/scaling-compositor.pro b/tests/manual/scaling-compositor/scaling-compositor.pro index 847e07ea7..200dc8c40 100644 --- a/tests/manual/scaling-compositor/scaling-compositor.pro +++ b/tests/manual/scaling-compositor/scaling-compositor.pro @@ -1,7 +1,6 @@ TEMPLATE = app -QT += gui qml quickcontrols2 - +QT += gui qml SOURCES += main.cpp RESOURCES += qml.qrc diff --git a/tests/manual/server-buffer/CMakeLists.txt b/tests/manual/server-buffer/CMakeLists.txt new file mode 100644 index 000000000..973063c71 --- /dev/null +++ b/tests/manual/server-buffer/CMakeLists.txt @@ -0,0 +1,5 @@ +cmake_minimum_required(VERSION 3.16) +project(server-buffer) + +add_subdirectory(cpp-client) +add_subdirectory(compositor) diff --git a/tests/manual/server-buffer/README b/tests/manual/server-buffer/README new file mode 100644 index 000000000..ae76ca755 --- /dev/null +++ b/tests/manual/server-buffer/README @@ -0,0 +1,32 @@ +This example shows how to use the low-level server buffer extension. This +version of Qt also provides a texture sharing extension that provides more +functionality and convenience for sharing graphical assets with Qt Quick +clients: see the texture-sharing example. + +Compile up both compositor and client. + +If you have the dmabuf-server buffer integration (and you are running Mesa) +then start the compositor with: + +$ QT_WAYLAND_SERVER_BUFFER_INTEGRATION=dmabuf-server ./compositor + + +Note: if you are running a compositor on an X11 desktop, you also need to +set QT_XCB_GL_INTEGRATION=xcb_egl as usual. + +The compositor broadcasts the name of the server buffer integration to +all clients through the hardware integration extension. Therefore, +all you need to do is to start the client with + +$ ./server-buffer-cpp-client -platform wayland + +The client will show all the buffers shared by the compositor. + +For testing on desktop, there is also a shared memory based server buffer +integration that works with any graphics hardware: + +$ QT_WAYLAND_SERVER_BUFFER_INTEGRATION=shm-emulation-server QT_XCB_GL_INTEGRATION=xcb_egl ./compositor + +Note: the shm-emulation-server integration does not actually share graphics +buffers, so it will not give any graphics memory savings. It is intended solely +for testing during development and should never be used in production. diff --git a/tests/manual/server-buffer/compositor/CMakeLists.txt b/tests/manual/server-buffer/compositor/CMakeLists.txt new file mode 100644 index 000000000..5f4fb0c51 --- /dev/null +++ b/tests/manual/server-buffer/compositor/CMakeLists.txt @@ -0,0 +1,57 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(compositor) + +set(CMAKE_AUTOMOC ON) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/wayland/server-buffer/compositor") + +find_package(Qt6 REQUIRED COMPONENTS Core Gui Qml WaylandCompositor) + +qt_add_executable(compositor + main.cpp + sharebufferextension.cpp sharebufferextension.h +) + +qt6_generate_wayland_protocol_server_sources(compositor + FILES + ${CMAKE_CURRENT_SOURCE_DIR}/../share-buffer.xml +) + +set_target_properties(compositor PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(compositor PUBLIC + Qt::Core + Qt::Gui + Qt::Qml + Qt::WaylandCompositorPrivate +) + +# Resources: +set(compositor_resource_files + "images/Siberischer_tiger_de_edit02.jpg" + "images/background.png" + "qml/main.qml" +) + +qt6_add_resources(compositor "compositor" + PREFIX + "/" + FILES + ${compositor_resource_files} +) + +install(TARGETS compositor + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/tests/manual/server-buffer/compositor/compositor.pro b/tests/manual/server-buffer/compositor/compositor.pro new file mode 100644 index 000000000..26334c63c --- /dev/null +++ b/tests/manual/server-buffer/compositor/compositor.pro @@ -0,0 +1,26 @@ +QT += core gui qml + +QT += waylandcompositor-private + +CONFIG += wayland-scanner +CONFIG += c++11 +SOURCES += \ + main.cpp \ + sharebufferextension.cpp + +OTHER_FILES = \ + qml/main.qml \ + images/background.jpg + +WAYLANDSERVERSOURCES += \ + ../share-buffer.xml + +RESOURCES += compositor.qrc + +TARGET = compositor + +HEADERS += \ + sharebufferextension.h + +target.path = $$[QT_INSTALL_EXAMPLES]/wayland/server-buffer/compositor +INSTALLS += target diff --git a/tests/manual/server-buffer/compositor/compositor.qrc b/tests/manual/server-buffer/compositor/compositor.qrc new file mode 100644 index 000000000..b50594b55 --- /dev/null +++ b/tests/manual/server-buffer/compositor/compositor.qrc @@ -0,0 +1,7 @@ +<RCC> + <qresource prefix="/"> + <file>images/background.png</file> + <file>images/Siberischer_tiger_de_edit02.jpg</file> + <file>qml/main.qml</file> + </qresource> +</RCC> diff --git a/tests/manual/server-buffer/compositor/images/Siberischer_tiger_de_edit02.jpg b/tests/manual/server-buffer/compositor/images/Siberischer_tiger_de_edit02.jpg Binary files differnew file mode 100644 index 000000000..eb1b73f84 --- /dev/null +++ b/tests/manual/server-buffer/compositor/images/Siberischer_tiger_de_edit02.jpg diff --git a/tests/manual/server-buffer/compositor/images/Siberischer_tiger_de_edit02.txt b/tests/manual/server-buffer/compositor/images/Siberischer_tiger_de_edit02.txt new file mode 100644 index 000000000..3a26c00d3 --- /dev/null +++ b/tests/manual/server-buffer/compositor/images/Siberischer_tiger_de_edit02.txt @@ -0,0 +1,5 @@ +Image from https://en.wikipedia.org/wiki/File:Siberischer_tiger_de_edit02.jpg + +Author: S. Taheri, edited by Fir0002 + +License: Creative Commons Attribution-Share Alike 2.5 Generic diff --git a/tests/manual/server-buffer/compositor/images/background.png b/tests/manual/server-buffer/compositor/images/background.png Binary files differnew file mode 100644 index 000000000..292160cd8 --- /dev/null +++ b/tests/manual/server-buffer/compositor/images/background.png diff --git a/tests/manual/server-buffer/compositor/main.cpp b/tests/manual/server-buffer/compositor/main.cpp new file mode 100644 index 000000000..36e607e34 --- /dev/null +++ b/tests/manual/server-buffer/compositor/main.cpp @@ -0,0 +1,29 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include <QtCore/QUrl> +#include <QtCore/QDebug> +#include <QtGui/QGuiApplication> +#include <QtQml/QQmlApplicationEngine> + +#include <QtQml/qqml.h> +#include <QtQml/QQmlEngine> + +#include "sharebufferextension.h" + +static void registerTypes() +{ + qmlRegisterType<ShareBufferExtensionQuickExtension>("io.qt.examples.sharebufferextension", 1, 0, "ShareBufferExtension"); +} + +int main(int argc, char *argv[]) +{ + // Make sure there is a valid OpenGL context in the main thread + qputenv("QSG_RENDER_LOOP", "basic"); + + QGuiApplication app(argc, argv); + registerTypes(); + QQmlApplicationEngine appEngine(QUrl("qrc:///qml/main.qml")); + + return app.exec(); +} diff --git a/tests/manual/server-buffer/compositor/qml/main.qml b/tests/manual/server-buffer/compositor/qml/main.qml new file mode 100644 index 000000000..4227584af --- /dev/null +++ b/tests/manual/server-buffer/compositor/qml/main.qml @@ -0,0 +1,43 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick +import QtWayland.Compositor +import QtWayland.Compositor.WlShell +import QtQuick.Window + +import io.qt.examples.sharebufferextension + +WaylandCompositor { + WaylandOutput { + sizeFollowsWindow: true + window: Window { + width: 1024 + height: 768 + visible: true + Image { + id: surfaceArea + anchors.fill: parent + fillMode: Image.Tile + source: "qrc:/images/background.png" + smooth: false + } + } + } + + Component { + id: chromeComponent + ShellSurfaceItem { + onSurfaceDestroyed: destroy() + } + } + + WlShell { + onWlShellSurfaceCreated: (shellSurface) => { + chromeComponent.createObject(surfaceArea, { "shellSurface": shellSurface } ); + } + } + + ShareBufferExtension { + } +} diff --git a/tests/manual/server-buffer/compositor/sharebufferextension.cpp b/tests/manual/server-buffer/compositor/sharebufferextension.cpp new file mode 100644 index 000000000..bc8b01af3 --- /dev/null +++ b/tests/manual/server-buffer/compositor/sharebufferextension.cpp @@ -0,0 +1,86 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "sharebufferextension.h" + +#include <QWaylandSurface> + +#include <QDebug> + +#include <QQuickWindow> + +#include <QPainter> +#include <QPen> + +ShareBufferExtension::ShareBufferExtension(QWaylandCompositor *compositor) + : QWaylandCompositorExtensionTemplate(compositor) +{ +} + +void ShareBufferExtension::initialize() +{ + QWaylandCompositorExtensionTemplate::initialize(); + QWaylandCompositor *compositor = static_cast<QWaylandCompositor *>(extensionContainer()); + init(compositor->display(), 1); +} + +QtWayland::ServerBuffer *ShareBufferExtension::addImage(const QImage &img) +{ + if (!m_server_buffer_integration) { + QWaylandCompositor *compositor = static_cast<QWaylandCompositor *>(extensionContainer()); + + m_server_buffer_integration = QWaylandCompositorPrivate::get(compositor)->serverBufferIntegration(); + if (!m_server_buffer_integration) { + qWarning("Could not find a server buffer integration"); + return nullptr; + } + } + + QImage image = img.convertToFormat(QImage::Format_RGBA8888); + + auto *buffer = m_server_buffer_integration->createServerBufferFromImage(image, QtWayland::ServerBuffer::RGBA32); + + m_server_buffers.append(buffer); + return buffer; +} + +void ShareBufferExtension::createServerBuffers() +{ + QImage image(100,100,QImage::Format_ARGB32_Premultiplied); + image.fill(QColor(0x55,0x0,0x55,0x01)); + { + QPainter p(&image); + QPen pen = p.pen(); + pen.setWidthF(3); + pen.setColor(Qt::red); + p.setPen(pen); + p.drawLine(0,0,100,100); + pen.setColor(Qt::green); + p.setPen(pen); + p.drawLine(100,0,0,100); + pen.setColor(Qt::blue); + p.setPen(pen); + p.drawLine(25,15,75,15); + } + + addImage(image); + + QImage image2(":/images/Siberischer_tiger_de_edit02.jpg"); + addImage(image2); + + m_server_buffers_created = true; +} + + +void ShareBufferExtension::share_buffer_bind_resource(Resource *resource) +{ + if (!m_server_buffers_created) + createServerBuffers(); + + for (auto *buffer : std::as_const(m_server_buffers)) { + qDebug() << "sending" << buffer << "to client"; + struct ::wl_client *client = wl_resource_get_client(resource->handle); + struct ::wl_resource *buffer_resource = buffer->resourceForClient(client); + send_cross_buffer(resource->handle, buffer_resource); + } +} diff --git a/tests/manual/server-buffer/compositor/sharebufferextension.h b/tests/manual/server-buffer/compositor/sharebufferextension.h new file mode 100644 index 000000000..58809e3d4 --- /dev/null +++ b/tests/manual/server-buffer/compositor/sharebufferextension.h @@ -0,0 +1,53 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#ifndef SHAREBUFFEREXTENSION_H +#define SHAREBUFFEREXTENSION_H + +#include "wayland-util.h" + +#include <QtCore/QMap> + +#include <QtWaylandCompositor/QWaylandCompositorExtensionTemplate> +#include <QtWaylandCompositor/QWaylandQuickExtension> +#include <QtWaylandCompositor/QWaylandCompositor> + +#include <QtWaylandCompositor/private/qwaylandcompositor_p.h> +#include <QtWaylandCompositor/private/qwlserverbufferintegration_p.h> + +#include "qwayland-server-share-buffer.h" + +QT_BEGIN_NAMESPACE + +namespace QtWayland +{ + class ServerBufferIntegration; +}; + + +class ShareBufferExtension : public QWaylandCompositorExtensionTemplate<ShareBufferExtension> + , public QtWaylandServer::qt_share_buffer +{ + Q_OBJECT +public: + ShareBufferExtension(QWaylandCompositor *compositor = nullptr); + void initialize() override; + +protected slots: + QtWayland::ServerBuffer *addImage(const QImage &image); + +protected: + void share_buffer_bind_resource(Resource *resource) override; + +private: + void createServerBuffers(); + QList<QtWayland::ServerBuffer *> m_server_buffers; + QtWayland::ServerBufferIntegration *m_server_buffer_integration = nullptr; + bool m_server_buffers_created = false; +}; + +Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(ShareBufferExtension) + +QT_END_NAMESPACE + +#endif // SHAREBUFFEREXTENSION_H diff --git a/tests/manual/server-buffer/cpp-client/CMakeLists.txt b/tests/manual/server-buffer/cpp-client/CMakeLists.txt new file mode 100644 index 000000000..01c0df44f --- /dev/null +++ b/tests/manual/server-buffer/cpp-client/CMakeLists.txt @@ -0,0 +1,44 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(server-buffer-cpp-client) + +set(CMAKE_AUTOMOC ON) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/wayland/server-buffer/cpp-client") + +find_package(Qt6 REQUIRED COMPONENTS Core Gui OpenGL WaylandClient) + +qt_add_executable(server-buffer-cpp-client + main.cpp + sharebufferextension.cpp sharebufferextension.h +) + +qt6_generate_wayland_protocol_client_sources(server-buffer-cpp-client + FILES + ${CMAKE_CURRENT_SOURCE_DIR}/../share-buffer.xml +) + +set_target_properties(server-buffer-cpp-client PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(server-buffer-cpp-client PUBLIC + Qt::Core + Qt::Gui + Qt::GuiPrivate + Qt::OpenGL + Qt::WaylandClientPrivate +) + +install(TARGETS server-buffer-cpp-client + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/tests/manual/server-buffer/cpp-client/cpp-client.pro b/tests/manual/server-buffer/cpp-client/cpp-client.pro new file mode 100644 index 000000000..6ac551323 --- /dev/null +++ b/tests/manual/server-buffer/cpp-client/cpp-client.pro @@ -0,0 +1,15 @@ +QT += waylandclient-private gui-private opengl +CONFIG += wayland-scanner + +WAYLANDCLIENTSOURCES += ../share-buffer.xml + +SOURCES += main.cpp \ + sharebufferextension.cpp + +HEADERS += \ + sharebufferextension.h + +TARGET = server-buffer-cpp-client + +target.path = $$[QT_INSTALL_EXAMPLES]/wayland/server-buffer/cpp-client +INSTALLS += target diff --git a/tests/manual/server-buffer/cpp-client/main.cpp b/tests/manual/server-buffer/cpp-client/main.cpp new file mode 100644 index 000000000..b11921f67 --- /dev/null +++ b/tests/manual/server-buffer/cpp-client/main.cpp @@ -0,0 +1,88 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include <QGuiApplication> +#include <QtGui/private/qguiapplication_p.h> +#include <QOpenGLWindow> +#include <QOpenGLTexture> +#include <QOpenGLTextureBlitter> +#include <QPainter> +#include <QMouseEvent> +#include <QPlatformSurfaceEvent> + +#include <QtWaylandClient/private/qwaylanddisplay_p.h> +#include <QtWaylandClient/private/qwaylandintegration_p.h> +#include <QtWaylandClient/private/qwaylandserverbufferintegration_p.h> +#include "sharebufferextension.h" + +#include <QDebug> +#include <QtGui/qpa/qplatformnativeinterface.h> +#include <QTimer> +#include <QMap> + +class TestWindow : public QOpenGLWindow +{ + Q_OBJECT + +public: + TestWindow() + { + m_extension = new ShareBufferExtension; + connect(m_extension, SIGNAL(bufferReceived(QtWaylandClient::QWaylandServerBuffer*)), this, SLOT(receiveBuffer(QtWaylandClient::QWaylandServerBuffer*))); + } + +public slots: + void receiveBuffer(QtWaylandClient::QWaylandServerBuffer *buffer) + { + m_buffers.append(buffer); + update(); + } + +protected: + + void initializeGL() override + { + m_blitter = new QOpenGLTextureBlitter; + m_blitter->create(); + } + + void paintGL() override { + glClearColor(.5, .45, .42, 1.); + glClear(GL_COLOR_BUFFER_BIT); + int x = 0; + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + for (auto buffer: m_buffers) { + m_blitter->bind(); + QPointF pos(x,0); + QSize s(buffer->size()); + QRectF targetRect(pos, s); + QOpenGLTexture *texture = buffer->toOpenGlTexture(); + auto surfaceOrigin = QOpenGLTextureBlitter::OriginTopLeft; + QMatrix4x4 targetTransform = QOpenGLTextureBlitter::targetTransform(targetRect, QRect(QPoint(), size())); + m_blitter->blit(texture->textureId(), targetTransform, surfaceOrigin); + m_blitter->release(); + x += s.width() + 10; + } + } + +private: + + QOpenGLTextureBlitter *m_blitter = nullptr; + ShareBufferExtension *m_extension = nullptr; + QList<QtWaylandClient::QWaylandServerBuffer*> m_buffers; + +}; + +int main (int argc, char **argv) +{ + QGuiApplication app(argc, argv); + + TestWindow window; + window.show(); + + return app.exec(); +} + +#include "main.moc" diff --git a/tests/manual/server-buffer/cpp-client/sharebufferextension.cpp b/tests/manual/server-buffer/cpp-client/sharebufferextension.cpp new file mode 100644 index 000000000..299684a89 --- /dev/null +++ b/tests/manual/server-buffer/cpp-client/sharebufferextension.cpp @@ -0,0 +1,36 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "sharebufferextension.h" +#include <QtWaylandClient/private/qwaylanddisplay_p.h> +#include <QtWaylandClient/private/qwaylandintegration_p.h> +#include <QtWaylandClient/private/qwaylandserverbufferintegration_p.h> +#include <QtGui/QGuiApplication> +#include <QtGui/private/qguiapplication_p.h> +#include <QtGui/QWindow> +#include <QtGui/QPlatformSurfaceEvent> +#include <QtGui/qpa/qplatformnativeinterface.h> +#include <QDebug> + +QT_BEGIN_NAMESPACE + +ShareBufferExtension::ShareBufferExtension() + : QWaylandClientExtensionTemplate(/* Supported protocol version */ 1 ) +{ + + auto *wayland_integration = static_cast<QtWaylandClient::QWaylandIntegration *>(QGuiApplicationPrivate::platformIntegration()); + m_server_buffer_integration = wayland_integration->serverBufferIntegration(); + if (!m_server_buffer_integration) { + qCritical() << "This application requires a working serverBufferIntegration"; + QGuiApplication::quit(); + } +} + +void ShareBufferExtension::share_buffer_cross_buffer(struct ::qt_server_buffer *buffer) +{ + QtWaylandClient::QWaylandServerBuffer *serverBuffer = m_server_buffer_integration->serverBuffer(buffer); + emit bufferReceived(serverBuffer); +} + + +QT_END_NAMESPACE diff --git a/tests/manual/server-buffer/cpp-client/sharebufferextension.h b/tests/manual/server-buffer/cpp-client/sharebufferextension.h new file mode 100644 index 000000000..6fc429194 --- /dev/null +++ b/tests/manual/server-buffer/cpp-client/sharebufferextension.h @@ -0,0 +1,36 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#ifndef SHAREBUFFEREXTENSION_H +#define SHAREBUFFEREXTENSION_H + +#include <qpa/qwindowsysteminterface.h> +#include <QtWaylandClient/private/qwayland-wayland.h> +#include <QtWaylandClient/qwaylandclientextension.h> +#include "qwayland-share-buffer.h" + +QT_BEGIN_NAMESPACE + +namespace QtWaylandClient { + class QWaylandServerBuffer; + class QWaylandServerBufferIntegration; +}; + +class ShareBufferExtension : public QWaylandClientExtensionTemplate<ShareBufferExtension> + , public QtWayland::qt_share_buffer +{ + Q_OBJECT +public: + ShareBufferExtension(); + +signals: + void bufferReceived(QtWaylandClient::QWaylandServerBuffer *buffer); + +private: + void share_buffer_cross_buffer(struct ::qt_server_buffer *buffer) override; + QtWaylandClient::QWaylandServerBufferIntegration *m_server_buffer_integration = nullptr; +}; + +QT_END_NAMESPACE + +#endif // SHAREBUFFEREXTENSION_H diff --git a/tests/manual/server-buffer/server-buffer.pro b/tests/manual/server-buffer/server-buffer.pro new file mode 100644 index 000000000..0c737ea8c --- /dev/null +++ b/tests/manual/server-buffer/server-buffer.pro @@ -0,0 +1,6 @@ +TEMPLATE=subdirs + +SUBDIRS += cpp-client compositor + +EXAMPLE_FILES += \ + share-buffer.xml diff --git a/tests/manual/server-buffer/share-buffer.xml b/tests/manual/server-buffer/share-buffer.xml new file mode 100644 index 000000000..2a4ae6748 --- /dev/null +++ b/tests/manual/server-buffer/share-buffer.xml @@ -0,0 +1,13 @@ +<protocol name="share_buffer"> + + <copyright> + Copyright (C) 2015 The Qt Company Ltd. + SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + </copyright> + + <interface name="qt_share_buffer" version="1"> + <event name="cross_buffer"> + <arg name="buffer" type="object" interface="qt_server_buffer"/> + </event> + </interface> +</protocol> diff --git a/tests/manual/subsurface/CMakeLists.txt b/tests/manual/subsurface/CMakeLists.txt new file mode 100644 index 000000000..0c1b50e0c --- /dev/null +++ b/tests/manual/subsurface/CMakeLists.txt @@ -0,0 +1,38 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +# Generated from subsurface.pro. + +##################################################################### +## subsurface Binary: +##################################################################### + +qt_internal_add_manual_test(subsurface + GUI + SOURCES + main.cpp + shmwindow.cpp shmwindow.h + LIBRARIES + Qt::CorePrivate + Qt::Gui + Qt::GuiPrivate + Qt::Quick + Qt::WaylandClient +) + +# Resources: +set(qml_resource_files + "child.qml" + "main.qml" +) + +qt_internal_add_resource(subsurface "qml" + PREFIX + "/" + FILES + ${qml_resource_files} +) + + +#### Keys ignored in scope 1:.:.:subsurface.pro:<TRUE>: +# TEMPLATE = "app" diff --git a/tests/manual/subsurface/child.qml b/tests/manual/subsurface/child.qml index f1bdd66ef..82d2e0757 100644 --- a/tests/manual/subsurface/child.qml +++ b/tests/manual/subsurface/child.qml @@ -1,52 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2015 LG Electronics Inc, author: <mikko.levonmaa@lge.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2015 LG Electronics Inc, author: <mikko.levonmaa@lge.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick 2.4 import QtQuick.Window 2.2 diff --git a/tests/manual/subsurface/main.cpp b/tests/manual/subsurface/main.cpp index 375e5d2b9..c353496c0 100644 --- a/tests/manual/subsurface/main.cpp +++ b/tests/manual/subsurface/main.cpp @@ -1,52 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2015 LG Electronics Inc, author: <mikko.levonmaa@lge.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2015 LG Electronics Inc, author: <mikko.levonmaa@lge.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QGuiApplication> #include <QQmlEngine> @@ -54,8 +7,6 @@ #include <QQmlContext> #include <QQuickView> -#include <QtPlatformHeaders/qwaylandwindowfunctions.h> - #include "shmwindow.h" class Filter : public QObject @@ -84,12 +35,6 @@ public: void toggleSync(QWindow *w) { - sync = !QWaylandWindowFunctions::isSync(w); - if (QWaylandWindowFunctions::isSync(w)) - QWaylandWindowFunctions::setDeSync(w); - else - QWaylandWindowFunctions::setSync(w); - emit syncChanged(); } bool getSync() const diff --git a/tests/manual/subsurface/main.qml b/tests/manual/subsurface/main.qml index 8c27ac78d..e6f7eeb79 100644 --- a/tests/manual/subsurface/main.qml +++ b/tests/manual/subsurface/main.qml @@ -1,52 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2015 LG Electronics Inc, author: <mikko.levonmaa@lge.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2015 LG Electronics Inc, author: <mikko.levonmaa@lge.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick 2.4 import QtQuick.Window 2.2 diff --git a/tests/manual/subsurface/shmwindow.cpp b/tests/manual/subsurface/shmwindow.cpp index 323582101..c6b59d132 100644 --- a/tests/manual/subsurface/shmwindow.cpp +++ b/tests/manual/subsurface/shmwindow.cpp @@ -1,52 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2015 LG Electronics Ltd, author: <mikko.levonmaa@lge.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2015 LG Electronics Ltd, author: <mikko.levonmaa@lge.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "shmwindow.h" diff --git a/tests/manual/subsurface/shmwindow.h b/tests/manual/subsurface/shmwindow.h index 10041eea9..55a0336e6 100644 --- a/tests/manual/subsurface/shmwindow.h +++ b/tests/manual/subsurface/shmwindow.h @@ -1,52 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2015 LG Electronics Ltd, author: <mikko.levonmaa@lge.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2015 LG Electronics Ltd, author: <mikko.levonmaa@lge.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef SHMWINDOW_H #define SHMWINDOW_H diff --git a/tests/manual/texture-sharing-2/.gitignore b/tests/manual/texture-sharing-2/.gitignore new file mode 100644 index 000000000..c684448d3 --- /dev/null +++ b/tests/manual/texture-sharing-2/.gitignore @@ -0,0 +1,2 @@ +custom-compositor/custom-compositor +qml-client/qml-client diff --git a/tests/manual/texture-sharing-2/CMakeLists.txt b/tests/manual/texture-sharing-2/CMakeLists.txt new file mode 100644 index 000000000..9a212ea3e --- /dev/null +++ b/tests/manual/texture-sharing-2/CMakeLists.txt @@ -0,0 +1,7 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +# Generated from texture-sharing.pro. + +add_subdirectory(qml-client) +add_subdirectory(custom-compositor) diff --git a/tests/manual/texture-sharing-2/README b/tests/manual/texture-sharing-2/README new file mode 100644 index 000000000..27ea76745 --- /dev/null +++ b/tests/manual/texture-sharing-2/README @@ -0,0 +1,27 @@ +This example shows how to use the texture sharing extension, allowing +multiple clients to share the same copy of an image in graphics memory. + +The texture sharing extension uses the server buffer extension to transport +graphics buffers. There are different server buffer plugins for different +graphics hardware. This is specified by setting an environment variable for +the compositor process. + +-On a device with Mesa and Intel integrated graphics, set: + + QT_WAYLAND_SERVER_BUFFER_INTEGRATION=dmabuf-server + +-On a device with NVIDIA graphics, set: + + QT_WAYLAND_SERVER_BUFFER_INTEGRATION=vulkan-server + +'custom-compositor' shows how to write a server that creates shared textures +programmatically. + +The file 'minimal-compositor.qml' shows how to add texture sharing to an +existing compositor, using only QML. It is based on the minimal-qml example, +and can be executed with qmlscene. + +'qml-client' shows how to use shared textures in a Qt Quick client. +The compositor uses the hardware integration extension to broadcast +the name of the server buffer integration to all clients, so qml-client +can be started like any normal wayland client. diff --git a/tests/manual/texture-sharing-2/custom-compositor/CMakeLists.txt b/tests/manual/texture-sharing-2/custom-compositor/CMakeLists.txt new file mode 100644 index 000000000..1a6c1494a --- /dev/null +++ b/tests/manual/texture-sharing-2/custom-compositor/CMakeLists.txt @@ -0,0 +1,28 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +qt_internal_add_manual_test(texture-sharing-custom-compositor + GUI + SOURCES + main.cpp + LIBRARIES + Qt::Qml + Qt::WaylandCompositorPrivate +) + + +# Resources: +set(compositor_resource_files + "images/background.png" + "images/car.ktx" + "images/qt4.astc" + "images/qt_logo.png" + "qml/main.qml" +) + +qt_internal_add_resource(texture-sharing-custom-compositor "compositor" + PREFIX + "/" + FILES + ${compositor_resource_files} +) diff --git a/tests/manual/texture-sharing-2/custom-compositor/compositor.qrc b/tests/manual/texture-sharing-2/custom-compositor/compositor.qrc new file mode 100644 index 000000000..86a8567f7 --- /dev/null +++ b/tests/manual/texture-sharing-2/custom-compositor/compositor.qrc @@ -0,0 +1,9 @@ +<RCC> + <qresource prefix="/"> + <file>images/background.png</file> + <file>images/qt_logo.png</file> + <file>images/qt4.astc</file> + <file>images/car.ktx</file> + <file>qml/main.qml</file> + </qresource> +</RCC> diff --git a/tests/manual/texture-sharing-2/custom-compositor/custom-compositor.pro b/tests/manual/texture-sharing-2/custom-compositor/custom-compositor.pro new file mode 100644 index 000000000..098034f3b --- /dev/null +++ b/tests/manual/texture-sharing-2/custom-compositor/custom-compositor.pro @@ -0,0 +1,17 @@ +QT += core gui qml + +QT += waylandcompositor-private + +SOURCES += \ + main.cpp + +OTHER_FILES = \ + qml/main.qml \ + images/background.jpg + +RESOURCES += compositor.qrc + +TARGET = texture-sharing-custom-compositor + +target.path = $$[QT_INSTALL_EXAMPLES]/wayland/texture-sharing/custom-compositor +INSTALLS += target diff --git a/tests/manual/texture-sharing-2/custom-compositor/images/background.png b/tests/manual/texture-sharing-2/custom-compositor/images/background.png Binary files differnew file mode 100644 index 000000000..845830c59 --- /dev/null +++ b/tests/manual/texture-sharing-2/custom-compositor/images/background.png diff --git a/tests/manual/texture-sharing-2/custom-compositor/images/car.ktx b/tests/manual/texture-sharing-2/custom-compositor/images/car.ktx Binary files differnew file mode 100644 index 000000000..2aefdd306 --- /dev/null +++ b/tests/manual/texture-sharing-2/custom-compositor/images/car.ktx diff --git a/tests/manual/texture-sharing-2/custom-compositor/images/qt4.astc b/tests/manual/texture-sharing-2/custom-compositor/images/qt4.astc Binary files differnew file mode 100644 index 000000000..7f7a3f473 --- /dev/null +++ b/tests/manual/texture-sharing-2/custom-compositor/images/qt4.astc diff --git a/tests/manual/texture-sharing-2/custom-compositor/images/qt_logo.png b/tests/manual/texture-sharing-2/custom-compositor/images/qt_logo.png Binary files differnew file mode 100644 index 000000000..5e2b355ea --- /dev/null +++ b/tests/manual/texture-sharing-2/custom-compositor/images/qt_logo.png diff --git a/tests/manual/texture-sharing-2/custom-compositor/main.cpp b/tests/manual/texture-sharing-2/custom-compositor/main.cpp new file mode 100644 index 000000000..0c229413b --- /dev/null +++ b/tests/manual/texture-sharing-2/custom-compositor/main.cpp @@ -0,0 +1,100 @@ +// Copyright (C) 2019 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include <QtCore/QUrl> +#include <QtCore/QDebug> +#include <QtGui/QGuiApplication> +#include <QtQml/QQmlApplicationEngine> + +#include <QtQml/qqml.h> +#include <QtQml/QQmlEngine> + +#include <QtGui/QPainter> +#include <QtGui/QImage> + +#include <QtCore/QDateTime> + +#include "QtWaylandCompositor/private/qwltexturesharingextension_p.h" + +#ifndef GL_RGBA8 +#define GL_RGBA8 0x8058 +#endif + +class CustomSharingExtension : public QWaylandTextureSharingExtension +{ + Q_OBJECT +public: + CustomSharingExtension() {qDebug("Instantiating custom texture sharing extension.");} +protected: + bool customPixelData(const QString &key, QByteArray *data, QSize *size, uint *glInternalFormat) override + { + qDebug() << "CustomSharingExtension looking for local texture data for" << key; + if (key.startsWith("unreasonably large ")) { + int w = 10000; + int h = 10000; + int numBytes = w * h * 4; + *data = QByteArray(numBytes, 0); + quint32 *pixels = reinterpret_cast<quint32*>(data->data()); + for (int i = 0; i < w*h; ++i) + pixels[i] = 0xff7f1fff; + *glInternalFormat = GL_RGBA8; + *size = QSize(w,h); + return true; + } + + QImage img; + + if (key == QLatin1String("test pattern 1")) { + img = QImage(128,128,QImage::Format_ARGB32_Premultiplied); + img.fill(QColor(0x55,0x0,0x55,0x01)); + { + QPainter p(&img); + QPen pen = p.pen(); + pen.setWidthF(3); + pen.setColor(Qt::red); + p.setPen(pen); + p.drawLine(0,0,128,128); + pen.setColor(Qt::green); + p.setPen(pen); + p.drawLine(128,0,0,128); + pen.setColor(Qt::blue); + p.setPen(pen); + p.drawLine(32,16,96,16); + pen.setColor(Qt::black); + p.setPen(pen); + p.translate(64, 64); + p.rotate(45); + p.drawText(QRect(-48, -32, 96, 64), + QDateTime::currentDateTime().toString(), + QTextOption(Qt::AlignHCenter)); + } + } + + if (!img.isNull()) { + img = img.convertToFormat(QImage::Format_RGBA8888); + *data = QByteArray(reinterpret_cast<const char*>(img.constBits()), img.sizeInBytes()); + *size = img.size(); + *glInternalFormat = GL_RGBA8; + return true; + } + return false; + } +}; + +Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(CustomSharingExtension); + +int main(int argc, char *argv[]) +{ + QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts, true); + QGuiApplication app(argc, argv); + QQmlApplicationEngine appEngine; + + qmlRegisterType<CustomSharingExtensionQuickExtension>("io.qt.tests.customsharingextension", 1, 0, "CustomSharingExtension"); + appEngine.addImageProvider("wlshared", new QWaylandSharedTextureProvider); + + appEngine.load(QUrl("qrc:///qml/main.qml")); + + return app.exec(); +} + +#include "main.moc" diff --git a/tests/manual/texture-sharing-2/custom-compositor/qml/main.qml b/tests/manual/texture-sharing-2/custom-compositor/qml/main.qml new file mode 100644 index 000000000..dd1f60f4e --- /dev/null +++ b/tests/manual/texture-sharing-2/custom-compositor/qml/main.qml @@ -0,0 +1,72 @@ +// Copyright (C) 2019 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick +import QtQuick.Window +import QtWayland.Compositor +import QtWayland.Compositor.XdgShell +import QtWayland.Compositor.WlShell + +import io.qt.tests.customsharingextension + +WaylandCompositor { + WaylandOutput { + sizeFollowsWindow: true + window: Window { + width: 1024 + height: 768 + visible: true + Image { + id: background + anchors.fill: parent + fillMode: Image.Tile + source: "qrc:/images/background.png" + smooth: true + + Rectangle { + width: 100 + height: 100 + color: "red" + anchors.bottom: parent.bottom; + anchors.right: parent.right; + MouseArea { + anchors.fill: parent + onClicked: sharedTextureImage.source = "image://wlshared/car.ktx" + } + } + Image { + id: sharedTextureImage + anchors.bottom: parent.bottom; + anchors.right: parent.right; + source: "" + } + Image { + id: topRightImage + anchors.top: parent.top; + anchors.right: parent.right; + source: "image://wlshared/qt_logo.png" + } + } + Repeater { + model: shellSurfaces + ShellSurfaceItem { + shellSurface: modelData + onSurfaceDestroyed: shellSurfaces.remove(index) + } + } + } + } + WlShell { + onWlShellSurfaceCreated: + shellSurfaces.append({shellSurface: shellSurface}); + } + XdgShell { + onToplevelCreated: + shellSurfaces.append({shellSurface: xdgSurface}); + } + ListModel { id: shellSurfaces } + + CustomSharingExtension { + imageSearchPath: ":/images;." + } +} diff --git a/tests/manual/texture-sharing-2/minimal-compositor.qml b/tests/manual/texture-sharing-2/minimal-compositor.qml new file mode 100644 index 000000000..d12216156 --- /dev/null +++ b/tests/manual/texture-sharing-2/minimal-compositor.qml @@ -0,0 +1,43 @@ +// Copyright (C) 2019 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick +import QtQuick.Window +import QtWayland.Compositor +import QtWayland.Compositor.XdgShell +import QtWayland.Compositor.WlShell + +// importing the texture sharing extension: +import QtWayland.Compositor.TextureSharingExtension + +WaylandCompositor { + WaylandOutput { + sizeFollowsWindow: true + window: Window { + width: 1024 + height: 768 + visible: true + Repeater { + model: shellSurfaces + ShellSurfaceItem { + shellSurface: modelData + onSurfaceDestroyed: shellSurfaces.remove(index) + } + } + } + } + WlShell { + onWlShellSurfaceCreated: + shellSurfaces.append({shellSurface: shellSurface}); + } + XdgShell { + onToplevelCreated: + shellSurfaces.append({shellSurface: xdgSurface}); + } + ListModel { id: shellSurfaces } + + // instantiating the texture sharing extension: + TextureSharingExtension { + imageSearchPath: ".;/tmp;/usr/share/pixmaps" + } +} diff --git a/tests/manual/texture-sharing-2/qml-client/CMakeLists.txt b/tests/manual/texture-sharing-2/qml-client/CMakeLists.txt new file mode 100644 index 000000000..ce6bc118d --- /dev/null +++ b/tests/manual/texture-sharing-2/qml-client/CMakeLists.txt @@ -0,0 +1,22 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +qt_internal_add_manual_test(qml-client + GUI + SOURCES + main.cpp + LIBRARIES + Qt::Quick +) + +# Resources: +set(qml-client_resource_files + "main.qml" +) + +qt_internal_add_resource(qml-client "qml-client" + PREFIX + "/" + FILES + ${qml-client_resource_files} +) diff --git a/tests/manual/texture-sharing-2/qml-client/main.cpp b/tests/manual/texture-sharing-2/qml-client/main.cpp new file mode 100644 index 000000000..8af386939 --- /dev/null +++ b/tests/manual/texture-sharing-2/qml-client/main.cpp @@ -0,0 +1,21 @@ +// Copyright (C) 2019 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include <QGuiApplication> +#include <QtQuick/QQuickView> +#include <QStandardPaths> +#include <QFileInfo> +#include <QQmlApplicationEngine> +#include <QDebug> +#include <QDir> +#include <QTimer> + +int main(int argc, char **argv) +{ + QGuiApplication app(argc, argv); + QQmlApplicationEngine appEngine; + + appEngine.load(QUrl("qrc:///main.qml")); + + return app.exec(); +} diff --git a/tests/manual/texture-sharing-2/qml-client/main.qml b/tests/manual/texture-sharing-2/qml-client/main.qml new file mode 100644 index 000000000..819a93bcf --- /dev/null +++ b/tests/manual/texture-sharing-2/qml-client/main.qml @@ -0,0 +1,201 @@ +// Copyright (C) 2019 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick +import QtQuick.Window + +import QtWayland.Client.TextureSharing + +Window { + width: 800 + height: 500 + visible: true + + Rectangle { + anchors.fill: parent + color: "#C0FEFE" + + Flickable { + anchors.fill: parent + contentHeight: imageGrid.height + + Grid { + id: imageGrid + columns: 2 + width: parent.width + spacing: 25 + padding: 25 + + + // loadedImage + Text { + width: 400 + wrapMode: Text.Wrap + text: "An Image element using the shared buffer provider to load from a PNG image.<br>" + + "Source: '" + loadedImage.source + "'" + + (loadedImage.sourceSize.height <= 0 ? "<font color=\"#FF0000\"><br>[Image not loaded]</font>" : "") + } + Image { + id: loadedImage + fillMode: Image.PreserveAspectFit + source: "image://wlshared/qt_logo.png" + } + Rectangle { + visible: loadedImage.height <= 0 + width:100; height: 100 + color: "green" + } + + // paintedImage + Text { + width: 400 + wrapMode: Text.Wrap + text: "An Image element using the shared buffer provider.<br>" + + "This texture is created by the compositor using QPainter. <br>" + + "Source: '" + paintedImage.source + "'" + + (paintedImage.sourceSize.height <= 0 ? "<font color=\"#FF0000\"><br>[Image not loaded]</font>" : "") + } + Image { + id: paintedImage + fillMode: Image.PreserveAspectFit + source: "image://wlshared/test pattern 1" + } + Rectangle { + visible: paintedImage.height <= 0 + width:100; height: 100 + color: "green" + } + + // ktxImage + Text { + width: 400 + wrapMode: Text.Wrap + text: "An Image element using the shared buffer provider to load an ETC2 compressed texture." + + "<br>Source: '" + ktxImage.source + "'" + + (ktxImage.sourceSize.height <= 0 ? "<font color=\"#FF0000\"><br>[Image not loaded]</font>" : "") + } + Image { + id: ktxImage + source: "image://wlshared/car.ktx" + fillMode: Image.PreserveAspectFit + } + Rectangle { + visible: ktxImage.height <= 0 + width:100; height: 100 + color: "green" + } + + //astcImage + Text { + width: 400 + wrapMode: Text.Wrap + text: "An Image element using the shared buffer provider to load an ASTC compressed texture." + + "<br>Source: '" + astcImage.source + "'" + + (astcImage.sourceSize.height <= 0 ? "<font color=\"#FF0000\"><br>[Image not loaded]</font>" : "") + } + + Image { + id: astcImage + source: "image://wlshared/qt4.astc" + fillMode: Image.PreserveAspectFit + } + Rectangle { + visible: astcImage.height <= 0 + width:100; height: 100 + color: "green" + } + + // dynamicImage + Column { + Text { + width: 400 + wrapMode: Text.Wrap + text: "An Image element using the shared buffer provider." + + "<br>Source: '" + dynamicImage.source + "'" + + (dynamicImage.sourceSize.height <= 0 ? "<font color=\"#FF0000\"><br>[Image not loaded]</font>" : "") + } + Row { + spacing: 10 + Text { + text: "Enter filename:" + } + Rectangle { + color: "white" + width: sourceEdit.contentWidth + 30 + height: sourceEdit.contentHeight + TextInput { + id: sourceEdit + anchors.fill: parent + horizontalAlignment: TextInput.AlignHCenter + onEditingFinished: dynamicImage.source = text ? "image://wlshared/" + text : "" + } + } + } + } + Image { + id: dynamicImage + fillMode: Image.PreserveAspectFit + } + Rectangle { + visible: dynamicImage.height <= 0 + width:100; height: 100 + color: "green" + } + + // largeImage + Text { + width: 400 + wrapMode: Text.Wrap + text: "An Image element using the shared buffer provider.<br>" + + "Left click to load a very large image. " + + "Right click to unload the image, potentially freeing graphics memory on the server-side " + + "if no other client is using the image." + + "<br>Source: '" + largeImage.source + "'" + + "<br>Size: " + largeImage.sourceSize + + (largeImage.sourceSize.height <= 0 ? "<font color=\"#FF0000\"><br>[Image not loaded]</font>" : "") + } + + Rectangle { + width: 200 + height: 200 + border.color: "black" + border.width: 2 + color: "transparent" + Image { + id: largeImage + anchors.fill: parent + fillMode: Image.PreserveAspectFit + } + MouseArea { + anchors.fill: parent + acceptedButtons: Qt.LeftButton | Qt.RightButton + onClicked: { + if (mouse.button == Qt.LeftButton) + largeImage.source = "image://wlshared/unreasonably large image" + else + largeImage.source = "" + + } + } + } + + } // Grid + } + + Rectangle { + color: "gray" + width: parent.width + height: 20 + anchors.bottom: parent.bottom + + Text { + color: "white" + anchors.fill: parent + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + text: "Scroll or drag for more" + } + } + + } +} diff --git a/tests/manual/texture-sharing-2/qml-client/qml-client.pro b/tests/manual/texture-sharing-2/qml-client/qml-client.pro new file mode 100644 index 000000000..67d5c7071 --- /dev/null +++ b/tests/manual/texture-sharing-2/qml-client/qml-client.pro @@ -0,0 +1,13 @@ +QT += quick + +SOURCES += \ + main.cpp + +RESOURCES += \ + qml-client.qrc + +DISTFILES += \ + main.qml + +target.path = $$[QT_INSTALL_EXAMPLES]/wayland/texture-sharing/qml-client +INSTALLS += target diff --git a/tests/manual/texture-sharing-2/qml-client/qml-client.qrc b/tests/manual/texture-sharing-2/qml-client/qml-client.qrc new file mode 100644 index 000000000..5f6483ac3 --- /dev/null +++ b/tests/manual/texture-sharing-2/qml-client/qml-client.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/"> + <file>main.qml</file> + </qresource> +</RCC> diff --git a/tests/manual/texture-sharing-2/texture-sharing.pro b/tests/manual/texture-sharing-2/texture-sharing.pro new file mode 100644 index 000000000..3f7792828 --- /dev/null +++ b/tests/manual/texture-sharing-2/texture-sharing.pro @@ -0,0 +1,5 @@ +TEMPLATE=subdirs + +SUBDIRS += \ + qml-client \ + custom-compositor diff --git a/tests/manual/texture-sharing/cpp-client/CMakeLists.txt b/tests/manual/texture-sharing/cpp-client/CMakeLists.txt new file mode 100644 index 000000000..1059e6e5e --- /dev/null +++ b/tests/manual/texture-sharing/cpp-client/CMakeLists.txt @@ -0,0 +1,32 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +# Generated from cpp-client.pro. + +##################################################################### +## cpp-client Binary: +##################################################################### + +qt_internal_add_manual_test(cpp-client + GUI + SOURCES + ../../../../src/imports/texture-sharing/texturesharingextension.cpp + ../../../../src/imports/texture-sharing/texturesharingextension_p.h + main.cpp + INCLUDE_DIRECTORIES + ../../../../src/imports/texture-sharing + LIBRARIES + Qt::Gui + Qt::GuiPrivate + Qt::OpenGL + Qt::WaylandClientPrivate +) + +qt6_generate_wayland_protocol_client_sources(cpp-client + FILES + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/extensions/qt-texture-sharing-unstable-v1.xml +) + +#### Keys ignored in scope 1:.:.:cpp-client.pro:<TRUE>: +# INSTALLS = "target" +# target.path = "$$[QT_INSTALL_EXAMPLES]/wayland/texture-sharing/cpp-client" diff --git a/tests/manual/texture-sharing/cpp-client/cpp-client.pro b/tests/manual/texture-sharing/cpp-client/cpp-client.pro index d251791db..99a100e07 100644 --- a/tests/manual/texture-sharing/cpp-client/cpp-client.pro +++ b/tests/manual/texture-sharing/cpp-client/cpp-client.pro @@ -1,4 +1,4 @@ -QT += waylandclient-private gui-private +QT += waylandclient-private gui-private opengl CONFIG += wayland-scanner WAYLANDCLIENTSOURCES += $$PWD/../../../../src/extensions/qt-texture-sharing-unstable-v1.xml diff --git a/tests/manual/texture-sharing/cpp-client/main.cpp b/tests/manual/texture-sharing/cpp-client/main.cpp index e3f6d7025..f992ea1b6 100644 --- a/tests/manual/texture-sharing/cpp-client/main.cpp +++ b/tests/manual/texture-sharing/cpp-client/main.cpp @@ -1,52 +1,5 @@ -/**************************************************************************** - ** - ** Copyright (C) 2019 The Qt Company Ltd. - ** Contact: https://www.qt.io/licensing/ - ** - ** This file is part of the examples of the Qt Wayland module - ** - ** $QT_BEGIN_LICENSE:BSD$ - ** Commercial License Usage - ** Licensees holding valid commercial Qt licenses may use this file in - ** accordance with the commercial license agreement provided with the - ** Software or, alternatively, in accordance with the terms contained in - ** a written agreement between you and The Qt Company. For licensing terms - ** and conditions see https://www.qt.io/terms-conditions. For further - ** information use the contact form at https://www.qt.io/contact-us. - ** - ** BSD License Usage - ** Alternatively, you may use this file under the terms of the BSD license - ** as follows: - ** - ** "Redistribution and use in source and binary forms, with or without - ** modification, are permitted provided that the following conditions are - ** met: - ** * Redistributions of source code must retain the above copyright - ** notice, this list of conditions and the following disclaimer. - ** * Redistributions in binary form must reproduce the above copyright - ** notice, this list of conditions and the following disclaimer in - ** the documentation and/or other materials provided with the - ** distribution. - ** * Neither the name of The Qt Company Ltd nor the names of its - ** contributors may be used to endorse or promote products derived - ** from this software without specific prior written permission. - ** - ** - ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." - ** - ** $QT_END_LICENSE$ - ** - ****************************************************************************/ +// Copyright (C) 2019 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QGuiApplication> #include <QtGui/private/qguiapplication_p.h> @@ -134,7 +87,7 @@ protected: int x = 0; qDebug() << "*** paintGL ***"; showBuffers(); - for (auto buffer: qAsConst(m_buffers)) { + for (auto buffer: std::as_const(m_buffers)) { m_blitter->bind(); QSize s(buffer->size()); qDebug() << "painting" << buffer << s; diff --git a/tests/manual/wip-cpp-compositor/CMakeLists.txt b/tests/manual/wip-cpp-compositor/CMakeLists.txt new file mode 100644 index 000000000..4d8a166ed --- /dev/null +++ b/tests/manual/wip-cpp-compositor/CMakeLists.txt @@ -0,0 +1,23 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +# Generated from wip-cpp-compositor.pro. + +##################################################################### +## wip-cpp-compositor Binary: +##################################################################### + +qt_internal_add_manual_test(wip-cpp-compositor + GUI + SOURCES + compositor.cpp compositor.h + main.cpp + window.cpp window.h + LIBRARIES + Qt::Gui + Qt::WaylandCompositor +) + +#### Keys ignored in scope 1:.:.:wip-cpp-compositor.pro:<TRUE>: +# INSTALLS = "target" +# target.path = "$$[QT_INSTALL_EXAMPLES]/wayland/reference-cpp" diff --git a/tests/manual/wip-cpp-compositor/compositor.cpp b/tests/manual/wip-cpp-compositor/compositor.cpp index d65c5f0c3..2f7025115 100644 --- a/tests/manual/wip-cpp-compositor/compositor.cpp +++ b/tests/manual/wip-cpp-compositor/compositor.cpp @@ -1,52 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Wayland module -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2019 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "compositor.h" #include "window.h" @@ -80,7 +33,7 @@ QPoint View::mapToLocal(const QPoint &globalPosition) const void View::updateAnchoredPosition() { QPoint offset; - QSize size = surface()->size(); + QSize size = surface()->bufferSize(); QSize delta = size - m_lastSize; if (m_anchorEdges & Qt::RightEdge) offset.setX(-delta.width()); @@ -109,7 +62,7 @@ ToplevelView::ToplevelView(QWaylandXdgToplevel *toplevel) setAnchorEdges(opposite); emit startResize(); }); - QVector<QWaylandXdgToplevel::State> states{QWaylandXdgToplevel::ActivatedState}; + QList<QWaylandXdgToplevel::State> states{QWaylandXdgToplevel::ActivatedState}; toplevel->sendConfigure(QSize(0, 0), states); } diff --git a/tests/manual/wip-cpp-compositor/compositor.h b/tests/manual/wip-cpp-compositor/compositor.h index 5c2d6a2f5..b2810d0da 100644 --- a/tests/manual/wip-cpp-compositor/compositor.h +++ b/tests/manual/wip-cpp-compositor/compositor.h @@ -1,52 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Wayland module -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2019 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef COMPOSITOR_H #define COMPOSITOR_H @@ -71,8 +24,8 @@ class View : public QWaylandView public: explicit View() = default; QOpenGLTexture *getTexture(); - QSize size() const { return surface() ? surface()->size() : QSize(); } - QRect globalGeometry() const { return {globalPosition(), surface()->size()}; } + QSize bufferSize() const { return surface() ? surface()->bufferSize() : QSize(); } + QRect globalGeometry() const { return {globalPosition(), surface()->bufferSize()}; } QPoint globalPosition() const { return m_globalPosition; } void setGlobalPosition(const QPoint &position); QPoint mapToLocal(const QPoint &globalPosition) const; diff --git a/tests/manual/wip-cpp-compositor/main.cpp b/tests/manual/wip-cpp-compositor/main.cpp index 8ca5a6f33..e8a34a14f 100644 --- a/tests/manual/wip-cpp-compositor/main.cpp +++ b/tests/manual/wip-cpp-compositor/main.cpp @@ -1,52 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Wayland module -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2019 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QGuiApplication> #include "window.h" diff --git a/tests/manual/wip-cpp-compositor/window.cpp b/tests/manual/wip-cpp-compositor/window.cpp index b5b2581e0..413e56572 100644 --- a/tests/manual/wip-cpp-compositor/window.cpp +++ b/tests/manual/wip-cpp-compositor/window.cpp @@ -1,52 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Wayland module -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2019 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "window.h" #include "compositor.h" @@ -116,23 +69,28 @@ void Window::paintGL() void Window::mousePressEvent(QMouseEvent *event) { - m_compositor->handleMousePress(event->localPos().toPoint(), event->button()); + m_compositor->handleMousePress(event->position().toPoint(), event->button()); } void Window::mouseReleaseEvent(QMouseEvent *event) { - m_compositor->handleMouseRelease(event->localPos().toPoint(), event->button(), event->buttons()); + m_compositor->handleMouseRelease(event->position().toPoint(), event->button(), event->buttons()); } void Window::mouseMoveEvent(QMouseEvent *event) { - m_compositor->handleMouseMove(event->localPos().toPoint()); + m_compositor->handleMouseMove(event->position().toPoint()); } +#if QT_CONFIG(wheelevent) void Window::wheelEvent(QWheelEvent *event) { - m_compositor->handleMouseWheel(event->orientation(), event->delta()); + if (event->angleDelta().x() != 0) + m_compositor->handleMouseWheel(Qt::Horizontal, event->angleDelta().x()); + if (event->angleDelta().y() != 0) + m_compositor->handleMouseWheel(Qt::Vertical, event->angleDelta().y()); } +#endif void Window::keyPressEvent(QKeyEvent *event) { diff --git a/tests/manual/wip-cpp-compositor/window.h b/tests/manual/wip-cpp-compositor/window.h index bc71207ee..58ed1d5a0 100644 --- a/tests/manual/wip-cpp-compositor/window.h +++ b/tests/manual/wip-cpp-compositor/window.h @@ -1,52 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Wayland module -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2019 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef WINDOW_H #define WINDOW_H @@ -71,7 +24,9 @@ protected: void mousePressEvent(QMouseEvent *event) override; void mouseReleaseEvent(QMouseEvent *event) override; void mouseMoveEvent(QMouseEvent *event) override; +#if QT_CONFIG(wheelevent) void wheelEvent(QWheelEvent *event) override; +#endif void keyPressEvent(QKeyEvent *event) override; void keyReleaseEvent(QKeyEvent *event) override; diff --git a/tests/manual/wlscaler/main.cpp b/tests/manual/wlscaler/main.cpp deleted file mode 100644 index b836e3787..000000000 --- a/tests/manual/wlscaler/main.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <QtGui/QGuiApplication> -#include <QtQml/QQmlApplicationEngine> - -int main(int argc, char* argv[]) -{ - QGuiApplication app(argc, argv); - QQmlApplicationEngine engine(QUrl("qrc:/main.qml")); - return app.exec(); -} diff --git a/tests/manual/wlscaler/main.qml b/tests/manual/wlscaler/main.qml deleted file mode 100644 index ddadf4801..000000000 --- a/tests/manual/wlscaler/main.qml +++ /dev/null @@ -1,100 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -import QtQuick 2.2 -import QtQuick.Window 2.2 -import QtWayland.Compositor 1.13 - -WaylandCompositor { - id: comp - WaylandOutput { - id: output - compositor: comp - sizeFollowsWindow: true - window: Window { - id: win - width: 500 - height: 500 - visible: true - title: "wlscaler-compositor - " + comp.socketName - Repeater { - model: shellSurfaces - ShellSurfaceItem { - shellSurface: modelData - onSurfaceDestroyed: shellSurfaces.remove(index); - autoCreatePopupItems: true - } - } - } - } - - WlScaler {} - - ListModel { id: shellSurfaces } - - XdgShell { - onToplevelCreated: shellSurfaces.append({shellSurface: xdgSurface}); - } - - // Including legacy shell extensions as well, as clients using wl-scaler - // probably use outdated shells as well. - - WlShell { - onWlShellSurfaceCreated: shellSurfaces.append({shellSurface: shellSurface}); - } - - XdgShellV5 { - onXdgSurfaceCreated: shellSurfaces.append({shellSurface: xdgSurface}); - } - - XdgShellV6 { - onToplevelCreated: shellSurfaces.append({shellSurface: xdgSurface}); - } -} diff --git a/tests/manual/wlscaler/qml.qrc b/tests/manual/wlscaler/qml.qrc deleted file mode 100644 index 6b2d0a781..000000000 --- a/tests/manual/wlscaler/qml.qrc +++ /dev/null @@ -1,5 +0,0 @@ -<!DOCTYPE RCC><RCC version="1.0"> -<qresource> - <file>main.qml</file> -</qresource> -</RCC> diff --git a/tests/manual/wlscaler/wlscaler.pro b/tests/manual/wlscaler/wlscaler.pro deleted file mode 100644 index e4ba825f8..000000000 --- a/tests/manual/wlscaler/wlscaler.pro +++ /dev/null @@ -1,7 +0,0 @@ -TEMPLATE = app - -QT += gui qml - -SOURCES += main.cpp - -RESOURCES += qml.qrc diff --git a/tests/tests.pro b/tests/tests.pro deleted file mode 100644 index 85e4f3a53..000000000 --- a/tests/tests.pro +++ /dev/null @@ -1,2 +0,0 @@ -TEMPLATE = subdirs -SUBDIRS += auto |