summaryrefslogtreecommitdiffstats
path: root/src/compositor/compositor_api/qwaylandsurface.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/compositor/compositor_api/qwaylandsurface.cpp')
-rw-r--r--src/compositor/compositor_api/qwaylandsurface.cpp870
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