summaryrefslogtreecommitdiffstats
path: root/tests/auto/client
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/client')
-rw-r--r--tests/auto/client/CMakeLists.txt36
-rw-r--r--tests/auto/client/client.pro19
-rw-r--r--tests/auto/client/client/CMakeLists.txt18
-rw-r--r--tests/auto/client/client/client.pro6
-rwxr-xr-xtests/auto/client/client/run-with-all-shells.sh1
-rw-r--r--tests/auto/client/client/tst_client.cpp378
-rw-r--r--tests/auto/client/clientextension/CMakeLists.txt17
-rw-r--r--tests/auto/client/clientextension/test.xml6
-rw-r--r--tests/auto/client/clientextension/tst_clientextension.cpp134
-rw-r--r--tests/auto/client/cursor/CMakeLists.txt11
-rw-r--r--tests/auto/client/cursor/cursorshapev1.cpp47
-rw-r--r--tests/auto/client/cursor/cursorshapev1.h44
-rw-r--r--tests/auto/client/cursor/tst_cursor.cpp103
-rw-r--r--tests/auto/client/datadevicev1/CMakeLists.txt15
-rw-r--r--tests/auto/client/datadevicev1/datadevicev1.pro4
-rw-r--r--tests/auto/client/datadevicev1/tst_datadevicev1.cpp131
-rw-r--r--tests/auto/client/fullscreenshellv1/CMakeLists.txt15
-rw-r--r--tests/auto/client/fullscreenshellv1/fullscreenshellv1.pro4
-rw-r--r--tests/auto/client/fullscreenshellv1/tst_fullscreenshellv1.cpp91
-rw-r--r--tests/auto/client/inputcontext/CMakeLists.txt15
-rw-r--r--tests/auto/client/inputcontext/inputcontext.pro4
-rw-r--r--tests/auto/client/inputcontext/tst_inputcontext.cpp169
-rw-r--r--tests/auto/client/iviapplication/CMakeLists.txt15
-rw-r--r--tests/auto/client/iviapplication/iviapplication.pro5
-rw-r--r--tests/auto/client/iviapplication/tst_iviapplication.cpp117
-rw-r--r--tests/auto/client/multithreaded/CMakeLists.txt15
-rw-r--r--tests/auto/client/multithreaded/tst_multithreaded.cpp140
-rw-r--r--tests/auto/client/nooutput/CMakeLists.txt15
-rw-r--r--tests/auto/client/nooutput/tst_nooutput.cpp53
-rw-r--r--tests/auto/client/output/CMakeLists.txt15
-rw-r--r--tests/auto/client/output/output.pro5
-rw-r--r--tests/auto/client/output/tst_output.cpp94
-rw-r--r--tests/auto/client/primaryselectionv1/CMakeLists.txt15
-rw-r--r--tests/auto/client/primaryselectionv1/primaryselectionv1.pro7
-rw-r--r--tests/auto/client/primaryselectionv1/tst_primaryselectionv1.cpp64
-rw-r--r--tests/auto/client/reconnect/CMakeLists.txt11
-rw-r--r--tests/auto/client/reconnect/tst_reconnect.cpp253
-rw-r--r--tests/auto/client/reconnect/wl-socket.c166
-rw-r--r--tests/auto/client/reconnect/wl-socket.h34
-rw-r--r--tests/auto/client/scaling/CMakeLists.txt10
-rw-r--r--tests/auto/client/scaling/tst_scaling.cpp134
-rw-r--r--tests/auto/client/seat/CMakeLists.txt15
-rw-r--r--tests/auto/client/seat/tst_seat.cpp (renamed from tests/auto/client/seatv5/tst_seatv5.cpp)369
-rw-r--r--tests/auto/client/seatv4/BLACKLIST2
-rw-r--r--tests/auto/client/seatv4/CMakeLists.txt24
-rw-r--r--tests/auto/client/seatv4/seatv4.pro9
-rw-r--r--tests/auto/client/seatv4/tst_seatv4.cpp106
-rw-r--r--tests/auto/client/seatv5/seatv5.pro4
-rw-r--r--tests/auto/client/seatv7/CMakeLists.txt13
-rw-r--r--tests/auto/client/seatv7/tst_seatv7.cpp129
-rw-r--r--tests/auto/client/shared/CMakeLists.txt73
-rw-r--r--tests/auto/client/shared/corecompositor.cpp52
-rw-r--r--tests/auto/client/shared/corecompositor.h54
-rw-r--r--tests/auto/client/shared/coreprotocol.cpp234
-rw-r--r--tests/auto/client/shared/coreprotocol.h147
-rw-r--r--tests/auto/client/shared/datadevice.cpp67
-rw-r--r--tests/auto/client/shared/datadevice.h63
-rw-r--r--tests/auto/client/shared/fractionalscalev1.cpp40
-rw-r--r--tests/auto/client/shared/fractionalscalev1.h39
-rw-r--r--tests/auto/client/shared/fullscreenshellv1.cpp22
-rw-r--r--tests/auto/client/shared/fullscreenshellv1.h34
-rw-r--r--tests/auto/client/shared/iviapplication.cpp45
-rw-r--r--tests/auto/client/shared/iviapplication.h50
-rw-r--r--tests/auto/client/shared/mockcompositor.cpp136
-rw-r--r--tests/auto/client/shared/mockcompositor.h58
-rw-r--r--tests/auto/client/shared/qttextinput.cpp20
-rw-r--r--tests/auto/client/shared/qttextinput.h26
-rw-r--r--tests/auto/client/shared/shared.pri5
-rw-r--r--tests/auto/client/shared/textinput.cpp32
-rw-r--r--tests/auto/client/shared/textinput.h29
-rw-r--r--tests/auto/client/shared/viewport.cpp58
-rw-r--r--tests/auto/client/shared/viewport.h50
-rw-r--r--tests/auto/client/shared/xdgdialog.cpp59
-rw-r--r--tests/auto/client/shared/xdgdialog.h49
-rw-r--r--tests/auto/client/shared/xdgoutputv1.cpp34
-rw-r--r--tests/auto/client/shared/xdgoutputv1.h63
-rw-r--r--tests/auto/client/shared/xdgshell.cpp44
-rw-r--r--tests/auto/client/shared/xdgshell.h42
-rw-r--r--tests/auto/client/shared_old/mockcompositor.cpp489
-rw-r--r--tests/auto/client/shared_old/mockcompositor.h285
-rw-r--r--tests/auto/client/shared_old/mockfullscreenshellv1.cpp43
-rw-r--r--tests/auto/client/shared_old/mockfullscreenshellv1.h58
-rw-r--r--tests/auto/client/shared_old/mockinput.cpp474
-rw-r--r--tests/auto/client/shared_old/mockinput.h172
-rw-r--r--tests/auto/client/shared_old/mockiviapplication.cpp72
-rw-r--r--tests/auto/client/shared_old/mockiviapplication.h85
-rw-r--r--tests/auto/client/shared_old/mockoutput.cpp93
-rw-r--r--tests/auto/client/shared_old/mockoutput.h62
-rw-r--r--tests/auto/client/shared_old/mocksurface.cpp162
-rw-r--r--tests/auto/client/shared_old/mocksurface.h87
-rw-r--r--tests/auto/client/shared_old/mockwlshell.cpp52
-rw-r--r--tests/auto/client/shared_old/mockwlshell.h58
-rw-r--r--tests/auto/client/shared_old/mockxdgshellv6.cpp145
-rw-r--r--tests/auto/client/shared_old/mockxdgshellv6.h114
-rw-r--r--tests/auto/client/shared_old/shared_old.pri34
-rw-r--r--tests/auto/client/surface/CMakeLists.txt15
-rw-r--r--tests/auto/client/surface/surface.pro5
-rw-r--r--tests/auto/client/surface/tst_surface.cpp103
-rw-r--r--tests/auto/client/tabletv2/CMakeLists.txt15
-rw-r--r--tests/auto/client/tabletv2/tst_tabletv2.cpp893
-rw-r--r--tests/auto/client/wl_connect/CMakeLists.txt16
-rw-r--r--tests/auto/client/wl_connect/tst_wlconnect.cpp29
-rw-r--r--tests/auto/client/wl_connect/wl_connect.pro5
-rw-r--r--tests/auto/client/xdgdecorationv1/CMakeLists.txt15
-rw-r--r--tests/auto/client/xdgdecorationv1/tst_xdgdecorationv1.cpp70
-rw-r--r--tests/auto/client/xdgdecorationv1/xdgdecorationv1.pro7
-rw-r--r--tests/auto/client/xdgoutput/CMakeLists.txt15
-rw-r--r--tests/auto/client/xdgoutput/tst_xdgoutput.cpp176
-rw-r--r--tests/auto/client/xdgoutput/xdgoutput.pro8
-rw-r--r--tests/auto/client/xdgshell/CMakeLists.txt15
-rw-r--r--tests/auto/client/xdgshell/tst_xdgshell.cpp455
-rw-r--r--tests/auto/client/xdgshell/xdgshell.pro5
-rw-r--r--tests/auto/client/xdgshellv6/tst_xdgshellv6.cpp445
-rw-r--r--tests/auto/client/xdgshellv6/xdgshellv6.pro5
114 files changed, 5067 insertions, 4447 deletions
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> &parameters);
- static void sendMousePress(void *data, const QList<QVariant> &parameters);
- static void sendMouseRelease(void *data, const QList<QVariant> &parameters);
- static void sendKeyPress(void *data, const QList<QVariant> &parameters);
- static void sendKeyRelease(void *data, const QList<QVariant> &parameters);
- static void sendTouchDown(void *data, const QList<QVariant> &parameters);
- static void sendTouchUp(void *data, const QList<QVariant> &parameters);
- static void sendTouchMotion(void *data, const QList<QVariant> &parameters);
- static void sendTouchFrame(void *data, const QList<QVariant> &parameters);
- static void sendDataDeviceDataOffer(void *data, const QList<QVariant> &parameters);
- static void sendDataDeviceEnter(void *data, const QList<QVariant> &parameters);
- static void sendDataDeviceMotion(void *data, const QList<QVariant> &parameters);
- static void sendDataDeviceDrop(void *data, const QList<QVariant> &parameters);
- static void sendDataDeviceLeave(void *data, const QList<QVariant> &parameters);
- static void waitForStartDrag(void *data, const QList<QVariant> &parameters);
- static void setOutputMode(void *compositor, const QList<QVariant> &parameters);
- static void sendShellSurfaceConfigure(void *data, const QList<QVariant> &parameters);
- static void sendIviSurfaceConfigure(void *data, const QList<QVariant> &parameters);
- static void sendXdgToplevelV6Configure(void *data, const QList<QVariant> &parameters);
-
-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> &parameters);
-
- 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> &parameters)
-{
- Compositor *compositor = static_cast<Compositor *>(data);
- compositor->m_keyboard->setFocus(resolveSurface(parameters.first()));
-}
-
-void Compositor::sendMousePress(void *data, const QList<QVariant> &parameters)
-{
- 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> &parameters)
-{
- 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> &parameters)
-{
- 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> &parameters)
-{
- 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> &parameters)
-{
- 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> &parameters)
-{
- 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> &parameters)
-{
- 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> &parameters)
-{
- 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> &parameters)
-{
- 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> &parameters)
-{
- 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> &parameters)
-{
- 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> &parameters)
-{
- 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> &parameters)
-{
- 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> &parameters)
-{
- 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> &parameters)
-{
- 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> &parameters)
-{
- 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> &parameters)
-{
- 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> &parameters)
-{
- 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
-