diff options
Diffstat (limited to 'src/compositor/compositor_api/qwaylandsurface.cpp')
-rw-r--r-- | src/compositor/compositor_api/qwaylandsurface.cpp | 870 |
1 files changed, 563 insertions, 307 deletions
diff --git a/src/compositor/compositor_api/qwaylandsurface.cpp b/src/compositor/compositor_api/qwaylandsurface.cpp index 64f78bd7..3ac791eb 100644 --- a/src/compositor/compositor_api/qwaylandsurface.cpp +++ b/src/compositor/compositor_api/qwaylandsurface.cpp @@ -4,521 +4,777 @@ ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** -** This file is part of the Qt Compositor. +** This file is part of the QtWaylandCompositor module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: +** $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. ** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. +** 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. ** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** 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 "qwaylandsurface.h" +#include "qwaylandsurface_p.h" -#include <private/qobject_p.h> - -#include "wayland_wrapper/qwlsurface_p.h" -#include "wayland_wrapper/qwlextendedsurface_p.h" -#include "wayland_wrapper/qwlcompositor_p.h" -#include "wayland_wrapper/qwlshellsurface_p.h" -#include "wayland_wrapper/qwlinputdevice_p.h" #include "wayland_wrapper/qwldatadevice_p.h" #include "wayland_wrapper/qwldatadevicemanager_p.h" +#include "wayland_wrapper/qwlregion_p.h" -#include "qwaylandcompositor.h" -#include "qwaylandclient.h" -#include "qwaylandsurface_p.h" -#include "qwaylandbufferref.h" -#include "qwaylandsurfaceinterface.h" +#include "extensions/qwlextendedsurface_p.h" -#include <QtGui/QGuiApplication> -#include <QtGui/QScreen> +#include <QtWaylandCompositor/QWaylandCompositor> +#include <QtWaylandCompositor/QWaylandClient> +#include <QtWaylandCompositor/QWaylandView> +#include <QtWaylandCompositor/QWaylandBufferRef> -QT_BEGIN_NAMESPACE +#include <QtWaylandCompositor/private/qwaylandcompositor_p.h> +#include <QtWaylandCompositor/private/qwaylandview_p.h> +#include <QtWaylandCompositor/private/qwaylandinput_p.h> -const QEvent::Type QWaylandSurfaceEnterEvent::WaylandSurfaceEnter = (QEvent::Type)QEvent::registerEventType(); -const QEvent::Type QWaylandSurfaceLeaveEvent::WaylandSurfaceLeave = (QEvent::Type)QEvent::registerEventType(); +#include <QtCore/private/qobject_p.h> -QWaylandSurfacePrivate::QWaylandSurfacePrivate(wl_client *wlClient, quint32 id, int version, QWaylandCompositor *compositor, QWaylandSurface *surface) - : QtWayland::Surface(wlClient, id, version, compositor, surface) - , closing(false) - , refCount(1) - , client(QWaylandClient::fromWlClient(wlClient)) - , windowType(QWaylandSurface::None) -{} +#include <QtGui/QGuiApplication> +#include <QtGui/QScreen> +#include <QtCore/QDebug> -class QWaylandSurfaceEnterEventPrivate -{ +QT_BEGIN_NAMESPACE + +namespace QtWayland { +class FrameCallback { public: - QWaylandSurfaceEnterEventPrivate(QWaylandOutput *_output) - : output(_output) + FrameCallback(QWaylandSurface *surf, wl_resource *res) + : surface(surf) + , resource(res) + , canSend(false) { +#if WAYLAND_VERSION_MAJOR < 1 || (WAYLAND_VERSION_MAJOR == 1 && WAYLAND_VERSION_MINOR <= 2) + res->data = this; + res->destroy = destroyCallback; +#else + wl_resource_set_implementation(res, 0, this, destroyCallback); +#endif } - - QWaylandOutput *output; + ~FrameCallback() + { + } + void destroy() + { + if (resource) + wl_resource_destroy(resource); + else + delete this; + } + void send(uint time) + { + wl_callback_send_done(resource, time); + wl_resource_destroy(resource); + } + static void destroyCallback(wl_resource *res) + { +#if WAYLAND_VERSION_MAJOR < 1 || (WAYLAND_VERSION_MAJOR == 1 && WAYLAND_VERSION_MINOR <= 2) + FrameCallback *_this = static_cast<FrameCallback *>(res->data); +#else + FrameCallback *_this = static_cast<FrameCallback *>(wl_resource_get_user_data(res)); +#endif + if (_this->surface) + QWaylandSurfacePrivate::get(_this->surface)->removeFrameCallback(_this); + delete _this; + } + QWaylandSurface *surface; + wl_resource *resource; + bool canSend; }; - - -QWaylandSurfaceEnterEvent::QWaylandSurfaceEnterEvent(QWaylandOutput *output) - : QEvent(WaylandSurfaceEnter) - , d(new QWaylandSurfaceEnterEventPrivate(output)) -{ -} - -QWaylandSurfaceEnterEvent::~QWaylandSurfaceEnterEvent() -{ - delete d; } - -QWaylandOutput *QWaylandSurfaceEnterEvent::output() const -{ - return d->output; +static QRegion infiniteRegion() { + return QRegion(QRect(QPoint(std::numeric_limits<int>::min(), std::numeric_limits<int>::min()), + QPoint(std::numeric_limits<int>::max(), std::numeric_limits<int>::max()))); } +#ifndef QT_NO_DEBUG +QList<QWaylandSurfacePrivate *> QWaylandSurfacePrivate::uninitializedSurfaces; +#endif -class QWaylandSurfaceLeaveEventPrivate -{ -public: - QWaylandSurfaceLeaveEventPrivate(QWaylandOutput *_output) - : output(_output) - { +QWaylandSurfacePrivate::QWaylandSurfacePrivate() + : QtWaylandServer::wl_surface() + , compositor(Q_NULLPTR) + , refCount(1) + , client(Q_NULLPTR) + , buffer(0) + , inputPanelSurface(0) + , inputRegion(infiniteRegion()) + , isCursorSurface(false) + , destroyed(false) + , mapped(false) + , isInitialized(false) + , contentOrientation(Qt::PrimaryOrientation) +{ + pending.buffer = 0; + pending.newlyAttached = false; + pending.inputRegion = infiniteRegion(); +#ifndef QT_NO_DEBUG + addUninitializedSurface(this); +#endif +} + +QWaylandSurfacePrivate::~QWaylandSurfacePrivate() +{ + for (int i = 0; i < views.size(); i++) { + QWaylandViewPrivate::get(views.at(i))->markSurfaceAsDestroyed(q_func()); } + views.clear(); - QWaylandOutput *output; -}; + bufferRef = QWaylandBufferRef(); + for (int i = 0; i < bufferPool.size(); i++) + bufferPool[i]->setDestroyIfUnused(true); -QWaylandSurfaceLeaveEvent::QWaylandSurfaceLeaveEvent(QWaylandOutput *output) - : QEvent(WaylandSurfaceLeave) - , d(new QWaylandSurfaceLeaveEventPrivate(output)) -{ + foreach (QtWayland::FrameCallback *c, pendingFrameCallbacks) + c->destroy(); + foreach (QtWayland::FrameCallback *c, frameCallbacks) + c->destroy(); } -QWaylandSurfaceLeaveEvent::~QWaylandSurfaceLeaveEvent() +void QWaylandSurfacePrivate::setSize(const QSize &s) { - delete d; + Q_Q(QWaylandSurface); + if (size != s) { + opaqueRegion = QRegion(); + size = s; + q->sizeChanged(); + } } -QWaylandOutput *QWaylandSurfaceLeaveEvent::output() const +void QWaylandSurfacePrivate::removeFrameCallback(QtWayland::FrameCallback *callback) { - return d->output; + pendingFrameCallbacks.removeOne(callback); + frameCallbacks.removeOne(callback); } - -QWaylandSurface::QWaylandSurface(wl_client *client, quint32 id, int version, QWaylandCompositor *compositor) - : QObject(*new QWaylandSurfacePrivate(client, id, version, compositor, this)) +void QWaylandSurfacePrivate::notifyViewsAboutDestruction() { - + Q_Q(QWaylandSurface); + foreach (QWaylandView *view, views) { + QWaylandViewPrivate::get(view)->markSurfaceAsDestroyed(q); + } + if (mapped) { + mapped = false; + emit q->mappedChanged(); + } } -QWaylandSurface::QWaylandSurface(QWaylandSurfacePrivate *dptr) - : QObject(*dptr) +#ifndef QT_NO_DEBUG +void QWaylandSurfacePrivate::addUninitializedSurface(QWaylandSurfacePrivate *surface) { - + Q_ASSERT(!surface->isInitialized); + Q_ASSERT(!uninitializedSurfaces.contains(surface)); + uninitializedSurfaces.append(surface); } -QWaylandSurface::~QWaylandSurface() +void QWaylandSurfacePrivate::removeUninitializedSurface(QWaylandSurfacePrivate *surface) { - Q_D(QWaylandSurface); - qDeleteAll(d->interfaces); - delete d->m_attacher; + Q_ASSERT(surface->isInitialized); + bool removed = uninitializedSurfaces.removeOne(surface); + Q_ASSERT(removed); } -QWaylandClient *QWaylandSurface::client() const +bool QWaylandSurfacePrivate::hasUninitializedSurface() { - Q_D(const QWaylandSurface); - if (d->isDestroyed() || !d->compositor()->clients().contains(d->client)) - return Q_NULLPTR; - return d->client; + return uninitializedSurfaces.size(); } +#endif -void QWaylandSurface::addInterface(QWaylandSurfaceInterface *iface) +void QWaylandSurfacePrivate::surface_destroy_resource(Resource *) { - Q_D(QWaylandSurface); - d->interfaces.prepend(iface); + Q_Q(QWaylandSurface); + notifyViewsAboutDestruction(); + + destroyed = true; + emit q->surfaceDestroyed(); + q->destroy(); } -void QWaylandSurface::removeInterface(QWaylandSurfaceInterface *iface) +void QWaylandSurfacePrivate::surface_destroy(Resource *resource) { - Q_D(QWaylandSurface); - d->interfaces.removeOne(iface); + wl_resource_destroy(resource->handle); } -QWaylandSurface::Type QWaylandSurface::type() const +void QWaylandSurfacePrivate::surface_attach(Resource *, struct wl_resource *buffer, int x, int y) { - Q_D(const QWaylandSurface); - return d->type(); + if (pending.buffer) + pending.buffer->disown(); + pending.buffer = createSurfaceBuffer(buffer); + pending.offset = QPoint(x, y); + pending.newlyAttached = true; } -bool QWaylandSurface::isYInverted() const +void QWaylandSurfacePrivate::surface_damage(Resource *, int32_t x, int32_t y, int32_t width, int32_t height) { - Q_D(const QWaylandSurface); - return d->isYInverted(); + pending.damage = pending.damage.united(QRect(x, y, width, height)); } -bool QWaylandSurface::visible() const +void QWaylandSurfacePrivate::surface_frame(Resource *resource, uint32_t callback) { - return isMapped(); + Q_Q(QWaylandSurface); + struct wl_resource *frame_callback = wl_resource_create(resource->client(), &wl_callback_interface, wl_callback_interface.version, callback); + pendingFrameCallbacks << new QtWayland::FrameCallback(q, frame_callback); } -bool QWaylandSurface::isMapped() const +void QWaylandSurfacePrivate::surface_set_opaque_region(Resource *, struct wl_resource *region) { - Q_D(const QWaylandSurface); - return d->mapped(); + opaqueRegion = region ? QtWayland::Region::fromResource(region)->region() : QRegion(); } -QSize QWaylandSurface::size() const +void QWaylandSurfacePrivate::surface_set_input_region(Resource *, struct wl_resource *region) { - Q_D(const QWaylandSurface); - return d->size(); + if (region) { + pending.inputRegion = QtWayland::Region::fromResource(region)->region(); + } else { + pending.inputRegion = infiniteRegion(); + } } -void QWaylandSurface::requestSize(const QSize &size) +void QWaylandSurfacePrivate::surface_commit(Resource *) { - Q_D(QWaylandSurface); - QWaylandSurfaceResizeOp op(size); - if (!sendInterfaceOp(op)) { - int id = wl_resource_get_id(d->resource()->handle); - qWarning("No surface interface forwarded the resize request for this surface (wl_surface@%d).", id); + Q_Q(QWaylandSurface); + + if (pending.buffer || pending.newlyAttached) { + setBackBuffer(pending.buffer, pending.damage); } + + pending.buffer = 0; + pending.offset = QPoint(); + pending.newlyAttached = false; + pending.damage = QRegion(); + + if (buffer) + buffer->setCommitted(); + + frameCallbacks << pendingFrameCallbacks; + pendingFrameCallbacks.clear(); + + inputRegion = pending.inputRegion.intersected(QRect(QPoint(), size)); + + emit q->redraw(); } -Qt::ScreenOrientations QWaylandSurface::orientationUpdateMask() const +void QWaylandSurfacePrivate::surface_set_buffer_transform(Resource *resource, int32_t orientation) { - Q_D(const QWaylandSurface); - if (!d->extendedSurface()) - return Qt::PrimaryOrientation; - return d->extendedSurface()->contentOrientationMask(); + Q_UNUSED(resource); + Q_Q(QWaylandSurface); + QScreen *screen = QGuiApplication::primaryScreen(); + bool isPortrait = screen->primaryOrientation() == Qt::PortraitOrientation; + Qt::ScreenOrientation oldOrientation = contentOrientation; + switch (orientation) { + case WL_OUTPUT_TRANSFORM_90: + contentOrientation = isPortrait ? Qt::InvertedLandscapeOrientation : Qt::PortraitOrientation; + break; + case WL_OUTPUT_TRANSFORM_180: + contentOrientation = isPortrait ? Qt::InvertedPortraitOrientation : Qt::InvertedLandscapeOrientation; + break; + case WL_OUTPUT_TRANSFORM_270: + contentOrientation = isPortrait ? Qt::LandscapeOrientation : Qt::InvertedPortraitOrientation; + break; + default: + contentOrientation = Qt::PrimaryOrientation; + } + if (contentOrientation != oldOrientation) + emit q->contentOrientationChanged(); } -Qt::ScreenOrientation QWaylandSurface::contentOrientation() const +void QWaylandSurfacePrivate::setBackBuffer(QtWayland::SurfaceBuffer *b, const QRegion &d) { - Q_D(const QWaylandSurface); - return d->contentOrientation(); + Q_Q(QWaylandSurface); + buffer = b; + + bufferRef = QWaylandBufferRef(buffer); + + setSize(bufferRef.size()); + damage = d.intersected(QRect(QPoint(), size)); + + for (int i = 0; i < views.size(); i++) { + views.at(i)->attach(bufferRef, damage); + } + + emit q->damaged(damage); + + bool oldMapped = mapped; + mapped = QtWayland::SurfaceBuffer::hasContent(buffer); + if (oldMapped != mapped) + emit q->mappedChanged(); + + if (!pending.offset.isNull()) + emit q->offsetForNextFrame(pending.offset); } -QWaylandSurface::WindowFlags QWaylandSurface::windowFlags() const +QtWayland::SurfaceBuffer *QWaylandSurfacePrivate::createSurfaceBuffer(struct ::wl_resource *buffer) { - Q_D(const QWaylandSurface); - if (!d->extendedSurface()) - return QWaylandSurface::WindowFlags(0); - return d->extendedSurface()->windowFlags(); + Q_Q(QWaylandSurface); + QtWayland::SurfaceBuffer *newBuffer = 0; + for (int i = 0; i < bufferPool.size(); i++) { + if (!bufferPool[i]->isRegisteredWithBuffer()) { + newBuffer = bufferPool[i]; + newBuffer->initialize(buffer); + break; + } + } + + if (!newBuffer) { + newBuffer = new QtWayland::SurfaceBuffer(q); + newBuffer->initialize(buffer); + bufferPool.append(newBuffer); + if (bufferPool.size() > 3) + qWarning() << "Increased buffer pool size to" << bufferPool.size() << "for surface" << q; + } + + return newBuffer; } -QWaylandSurface::WindowType QWaylandSurface::windowType() const +/*! + * \qmltype WaylandSurface + * \inqmlmodule QtWayland.Compositor + * \brief A rectangular area which is displayed on an output device. + * + * This type encapsulates a rectangular area of pixels that is displayed on an output device. It + * corresponds to the interface wl_surface in the Wayland protocol. + */ + +/*! + * \class QWaylandSurface + * \inmodule QtWaylandCompositor + * \brief A rectangular area which is displayed on an output device. + * + * This class encapsulates a rectangular area of pixels that is displayed on an output device. It + * corresponds to the interface wl_surface in the Wayland protocol. + */ + +/*! + * Constructs a an uninitialized QWaylandSurface. + */ +QWaylandSurface::QWaylandSurface() + : QWaylandObject(*new QWaylandSurfacePrivate()) { - Q_D(const QWaylandSurface); - return d->windowType; } -QWaylandSurface *QWaylandSurface::transientParent() const +/*! + * Constructs and initializes a QWaylandSurface for the given \a compositor and \a client, and with the given \a id + * and \a version. + */ +QWaylandSurface::QWaylandSurface(QWaylandCompositor *compositor, QWaylandClient *client, uint id, int version) + : QWaylandObject(*new QWaylandSurfacePrivate()) { - Q_D(const QWaylandSurface); - return d->transientParent() ? d->transientParent()->waylandSurface() : 0; + initialize(compositor, client, id, version); } -QPointF QWaylandSurface::transientOffset() const +/*! + * \internal + */ +QWaylandSurface::QWaylandSurface(QWaylandSurfacePrivate &dptr) + : QWaylandObject(dptr) { - Q_D(const QWaylandSurface); - return d->m_transientOffset; } -QtWayland::Surface * QWaylandSurface::handle() +/*! + * Destroys the QWaylandSurface. + */ +QWaylandSurface::~QWaylandSurface() { Q_D(QWaylandSurface); - return d; + QWaylandCompositorPrivate::get(d->compositor)->unregisterSurface(this); + d->notifyViewsAboutDestruction(); } -QVariantMap QWaylandSurface::windowProperties() const -{ - Q_D(const QWaylandSurface); - if (!d->extendedSurface()) - return QVariantMap(); - - return d->extendedSurface()->windowProperties(); -} +/*! + * \qmlmethod void QtWaylandCompositor::WaylandSurface::initialize(object compositor, object client, int id, int version) + * + * Initializes the QWaylandSurface with the given \a compositor and \a client, and with the given \a id + * and \a version. + */ -void QWaylandSurface::setWindowProperty(const QString &name, const QVariant &value) +/*! + * Initializes the QWaylandSurface with the given \a compositor and \a client, and with the given \a id + * and \a version. + */ +void QWaylandSurface::initialize(QWaylandCompositor *compositor, QWaylandClient *client, uint id, int version) { Q_D(QWaylandSurface); - if (!d->extendedSurface()) - return; - - d->extendedSurface()->setWindowProperty(name, value); + d->compositor = compositor; + d->client = client; + d->init(client->client(), id, version); + d->isInitialized = true; +#ifndef QT_NO_DEBUG + QWaylandSurfacePrivate::removeUninitializedSurface(d); +#endif } -QWaylandCompositor *QWaylandSurface::compositor() const +/*! + * Returns true if the QWaylandSurface has been initialized. + */ +bool QWaylandSurface::isInitialized() const { Q_D(const QWaylandSurface); - return d->compositor()->waylandCompositor(); + return d->isInitialized; } -QWaylandOutput *QWaylandSurface::mainOutput() const +/*! + * \qmlproperty object QtWaylandCompositor::WaylandSurface::client + * + * This property holds the client using this QWaylandSurface. + */ + +/*! + * \property QWaylandSurface::client + * + * This property holds the client using this QWaylandSurface. + */ +QWaylandClient *QWaylandSurface::client() const { Q_D(const QWaylandSurface); + if (isDestroyed() || !compositor()->clients().contains(d->client)) + return Q_NULLPTR; - // Returns the output that contains the most if not all - // the surface (window managers will take care of setting - // this, defaults to the first output) - return d->mainOutput()->waylandOutput(); + return d->client; } -void QWaylandSurface::setMainOutput(QWaylandOutput *mainOutput) -{ - Q_D(QWaylandSurface); +/*! + * \qmlproperty bool QtWaylandCompositor::WaylandSurface::isMapped + * + * This property holds whether the WaylandSurface has content. + */ - if (mainOutput) - d->setMainOutput(mainOutput->handle()); +/*! + * \property QWaylandSurface::isMapped + * + * This property holds whether the QWaylandSurface has content. + */ +bool QWaylandSurface::isMapped() const +{ + Q_D(const QWaylandSurface); + return d->mapped; } -QList<QWaylandOutput *> QWaylandSurface::outputs() const +/*! + * \qmlproperty size QtWaylandCompositor::WaylandSurface::size + * + * This property holds the WaylandSurface's size in pixels. + */ + +/*! + * \property QWaylandSurface::size + * + * This property holds the QWaylandSurface's size in pixels. + */ +QSize QWaylandSurface::size() const { Q_D(const QWaylandSurface); - - QList<QWaylandOutput *> list; - const QList<QtWayland::Output *> outputs = d->outputs(); - list.reserve(outputs.count()); - Q_FOREACH (QtWayland::Output *output, outputs) - list.append(output->waylandOutput()); - return list; + return d->size; } -QWindow::Visibility QWaylandSurface::visibility() const +/*! + * \qmlproperty enum QtWaylandCompositor::WaylandSurface::contentOrientation + * + * This property holds the orientation of the WaylandSurface's contents. + * + * \sa QtWaylandCompositor::WaylandOutput::transform + */ + +/*! + * \property QWaylandSurface::contentOrientation + * + * This property holds the orientation of the QWaylandSurface's contents. + * + * \sa QWaylandOutput::transform + */ +Qt::ScreenOrientation QWaylandSurface::contentOrientation() const { Q_D(const QWaylandSurface); - return d->m_visibility; + return d->contentOrientation; } -void QWaylandSurface::setVisibility(QWindow::Visibility v) -{ - Q_D(QWaylandSurface); - if (v == visibility()) - return; +/*! + * \enum QWaylandSurface::Origin + * + * This enum type is used to specify the origin of a QWaylandSurface's buffer. + * + * \value OriginTopLeft The origin is the top left corner of the buffer. + * \value OriginBottomLeft The origin is the bottom left corner of the buffer. + */ - d->m_visibility = v; - QWaylandSurfaceSetVisibilityOp op(v); - sendInterfaceOp(op); +/*! + * \qmlproperty enum QtWaylandCompositor::WaylandSurface::origin + * + * This property holds the origin of the WaylandSurface's buffer, or + * WaylandSurface.OriginTopLeft if the surface has no buffer. + * + * It can have the following values: + * \list + * \li WaylandSurface.OriginTopLeft The origin is the top left corner of the buffer. + * \li WaylandSurface.OriginBottomLeft The origin is the bottom left corner of the buffer. + * \endlist + */ - emit visibilityChanged(); +/*! + * \property QWaylandSurface::origin + * + * This property holds the origin of the QWaylandSurface's buffer, or + * QWaylandSurface::OriginTopLeft if the surface has no buffer. + */ +QWaylandSurface::Origin QWaylandSurface::origin() const +{ + Q_D(const QWaylandSurface); + return d->buffer ? d->buffer->origin() : QWaylandSurface::OriginTopLeft; } -bool QWaylandSurface::sendInterfaceOp(QWaylandSurfaceOp &op) +/*! + * Returns the compositor for this QWaylandSurface. + */ +QWaylandCompositor *QWaylandSurface::compositor() const { - Q_D(QWaylandSurface); - foreach (QWaylandSurfaceInterface *iface, d->interfaces) { - if (iface->runOperation(&op)) - return true; - } - return false; + Q_D(const QWaylandSurface); + return d->compositor; } -void QWaylandSurface::ping() +/*! + * Prepares all frame callbacks for sending. + */ +void QWaylandSurface::frameStarted() { Q_D(QWaylandSurface); - uint32_t serial = wl_display_next_serial(compositor()->waylandDisplay()); - QWaylandSurfacePingOp op(serial); - if (!sendInterfaceOp(op)) { - int id = wl_resource_get_id(d->resource()->handle); - qWarning("No surface interface forwarded the ping for this surface (wl_surface@%d).", id); - } + foreach (QtWayland::FrameCallback *c, d->frameCallbacks) + c->canSend = true; } -void QWaylandSurface::sendOnScreenVisibilityChange(bool visible) +/*! + * Sends pending frame callbacks. + */ +void QWaylandSurface::sendFrameCallbacks() { - setVisibility(visible ? QWindow::AutomaticVisibility : QWindow::Hidden); + Q_D(QWaylandSurface); + uint time = d->compositor->currentTimeMsecs(); + int i = 0; + while (i < d->frameCallbacks.size()) { + if (d->frameCallbacks.at(i)->canSend) { + d->frameCallbacks.at(i)->surface = Q_NULLPTR; + d->frameCallbacks.at(i)->send(time); + d->frameCallbacks.removeAt(i); + } else { + i++; + } + } } -QString QWaylandSurface::className() const +/*! + * Returns true if the QWaylandSurface has an input panel surface. Otherwise returns false. + */ +bool QWaylandSurface::hasInputPanelSurface() const { Q_D(const QWaylandSurface); - return d->className(); -} -QString QWaylandSurface::title() const -{ - Q_D(const QWaylandSurface); - return d->title(); + return d->inputPanelSurface != 0; } -bool QWaylandSurface::hasInputPanelSurface() const +/*! + * Returns true if the QWaylandSurface's input region contains the point \a p. + * Otherwise returns false. + */ +bool QWaylandSurface::inputRegionContains(const QPoint &p) const { Q_D(const QWaylandSurface); - - return d->inputPanelSurface() != 0; + return d->inputRegion.contains(p); } /*! - * \return True if WL_SHELL_SURFACE_TRANSIENT_INACTIVE was set for this surface, meaning it should not receive keyboard focus. + * \qmlmethod void QtWaylandCompositor::WaylandSurface::destroy() + * + * Destroys the QWaylandSurface. + */ + +/*! + * Destroys the QWaylandSurface. */ -bool QWaylandSurface::transientInactive() const +void QWaylandSurface::destroy() { - Q_D(const QWaylandSurface); - return d->transientInactive(); + Q_D(QWaylandSurface); + d->deref(); } -bool QWaylandSurface::inputRegionContains(const QPoint &p) const +/*! + * \qmlmethod bool QtWaylandCompositor::WaylandSurface::isDestroyed() + * + * Returns true if the WaylandSurface has been destroyed. Otherwise returns false. + */ + +/*! + * Returns true if the QWaylandSurface has been destroyed. Otherwise returns false. + */ +bool QWaylandSurface::isDestroyed() const { Q_D(const QWaylandSurface); - return d->inputRegion().contains(p); + return d->destroyed; } -void QWaylandSurface::destroy() +/*! + * \qmlproperty bool QtWaylandCompositor::WaylandSurface::cursorSurface + * + * This property holds whether the WaylandSurface is a cursor surface. + */ + +/*! + * \property QWaylandSurface::cursorSurface + * + * This property holds whether the QWaylandSurface is a cursor surface. + */ +void QWaylandSurface::markAsCursorSurface(bool cursorSurface) { Q_D(QWaylandSurface); - if (--d->refCount == 0) - compositor()->handle()->destroySurface(d); + d->isCursorSurface = cursorSurface; } -void QWaylandSurface::destroySurface() +bool QWaylandSurface::isCursorSurface() const { - QWaylandSurfaceOp op(QWaylandSurfaceOp::Close); - if (!sendInterfaceOp(op)) - emit surfaceDestroyed(); + Q_D(const QWaylandSurface); + return d->isCursorSurface; } /*! - Updates the surface with the compositor's retained clipboard selection. While this - is done automatically when the surface receives keyboard focus, this function is - useful for updating clients which do not have keyboard focus. -*/ + * Updates the surface with the compositor's retained clipboard selection. While this + * is done automatically when the surface receives keyboard focus, this function is + * useful for updating clients which do not have keyboard focus. + */ void QWaylandSurface::updateSelection() { Q_D(QWaylandSurface); - const QtWayland::InputDevice *inputDevice = d->compositor()->defaultInputDevice(); + QWaylandInputDevice *inputDevice = d->compositor->defaultInputDevice(); if (inputDevice) { - const QtWayland::DataDevice *dataDevice = inputDevice->dataDevice(); + const QtWayland::DataDevice *dataDevice = QWaylandInputDevicePrivate::get(inputDevice)->dataDevice(); if (dataDevice) { - d->compositor()->dataDeviceManager()->offerRetainedSelection( + QWaylandCompositorPrivate::get(d->compositor)->dataDeviceManager()->offerRetainedSelection( dataDevice->resourceMap().value(d->resource()->client())->handle); } } } -void QWaylandSurface::ref() +/*! + * Returns this QWaylandSurface's throttling view. + * + * \sa QWaylandView::advance() + */ +QWaylandView *QWaylandSurface::throttlingView() const { - Q_D(QWaylandSurface); - ++d->refCount; + Q_D(const QWaylandSurface); + if (d->views.isEmpty()) + return Q_NULLPTR; + return d->views.first(); } -void QWaylandSurface::setMapped(bool mapped) +/*! + * Sets this QWaylandSurface's throttling view to \a view, in case there are + * multiple views of this surface. The throttling view is the view that + * governs the client's refresh rate. It takes care of discarding buffer + * references when QWaylandView::advance() is called. See the documentation + * for QWaylandView::advance() for more details. + * + * \sa QWaylandView::advance() + */ +void QWaylandSurface::setThrottlingView(QWaylandView *view) { Q_D(QWaylandSurface); - d->setMapped(mapped); -} -void QWaylandSurface::setBufferAttacher(QWaylandBufferAttacher *attacher) -{ - Q_D(QWaylandSurface); - if (d->m_attacher) { - delete d->m_attacher; + if (!view) + return; + + int index = d->views.indexOf(view); + + if (index < 0) { + view->setSurface(this); + index = d->views.indexOf(view); } - d->m_attacher = attacher; -} -QWaylandBufferAttacher *QWaylandSurface::bufferAttacher() const -{ - Q_D(const QWaylandSurface); - return d->m_attacher; + d->views.move(index, 0); } -QList<QWaylandSurfaceView *> QWaylandSurface::views() const +/*! + * Returns the views for this QWaylandSurface. + */ +QList<QWaylandView *> QWaylandSurface::views() const { Q_D(const QWaylandSurface); return d->views; } -QList<QWaylandSurfaceInterface *> QWaylandSurface::interfaces() const +/*! + * Returns the QWaylandSurface corresponding to the Wayland resource \a res. + */ +QWaylandSurface *QWaylandSurface::fromResource(::wl_resource *res) { - Q_D(const QWaylandSurface); - return d->interfaces; + return static_cast<QWaylandSurfacePrivate *>(QWaylandSurfacePrivate::Resource::fromResource(res)->surface_object)->q_func(); } -QWaylandSurface *QWaylandSurface::fromResource(::wl_resource *res) +/*! + * Returns the Wayland resource corresponding to this QWaylandSurface. + */ +struct wl_resource *QWaylandSurface::resource() const { - QtWayland::Surface *s = QtWayland::Surface::fromResource(res); - if (s) - return s->waylandSurface(); - return Q_NULLPTR; + Q_D(const QWaylandSurface); + return d->resource()->handle; } -void QWaylandSurfacePrivate::setTitle(const QString &title) +QWaylandSurfacePrivate *QWaylandSurfacePrivate::get(QWaylandSurface *surface) { - Q_Q(QWaylandSurface); - if (m_title != title) { - m_title = title; - emit q->titleChanged(); - } + return surface ? surface->d_func() : Q_NULLPTR; } -void QWaylandSurfacePrivate::setClassName(const QString &className) +void QWaylandSurfacePrivate::ref() { - Q_Q(QWaylandSurface); - if (m_className != className) { - m_className = className; - emit q->classNameChanged(); - } + ++refCount; } -void QWaylandSurfacePrivate::setType(QWaylandSurface::WindowType type) +void QWaylandSurfacePrivate::deref() { - Q_Q(QWaylandSurface); - if (windowType != type) { - windowType = type; - emit q->windowTypeChanged(type); - } + if (--refCount == 0) + QWaylandCompositorPrivate::get(compositor)->destroySurface(q_func()); } -class QWaylandUnmapLockPrivate +void QWaylandSurfacePrivate::refView(QWaylandView *view) { -public: - QWaylandSurface *surface; -}; - -/*! - Constructs a QWaylandUnmapLock object. + if (views.contains(view)) + return; - The lock will act on the \a surface parameter, and will prevent the surface to - be unmapped, retaining the last valid buffer when the client attachs a NULL buffer. - The lock will be automatically released when deleted. -*/ -QWaylandUnmapLock::QWaylandUnmapLock(QWaylandSurface *surface) - : d(new QWaylandUnmapLockPrivate) -{ - d->surface = surface; - surface->handle()->addUnmapLock(this); + views.append(view); + ref(); + QWaylandBufferRef ref(buffer); + view->attach(ref, QRect(QPoint(0,0), ref.size())); } -QWaylandUnmapLock::~QWaylandUnmapLock() +void QWaylandSurfacePrivate::derefView(QWaylandView *view) { - d->surface->handle()->removeUnmapLock(this); - delete d; + int nViews = views.removeAll(view); + + for (int i = 0; i < nViews && refCount > 0; i++) { + deref(); + } } QT_END_NAMESPACE |