diff options
Diffstat (limited to 'tests/auto/compositor/compositor/mockclient.cpp')
-rw-r--r-- | tests/auto/compositor/compositor/mockclient.cpp | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/tests/auto/compositor/compositor/mockclient.cpp b/tests/auto/compositor/compositor/mockclient.cpp new file mode 100644 index 000000000..9b6d327a9 --- /dev/null +++ b/tests/auto/compositor/compositor/mockclient.cpp @@ -0,0 +1,215 @@ +/**************************************************************************** +** +** 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 "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("wayland-qt-test-0")) + , compositor(0) + , output(0) + , registry(0) + , wlshell(0) + , xdgShell(nullptr) +{ + 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 ) +{ + Q_UNUSED(width); + Q_UNUSED(height); + 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) +{ + Q_UNUSED(registry); + Q_UNUSED(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 == "xdg_shell") { + xdgShell = static_cast<xdg_shell *>(wl_registry_bind(registry, id, &xdg_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); +} + +xdg_surface *MockClient::createXdgSurface(wl_surface *surface) +{ + flushDisplay(); + return xdg_shell_get_xdg_surface(xdgShell, 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_Premultiplied); + 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); +} + |