summaryrefslogtreecommitdiffstats
path: root/tests/auto/client
diff options
context:
space:
mode:
authorSamuel Rødal <samuel.rodal@nokia.com>2012-03-06 10:29:45 +0100
committerJørgen Lind <jorgen.lind@nokia.com>2012-03-07 09:06:52 +0100
commit28f40671e8ec939ef451746925a9986ea596c616 (patch)
treebb76b07cf770b3ccfe5931dc9e3aa0b372f3f9d2 /tests/auto/client
parent394cb2f27df11afe009ba5bb05572bd41fc81228 (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.pro34
-rw-r--r--tests/auto/client/mockcompositor.cpp269
-rw-r--r--tests/auto/client/mockcompositor.h179
-rw-r--r--tests/auto/client/mockinput.cpp125
-rw-r--r--tests/auto/client/mockoutput.cpp81
-rw-r--r--tests/auto/client/mockshell.cpp159
-rw-r--r--tests/auto/client/mockshm.cpp100
-rw-r--r--tests/auto/client/mocksurface.cpp145
-rw-r--r--tests/auto/client/mocksurface.h67
-rw-r--r--tests/auto/client/tst_client.cpp195
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> &parameters);
+
+ QVector<Surface *> surfaces() const;
+
+ void addSurface(Surface *surface);
+ void removeSurface(Surface *surface);
+
+ static void setKeyboardFocus(void *data, const QList<QVariant> &parameters);
+ static void sendMousePress(void *data, const QList<QVariant> &parameters);
+ static void sendMouseRelease(void *data, const QList<QVariant> &parameters);
+
+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> &parameters);
+
+ 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> &parameters)
+{
+ 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> &parameters)
+{
+ 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> &parameters)
+{
+ 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> &parameters)
+{
+ 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>