diff options
author | Paul Olav Tvete <paul.tvete@qt.io> | 2016-08-05 11:53:43 +0200 |
---|---|---|
committer | Jędrzej Nowacki <jedrzej.nowacki@theqtcompany.com> | 2016-08-19 11:46:04 +0000 |
commit | 2cc758045e322873ad58f675a70c8d8366b5c318 (patch) | |
tree | 91843191d0d8dc5be0b243fd5863f7b4a5fdede2 /tests/auto/compositor/compositor | |
parent | 9b7a5b428ba528dfb568af99b09e9e441f482e78 (diff) |
Fix autotest directory structure
The client and server parts are separate modules, so they need separate
top-level directories under tests/auto. This also makes it easier to add
new tests later.
Change-Id: I393341b6f4e8fc3afa480653f3482192e002e425
Reviewed-by: Giulio Camuffo <giulio.camuffo@kdab.com>
Diffstat (limited to 'tests/auto/compositor/compositor')
-rw-r--r-- | tests/auto/compositor/compositor/BLACKLIST | 2 | ||||
-rw-r--r-- | tests/auto/compositor/compositor/compositor.pro | 36 | ||||
-rw-r--r-- | tests/auto/compositor/compositor/mockclient.cpp | 207 | ||||
-rw-r--r-- | tests/auto/compositor/compositor/mockclient.h | 110 | ||||
-rw-r--r-- | tests/auto/compositor/compositor/mockseat.cpp | 48 | ||||
-rw-r--r-- | tests/auto/compositor/compositor/mockseat.h | 50 | ||||
-rw-r--r-- | tests/auto/compositor/compositor/testcompositor.cpp | 52 | ||||
-rw-r--r-- | tests/auto/compositor/compositor/testcompositor.h | 47 | ||||
-rw-r--r-- | tests/auto/compositor/compositor/testinputdevice.cpp | 62 | ||||
-rw-r--r-- | tests/auto/compositor/compositor/testinputdevice.h | 59 | ||||
-rw-r--r-- | tests/auto/compositor/compositor/testkeyboardgrabber.cpp | 65 | ||||
-rw-r--r-- | tests/auto/compositor/compositor/testkeyboardgrabber.h | 57 | ||||
-rw-r--r-- | tests/auto/compositor/compositor/tst_compositor.cpp | 395 |
13 files changed, 1190 insertions, 0 deletions
diff --git a/tests/auto/compositor/compositor/BLACKLIST b/tests/auto/compositor/compositor/BLACKLIST new file mode 100644 index 000000000..df4672be3 --- /dev/null +++ b/tests/auto/compositor/compositor/BLACKLIST @@ -0,0 +1,2 @@ +[keyboardGrab] +ubuntu-14.04 diff --git a/tests/auto/compositor/compositor/compositor.pro b/tests/auto/compositor/compositor/compositor.pro new file mode 100644 index 000000000..39d2179ad --- /dev/null +++ b/tests/auto/compositor/compositor/compositor.pro @@ -0,0 +1,36 @@ +CONFIG += testcase link_pkgconfig +TARGET = tst_compositor + +QT += testlib +QT += core-private gui-private compositor compositor-private + +!contains(QT_CONFIG, no-pkg-config) { + PKGCONFIG += wayland-client wayland-server +} else { + LIBS += -lwayland-client -lwayland-server +} + +config_xkbcommon { + !contains(QT_CONFIG, no-pkg-config) { + PKGCONFIG_PRIVATE += xkbcommon + } else { + LIBS_PRIVATE += -lxkbcommon + } +} else { + DEFINES += QT_NO_WAYLAND_XKB +} + +SOURCES += \ + tst_compositor.cpp \ + testcompositor.cpp \ + testkeyboardgrabber.cpp \ + mockclient.cpp \ + mockseat.cpp \ + testinputdevice.cpp + +HEADERS += \ + testcompositor.h \ + testkeyboardgrabber.h \ + mockclient.h \ + mockseat.h \ + testinputdevice.h diff --git a/tests/auto/compositor/compositor/mockclient.cpp b/tests/auto/compositor/compositor/mockclient.cpp new file mode 100644 index 000000000..33847da7d --- /dev/null +++ b/tests/auto/compositor/compositor/mockclient.cpp @@ -0,0 +1,207 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "mockclient.h" +#include "mockseat.h" + +#include <QElapsedTimer> +#include <QSocketNotifier> + +#include <private/qguiapplication_p.h> + +#include <unistd.h> +#include <fcntl.h> +#include <stdio.h> +#include <errno.h> +#include <sys/mman.h> + +const struct wl_registry_listener MockClient::registryListener = { + MockClient::handleGlobal +}; + +MockClient::MockClient() + : display(wl_display_connect(0)) + , compositor(0) + , output(0) + , registry(0) + , wlshell(0) +{ + if (!display) + qFatal("MockClient(): wl_display_connect() failed"); + + registry = wl_display_get_registry(display); + wl_registry_add_listener(registry, ®istryListener, this); + + fd = wl_display_get_fd(display); + + QSocketNotifier *readNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, this); + connect(readNotifier, SIGNAL(activated(int)), this, SLOT(readEvents())); + + QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::eventDispatcher; + connect(dispatcher, SIGNAL(awake()), this, SLOT(flushDisplay())); + + QElapsedTimer timeout; + timeout.start(); + do { + QCoreApplication::processEvents(); + } while (!(compositor && output) && timeout.elapsed() < 1000); + + if (!compositor || !output) + qFatal("MockClient(): failed to receive globals from display"); +} + +const wl_output_listener MockClient::outputListener = { + MockClient::outputGeometryEvent, + MockClient::outputModeEvent, + MockClient::outputDone, + MockClient::outputScale +}; + +MockClient::~MockClient() +{ + wl_display_disconnect(display); +} + +void MockClient::outputGeometryEvent(void *data, wl_output *, + int32_t x, int32_t y, + int32_t width, int32_t height, + int, const char *, const char *, + int32_t ) +{ + resolve(data)->geometry.moveTopLeft(QPoint(x, y)); +} + +void MockClient::outputModeEvent(void *data, wl_output *, uint32_t, + int w, int h, int) +{ + resolve(data)->geometry.setSize(QSize(w, h)); +} + +void MockClient::outputDone(void *, wl_output *) +{ + +} + +void MockClient::outputScale(void *, wl_output *, int) +{ + +} + +void MockClient::readEvents() +{ + wl_display_dispatch(display); +} + +void MockClient::flushDisplay() +{ + wl_display_dispatch_pending(display); + wl_display_flush(display); +} + +void MockClient::handleGlobal(void *data, wl_registry *registry, uint32_t id, const char *interface, uint32_t version) +{ + resolve(data)->handleGlobal(id, QByteArray(interface)); +} + +void MockClient::handleGlobal(uint32_t id, const QByteArray &interface) +{ + if (interface == "wl_compositor") { + compositor = static_cast<wl_compositor *>(wl_registry_bind(registry, id, &wl_compositor_interface, 1)); + } else if (interface == "wl_output") { + output = static_cast<wl_output *>(wl_registry_bind(registry, id, &wl_output_interface, 2)); + wl_output_add_listener(output, &outputListener, this); + } else if (interface == "wl_shm") { + shm = static_cast<wl_shm *>(wl_registry_bind(registry, id, &wl_shm_interface, 1)); + } else if (interface == "wl_shell") { + wlshell = static_cast<wl_shell *>(wl_registry_bind(registry, id, &wl_shell_interface, 1)); + } else if (interface == "wl_seat") { + wl_seat *s = static_cast<wl_seat *>(wl_registry_bind(registry, id, &wl_seat_interface, 1)); + m_seats << new MockSeat(s); + } +} + +wl_surface *MockClient::createSurface() +{ + flushDisplay(); + return wl_compositor_create_surface(compositor); +} + +wl_shell_surface *MockClient::createShellSurface(wl_surface *surface) +{ + flushDisplay(); + return wl_shell_get_shell_surface(wlshell, surface); +} + +ShmBuffer::ShmBuffer(const QSize &size, wl_shm *shm) + : handle(0) +{ + int stride = size.width() * 4; + int alloc = stride * size.height(); + + char filename[] = "/tmp/wayland-shm-XXXXXX"; + + int fd = mkstemp(filename); + if (fd < 0) { + qWarning("open %s failed: %s", filename, strerror(errno)); + return; + } + + if (ftruncate(fd, alloc) < 0) { + qWarning("ftruncate failed: %s", strerror(errno)); + close(fd); + return; + } + + void *data = mmap(0, alloc, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + unlink(filename); + + if (data == MAP_FAILED) { + qWarning("mmap failed: %s", strerror(errno)); + close(fd); + return; + } + + image = QImage(static_cast<uchar *>(data), size.width(), size.height(), stride, QImage::Format_ARGB32); + shm_pool = wl_shm_create_pool(shm,fd,alloc); + handle = wl_shm_pool_create_buffer(shm_pool,0, size.width(), size.height(), + stride, WL_SHM_FORMAT_ARGB8888); + close(fd); +} + +ShmBuffer::~ShmBuffer() +{ + munmap(image.bits(), image.byteCount()); + wl_buffer_destroy(handle); + wl_shm_pool_destroy(shm_pool); +} + diff --git a/tests/auto/compositor/compositor/mockclient.h b/tests/auto/compositor/compositor/mockclient.h new file mode 100644 index 000000000..8647205f2 --- /dev/null +++ b/tests/auto/compositor/compositor/mockclient.h @@ -0,0 +1,110 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <wayland-client.h> + +#include <QObject> +#include <QImage> +#include <QRect> +#include <QList> + +class MockSeat; + +class ShmBuffer +{ +public: + ShmBuffer(const QSize &size, wl_shm *shm); + ~ShmBuffer(); + + struct wl_buffer *handle; + struct wl_shm_pool *shm_pool; + QImage image; +}; + +class MockClient : public QObject +{ + Q_OBJECT + +public: + MockClient(); + ~MockClient(); + + wl_surface *createSurface(); + wl_shell_surface *createShellSurface(wl_surface *surface); + + wl_display *display; + wl_compositor *compositor; + wl_output *output; + wl_shm *shm; + wl_registry *registry; + wl_shell *wlshell; + + QList<MockSeat *> m_seats; + + QRect geometry; + + int fd; + +private slots: + void readEvents(); + void flushDisplay(); + +private: + static MockClient *resolve(void *data) { return static_cast<MockClient *>(data); } + static const struct wl_registry_listener registryListener; + static void handleGlobal(void *data, struct wl_registry *registry, uint32_t id, const char *interface, uint32_t version); + static int sourceUpdate(uint32_t mask, void *data); + + static void outputGeometryEvent(void *data, + wl_output *output, + int32_t x, int32_t y, + int32_t width, int32_t height, + int subpixel, + const char *make, + const char *model, + int32_t transform); + + static void outputModeEvent(void *data, + wl_output *wl_output, + uint32_t flags, + int width, + int height, + int refresh); + static void outputDone(void *data, wl_output *output); + static void outputScale(void *data, wl_output *output, int factor); + + void handleGlobal(uint32_t id, const QByteArray &interface); + + static const wl_output_listener outputListener; +}; + diff --git a/tests/auto/compositor/compositor/mockseat.cpp b/tests/auto/compositor/compositor/mockseat.cpp new file mode 100644 index 000000000..ebf387f94 --- /dev/null +++ b/tests/auto/compositor/compositor/mockseat.cpp @@ -0,0 +1,48 @@ +/**************************************************************************** +** +** Copyright (C) 2014 LG Electronics Ltd., author: <mikko.levonmaa@lge.com> +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "mockseat.h" + +MockSeat::MockSeat(wl_seat *seat) + : m_seat(seat) +{ + // Bind to the keyboard interface so that the compositor has + // the right resource associations + m_keyboard = wl_seat_get_keyboard(seat); +} + +MockSeat::~MockSeat() +{ + wl_keyboard_destroy(m_keyboard); + wl_seat_destroy(m_seat); +} diff --git a/tests/auto/compositor/compositor/mockseat.h b/tests/auto/compositor/compositor/mockseat.h new file mode 100644 index 000000000..24399a448 --- /dev/null +++ b/tests/auto/compositor/compositor/mockseat.h @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2014 LG Electronics Ltd., author: <mikko.levonmaa@lge.com> +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef MOCKSEAT +#define MOCKSEAT + +#include <QObject> +#include <wayland-client.h> + +class MockSeat : public QObject +{ + Q_OBJECT + +public: + MockSeat(wl_seat *seat); + ~MockSeat(); + + wl_seat *m_seat; + wl_keyboard *m_keyboard; +}; +#endif diff --git a/tests/auto/compositor/compositor/testcompositor.cpp b/tests/auto/compositor/compositor/testcompositor.cpp new file mode 100644 index 000000000..95dd87e3c --- /dev/null +++ b/tests/auto/compositor/compositor/testcompositor.cpp @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "testcompositor.h" + +TestCompositor::TestCompositor(QWaylandCompositor::ExtensionFlag flags) : QWaylandCompositor(0, flags) +{ + createOutput(0, "", ""); + addDefaultShell(); +} + +void TestCompositor::surfaceCreated(QWaylandSurface *surface) +{ + surfaces << surface; +} + +void TestCompositor::surfaceAboutToBeDestroyed(QWaylandSurface *surface) +{ + surfaces.removeOne(surface); +} + + diff --git a/tests/auto/compositor/compositor/testcompositor.h b/tests/auto/compositor/compositor/testcompositor.h new file mode 100644 index 000000000..c7d571d23 --- /dev/null +++ b/tests/auto/compositor/compositor/testcompositor.h @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwaylandcompositor.h" +#include "qwaylandsurface.h" + +class TestCompositor : public QWaylandCompositor +{ +public: + TestCompositor(QWaylandCompositor::ExtensionFlag flags = QWaylandCompositor::DefaultExtensions); + + void surfaceCreated(QWaylandSurface *surface); + void surfaceAboutToBeDestroyed(QWaylandSurface *surface); + + QList<QWaylandSurface *> surfaces; +}; + diff --git a/tests/auto/compositor/compositor/testinputdevice.cpp b/tests/auto/compositor/compositor/testinputdevice.cpp new file mode 100644 index 000000000..db2d1d706 --- /dev/null +++ b/tests/auto/compositor/compositor/testinputdevice.cpp @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2014 LG Electronics, Inc., author: <mikko.levonmaa@lge.com> +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "testinputdevice.h" + +#include <QMouseEvent> + +TestInputDevice::TestInputDevice(QWaylandCompositor *compositor, QWaylandInputDevice::CapabilityFlags caps) + : QWaylandInputDevice(compositor, caps) +{ + m_queryCount = 0; +} + +TestInputDevice::~TestInputDevice() +{ +} + +bool TestInputDevice::isOwner(QInputEvent *event) +{ + m_queryCount++; + QMouseEvent *me = dynamic_cast<QMouseEvent *>(event); + return m_events.contains(me); +} + +QList<QMouseEvent *> TestInputDevice::createMouseEvents(int count) +{ + for (int i = 0; i < count; i++) { + m_events.append(new QMouseEvent(QEvent::MouseMove, QPointF(10 + i, 10 + i), Qt::NoButton, Qt::NoButton, Qt::NoModifier)); + } + return m_events; +} + diff --git a/tests/auto/compositor/compositor/testinputdevice.h b/tests/auto/compositor/compositor/testinputdevice.h new file mode 100644 index 000000000..df5c646d1 --- /dev/null +++ b/tests/auto/compositor/compositor/testinputdevice.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2014 LG Electronics, Inc., author: <mikko.levonmaa@lge.com> +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QWaylandInputDevice> +#include <QList> + +QT_BEGIN_NAMESPACE +class QInputEvent; +class QMouseEvent; +QT_END_NAMESPACE + +class TestInputDevice : public QWaylandInputDevice +{ + +public: + + TestInputDevice(QWaylandCompositor *compositor, QWaylandInputDevice::CapabilityFlags caps); + ~TestInputDevice(); + + bool isOwner(QInputEvent *event); + + QList<QMouseEvent *> createMouseEvents(int count); + + int queryCount() { return m_queryCount; } + +private: + int m_queryCount; + QList<QMouseEvent *> m_events; +}; diff --git a/tests/auto/compositor/compositor/testkeyboardgrabber.cpp b/tests/auto/compositor/compositor/testkeyboardgrabber.cpp new file mode 100644 index 000000000..da2f467d9 --- /dev/null +++ b/tests/auto/compositor/compositor/testkeyboardgrabber.cpp @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2014 LG Electronics, Inc., author: <mikko.levonmaa@lge.com> +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "testkeyboardgrabber.h" + +namespace QtWayland { + KeyboardGrabber::~KeyboardGrabber() {} +} + +void TestKeyboardGrabber::focused(QtWayland::Surface *surface) +{ + Q_UNUSED(surface); + Q_EMIT focusedCalled(); +} + +void TestKeyboardGrabber::key(uint32_t serial, uint32_t time, uint32_t key, uint32_t state) +{ + Q_UNUSED(serial); + Q_UNUSED(time); + Q_UNUSED(key); + Q_UNUSED(state); + Q_EMIT keyCalled(); +} + +void TestKeyboardGrabber::modifiers(uint32_t serial, uint32_t mods_depressed, + uint32_t mods_latched, uint32_t mods_locked, uint32_t group) +{ + Q_UNUSED(serial); + Q_UNUSED(mods_depressed); + Q_UNUSED(mods_latched); + Q_UNUSED(mods_locked); + Q_UNUSED(group); + Q_EMIT modifiersCalled(); +} + diff --git a/tests/auto/compositor/compositor/testkeyboardgrabber.h b/tests/auto/compositor/compositor/testkeyboardgrabber.h new file mode 100644 index 000000000..0ce56b1a7 --- /dev/null +++ b/tests/auto/compositor/compositor/testkeyboardgrabber.h @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2014 LG Electronics, Inc., author: <mikko.levonmaa@lge.com> +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "QtCompositor/private/qwlkeyboard_p.h" +#include "QtCompositor/private/qwlsurface_p.h" + +class TestKeyboardGrabber : public QObject, public QtWayland::KeyboardGrabber +{ + Q_OBJECT + +public: + + TestKeyboardGrabber() {} + ~TestKeyboardGrabber() {} + + void focused(QtWayland::Surface *surface); + void key(uint32_t serial, uint32_t time, uint32_t key, uint32_t state); + void modifiers(uint32_t serial, uint32_t mods_depressed, + uint32_t mods_latched, uint32_t mods_locked, uint32_t group); + +signals: + void focusedCalled(); + void keyCalled(); + void modifiersCalled(); +}; + + diff --git a/tests/auto/compositor/compositor/tst_compositor.cpp b/tests/auto/compositor/compositor/tst_compositor.cpp new file mode 100644 index 000000000..c30ebc02b --- /dev/null +++ b/tests/auto/compositor/compositor/tst_compositor.cpp @@ -0,0 +1,395 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "mockclient.h" +#include "testcompositor.h" +#include "testkeyboardgrabber.h" + +#include "QtCompositor/private/qwlkeyboard_p.h" +#include "QtCompositor/private/qwlinputdevice_p.h" +#include "QtCompositor/private/qwlcompositor_p.h" +#include "testinputdevice.h" + +#include "qwaylandbufferref.h" + +#include <QtTest/QtTest> + +#include <QtCompositor/private/qwlinputdevice_p.h> + +class tst_WaylandCompositor : public QObject +{ + Q_OBJECT + +public: + tst_WaylandCompositor() { + setenv("XDG_RUNTIME_DIR", ".", 1); + } + +private slots: + void inputDeviceCapabilities(); + void keyboardGrab(); + void inputDeviceCreation(); + void inputDeviceKeyboardFocus(); + void singleClient(); + void multipleClients(); + void geometry(); + void mapSurface(); + void frameCallback(); +}; + +void tst_WaylandCompositor::singleClient() +{ + TestCompositor compositor; + + MockClient client; + + wl_surface *sa = client.createSurface(); + QTRY_COMPARE(compositor.surfaces.size(), 1); + + wl_surface *sb = client.createSurface(); + QTRY_COMPARE(compositor.surfaces.size(), 2); + + QWaylandClient *ca = compositor.surfaces.at(0)->client(); + QWaylandClient *cb = compositor.surfaces.at(1)->client(); + + QCOMPARE(ca, cb); + QVERIFY(ca != 0); + + QList<QWaylandSurface *> surfaces = compositor.surfacesForClient(ca); + QCOMPARE(surfaces.size(), 2); + QVERIFY((surfaces.at(0) == compositor.surfaces.at(0) && surfaces.at(1) == compositor.surfaces.at(1)) + || (surfaces.at(0) == compositor.surfaces.at(1) && surfaces.at(1) == compositor.surfaces.at(0))); + + wl_surface_destroy(sa); + QTRY_COMPARE(compositor.surfaces.size(), 1); + + wl_surface_destroy(sb); + QTRY_COMPARE(compositor.surfaces.size(), 0); +} + +void tst_WaylandCompositor::multipleClients() +{ + TestCompositor compositor; + + MockClient a; + MockClient b; + MockClient c; + + wl_surface *sa = a.createSurface(); + wl_surface *sb = b.createSurface(); + wl_surface *sc = c.createSurface(); + + QTRY_COMPARE(compositor.surfaces.size(), 3); + + QWaylandClient *ca = compositor.surfaces.at(0)->client(); + QWaylandClient *cb = compositor.surfaces.at(1)->client(); + QWaylandClient *cc = compositor.surfaces.at(2)->client(); + + QVERIFY(ca != cb); + QVERIFY(ca != cc); + QVERIFY(cb != cc); + QVERIFY(ca != 0); + + QCOMPARE(compositor.surfacesForClient(ca).size(), 1); + QCOMPARE(compositor.surfacesForClient(ca).at(0), compositor.surfaces.at(0)); + + QCOMPARE(compositor.surfacesForClient(cb).size(), 1); + QCOMPARE(compositor.surfacesForClient(cb).at(0), compositor.surfaces.at(1)); + + QCOMPARE(compositor.surfacesForClient(cc).size(), 1); + QCOMPARE(compositor.surfacesForClient(cc).at(0), compositor.surfaces.at(2)); + + wl_surface_destroy(sa); + wl_surface_destroy(sb); + wl_surface_destroy(sc); + + QTRY_COMPARE(compositor.surfaces.size(), 0); +} + +void tst_WaylandCompositor::keyboardGrab() +{ + TestCompositor compositor((QWaylandCompositor::ExtensionFlag)0); + MockClient mc; + + mc.createSurface(); + // This is needed for timing purposes, otherwise the query for the + // compositor surfaces will return null + QTRY_COMPARE(compositor.surfaces.size(), 1); + + // Set the focused surface so that key event will flow through + QWaylandSurface *waylandSurface = compositor.surfaces.at(0); + QWaylandInputDevice* inputDevice = compositor.defaultInputDevice(); + inputDevice->handle()->keyboardDevice()->setFocus(waylandSurface->handle()); + + TestKeyboardGrabber grab; + QSignalSpy grabFocusSpy(&grab, SIGNAL(focusedCalled())); + QSignalSpy grabKeySpy(&grab, SIGNAL(keyCalled())); + QSignalSpy grabModifierSpy(&grab, SIGNAL(modifiersCalled())); + + QtWayland::Keyboard *keyboard = inputDevice->handle()->keyboardDevice(); + keyboard->startGrab(&grab); + + QTRY_COMPARE(grabFocusSpy.count(), 1); + QCOMPARE(grab.m_keyboard, inputDevice->handle()->keyboardDevice()); + + QKeyEvent ke(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier, 30, 0, 0); + QKeyEvent ke1(QEvent::KeyRelease, Qt::Key_A, Qt::NoModifier, 30, 0, 0); + inputDevice->sendFullKeyEvent(&ke); + inputDevice->sendFullKeyEvent(&ke1); + QTRY_COMPARE(grabKeySpy.count(), 2); + + QKeyEvent ke2(QEvent::KeyPress, Qt::Key_Shift, Qt::NoModifier, 50, 0, 0); + QKeyEvent ke3(QEvent::KeyRelease, Qt::Key_Shift, Qt::NoModifier, 50, 0, 0); + inputDevice->sendFullKeyEvent(&ke2); + inputDevice->sendFullKeyEvent(&ke3); + QTRY_COMPARE(grabModifierSpy.count(), 2); + // Modifiers are also keys + QTRY_COMPARE(grabKeySpy.count(), 4); + + // Stop grabbing + keyboard->endGrab(); + inputDevice->sendFullKeyEvent(&ke); + inputDevice->sendFullKeyEvent(&ke1); + QTRY_COMPARE(grabKeySpy.count(), 4); +} + +void tst_WaylandCompositor::geometry() +{ + TestCompositor compositor; + + QRect geometry(0, 0, 4096, 3072); + compositor.setOutputGeometry(geometry); + + MockClient client; + + QTRY_COMPARE(client.geometry, geometry); +} + +void tst_WaylandCompositor::mapSurface() +{ + TestCompositor compositor; + + MockClient client; + + wl_surface *surface = client.createSurface(); + QTRY_COMPARE(compositor.surfaces.size(), 1); + + QWaylandSurface *waylandSurface = compositor.surfaces.at(0); + + QSignalSpy mappedSpy(waylandSurface, SIGNAL(mapped())); + + QCOMPARE(waylandSurface->size(), QSize()); + QCOMPARE(waylandSurface->type(), QWaylandSurface::Invalid); + + QSize size(256, 256); + ShmBuffer buffer(size, client.shm); + + // we need to create a shell surface here or the surface won't be mapped + client.createShellSurface(surface); + wl_surface_attach(surface, buffer.handle, 0, 0); + wl_surface_damage(surface, 0, 0, size.width(), size.height()); + wl_surface_commit(surface); + + QTRY_COMPARE(waylandSurface->size(), size); + QTRY_COMPARE(waylandSurface->type(), QWaylandSurface::Shm); + QTRY_COMPARE(mappedSpy.count(), 1); + + wl_surface_destroy(surface); +} + +static void frameCallbackFunc(void *data, wl_callback *callback, uint32_t) +{ + ++*static_cast<int *>(data); + wl_callback_destroy(callback); +} + +static void registerFrameCallback(wl_surface *surface, int *counter) +{ + static const wl_callback_listener frameCallbackListener = { + frameCallbackFunc + }; + + wl_callback_add_listener(wl_surface_frame(surface), &frameCallbackListener, counter); +} + +void tst_WaylandCompositor::frameCallback() +{ + class BufferAttacher : public QWaylandBufferAttacher + { + public: + void attach(const QWaylandBufferRef &ref) Q_DECL_OVERRIDE + { + bufferRef = ref; + } + void unmap() Q_DECL_OVERRIDE + { + } + + QImage image() const + { + if (!bufferRef || !bufferRef.isShm()) + return QImage(); + return bufferRef.image(); + } + + QWaylandBufferRef bufferRef; + }; + + TestCompositor compositor; + + MockClient client; + + wl_surface *surface = client.createSurface(); + + int frameCounter = 0; + + QTRY_COMPARE(compositor.surfaces.size(), 1); + QWaylandSurface *waylandSurface = compositor.surfaces.at(0); + BufferAttacher attacher; + waylandSurface->setBufferAttacher(&attacher); + QSignalSpy damagedSpy(waylandSurface, SIGNAL(damaged(const QRegion &))); + + for (int i = 0; i < 10; ++i) { + QSize size(i * 8 + 2, i * 8 + 2); + ShmBuffer buffer(size, client.shm); + + // attach a new buffer every frame, else the damage signal won't be fired + wl_surface_attach(surface, buffer.handle, 0, 0); + registerFrameCallback(surface, &frameCounter); + wl_surface_damage(surface, 0, 0, size.width(), size.height()); + wl_surface_commit(surface); + + QTRY_COMPARE(waylandSurface->type(), QWaylandSurface::Shm); + QTRY_COMPARE(damagedSpy.count(), i + 1); + + QCOMPARE(static_cast<BufferAttacher *>(waylandSurface->bufferAttacher())->image(), buffer.image); + compositor.frameStarted(); + compositor.sendFrameCallbacks(QList<QWaylandSurface *>() << waylandSurface); + + QTRY_COMPARE(frameCounter, i + 1); + } + + wl_surface_destroy(surface); +} + +void tst_WaylandCompositor::inputDeviceCapabilities() +{ + TestCompositor compositor; + QtWayland::InputDevice dev(NULL, compositor.handle(), QWaylandInputDevice::Pointer); + + QTRY_VERIFY(dev.pointerDevice()); + QTRY_VERIFY(!dev.keyboardDevice()); + QTRY_VERIFY(!dev.touchDevice()); + + dev.setCapabilities(QWaylandInputDevice::Keyboard | QWaylandInputDevice::Touch); + QTRY_VERIFY(!dev.pointerDevice()); + QTRY_VERIFY(dev.keyboardDevice()); + QTRY_VERIFY(dev.touchDevice()); + + // Test that existing devices do not change when another is removed + QtWayland::Keyboard *k = dev.keyboardDevice(); + dev.setCapabilities(QWaylandInputDevice::Keyboard); + QTRY_COMPARE(k, dev.keyboardDevice()); +} + +void tst_WaylandCompositor::inputDeviceCreation() +{ + TestCompositor compositor; + TestInputDevice dev1(&compositor, QWaylandInputDevice::Pointer | QWaylandInputDevice::Keyboard); + TestInputDevice dev2(&compositor, QWaylandInputDevice::Pointer | QWaylandInputDevice::Keyboard); + + compositor.handle()->registerInputDevice(&dev1); + compositor.handle()->registerInputDevice(&dev2); + + // The compositor will create the default input device + QTRY_COMPARE(compositor.handle()->inputDevices().count(), 3); + // Test the order + QTRY_COMPARE(compositor.handle()->inputDevices().at(0), &dev2); + QTRY_COMPARE(compositor.handle()->inputDevices().at(1), &dev1); + QTRY_COMPARE(compositor.handle()->inputDevices().at(2), compositor.defaultInputDevice()); + + QList<QMouseEvent *> allEvents; + allEvents += dev1.createMouseEvents(2); + allEvents += dev2.createMouseEvents(5); + foreach (QMouseEvent *me, allEvents) { + compositor.inputDeviceFor(me); + } + + // The first input device will only get called exatly the number of times it has created + // the events + QTRY_COMPARE(dev1.queryCount(), 2); + // The second will get called the total number of times as it sits as the first item in + // the registered input devices list + QTRY_COMPARE(dev2.queryCount(), 7); +} + +void tst_WaylandCompositor::inputDeviceKeyboardFocus() +{ + TestCompositor compositor; + + + TestInputDevice dev1(&compositor, QWaylandInputDevice::Keyboard); + TestInputDevice dev2(&compositor, QWaylandInputDevice::Keyboard); + + compositor.handle()->registerInputDevice(&dev1); + compositor.handle()->registerInputDevice(&dev2); + + // Create client after all the input devices have been set up as the mock client + // does not dynamically listen to new seats + MockClient client; + wl_surface *surface = client.createSurface(); + QTRY_COMPARE(compositor.surfaces.size(), 1); + + QWaylandSurface *waylandSurface = compositor.surfaces.at(0); + QList<QWaylandInputDevice *> devices = compositor.handle()->inputDevices(); + foreach (QWaylandInputDevice *dev, devices) { + dev->setKeyboardFocus(waylandSurface); + } + QTRY_COMPARE(compositor.defaultInputDevice()->keyboardFocus(), waylandSurface); + QTRY_COMPARE(dev1.keyboardFocus(), waylandSurface); + QTRY_COMPARE(dev2.keyboardFocus(), waylandSurface); + + wl_surface_destroy(surface); + QTRY_VERIFY(compositor.surfaces.size() == 0); + // This will normally be called for example in the quick compositor + // but here call it manually to get rid of the surface and have it reset + // the focus + compositor.handle()->cleanupGraphicsResources(); + + QTRY_VERIFY(!compositor.defaultInputDevice()->keyboardFocus()); + QTRY_VERIFY(!dev1.keyboardFocus()); + QTRY_VERIFY(!dev2.keyboardFocus()); +} + +#include <tst_compositor.moc> +QTEST_MAIN(tst_WaylandCompositor); |