Client: Test that the current screen is updated by surface events
Change-Id: If96691a2d844263a1e01a86df8b0d58f23848a4c Reviewed-by: Pier Luigi Fiorini <pierluigi.fiorini@liri.io>
This commit is contained in:
parent
7f8e7b4195
commit
679dc2e281
@ -137,7 +137,8 @@ public slots:
|
||||
}
|
||||
|
||||
private slots:
|
||||
void screen();
|
||||
void primaryScreen();
|
||||
void windowScreens();
|
||||
void createDestroyWindow();
|
||||
void events();
|
||||
void backingStore();
|
||||
@ -151,11 +152,49 @@ private:
|
||||
MockCompositor *compositor;
|
||||
};
|
||||
|
||||
void tst_WaylandClient::screen()
|
||||
void tst_WaylandClient::primaryScreen()
|
||||
{
|
||||
compositor->setOutputMode(screenSize);
|
||||
QTRY_COMPARE(QGuiApplication::primaryScreen()->size(), screenSize);
|
||||
}
|
||||
|
||||
void tst_WaylandClient::windowScreens()
|
||||
{
|
||||
QSharedPointer<MockOutput> firstOutput;
|
||||
QTRY_VERIFY(firstOutput = compositor->output());
|
||||
|
||||
TestWindow window;
|
||||
window.show();
|
||||
|
||||
QSharedPointer<MockSurface> surface;
|
||||
QTRY_VERIFY(surface = compositor->surface());
|
||||
QTRY_COMPARE(QGuiApplication::screens().size(), 1);
|
||||
QScreen *primaryScreen = QGuiApplication::screens().first();
|
||||
QCOMPARE(window.screen(), primaryScreen);
|
||||
|
||||
compositor->sendAddOutput();
|
||||
|
||||
QTRY_COMPARE(QGuiApplication::screens().size(), 2);
|
||||
QScreen *secondaryScreen = QGuiApplication::screens().at(1);
|
||||
QVERIFY(secondaryScreen);
|
||||
|
||||
window.setScreen(secondaryScreen);
|
||||
QCOMPARE(window.screen(), secondaryScreen);
|
||||
|
||||
QSharedPointer<MockOutput> secondOutput;
|
||||
QTRY_VERIFY(secondOutput = compositor->output(1));
|
||||
compositor->sendSurfaceEnter(surface, firstOutput);
|
||||
|
||||
compositor->sendSurfaceEnter(surface, secondOutput);
|
||||
QTRY_COMPARE(window.screen(), primaryScreen);
|
||||
|
||||
compositor->sendSurfaceLeave(surface, firstOutput);
|
||||
QTRY_COMPARE(window.screen(), secondaryScreen);
|
||||
|
||||
window.destroy();
|
||||
QTRY_VERIFY(!compositor->surface());
|
||||
}
|
||||
|
||||
void tst_WaylandClient::createDestroyWindow()
|
||||
{
|
||||
TestWindow window;
|
||||
@ -417,7 +456,7 @@ int main(int argc, char **argv)
|
||||
setenv("QT_WAYLAND_DISABLE_WINDOWDECORATION", "1", 1);
|
||||
|
||||
MockCompositor compositor;
|
||||
compositor.setOutputGeometry(QRect(QPoint(), screenSize));
|
||||
compositor.setOutputMode(screenSize);
|
||||
|
||||
QGuiApplication app(argc, argv);
|
||||
compositor.applicationInitialized();
|
||||
|
@ -28,6 +28,7 @@
|
||||
|
||||
#include "mockcompositor.h"
|
||||
#include "mockinput.h"
|
||||
#include "mockoutput.h"
|
||||
#include "mocksurface.h"
|
||||
|
||||
#include <wayland-xdg-shell-unstable-v6-server-protocol.h>
|
||||
@ -77,10 +78,10 @@ void MockCompositor::processWaylandEvents()
|
||||
m_waitCondition.wakeOne();
|
||||
}
|
||||
|
||||
void MockCompositor::setOutputGeometry(const QRect &rect)
|
||||
void MockCompositor::setOutputMode(const QSize &size)
|
||||
{
|
||||
Command command = makeCommand(Impl::Compositor::setOutputGeometry, m_compositor);
|
||||
command.parameters << rect;
|
||||
Command command = makeCommand(Impl::Compositor::setOutputMode, m_compositor);
|
||||
command.parameters << size;
|
||||
processCommand(command);
|
||||
}
|
||||
|
||||
@ -182,6 +183,28 @@ void MockCompositor::sendDataDeviceLeave(const QSharedPointer<MockSurface> &surf
|
||||
processCommand(command);
|
||||
}
|
||||
|
||||
void MockCompositor::sendAddOutput()
|
||||
{
|
||||
Command command = makeCommand(Impl::Compositor::sendAddOutput, m_compositor);
|
||||
processCommand(command);
|
||||
}
|
||||
|
||||
void MockCompositor::sendSurfaceEnter(const QSharedPointer<MockSurface> &surface, QSharedPointer<MockOutput> &output)
|
||||
{
|
||||
Command command = makeCommand(Impl::Compositor::sendSurfaceEnter, m_compositor);
|
||||
command.parameters << QVariant::fromValue(surface);
|
||||
command.parameters << QVariant::fromValue(output);
|
||||
processCommand(command);
|
||||
}
|
||||
|
||||
void MockCompositor::sendSurfaceLeave(const QSharedPointer<MockSurface> &surface, QSharedPointer<MockOutput> &output)
|
||||
{
|
||||
Command command = makeCommand(Impl::Compositor::sendSurfaceLeave, m_compositor);
|
||||
command.parameters << QVariant::fromValue(surface);
|
||||
command.parameters << QVariant::fromValue(output);
|
||||
processCommand(command);
|
||||
}
|
||||
|
||||
void MockCompositor::waitForStartDrag()
|
||||
{
|
||||
Command command = makeCommand(Impl::Compositor::waitForStartDrag, m_compositor);
|
||||
@ -204,6 +227,15 @@ QSharedPointer<MockSurface> MockCompositor::surface()
|
||||
return result;
|
||||
}
|
||||
|
||||
QSharedPointer<MockOutput> MockCompositor::output(int index)
|
||||
{
|
||||
QSharedPointer<MockOutput> result;
|
||||
lock();
|
||||
result = m_compositor->outputs().at(index)->mockOutput();
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
MockCompositor::Command MockCompositor::makeCommand(Command::Callback callback, void *target)
|
||||
{
|
||||
Command command;
|
||||
@ -267,8 +299,6 @@ namespace Impl {
|
||||
Compositor::Compositor()
|
||||
: m_display(wl_display_create())
|
||||
{
|
||||
wl_list_init(&m_outputResources);
|
||||
|
||||
if (wl_display_add_socket(m_display, 0)) {
|
||||
fprintf(stderr, "Fatal: Failed to open server socket\n");
|
||||
exit(EXIT_FAILURE);
|
||||
@ -285,7 +315,7 @@ Compositor::Compositor()
|
||||
m_keyboard = m_seat->keyboard();
|
||||
m_touch = m_seat->touch();
|
||||
|
||||
wl_global_create(m_display, &wl_output_interface, 1, this, bindOutput);
|
||||
m_outputs.append(new Output(m_display, QSize(1920, 1080), QPoint(0, 0)));
|
||||
wl_global_create(m_display, &wl_shell_interface, 1, this, bindShell);
|
||||
wl_global_create(m_display, &zxdg_shell_v6_interface, 1, this, bindXdgShellV6);
|
||||
|
||||
@ -350,6 +380,11 @@ QVector<Surface *> Compositor::surfaces() const
|
||||
return m_surfaces;
|
||||
}
|
||||
|
||||
QVector<Output *> Compositor::outputs() const
|
||||
{
|
||||
return m_outputs;
|
||||
}
|
||||
|
||||
uint32_t Compositor::nextSerial()
|
||||
{
|
||||
return wl_display_next_serial(m_display);
|
||||
@ -367,5 +402,17 @@ void Compositor::removeSurface(Surface *surface)
|
||||
m_pointer->handleSurfaceDestroyed(surface);
|
||||
}
|
||||
|
||||
Surface *Compositor::resolveSurface(const QVariant &v)
|
||||
{
|
||||
QSharedPointer<MockSurface> mockSurface = v.value<QSharedPointer<MockSurface> >();
|
||||
return mockSurface ? mockSurface->handle() : nullptr;
|
||||
}
|
||||
|
||||
Output *Compositor::resolveOutput(const QVariant &v)
|
||||
{
|
||||
QSharedPointer<MockOutput> mockOutput = v.value<QSharedPointer<MockOutput> >();
|
||||
return mockOutput ? mockOutput->handle() : nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -51,6 +51,7 @@ class Touch;
|
||||
class Seat;
|
||||
class DataDeviceManager;
|
||||
class Surface;
|
||||
class Output;
|
||||
|
||||
class Compositor
|
||||
{
|
||||
@ -64,9 +65,8 @@ public:
|
||||
uint32_t nextSerial();
|
||||
uint32_t time() { return ++m_time; }
|
||||
|
||||
static void setOutputGeometry(void *compositor, const QList<QVariant> ¶meters);
|
||||
|
||||
QVector<Surface *> surfaces() const;
|
||||
QVector<Output *> outputs() const;
|
||||
|
||||
void addSurface(Surface *surface);
|
||||
void removeSurface(Surface *surface);
|
||||
@ -86,21 +86,23 @@ public:
|
||||
static void sendDataDeviceDrop(void *data, const QList<QVariant> ¶meters);
|
||||
static void sendDataDeviceLeave(void *data, const QList<QVariant> ¶meters);
|
||||
static void waitForStartDrag(void *data, const QList<QVariant> ¶meters);
|
||||
static void setOutputMode(void *compositor, const QList<QVariant> ¶meters);
|
||||
static void sendAddOutput(void *data, const QList<QVariant> ¶meters);
|
||||
static void sendSurfaceEnter(void *data, const QList<QVariant> ¶meters);
|
||||
static void sendSurfaceLeave(void *data, const QList<QVariant> ¶meters);
|
||||
|
||||
public:
|
||||
bool m_startDragSeen = false;
|
||||
|
||||
private:
|
||||
static void bindCompositor(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 bindXdgShellV6(wl_client *client, void *compositorData, uint32_t version, uint32_t id);
|
||||
static Surface *resolveSurface(const QVariant &v);
|
||||
static Output *resolveOutput(const QVariant &v);
|
||||
|
||||
void initShm();
|
||||
|
||||
void sendOutputGeometry(wl_resource *resource);
|
||||
void sendOutputMode(wl_resource *resource);
|
||||
|
||||
QRect m_outputGeometry;
|
||||
|
||||
wl_display *m_display = nullptr;
|
||||
@ -108,7 +110,6 @@ private:
|
||||
wl_shm *m_shm = nullptr;
|
||||
int m_fd = -1;
|
||||
|
||||
wl_list m_outputResources;
|
||||
uint32_t m_time = 0;
|
||||
|
||||
QScopedPointer<Seat> m_seat;
|
||||
@ -117,6 +118,7 @@ private:
|
||||
Touch *m_touch = nullptr;
|
||||
QScopedPointer<DataDeviceManager> m_data_device_manager;
|
||||
QVector<Surface *> m_surfaces;
|
||||
QVector<Output *> m_outputs;
|
||||
};
|
||||
|
||||
void registerResource(wl_list *list, wl_resource *resource);
|
||||
@ -140,6 +142,16 @@ private:
|
||||
|
||||
Q_DECLARE_METATYPE(QSharedPointer<MockSurface>)
|
||||
|
||||
class MockOutput {
|
||||
public:
|
||||
Impl::Output *handle() const { return m_output; }
|
||||
MockOutput(Impl::Output *output);
|
||||
private:
|
||||
Impl::Output *m_output;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(QSharedPointer<MockOutput>)
|
||||
|
||||
class MockCompositor
|
||||
{
|
||||
public:
|
||||
@ -151,7 +163,7 @@ public:
|
||||
int waylandFileDescriptor() const;
|
||||
void processWaylandEvents();
|
||||
|
||||
void setOutputGeometry(const QRect &rect);
|
||||
void setOutputMode(const QSize &size);
|
||||
void setKeyboardFocus(const QSharedPointer<MockSurface> &surface);
|
||||
void sendMousePress(const QSharedPointer<MockSurface> &surface, const QPoint &pos);
|
||||
void sendMouseRelease(const QSharedPointer<MockSurface> &surface);
|
||||
@ -166,9 +178,13 @@ public:
|
||||
void sendDataDeviceMotion(const QPoint &position);
|
||||
void sendDataDeviceDrop(const QSharedPointer<MockSurface> &surface);
|
||||
void sendDataDeviceLeave(const QSharedPointer<MockSurface> &surface);
|
||||
void sendAddOutput();
|
||||
void sendSurfaceEnter(const QSharedPointer<MockSurface> &surface, QSharedPointer<MockOutput> &output);
|
||||
void sendSurfaceLeave(const QSharedPointer<MockSurface> &surface, QSharedPointer<MockOutput> &output);
|
||||
void waitForStartDrag();
|
||||
|
||||
QSharedPointer<MockSurface> surface();
|
||||
QSharedPointer<MockOutput> output(int index = 0);
|
||||
|
||||
void lock();
|
||||
void unlock();
|
||||
|
@ -32,12 +32,6 @@
|
||||
|
||||
namespace Impl {
|
||||
|
||||
static Surface *resolveSurface(const QVariant &v)
|
||||
{
|
||||
QSharedPointer<MockSurface> mockSurface = v.value<QSharedPointer<MockSurface> >();
|
||||
return mockSurface ? mockSurface->handle() : 0;
|
||||
}
|
||||
|
||||
void Compositor::setKeyboardFocus(void *data, const QList<QVariant> ¶meters)
|
||||
{
|
||||
Compositor *compositor = static_cast<Compositor *>(data);
|
||||
|
@ -27,41 +27,76 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "mockcompositor.h"
|
||||
#include "mockoutput.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
namespace Impl {
|
||||
|
||||
void Compositor::bindOutput(wl_client *client, void *compositorData, uint32_t version, uint32_t id)
|
||||
void Compositor::sendAddOutput(void *data, const QList<QVariant> ¶meters) {
|
||||
Q_UNUSED(parameters);
|
||||
Compositor *compositor = static_cast<Compositor *>(data);
|
||||
auto output = new Output(compositor->m_display, QSize(1920, 1200), QPoint(0, 0));
|
||||
compositor->m_outputs.append(output);
|
||||
|
||||
// Wait for the client to bind to the output
|
||||
while (output->resourceMap().isEmpty())
|
||||
compositor->dispatchEvents();
|
||||
}
|
||||
|
||||
void Compositor::setOutputMode(void *data, const QList<QVariant> ¶meters)
|
||||
{
|
||||
wl_resource *resource = wl_resource_create(client, &wl_output_interface, static_cast<int>(version), id);
|
||||
|
||||
Compositor *compositor = static_cast<Compositor *>(compositorData);
|
||||
registerResource(&compositor->m_outputResources, resource);
|
||||
|
||||
compositor->sendOutputGeometry(resource);
|
||||
compositor->sendOutputMode(resource);
|
||||
Compositor *compositor = static_cast<Compositor *>(data);
|
||||
QSize size = parameters.first().toSize();
|
||||
Output *output = compositor->m_outputs.first();
|
||||
Q_ASSERT(output);
|
||||
output->setCurrentMode(size);
|
||||
}
|
||||
|
||||
void Compositor::sendOutputGeometry(wl_resource *resource)
|
||||
Output::Output(wl_display *display, const QSize &resolution, const QPoint &position)
|
||||
: wl_output(display, 2)
|
||||
, m_size(resolution)
|
||||
, m_position(position)
|
||||
, m_physicalSize(520, 320)
|
||||
, m_mockOutput(new MockOutput(this))
|
||||
{
|
||||
const QRect &r = m_outputGeometry;
|
||||
wl_output_send_geometry(resource, r.x(), r.y(), r.width(), r.height(), 0, "", "",0);
|
||||
}
|
||||
|
||||
void Compositor::sendOutputMode(wl_resource *resource)
|
||||
void Output::setCurrentMode(const QSize &size)
|
||||
{
|
||||
const QRect &r = m_outputGeometry;
|
||||
wl_output_send_mode(resource, WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED, r.width(), r.height(), 60);
|
||||
qDebug() << Q_FUNC_INFO << size;
|
||||
m_size = size;
|
||||
for (Resource *resource : resourceMap())
|
||||
sendCurrentMode(resource);
|
||||
}
|
||||
|
||||
void Compositor::setOutputGeometry(void *c, const QList<QVariant> ¶meters)
|
||||
void Output::output_bind_resource(QtWaylandServer::wl_output::Resource *resource)
|
||||
{
|
||||
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);
|
||||
sendGeometry(resource);
|
||||
sendCurrentMode(resource);
|
||||
}
|
||||
|
||||
void Output::sendGeometry(Resource *resource)
|
||||
{
|
||||
const int subPixel = 0;
|
||||
const int transform = 0;
|
||||
|
||||
send_geometry(resource->handle,
|
||||
m_position.x(), m_position.y(),
|
||||
m_physicalSize.width(), m_physicalSize.height(),
|
||||
subPixel, "", "", transform );
|
||||
}
|
||||
|
||||
void Output::sendCurrentMode(Resource *resource)
|
||||
{
|
||||
send_mode(resource->handle,
|
||||
WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED,
|
||||
m_size.width(), m_size.height(), 60000);
|
||||
}
|
||||
|
||||
} // Impl
|
||||
|
||||
MockOutput::MockOutput(Impl::Output *output)
|
||||
: m_output(output)
|
||||
{
|
||||
}
|
||||
|
62
tests/auto/wayland/shared/mockoutput.h
Normal file
62
tests/auto/wayland/shared/mockoutput.h
Normal file
@ -0,0 +1,62 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2017 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the test suite of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef MOCKOUTPUT_H
|
||||
#define MOCKOUTPUT_H
|
||||
|
||||
#include <qglobal.h>
|
||||
|
||||
#include "qwayland-server-wayland.h"
|
||||
|
||||
#include "mockcompositor.h"
|
||||
|
||||
namespace Impl {
|
||||
|
||||
class Output : public QtWaylandServer::wl_output
|
||||
{
|
||||
public:
|
||||
Output(::wl_display *display, const QSize &resolution, const QPoint &position);
|
||||
|
||||
QSharedPointer<MockOutput> mockOutput() const { return m_mockOutput; }
|
||||
void setCurrentMode(const QSize &size);
|
||||
|
||||
protected:
|
||||
void output_bind_resource(Resource *resource) override;
|
||||
|
||||
private:
|
||||
void sendGeometry(Resource *resource);
|
||||
void sendCurrentMode(Resource *resource);
|
||||
QSize m_size;
|
||||
QPoint m_position;
|
||||
const QSize m_physicalSize;
|
||||
QSharedPointer<MockOutput> m_mockOutput;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // MOCKOUTPUT_H
|
@ -27,10 +27,39 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "mocksurface.h"
|
||||
#include "mockoutput.h"
|
||||
#include "mockcompositor.h"
|
||||
|
||||
namespace Impl {
|
||||
|
||||
void Compositor::sendSurfaceEnter(void *data, const QList<QVariant> ¶meters)
|
||||
{
|
||||
Q_UNUSED(data);
|
||||
Surface *surface = resolveSurface(parameters.at(0));
|
||||
Output *output = resolveOutput(parameters.at(1));
|
||||
Q_ASSERT(surface && surface->resource());
|
||||
Q_ASSERT(output);
|
||||
auto outputResources = output->resourceMap().values(surface->resource()->client());
|
||||
Q_ASSERT(!outputResources.isEmpty());
|
||||
|
||||
for (auto outputResource : outputResources)
|
||||
surface->send_enter(outputResource->handle);
|
||||
}
|
||||
|
||||
void Compositor::sendSurfaceLeave(void *data, const QList<QVariant> ¶meters)
|
||||
{
|
||||
Q_UNUSED(data);
|
||||
Surface *surface = resolveSurface(parameters.at(0));
|
||||
Output *output = resolveOutput(parameters.at(1));
|
||||
Q_ASSERT(surface && surface->resource());
|
||||
Q_ASSERT(output);
|
||||
auto outputResources = output->resourceMap().values(surface->resource()->client());
|
||||
Q_ASSERT(!outputResources.isEmpty());
|
||||
|
||||
for (auto outputResource : outputResources)
|
||||
surface->send_leave(outputResource->handle);
|
||||
}
|
||||
|
||||
Surface::Surface(wl_client *client, uint32_t id, int v, Compositor *compositor)
|
||||
: QtWaylandServer::wl_surface(client, id, v)
|
||||
, m_buffer(nullptr)
|
||||
|
@ -21,4 +21,5 @@ SOURCES += \
|
||||
HEADERS += \
|
||||
../shared/mockcompositor.h \
|
||||
../shared/mockinput.h \
|
||||
../shared/mocksurface.h
|
||||
../shared/mocksurface.h \
|
||||
../shared/mockoutput.h
|
||||
|
@ -108,7 +108,7 @@ int main(int argc, char **argv)
|
||||
setenv("QT_WAYLAND_DISABLE_WINDOWDECORATION", "1", 1);
|
||||
|
||||
MockCompositor compositor;
|
||||
compositor.setOutputGeometry(QRect(QPoint(), screenSize));
|
||||
compositor.setOutputMode(screenSize);
|
||||
|
||||
QGuiApplication app(argc, argv);
|
||||
compositor.applicationInitialized();
|
||||
|
Loading…
x
Reference in New Issue
Block a user