diff options
20 files changed, 1228 insertions, 7 deletions
diff --git a/examples/wayland/multi-output/qml/GridScreen.qml b/examples/wayland/multi-output/qml/GridScreen.qml index 340291afd..a59cb8fb4 100644 --- a/examples/wayland/multi-output/qml/GridScreen.qml +++ b/examples/wayland/multi-output/qml/GridScreen.qml @@ -50,7 +50,7 @@ import QtQuick 2.0 import QtQuick.Window 2.2 -import QtWayland.Compositor 1.0 +import QtWayland.Compositor 1.14 WaylandOutput { id: output @@ -93,4 +93,12 @@ WaylandOutput { } } } + + XdgOutputV1 { + name: "WL-2" + description: "Overview screen" + logicalPosition: output.position + logicalSize: Qt.size(output.geometry.width / output.scaleFactor, + output.geometry.height / output.scaleFactor) + } } diff --git a/examples/wayland/multi-output/qml/ShellScreen.qml b/examples/wayland/multi-output/qml/ShellScreen.qml index 4482e6e85..aa9b4b29b 100644 --- a/examples/wayland/multi-output/qml/ShellScreen.qml +++ b/examples/wayland/multi-output/qml/ShellScreen.qml @@ -50,7 +50,7 @@ import QtQuick 2.0 import QtQuick.Window 2.2 -import QtWayland.Compositor 1.0 +import QtWayland.Compositor 1.14 WaylandOutput { id: output @@ -84,4 +84,12 @@ WaylandOutput { } } } + + XdgOutputV1 { + name: "WL-1" + description: "Screen with window management" + logicalPosition: output.position + logicalSize: Qt.size(output.geometry.width / output.scaleFactor, + output.geometry.height / output.scaleFactor) + } } diff --git a/examples/wayland/multi-output/qml/main.qml b/examples/wayland/multi-output/qml/main.qml index d01def55e..45f91fd66 100644 --- a/examples/wayland/multi-output/qml/main.qml +++ b/examples/wayland/multi-output/qml/main.qml @@ -49,7 +49,7 @@ ****************************************************************************/ import QtQuick 2.0 -import QtWayland.Compositor 1.0 +import QtWayland.Compositor 1.14 WaylandCompositor { id: comp @@ -91,6 +91,8 @@ WaylandCompositor { } } + XdgOutputManagerV1 {} + WlShell { id: defaultShell diff --git a/src/3rdparty/protocol/qt_attribution.json b/src/3rdparty/protocol/qt_attribution.json index e6f90698b..c49ead4f3 100644 --- a/src/3rdparty/protocol/qt_attribution.json +++ b/src/3rdparty/protocol/qt_attribution.json @@ -127,8 +127,9 @@ Copyright (c) 2013 BMW Car IT GmbH" "Id": "wayland-xdg-output-protocol", "Name": "Wayland XDG Output Protocol", "QDocModule": "qtwaylandcompositor", - "QtUsage": "Used in the Qt Wayland platform plugin.", + "QtUsage": "Used in the Qt Wayland Compositor API, and the Qt Wayland platform plugin.", "Files": "xdg-output-unstable-v1.xml", + "Description": "The XDG Output protocol is an extended way to describe output regions under Wayland", "Homepage": "https://wayland.freedesktop.org", "Version": "unstable v1, version 2", diff --git a/src/compositor/compositor_api/qwaylandoutput.cpp b/src/compositor/compositor_api/qwaylandoutput.cpp index 7a02d4caa..601f692af 100644 --- a/src/compositor/compositor_api/qwaylandoutput.cpp +++ b/src/compositor/compositor_api/qwaylandoutput.cpp @@ -48,6 +48,7 @@ #include <QtWaylandCompositor/private/qwaylandcompositor_p.h> #include <QtWaylandCompositor/private/qwaylandview_p.h> #include <QtWaylandCompositor/private/qwaylandutils_p.h> +#include <QtWaylandCompositor/private/qwaylandxdgoutputv1_p.h> #include <QtCore/QCoreApplication> #include <QtCore/QtMath> @@ -162,6 +163,9 @@ void QWaylandOutputPrivate::sendGeometryInfo() if (resource->version() >= 2) send_done(resource->handle); } + + if (xdgOutput) + QWaylandXdgOutputV1Private::get(xdgOutput)->sendDone(); } void QWaylandOutputPrivate::sendMode(const Resource *resource, const QWaylandOutputMode &mode) @@ -185,6 +189,9 @@ void QWaylandOutputPrivate::sendModesInfo() if (resource->version() >= 2) send_done(resource->handle); } + + if (xdgOutput) + QWaylandXdgOutputV1Private::get(xdgOutput)->sendDone(); } void QWaylandOutputPrivate::handleWindowPixelSizeChanged() @@ -840,6 +847,9 @@ void QWaylandOutput::setScaleFactor(int scale) } Q_EMIT scaleFactorChanged(); + + if (d->xdgOutput) + QWaylandXdgOutputV1Private::get(d->xdgOutput)->sendDone(); } /*! diff --git a/src/compositor/compositor_api/qwaylandoutput_p.h b/src/compositor/compositor_api/qwaylandoutput_p.h index 4badd3797..58188ac38 100644 --- a/src/compositor/compositor_api/qwaylandoutput_p.h +++ b/src/compositor/compositor_api/qwaylandoutput_p.h @@ -57,6 +57,7 @@ #include <QtWaylandCompositor/QWaylandOutput> #include <QtWaylandCompositor/QWaylandClient> #include <QtWaylandCompositor/QWaylandSurface> +#include <QtWaylandCompositor/QWaylandXdgOutputV1> #include <QtWaylandCompositor/private/qwayland-server-wayland.h> @@ -110,6 +111,8 @@ public: void handleWindowPixelSizeChanged(); + QPointer<QWaylandXdgOutputV1> xdgOutput; + protected: void output_bind_resource(Resource *resource) override; @@ -137,6 +140,8 @@ private: Q_DECLARE_PUBLIC(QWaylandOutput) Q_DISABLE_COPY(QWaylandOutputPrivate) + + friend class QWaylandXdgOutputManagerV1Private; }; diff --git a/src/compositor/extensions/extensions.pri b/src/compositor/extensions/extensions.pri index c1a9f7882..61ab043ea 100644 --- a/src/compositor/extensions/extensions.pri +++ b/src/compositor/extensions/extensions.pri @@ -14,6 +14,7 @@ WAYLANDSERVERSOURCES += \ ../3rdparty/protocol/xdg-shell-unstable-v6.xml \ ../3rdparty/protocol/xdg-shell.xml \ ../3rdparty/protocol/xdg-decoration-unstable-v1.xml \ + ../3rdparty/protocol/xdg-output-unstable-v1.xml \ ../3rdparty/protocol/ivi-application.xml \ ../3rdparty/protocol/idle-inhibit-unstable-v1.xml \ @@ -42,6 +43,8 @@ HEADERS += \ extensions/qwaylandxdgshell_p.h \ extensions/qwaylandxdgdecorationv1.h \ extensions/qwaylandxdgdecorationv1_p.h \ + extensions/qwaylandxdgoutputv1.h \ + extensions/qwaylandxdgoutputv1_p.h \ extensions/qwaylandshellsurface.h \ extensions/qwaylandidleinhibitv1.h \ extensions/qwaylandidleinhibitv1_p.h \ @@ -64,6 +67,7 @@ SOURCES += \ extensions/qwaylandxdgshellv6.cpp \ extensions/qwaylandxdgshell.cpp \ extensions/qwaylandxdgdecorationv1.cpp \ + extensions/qwaylandxdgoutputv1.cpp \ extensions/qwaylandshellsurface.cpp \ extensions/qwaylandidleinhibitv1.cpp \ extensions/qwaylandiviapplication.cpp \ @@ -76,6 +80,7 @@ qtHaveModule(quick) { extensions/qwaylandquickshellsurfaceitem_p.h \ extensions/qwaylandivisurfaceintegration_p.h \ extensions/qwaylandwlshellintegration_p.h \ + extensions/qwaylandquickxdgoutputv1.h \ extensions/qwaylandxdgshellv5integration_p.h \ extensions/qwaylandxdgshellv6integration_p.h \ extensions/qwaylandxdgshellintegration_p.h \ @@ -85,6 +90,7 @@ qtHaveModule(quick) { extensions/qwaylandquickshellsurfaceitem.cpp \ extensions/qwaylandivisurfaceintegration.cpp \ extensions/qwaylandwlshellintegration.cpp \ + extensions/qwaylandquickxdgoutputv1.cpp \ extensions/qwaylandxdgshellv5integration.cpp \ extensions/qwaylandxdgshellv6integration.cpp \ extensions/qwaylandxdgshellintegration.cpp \ diff --git a/src/compositor/extensions/qwaylandquickxdgoutputv1.cpp b/src/compositor/extensions/qwaylandquickxdgoutputv1.cpp new file mode 100644 index 000000000..eb6717a78 --- /dev/null +++ b/src/compositor/extensions/qwaylandquickxdgoutputv1.cpp @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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 <QWaylandCompositor> +#include <QWaylandOutput> + +#include "qwaylandquickxdgoutputv1.h" +#include "qwaylandxdgoutputv1_p.h" + +QWaylandQuickXdgOutputV1::QWaylandQuickXdgOutputV1() + : QWaylandXdgOutputV1() +{ +} + +void QWaylandQuickXdgOutputV1::componentComplete() +{ + // Try to find the manager from the compositor extensions + if (!manager()) { + for (auto *p = parent(); p != nullptr; p = p->parent()) { + if (auto *c = qobject_cast<QWaylandCompositor *>(p)) { + for (auto *extension : c->extensions()) { + if (auto *m = qobject_cast<QWaylandXdgOutputManagerV1 *>(extension)) { + QWaylandXdgOutputV1Private::get(this)->setManager(m); + break; + } + } + } + } + } + + // Try to find the output from the parents + if (!output()) { + for (auto *p = parent(); p != nullptr; p = p->parent()) { + if (auto *o = qobject_cast<QWaylandOutput *>(p)) { + QWaylandXdgOutputV1Private::get(this)->setOutput(o); + break; + } + } + } +} diff --git a/src/compositor/extensions/qwaylandquickxdgoutputv1.h b/src/compositor/extensions/qwaylandquickxdgoutputv1.h new file mode 100644 index 000000000..c8b16ab8e --- /dev/null +++ b/src/compositor/extensions/qwaylandquickxdgoutputv1.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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 QWAYLANDQUICKXDGOUTPUT_V1 +#define QWAYLANDQUICKXDGOUTPUT_V1 + +#include <QtQml/QQmlListProperty> +#include <QtQml/QQmlParserStatus> +#include <QtWaylandCompositor/QWaylandXdgOutputV1> + +QT_BEGIN_NAMESPACE + +class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandQuickXdgOutputV1 + : public QWaylandXdgOutputV1 + , public QQmlParserStatus +{ + Q_OBJECT + Q_INTERFACES(QQmlParserStatus) +public: + explicit QWaylandQuickXdgOutputV1(); + +protected: + void classBegin() override {} + void componentComplete() override; +}; + +QT_END_NAMESPACE + +#endif // QWAYLANDQUICKXDGOUTPUT_V1 diff --git a/src/compositor/extensions/qwaylandxdgoutputv1.cpp b/src/compositor/extensions/qwaylandxdgoutputv1.cpp new file mode 100644 index 000000000..2ab26c162 --- /dev/null +++ b/src/compositor/extensions/qwaylandxdgoutputv1.cpp @@ -0,0 +1,595 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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 <QWaylandCompositor> + +#include "qwaylandxdgoutputv1_p.h" +#include "qwaylandoutput_p.h" + +#include <wayland-server.h> + +QT_BEGIN_NAMESPACE + +/*! + * \qmltype XdgOutputManagerV1 + * \inqmlmodule QtWayland.Compositor + * \since 5.14 + * \brief Provides an extension for describing outputs in a desktop oriented fashion + * + * The XdgOutputManagerV1 extension provides a way for a compositor to describe outputs in a way + * that is more in line with the concept of an output on desktop oriented systems. + * + * Some information may not make sense in other applications such as IVI systems. + * + * Typically the global compositor space on a desktop system is made of a + * contiguous or overlapping set of rectangular regions. + * + * XdgOutputManagerV1 corresponds to the Wayland interface, \c zxdg_output_manager_v1. + * + * To provide the functionality of the extension in a compositor, create an instance of the + * XdgOutputManagerV1 component and add it to the list of extensions supported by the compositor, + * and associated each XdgOutputV1 with its WaylandOutput: + * + * \qml \QtMinorVersion + * import QtWayland.Compositor 1.\1 + * + * WaylandCompositor { + * XdgOutputManagerV1 { + * WaylandOutput { + * id: output1 + * + * position: Qt.point(0, 0) + * window: Window {} + * + * XdgOutputV1 { + * name: "WL-1" + * logicalPosition: output1.position + * logicalSize: Qt.size(output1.geometry.width / output1.scaleFactor, + * output1.geometry.height / output1.scaleFactor) + * } + * } + * + * WaylandOutput { + * id: output2 + * + * position: Qt.point(800, 0) + * window: Window {} + * + * XdgOutputV1 { + * name: "WL-2" + * logicalPosition: output2.position + * logicalSize: Qt.size(output2.geometry.width / output2.scaleFactor, + * output2.geometry.height / output2.scaleFactor) + * } + * } + * } + * } + * \endqml + */ + +/*! + * \class QWaylandXdgOutputManagerV1 + * \inmodule QtWaylandCompositor + * \since 5.14 + * \brief Provides an extension for describing outputs in a desktop oriented fashion + * + * The QWaylandXdgOutputManagerV1 extension provides a way for a compositor to describe outputs in a way + * that is more in line with the concept of an output on desktop oriented systems. + * + * Some information may not make sense in other applications such as IVI systems. + * + * QWaylandXdgOutputManagerV1 corresponds to the Wayland interface, \c zxdg_output_manager_v1. + */ + +/*! + * Constructs a QWaylandXdgOutputManagerV1 object. + */ +QWaylandXdgOutputManagerV1::QWaylandXdgOutputManagerV1() + : QWaylandCompositorExtensionTemplate<QWaylandXdgOutputManagerV1>(*new QWaylandXdgOutputManagerV1Private()) +{ +} + +/*! + * Constructs a QWaylandXdgOutputManagerV1 object for the provided \a compositor. + */ +QWaylandXdgOutputManagerV1::QWaylandXdgOutputManagerV1(QWaylandCompositor *compositor) + : QWaylandCompositorExtensionTemplate<QWaylandXdgOutputManagerV1>(compositor, *new QWaylandXdgOutputManagerV1Private()) +{ +} + +// QWaylandXdgOutputManagerV1Private + +/*! + * Initializes the extension. + */ +void QWaylandXdgOutputManagerV1::initialize() +{ + Q_D(QWaylandXdgOutputManagerV1); + + QWaylandCompositorExtensionTemplate::initialize(); + QWaylandCompositor *compositor = static_cast<QWaylandCompositor *>(extensionContainer()); + if (!compositor) { + qCWarning(qLcWaylandCompositor) << "Failed to find QWaylandCompositor when initializing QWaylandXdgOutputManagerV1"; + return; + } + d->init(compositor->display(), d->interfaceVersion()); +} + +/*! + * Returns the Wayland interface for QWaylandXdgOutputManagerV1. + */ +const wl_interface *QWaylandXdgOutputManagerV1::interface() +{ + return QWaylandXdgOutputManagerV1Private::interface(); +} + +// QWaylandXdgOutputManagerV1Private + +void QWaylandXdgOutputManagerV1Private::registerXdgOutput(QWaylandOutput *output, QWaylandXdgOutputV1 *xdgOutput) +{ + if (!xdgOutputs.contains(output)) { + xdgOutputs[output] = xdgOutput; + QWaylandOutputPrivate::get(output)->xdgOutput = xdgOutput; + } +} + +void QWaylandXdgOutputManagerV1Private::unregisterXdgOutput(QWaylandOutput *output) +{ + xdgOutputs.remove(output); +} + +void QWaylandXdgOutputManagerV1Private::zxdg_output_manager_v1_get_xdg_output(Resource *resource, + uint32_t id, + wl_resource *outputResource) +{ + Q_Q(QWaylandXdgOutputManagerV1); + + // Verify if the associated output exist + auto *output = QWaylandOutput::fromResource(outputResource); + if (!output) { + qCWarning(qLcWaylandCompositor, + "The client is requesting a QWaylandXdgOutputV1 for a " + "QWaylandOutput that doesn't exist"); + wl_resource_post_error(resource->handle, WL_DISPLAY_ERROR_INVALID_OBJECT, "output not found"); + return; + } + + // Do we have a QWaylandXdgOutputV1 for this output? + if (!xdgOutputs.contains(output)) { + qCWarning(qLcWaylandCompositor, + "The client is requesting a QWaylandXdgOutputV1 that the compositor " + "didn't create before"); + wl_resource_post_error(resource->handle, WL_DISPLAY_ERROR_INVALID_OBJECT, + "compositor didn't create a QWaylandXdgOutputV1 for this zxdg_output_v1 object"); + return; + } + + // Bind QWaylandXdgOutputV1 and initialize + auto *xdgOutput = xdgOutputs[output]; + auto *xdgOutputPrivate = QWaylandXdgOutputV1Private::get(xdgOutput); + Q_ASSERT(xdgOutputPrivate); + xdgOutputPrivate->setManager(q); + xdgOutputPrivate->setOutput(output); + xdgOutputPrivate->add(resource->client(), id, qMin(resource->version(), QWaylandXdgOutputV1Private::interfaceVersion())); +} + +// QWaylandXdgOutputV1 + +QWaylandXdgOutputV1::QWaylandXdgOutputV1() + : QObject(*new QWaylandXdgOutputV1Private) +{ +} + +QWaylandXdgOutputV1::QWaylandXdgOutputV1(QWaylandOutput *output, QWaylandXdgOutputManagerV1 *manager) + : QObject(*new QWaylandXdgOutputV1Private) +{ + Q_D(QWaylandXdgOutputV1); + + // Set members before emitting changed signals so that handlers will + // see both already set and not nullptr, avoiding potential crashes + d->manager = manager; + d->output = output; + + QWaylandXdgOutputManagerV1Private::get(d->manager)->registerXdgOutput(output, this); + + emit managerChanged(); + emit outputChanged(); +} + +QWaylandXdgOutputV1::~QWaylandXdgOutputV1() +{ + Q_D(QWaylandXdgOutputV1); + + if (d->manager) + QWaylandXdgOutputManagerV1Private::get(d->manager)->unregisterXdgOutput(d->output); +} + +/*! + * \qmlproperty XdgOutputManagerV1 QtWaylandCompositor::XdgOutputV1::manager + * \readonly + * + * This property holds the object that manages this XdgOutputV1. + */ +/*! + * \property QWaylandXdgOutputV1::manager + * \readonly + * + * This property holds the object that manages this QWaylandXdgOutputV1. + */ +QWaylandXdgOutputManagerV1 *QWaylandXdgOutputV1::manager() const +{ + Q_D(const QWaylandXdgOutputV1); + return d->manager; +} + +/*! + * \qmlproperty WaylandOutput QtWaylandCompositor::XdgOutputV1::output + * \readonly + * + * This property holds the WaylandOutput associated with this XdgOutputV1. + */ +/*! + * \property QWaylandXdgOutputV1::output + * \readonly + * + * This property holds the QWaylandOutput associated with this QWaylandXdgOutputV1. + */ +QWaylandOutput *QWaylandXdgOutputV1::output() const +{ + Q_D(const QWaylandXdgOutputV1); + return d->output; +} + +/*! + * \qmlproperty string QtWaylandCompositor::XdgOutputV1::name + * + * This property holds the name of this output. + * + * The naming convention is compositor defined, but limited to alphanumeric + * characters and dashes ("-"). Each name is unique and will also remain + * consistent across sessions with the same hardware and software configuration. + * + * Examples of names include "HDMI-A-1", "WL-1", "X11-1" etc... + * However don't assume the name reflects the underlying technology. + * + * Changing this property after initialization doesn't take effect. + */ +/*! + * \property QWaylandXdgOutputV1::name + * + * This property holds the name of this output. + * + * The naming convention is compositor defined, but limited to alphanumeric + * characters and dashes ("-"). Each name is unique and will also remain + * consistent across sessions with the same hardware and software configuration. + * + * Examples of names include "HDMI-A-1", "WL-1", "X11-1" etc... + * However don't assume the name reflects the underlying technology. + * + * Changing this property after initialization doesn't take effect. + */ +QString QWaylandXdgOutputV1::name() const +{ + Q_D(const QWaylandXdgOutputV1); + return d->name; +} + +void QWaylandXdgOutputV1::setName(const QString &name) +{ + Q_D(QWaylandXdgOutputV1); + + if (d->name == name) + return; + + // Can't change after clients bound to xdg-output + if (d->initialized) { + qCWarning(qLcWaylandCompositor, "QWaylandXdgOutputV1::name cannot be changed after initialization"); + return; + } + + d->name = name; + emit nameChanged(); +} + +/*! + * \qmlproperty string QtWaylandCompositor::XdgOutputV1::description + * + * This property holds the description of this output. + * + * No convention is defined for the description. + * + * Changing this property after initialization doesn't take effect. + */ +/*! + * \property QWaylandXdgOutputV1::description + * + * This property holds the description of this output. + * + * No convention is defined for the description. + * + * Changing this property after initialization doesn't take effect. + */ +QString QWaylandXdgOutputV1::description() const +{ + Q_D(const QWaylandXdgOutputV1); + return d->description; +} + +void QWaylandXdgOutputV1::setDescription(const QString &description) +{ + Q_D(QWaylandXdgOutputV1); + + if (d->description == description) + return; + + // Can't change after clients bound to xdg-output + if (d->initialized) { + qCWarning(qLcWaylandCompositor, "QWaylandXdgOutputV1::description cannot be changed after initialization"); + return; + } + + d->description = description; + emit descriptionChanged(); +} + +/*! + * \qmlproperty point QtWaylandCompositor::XdgOutputV1::logicalPosition + * + * This property holds the coordinates of the output within the global compositor space. + * + * The default value is 0,0. + */ +/*! + * \property QWaylandXdgOutputV1::logicalPosition + * + * This property holds the coordinates of the output within the global compositor space. + * + * The default value is 0,0. + */ +QPoint QWaylandXdgOutputV1::logicalPosition() const +{ + Q_D(const QWaylandXdgOutputV1); + return d->logicalPos; +} + +void QWaylandXdgOutputV1::setLogicalPosition(const QPoint &position) +{ + Q_D(QWaylandXdgOutputV1); + + if (d->logicalPos == position) + return; + + d->logicalPos = position; + if (d->initialized) { + d->sendLogicalPosition(position); + d->sendDone(); + } + emit logicalPositionChanged(); + emit logicalGeometryChanged(); +} + +/*! + * \qmlproperty size QtWaylandCompositor::XdgOutputV1::logicalSize + * + * This property holds the size of the output in the global compositor space. + * + * The default value is -1,-1 which is invalid. + * + * Please remember that this is the logical size, not the physical size. + * For example, for a WaylandOutput mode 3840x2160 and a scale factor 2: + * \list + * \li A compositor not scaling the surface buffers, will report a logical size of 3840x2160. + * \li A compositor automatically scaling the surface buffers, will report a logical size of 1920x1080. + * \li A compositor using a fractional scale of 1.5, will report a logical size of 2560x1620. + * \endlist + */ +/*! + * \property QWaylandXdgOutputV1::logicalSize + * + * This property holds the size of the output in the global compositor space. + * + * The default value is -1,-1 which is invalid. + * + * Please remember that this is the logical size, not the physical size. + * For example, for a WaylandOutput mode 3840x2160 and a scale factor 2: + * \list + * \li A compositor not scaling the surface buffers, will report a logical size of 3840x2160. + * \li A compositor automatically scaling the surface buffers, will report a logical size of 1920x1080. + * \li A compositor using a fractional scale of 1.5, will report a logical size of 2560x1620. + * \endlist + */ +QSize QWaylandXdgOutputV1::logicalSize() const +{ + Q_D(const QWaylandXdgOutputV1); + return d->logicalSize; +} + +void QWaylandXdgOutputV1::setLogicalSize(const QSize &size) +{ + Q_D(QWaylandXdgOutputV1); + + if (d->logicalSize == size) + return; + + d->logicalSize = size; + if (d->initialized) { + d->sendLogicalSize(size); + d->sendDone(); + } + emit logicalSizeChanged(); + emit logicalGeometryChanged(); +} + +/*! + * \qmlproperty rect QtWaylandCompositor::XdgOutputV1::logicalGeometry + * \readonly + * + * This property holds the position and size of the output in the global compositor space. + * It's the combination of the logical position and logical size. + * + * \sa XdgOutputV1::logicalPosition + * \sa XdgOutputV1::logicalSize + */ +/*! + * \property QWaylandXdgOutputV1::logicalGeometry + * \readonly + * + * This property holds the position and size of the output in the global compositor space. + * It's the combination of the logical position and logical size. + * + * \sa QWaylandXdgOutputV1::logicalPosition + * \sa QWaylandXdgOutputV1::logicalSize + */ +QRect QWaylandXdgOutputV1::logicalGeometry() const +{ + Q_D(const QWaylandXdgOutputV1); + return QRect(d->logicalPos, d->logicalSize); +} + +// QWaylandXdgOutputV1Private + +void QWaylandXdgOutputV1Private::sendLogicalPosition(const QPoint &position) +{ + const auto values = resourceMap().values(); + for (auto *resource : values) + send_logical_position(resource->handle, position.x(), position.y()); + needToSendDone = true; +} + +void QWaylandXdgOutputV1Private::sendLogicalSize(const QSize &size) +{ + const auto values = resourceMap().values(); + for (auto *resource : values) + send_logical_size(resource->handle, size.width(), size.height()); + needToSendDone = true; +} + +void QWaylandXdgOutputV1Private::sendDone() +{ + if (needToSendDone) { + const auto values = resourceMap().values(); + for (auto *resource : values) { + if (resource->version() < 3) + send_done(resource->handle); + } + needToSendDone = false; + } +} + +void QWaylandXdgOutputV1Private::setManager(QWaylandXdgOutputManagerV1 *_manager) +{ + Q_Q(QWaylandXdgOutputV1); + + if (!_manager) { + qCWarning(qLcWaylandCompositor, + "Cannot associate a null QWaylandXdgOutputManagerV1 to QWaylandXdgOutputV1 %p", this); + return; + } + + if (manager == _manager) + return; + + if (manager) { + qCWarning(qLcWaylandCompositor, + "Cannot associate a different QWaylandXdgOutputManagerV1 to QWaylandXdgOutputV1 %p " + "after initialization", this); + return; + } + + manager = _manager; + emit q->managerChanged(); +} + +void QWaylandXdgOutputV1Private::setOutput(QWaylandOutput *_output) +{ + Q_Q(QWaylandXdgOutputV1); + + if (!_output) { + qCWarning(qLcWaylandCompositor, + "Cannot associate a null QWaylandOutput to QWaylandXdgOutputV1 %p", this); + return; + } + + if (output == _output) + return; + + if (output) { + qCWarning(qLcWaylandCompositor, + "Cannot associate a different QWaylandOutput to QWaylandXdgOutputV1 %p " + "after initialization", this); + return; + } + + // Assign output above manager, to make both values valid in handlers + output = _output; + + if (!manager) { + // Try to find the manager from the output parents + for (auto *p = output->parent(); p != nullptr; p = p->parent()) { + if (auto *m = qobject_cast<QWaylandXdgOutputManagerV1 *>(p)) { + manager = m; + emit q->managerChanged(); + break; + } + } + } + + emit q->outputChanged(); + + // Register the output + if (manager) + QWaylandXdgOutputManagerV1Private::get(manager)->registerXdgOutput(output, q); +} + +void QWaylandXdgOutputV1Private::zxdg_output_v1_bind_resource(Resource *resource) +{ + send_logical_position(resource->handle, logicalPos.x(), logicalPos.y()); + send_logical_size(resource->handle, logicalSize.width(), logicalSize.height()); + if (resource->version() >= ZXDG_OUTPUT_V1_NAME_SINCE_VERSION) + send_name(resource->handle, name); + if (resource->version() >= ZXDG_OUTPUT_V1_DESCRIPTION_SINCE_VERSION) + send_description(resource->handle, description); + send_done(resource->handle); + + initialized = true; +} + +void QWaylandXdgOutputV1Private::zxdg_output_v1_destroy(Resource *resource) +{ + wl_resource_destroy(resource->handle); +} + +QT_END_NAMESPACE diff --git a/src/compositor/extensions/qwaylandxdgoutputv1.h b/src/compositor/extensions/qwaylandxdgoutputv1.h new file mode 100644 index 000000000..c5f03758a --- /dev/null +++ b/src/compositor/extensions/qwaylandxdgoutputv1.h @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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 QWAYLANDXDGOUTPUTV1_H +#define QWAYLANDXDGOUTPUTV1_H + +#include <QRect> +#include <QWaylandCompositorExtension> +#include <QtWaylandCompositor/qwaylandquickchildren.h> + +QT_BEGIN_NAMESPACE + +class QWaylandOutput; + +class QWaylandXdgOutputManagerV1Private; +class QWaylandXdgOutputV1Private; + +class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandXdgOutputManagerV1 + : public QWaylandCompositorExtensionTemplate<QWaylandXdgOutputManagerV1> +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QWaylandXdgOutputManagerV1) +public: + explicit QWaylandXdgOutputManagerV1(); + QWaylandXdgOutputManagerV1(QWaylandCompositor *compositor); + + void initialize() override; + + static const wl_interface *interface(); +}; + +class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandXdgOutputV1 : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QWaylandXdgOutputV1) + Q_WAYLAND_COMPOSITOR_DECLARE_QUICK_CHILDREN(QWaylandXdgOutputV1) + Q_PROPERTY(QWaylandXdgOutputManagerV1 *manager READ manager NOTIFY managerChanged) + Q_PROPERTY(QWaylandOutput *output READ output NOTIFY outputChanged) + Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) + Q_PROPERTY(QString description READ description WRITE setDescription NOTIFY descriptionChanged) + Q_PROPERTY(QPoint logicalPosition READ logicalPosition WRITE setLogicalPosition NOTIFY logicalPositionChanged) + Q_PROPERTY(QSize logicalSize READ logicalSize WRITE setLogicalSize NOTIFY logicalSizeChanged) + Q_PROPERTY(QRect logicalGeometry READ logicalGeometry NOTIFY logicalGeometryChanged) +public: + QWaylandXdgOutputV1(); + QWaylandXdgOutputV1(QWaylandOutput *output, QWaylandXdgOutputManagerV1 *manager); + ~QWaylandXdgOutputV1() override; + + QWaylandXdgOutputManagerV1 *manager() const; + QWaylandOutput *output() const; + + QString name() const; + void setName(const QString &name); + + QString description() const; + void setDescription(const QString &name); + + QPoint logicalPosition() const; + void setLogicalPosition(const QPoint &position); + + QSize logicalSize() const; + void setLogicalSize(const QSize &size); + + QRect logicalGeometry() const; + +Q_SIGNALS: + void managerChanged(); + void outputChanged(); + void logicalPositionChanged(); + void logicalSizeChanged(); + void logicalGeometryChanged(); + void nameChanged(); + void descriptionChanged(); +}; + +QT_END_NAMESPACE + +#endif // QWAYLANDXDGOUTPUTV1_H diff --git a/src/compositor/extensions/qwaylandxdgoutputv1_p.h b/src/compositor/extensions/qwaylandxdgoutputv1_p.h new file mode 100644 index 000000000..2e8a6fff9 --- /dev/null +++ b/src/compositor/extensions/qwaylandxdgoutputv1_p.h @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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 QWAYLANDXDGOUTPUTV1_P_H +#define QWAYLANDXDGOUTPUTV1_P_H + +#include <QWaylandOutput> +#include <QWaylandXdgOutputV1> +#include <QtWaylandCompositor/private/qwaylandcompositorextension_p.h> +#include <QtWaylandCompositor/private/qwayland-server-xdg-output-unstable-v1.h> + +// +// 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 QWaylandXdgOutputManagerV1Private + : public QWaylandCompositorExtensionPrivate + , public QtWaylandServer::zxdg_output_manager_v1 +{ + Q_DECLARE_PUBLIC(QWaylandXdgOutputManagerV1) +public: + explicit QWaylandXdgOutputManagerV1Private() = default; + + void registerXdgOutput(QWaylandOutput *output, QWaylandXdgOutputV1 *xdgOutput); + void unregisterXdgOutput(QWaylandOutput *output); + + static QWaylandXdgOutputManagerV1Private *get(QWaylandXdgOutputManagerV1 *manager) { return manager ? manager->d_func() : nullptr; } + +protected: + void zxdg_output_manager_v1_get_xdg_output(Resource *resource, uint32_t id, + wl_resource *outputResource) override; + +private: + QHash<QWaylandOutput *, QWaylandXdgOutputV1 *> xdgOutputs; +}; + +class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandXdgOutputV1Private + : public QObjectPrivate + , public QtWaylandServer::zxdg_output_v1 +{ + Q_DECLARE_PUBLIC(QWaylandXdgOutputV1) +public: + explicit QWaylandXdgOutputV1Private() = default; + + void sendLogicalPosition(const QPoint &position); + void sendLogicalSize(const QSize &size); + void sendDone(); + + void setManager(QWaylandXdgOutputManagerV1 *manager); + void setOutput(QWaylandOutput *output); + + static QWaylandXdgOutputV1Private *get(QWaylandXdgOutputV1 *xdgOutput) { return xdgOutput ? xdgOutput->d_func() : nullptr; } + + bool initialized = false; + QWaylandOutput *output = nullptr; + QWaylandXdgOutputManagerV1 *manager = nullptr; + QPoint logicalPos; + QSize logicalSize; + QString name; + QString description; + bool needToSendDone = false; + +protected: + void zxdg_output_v1_bind_resource(Resource *resource) override; + void zxdg_output_v1_destroy(Resource *resource) override; +}; + +QT_END_NAMESPACE + +#endif // QWAYLANDXDGOUTPUTV1_P_H diff --git a/src/imports/compositor/qwaylandquickcompositorplugin.cpp b/src/imports/compositor/qwaylandquickcompositorplugin.cpp index cd049331c..223ca0bc5 100644 --- a/src/imports/compositor/qwaylandquickcompositorplugin.cpp +++ b/src/imports/compositor/qwaylandquickcompositorplugin.cpp @@ -67,6 +67,7 @@ #include <QtWaylandCompositor/QWaylandXdgShell> #include <QtWaylandCompositor/QWaylandXdgDecorationManagerV1> #include <QtWaylandCompositor/QWaylandIdleInhibitManagerV1> +#include <QtWaylandCompositor/QWaylandQuickXdgOutputV1> #include <QtWaylandCompositor/QWaylandIviApplication> #include <QtWaylandCompositor/QWaylandIviSurface> @@ -87,6 +88,7 @@ Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandXdgShellV5) Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandXdgShellV6) Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandXdgShell) Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandXdgDecorationManagerV1) +Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandXdgOutputManagerV1) Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandTextInputManager) class QmlUrlResolver @@ -193,6 +195,9 @@ public: #endif qmlRegisterType<QWaylandIdleInhibitManagerV1QuickExtension>(uri, 1, 14, "IdleInhibitManagerV1"); + + qmlRegisterType<QWaylandXdgOutputManagerV1QuickExtension>(uri, 1, 14, "XdgOutputManagerV1"); + qmlRegisterType<QWaylandQuickXdgOutputV1>(uri, 1, 14, "XdgOutputV1"); } }; //![class decl] diff --git a/sync.profile b/sync.profile index be25721fc..5c7ada912 100644 --- a/sync.profile +++ b/sync.profile @@ -68,6 +68,7 @@ "^qwayland-server-touch-extension.h", "^qwayland-server-viewporter.h", "^qwayland-server-xdg-decoration-unstable-v1.h", + "^qwayland-server-xdg-output-unstable-v1.h", "^qwayland-server-xdg-shell-unstable-v6.h", "^qwayland-server-xdg-shell.h", "^wayland-hardware-integration-server-protocol.h", @@ -83,6 +84,7 @@ "^wayland-touch-extension-server-protocol.h", "^wayland-wayland-server-protocol.h", "^wayland-xdg-decoration-unstable-v1-server-protocol.h", + "^wayland-xdg-output-unstable-v1-server-protocol.h", "^wayland-xdg-shell-server-protocol.h", "^wayland-xdg-shell-unstable-v6-server-protocol.h", ], diff --git a/tests/auto/compositor/compositor/compositor.pro b/tests/auto/compositor/compositor/compositor.pro index 8a364e52c..270016597 100644 --- a/tests/auto/compositor/compositor/compositor.pro +++ b/tests/auto/compositor/compositor/compositor.pro @@ -15,7 +15,8 @@ WAYLANDCLIENTSOURCES += \ ../../../../src/3rdparty/protocol/wayland.xml \ ../../../../src/3rdparty/protocol/xdg-shell.xml \ ../../../../src/3rdparty/protocol/viewporter.xml \ - ../../../../src/3rdparty/protocol/idle-inhibit-unstable-v1.xml + ../../../../src/3rdparty/protocol/idle-inhibit-unstable-v1.xml \ + ../../../../src/3rdparty/protocol/xdg-output-unstable-v1.xml SOURCES += \ tst_compositor.cpp \ @@ -25,7 +26,8 @@ SOURCES += \ mockseat.cpp \ testseat.cpp \ mockkeyboard.cpp \ - mockpointer.cpp + mockpointer.cpp \ + mockxdgoutputv1.cpp HEADERS += \ testcompositor.h \ @@ -34,4 +36,5 @@ HEADERS += \ mockseat.h \ testseat.h \ mockkeyboard.h \ - mockpointer.h + mockpointer.h \ + mockxdgoutputv1.h diff --git a/tests/auto/compositor/compositor/mockclient.cpp b/tests/auto/compositor/compositor/mockclient.cpp index 4ae04998e..27d1eed89 100644 --- a/tests/auto/compositor/compositor/mockclient.cpp +++ b/tests/auto/compositor/compositor/mockclient.cpp @@ -186,11 +186,17 @@ void MockClient::handleGlobal(uint32_t id, const QByteArray &interface) m_seats << new MockSeat(s); } else if (interface == "zwp_idle_inhibit_manager_v1") { idleInhibitManager = static_cast<zwp_idle_inhibit_manager_v1 *>(wl_registry_bind(registry, id, &zwp_idle_inhibit_manager_v1_interface, 1)); + } else if (interface == "zxdg_output_manager_v1") { + xdgOutputManager = new QtWayland::zxdg_output_manager_v1(registry, id, 2); } } void MockClient::handleGlobalRemove(uint32_t id) { + auto *output = m_outputs[id]; + if (m_xdgOutputs.contains(output)) + delete m_xdgOutputs.take(output); + m_outputs.remove(id); } @@ -234,6 +240,13 @@ zwp_idle_inhibitor_v1 *MockClient::createIdleInhibitor(wl_surface *surface) return idleInhibitor; } +MockXdgOutputV1 *MockClient::createXdgOutput(wl_output *output) +{ + auto *xdgOutput = new MockXdgOutputV1(xdgOutputManager->get_xdg_output(output)); + m_xdgOutputs[output] = xdgOutput; + return xdgOutput; +} + ShmBuffer::ShmBuffer(const QSize &size, wl_shm *shm) { int stride = size.width() * 4; diff --git a/tests/auto/compositor/compositor/mockclient.h b/tests/auto/compositor/compositor/mockclient.h index aa20a7ac7..69a0e47cf 100644 --- a/tests/auto/compositor/compositor/mockclient.h +++ b/tests/auto/compositor/compositor/mockclient.h @@ -38,6 +38,8 @@ #include <QList> #include <QWaylandOutputMode> +#include "mockxdgoutputv1.h" + class MockSeat; class ShmBuffer @@ -65,10 +67,12 @@ public: xdg_toplevel *createXdgToplevel(xdg_surface *xdgSurface); ivi_surface *createIviSurface(wl_surface *surface, uint iviId); zwp_idle_inhibitor_v1 *createIdleInhibitor(wl_surface *surface); + MockXdgOutputV1 *createXdgOutput(wl_output *output); wl_display *display = nullptr; wl_compositor *compositor = nullptr; QMap<uint, wl_output *> m_outputs; + QMap<wl_output *, MockXdgOutputV1 *> m_xdgOutputs; wl_shm *shm = nullptr; wl_registry *registry = nullptr; wl_shell *wlshell = nullptr; @@ -76,6 +80,7 @@ public: wp_viewporter *viewporter = nullptr; ivi_application *iviApplication = nullptr; zwp_idle_inhibit_manager_v1 *idleInhibitManager = nullptr; + QtWayland::zxdg_output_manager_v1 *xdgOutputManager = nullptr; QList<MockSeat *> m_seats; diff --git a/tests/auto/compositor/compositor/mockxdgoutputv1.cpp b/tests/auto/compositor/compositor/mockxdgoutputv1.cpp new file mode 100644 index 000000000..eebc55bbb --- /dev/null +++ b/tests/auto/compositor/compositor/mockxdgoutputv1.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "mockxdgoutputv1.h" + +MockXdgOutputV1::MockXdgOutputV1(struct ::zxdg_output_v1 *object) + : QtWayland::zxdg_output_v1(object) +{ +} + +MockXdgOutputV1::~MockXdgOutputV1() +{ + destroy(); +} + +void MockXdgOutputV1::zxdg_output_v1_logical_position(int32_t x, int32_t y) +{ + pending.logicalPosition = QPoint(x, y); +} + +void MockXdgOutputV1::zxdg_output_v1_logical_size(int32_t width, int32_t height) +{ + pending.logicalSize = QSize(width, height); +} + +void MockXdgOutputV1::zxdg_output_v1_done() +{ + // In version 3 we'll have to do this for wl_output.done as well + name = pending.name; + description = pending.description; + logicalPosition = pending.logicalPosition; + logicalSize = pending.logicalSize; +} + +void MockXdgOutputV1::zxdg_output_v1_name(const QString &name) +{ + pending.name = name; +} + +void MockXdgOutputV1::zxdg_output_v1_description(const QString &description) +{ + pending.description = description; +} diff --git a/tests/auto/compositor/compositor/mockxdgoutputv1.h b/tests/auto/compositor/compositor/mockxdgoutputv1.h new file mode 100644 index 000000000..db5820698 --- /dev/null +++ b/tests/auto/compositor/compositor/mockxdgoutputv1.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> +** 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 MOCKXDGOUTPUTV1_H +#define MOCKXDGOUTPUTV1_H + +#include <QPoint> +#include <QSize> +#include <QString> + +#include "qwayland-xdg-output-unstable-v1.h" + +class MockXdgOutputV1 : public QtWayland::zxdg_output_v1 +{ +public: + explicit MockXdgOutputV1(struct ::zxdg_output_v1 *object); + ~MockXdgOutputV1(); + + QString name; + QString description; + QPoint logicalPosition; + QSize logicalSize; + + struct { + QString name; + QString description; + QPoint logicalPosition; + QSize logicalSize; + } pending; + +protected: + void zxdg_output_v1_logical_position(int32_t x, int32_t y) override; + void zxdg_output_v1_logical_size(int32_t width, int32_t height) override; + void zxdg_output_v1_done() override; + void zxdg_output_v1_name(const QString &name) override; + void zxdg_output_v1_description(const QString &description) override; +}; + +#endif // MOCKXDGOUTPUTV1_H diff --git a/tests/auto/compositor/compositor/tst_compositor.cpp b/tests/auto/compositor/compositor/tst_compositor.cpp index 28ec6c3e4..f4f63228c 100644 --- a/tests/auto/compositor/compositor/tst_compositor.cpp +++ b/tests/auto/compositor/compositor/tst_compositor.cpp @@ -29,6 +29,7 @@ #include "mockclient.h" #include "mockseat.h" #include "mockpointer.h" +#include "mockxdgoutputv1.h" #include "testcompositor.h" #include "testkeyboardgrabber.h" #include "testseat.h" @@ -48,8 +49,10 @@ #include <QtWaylandCompositor/QWaylandKeymap> #include <QtWaylandCompositor/QWaylandViewporter> #include <QtWaylandCompositor/QWaylandIdleInhibitManagerV1> +#include <QtWaylandCompositor/QWaylandXdgOutputManagerV1> #include <qwayland-xdg-shell.h> #include <qwayland-ivi-application.h> +#include <QtWaylandCompositor/private/qwaylandoutput_p.h> #include <QtWaylandCompositor/private/qwaylandsurface_p.h> #include <QtTest/QtTest> @@ -116,6 +119,8 @@ private slots: void viewportHiDpi(); void idleInhibit(); + + void xdgOutput(); }; void tst_WaylandCompositor::init() { @@ -1793,5 +1798,68 @@ void tst_WaylandCompositor::idleInhibit() QTRY_COMPARE(changedSpy.count(), 1); } +class XdgOutputCompositor : public TestCompositor +{ + Q_OBJECT +public: + XdgOutputCompositor() : xdgOutputManager(this) {} + QWaylandXdgOutputManagerV1 xdgOutputManager; +}; + +void tst_WaylandCompositor::xdgOutput() +{ + XdgOutputCompositor compositor; + compositor.create(); + + QWaylandOutputMode mode(QSize(1024, 768), 60000); + compositor.defaultOutput()->addMode(mode, true); + compositor.defaultOutput()->setCurrentMode(mode); + + MockClient client; + QTRY_VERIFY(client.xdgOutputManager); + QTRY_COMPARE(client.m_outputs.size(), 1); + + auto *wlOutput = client.m_outputs.first(); + QVERIFY(wlOutput); + + // Output is not associated yet + QCOMPARE(QWaylandOutputPrivate::get(compositor.defaultOutput())->xdgOutput.isNull(), true); + + // Create xdg-output on the server + auto *xdgOutputServer = new QWaylandXdgOutputV1(compositor.defaultOutput(), &compositor.xdgOutputManager); + QVERIFY(xdgOutputServer); + xdgOutputServer->setName(QStringLiteral("OUTPUT1")); + xdgOutputServer->setDescription(QStringLiteral("This is a test output")); + + // Create it on the client + auto *xdgOutput = client.createXdgOutput(wlOutput); + QVERIFY(xdgOutput); + QVERIFY(client.m_xdgOutputs.contains(wlOutput)); + + // Now it should be associated + QCOMPARE(QWaylandOutputPrivate::get(compositor.defaultOutput())->xdgOutput.isNull(), false); + + // Verify initial values + QTRY_COMPARE(xdgOutput->name, "OUTPUT1"); + QTRY_COMPARE(xdgOutput->logicalPosition, QPoint()); + QTRY_COMPARE(xdgOutput->logicalSize, QSize()); + + // Change properties + xdgOutputServer->setName(QStringLiteral("OUTPUT2")); + xdgOutputServer->setDescription(QStringLiteral("New description")); + xdgOutputServer->setLogicalPosition(QPoint(100, 100)); + xdgOutputServer->setLogicalSize(QSize(1000, 1000)); + compositor.flushClients(); + + // Name and description can't be changed after initialization, + // so we expect them to be the same + // TODO: With protocol version 3 the description will be allowed to change, + // but we implement version 2 now + QTRY_COMPARE(xdgOutput->name, "OUTPUT1"); + QTRY_COMPARE(xdgOutput->description, "This is a test output"); + QTRY_COMPARE(xdgOutput->logicalPosition, QPoint(100, 100)); + QTRY_COMPARE(xdgOutput->logicalSize, QSize(1000, 1000)); +} + #include <tst_compositor.moc> QTEST_MAIN(tst_WaylandCompositor); |