summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/wayland/custom-extension/compositor/qml/Screen.qml1
-rw-r--r--examples/wayland/minimal-cpp/compositor.cpp5
-rw-r--r--examples/wayland/minimal-qml/main.qml1
-rw-r--r--examples/wayland/multi-output/qml/GridScreen.qml1
-rw-r--r--examples/wayland/multi-output/qml/ShellScreen.qml1
-rw-r--r--examples/wayland/pure-qml/qml/Screen.qml1
-rw-r--r--examples/wayland/qwindow-compositor/compositor.cpp5
-rw-r--r--examples/wayland/server-buffer/compositor/main.cpp9
-rw-r--r--examples/wayland/spanning-screens/main.qml2
-rw-r--r--src/compositor/compositor_api/compositor_api.pri6
-rw-r--r--src/compositor/compositor_api/qwaylandoutput.cpp269
-rw-r--r--src/compositor/compositor_api/qwaylandoutput.h28
-rw-r--r--src/compositor/compositor_api/qwaylandoutput_p.h12
-rw-r--r--src/compositor/compositor_api/qwaylandoutputmode.cpp139
-rw-r--r--src/compositor/compositor_api/qwaylandoutputmode.h72
-rw-r--r--src/compositor/compositor_api/qwaylandoutputmode_p.h66
-rw-r--r--tests/auto/compositor/compositor/mockclient.cpp19
-rw-r--r--tests/auto/compositor/compositor/mockclient.h8
-rw-r--r--tests/auto/compositor/compositor/tst_compositor.cpp58
19 files changed, 565 insertions, 138 deletions
diff --git a/examples/wayland/custom-extension/compositor/qml/Screen.qml b/examples/wayland/custom-extension/compositor/qml/Screen.qml
index a6d5fbc7..7a87951b 100644
--- a/examples/wayland/custom-extension/compositor/qml/Screen.qml
+++ b/examples/wayland/custom-extension/compositor/qml/Screen.qml
@@ -45,6 +45,7 @@ import QtWayland.Compositor 1.0
WaylandOutput {
id: output
property alias surfaceArea: background
+ sizeFollowsWindow: true
window: Window {
id: screen
diff --git a/examples/wayland/minimal-cpp/compositor.cpp b/examples/wayland/minimal-cpp/compositor.cpp
index 5e46895c..5a6249c9 100644
--- a/examples/wayland/minimal-cpp/compositor.cpp
+++ b/examples/wayland/minimal-cpp/compositor.cpp
@@ -67,8 +67,11 @@ Compositor::~Compositor()
void Compositor::create()
{
- new QWaylandOutput(this, m_window);
+ QWaylandOutput *output = new QWaylandOutput(this, m_window);
+ QWaylandOutputMode mode(QSize(800, 600), 60000);
+ output->addMode(mode, true);
QWaylandCompositor::create();
+ output->setCurrentMode(mode);
connect(this, &QWaylandCompositor::surfaceCreated, this, &Compositor::onSurfaceCreated);
}
diff --git a/examples/wayland/minimal-qml/main.qml b/examples/wayland/minimal-qml/main.qml
index 3d6c3b7b..d44d0c6a 100644
--- a/examples/wayland/minimal-qml/main.qml
+++ b/examples/wayland/minimal-qml/main.qml
@@ -47,6 +47,7 @@ WaylandCompositor {
// The output defines the screen.
WaylandOutput {
compositor: wlcompositor
+ sizeFollowsWindow: true
window: Window {
width: 1024
height: 768
diff --git a/examples/wayland/multi-output/qml/GridScreen.qml b/examples/wayland/multi-output/qml/GridScreen.qml
index 3dab99d0..2a48cf16 100644
--- a/examples/wayland/multi-output/qml/GridScreen.qml
+++ b/examples/wayland/multi-output/qml/GridScreen.qml
@@ -46,6 +46,7 @@ WaylandOutput {
id: output
property alias gridSurfaces: listModel
+ sizeFollowsWindow: true
window: Window {
width: 1024
height: 760
diff --git a/examples/wayland/multi-output/qml/ShellScreen.qml b/examples/wayland/multi-output/qml/ShellScreen.qml
index 9a612211..7b8a48ff 100644
--- a/examples/wayland/multi-output/qml/ShellScreen.qml
+++ b/examples/wayland/multi-output/qml/ShellScreen.qml
@@ -46,6 +46,7 @@ WaylandOutput {
id: output
property alias surfaceArea: background
+ sizeFollowsWindow: true
window: Window {
width: 1024
height: 760
diff --git a/examples/wayland/pure-qml/qml/Screen.qml b/examples/wayland/pure-qml/qml/Screen.qml
index 0920a8b9..a12f387f 100644
--- a/examples/wayland/pure-qml/qml/Screen.qml
+++ b/examples/wayland/pure-qml/qml/Screen.qml
@@ -45,6 +45,7 @@ import QtWayland.Compositor 1.0
WaylandOutput {
id: output
property alias surfaceArea: background
+ sizeFollowsWindow: true
window: Window {
id: screen
diff --git a/examples/wayland/qwindow-compositor/compositor.cpp b/examples/wayland/qwindow-compositor/compositor.cpp
index a55bb3b7..4878c373 100644
--- a/examples/wayland/qwindow-compositor/compositor.cpp
+++ b/examples/wayland/qwindow-compositor/compositor.cpp
@@ -139,8 +139,11 @@ Compositor::~Compositor()
void Compositor::create()
{
- new QWaylandOutput(this, m_window);
+ QWaylandOutput *output = new QWaylandOutput(this, m_window);
+ QWaylandOutputMode mode(QSize(800, 600), 60000);
+ output->addMode(mode, true);
QWaylandCompositor::create();
+ output->setCurrentMode(mode);
connect(this, &QWaylandCompositor::surfaceCreated, this, &Compositor::onSurfaceCreated);
connect(defaultSeat(), &QWaylandSeat::cursorSurfaceRequest, this, &Compositor::adjustCursorSurface);
diff --git a/examples/wayland/server-buffer/compositor/main.cpp b/examples/wayland/server-buffer/compositor/main.cpp
index 9c5ee42a..8c43ce5c 100644
--- a/examples/wayland/server-buffer/compositor/main.cpp
+++ b/examples/wayland/server-buffer/compositor/main.cpp
@@ -86,15 +86,13 @@ public:
m_view.setColor(Qt::black);
m_view.create();
m_output = new QWaylandQuickOutput(this, &m_view);
+ m_output->setSizeFollowsWindow(true);
connect(&m_view, &QQuickView::afterRendering, this, &QmlCompositor::sendCallbacks);
connect(&m_view, &QQuickView::sceneGraphInitialized, this, &QmlCompositor::initiateServerBuffer,Qt::DirectConnection);
connect(this, &QmlCompositor::serverBuffersCreated, this, &QmlCompositor::createServerBufferItems);
- connect(&m_view, &QWindow::widthChanged, this, &QmlCompositor::sizeAdjusted);
- connect(&m_view, &QWindow::heightChanged, this, &QmlCompositor::sizeAdjusted);
-
connect(this, SIGNAL(windowAdded(QVariant)), m_view.rootObject(), SLOT(windowAdded(QVariant)));
connect(this, SIGNAL(windowResized(QVariant)), m_view.rootObject(), SLOT(windowResized(QVariant)));
connect(this, SIGNAL(serverBufferItemCreated(QVariant)), m_view.rootObject(), SLOT(serverBufferItemCreated(QVariant)));
@@ -211,11 +209,6 @@ private slots:
}
}
protected:
- void sizeAdjusted()
- {
- defaultOutput()->setGeometry(QRect(QPoint(0, 0), m_view.size()));
- }
-
void onSurfaceCreated(QWaylandSurface *surface) {
QWaylandQuickItem *item = new QWaylandQuickItem();
item->setSurface(surface);
diff --git a/examples/wayland/spanning-screens/main.qml b/examples/wayland/spanning-screens/main.qml
index 00bf517f..32dc11f3 100644
--- a/examples/wayland/spanning-screens/main.qml
+++ b/examples/wayland/spanning-screens/main.qml
@@ -47,6 +47,7 @@ WaylandCompositor {
WaylandOutput {
compositor: wlcompositor
+ sizeFollowsWindow: true
window: Window {
id: topSurfaceArea
width: 1024
@@ -59,6 +60,7 @@ WaylandCompositor {
WaylandOutput {
compositor: wlcompositor
+ sizeFollowsWindow: true
window: Window {
id: bottomSurfaceArea
width: 1024
diff --git a/src/compositor/compositor_api/compositor_api.pri b/src/compositor/compositor_api/compositor_api.pri
index 0f70773c..0253cd0e 100644
--- a/src/compositor/compositor_api/compositor_api.pri
+++ b/src/compositor/compositor_api/compositor_api.pri
@@ -17,6 +17,8 @@ HEADERS += \
compositor_api/qwaylandtouch.h \
compositor_api/qwaylandtouch_p.h \
compositor_api/qwaylandoutput.h \
+ compositor_api/qwaylandoutputmode.h \
+ compositor_api/qwaylandoutputmode_p.h \
compositor_api/qwaylanddrag.h \
compositor_api/qwaylandbufferref.h \
compositor_api/qwaylanddestroylistener.h \
@@ -26,7 +28,8 @@ HEADERS += \
compositor_api/qwaylandresource.h \
compositor_api/qwaylandsurfacegrabber.h \
compositor_api/qwaylandinputmethodcontrol.h \
- compositor_api/qwaylandinputmethodcontrol_p.h
+ compositor_api/qwaylandinputmethodcontrol_p.h \
+ compositor_api/qwaylandoutputmode_p.h
SOURCES += \
compositor_api/qwaylandcompositor.cpp \
@@ -38,6 +41,7 @@ SOURCES += \
compositor_api/qwaylandpointer.cpp \
compositor_api/qwaylandtouch.cpp \
compositor_api/qwaylandoutput.cpp \
+ compositor_api/qwaylandoutputmode.cpp \
compositor_api/qwaylanddrag.cpp \
compositor_api/qwaylandbufferref.cpp \
compositor_api/qwaylanddestroylistener.cpp \
diff --git a/src/compositor/compositor_api/qwaylandoutput.cpp b/src/compositor/compositor_api/qwaylandoutput.cpp
index 40cd9798..19e17bb3 100644
--- a/src/compositor/compositor_api/qwaylandoutput.cpp
+++ b/src/compositor/compositor_api/qwaylandoutput.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2014-2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** Copyright (C) 2014-2016 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB).
** Contact: http://www.qt.io/licensing/
**
@@ -48,6 +48,7 @@
#include <QtCore/QtMath>
#include <QtGui/QWindow>
#include <QtGui/QExposeEvent>
+#include <QtGui/QScreen>
#include <private/qobject_p.h>
QT_BEGIN_NAMESPACE
@@ -102,16 +103,14 @@ QWaylandOutputPrivate::QWaylandOutputPrivate()
: QtWaylandServer::wl_output()
, compositor(Q_NULLPTR)
, window(Q_NULLPTR)
+ , currentMode(-1)
+ , preferredMode(-1)
, subpixel(QWaylandOutput::SubpixelUnknown)
, transform(QWaylandOutput::TransformNormal)
, scaleFactor(1)
- , sizeFollowsWindow(true)
+ , sizeFollowsWindow(false)
, initialized(false)
{
- mode.size = QSize();
- mode.refreshRate = 60;
-
- qRegisterMetaType<QWaylandOutput::Mode>("WaylandOutput::Mode");
}
QWaylandOutputPrivate::~QWaylandOutputPrivate()
@@ -120,15 +119,10 @@ QWaylandOutputPrivate::~QWaylandOutputPrivate()
void QWaylandOutputPrivate::output_bind_resource(Resource *resource)
{
- send_geometry(resource->handle,
- position.x(), position.y(),
- physicalSize.width(), physicalSize.height(),
- toWlSubpixel(subpixel), manufacturer, model,
- toWlTransform(transform));
+ sendGeometry(resource);
- send_mode(resource->handle, mode_current | mode_preferred,
- mode.size.width(), mode.size.height(),
- mode.refreshRate * 1000);
+ for (const QWaylandOutputMode &mode : modes)
+ sendMode(resource, mode);
if (resource->version() >= 2) {
send_scale(resource->handle, scaleFactor);
@@ -136,19 +130,46 @@ void QWaylandOutputPrivate::output_bind_resource(Resource *resource)
}
}
+void QWaylandOutputPrivate::sendGeometry(const Resource *resource)
+{
+ send_geometry(resource->handle,
+ position.x(), position.y(),
+ physicalSize.width(), physicalSize.height(),
+ toWlSubpixel(subpixel), manufacturer, model,
+ toWlTransform(transform));
+}
+
void QWaylandOutputPrivate::sendGeometryInfo()
{
- Q_FOREACH (Resource *resource, resourceMap().values()) {
- send_geometry(resource->handle,
- position.x(), position.y(),
- physicalSize.width(), physicalSize.height(),
- toWlSubpixel(subpixel), manufacturer, model,
- toWlTransform(transform));
+ for (const Resource *resource : resourceMap().values()) {
+ sendGeometry(resource);
if (resource->version() >= 2)
send_done(resource->handle);
}
}
+void QWaylandOutputPrivate::sendMode(const Resource *resource, const QWaylandOutputMode &mode)
+{
+ quint32 flags = 0;
+ if (currentMode == modes.indexOf(mode))
+ flags |= QtWaylandServer::wl_output::mode_current;
+ if (preferredMode == modes.indexOf(mode))
+ flags |= QtWaylandServer::wl_output::mode_preferred;
+
+ send_mode(resource->handle, flags,
+ mode.size().width(), mode.size().height(),
+ mode.refreshRate());
+}
+
+void QWaylandOutputPrivate::sendModesInfo()
+{
+ for (const Resource *resource : resourceMap().values()) {
+ for (const QWaylandOutputMode &mode : modes)
+ sendMode(resource, mode);
+ if (resource->version() >= 2)
+ send_done(resource->handle);
+ }
+}
void QWaylandOutputPrivate::addView(QWaylandView *view, QWaylandSurface *surface)
{
@@ -252,16 +273,23 @@ void QWaylandOutput::initialize()
Q_ASSERT(d->compositor);
Q_ASSERT(d->compositor->isCreated());
- if (d->window)
- d->mode.size = d->window->size();
- else
- d->sizeFollowsWindow = false;
+ // Replace modes with one that follows the window size and refresh rate,
+ // but only if window size is valid
+ if (d->window && d->sizeFollowsWindow) {
+ QWaylandOutputMode mode(d->window->size(),
+ qFloor(d->window->screen()->refreshRate() * 1000));
+ if (mode.isValid()) {
+ d->modes.clear();
+ addMode(mode, true);
+ setCurrentMode(mode);
+ }
+ }
QWaylandCompositorPrivate::get(d->compositor)->addOutput(this);
if (d->window) {
- QObject::connect(d->window, &QWindow::widthChanged, this, &QWaylandOutput::setWidth);
- QObject::connect(d->window, &QWindow::heightChanged, this, &QWaylandOutput::setHeight);
+ QObject::connect(d->window, &QWindow::widthChanged, this, &QWaylandOutput::handleSetWidth);
+ QObject::connect(d->window, &QWindow::heightChanged, this, &QWaylandOutput::handleSetHeight);
QObject::connect(d->window, &QObject::destroyed, this, &QWaylandOutput::handleWindowDestroyed);
}
@@ -431,39 +459,75 @@ void QWaylandOutput::setPosition(const QPoint &pt)
}
/*!
- * \property QWaylandOutput::mode
- *
- * This property holds the output's size in pixels and refresh rate in Hz.
+ * Returns the list of modes.
*/
-QWaylandOutput::Mode QWaylandOutput::mode() const
+QList<QWaylandOutputMode> QWaylandOutput::modes() const
{
- return d_func()->mode;
+ Q_D(const QWaylandOutput);
+ return d->modes.toList();
}
-void QWaylandOutput::setMode(const Mode &mode)
+/*!
+ * Adds the mode \a mode to the output and mark it as preferred
+ * if \a preferred is \c true.
+ * Please note there can only be one preferred mode.
+ */
+void QWaylandOutput::addMode(const QWaylandOutputMode &mode, bool preferred)
{
Q_D(QWaylandOutput);
- if (d->mode.size == mode.size && d->mode.refreshRate == mode.refreshRate)
+
+ if (!mode.isValid()) {
+ qWarning("Cannot add an invalid mode");
return;
+ }
- d->mode = mode;
+ d->modes.append(mode);
- Q_FOREACH (QWaylandOutputPrivate::Resource *resource, d->resourceMap().values()) {
- d->send_mode(resource->handle, d->mode_current,
- d->mode.size.width(), d->mode.size.height(),
- d->mode.refreshRate * 1000);
- if (resource->version() >= 2)
- d->send_done(resource->handle);
+ if (preferred)
+ d->preferredMode = d->modes.indexOf(mode);
+
+ emit modeAdded();
+}
+
+/*!
+ * Returns the output's size in pixels and refresh rate in mHz.
+ * If the current mode is not set it will return an invalid mode.
+ *
+ * \sa QWaylandOutput::modes
+ * \sa QWaylandOutputMode
+ */
+QWaylandOutputMode QWaylandOutput::currentMode() const
+{
+ Q_D(const QWaylandOutput);
+
+ if (d->currentMode >= 0 && d->currentMode <= d->modes.size() - 1)
+ return d->modes.at(d->currentMode);
+ return QWaylandOutputMode();
+}
+
+/*!
+ * Sets the current mode.
+ * The mode \a mode must have been previously added.
+ *
+ * \sa QWaylandOutput::modes
+ * \sa QWaylandOutputMode
+ */
+void QWaylandOutput::setCurrentMode(const QWaylandOutputMode &mode)
+{
+ Q_D(QWaylandOutput);
+
+ int index = d->modes.indexOf(mode);
+ if (index < 0) {
+ qWarning("Cannot set an unknown QWaylandOutput mode as current");
+ return;
}
- Q_EMIT modeChanged();
+ d->currentMode = index;
+
+ Q_EMIT currentModeChanged();
Q_EMIT geometryChanged();
- if (d->window) {
- d->window->resize(mode.size);
- d->window->setMinimumSize(mode.size);
- d->window->setMaximumSize(mode.size);
- }
+ d->sendModesInfo();
}
/*!
@@ -477,37 +541,12 @@ void QWaylandOutput::setMode(const Mode &mode)
*
* This property holds the geometry of the QWaylandOutput.
*
- * \sa QWaylandOutput::mode
+ * \sa QWaylandOutput::currentMode
*/
QRect QWaylandOutput::geometry() const
{
Q_D(const QWaylandOutput);
- return QRect(d->position, d->mode.size);
-}
-
-void QWaylandOutput::setGeometry(const QRect &geometry)
-{
- Q_D(QWaylandOutput);
- if (d->position == geometry.topLeft() && d->mode.size == geometry.size())
- return;
-
- d->position = geometry.topLeft();
- d->mode.size = geometry.size();
-
- Q_FOREACH (QWaylandOutputPrivate::Resource *resource, d->resourceMap().values()) {
- d->send_geometry(resource->handle,
- d->position.x(), d->position.y(),
- d->physicalSize.width(), d->physicalSize.height(),
- toWlSubpixel(d->subpixel), d->manufacturer, d->model,
- toWlTransform(d->transform));
- d->send_mode(resource->handle, d->mode_current,
- d->mode.size.width(), d->mode.size.height(),
- d->mode.refreshRate * 1000);
- if (resource->version() >= 2)
- d->send_done(resource->handle);
- }
- Q_EMIT positionChanged();
- Q_EMIT modeChanged();
+ return QRect(d->position, currentMode().size());
}
/*!
@@ -527,13 +566,14 @@ void QWaylandOutput::setGeometry(const QRect &geometry)
* The available geometry is in output coordinates space, starts from 0,0 and it's as big
* as the output by default.
*
- * \sa QWaylandOutput::mode, QWaylandOutput::geometry
+ * \sa QWaylandOutput::currentMode, QWaylandOutput::geometry
*/
QRect QWaylandOutput::availableGeometry() const
{
Q_D(const QWaylandOutput);
+
if (!d->availableGeometry.isValid())
- return QRect(QPoint(0, 0), d->mode.size);
+ return QRect(QPoint(0, 0), currentMode().size());
return d->availableGeometry;
}
@@ -565,7 +605,7 @@ void QWaylandOutput::setAvailableGeometry(const QRect &availableGeometry)
*
* This property holds the physical size of the QWaylandOutput in millimeters.
*
- * \sa QWaylandOutput::geometry, QWaylandOutput::mode
+ * \sa QWaylandOutput::geometry, QWaylandOutput::currentMode
*/
QSize QWaylandOutput::physicalSize() const
{
@@ -755,7 +795,10 @@ void QWaylandOutput::setScaleFactor(int scale)
* This property controls whether the size of the WaylandOutput matches the
* size of its window.
*
- * The default is \c true if this WaylandOutput has a window.
+ * If this property is true, all modes previously added are replaced by a
+ * mode that matches window size and screen refresh rate.
+ *
+ * The default is false.
*/
/*!
@@ -764,7 +807,10 @@ void QWaylandOutput::setScaleFactor(int scale)
* This property controls whether the size of the QWaylandOutput matches the
* size of its window.
*
- * The default is \c true if this QWaylandOutput has a window.
+ * If this property is true, all modes previously added are replaced by a
+ * mode that matches window size and screen refresh rate.
+ *
+ * The default is false.
*/
bool QWaylandOutput::sizeFollowsWindow() const
{
@@ -781,13 +827,6 @@ void QWaylandOutput::setSizeFollowsWindow(bool follow)
}
if (follow != d->sizeFollowsWindow) {
- if (follow) {
- QObject::connect(d->window, &QWindow::widthChanged, this, &QWaylandOutput::setWidth);
- QObject::connect(d->window, &QWindow::heightChanged, this, &QWaylandOutput::setHeight);
- } else {
- QObject::disconnect(d->window, &QWindow::widthChanged, this, &QWaylandOutput::setWidth);
- QObject::disconnect(d->window, &QWindow::heightChanged, this, &QWaylandOutput::setHeight);
- }
d->sizeFollowsWindow = follow;
Q_EMIT sizeFollowsWindowChanged();
}
@@ -882,35 +921,63 @@ void QWaylandOutput::surfaceLeave(QWaylandSurface *surface)
}
/*!
- * Sets the width of this QWaylandOutput to \a newWidth.
- *
- * \sa setHeight, QWaylandOutput::geometry
+ * \internal
*/
-void QWaylandOutput::setWidth(int newWidth)
+void QWaylandOutput::handleSetWidth(int newWidth)
{
Q_D(QWaylandOutput);
- if (d->mode.size.width() == newWidth)
+
+ if (!d->window || !d->sizeFollowsWindow)
return;
- QSize s = d->mode.size;
- s.setWidth(newWidth);
- setGeometry(QRect(d->position, s));
+ if (d->currentMode <= d->modes.size() - 1) {
+ if (d->currentMode >= 0) {
+ QWaylandOutputMode mode = d->modes.at(d->currentMode);
+ mode.setWidth(newWidth);
+ d->modes.replace(d->currentMode, mode);
+ d->sendModesInfo();
+ } else {
+ // We didn't add a mode during the initialization because the window
+ // size was invalid, let's add it now
+ QWaylandOutputMode mode(d->window->size(),
+ qFloor(d->window->screen()->refreshRate() * 1000));
+ if (mode.isValid()) {
+ d->modes.clear();
+ addMode(mode, true);
+ setCurrentMode(mode);
+ }
+ }
+ }
}
/*!
- * Sets the height of this QWaylandOutput to \a newHeight.
- *
- * \sa setWidth, QWaylandOutput::geometry
+ * \internal
*/
-void QWaylandOutput::setHeight(int newHeight)
+void QWaylandOutput::handleSetHeight(int newHeight)
{
Q_D(QWaylandOutput);
- if (d->mode.size.height() == newHeight)
+
+ if (!d->window || !d->sizeFollowsWindow)
return;
- QSize s = d->mode.size;
- s.setHeight(newHeight);
- setGeometry(QRect(d->position, s));
+ if (d->currentMode <= d->modes.size() - 1) {
+ if (d->currentMode >= 0) {
+ QWaylandOutputMode mode = d->modes.at(d->currentMode);
+ mode.setHeight(newHeight);
+ d->modes.replace(d->currentMode, mode);
+ d->sendModesInfo();
+ } else {
+ // We didn't add a mode during the initialization because the window
+ // size was invalid, let's add it now
+ QWaylandOutputMode mode(d->window->size(),
+ qFloor(d->window->screen()->refreshRate() * 1000));
+ if (mode.isValid()) {
+ d->modes.clear();
+ addMode(mode, true);
+ setCurrentMode(mode);
+ }
+ }
+ }
}
/*!
diff --git a/src/compositor/compositor_api/qwaylandoutput.h b/src/compositor/compositor_api/qwaylandoutput.h
index e4cbb610..190231c1 100644
--- a/src/compositor/compositor_api/qwaylandoutput.h
+++ b/src/compositor/compositor_api/qwaylandoutput.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2014-2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** Copyright (C) 2014-2016 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB).
** Contact: http://www.qt.io/licensing/
**
@@ -39,6 +39,7 @@
#define QWAYLANDOUTPUT_H
#include <QtWaylandCompositor/qwaylandcompositorextension.h>
+#include <QtWaylandCompositor/QWaylandOutputMode>
#include <QtCore/QObject>
#include <QObject>
@@ -66,7 +67,6 @@ class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandOutput : public QWaylandObject
Q_PROPERTY(QString manufacturer READ manufacturer WRITE setManufacturer NOTIFY manufacturerChanged)
Q_PROPERTY(QString model READ model WRITE setModel NOTIFY modelChanged)
Q_PROPERTY(QPoint position READ position WRITE setPosition NOTIFY positionChanged)
- Q_PROPERTY(QWaylandOutput::Mode mode READ mode WRITE setMode NOTIFY modeChanged)
Q_PROPERTY(QRect geometry READ geometry NOTIFY geometryChanged)
Q_PROPERTY(QRect availableGeometry READ availableGeometry WRITE setAvailableGeometry NOTIFY availableGeometryChanged)
Q_PROPERTY(QSize physicalSize READ physicalSize WRITE setPhysicalSize NOTIFY physicalSizeChanged)
@@ -99,12 +99,6 @@ public:
};
Q_ENUM(Transform)
- struct Mode
- {
- QSize size;
- qreal refreshRate;
- };
-
QWaylandOutput();
QWaylandOutput(QWaylandCompositor *compositor, QWindow *window);
~QWaylandOutput();
@@ -127,13 +121,14 @@ public:
QPoint position() const;
void setPosition(const QPoint &pt);
- Mode mode() const;
- void setMode(const Mode &mode);
+ QList<QWaylandOutputMode> modes() const;
+
+ void addMode(const QWaylandOutputMode &mode, bool preferred = false);
+
+ QWaylandOutputMode currentMode() const;
+ void setCurrentMode(const QWaylandOutputMode &mode);
QRect geometry() const;
- void setGeometry(const QRect &geometry);
- void setWidth(int newWidth);
- void setHeight(int newHeight);
QRect availableGeometry() const;
void setAvailableGeometry(const QRect &availableGeometry);
@@ -169,7 +164,8 @@ Q_SIGNALS:
void windowChanged();
void positionChanged();
void geometryChanged();
- void modeChanged();
+ void modeAdded();
+ void currentModeChanged();
void availableGeometryChanged();
void physicalSizeChanged();
void scaleFactorChanged();
@@ -182,6 +178,8 @@ Q_SIGNALS:
void windowDestroyed();
private Q_SLOTS:
+ void handleSetWidth(int newWidth);
+ void handleSetHeight(int newHeight);
void handleWindowDestroyed();
protected:
@@ -192,6 +190,4 @@ protected:
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(QWaylandOutput::Mode)
-
#endif // QWAYLANDOUTPUT_H
diff --git a/src/compositor/compositor_api/qwaylandoutput_p.h b/src/compositor/compositor_api/qwaylandoutput_p.h
index 9b6ba907..ea8e7bcd 100644
--- a/src/compositor/compositor_api/qwaylandoutput_p.h
+++ b/src/compositor/compositor_api/qwaylandoutput_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2014-2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** Copyright (C) 2014-2016 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB).
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
@@ -102,19 +102,25 @@ public:
void addView(QWaylandView *view, QWaylandSurface *surface);
void removeView(QWaylandView *view, QWaylandSurface *surface);
+
+ void sendGeometry(const Resource *resource);
void sendGeometryInfo();
+ void sendMode(const Resource *resource, const QWaylandOutputMode &mode);
+ void sendModesInfo();
+
protected:
void output_bind_resource(Resource *resource) Q_DECL_OVERRIDE;
-
private:
QWaylandCompositor *compositor;
QWindow *window;
QString manufacturer;
QString model;
QPoint position;
- QWaylandOutput::Mode mode;
+ QVector<QWaylandOutputMode> modes;
+ int currentMode;
+ int preferredMode;
QRect availableGeometry;
QVector<QWaylandSurfaceViewMapper> surfaceViews;
QSize physicalSize;
diff --git a/src/compositor/compositor_api/qwaylandoutputmode.cpp b/src/compositor/compositor_api/qwaylandoutputmode.cpp
new file mode 100644
index 00000000..463b984a
--- /dev/null
+++ b/src/compositor/compositor_api/qwaylandoutputmode.cpp
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylandoutputmode.h"
+#include "qwaylandoutputmode_p.h"
+
+/*!
+ \class QWaylandOutputMode
+ \inmodule QtWaylandCompositor
+ \since 5.8
+ \brief The QWaylandOutputMode class holds the resolution and refresh rate of an output.
+
+ QWaylandOutputMode holds the resolution and refresh rate of an output.
+ Resolution is expressed in pixels and refresh rate is measured in mHz.
+
+ \sa QWaylandOutput
+*/
+
+QWaylandOutputMode::QWaylandOutputMode()
+ : d(new QWaylandOutputModePrivate)
+{
+}
+
+QWaylandOutputMode::QWaylandOutputMode(const QSize &size, int refreshRate)
+ : d(new QWaylandOutputModePrivate)
+{
+ d->size = size;
+ d->refreshRate = refreshRate;
+}
+
+QWaylandOutputMode::QWaylandOutputMode(const QWaylandOutputMode &other)
+ : d(new QWaylandOutputModePrivate)
+{
+ d->size = other.size();
+ d->refreshRate = other.refreshRate();
+}
+
+QWaylandOutputMode::~QWaylandOutputMode()
+{
+ delete d;
+}
+
+QWaylandOutputMode &QWaylandOutputMode::operator=(const QWaylandOutputMode &other)
+{
+ d->size = other.size();
+ d->refreshRate = other.refreshRate();
+ return *this;
+}
+
+/*!
+ Returns \c true if this mode is equal to \a other,
+ otherwise returns \c false.
+*/
+bool QWaylandOutputMode::operator==(const QWaylandOutputMode &other) const
+{
+ return size() == other.size() && refreshRate() == refreshRate();
+}
+
+/*!
+ Returns \c true if this mode is not equal to \a other,
+ otherwise returns \c false.
+*/
+bool QWaylandOutputMode::operator!=(const QWaylandOutputMode &other) const
+{
+ return size() != other.size() || refreshRate() != refreshRate();
+}
+
+/*!
+ Returns whether this mode contains a valid resolution and refresh rate.
+*/
+bool QWaylandOutputMode::isValid() const
+{
+ return !d->size.isEmpty() && d->refreshRate > 0;
+}
+
+/*!
+ Returns the resolution in pixels.
+*/
+QSize QWaylandOutputMode::size() const
+{
+ return d->size;
+}
+
+/*!
+ Returns the refresh rate in mHz.
+*/
+int QWaylandOutputMode::refreshRate() const
+{
+ return d->refreshRate;
+}
+
+/*!
+ * \internal
+ */
+void QWaylandOutputMode::setWidth(int width)
+{
+ d->size.setWidth(width);
+}
+
+/*!
+ * \internal
+ */
+void QWaylandOutputMode::setHeight(int height)
+{
+ d->size.setHeight(height);
+}
diff --git a/src/compositor/compositor_api/qwaylandoutputmode.h b/src/compositor/compositor_api/qwaylandoutputmode.h
new file mode 100644
index 00000000..4ef57f2e
--- /dev/null
+++ b/src/compositor/compositor_api/qwaylandoutputmode.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDOUTPUTMODE_H
+#define QWAYLANDOUTPUTMODE_H
+
+#include <QtWaylandCompositor/qwaylandexport.h>
+#include <QtCore/QSize>
+
+QT_BEGIN_NAMESPACE
+
+class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandOutputMode
+{
+public:
+ explicit QWaylandOutputMode();
+ QWaylandOutputMode(const QSize &size, int refreshRate);
+ QWaylandOutputMode(const QWaylandOutputMode &other);
+ ~QWaylandOutputMode();
+
+ QWaylandOutputMode &operator=(const QWaylandOutputMode &other);
+ bool operator==(const QWaylandOutputMode &other) const;
+ bool operator!=(const QWaylandOutputMode &other) const;
+
+ bool isValid() const;
+
+ QSize size() const;
+ int refreshRate() const;
+
+private:
+ class QWaylandOutputModePrivate *const d;
+ friend class QWaylandOutput;
+
+ void setWidth(int width);
+ void setHeight(int height);
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDOUTPUTMODE_H
diff --git a/src/compositor/compositor_api/qwaylandoutputmode_p.h b/src/compositor/compositor_api/qwaylandoutputmode_p.h
new file mode 100644
index 00000000..e9a0eaa3
--- /dev/null
+++ b/src/compositor/compositor_api/qwaylandoutputmode_p.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDOUTPUTMODE_P_H
+#define QWAYLANDOUTPUTMODE_P_H
+
+#include <QtWaylandCompositor/QWaylandOutput>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandOutputModePrivate
+{
+public:
+ QWaylandOutputModePrivate() {}
+
+ QSize size;
+ int refreshRate = 60000;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDOUTPUTMODE_P_H
diff --git a/tests/auto/compositor/compositor/mockclient.cpp b/tests/auto/compositor/compositor/mockclient.cpp
index f2fbc5de..da1096fb 100644
--- a/tests/auto/compositor/compositor/mockclient.cpp
+++ b/tests/auto/compositor/compositor/mockclient.cpp
@@ -52,6 +52,7 @@ MockClient::MockClient()
, wlshell(0)
, xdgShell(nullptr)
, iviApplication(nullptr)
+ , refreshRate(-1)
, error(0 /* means no error according to spec */)
, protocolError({0, 0, nullptr})
{
@@ -102,10 +103,22 @@ void MockClient::outputGeometryEvent(void *data, wl_output *,
resolve(data)->geometry.moveTopLeft(QPoint(x, y));
}
-void MockClient::outputModeEvent(void *data, wl_output *, uint32_t,
- int w, int h, int)
+void MockClient::outputModeEvent(void *data, wl_output *, uint32_t flags,
+ int w, int h, int refreshRate)
{
- resolve(data)->geometry.setSize(QSize(w, h));
+ QWaylandOutputMode mode(QSize(w, h), refreshRate);
+
+ if (flags & WL_OUTPUT_MODE_CURRENT) {
+ resolve(data)->geometry.setSize(QSize(w, h));
+ resolve(data)->resolution = QSize(w, h);
+ resolve(data)->refreshRate = refreshRate;
+ resolve(data)->currentMode = mode;
+ }
+
+ if (flags & WL_OUTPUT_MODE_PREFERRED)
+ resolve(data)->preferredMode = mode;
+
+ resolve(data)->modes.append(mode);
}
void MockClient::outputDone(void *, wl_output *)
diff --git a/tests/auto/compositor/compositor/mockclient.h b/tests/auto/compositor/compositor/mockclient.h
index ed9319af..1881393a 100644
--- a/tests/auto/compositor/compositor/mockclient.h
+++ b/tests/auto/compositor/compositor/mockclient.h
@@ -34,6 +34,7 @@
#include <QImage>
#include <QRect>
#include <QList>
+#include <QWaylandOutputMode>
class MockSeat;
@@ -73,6 +74,11 @@ public:
QList<MockSeat *> m_seats;
QRect geometry;
+ QSize resolution;
+ int refreshRate;
+ QWaylandOutputMode currentMode;
+ QWaylandOutputMode preferredMode;
+ QList<QWaylandOutputMode> modes;
int fd;
int error;
@@ -106,7 +112,7 @@ private:
uint32_t flags,
int width,
int height,
- int refresh);
+ int refreshRate);
static void outputDone(void *data, wl_output *output);
static void outputScale(void *data, wl_output *output, int factor);
diff --git a/tests/auto/compositor/compositor/tst_compositor.cpp b/tests/auto/compositor/compositor/tst_compositor.cpp
index 16aedd8e..393b9f5b 100644
--- a/tests/auto/compositor/compositor/tst_compositor.cpp
+++ b/tests/auto/compositor/compositor/tst_compositor.cpp
@@ -35,6 +35,7 @@
#include "qwaylandbufferref.h"
#include "qwaylandseat.h"
+#include <QtGui/QScreen>
#include <QtWaylandCompositor/QWaylandXdgShellV5>
#include <QtWaylandCompositor/QWaylandIviApplication>
#include <QtWaylandCompositor/QWaylandIviSurface>
@@ -58,6 +59,8 @@ private slots:
void singleClient();
void multipleClients();
void geometry();
+ void modes();
+ void sizeFollowsWindow();
void mapSurface();
void frameCallback();
@@ -202,12 +205,61 @@ void tst_WaylandCompositor::geometry()
TestCompositor compositor;
compositor.create();
- QRect geometry(0, 0, 4096, 3072);
- compositor.defaultOutput()->setGeometry(geometry);
+ QWaylandOutputMode mode(QSize(4096, 3072), 60000);
+ compositor.defaultOutput()->setPosition(QPoint(1024, 0));
+ compositor.defaultOutput()->addMode(mode, true);
+ compositor.defaultOutput()->setCurrentMode(mode);
MockClient client;
- QTRY_COMPARE(client.geometry, geometry);
+ QTRY_COMPARE(client.geometry, QRect(QPoint(1024, 0), QSize(4096, 3072)));
+ QTRY_COMPARE(client.resolution, QSize(4096, 3072));
+ QTRY_COMPARE(client.refreshRate, 60000);
+}
+
+void tst_WaylandCompositor::modes()
+{
+ TestCompositor compositor;
+ compositor.create();
+
+ // mode3 is current, mode4 is preferred
+ QWaylandOutputMode mode1(QSize(800, 600), 120000);
+ QWaylandOutputMode mode2(QSize(1024, 768), 100000);
+ QWaylandOutputMode mode3(QSize(1920, 1080), 60000);
+ QWaylandOutputMode mode4(QSize(2560, 1440), 59000);
+ compositor.defaultOutput()->addMode(mode1);
+ compositor.defaultOutput()->addMode(mode2, true);
+ compositor.defaultOutput()->addMode(mode3);
+ compositor.defaultOutput()->addMode(mode4, true);
+ compositor.defaultOutput()->setCurrentMode(mode3);
+
+ MockClient client;
+
+ QTRY_COMPARE(client.modes.size(), 4);
+ QTRY_COMPARE(client.currentMode, mode3);
+ QTRY_COMPARE(client.preferredMode, mode4);
+ QTRY_COMPARE(client.geometry, QRect(QPoint(0, 0), QSize(1920, 1080)));
+}
+
+void tst_WaylandCompositor::sizeFollowsWindow()
+{
+ TestCompositor compositor;
+
+ QWindow window;
+ window.resize(800, 600);
+
+ auto output = new QWaylandOutput(&compositor, &window);
+ output->setSizeFollowsWindow(true);
+
+ compositor.create();
+
+ QWaylandOutputMode mode(window.size(), qFloor(window.screen()->refreshRate() * 1000));
+
+ MockClient client;
+
+ QTRY_COMPARE(client.modes.size(), 1);
+ QTRY_COMPARE(client.currentMode, mode);
+ QTRY_COMPARE(client.preferredMode, mode);
}
void tst_WaylandCompositor::mapSurface()