diff options
author | Samuel Rødal <samuel.rodal@nokia.com> | 2012-03-06 10:29:45 +0100 |
---|---|---|
committer | Jørgen Lind <jorgen.lind@nokia.com> | 2012-03-07 09:06:52 +0100 |
commit | 28f40671e8ec939ef451746925a9986ea596c616 (patch) | |
tree | bb76b07cf770b3ccfe5931dc9e3aa0b372f3f9d2 /tests/auto/client | |
parent | 394cb2f27df11afe009ba5bb05572bd41fc81228 (diff) |
Added auto-test for wayland plugin.
Similar to the compositor auto-test, except this time we mock the
compositor, and test the client code, by forcing the wayland plugin to
be used.
Change-Id: I363019ff7e136db6822993f1881fec48a02a7db4
Reviewed-by: Jørgen Lind <jorgen.lind@nokia.com>
Diffstat (limited to 'tests/auto/client')
-rw-r--r-- | tests/auto/client/client.pro | 34 | ||||
-rw-r--r-- | tests/auto/client/mockcompositor.cpp | 269 | ||||
-rw-r--r-- | tests/auto/client/mockcompositor.h | 179 | ||||
-rw-r--r-- | tests/auto/client/mockinput.cpp | 125 | ||||
-rw-r--r-- | tests/auto/client/mockoutput.cpp | 81 | ||||
-rw-r--r-- | tests/auto/client/mockshell.cpp | 159 | ||||
-rw-r--r-- | tests/auto/client/mockshm.cpp | 100 | ||||
-rw-r--r-- | tests/auto/client/mocksurface.cpp | 145 | ||||
-rw-r--r-- | tests/auto/client/mocksurface.h | 67 | ||||
-rw-r--r-- | tests/auto/client/tst_client.cpp | 195 |
10 files changed, 1354 insertions, 0 deletions
diff --git a/tests/auto/client/client.pro b/tests/auto/client/client.pro new file mode 100644 index 000000000..5d1f43d69 --- /dev/null +++ b/tests/auto/client/client.pro @@ -0,0 +1,34 @@ +CONFIG += testcase +TARGET = tst_client + +QT += testlib +QT += core-private gui-private + +use_pkgconfig { + CONFIG += link_pkgconfig + PKGCONFIG += wayland-server + + #set the rpath + !isEmpty(QMAKE_LFLAGS_RPATH) { + WAYLAND_NEEDS_RPATH = $$system(pkg-config --libs-only-L wayland-server) + !isEmpty(WAYLAND_NEEDS_RPATH) { + WAYLAND_LIBDIR = $$system(pkg-config --variable=libdir wayland-server) + !isEmpty(WAYLAND_LIBDIR):QMAKE_LFLAGS += $${QMAKE_LFLAGS_RPATH}$${WAYLAND_LIBDIR} + } + } +} else { + INCLUDEPATH += $$QMAKE_INCDIR_WAYLAND + !isEmpty(QMAKE_LIBDIR_WAYLAND) { + LIBS += -L$$QMAKE_LIBDIR_WAYLAND + } + LIBS += -lwayland-server -lffi +} + +SOURCES += tst_client.cpp \ + mockcompositor.cpp \ + mockinput.cpp \ + mockshell.cpp \ + mockshm.cpp \ + mocksurface.cpp \ + mockoutput.cpp +HEADERS += mockcompositor.h mocksurface.h diff --git a/tests/auto/client/mockcompositor.cpp b/tests/auto/client/mockcompositor.cpp new file mode 100644 index 000000000..39bd6e3e7 --- /dev/null +++ b/tests/auto/client/mockcompositor.cpp @@ -0,0 +1,269 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "mockcompositor.h" +#include "mocksurface.h" + +MockCompositor::MockCompositor() + : m_alive(true) + , m_ready(false) + , m_compositor(0) +{ + 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::setOutputGeometry(const QRect &rect) +{ + Command command = makeCommand(Impl::Compositor::setOutputGeometry, m_compositor); + command.parameters << rect; + 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); +} + +QSharedPointer<MockSurface> MockCompositor::surface() +{ + QSharedPointer<MockSurface> result; + lock(); + QVector<Impl::Surface *> surfaces = m_compositor->surfaces(); + if (!surfaces.isEmpty()) + result = surfaces.first()->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() +{ + foreach (const Command &command, m_commandQueue) + command.callback(command.target, command.parameters); + m_commandQueue.clear(); +} + +void *MockCompositor::run(void *data) +{ + MockCompositor *controller = static_cast<MockCompositor *>(data); + + Impl::Compositor compositor; + + controller->m_compositor = &compositor; + controller->m_waitCondition.wakeOne(); + + while (!controller->m_ready) { + controller->dispatchCommands(); + compositor.dispatchEvents(20); + } + + while (controller->m_alive) { + QMutexLocker locker(&controller->m_mutex); + controller->m_waitCondition.wait(&controller->m_mutex); + controller->dispatchCommands(); + compositor.dispatchEvents(20); + } + + return 0; +} + +namespace Impl { + +Compositor::Compositor() + : m_display(wl_display_create()) + , m_time(0) +{ + wl_list_init(&m_outputResources); + + wl_display_add_socket(m_display, 0); + + wl_input_device_init(&m_input); + + wl_display_add_global(m_display, &wl_compositor_interface, this, bindCompositor); + wl_display_add_global(m_display, &wl_input_device_interface, this, bindInput); + wl_display_add_global(m_display, &wl_output_interface, this, bindOutput); + wl_display_add_global(m_display, &wl_shell_interface, this, bindShell); + + initShm(); + + m_loop = wl_display_get_event_loop(m_display); + m_fd = wl_event_loop_get_fd(m_loop); +} + +Compositor::~Compositor() +{ + wl_shm_finish(m_shm); + wl_display_destroy(m_display); +} + +void Compositor::dispatchEvents(int timeout) +{ + 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 *>(compositorResource->data); + compositor->addSurface(new Surface(client, id, 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 + }; + + Q_UNUSED(version); + wl_client_add_object(client, &wl_compositor_interface, &compositorInterface, id, compositorData); +} + +static void unregisterResourceCallback(wl_listener *listener, + wl_resource *resource, + uint32_t time) +{ + Q_UNUSED(time); + wl_list_remove(&resource->link); + delete listener; +} + +void registerResource(wl_list *list, wl_resource *resource) +{ + wl_list_insert(list, &resource->link); + + wl_listener *listener = new wl_listener; + listener->func = unregisterResourceCallback; + + wl_list_insert(&resource->destroy_listener_list, &listener->link); +} + +QVector<Surface *> Compositor::surfaces() const +{ + return m_surfaces; +} + +void Compositor::addSurface(Surface *surface) +{ + m_surfaces << surface; +} + +void Compositor::removeSurface(Surface *surface) +{ + m_surfaces.remove(m_surfaces.indexOf(surface)); +} + +} + diff --git a/tests/auto/client/mockcompositor.h b/tests/auto/client/mockcompositor.h new file mode 100644 index 000000000..ece197277 --- /dev/null +++ b/tests/auto/client/mockcompositor.h @@ -0,0 +1,179 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MOCKCOMPOSITOR_H +#define MOCKCOMPOSITOR_H + +#include <pthread.h> +#include <qglobal.h> +#include <wayland-server.h> + +#include <QRect> +#include <QMutex> +#include <QSharedPointer> +#include <QVariant> +#include <QVector> +#include <QWaitCondition> + +namespace Impl { + +typedef void (**Implementation)(void); + +class Surface; + +class Compositor +{ +public: + Compositor(); + ~Compositor(); + + int fileDescriptor() const { return m_fd; } + void dispatchEvents(int timeout = 0); + + uint32_t time() { return ++m_time; } + + static void setOutputGeometry(void *compositor, const QList<QVariant> ¶meters); + + QVector<Surface *> surfaces() const; + + void addSurface(Surface *surface); + void removeSurface(Surface *surface); + + static void setKeyboardFocus(void *data, const QList<QVariant> ¶meters); + static void sendMousePress(void *data, const QList<QVariant> ¶meters); + static void sendMouseRelease(void *data, const QList<QVariant> ¶meters); + +private: + static void bindCompositor(wl_client *client, void *data, uint32_t version, uint32_t id); + static void bindInput(wl_client *client, void *data, uint32_t version, uint32_t id); + static void bindOutput(wl_client *client, void *data, uint32_t version, uint32_t id); + static void bindShell(wl_client *client, void *data, uint32_t version, uint32_t id); + + static void destroyInputResource(wl_resource *resource); + + void initShm(); + + void sendOutputGeometry(wl_resource *resource); + void sendOutputMode(wl_resource *resource); + + QRect m_outputGeometry; + + wl_display *m_display; + wl_event_loop *m_loop; + wl_shm *m_shm; + int m_fd; + + wl_list m_outputResources; + uint32_t m_time; + + wl_input_device m_input; + QVector<Surface *> m_surfaces; +}; + +void registerResource(wl_list *list, wl_resource *resource); + +} + +class MockSurface +{ +public: + Impl::Surface *handle() const { return m_surface; } + +private: + MockSurface(Impl::Surface *surface); + friend class Impl::Compositor; + friend class Impl::Surface; + + Impl::Surface *m_surface; +}; + +Q_DECLARE_METATYPE(QSharedPointer<MockSurface>) + +class MockCompositor +{ +public: + MockCompositor(); + ~MockCompositor(); + + void applicationInitialized(); + + int waylandFileDescriptor() const; + void processWaylandEvents(); + + void setOutputGeometry(const QRect &rect); + void setKeyboardFocus(const QSharedPointer<MockSurface> &surface); + void sendMousePress(const QSharedPointer<MockSurface> &surface, const QPoint &pos); + void sendMouseRelease(const QSharedPointer<MockSurface> &surface); + + QSharedPointer<MockSurface> surface(); + + void lock(); + void unlock(); + +private: + struct Command + { + typedef void (*Callback)(void *target, const QList<QVariant> ¶meters); + + Callback callback; + void *target; + 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; + bool m_ready; + pthread_t m_thread; + QMutex m_mutex; + QWaitCondition m_waitCondition; + + Impl::Compositor *m_compositor; + + QList<Command> m_commandQueue; +}; + +#endif diff --git a/tests/auto/client/mockinput.cpp b/tests/auto/client/mockinput.cpp new file mode 100644 index 000000000..9d6286db2 --- /dev/null +++ b/tests/auto/client/mockinput.cpp @@ -0,0 +1,125 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "mockcompositor.h" +#include "mocksurface.h" + +namespace Impl { + +void Compositor::destroyInputResource(wl_resource *resource) +{ + Compositor *compositor = static_cast<Compositor *>(resource->data); + wl_input_device *input = &compositor->m_input; + + if (input->keyboard_focus_resource == resource) + input->keyboard_focus_resource = 0; + if (input->pointer_focus_resource == resource) + input->pointer_focus_resource = 0; + + wl_list_remove(&resource->link); + + free(resource); +} + +void input_device_attach(wl_client *client, + wl_resource *device_resource, + uint32_t time, + wl_resource *buffer_resource, int32_t x, int32_t y) +{ + Q_UNUSED(client); + Q_UNUSED(device_resource); + Q_UNUSED(time); + Q_UNUSED(buffer_resource); + Q_UNUSED(QPoint(x, y)); +} + +void Compositor::bindInput(wl_client *client, void *compositorData, uint32_t version, uint32_t id) +{ + static const struct wl_input_device_interface inputDeviceInterface = { + input_device_attach, + }; + + Q_UNUSED(version); + wl_resource *resource = wl_client_add_object(client, &wl_input_device_interface, &inputDeviceInterface, id, compositorData); + resource->destroy = destroyInputResource; + + Compositor *compositor = static_cast<Compositor *>(compositorData); + wl_list_insert(&compositor->m_input.resource_list, &resource->link); +} + +static wl_surface *resolveSurface(const QVariant &v) +{ + QSharedPointer<MockSurface> mockSurface = v.value<QSharedPointer<MockSurface> >(); + Surface *surface = mockSurface ? mockSurface->handle() : 0; + return surface ? surface->handle() : 0; +} + +void Compositor::setKeyboardFocus(void *data, const QList<QVariant> ¶meters) +{ + Compositor *compositor = static_cast<Compositor *>(data); + wl_input_device_set_keyboard_focus(&compositor->m_input, resolveSurface(parameters.first()), compositor->time()); +} + +void Compositor::sendMousePress(void *data, const QList<QVariant> ¶meters) +{ + Compositor *compositor = static_cast<Compositor *>(data); + wl_surface *surface = resolveSurface(parameters.first()); + if (!surface) + return; + + QPoint pos = parameters.last().toPoint(); + wl_input_device_set_pointer_focus(&compositor->m_input, surface, compositor->time(), pos.x(), pos.y()); + wl_input_device_send_motion(compositor->m_input.pointer_focus_resource, compositor->time(), pos.x(), pos.y()); + wl_input_device_send_button(compositor->m_input.pointer_focus_resource, compositor->time(), 0x110, 1); +} + +void Compositor::sendMouseRelease(void *data, const QList<QVariant> ¶meters) +{ + Compositor *compositor = static_cast<Compositor *>(data); + wl_surface *surface = resolveSurface(parameters.first()); + if (!surface) + return; + + wl_input_device_send_button(compositor->m_input.pointer_focus_resource, compositor->time(), 0x110, 0); +} + +} + diff --git a/tests/auto/client/mockoutput.cpp b/tests/auto/client/mockoutput.cpp new file mode 100644 index 000000000..18773f021 --- /dev/null +++ b/tests/auto/client/mockoutput.cpp @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "mockcompositor.h" + +namespace Impl { + +void Compositor::bindOutput(wl_client *client, void *compositorData, uint32_t version, uint32_t id) +{ + Q_UNUSED(version); + + wl_resource *resource = wl_client_add_object(client, &wl_output_interface, 0, id, compositorData); + + Compositor *compositor = static_cast<Compositor *>(compositorData); + registerResource(&compositor->m_outputResources, resource); + + compositor->sendOutputGeometry(resource); + compositor->sendOutputMode(resource); +} + +void Compositor::sendOutputGeometry(wl_resource *resource) +{ + const QRect &r = m_outputGeometry; + wl_output_send_geometry(resource, r.x(), r.y(), r.width(), r.height(), 0, "", ""); +} + +void Compositor::sendOutputMode(wl_resource *resource) +{ + wl_output_send_mode(resource, WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED, 640, 480, 60); +} + +void Compositor::setOutputGeometry(void *c, const QList<QVariant> ¶meters) +{ + Compositor *compositor = static_cast<Compositor *>(c); + compositor->m_outputGeometry = parameters.first().toRect(); + + wl_resource *resource; + wl_list_for_each(resource, &compositor->m_outputResources, link) + compositor->sendOutputGeometry(resource); +} + +} + diff --git a/tests/auto/client/mockshell.cpp b/tests/auto/client/mockshell.cpp new file mode 100644 index 000000000..ede240d8e --- /dev/null +++ b/tests/auto/client/mockshell.cpp @@ -0,0 +1,159 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "mockcompositor.h" + +namespace Impl { + +void shell_surface_move(wl_client *client, + wl_resource *surface_resource, + wl_resource *input_device_resource, + uint32_t time) +{ + Q_UNUSED(client); + Q_UNUSED(surface_resource); + Q_UNUSED(input_device_resource); + Q_UNUSED(time); +} + +void shell_surface_resize(wl_client *client, + wl_resource *surface_resource, + wl_resource *input_device_resource, + uint32_t time, + uint32_t edges) +{ + Q_UNUSED(client); + Q_UNUSED(surface_resource); + Q_UNUSED(input_device_resource); + Q_UNUSED(time); + Q_UNUSED(edges); + +} + +void shell_surface_set_toplevel(wl_client *client, + wl_resource *surface_resource) +{ + Q_UNUSED(client); + Q_UNUSED(surface_resource); +} + +void shell_surface_set_transient(wl_client *client, + wl_resource *surface_resource, + wl_resource *parent_surface_resource, + int x, + int y, + uint32_t flags) +{ + + Q_UNUSED(client); + Q_UNUSED(surface_resource); + Q_UNUSED(parent_surface_resource); + Q_UNUSED(x); + Q_UNUSED(y); + Q_UNUSED(flags); +} + +void shell_surface_set_fullscreen(wl_client *client, + wl_resource *surface_resource, + uint32_t method, + uint32_t framerate, + wl_resource *output) +{ + Q_UNUSED(client); + Q_UNUSED(surface_resource); + Q_UNUSED(method); + Q_UNUSED(framerate); + Q_UNUSED(output); +} + +void shell_surface_set_popup(wl_client *client, wl_resource *resource, + wl_resource *input_device, uint32_t time, + wl_resource *parent, + int32_t x, int32_t y, + uint32_t flags) +{ + Q_UNUSED(client); + Q_UNUSED(resource); + Q_UNUSED(input_device); + Q_UNUSED(time); + Q_UNUSED(parent); + Q_UNUSED(x); + Q_UNUSED(y); + Q_UNUSED(flags); +} + +void shell_surface_set_maximized(wl_client *client, + wl_resource *surface_resource, + wl_resource *output) +{ + Q_UNUSED(client); + Q_UNUSED(surface_resource); + Q_UNUSED(output); +} + +static void get_shell_surface(wl_client *client, wl_resource *compositorResource, uint32_t id, wl_resource *surfaceResource) +{ + const struct wl_shell_surface_interface shellSurfaceInterface = { + shell_surface_move, + shell_surface_resize, + shell_surface_set_toplevel, + shell_surface_set_transient, + shell_surface_set_fullscreen, + shell_surface_set_popup, + shell_surface_set_maximized + }; + + Q_UNUSED(compositorResource); + wl_client_add_object(client, &wl_shell_surface_interface, &shellSurfaceInterface, id, surfaceResource->data); +} + +void Compositor::bindShell(wl_client *client, void *compositorData, uint32_t version, uint32_t id) +{ + static const struct wl_shell_interface shellInterface = { + get_shell_surface + }; + + Q_UNUSED(version); + wl_client_add_object(client, &wl_shell_interface, &shellInterface, id, compositorData); +} + +} + diff --git a/tests/auto/client/mockshm.cpp b/tests/auto/client/mockshm.cpp new file mode 100644 index 000000000..9deceebbb --- /dev/null +++ b/tests/auto/client/mockshm.cpp @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "mockcompositor.h" + +#include <QImage> + +namespace Impl { + +class ShmBuffer +{ +public: + ShmBuffer(wl_buffer *buffer) + : m_buffer(buffer) + { + refresh(); + } + + void refresh() + { + m_image = QImage(static_cast<uint8_t *>(wl_shm_buffer_get_data(m_buffer)), + m_buffer->width, m_buffer->height, + wl_shm_buffer_get_stride(m_buffer), + QImage::Format_ARGB32_Premultiplied); + } + +private: + wl_buffer *m_buffer; + QImage m_image; +}; + +static void shm_buffer_created(wl_buffer *buffer) +{ + buffer->user_data = new ShmBuffer(buffer); +} + +static void shm_buffer_damaged(wl_buffer *buffer, + int32_t x, int32_t y, + int32_t width, int32_t height) +{ + Q_UNUSED(QRect(x, y, width, height)); + static_cast<ShmBuffer *>(buffer->user_data)->refresh(); +} + +static void shm_buffer_destroyed(wl_buffer *buffer) +{ + delete static_cast<ShmBuffer *>(buffer->user_data); +} + +void Compositor::initShm() +{ + static struct wl_shm_callbacks shmCallbacks = { + shm_buffer_created, + shm_buffer_damaged, + shm_buffer_destroyed + }; + + m_shm = wl_shm_init(m_display, &shmCallbacks); +} + +} + diff --git a/tests/auto/client/mocksurface.cpp b/tests/auto/client/mocksurface.cpp new file mode 100644 index 000000000..38fc955e5 --- /dev/null +++ b/tests/auto/client/mocksurface.cpp @@ -0,0 +1,145 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "mocksurface.h" +#include "mockcompositor.h" + +namespace Impl { + +void destroy_surface(wl_resource *resource) +{ + Surface *surface = static_cast<Surface *>(resource->data); + surface->compositor()->removeSurface(surface); + delete surface; +} + +static void surface_destroy(wl_client *, wl_resource *surfaceResource) +{ + Surface *surface = static_cast<Surface *>(surfaceResource->data); + wl_resource_destroy(surfaceResource, surface->compositor()->time()); +} + +void surface_attach(wl_client *client, wl_resource *surface, + wl_resource *buffer, int x, int y) +{ + Q_UNUSED(client); + Q_UNUSED(surface); + Q_UNUSED(buffer); + Q_UNUSED(x); + Q_UNUSED(y); + //resolve<Surface>(surface)->attach(buffer ? reinterpret_cast<wl_buffer *>(buffer->data) : 0); +} + +void surface_damage(wl_client *client, wl_resource *surface, + int32_t x, int32_t y, int32_t width, int32_t height) +{ + Q_UNUSED(client); + Q_UNUSED(surface); + Q_UNUSED(x); + Q_UNUSED(y); + Q_UNUSED(width); + Q_UNUSED(height); + //resolve<Surface>(surface)->damage(QRect(x, y, width, height)); +} + +void surface_frame(wl_client *client, + wl_resource *surface, + uint32_t callback) +{ + Q_UNUSED(client); + Q_UNUSED(surface); + Q_UNUSED(callback); +// Surface *surface = resolve<Surface>(resource); +// wl_resource *frame_callback = wl_client_add_object(client, &wl_callback_interface, 0, callback, surface); +// wl_list_insert(&surface->m_frame_callback_list, &frame_callback->link); +} + +void surface_set_opaque_region(wl_client *client, wl_resource *surfaceResource, + wl_resource *region) +{ + Q_UNUSED(client); + Q_UNUSED(surfaceResource); + Q_UNUSED(region); +} + +void surface_set_input_region(wl_client *client, wl_resource *surfaceResource, + wl_resource *region) +{ + Q_UNUSED(client); + Q_UNUSED(surfaceResource); + Q_UNUSED(region); +} + +Surface::Surface(wl_client *client, uint32_t id, Compositor *compositor) + : m_surface(wl_surface()) + , m_compositor(compositor) + , m_mockSurface(new MockSurface(this)) +{ + static const struct wl_surface_interface surfaceInterface = { + surface_destroy, + surface_attach, + surface_damage, + surface_frame, + surface_set_opaque_region, + surface_set_input_region + }; + + m_surface.resource.object.id = id; + m_surface.resource.object.interface = &wl_surface_interface; + m_surface.resource.object.implementation = (Implementation)&surfaceInterface; + m_surface.resource.data = this; + m_surface.resource.destroy = destroy_surface; + + wl_client_add_resource(client, &m_surface.resource); + +} + +Surface::~Surface() +{ + m_mockSurface->m_surface = 0; +} + +} + +MockSurface::MockSurface(Impl::Surface *surface) + : m_surface(surface) +{ +} diff --git a/tests/auto/client/mocksurface.h b/tests/auto/client/mocksurface.h new file mode 100644 index 000000000..69ae80248 --- /dev/null +++ b/tests/auto/client/mocksurface.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qglobal.h> +#include <wayland-server.h> + +#include "mockcompositor.h" + +namespace Impl { + +class Surface +{ +public: + Surface(wl_client *client, uint32_t id, Compositor *compositor); + ~Surface(); + + Compositor *compositor() const { return m_compositor; } + wl_surface *handle() { return &m_surface; } + + QSharedPointer<MockSurface> mockSurface() const { return m_mockSurface; } + +private: + wl_surface m_surface; + + Compositor *m_compositor; + QSharedPointer<MockSurface> m_mockSurface; +}; + +} diff --git a/tests/auto/client/tst_client.cpp b/tests/auto/client/tst_client.cpp new file mode 100644 index 000000000..fdcb12991 --- /dev/null +++ b/tests/auto/client/tst_client.cpp @@ -0,0 +1,195 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "mockcompositor.h" + +#include <QtTest/QtTest> + +static const QSize screenSize(1600, 1200); + +class TestWindow : public QWindow +{ +public: + TestWindow() + : focusInEventCount(0) + , focusOutEventCount(0) + , keyPressEventCount(0) + , keyReleaseEventCount(0) + , mousePressEventCount(0) + , mouseReleaseEventCount(0) + { + setSurfaceType(QSurface::RasterSurface); + setGeometry(0, 0, 32, 32); + create(); + } + + void focusInEvent(QFocusEvent *) + { + ++focusInEventCount; + } + + void focusOutEvent(QFocusEvent *) + { + ++focusOutEventCount; + } + + void keyPressEvent(QKeyEvent *) + { + ++keyPressEventCount; + } + + void keyReleaseEvent(QKeyEvent *) + { + ++keyReleaseEventCount; + } + + void mousePressEvent(QMouseEvent *event) + { + ++mousePressEventCount; + mousePressPos = event->pos(); + } + + void mouseReleaseEvent(QMouseEvent *) + { + ++mouseReleaseEventCount; + } + + int focusInEventCount; + int focusOutEventCount; + int keyPressEventCount; + int keyReleaseEventCount; + int mousePressEventCount; + int mouseReleaseEventCount; + + QPoint mousePressPos; +}; + +class tst_WaylandClient : public QObject +{ + 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())); + } + +public slots: + void processWaylandEvents() + { + compositor->processWaylandEvents(); + } + +private slots: + void screen(); + void createDestroyWindow(); + void events(); + +private: + MockCompositor *compositor; +}; + +void tst_WaylandClient::screen() +{ + QTRY_COMPARE(QGuiApplication::primaryScreen()->size(), screenSize); +} + +void tst_WaylandClient::createDestroyWindow() +{ + TestWindow window; + window.show(); + + QTRY_VERIFY(compositor->surface()); + + window.destroy(); + QTRY_VERIFY(!compositor->surface()); +} + +void tst_WaylandClient::events() +{ + TestWindow window; + window.show(); + + QSharedPointer<MockSurface> surface; + QTRY_VERIFY(surface = compositor->surface()); + + QCOMPARE(window.focusInEventCount, 0); + compositor->setKeyboardFocus(surface); + QTRY_COMPARE(window.focusInEventCount, 1); + QTRY_COMPARE(QGuiApplication::focusWindow(), &window); + + QCOMPARE(window.focusOutEventCount, 0); + compositor->setKeyboardFocus(QSharedPointer<MockSurface>(0)); + QTRY_COMPARE(window.focusOutEventCount, 1); + QTRY_COMPARE(QGuiApplication::focusWindow(), static_cast<QWindow *>(0)); + + compositor->setKeyboardFocus(surface); + QTRY_COMPARE(window.focusInEventCount, 2); + QTRY_COMPARE(QGuiApplication::focusWindow(), &window); + + QPoint mousePressPos(16, 16); + QCOMPARE(window.mousePressEventCount, 0); + compositor->sendMousePress(surface, mousePressPos); + QTRY_COMPARE(window.mousePressEventCount, 1); + QTRY_COMPARE(window.mousePressPos, mousePressPos); + + QCOMPARE(window.mouseReleaseEventCount, 0); + compositor->sendMouseRelease(surface); + QTRY_COMPARE(window.mouseReleaseEventCount, 1); +} + +int main(int argc, char **argv) +{ + setenv("XDG_RUNTIME_DIR", ".", 1); + setenv("QT_QPA_PLATFORM", "wayland", 1); // force QGuiApplication to use wayland plugin + + MockCompositor compositor; + compositor.setOutputGeometry(QRect(QPoint(), screenSize)); + + QGuiApplication app(argc, argv); + compositor.applicationInitialized(); + + tst_WaylandClient tc(&compositor); + return QTest::qExec(&tc, argc, argv); +} + +#include <tst_client.moc> |