diff options
Diffstat (limited to 'src/compositor/compositor_api')
53 files changed, 7551 insertions, 2808 deletions
diff --git a/src/compositor/compositor_api/compositor_api.pri b/src/compositor/compositor_api/compositor_api.pri index 903eef9e5..70f3e3a12 100644 --- a/src/compositor/compositor_api/compositor_api.pri +++ b/src/compositor/compositor_api/compositor_api.pri @@ -2,30 +2,41 @@ INCLUDEPATH += compositor_api HEADERS += \ compositor_api/qwaylandcompositor.h \ + compositor_api/qwaylandcompositor_p.h \ compositor_api/qwaylandclient.h \ compositor_api/qwaylandsurface.h \ compositor_api/qwaylandsurface_p.h \ compositor_api/qwaylandinput.h \ + compositor_api/qwaylandinput_p.h \ + compositor_api/qwaylandkeyboard.h \ + compositor_api/qwaylandkeyboard_p.h \ + compositor_api/qwaylandpointer.h \ + compositor_api/qwaylandpointer_p.h \ + compositor_api/qwaylandtouch.h \ + compositor_api/qwaylandtouch_p.h \ compositor_api/qwaylandinputpanel.h \ compositor_api/qwaylandoutput.h \ compositor_api/qwaylanddrag.h \ compositor_api/qwaylandbufferref.h \ - compositor_api/qwaylandsurfaceview.h \ - compositor_api/qwaylandglobalinterface.h \ - compositor_api/qwaylandsurfaceinterface.h + compositor_api/qwaylanddestroylistener.h \ + compositor_api/qwaylanddestroylistener_p.h \ + compositor_api/qwaylandview.h \ + compositor_api/qwaylandview_p.h \ SOURCES += \ compositor_api/qwaylandcompositor.cpp \ compositor_api/qwaylandclient.cpp \ compositor_api/qwaylandsurface.cpp \ compositor_api/qwaylandinput.cpp \ + compositor_api/qwaylandkeyboard.cpp \ + compositor_api/qwaylandpointer.cpp \ + compositor_api/qwaylandtouch.cpp \ compositor_api/qwaylandinputpanel.cpp \ compositor_api/qwaylandoutput.cpp \ compositor_api/qwaylanddrag.cpp \ compositor_api/qwaylandbufferref.cpp \ - compositor_api/qwaylandsurfaceview.cpp \ - compositor_api/qwaylandglobalinterface.cpp \ - compositor_api/qwaylandsurfaceinterface.cpp + compositor_api/qwaylanddestroylistener.cpp \ + compositor_api/qwaylandview.cpp \ QT += core-private @@ -34,16 +45,14 @@ qtHaveModule(quick) { compositor_api/qwaylandquickcompositor.cpp \ compositor_api/qwaylandquicksurface.cpp \ compositor_api/qwaylandquickoutput.cpp \ - compositor_api/qwaylandsurfaceitem.cpp \ - compositor_api/qwaylandtexturebufferattacher.cpp + compositor_api/qwaylandquickitem.cpp HEADERS += \ compositor_api/qwaylandquickcompositor.h \ compositor_api/qwaylandquicksurface.h \ compositor_api/qwaylandquickoutput.h \ - compositor_api/qwaylandsurfaceitem.h \ - compositor_api/qwaylandtexturebufferattacher_p.h + compositor_api/qwaylandquickitem.h \ + compositor_api/qwaylandquickitem_p.h - - QT += qml quick + QT += qml qml-private quick quick-private } diff --git a/src/compositor/compositor_api/qwaylandbufferref.cpp b/src/compositor/compositor_api/qwaylandbufferref.cpp index 68e52317b..d0fe7ca40 100644 --- a/src/compositor/compositor_api/qwaylandbufferref.cpp +++ b/src/compositor/compositor_api/qwaylandbufferref.cpp @@ -3,9 +3,9 @@ ** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.com> ** Contact: http://www.qt.io/licensing/ ** -** This file is part of the plugins of the Qt Toolkit. +** This file is part of the QtWaylandCompositor module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $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 @@ -16,16 +16,19 @@ ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** 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. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** 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$ ** @@ -43,14 +46,33 @@ class QWaylandBufferRefPrivate { public: QtWayland::SurfaceBuffer *buffer; + + bool nullOrDestroyed() { + return !buffer || buffer->isDestroyed(); + } }; +/*! + * \class QWaylandBufferRef + * \inmodule QtWaylandCompositor + * \brief A class which holds a reference to a surface buffer + * + * This class can be used to reference a surface buffer. As long as a reference + * to the buffer exists, it is owned by the compositor and the client cannot modify it. + */ + +/*! + * Constructs a null buffer ref. + */ QWaylandBufferRef::QWaylandBufferRef() : d(new QWaylandBufferRefPrivate) { d->buffer = 0; } +/*! + * Constructs a reference to \a buffer. + */ QWaylandBufferRef::QWaylandBufferRef(QtWayland::SurfaceBuffer *buffer) : d(new QWaylandBufferRefPrivate) { @@ -59,13 +81,20 @@ QWaylandBufferRef::QWaylandBufferRef(QtWayland::SurfaceBuffer *buffer) buffer->ref(); } +/*! + * Creates a new reference to the buffer referenced by \a ref. + */ QWaylandBufferRef::QWaylandBufferRef(const QWaylandBufferRef &ref) : d(new QWaylandBufferRefPrivate) { - d->buffer = 0; - *this = ref; + d->buffer = ref.d->buffer; + if (d->buffer) + d->buffer->ref(); } +/*! + * Dereferences the buffer. + */ QWaylandBufferRef::~QWaylandBufferRef() { if (d->buffer) @@ -73,6 +102,10 @@ QWaylandBufferRef::~QWaylandBufferRef() delete d; } +/*! + * Assigns \a ref to this buffer. The previously referenced buffer is + * dereferenced and the new one gets a new reference. + */ QWaylandBufferRef &QWaylandBufferRef::operator=(const QWaylandBufferRef &ref) { if (d->buffer) @@ -85,61 +118,137 @@ QWaylandBufferRef &QWaylandBufferRef::operator=(const QWaylandBufferRef &ref) return *this; } -QWaylandBufferRef::operator bool() const +/*! + * Returns true if this QWaylandBufferRef references the same buffer as \a ref. + * Otherwise returns false. + */ +bool QWaylandBufferRef::operator==(const QWaylandBufferRef &ref) { - return d->buffer && d->buffer->waylandBufferHandle(); + return d->buffer == ref.d->buffer; } -bool QWaylandBufferRef::isShm() const +/*! + * Returns false if this QWaylandBufferRef references the same buffer as \a ref. + * Otherwise returns true. + */ +bool QWaylandBufferRef::operator!=(const QWaylandBufferRef &ref) { - return d->buffer->isShmBuffer(); + return d->buffer != ref.d->buffer; } -QImage QWaylandBufferRef::image() const +/*! + * Returns true if this QWaylandBufferRef does not reference a buffer. + * Otherwise returns false. + * + * \sa hasBuffer() + */ +bool QWaylandBufferRef::isNull() const { - if (d->buffer->isShmBuffer()) - return d->buffer->image(); - return QImage(); + return !d->buffer; } -void *QWaylandBufferRef::waylandBuffer() const +/*! + * Returns true if this QWaylandBufferRef references a buffer. Otherwise returns false. + * + * \sa isNull() + */ +bool QWaylandBufferRef::hasBuffer() const { - return d->buffer->waylandBufferHandle(); + return d->buffer; } -#ifdef QT_COMPOSITOR_WAYLAND_GL +/*! + * Returns true if this QWaylandBufferRef references a buffer that + * has been destroyed. Otherwise returns false. + */ +bool QWaylandBufferRef::isDestroyed() const +{ + return d->buffer && d->buffer->isDestroyed(); +} -GLenum QWaylandBufferRef::textureTarget() const +/*! + * Returns the Wayland resource for the buffer. + */ +struct ::wl_resource *QWaylandBufferRef::wl_buffer() const { - Q_ASSERT(d->buffer->textureCreated()); - return d->buffer->textureTarget(); + return d->buffer ? d->buffer->waylandBufferHandle() : Q_NULLPTR; } -GLuint QWaylandBufferRef::createTexture() +/*! + * Returns the size of the buffer. + * If the buffer referenced is null, an invalid QSize() is returned. + */ +QSize QWaylandBufferRef::size() const { - if (!d->buffer->isShmBuffer() && !d->buffer->textureCreated()) { - d->buffer->createTexture(); - } - return d->buffer->texture(); + if (d->nullOrDestroyed()) + return QSize(); + + return d->buffer->size(); } -void QWaylandBufferRef::updateTexture() +/*! + * Returns the origin of the buffer. + * If the buffer referenced is null, QWaylandSurface::OriginBottomLeft + * is returned. + */ +QWaylandSurface::Origin QWaylandBufferRef::origin() const { - if (!d->buffer->isShmBuffer() && d->buffer->textureCreated()) - d->buffer->updateTexture(); + if (d->buffer) + return d->buffer->origin(); + + return QWaylandSurface::OriginBottomLeft; } -void QWaylandBufferRef::destroyTexture() +/*! + * Returns true if the buffer is a shared memory buffer. Otherwise returns false. + */ +bool QWaylandBufferRef::isShm() const { - if (!d->buffer->isShmBuffer() && d->buffer->textureCreated()) { - d->buffer->destroyTexture(); - } + if (d->nullOrDestroyed()) + return false; + + return d->buffer->isShm(); } -void *QWaylandBufferRef::nativeBuffer() const +/*! + * Returns an image with the contents of the buffer. + */ +QImage QWaylandBufferRef::image() const { - return d->buffer->handle(); + if (d->nullOrDestroyed()) + return QImage(); + + return d->buffer->image(); +} + +/*! + * Binds the buffer to the current OpenGL texture. This may + * perform a copy of the buffer data, depending on the platform + * and the type of the buffer. + */ +void QWaylandBufferRef::bindToTexture() const +{ + if (d->nullOrDestroyed()) + return; + + return d->buffer->bindToTexture(); + +} + +int QWaylandBufferRef::textureTarget() const +{ + if (d->nullOrDestroyed()) + return 0x0DE1; // GL_TEXTURE_2D + + return d->buffer->textureTarget(); +} + +void QWaylandBufferRef::updateTexture() const +{ + if (d->nullOrDestroyed() || d->buffer->isShm()) + return; + + d->buffer->updateTexture(); } -#endif QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandbufferref.h b/src/compositor/compositor_api/qwaylandbufferref.h index 618a36622..5683a0b31 100644 --- a/src/compositor/compositor_api/qwaylandbufferref.h +++ b/src/compositor/compositor_api/qwaylandbufferref.h @@ -3,9 +3,9 @@ ** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.com> ** Contact: http://www.qt.io/licensing/ ** -** This file is part of the plugins of the Qt Toolkit. +** This file is part of the QtWaylandCompositor module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $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 @@ -16,16 +16,19 @@ ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** 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. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** 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$ ** @@ -40,7 +43,10 @@ #include <QtGui/qopengl.h> #endif -#include <QtCompositor/qwaylandexport.h> +#include <QtWaylandCompositor/QWaylandSurface> +#include <QtWaylandCompositor/qwaylandexport.h> + +struct wl_resource; QT_BEGIN_NAMESPACE @@ -58,24 +64,23 @@ public: ~QWaylandBufferRef(); QWaylandBufferRef &operator=(const QWaylandBufferRef &ref); - operator bool() const; - bool isShm() const; + bool isNull() const; + bool hasBuffer() const; + bool isDestroyed() const; + bool operator==(const QWaylandBufferRef &ref); + bool operator!=(const QWaylandBufferRef &ref); + + struct wl_resource *wl_buffer() const; + + QSize size() const; + QWaylandSurface::Origin origin() const; + bool isShm() const; QImage image() const; - void *waylandBuffer() const; -#ifdef QT_COMPOSITOR_WAYLAND_GL - /** - * There must be a GL context bound when calling this function. - * The texture will be automatically destroyed when the last QWaylandBufferRef - * referring to the same underlying buffer will be destroyed or reset. - */ - GLuint createTexture(); - GLenum textureTarget() const; - void updateTexture(); - void destroyTexture(); - void *nativeBuffer() const; -#endif + void bindToTexture() const; + int textureTarget() const; + void updateTexture() const; private: class QWaylandBufferRefPrivate *const d; diff --git a/src/compositor/compositor_api/qwaylandclient.cpp b/src/compositor/compositor_api/qwaylandclient.cpp index 216abc4f8..65f1d6349 100644 --- a/src/compositor/compositor_api/qwaylandclient.cpp +++ b/src/compositor/compositor_api/qwaylandclient.cpp @@ -3,46 +3,43 @@ ** Copyright (C) 2014 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> ** 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 <private/qobject_p.h> - -#include "wayland_wrapper/qwlcompositor_p.h" -#include "qwaylandcompositor.h" #include "qwaylandclient.h" +#include <QtCore/private/qobject_p.h> + +#include <QtWaylandCompositor/QWaylandCompositor> +#include <QtWaylandCompositor/private/qwaylandcompositor_p.h> + #include <wayland-server.h> #include <wayland-util.h> @@ -52,8 +49,9 @@ QT_BEGIN_NAMESPACE class QWaylandClientPrivate : public QObjectPrivate { public: - QWaylandClientPrivate(wl_client *_client) - : client(_client) + QWaylandClientPrivate(QWaylandCompositor *compositor, wl_client *_client) + : compositor(compositor) + , client(_client) { // Save client credentials wl_client_get_credentials(client, &pid, &uid, &gid); @@ -69,10 +67,10 @@ public: QWaylandClient *client = reinterpret_cast<Listener *>(listener)->parent; Q_ASSERT(client != 0); - QtWayland::Compositor::instance()->m_clients.removeOne(client); delete client; } + QWaylandCompositor *compositor; wl_client *client; uid_t uid; @@ -86,8 +84,29 @@ public: Listener listener; }; -QWaylandClient::QWaylandClient(wl_client *client) - : QObject(*new QWaylandClientPrivate(client)) +/*! + * \qmltype WaylandClient + * \inqmlmodule QtWayland.Compositor + * \brief A client connecting to the WaylandCompositor. + * + * This type represents a client connecting to the compositor using the Wayland protocol. + * It corresponds to the Wayland interface wl_client. + */ + +/*! + * \class QWaylandClient + * \inmodule QtWaylandCompositor + * \brief A client connecting to the QWaylandCompositor. + * + * This class corresponds to a client connecting to the compositor using the Wayland protocol. + * It corresponds to the Wayland interface wl_client. + */ + +/*! + * Constructs a QWaylandClient for the \a compositor and the Wayland \a client. + */ +QWaylandClient::QWaylandClient(QWaylandCompositor *compositor, wl_client *client) + : QObject(*new QWaylandClientPrivate(compositor, client)) { Q_D(QWaylandClient); @@ -95,17 +114,29 @@ QWaylandClient::QWaylandClient(wl_client *client) d->listener.parent = this; d->listener.listener.notify = QWaylandClientPrivate::client_destroy_callback; wl_client_add_destroy_listener(client, &d->listener.listener); + + QWaylandCompositorPrivate::get(compositor)->addClient(this); } +/*! + * Destroys the QWaylandClient. + */ QWaylandClient::~QWaylandClient() { Q_D(QWaylandClient); // Remove listener from signal wl_list_remove(&d->listener.listener.link); + + QWaylandCompositorPrivate::get(d->compositor)->removeClient(this); } -QWaylandClient *QWaylandClient::fromWlClient(wl_client *wlClient) +/*! + * Returns the QWaylandClient corresponding to the Wayland client \a wl_client and \a compositor. + * If a QWaylandClient has not already been created for \a client, it is + * created and returned. + */ +QWaylandClient *QWaylandClient::fromWlClient(QWaylandCompositor *compositor, wl_client *wlClient) { if (!wlClient) return 0; @@ -124,13 +155,15 @@ QWaylandClient *QWaylandClient::fromWlClient(wl_client *wlClient) // bind several times resulting in multiple QWaylandClient // instances for the same wl_client therefore we create it from // here on demand - client = new QWaylandClient(wlClient); - QtWayland::Compositor::instance()->m_clients.append(client); + client = new QWaylandClient(compositor, wlClient); } return client; } +/*! + * Returns the Wayland client of this QWaylandClient. + */ wl_client *QWaylandClient::client() const { Q_D(const QWaylandClient); @@ -138,6 +171,17 @@ wl_client *QWaylandClient::client() const return d->client; } +/*! + * \qmlproperty int QtWaylandCompositor::WaylandClient::userId + * + * This property holds the user id of this WaylandClient. + */ + +/*! + * \property QWaylandClient::userId + * + * This property holds the user id of this QWaylandClient. + */ qint64 QWaylandClient::userId() const { Q_D(const QWaylandClient); @@ -145,6 +189,17 @@ qint64 QWaylandClient::userId() const return d->uid; } +/*! + * \qmlproperty int QtWaylandCompositor::WaylandClient::groupId + * + * This property holds the group id of this WaylandClient. + */ + +/*! + * \property int QWaylandClient::groupId + * + * This property holds the group id of this QWaylandClient. + */ qint64 QWaylandClient::groupId() const { Q_D(const QWaylandClient); @@ -152,6 +207,17 @@ qint64 QWaylandClient::groupId() const return d->gid; } +/*! + * \qmlproperty int QtWaylandCompositor::WaylandClient::processId + * + * This property holds the process id of this WaylandClient. + */ + +/*! + * \property QWaylandClient::processId + * + * This property holds the process id of this QWaylandClient. + */ qint64 QWaylandClient::processId() const { Q_D(const QWaylandClient); @@ -159,16 +225,35 @@ qint64 QWaylandClient::processId() const return d->pid; } -void QWaylandClient::kill(int sig) +/*! + * \qmlmethod void QtWaylandCompositor::WaylandClient::kill(signal) + * + * Kills the client with the specified \a signal. + */ + +/*! + * Kills the client with the specified \a signal. + */ +void QWaylandClient::kill(int signal) { Q_D(QWaylandClient); - ::kill(d->pid, sig); + ::kill(d->pid, signal); } +/*! + * \qmlmethod void QtWaylandCompositor::WaylandClient::close() + * + * Closes the client + */ + +/*! + * Closes the client. + */ void QWaylandClient::close() { - QtWayland::Compositor::instance()->waylandCompositor()->destroyClient(this); + Q_D(QWaylandClient); + d->compositor->destroyClient(this); } QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandclient.h b/src/compositor/compositor_api/qwaylandclient.h index 9199406b3..800013d3d 100644 --- a/src/compositor/compositor_api/qwaylandclient.h +++ b/src/compositor/compositor_api/qwaylandclient.h @@ -3,36 +3,32 @@ ** Copyright (C) 2014 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> ** 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$ ** @@ -41,7 +37,7 @@ #ifndef QWAYLANDCLIENT_H #define QWAYLANDCLIENT_H -#include <QtCompositor/qwaylandexport.h> +#include <QtWaylandCompositor/qwaylandexport.h> #include <QObject> @@ -52,6 +48,7 @@ struct wl_client; QT_BEGIN_NAMESPACE class QWaylandClientPrivate; +class QWaylandCompositor; class Q_COMPOSITOR_EXPORT QWaylandClient : public QObject { @@ -64,7 +61,7 @@ class Q_COMPOSITOR_EXPORT QWaylandClient : public QObject public: ~QWaylandClient(); - static QWaylandClient *fromWlClient(wl_client *wlClient); + static QWaylandClient *fromWlClient(QWaylandCompositor *compositor, wl_client *wlClient); wl_client *client() const; @@ -73,13 +70,13 @@ public: qint64 processId() const; - Q_INVOKABLE void kill(int sig = SIGTERM); + Q_INVOKABLE void kill(int signal = SIGTERM); public Q_SLOTS: void close(); private: - explicit QWaylandClient(wl_client *client); + explicit QWaylandClient(QWaylandCompositor *compositor, wl_client *client); }; QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandcompositor.cpp b/src/compositor/compositor_api/qwaylandcompositor.cpp index 04d1c4aed..a431cdde8 100644 --- a/src/compositor/compositor_api/qwaylandcompositor.cpp +++ b/src/compositor/compositor_api/qwaylandcompositor.cpp @@ -4,367 +4,801 @@ ** 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 "qwaylandcompositor.h" +#include "qwaylandcompositor_p.h" + +#include <QtWaylandCompositor/qwaylandclient.h> +#include <QtWaylandCompositor/qwaylandinput.h> +#include <QtWaylandCompositor/qwaylandoutput.h> +#include <QtWaylandCompositor/qwaylandview.h> +#include <QtWaylandCompositor/qwaylandclient.h> +#include <QtWaylandCompositor/qwaylandkeyboard.h> +#include <QtWaylandCompositor/qwaylandpointer.h> +#include <QtWaylandCompositor/qwaylandtouch.h> -#include "qwaylandclient.h" -#include "qwaylandinput.h" -#include "qwaylandoutput.h" -#include "qwaylandglobalinterface.h" -#include "qwaylandsurfaceview.h" +#include <QtWaylandCompositor/private/qwaylandkeyboard_p.h> +#include <QtWaylandCompositor/private/qwaylandsurface_p.h> -#include "wayland_wrapper/qwlcompositor_p.h" #include "wayland_wrapper/qwldatadevice_p.h" -#include "wayland_wrapper/qwlsurface_p.h" -#include "wayland_wrapper/qwlinputdevice_p.h" -#include "wayland_wrapper/qwlinputpanel_p.h" -#include "wayland_wrapper/qwlshellsurface_p.h" +#include "wayland_wrapper/qwldatadevicemanager_p.h" + +#include "hardware_integration/qwlclientbufferintegration_p.h" +#include "hardware_integration/qwlclientbufferintegrationfactory_p.h" +#include "hardware_integration/qwlserverbufferintegration_p.h" +#include "hardware_integration/qwlserverbufferintegrationfactory_p.h" +#include "hardware_integration/qwlhwintegration_p.h" + +#include "extensions/qwaylandwindowmanagerextension.h" + +#include "qwaylandxkb.h" +#include "qwaylandshmformathelper.h" #include <QtCore/QCoreApplication> #include <QtCore/QStringList> +#include <QtCore/QSocketNotifier> #include <QtGui/QDesktopServices> #include <QtGui/QScreen> -#include <QDebug> +#include <QtGui/qpa/qwindowsysteminterface_p.h> +#include <QtGui/qpa/qplatformnativeinterface.h> +#include <QtGui/private/qguiapplication_p.h> QT_BEGIN_NAMESPACE -QWaylandCompositor::QWaylandCompositor(const char *socketName, ExtensionFlags extensions) - : m_compositor(new QtWayland::Compositor(this, extensions)) +namespace QtWayland { + +class WindowSystemEventHandler : public QWindowSystemEventHandler { - m_compositor->m_socket_name = socketName; - m_compositor->init(); -} +public: + WindowSystemEventHandler(QWaylandCompositor *c) : compositor(c) {} + bool sendEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *e) Q_DECL_OVERRIDE + { + if (e->type == QWindowSystemInterfacePrivate::Key) { + QWindowSystemInterfacePrivate::KeyEvent *ke = static_cast<QWindowSystemInterfacePrivate::KeyEvent *>(e); + QWaylandKeyboardPrivate *keyb = QWaylandKeyboardPrivate::get(compositor->defaultInputDevice()->keyboard()); + + uint32_t code = ke->nativeScanCode; + bool isDown = ke->keyType == QEvent::KeyPress; + +#ifndef QT_NO_WAYLAND_XKB + QString text; + Qt::KeyboardModifiers modifiers = QWaylandXkb::modifiers(keyb->xkbState()); + + const xkb_keysym_t sym = xkb_state_key_get_one_sym(keyb->xkbState(), code); + uint utf32 = xkb_keysym_to_utf32(sym); + if (utf32) + text = QString::fromUcs4(&utf32, 1); + int qtkey = QWaylandXkb::keysymToQtKey(sym, modifiers, text); + + ke->key = qtkey; + ke->modifiers = modifiers; + ke->nativeVirtualKey = sym; + ke->nativeModifiers = keyb->xkbModsMask(); + ke->unicode = text; +#endif + if (!ke->repeat) + keyb->keyEvent(code, isDown ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED); -QWaylandCompositor::QWaylandCompositor(const char *socketName, QtWayland::Compositor *dptr) - : m_compositor(dptr) + QWindowSystemEventHandler::sendEvent(e); + + if (!ke->repeat) { + keyb->updateKeymap(); + keyb->updateModifierState(code, isDown ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED); + } + } else { + QWindowSystemEventHandler::sendEvent(e); + } + return true; + } + + QWaylandCompositor *compositor; +}; + +} // namespace + +QWaylandCompositorPrivate::QWaylandCompositorPrivate(QWaylandCompositor *compositor) + : display(0) +#if defined (QT_COMPOSITOR_WAYLAND_GL) + , use_hw_integration_extension(true) + , client_buffer_integration(0) + , server_buffer_integration(0) +#endif + , retainSelection(false) + , initialized(false) { - m_compositor->m_socket_name = socketName; - m_compositor->init(); + display = static_cast<wl_display*>(QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("server_wl_display")); + if (!display) + display = wl_display_create(); + eventHandler.reset(new QtWayland::WindowSystemEventHandler(compositor)); + timer.start(); + + QWindowSystemInterfacePrivate::installWindowSystemEventHandler(eventHandler.data()); } -QWaylandCompositor::~QWaylandCompositor() +void QWaylandCompositorPrivate::init() { - qDeleteAll(m_compositor->m_globals); - delete m_compositor; + Q_Q(QWaylandCompositor); + QStringList arguments = QCoreApplication::instance()->arguments(); + + int socketArg = arguments.indexOf(QLatin1String("--wayland-socket-name")); + if (socketArg != -1 && socketArg + 1 < arguments.size()) + socket_name = arguments.at(socketArg + 1).toLocal8Bit(); + + wl_compositor::init(display, 3); + + data_device_manager = new QtWayland::DataDeviceManager(q); + + wl_display_init_shm(display); + QVector<wl_shm_format> formats = QWaylandShmFormatHelper::supportedWaylandFormats(); + foreach (wl_shm_format format, formats) + wl_display_add_shm_format(display, format); + + const char *socketName = 0; + if (socket_name.size()) + socketName = socket_name.constData(); + if (wl_display_add_socket(display, socketName)) { + qFatal("Fatal: Failed to open server socket\n"); + } + + loop = wl_display_get_event_loop(display); + + int fd = wl_event_loop_get_fd(loop); + + QSocketNotifier *sockNot = new QSocketNotifier(fd, QSocketNotifier::Read, q); + QObject::connect(sockNot, SIGNAL(activated(int)), q, SLOT(processWaylandEvents())); + + QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::eventDispatcher; + QObject::connect(dispatcher, SIGNAL(aboutToBlock()), q, SLOT(processWaylandEvents())); + + initializeHardwareIntegration(); + initializeDefaultInputDevice(); + + initialized = true; + + Q_FOREACH (QPointer<QObject> object, polish_objects) { + if (object) { + QEvent polishEvent(QEvent::Polish); + QCoreApplication::sendEvent(object.data(), &polishEvent); + } + } } -void QWaylandCompositor::addGlobalInterface(QWaylandGlobalInterface *interface) +QWaylandCompositorPrivate::~QWaylandCompositorPrivate() { - wl_global_create(m_compositor->wl_display(), interface->interface(), interface->version(), interface, QtWayland::Compositor::bindGlobal); - m_compositor->m_globals << interface; + qDeleteAll(clients); + + qDeleteAll(outputs); + + delete data_device_manager; + + wl_display_destroy(display); } -void QWaylandCompositor::addDefaultShell() +void QWaylandCompositorPrivate::destroySurface(QWaylandSurface *surface) { - addGlobalInterface(new QtWayland::Shell); + Q_Q(QWaylandCompositor); + q->surfaceAboutToBeDestroyed(surface); + + delete surface; } -struct wl_display *QWaylandCompositor::waylandDisplay() const +void QWaylandCompositorPrivate::unregisterSurface(QWaylandSurface *surface) { - return m_compositor->wl_display(); + if (!all_surfaces.removeOne(surface)) + qWarning("%s Unexpected state. Cant find registered surface\n", Q_FUNC_INFO); } -void QWaylandCompositor::sendFrameCallbacks(QList<QWaylandSurface *> visibleSurfaces) +void QWaylandCompositorPrivate::feedRetainedSelectionData(QMimeData *data) { - m_compositor->sendFrameCallbacks(visibleSurfaces); + Q_Q(QWaylandCompositor); + if (retainSelection) + q->retainedSelectionReceived(data); } -void QWaylandCompositor::frameStarted() +void QWaylandCompositorPrivate::addPolishObject(QObject *object) { - foreach (QtWayland::Surface *surf, m_compositor->surfaces()) - surf->frameStarted(); + if (initialized) { + QCoreApplication::postEvent(object, new QEvent(QEvent::Polish)); + } else { + polish_objects.append(object); + } } -void QWaylandCompositor::destroyClientForSurface(QWaylandSurface *surface) +/*! + \qmlsignal void QtWaylandCompositor::WaylandCompositor::createSurface(object client, int id, int version) + + This signal is emitted when a client has created a surface. + The slot connecting to this signal may create and initialize + a WaylandSurface instance in the scope of the slot. + Otherwise a default surface is created. +*/ + +/*! + \fn void QWaylandCompositor::createSurface(QWaylandClient *client, uint id, int version) + + This signal is emitted when a client has created a surface. + The slot connecting to this signal may create and initialize + a QWaylandSurface instance in the scope of the slot. + Otherwise a default surface is created. + + Connections to this signal must be of Qt::DirectConnection connection type. +*/ + +/* + \qmlsignal void surfaceCreated(QWaylandSurface *surface) + + This signal is emitted when a new WaylandSurface instance has been created. +*/ + +/* + \fn void surfaceCreated(QWaylandSurface *surface) + + This signal is emitted when a new QWaylandSurface instance has been created. +*/ + + +void QWaylandCompositorPrivate::compositor_create_surface(Resource *resource, uint32_t id) { - destroyClient(surface->client()); + Q_Q(QWaylandCompositor); + QWaylandClient *client = QWaylandClient::fromWlClient(q, resource->client()); + emit q->createSurface(client, id, resource->version()); +#ifndef QT_NO_DEBUG + Q_ASSERT_X(!QWaylandSurfacePrivate::hasUninitializedSurface(), "QWaylandCompositor", QStringLiteral("Found uninitialized QWaylandSurface after emitting QWaylandCompositor::createSurface for id %1. All surfaces has to be initialized immediately after creation. See QWaylandSurface::initialize.").arg(id).toLocal8Bit().constData()); +#endif + struct wl_resource *surfResource = wl_client_get_object(client->client(), id); + + QWaylandSurface *surface; + if (surfResource) { + surface = QWaylandSurface::fromResource(surfResource); + } else { + surface = createDefaultSurface(); + surface->initialize(q, client, id, resource->version()); + } + Q_ASSERT(surface); + all_surfaces.append(surface); + emit q->surfaceCreated(surface); } -void QWaylandCompositor::destroyClient(QWaylandClient *client) +void QWaylandCompositorPrivate::compositor_create_region(Resource *resource, uint32_t id) { - m_compositor->destroyClient(client); + new QtWayland::Region(resource->client(), id); } -QList<QWaylandSurface *> QWaylandCompositor::surfacesForClient(QWaylandClient* client) const +/*! + \internal + Used to create a fallback QWaylandSurface when no surface was + created by emitting the QWaylandCompositor::createSurface signal. +*/ +QWaylandSurface *QWaylandCompositorPrivate::createDefaultSurface() { - QList<QtWayland::Surface *> surfaces = m_compositor->surfaces(); + return new QWaylandSurface(); +} - QList<QWaylandSurface *> result; - for (int i = 0; i < surfaces.count(); ++i) { - if (surfaces.at(i)->waylandSurface()->client() == client) { - result.append(surfaces.at(i)->waylandSurface()); - } - } +void QWaylandCompositorPrivate::initializeHardwareIntegration() +{ +#ifdef QT_COMPOSITOR_WAYLAND_GL + Q_Q(QWaylandCompositor); + if (use_hw_integration_extension) + hw_integration.reset(new QtWayland::HardwareIntegration(q)); + + loadClientBufferIntegration(); + loadServerBufferIntegration(); - return result; + if (client_buffer_integration) + client_buffer_integration->initializeHardware(display); + if (server_buffer_integration) + server_buffer_integration->initializeHardware(q); +#endif } -QList<QWaylandSurface *> QWaylandCompositor::surfaces() const +void QWaylandCompositorPrivate::initializeDefaultInputDevice() { - QList<QtWayland::Surface *> surfaces = m_compositor->surfaces(); - QList<QWaylandSurface *> surfs; - surfs.reserve(surfaces.count()); - foreach (QtWayland::Surface *s, surfaces) - surfs << s->waylandSurface(); - return surfs; + Q_Q(QWaylandCompositor); + inputDevices.append(q->createInputDevice()); + q->defaultInputDeviceChanged(); } -QList<QWaylandOutput *> QWaylandCompositor::outputs() const +void QWaylandCompositorPrivate::loadClientBufferIntegration() { - return m_compositor->outputs(); +#ifdef QT_COMPOSITOR_WAYLAND_GL + Q_Q(QWaylandCompositor); + QStringList keys = QtWayland::ClientBufferIntegrationFactory::keys(); + QString targetKey; + QByteArray clientBufferIntegration = qgetenv("QT_WAYLAND_HARDWARE_INTEGRATION"); + if (clientBufferIntegration.isEmpty()) + clientBufferIntegration = qgetenv("QT_WAYLAND_CLIENT_BUFFER_INTEGRATION"); + if (keys.contains(QString::fromLocal8Bit(clientBufferIntegration.constData()))) { + targetKey = QString::fromLocal8Bit(clientBufferIntegration.constData()); + } else if (keys.contains(QString::fromLatin1("wayland-egl"))) { + targetKey = QString::fromLatin1("wayland-egl"); + } else if (!keys.isEmpty()) { + targetKey = keys.first(); + } + + if (!targetKey.isEmpty()) { + client_buffer_integration.reset(QtWayland::ClientBufferIntegrationFactory::create(targetKey, QStringList())); + if (client_buffer_integration) { + client_buffer_integration->setCompositor(q); + if (hw_integration) + hw_integration->setClientBufferIntegration(targetKey); + } + } + //BUG: if there is no client buffer integration, bad things will happen when opengl is used +#endif } -QWaylandOutput *QWaylandCompositor::output(QWindow *window) +void QWaylandCompositorPrivate::loadServerBufferIntegration() { - return m_compositor->output(window); +#ifdef QT_COMPOSITOR_WAYLAND_GL + QStringList keys = QtWayland::ServerBufferIntegrationFactory::keys(); + QString targetKey; + QByteArray serverBufferIntegration = qgetenv("QT_WAYLAND_SERVER_BUFFER_INTEGRATION"); + if (keys.contains(QString::fromLocal8Bit(serverBufferIntegration.constData()))) { + targetKey = QString::fromLocal8Bit(serverBufferIntegration.constData()); + } + if (!targetKey.isEmpty()) { + server_buffer_integration.reset(QtWayland::ServerBufferIntegrationFactory::create(targetKey, QStringList())); + if (hw_integration) + hw_integration->setServerBufferIntegration(targetKey); + } +#endif } -QWaylandOutput *QWaylandCompositor::primaryOutput() const +/*! + \qmltype WaylandCompositor + \inqmlmodule QtWayland.Compositor + \brief Type managing the Wayland display server. + + The WaylandCompositor manages the connections to the clients, as well as the different + \l{WaylandOutput}{outputs} and \l{WaylandInput}{input devices}. + + Normally, a compositor application will have a single WaylandCompositor + instance, which can have several outputs as children. When a client + requests the compositor to create a surface, the request is handled by + the onCreateSurface handler. + + Extensions that are supported by the compositor should be instantiated and added to the + extensions property. +*/ + + +/*! + \class QWaylandCompositor + \inmodule QtWaylandCompositor + \brief Class managing the Wayland display server. + + The QWaylandCompositor manages the connections to the clients, as well as the different \l{QWaylandOutput}{outputs} + and \l{QWaylandInput}{input devices}. + + Normally, a compositor application will have a single WaylandCompositor + instance, which can have several outputs as children. +*/ + +/*! + * Constructs a QWaylandCompositor with the given \a parent. + */ +QWaylandCompositor::QWaylandCompositor(QObject *parent) + : QWaylandObject(*new QWaylandCompositorPrivate(this), parent) { - return m_compositor->primaryOutput(); } -void QWaylandCompositor::setPrimaryOutput(QWaylandOutput *output) +/*! + * \internal + * Constructs a QWaylandCompositor with the private object \a dptr and \a parent. + */ +QWaylandCompositor::QWaylandCompositor(QWaylandCompositorPrivate &dptr, QObject *parent) + : QWaylandObject(dptr, parent) { - m_compositor->setPrimaryOutput(output); } -void QWaylandCompositor::cleanupGraphicsResources() +/*! + * Destroys the QWaylandCompositor + */ +QWaylandCompositor::~QWaylandCompositor() { - m_compositor->cleanupGraphicsResources(); } -void QWaylandCompositor::surfaceAboutToBeDestroyed(QWaylandSurface *surface) +/*! + * Initializes the QWaylandCompositor. + * If you override this function in your subclass, be sure to call the base class implementation. + */ +void QWaylandCompositor::create() { - Q_UNUSED(surface); + Q_D(QWaylandCompositor); + d->init(); } -QWaylandSurfaceView *QWaylandCompositor::pickView(const QPointF &globalPosition) const +/*! + * Returns true if the QWaylandCompositor has been initialized. Otherwise returns false. + */ +bool QWaylandCompositor::isCreated() const { - Q_FOREACH (QWaylandOutput *output, outputs()) { - // Skip coordinates not in output - if (!QRectF(output->geometry()).contains(globalPosition)) - continue; + Q_D(const QWaylandCompositor); + return d->initialized; +} - Q_FOREACH (QWaylandSurface *surface, output->surfaces()) { - Q_FOREACH (QWaylandSurfaceView *view, surface->views()) { - if (QRectF(view->pos(), surface->size()).contains(globalPosition)) - return view; - } - } - } +/*! + * \qmlproperty string QtWaylandCompositor::WaylandCompositor::socketName + * + * This property holds the socket name used by WaylandCompositor to communicate with + * clients. It must be set before the component is completed. + * + * If the socketName is empty (the default), the contents of the environment + * variable WAYLAND_DISPLAY is used instead. If this is not set, the + * default "wayland-0" is used. + */ - return Q_NULLPTR; +/*! + * \property QWaylandCompositor::socketName + * + * This property holds the socket name used by QWaylandCompositor to communicate with + * clients. This must be set before the QWaylandCompositor is \l{create()}{created}. + * + * If the socketName is empty (the default), the contents of the environment + * variable WAYLAND_DISPLAY is used instead. If this is not set, the + * default "wayland-0" is used. + */ +void QWaylandCompositor::setSocketName(const QByteArray &name) +{ + Q_D(QWaylandCompositor); + if (d->initialized) { + qWarning("%s: Changing socket name after initializing the compositor is not supported.\n", Q_FUNC_INFO); + return; + } + d->socket_name = name; } -QPointF QWaylandCompositor::mapToView(QWaylandSurfaceView *surface, const QPointF &globalPosition) const +QByteArray QWaylandCompositor::socketName() const { - return globalPosition - surface->pos(); + Q_D(const QWaylandCompositor); + return d->socket_name; } /*! - Override this to handle QDesktopServices::openUrl() requests from the clients. - - The default implementation simply forwards the request to QDesktopServices::openUrl(). -*/ -bool QWaylandCompositor::openUrl(QWaylandClient *client, const QUrl &url) + * \internal + */ +struct wl_display *QWaylandCompositor::display() const { - Q_UNUSED(client); - return QDesktopServices::openUrl(url); + Q_D(const QWaylandCompositor); + return d->display; } -QtWayland::Compositor * QWaylandCompositor::handle() const +/*! + * \internal + */ +uint32_t QWaylandCompositor::nextSerial() { - return m_compositor; + Q_D(QWaylandCompositor); + return wl_display_next_serial(d->display); } -void QWaylandCompositor::setRetainedSelectionEnabled(bool enabled) +/*! + * \internal + */ +QList<QWaylandClient *>QWaylandCompositor::clients() const { - m_compositor->setRetainedSelectionEnabled(enabled); + Q_D(const QWaylandCompositor); + return d->clients; } -bool QWaylandCompositor::retainedSelectionEnabled() const +/*! + * \qmlmethod QtWaylandCompositor::WaylandCompositor::destroyClientForSurface(surface) + * + * Destroys the client for the WaylandSurface \a surface. + */ + +/*! + * Destroys the client for the \a surface. + */ +void QWaylandCompositor::destroyClientForSurface(QWaylandSurface *surface) { - return m_compositor->retainedSelectionEnabled(); + destroyClient(surface->client()); } -void QWaylandCompositor::retainedSelectionReceived(QMimeData *) +/*! + * \qmlmethod QtWaylandCompositor::WaylandCompositor::destroyClient(client) + * + * Destroys the given WaylandClient \a client. + */ + +/*! + * Destroys the \a client. + */ +void QWaylandCompositor::destroyClient(QWaylandClient *client) { + if (!client) + return; + + QWaylandWindowManagerExtension *wmExtension = QWaylandWindowManagerExtension::findIn(this); + if (wmExtension) + wmExtension->sendQuitMessage(client->client()); + + wl_client_destroy(client->client()); } -void QWaylandCompositor::overrideSelection(const QMimeData *data) +/*! + * \internal + */ +QList<QWaylandSurface *> QWaylandCompositor::surfacesForClient(QWaylandClient* client) const { - m_compositor->overrideSelection(data); + Q_D(const QWaylandCompositor); + QList<QWaylandSurface *> surfs; + foreach (QWaylandSurface *surface, d->all_surfaces) { + if (surface->client() == client) + surfs.append(surface); + } + return surfs; } -void QWaylandCompositor::setClientFullScreenHint(bool value) +/*! + * \internal + */ +QList<QWaylandSurface *> QWaylandCompositor::surfaces() const { - m_compositor->setClientFullScreenHint(value); + Q_D(const QWaylandCompositor); + return d->all_surfaces; } -const char *QWaylandCompositor::socketName() const -{ - if (m_compositor->m_socket_name.isEmpty()) - return 0; - return m_compositor->m_socket_name.constData(); +/*! + * Returns the QWaylandOutput that is connected to the given \a window. + */ +QWaylandOutput *QWaylandCompositor::outputFor(QWindow *window) const +{ + Q_D(const QWaylandCompositor); + foreach (QWaylandOutput *output, d->outputs) { + if (output->window() == window) + return output; + } + + return Q_NULLPTR; } -#if QT_DEPRECATED_SINCE(5, 5) /*! - Set the screen orientation based on accelerometer data or similar. -*/ -void QWaylandCompositor::setScreenOrientation(Qt::ScreenOrientation orientation) + * \qmlproperty object QtWaylandCompositor::WaylandCompositor::defaultOutput + * + * This property contains the first in the list of outputs added to the + * WaylandCompositor, or null if no outputs have been added. + * + * Setting a new default output prepends it to the output list, making + * it the new default, but the previous default is not removed from + * the list. + */ +/*! + * \property QWaylandCompositor::defaultOutput + * + * This property contains the first in the list of outputs added to the + * QWaylandCompositor, or null if no outputs have been added. + * + * Setting a new default output prepends it to the output list, making + * it the new default, but the previous default is not removed from + * the list. If the new default output was already in the list of outputs, + * it is moved to the beginning of the list. + */ +QWaylandOutput *QWaylandCompositor::defaultOutput() const { - QWaylandOutput *output = primaryOutput(); - if (output) { - bool isPortrait = output->window()->screen()->primaryOrientation() == Qt::PortraitOrientation; - - switch (orientation) { - case Qt::PrimaryOrientation: - output->setTransform(QWaylandOutput::TransformNormal); - break; - case Qt::LandscapeOrientation: - output->setTransform(isPortrait ? QWaylandOutput::Transform270 : QWaylandOutput::TransformNormal); - break; - case Qt::PortraitOrientation: - output->setTransform(isPortrait ? QWaylandOutput::TransformNormal : QWaylandOutput::Transform90); - break; - case Qt::InvertedLandscapeOrientation: - output->setTransform(isPortrait ? QWaylandOutput::Transform90 : QWaylandOutput::Transform180); - break; - case Qt::InvertedPortraitOrientation: - output->setTransform(isPortrait ? QWaylandOutput::Transform180 : QWaylandOutput::Transform270); - break; - } - } + Q_D(const QWaylandCompositor); + return d->defaultOutput(); } -void QWaylandCompositor::setOutputGeometry(const QRect &geometry) +void QWaylandCompositor::setDefaultOutput(QWaylandOutput *output) { - QWaylandOutput *output = primaryOutput(); - if (output) - output->setGeometry(geometry); + Q_D(QWaylandCompositor); + if (d->outputs.size() && d->outputs.first() == output) + return; + d->outputs.removeOne(output); + d->outputs.prepend(output); + defaultOutputChanged(); } -QRect QWaylandCompositor::outputGeometry() const +/*! + * \internal + */ +QList<QWaylandOutput *> QWaylandCompositor::outputs() const { - QWaylandOutput *output = primaryOutput(); - if (output) - return output->geometry(); - return QRect(); + Q_D(const QWaylandCompositor); + return d->outputs; } -void QWaylandCompositor::setOutputRefreshRate(int rate) +/*! + * \internal + */ +uint QWaylandCompositor::currentTimeMsecs() const { - QWaylandOutput *output = primaryOutput(); - if (output) - output->setMode({output->mode().size, rate}); + Q_D(const QWaylandCompositor); + return d->timer.elapsed(); } -int QWaylandCompositor::outputRefreshRate() const +/*! + * \internal + */ +void QWaylandCompositor::processWaylandEvents() { - QWaylandOutput *output = primaryOutput(); - if (output) - return output->mode().refreshRate; - return 0; + Q_D(QWaylandCompositor); + int ret = wl_event_loop_dispatch(d->loop, 0); + if (ret) + fprintf(stderr, "wl_event_loop_dispatch error: %d\n", ret); + wl_display_flush_clients(d->display); } -#endif -QWaylandInputDevice *QWaylandCompositor::defaultInputDevice() const +/*! + * \internal + */ +QWaylandInputDevice *QWaylandCompositor::createInputDevice() { - return m_compositor->defaultInputDevice()->handle(); + return new QWaylandInputDevice(this); } -QWaylandInputPanel *QWaylandCompositor::inputPanel() const +/*! + * \internal + */ +QWaylandPointer *QWaylandCompositor::createPointerDevice(QWaylandInputDevice *inputDevice) { - return m_compositor->inputPanel()->handle(); + return new QWaylandPointer(inputDevice); } -QWaylandDrag *QWaylandCompositor::drag() const +/*! + * \internal + */ +QWaylandKeyboard *QWaylandCompositor::createKeyboardDevice(QWaylandInputDevice *inputDevice) { - return m_compositor->defaultInputDevice()->dragHandle(); + return new QWaylandKeyboard(inputDevice); } -bool QWaylandCompositor::isDragging() const +/*! + * \internal + */ +QWaylandTouch *QWaylandCompositor::createTouchDevice(QWaylandInputDevice *inputDevice) { - return m_compositor->isDragging(); + return new QWaylandTouch(inputDevice); } -void QWaylandCompositor::sendDragMoveEvent(const QPoint &global, const QPoint &local, - QWaylandSurface *surface) +/*! + * \qmlproperty bool QtWaylandCompositor::WaylandCompositor::retainedSelection + * + * This property holds whether retained selection is enabled. + */ + +/*! + * \property QWaylandCompositor::retainedSelection + * + * This property holds whether retained selection is enabled. + */ +void QWaylandCompositor::setRetainedSelectionEnabled(bool enabled) { - m_compositor->sendDragMoveEvent(global, local, surface ? surface->handle() : 0); + Q_D(QWaylandCompositor); + d->retainSelection = enabled; } -void QWaylandCompositor::sendDragEndEvent() +bool QWaylandCompositor::retainedSelectionEnabled() const { - m_compositor->sendDragEndEvent(); + Q_D(const QWaylandCompositor); + return d->retainSelection; } -void QWaylandCompositor::setCursorSurface(QWaylandSurface *surface, int hotspotX, int hotspotY) +/*! + * \internal + */ +void QWaylandCompositor::retainedSelectionReceived(QMimeData *) { - Q_UNUSED(surface); - Q_UNUSED(hotspotX); - Q_UNUSED(hotspotY); } -void QWaylandCompositor::configureTouchExtension(TouchExtensionFlags flags) +/*! + * \internal + */ +void QWaylandCompositor::overrideSelection(const QMimeData *data) { - m_compositor->configureTouchExtension(flags); + Q_D(QWaylandCompositor); + d->data_device_manager->overrideSelection(*data); } -QWaylandSurfaceView *QWaylandCompositor::createView(QWaylandSurface *surface) +/*! + * \qmlproperty object QtWaylandCompositor::WaylandCompositor::defaultInputDevice + * + * This property contains the default input device for this + * WaylandCompositor. + */ + +/*! + * \property QWaylandCompositor::defaultInputDevice + * + * This property contains the default input device for this + * QWaylandCompositor. + */ +QWaylandInputDevice *QWaylandCompositor::defaultInputDevice() const { - return new QWaylandSurfaceView(surface); + Q_D(const QWaylandCompositor); + if (d->inputDevices.size()) + return d->inputDevices.first(); + return Q_NULLPTR; } +/*! + * \internal + * + * Currently, Qt only supports a single input device, so this exists for + * future proofing the APIs. + */ QWaylandInputDevice *QWaylandCompositor::inputDeviceFor(QInputEvent *inputEvent) { - return m_compositor->inputDeviceFor(inputEvent); + Q_D(QWaylandCompositor); + QWaylandInputDevice *dev = NULL; + for (int i = 0; i < d->inputDevices.size(); i++) { + QWaylandInputDevice *candidate = d->inputDevices.at(i); + if (candidate->isOwner(inputEvent)) { + dev = candidate; + break; + } + } + return dev; } -QWaylandOutput *QWaylandCompositor::createOutput(QWindow *window, - const QString &manufacturer, - const QString &model) +/*! + * \qmlproperty bool QtWaylandCompositor::WaylandCompositor::useHardwareIntegrationExtension + * + * This property holds whether the hardware integration extension should be enabled for + * this WaylandCompositor. + * + * This property must be set before the compositor component is completed. + */ + +/*! + * \property QWaylandCompositor::useHardwareIntegrationExtension + * + * This property holds whether the hardware integration extension should be enabled for + * this QWaylandCompositor. + * + * This property must be set before the compositor is \l{create()}{created}. + */ +bool QWaylandCompositor::useHardwareIntegrationExtension() const { - return new QWaylandOutput(this, window, manufacturer, model); + Q_D(const QWaylandCompositor); + return d->use_hw_integration_extension; +} + +void QWaylandCompositor::setUseHardwareIntegrationExtension(bool use) +{ + Q_D(QWaylandCompositor); + if (use == d->use_hw_integration_extension) + return; + + if (d->initialized) + qWarning("Setting QWaylandCompositor::useHardwareIntegrationExtension after initialization has no effect"); + + d->use_hw_integration_extension = use; + useHardwareIntegrationExtensionChanged(); } QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandcompositor.h b/src/compositor/compositor_api/qwaylandcompositor.h index 1817fa07d..cae7b4582 100644 --- a/src/compositor/compositor_api/qwaylandcompositor.h +++ b/src/compositor/compositor_api/qwaylandcompositor.h @@ -3,36 +3,32 @@ ** 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$ ** @@ -41,7 +37,9 @@ #ifndef QWAYLANDCOMPOSITOR_H #define QWAYLANDCOMPOSITOR_H -#include <QtCompositor/qwaylandexport.h> +#include <QtWaylandCompositor/qwaylandexport.h> +#include <QtWaylandCompositor/qwaylandextension.h> +#include <QtWaylandCompositor/QWaylandOutput> #include <QObject> #include <QImage> @@ -56,124 +54,89 @@ class QInputEvent; class QMimeData; class QUrl; class QOpenGLContext; +class QWaylandCompositorPrivate; class QWaylandClient; class QWaylandSurface; class QWaylandInputDevice; -class QWaylandInputPanel; -class QWaylandDrag; class QWaylandGlobalInterface; -class QWaylandSurfaceView; -class QWaylandOutput; +class QWaylandView; +class QWaylandPointer; +class QWaylandKeyboard; +class QWaylandTouch; -namespace QtWayland +class Q_COMPOSITOR_EXPORT QWaylandCompositor : public QWaylandObject { - class Compositor; -} + Q_OBJECT + Q_DECLARE_PRIVATE(QWaylandCompositor) + Q_PROPERTY(QByteArray socketName READ socketName WRITE setSocketName) + Q_PROPERTY(bool retainedSelection READ retainedSelectionEnabled WRITE setRetainedSelectionEnabled) + Q_PROPERTY(QWaylandOutput *defaultOutput READ defaultOutput WRITE setDefaultOutput NOTIFY defaultOutputChanged) + Q_PROPERTY(bool useHardwareIntegrationExtension READ useHardwareIntegrationExtension WRITE setUseHardwareIntegrationExtension NOTIFY useHardwareIntegrationExtensionChanged) + Q_PROPERTY(QWaylandInputDevice *defaultInputDevice READ defaultInputDevice NOTIFY defaultInputDeviceChanged) -class Q_COMPOSITOR_EXPORT QWaylandCompositor -{ public: - enum ExtensionFlag { - WindowManagerExtension = 0x01, - SurfaceExtension = 0x02, - QtKeyExtension = 0x04, - TouchExtension = 0x08, - SubSurfaceExtension = 0x10, - TextInputExtension = 0x20, - HardwareIntegrationExtension = 0x40, - - DefaultExtensions = WindowManagerExtension | SurfaceExtension | QtKeyExtension | TouchExtension | HardwareIntegrationExtension - }; - Q_DECLARE_FLAGS(ExtensionFlags, ExtensionFlag) - - QWaylandCompositor(const char *socketName = 0, ExtensionFlags extensions = DefaultExtensions); + QWaylandCompositor(QObject *parent = 0); virtual ~QWaylandCompositor(); - void addGlobalInterface(QWaylandGlobalInterface *interface); - void addDefaultShell(); - ::wl_display *waylandDisplay() const; - - void frameStarted(); - void sendFrameCallbacks(QList<QWaylandSurface *> visibleSurfaces); + virtual void create(); + bool isCreated() const; - void destroyClientForSurface(QWaylandSurface *surface); - void destroyClient(QWaylandClient *client); - - QList<QWaylandSurface *> surfacesForClient(QWaylandClient* client) const; - QList<QWaylandSurface *> surfaces() const; + void setSocketName(const QByteArray &name); + QByteArray socketName() const; - QList<QWaylandOutput *> outputs() const; - QWaylandOutput *output(QWindow *window); + ::wl_display *display() const; + uint32_t nextSerial(); - QWaylandOutput *primaryOutput() const; - void setPrimaryOutput(QWaylandOutput *output); + QList<QWaylandClient *>clients() const; + Q_INVOKABLE void destroyClientForSurface(QWaylandSurface *surface); + Q_INVOKABLE void destroyClient(QWaylandClient *client); - virtual void surfaceCreated(QWaylandSurface *surface) = 0; - virtual void surfaceAboutToBeDestroyed(QWaylandSurface *surface); + QList<QWaylandSurface *> surfaces() const; + QList<QWaylandSurface *> surfacesForClient(QWaylandClient* client) const; - virtual QWaylandSurfaceView *pickView(const QPointF &globalPosition) const; - virtual QPointF mapToView(QWaylandSurfaceView *view, const QPointF &surfacePosition) const; + Q_INVOKABLE QWaylandOutput *outputFor(QWindow *window) const; - virtual bool openUrl(QWaylandClient *client, const QUrl &url); + QWaylandOutput *defaultOutput() const; + void setDefaultOutput(QWaylandOutput *output); + QList<QWaylandOutput *> outputs() const; - QtWayland::Compositor *handle() const; + uint currentTimeMsecs() const; void setRetainedSelectionEnabled(bool enabled); bool retainedSelectionEnabled() const; void overrideSelection(const QMimeData *data); - void setClientFullScreenHint(bool value); - - const char *socketName() const; - -#if QT_DEPRECATED_SINCE(5, 5) - void setScreenOrientation(Qt::ScreenOrientation orientation); - - void setOutputGeometry(const QRect &outputGeometry); - QRect outputGeometry() const; - - void setOutputRefreshRate(int refreshRate); - int outputRefreshRate() const; -#endif - QWaylandInputDevice *defaultInputDevice() const; - QWaylandInputPanel *inputPanel() const; - QWaylandDrag *drag() const; + QWaylandView *createSurfaceView(QWaylandSurface *surface); - bool isDragging() const; - void sendDragMoveEvent(const QPoint &global, const QPoint &local, QWaylandSurface *surface); - void sendDragEndEvent(); - - virtual void setCursorSurface(QWaylandSurface *surface, int hotspotX, int hotspotY); + QWaylandInputDevice *inputDeviceFor(QInputEvent *inputEvent); - void cleanupGraphicsResources(); + bool useHardwareIntegrationExtension() const; + void setUseHardwareIntegrationExtension(bool use); - enum TouchExtensionFlag { - TouchExtMouseFromTouch = 0x01 - }; - Q_DECLARE_FLAGS(TouchExtensionFlags, TouchExtensionFlag) - void configureTouchExtension(TouchExtensionFlags flags); +public Q_SLOTS: + void processWaylandEvents(); - virtual QWaylandSurfaceView *createView(QWaylandSurface *surface); +Q_SIGNALS: + void createSurface(QWaylandClient *client, uint id, int version); + void surfaceCreated(QWaylandSurface *surface); + void surfaceAboutToBeDestroyed(QWaylandSurface *surface); - QWaylandInputDevice *inputDeviceFor(QInputEvent *inputEvent); + void defaultOutputChanged(); + void defaultInputDeviceChanged(); + void useHardwareIntegrationExtensionChanged(); protected: - QWaylandCompositor(const char *socketName, QtWayland::Compositor *dptr); virtual void retainedSelectionReceived(QMimeData *mimeData); + virtual QWaylandInputDevice *createInputDevice(); + virtual QWaylandPointer *createPointerDevice(QWaylandInputDevice *inputDevice); + virtual QWaylandKeyboard *createKeyboardDevice(QWaylandInputDevice *inputDevice); + virtual QWaylandTouch *createTouchDevice(QWaylandInputDevice *inputDevice); - virtual QWaylandOutput *createOutput(QWindow *window, - const QString &manufacturer, - const QString &model); - - friend class QtWayland::Compositor; - QtWayland::Compositor *m_compositor; + QWaylandCompositor(QWaylandCompositorPrivate &dptr, QObject *parent = 0); }; -Q_DECLARE_OPERATORS_FOR_FLAGS(QWaylandCompositor::ExtensionFlags) -Q_DECLARE_OPERATORS_FOR_FLAGS(QWaylandCompositor::TouchExtensionFlags) - QT_END_NAMESPACE #endif // QWAYLANDCOMPOSITOR_H diff --git a/src/compositor/compositor_api/qwaylandcompositor_p.h b/src/compositor/compositor_api/qwaylandcompositor_p.h new file mode 100644 index 000000000..fb0f803ed --- /dev/null +++ b/src/compositor/compositor_api/qwaylandcompositor_p.h @@ -0,0 +1,200 @@ +/**************************************************************************** +** +** Copyright (C) 2014-2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> +** Copyright (C) 2015 The Qt Company Ltd. +** 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 QWAYLANDCOMPOSITOR_P_H +#define QWAYLANDCOMPOSITOR_P_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. +// + +#include <QtWaylandCompositor/qwaylandexport.h> +#include <QtWaylandCompositor/QWaylandCompositor> +#include <QtCore/private/qobject_p.h> +#include <QtCore/QSet> +#include <QtCore/QElapsedTimer> + +#include <QtWaylandCompositor/private/qwayland-server-wayland.h> + +QT_BEGIN_NAMESPACE + +namespace QtWayland { + class HardwareIntegration; + class ClientBufferIntegration; + class ServerBufferIntegration; + class DataDeviceManager; +} + +class QWindowSystemEventHandler; +class QWaylandSurface; + +class Q_COMPOSITOR_EXPORT QWaylandCompositorPrivate : public QObjectPrivate, public QtWaylandServer::wl_compositor +{ +public: + static QWaylandCompositorPrivate *get(QWaylandCompositor *compositor) { return compositor->d_func(); } + + QWaylandCompositorPrivate(QWaylandCompositor *compositor); + ~QWaylandCompositorPrivate(); + + void init(); + + void destroySurface(QWaylandSurface *surface); + void unregisterSurface(QWaylandSurface *surface); + + QWaylandOutput *defaultOutput() const { return outputs.size() ? outputs.first() : Q_NULLPTR; } + + inline QtWayland::ClientBufferIntegration *clientBufferIntegration() const; + inline QtWayland::ServerBufferIntegration *serverBufferIntegration() const; + + QtWayland::DataDeviceManager *dataDeviceManager() const { return data_device_manager; } + void feedRetainedSelectionData(QMimeData *data); + + QWaylandPointer *callCreatePointerDevice(QWaylandInputDevice *inputDevice) + { return q_func()->createPointerDevice(inputDevice); } + QWaylandKeyboard *callCreateKeyboardDevice(QWaylandInputDevice *inputDevice) + { return q_func()->createKeyboardDevice(inputDevice); } + QWaylandTouch *callCreateTouchDevice(QWaylandInputDevice *inputDevice) + { return q_func()->createTouchDevice(inputDevice); } + + inline void addClient(QWaylandClient *client); + inline void removeClient(QWaylandClient *client); + + void addPolishObject(QObject *object); + + inline void addOutput(QWaylandOutput *output); + inline void removeOutput(QWaylandOutput *output); +protected: + void compositor_create_surface(Resource *resource, uint32_t id) Q_DECL_OVERRIDE; + void compositor_create_region(Resource *resource, uint32_t id) Q_DECL_OVERRIDE; + + virtual QWaylandSurface *createDefaultSurface(); +protected: + void initializeHardwareIntegration(); + void initializeExtensions(); + void initializeDefaultInputDevice(); + + void loadClientBufferIntegration(); + void loadServerBufferIntegration(); + + QByteArray socket_name; + struct wl_display *display; + + QList<QWaylandInputDevice *> inputDevices; + QList<QWaylandOutput *> outputs; + + QList<QWaylandSurface *> all_surfaces; + + QtWayland::DataDeviceManager *data_device_manager; + + QElapsedTimer timer; + + wl_event_loop *loop; + + QList<QWaylandClient *> clients; + +#ifdef QT_COMPOSITOR_WAYLAND_GL + bool use_hw_integration_extension; + QScopedPointer<QtWayland::HardwareIntegration> hw_integration; + QScopedPointer<QtWayland::ClientBufferIntegration> client_buffer_integration; + QScopedPointer<QtWayland::ServerBufferIntegration> server_buffer_integration; +#endif + + QScopedPointer<QWindowSystemEventHandler> eventHandler; + + bool retainSelection; + bool initialized; + QList<QPointer<QObject> > polish_objects; + + Q_DECLARE_PUBLIC(QWaylandCompositor) + Q_DISABLE_COPY(QWaylandCompositorPrivate) +}; + +QtWayland::ClientBufferIntegration * QWaylandCompositorPrivate::clientBufferIntegration() const +{ +#ifdef QT_COMPOSITOR_WAYLAND_GL + return client_buffer_integration.data(); +#else + return 0; +#endif +} + +QtWayland::ServerBufferIntegration * QWaylandCompositorPrivate::serverBufferIntegration() const +{ +#ifdef QT_COMPOSITOR_WAYLAND_GL + return server_buffer_integration.data(); +#else + return 0; +#endif +} + +void QWaylandCompositorPrivate::addClient(QWaylandClient *client) +{ + Q_ASSERT(!clients.contains(client)); + clients.append(client); +} + +void QWaylandCompositorPrivate::removeClient(QWaylandClient *client) +{ + Q_ASSERT(clients.contains(client)); + clients.removeOne(client); +} + +void QWaylandCompositorPrivate::addOutput(QWaylandOutput *output) +{ + Q_ASSERT(output); + if (outputs.contains(output)) + return; + outputs.append(output); +} + +void QWaylandCompositorPrivate::removeOutput(QWaylandOutput *output) +{ + Q_ASSERT(output); + Q_ASSERT(outputs.count(output) == 1); + outputs.removeOne(output); +} + +QT_END_NAMESPACE + +#endif //QWAYLANDCOMPOSITOR_P_H diff --git a/src/compositor/compositor_api/qwaylanddestroylistener.cpp b/src/compositor/compositor_api/qwaylanddestroylistener.cpp new file mode 100644 index 000000000..13ec63849 --- /dev/null +++ b/src/compositor/compositor_api/qwaylanddestroylistener.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.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 "qwaylanddestroylistener.h" +#include "qwaylanddestroylistener_p.h" + +QT_BEGIN_NAMESPACE + +QWaylandDestroyListenerPrivate::QWaylandDestroyListenerPrivate() +{ + listener.parent = this; + listener.listener.notify = handler; + wl_list_init(&listener.listener.link); +} + +QWaylandDestroyListener::QWaylandDestroyListener(QObject *parent) + : QObject(* new QWaylandDestroyListenerPrivate(), parent) +{ +} +void QWaylandDestroyListener::listenForDestruction(::wl_resource *resource) +{ + Q_D(QWaylandDestroyListener); + wl_resource_add_destroy_listener(resource, &d->listener.listener); +} + +void QWaylandDestroyListener::reset() +{ + Q_D(QWaylandDestroyListener); + wl_list_remove(&d->listener.listener.link); + wl_list_init(&d->listener.listener.link); +} + +void QWaylandDestroyListenerPrivate::handler(wl_listener *listener, void *data) +{ + QWaylandDestroyListenerPrivate *that = reinterpret_cast<Listener *>(listener)->parent; + emit that->q_func()->fired(data); +} + +QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylanddestroylistener.h b/src/compositor/compositor_api/qwaylanddestroylistener.h new file mode 100644 index 000000000..04e0546af --- /dev/null +++ b/src/compositor/compositor_api/qwaylanddestroylistener.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.com> +** Copyright (C) 2015 The Qt Company Ltd. +** 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 QWAYLANDDESTROYLISTENER_H +#define QWAYLANDDESTROYLISTENER_H + +#include <QtCore/QObject> +#include <QtWaylandCompositor/qwaylandexport.h> + +struct wl_resource; + +QT_BEGIN_NAMESPACE + +class QWaylandDestroyListenerPrivate; + +class Q_COMPOSITOR_EXPORT QWaylandDestroyListener : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QWaylandDestroyListener) +public: + QWaylandDestroyListener(QObject *parent = 0); + void listenForDestruction(struct wl_resource *resource); + void reset(); + +Q_SIGNALS: + void fired(void *data); + +}; + +QT_END_NAMESPACE + +#endif /*QWAYLANDDESTROYLISTENER_H*/ diff --git a/src/compositor/compositor_api/qwaylanddestroylistener_p.h b/src/compositor/compositor_api/qwaylanddestroylistener_p.h new file mode 100644 index 000000000..63b2d3ce9 --- /dev/null +++ b/src/compositor/compositor_api/qwaylanddestroylistener_p.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.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 QTWAYLAND_QWLLISTENER_H +#define QTWAYLAND_QWLLISTENER_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. +// + +#include "qwaylanddestroylistener.h" + +#include <QtCore/private/qobject_p.h> + +#include <wayland-server.h> + +QT_BEGIN_NAMESPACE + +class QWaylandDestroyListenerPrivate : public QObjectPrivate +{ +public: + Q_DECLARE_PUBLIC(QWaylandDestroyListener) + + QWaylandDestroyListenerPrivate(); + + static void handler(wl_listener *listener, void *data); + + struct Listener { + wl_listener listener; + QWaylandDestroyListenerPrivate *parent; + }; + Listener listener; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/compositor/compositor_api/qwaylanddrag.cpp b/src/compositor/compositor_api/qwaylanddrag.cpp index b31df31b8..cc45c1279 100644 --- a/src/compositor/compositor_api/qwaylanddrag.cpp +++ b/src/compositor/compositor_api/qwaylanddrag.cpp @@ -3,36 +3,32 @@ ** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB). ** 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$ ** @@ -42,51 +38,85 @@ #include <private/qobject_p.h> -#include "qwlcompositor_p.h" -#include "qwlinputdevice_p.h" #include "qwldatadevice_p.h" -#include "qwlsurface_p.h" -#include "qwaylandsurfaceview.h" +#include "qwaylandview.h" +#include <QtWaylandCompositor/private/qwaylandinput_p.h> QT_BEGIN_NAMESPACE class QWaylandDragPrivate : public QObjectPrivate { public: - QWaylandDragPrivate(QtWayland::InputDevice *id) + QWaylandDragPrivate(QWaylandInputDevice *id) : inputDevice(id) { } - QtWayland::InputDevice *inputDevice; -}; + QtWayland::DataDevice *dataDevice() + { + return QWaylandInputDevicePrivate::get(inputDevice)->dataDevice(); + } + + const QtWayland::DataDevice *dataDevice() const + { + return QWaylandInputDevicePrivate::get(inputDevice)->dataDevice(); + } + QWaylandInputDevice *inputDevice; +}; -QWaylandDrag::QWaylandDrag(QtWayland::InputDevice *inputDevice) +QWaylandDrag::QWaylandDrag(QWaylandInputDevice *inputDevice) : QObject(* new QWaylandDragPrivate(inputDevice)) { } -QWaylandSurfaceView *QWaylandDrag::icon() const +QWaylandSurface *QWaylandDrag::icon() const { Q_D(const QWaylandDrag); - const QtWayland::DataDevice *dataDevice = d->inputDevice->dataDevice(); + const QtWayland::DataDevice *dataDevice = d->dataDevice(); if (!dataDevice) return 0; return dataDevice->dragIcon(); } + bool QWaylandDrag::visible() const { Q_D(const QWaylandDrag); - const QtWayland::DataDevice *dataDevice = d->inputDevice->dataDevice(); + const QtWayland::DataDevice *dataDevice = d->dataDevice(); if (!dataDevice) return false; return dataDevice->dragIcon() != 0; } +void QWaylandDrag::dragMove(QWaylandSurface *target, const QPointF &pos) +{ + Q_D(QWaylandDrag); + QtWayland::DataDevice *dataDevice = d->dataDevice(); + if (!dataDevice) + return; + dataDevice->dragMove(target, pos); +} +void QWaylandDrag::drop() +{ + Q_D(QWaylandDrag); + QtWayland::DataDevice *dataDevice = d->dataDevice(); + if (!dataDevice) + return; + dataDevice->drop(); +} + +void QWaylandDrag::cancelDrag() +{ + Q_D(QWaylandDrag); + QtWayland::DataDevice *dataDevice = d->dataDevice(); + if (!dataDevice) + return; + dataDevice->cancelDrag(); +} + QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylanddrag.h b/src/compositor/compositor_api/qwaylanddrag.h index c0b0aca36..e7fcaad8e 100644 --- a/src/compositor/compositor_api/qwaylanddrag.h +++ b/src/compositor/compositor_api/qwaylanddrag.h @@ -3,36 +3,32 @@ ** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB). ** 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$ ** @@ -41,35 +37,48 @@ #ifndef QWAYLANDDRAG_H #define QWAYLANDDRAG_H -#include <QtCompositor/qwaylandexport.h> +#include <QtWaylandCompositor/qwaylandexport.h> -#include <QObject> +#include <QtCore/QObject> +#include <QtCore/QPointF> QT_BEGIN_NAMESPACE class QWaylandDragPrivate; class QWaylandSurface; -class QWaylandSurfaceView; +class QWaylandView; +class QWaylandInputDevice; namespace QtWayland { -class InputDevice; + class DataDevice; } + class Q_COMPOSITOR_EXPORT QWaylandDrag : public QObject { Q_OBJECT Q_DECLARE_PRIVATE(QWaylandDrag) - Q_PROPERTY(QWaylandSurfaceView* icon READ icon NOTIFY iconChanged) + Q_PROPERTY(QWaylandSurface *icon READ icon NOTIFY iconChanged) Q_PROPERTY(bool visible READ visible NOTIFY iconChanged) public: - explicit QWaylandDrag(QtWayland::InputDevice *inputDevice); + explicit QWaylandDrag(QWaylandInputDevice *inputDevice); - QWaylandSurfaceView *icon() const; + QWaylandSurface *icon() const; + // QPointF position() const; bool visible() const; +public Q_SLOTS: + void dragMove(QWaylandSurface *target, const QPointF &pos); + void drop(); + void cancelDrag(); + Q_SIGNALS: void iconChanged(); + void dragStarted(); // QWaylandSurface *icon???? + +private: + //friend class QtWayland::DataDevice; }; QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandglobalinterface.cpp b/src/compositor/compositor_api/qwaylandglobalinterface.cpp deleted file mode 100644 index 791964863..000000000 --- a/src/compositor/compositor_api/qwaylandglobalinterface.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.com> -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qwaylandglobalinterface.h" - -#include <wayland-server.h> - -QT_BEGIN_NAMESPACE - -QWaylandGlobalInterface::QWaylandGlobalInterface() -{ - -} - -QWaylandGlobalInterface::~QWaylandGlobalInterface() -{ - -} - -quint32 QWaylandGlobalInterface::version() const -{ - return interface()->version; -} - -QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandglobalinterface.h b/src/compositor/compositor_api/qwaylandglobalinterface.h deleted file mode 100644 index 6be3236fa..000000000 --- a/src/compositor/compositor_api/qwaylandglobalinterface.h +++ /dev/null @@ -1,65 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.com> -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QWAYLANDGLOBALINTERFACE_H -#define QWAYLANDGLOBALINTERFACE_H - -#include <QtCompositor/qwaylandexport.h> - -struct wl_interface; -struct wl_client; - -QT_BEGIN_NAMESPACE - -namespace QtWayland { -class Compositor; -} - -class Q_COMPOSITOR_EXPORT QWaylandGlobalInterface -{ -public: - QWaylandGlobalInterface(); - virtual ~QWaylandGlobalInterface(); - - virtual const wl_interface *interface() const = 0; - virtual quint32 version() const; - -protected: - virtual void bind(wl_client *client, quint32 version, quint32 id) = 0; - - friend class QtWayland::Compositor; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/compositor/compositor_api/qwaylandinput.cpp b/src/compositor/compositor_api/qwaylandinput.cpp index 4e106f5fe..be566c70d 100644 --- a/src/compositor/compositor_api/qwaylandinput.cpp +++ b/src/compositor/compositor_api/qwaylandinput.cpp @@ -3,52 +3,135 @@ ** 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 "qwaylandinput.h" +#include "qwaylandinput_p.h" -#include "qwlinputdevice_p.h" -#include "qwlkeyboard_p.h" #include "qwaylandcompositor.h" -#include "qwlsurface_p.h" -#include "qwlcompositor_p.h" -#include "qwaylandsurfaceview.h" +#include "qwaylandview.h" +#include <QtWaylandCompositor/QWaylandDrag> +#include <QtWaylandCompositor/QWaylandTouch> +#include <QtWaylandCompositor/QWaylandPointer> +#include <QtWaylandCompositor/private/qwlinputmethod_p.h> +#include <QtWaylandCompositor/private/qwaylandinput_p.h> +#include <QtWaylandCompositor/private/qwaylandcompositor_p.h> +#include <QtWaylandCompositor/private/qwldatadevice_p.h> + +#include "extensions/qwlqtkey_p.h" QT_BEGIN_NAMESPACE +QWaylandInputDevicePrivate::QWaylandInputDevicePrivate(QWaylandInputDevice *inputdevice, QWaylandCompositor *compositor) + : QObjectPrivate() + , QtWaylandServer::wl_seat(compositor->display(), 3) + , compositor(compositor) + , mouseFocus(Q_NULLPTR) + , capabilities() + , data_device() + , drag_handle(new QWaylandDrag(inputdevice)) +{ +} + +QWaylandInputDevicePrivate::~QWaylandInputDevicePrivate() +{ +} + +void QWaylandInputDevicePrivate::setCapabilities(QWaylandInputDevice::CapabilityFlags caps) +{ + Q_Q(QWaylandInputDevice); + if (capabilities != caps) { + QWaylandInputDevice::CapabilityFlags changed = caps ^ capabilities; + + if (changed & QWaylandInputDevice::Pointer) { + pointer.reset(pointer.isNull() ? QWaylandCompositorPrivate::get(compositor)->callCreatePointerDevice(q) : 0); + } + + if (changed & QWaylandInputDevice::Keyboard) { + keyboard.reset(keyboard.isNull() ? QWaylandCompositorPrivate::get(compositor)->callCreateKeyboardDevice(q) : 0); + } + + if (changed & QWaylandInputDevice::Touch) { + touch.reset(touch.isNull() ? QWaylandCompositorPrivate::get(compositor)->callCreateTouchDevice(q) : 0); + } + + capabilities = caps; + QList<Resource *> resources = resourceMap().values(); + for (int i = 0; i < resources.size(); i++) { + wl_seat::send_capabilities(resources.at(i)->handle, (uint32_t)capabilities); + } + } +} + +void QWaylandInputDevicePrivate::clientRequestedDataDevice(QtWayland::DataDeviceManager *, struct wl_client *client, uint32_t id) +{ + Q_Q(QWaylandInputDevice); + if (!data_device) + data_device.reset(new QtWayland::DataDevice(q)); + data_device->add(client, id, 1); +} + +void QWaylandInputDevicePrivate::seat_destroy_resource(wl_seat::Resource *) +{ +// cleanupDataDeviceForClient(resource->client(), true); +} + +void QWaylandInputDevicePrivate::seat_bind_resource(wl_seat::Resource *resource) +{ + // The order of capabilities matches the order defined in the wayland protocol + wl_seat::send_capabilities(resource->handle, (uint32_t)capabilities); +} + +void QWaylandInputDevicePrivate::seat_get_pointer(wl_seat::Resource *resource, uint32_t id) +{ + if (!pointer.isNull()) { + pointer->addClient(QWaylandClient::fromWlClient(compositor, resource->client()), id, resource->version()); + } +} + +void QWaylandInputDevicePrivate::seat_get_keyboard(wl_seat::Resource *resource, uint32_t id) +{ + if (!keyboard.isNull()) { + keyboard->addClient(QWaylandClient::fromWlClient(compositor, resource->client()), id, resource->version()); + } +} + +void QWaylandInputDevicePrivate::seat_get_touch(wl_seat::Resource *resource, uint32_t id) +{ + if (!touch.isNull()) { + touch->addClient(QWaylandClient::fromWlClient(compositor, resource->client()), id, resource->version()); + } +} + QWaylandKeymap::QWaylandKeymap(const QString &layout, const QString &variant, const QString &options, const QString &model, const QString &rules) : m_layout(layout) , m_variant(variant) @@ -59,134 +142,302 @@ QWaylandKeymap::QWaylandKeymap(const QString &layout, const QString &variant, co } +/*! + * \class QWaylandInputDevice + * \inmodule QtWaylandCompositor + * \brief The QWaylandInputDevice class provides access to keyboard, mouse and touch input. + * + * The QWaylandInputDevice provides access to different types of user input and maintains + * a keyboard focus and a mouse pointer. It corresponds to the wl_seat interface in the Wayland protocol. + */ -QWaylandInputDevice::QWaylandInputDevice(QWaylandCompositor *compositor, CapabilityFlags caps) - : d(new QtWayland::InputDevice(this,compositor->handle(), caps)) -{ -} +/*! + * \enum QWaylandInputDevice::CapabilityFlag + * + * This enum type describes the capabilities of a QWaylandInputDevice. + * + * \value Pointer The QWaylandInputDevice supports pointer input. + * \value Keyboard The QWaylandInputDevice supports keyboard input. + * \value Touch The QWaylandInputDevice supports touch input. + */ -QWaylandInputDevice::~QWaylandInputDevice() +/*! + * Constructs a QWaylandInputDevice for the given \a compositor and with the given \a capabilityFlags. + */ +QWaylandInputDevice::QWaylandInputDevice(QWaylandCompositor *compositor, CapabilityFlags capabilityFlags) + : QWaylandObject(*new QWaylandInputDevicePrivate(this,compositor)) { - delete d; + d_func()->setCapabilities(capabilityFlags); } -void QWaylandInputDevice::sendMousePressEvent(Qt::MouseButton button, const QPointF &localPos, const QPointF &globalPos) +/*! + * Destroys the QWaylandInputDevice + */ +QWaylandInputDevice::~QWaylandInputDevice() { - d->sendMousePressEvent(button,localPos,globalPos); } -void QWaylandInputDevice::sendMouseReleaseEvent(Qt::MouseButton button, const QPointF &localPos, const QPointF &globalPos) +/*! + * Sends a mouse press event for \a button to the QWaylandInputDevice's pointer device. + */ +void QWaylandInputDevice::sendMousePressEvent(Qt::MouseButton button) { - d->sendMouseReleaseEvent(button,localPos,globalPos); + Q_D(QWaylandInputDevice); + d->pointer->sendMousePressEvent(button); } -void QWaylandInputDevice::sendMouseMoveEvent(const QPointF &localPos, const QPointF &globalPos) +/*! + * Sends a mouse release event for \a button to the QWaylandInputDevice's pointer device. + */ +void QWaylandInputDevice::sendMouseReleaseEvent(Qt::MouseButton button) { - d->sendMouseMoveEvent(localPos,globalPos); + Q_D(QWaylandInputDevice); + d->pointer->sendMouseReleaseEvent(button); } -/** Convenience function that will set the mouse focus to the surface, then send the mouse move event. - * If the mouse focus is the same surface as the surface passed in, then only the move event is sent +/*! + * Sets the mouse focus to \a view and sends a mouse move event to the pointer device with the + * local position \a localPos and output space position \a outputSpacePos. **/ -void QWaylandInputDevice::sendMouseMoveEvent(QWaylandSurfaceView *surface, const QPointF &localPos, const QPointF &globalPos) +void QWaylandInputDevice::sendMouseMoveEvent(QWaylandView *view, const QPointF &localPos, const QPointF &outputSpacePos) { - d->sendMouseMoveEvent(surface,localPos,globalPos); + Q_D(QWaylandInputDevice); + d->pointer->sendMouseMoveEvent(view, localPos, outputSpacePos); } +/*! + * Sends a mouse wheel event to the QWaylandInputDevice's pointer device with the given \a orientation and \a delta. + */ void QWaylandInputDevice::sendMouseWheelEvent(Qt::Orientation orientation, int delta) { - d->sendMouseWheelEvent(orientation, delta); + Q_D(QWaylandInputDevice); + d->pointer->sendMouseWheelEvent(orientation, delta); } +/*! + * Sends a key press event with the key \a code to the keyboard device. + */ void QWaylandInputDevice::sendKeyPressEvent(uint code) { - d->keyboardDevice()->sendKeyPressEvent(code); + Q_D(QWaylandInputDevice); + d->keyboard->sendKeyPressEvent(code); } +/*! + * Sends a key release event with the key \a code to the keyboard device. + */ void QWaylandInputDevice::sendKeyReleaseEvent(uint code) { - d->keyboardDevice()->sendKeyReleaseEvent(code); + Q_D(QWaylandInputDevice); + d->keyboard->sendKeyReleaseEvent(code); } -void QWaylandInputDevice::sendTouchPointEvent(int id, double x, double y, Qt::TouchPointState state) +/*! + * Sends a touch point event with the given \a id and \a state to the touch device. The position + * of the touch point is given by \a point. + */ +void QWaylandInputDevice::sendTouchPointEvent(int id, const QPointF &point, Qt::TouchPointState state) { - d->sendTouchPointEvent(id,x,y,state); + Q_D(QWaylandInputDevice); + if (d->touch.isNull()) { + return; + } + d->touch->sendTouchPointEvent(id, point,state); } +/*! + * Sends a frame event to the touch device. + */ void QWaylandInputDevice::sendTouchFrameEvent() { - d->sendTouchFrameEvent(); + Q_D(QWaylandInputDevice); + if (!d->touch.isNull()) { + d->touch->sendFrameEvent(); + } } +/*! + * Sends a cancel event to the touch device. + */ void QWaylandInputDevice::sendTouchCancelEvent() { - d->sendTouchCancelEvent(); + Q_D(QWaylandInputDevice); + if (!d->touch.isNull()) { + d->touch->sendCancelEvent(); + } } +/*! + * Sends the \a event to the touch device. + */ void QWaylandInputDevice::sendFullTouchEvent(QTouchEvent *event) { - d->sendFullTouchEvent(event); + Q_D(QWaylandInputDevice); + if (!mouseFocus()) { + qWarning("Cannot send touch event, no pointer focus, fix the compositor"); + return; + } + + if (!d->touch) + return; + + d->touch->sendFullTouchEvent(event); } +/*! + * Sends the \a event to the keyboard device. + */ void QWaylandInputDevice::sendFullKeyEvent(QKeyEvent *event) { - d->sendFullKeyEvent(event); + Q_D(QWaylandInputDevice); + if (!keyboardFocus()) { + qWarning("Cannot send key event, no keyboard focus, fix the compositor"); + return; + } + + QtWayland::QtKeyExtensionGlobal *ext = QtWayland::QtKeyExtensionGlobal::findIn(d->compositor); + if (ext && ext->postQtKeyEvent(event, keyboardFocus())) + return; + + if (!d->keyboard.isNull() && !event->isAutoRepeat()) { + if (event->type() == QEvent::KeyPress) + d->keyboard->sendKeyPressEvent(event->nativeScanCode()); + else if (event->type() == QEvent::KeyRelease) + d->keyboard->sendKeyReleaseEvent(event->nativeScanCode()); + } } -void QWaylandInputDevice::sendFullKeyEvent(QWaylandSurface *surface, QKeyEvent *event) +/*! + * Returns the keyboard for this input device. + */ +QWaylandKeyboard *QWaylandInputDevice::keyboard() const { - d->sendFullKeyEvent(surface->handle(), event); + Q_D(const QWaylandInputDevice); + return d->keyboard.data(); } +/*! + * Returns the current focused surface for keyboard input. + */ QWaylandSurface *QWaylandInputDevice::keyboardFocus() const { - QtWayland::Surface *wlsurface = d->keyboardFocus(); - if (wlsurface) - return wlsurface->waylandSurface(); - return 0; + Q_D(const QWaylandInputDevice); + if (d->keyboard.isNull() || !d->keyboard->focus()) + return Q_NULLPTR; + + return d->keyboard->focus(); } +/*! + * Sets the current keyboard focus to \a surface. + */ bool QWaylandInputDevice::setKeyboardFocus(QWaylandSurface *surface) { - QtWayland::Surface *wlsurface = surface?surface->handle():0; - return d->setKeyboardFocus(wlsurface); + Q_D(QWaylandInputDevice); + if (surface && surface->isDestroyed()) + return false; + + if (surface == keyboardFocus()) + return true; + + if (!d->keyboard.isNull() && d->keyboard->setFocus(surface)) { + if (d->data_device) + d->data_device->setFocus(d->keyboard->focusClient()); + return true; + } + return false; } +/*! + * Sets the key map of this QWaylandInputDevice to \a keymap. + */ void QWaylandInputDevice::setKeymap(const QWaylandKeymap &keymap) { - if (handle()->keyboardDevice()) - handle()->keyboardDevice()->setKeymap(keymap); + if (keyboard()) + keyboard()->setKeymap(keymap); } -QWaylandSurfaceView *QWaylandInputDevice::mouseFocus() const +/*! + * Returns the pointer device for this QWaylandInputDevice. + */ +QWaylandPointer *QWaylandInputDevice::pointer() const { - return d->mouseFocus(); + Q_D(const QWaylandInputDevice); + return d->pointer.data(); } -void QWaylandInputDevice::setMouseFocus(QWaylandSurfaceView *surface, const QPointF &localPos, const QPointF &globalPos) +/*! + * Returns the view that currently has mouse focus. + */ +QWaylandView *QWaylandInputDevice::mouseFocus() const { - d->setMouseFocus(surface,localPos,globalPos); + Q_D(const QWaylandInputDevice); + return d->mouseFocus; } +/*! + * Sets the current mouse focus to \a view. + */ +void QWaylandInputDevice::setMouseFocus(QWaylandView *view) +{ + Q_D(QWaylandInputDevice); + if (view == d->mouseFocus) + return; + + QWaylandView *oldFocus = d->mouseFocus; + d->mouseFocus = view; + emit mouseFocusChanged(d->mouseFocus, oldFocus); +} + +/*! + * Returns the compositor for this QWaylandInputDevice. + */ QWaylandCompositor *QWaylandInputDevice::compositor() const { - return d->compositor()->waylandCompositor(); + Q_D(const QWaylandInputDevice); + return d->compositor; } -QtWayland::InputDevice *QWaylandInputDevice::handle() const +/*! + * Returns the drag object for this QWaylandInputDevice. + */ +QWaylandDrag *QWaylandInputDevice::drag() const { - return d; + Q_D(const QWaylandInputDevice); + return d->drag_handle.data(); } -QWaylandInputDevice::CapabilityFlags QWaylandInputDevice::capabilities() +/*! + * Returns the capability flags for this QWaylandInputDevice. + */ +QWaylandInputDevice::CapabilityFlags QWaylandInputDevice::capabilities() const { - return d->capabilities(); + Q_D(const QWaylandInputDevice); + return d->capabilities; } -bool QWaylandInputDevice::isOwner(QInputEvent *inputEvent) +/*! + * \internal + */ +bool QWaylandInputDevice::isOwner(QInputEvent *inputEvent) const { Q_UNUSED(inputEvent); return true; } +/*! + * Returns the QWaylandInputDevice corresponding to the \a resource. The \a resource is expected + * to have the type wl_seat. + */ +QWaylandInputDevice *QWaylandInputDevice::fromSeatResource(struct ::wl_resource *resource) +{ + return static_cast<QWaylandInputDevicePrivate *>(QWaylandInputDevicePrivate::Resource::fromResource(resource)->seat_object)->q_func(); +} + +/*! + * \fn void mouseFocusChanged(QWaylandView *newFocus, QWaylandView *oldFocus) + * + * This signal is emitted when the mouse focus has changed from \a oldFocus to \a newFocus. + */ + QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandinput.h b/src/compositor/compositor_api/qwaylandinput.h index 7842fa38b..e4b6e1275 100644 --- a/src/compositor/compositor_api/qwaylandinput.h +++ b/src/compositor/compositor_api/qwaylandinput.h @@ -3,36 +3,32 @@ ** 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$ ** @@ -45,7 +41,9 @@ #include <QtCore/QPoint> #include <QtCore/QString> -#include <QtCompositor/qwaylandexport.h> +#include <QtWaylandCompositor/qwaylandexport.h> +#include <QtWaylandCompositor/qwaylandextension.h> +#include <QtWaylandCompositor/qwaylandkeyboard.h> QT_BEGIN_NAMESPACE @@ -53,35 +51,22 @@ class QWaylandCompositor; class QWaylandSurface; class QKeyEvent; class QTouchEvent; -class QWaylandSurfaceView; +class QWaylandView; class QInputEvent; +class QWaylandInputDevicePrivate; +class QWaylandDrag; +class QWaylandKeyboard; +class QWaylandPointer; +class QWaylandTouch; namespace QtWayland { class InputDevice; } -class Q_COMPOSITOR_EXPORT QWaylandKeymap -{ -public: - QWaylandKeymap(const QString &layout = QString(), const QString &variant = QString(), const QString &options = QString(), - const QString &model = QString(), const QString &rules = QString()); - - inline QString layout() const { return m_layout; } - inline QString variant() const { return m_variant; } - inline QString options() const { return m_options; } - inline QString rules() const { return m_rules; } - inline QString model() const { return m_model; } - -private: - QString m_layout; - QString m_variant; - QString m_options; - QString m_rules; - QString m_model; -}; - -class Q_COMPOSITOR_EXPORT QWaylandInputDevice +class Q_COMPOSITOR_EXPORT QWaylandInputDevice : public QWaylandObject { + Q_OBJECT + Q_DECLARE_PRIVATE(QWaylandInputDevice) public: enum CapabilityFlag { // The order should match the enum WL_SEAT_CAPABILITY_* @@ -92,14 +77,14 @@ public: DefaultCapabilities = Pointer | Keyboard | Touch }; Q_DECLARE_FLAGS(CapabilityFlags, CapabilityFlag) + Q_ENUM(CapabilityFlags) - QWaylandInputDevice(QWaylandCompositor *compositor, CapabilityFlags caps = DefaultCapabilities); + QWaylandInputDevice(QWaylandCompositor *compositor, CapabilityFlags capabilityFlags = DefaultCapabilities); virtual ~QWaylandInputDevice(); - void sendMousePressEvent(Qt::MouseButton button, const QPointF &localPos, const QPointF &globalPos = QPointF()); - void sendMouseReleaseEvent(Qt::MouseButton button, const QPointF &localPos, const QPointF &globalPos = QPointF()); - void sendMouseMoveEvent(const QPointF &localPos, const QPointF &globalPos = QPointF()); - void sendMouseMoveEvent(QWaylandSurfaceView *surface , const QPointF &localPos, const QPointF &globalPos = QPointF()); + void sendMousePressEvent(Qt::MouseButton button); + void sendMouseReleaseEvent(Qt::MouseButton button); + void sendMouseMoveEvent(QWaylandView *surface , const QPointF &localPos, const QPointF &outputSpacePos = QPointF()); void sendMouseWheelEvent(Qt::Orientation orientation, int delta); void sendKeyPressEvent(uint code); @@ -108,29 +93,38 @@ public: void sendFullKeyEvent(QKeyEvent *event); void sendFullKeyEvent(QWaylandSurface *surface, QKeyEvent *event); - void sendTouchPointEvent(int id, double x, double y, Qt::TouchPointState state); + void sendTouchPointEvent(int id, const QPointF &point, Qt::TouchPointState state); void sendTouchFrameEvent(); void sendTouchCancelEvent(); void sendFullTouchEvent(QTouchEvent *event); + QWaylandPointer *pointer() const; + //Normally set by the mouse device, + //But can be set manually for use with touch or can reset unset the current mouse focus; + QWaylandView *mouseFocus() const; + void setMouseFocus(QWaylandView *view); + + QWaylandKeyboard *keyboard() const; QWaylandSurface *keyboardFocus() const; bool setKeyboardFocus(QWaylandSurface *surface); void setKeymap(const QWaylandKeymap &keymap); - QWaylandSurfaceView *mouseFocus() const; - void setMouseFocus(QWaylandSurfaceView *surface, const QPointF &local_pos, const QPointF &global_pos = QPointF()); + QWaylandTouch *touch() const; QWaylandCompositor *compositor() const; - QtWayland::InputDevice *handle() const; - QWaylandInputDevice::CapabilityFlags capabilities(); + QWaylandDrag *drag() const; + + QWaylandInputDevice::CapabilityFlags capabilities() const; + + virtual bool isOwner(QInputEvent *inputEvent) const; - virtual bool isOwner(QInputEvent *inputEvent); + static QWaylandInputDevice *fromSeatResource(struct ::wl_resource *resource); -private: - QtWayland::InputDevice *d; - Q_DISABLE_COPY(QWaylandInputDevice) +Q_SIGNALS: + void mouseFocusChanged(QWaylandView *newFocus, QWaylandView *oldFocus); + void cursorSurfaceRequest(QWaylandSurface *surface, int hotspotX, int hotspotY); }; Q_DECLARE_OPERATORS_FOR_FLAGS(QWaylandInputDevice::CapabilityFlags) diff --git a/src/compositor/compositor_api/qwaylandinput_p.h b/src/compositor/compositor_api/qwaylandinput_p.h new file mode 100644 index 000000000..4ae741d05 --- /dev/null +++ b/src/compositor/compositor_api/qwaylandinput_p.h @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** 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 QWAYLANDINPUT_P_H +#define QWAYLANDINPUT_P_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. +// + +#include <stdint.h> + +#include <QtWaylandCompositor/qwaylandexport.h> +#include <QtWaylandCompositor/qwaylandinput.h> + +#include <QtCore/QList> +#include <QtCore/QPoint> +#include <QtCore/QScopedPointer> +#include <QtCore/private/qobject_p.h> + +#ifndef QT_NO_WAYLAND_XKB +#include <xkbcommon/xkbcommon.h> +#endif + +#include <QtWaylandCompositor/private/qwayland-server-wayland.h> + +QT_BEGIN_NAMESPACE + +class QKeyEvent; +class QTouchEvent; +class QWaylandInputDevice; +class QWaylandDrag; +class QWaylandView; + +namespace QtWayland { + +class Compositor; +class DataDevice; +class Surface; +class DataDeviceManager; +class Pointer; +class Keyboard; +class Touch; +class InputMethod; + +} + +class Q_COMPOSITOR_EXPORT QWaylandInputDevicePrivate : public QObjectPrivate, public QtWaylandServer::wl_seat +{ +public: + Q_DECLARE_PUBLIC(QWaylandInputDevice) + + QWaylandInputDevicePrivate(QWaylandInputDevice *device, QWaylandCompositor *compositor); + ~QWaylandInputDevicePrivate(); + + void clientRequestedDataDevice(QtWayland::DataDeviceManager *dndSelection, struct wl_client *client, uint32_t id); + void setCapabilities(QWaylandInputDevice::CapabilityFlags caps); + + static QWaylandInputDevicePrivate *get(QWaylandInputDevice *device) { return device->d_func(); } + + QtWayland::DataDevice *dataDevice() const { return data_device.data(); } + +protected: + void seat_bind_resource(wl_seat::Resource *resource) Q_DECL_OVERRIDE; + + void seat_get_pointer(wl_seat::Resource *resource, + uint32_t id) Q_DECL_OVERRIDE; + void seat_get_keyboard(wl_seat::Resource *resource, + uint32_t id) Q_DECL_OVERRIDE; + void seat_get_touch(wl_seat::Resource *resource, + uint32_t id) Q_DECL_OVERRIDE; + + void seat_destroy_resource(wl_seat::Resource *resource) Q_DECL_OVERRIDE; + +private: + QWaylandCompositor *compositor; + QWaylandView *mouseFocus; + QWaylandInputDevice::CapabilityFlags capabilities; + + QScopedPointer<QWaylandPointer> pointer; + QScopedPointer<QWaylandKeyboard> keyboard; + QScopedPointer<QWaylandTouch> touch; + QScopedPointer<QtWayland::DataDevice> data_device; + QScopedPointer<QWaylandDrag> drag_handle; + +}; + +QT_END_NAMESPACE + +#endif // QWAYLANDINPUT_P_H diff --git a/src/compositor/compositor_api/qwaylandinputpanel.cpp b/src/compositor/compositor_api/qwaylandinputpanel.cpp index db4cd3296..6f774cd98 100644 --- a/src/compositor/compositor_api/qwaylandinputpanel.cpp +++ b/src/compositor/compositor_api/qwaylandinputpanel.cpp @@ -3,36 +3,32 @@ ** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB). ** 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$ ** @@ -40,59 +36,48 @@ #include "qwaylandinputpanel.h" +#include <QtWaylandCompositor/QWaylandCompositor> + #include <private/qobject_p.h> #include "qwlinputpanel_p.h" -#include "qwlsurface_p.h" QT_BEGIN_NAMESPACE -class QWaylandInputPanelPrivate : public QObjectPrivate -{ -public: - QWaylandInputPanelPrivate(QtWayland::InputPanel *panel) - : inputPanel(panel) - { - } - - QtWayland::InputPanel *inputPanel; -}; - - -QWaylandInputPanel::QWaylandInputPanel(QtWayland::InputPanel *inputPanel) - : QObject(*new QWaylandInputPanelPrivate(inputPanel)) +QWaylandInputPanel::QWaylandInputPanel(QWaylandCompositor *compositor) + : QWaylandExtensionTemplate(compositor, *new QWaylandInputPanelPrivate(compositor)) { } -QtWayland::InputPanel *QWaylandInputPanel::handle() const +QWaylandSurface *QWaylandInputPanel::focus() const { - Q_D(const QWaylandInputPanel); + Q_D(const QWaylandInputPanel); - return d->inputPanel; + return d->focus(); } -QWaylandSurface *QWaylandInputPanel::focus() const +bool QWaylandInputPanel::visible() const { Q_D(const QWaylandInputPanel); - QtWayland::Surface *surface = d->inputPanel->focus(); - if (surface) - return surface->waylandSurface(); - return 0; + return d->inputPanelVisible(); } -bool QWaylandInputPanel::visible() const +QRect QWaylandInputPanel::cursorRectangle() const { Q_D(const QWaylandInputPanel); - return d->inputPanel->inputPanelVisible(); + return d->cursorRectangle(); } -QRect QWaylandInputPanel::cursorRectangle() const +const struct wl_interface *QWaylandInputPanel::interface() { - Q_D(const QWaylandInputPanel); + return QWaylandInputPanelPrivate::interface(); +} - return d->inputPanel->cursorRectangle(); +QByteArray QWaylandInputPanel::interfaceName() +{ + return QWaylandInputPanelPrivate::interfaceName(); } QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandinputpanel.h b/src/compositor/compositor_api/qwaylandinputpanel.h index 22dc8b9f4..cce1f4583 100644 --- a/src/compositor/compositor_api/qwaylandinputpanel.h +++ b/src/compositor/compositor_api/qwaylandinputpanel.h @@ -3,36 +3,32 @@ ** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB). ** 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$ ** @@ -41,7 +37,8 @@ #ifndef QWAYLANDINPUTPANEL_H #define QWAYLANDINPUTPANEL_H -#include <QtCompositor/qwaylandexport.h> +#include <QtWaylandCompositor/qwaylandexport.h> +#include <QtWaylandCompositor/qwaylandextension.h> #include <QObject> #include <QRect> @@ -52,11 +49,7 @@ class QWaylandCompositor; class QWaylandInputPanelPrivate; class QWaylandSurface; -namespace QtWayland { -class InputPanel; -} - -class Q_COMPOSITOR_EXPORT QWaylandInputPanel : public QObject +class Q_COMPOSITOR_EXPORT QWaylandInputPanel : public QWaylandExtensionTemplate<QWaylandInputPanel> { Q_OBJECT Q_DECLARE_PRIVATE(QWaylandInputPanel) @@ -66,14 +59,14 @@ class Q_COMPOSITOR_EXPORT QWaylandInputPanel : public QObject Q_PROPERTY(QRect cursorRectangle READ cursorRectangle NOTIFY cursorRectangleChanged) public: - explicit QWaylandInputPanel(QtWayland::InputPanel *inputPanel); - - QtWayland::InputPanel *handle() const; + explicit QWaylandInputPanel(QWaylandCompositor *compositor); QWaylandSurface *focus() const; bool visible() const; QRect cursorRectangle() const; + static const struct wl_interface *interface(); + static QByteArray interfaceName(); Q_SIGNALS: void focusChanged(); void visibleChanged(); diff --git a/src/compositor/compositor_api/qwaylandkeyboard.cpp b/src/compositor/compositor_api/qwaylandkeyboard.cpp new file mode 100644 index 000000000..f39bb3e04 --- /dev/null +++ b/src/compositor/compositor_api/qwaylandkeyboard.cpp @@ -0,0 +1,566 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB). +** 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 "qwaylandkeyboard.h" +#include "qwaylandkeyboard_p.h" +#include <QtWaylandCompositor/QWaylandCompositor> +#include <QtWaylandCompositor/QWaylandInputDevice> +#include <QtWaylandCompositor/QWaylandClient> + +#include <QtWaylandCompositor/QWaylandShellSurface> + +#include <QtCore/QFile> +#include <QtCore/QStandardPaths> + +#include <fcntl.h> +#include <unistd.h> +#ifndef QT_NO_WAYLAND_XKB +#include <sys/mman.h> +#include <sys/types.h> +#endif + +QT_BEGIN_NAMESPACE + +QWaylandKeyboardPrivate::QWaylandKeyboardPrivate(QWaylandInputDevice *seat) + : QtWaylandServer::wl_keyboard() + , seat(seat) + , focus() + , focusResource() + , keys() + , modsDepressed() + , modsLatched() + , modsLocked() + , group() + , pendingKeymap(false) +#ifndef QT_NO_WAYLAND_XKB + , keymap_fd(-1) + , xkb_state(0) +#endif + , repeatRate(40) + , repeatDelay(400) +{ +#ifndef QT_NO_WAYLAND_XKB + initXKB(); +#endif +} + +QWaylandKeyboardPrivate::~QWaylandKeyboardPrivate() +{ +#ifndef QT_NO_WAYLAND_XKB + if (xkb_context) { + if (keymap_area) + munmap(keymap_area, keymap_size); + close(keymap_fd); + xkb_context_unref(xkb_context); + xkb_state_unref(xkb_state); + } +#endif +} + +QWaylandKeyboardPrivate *QWaylandKeyboardPrivate::get(QWaylandKeyboard *keyboard) +{ + return keyboard->d_func(); +} + +void QWaylandKeyboardPrivate::checkFocusResource(Resource *keyboardResource) +{ + if (!keyboardResource || !focus) + return; + + // this is already the current resource, do no send enter twice + if (focusResource == keyboardResource) + return; + + // check if new wl_keyboard resource is from the client owning the focus surface + if (focus->resource()->client == keyboardResource->client()) { + sendEnter(focus, keyboardResource); + focusResource = keyboardResource; + } +} + +void QWaylandKeyboardPrivate::sendEnter(QWaylandSurface *surface, Resource *keyboardResource) +{ + uint32_t serial = compositor()->nextSerial(); + send_modifiers(keyboardResource->handle, serial, modsDepressed, modsLatched, modsLocked, group); + send_enter(keyboardResource->handle, serial, surface->resource(), QByteArray::fromRawData((char *)keys.data(), keys.size() * sizeof(uint32_t))); +} + +void QWaylandKeyboardPrivate::focused(QWaylandSurface *surface) +{ + if (surface && surface->isCursorSurface()) + surface = Q_NULLPTR; + if (focus != surface) { + if (focusResource) { + uint32_t serial = compositor()->nextSerial(); + send_leave(focusResource->handle, serial, focus->resource()); + } + focusDestroyListener.reset(); + if (surface) + focusDestroyListener.listenForDestruction(surface->resource()); + } + + Resource *resource = surface ? resourceMap().value(surface->waylandClient()) : 0; + + if (resource && (focus != surface || focusResource != resource)) + sendEnter(surface, resource); + + focusResource = resource; + focus = surface; + Q_EMIT q_func()->focusChanged(focus); +} + + +void QWaylandKeyboardPrivate::keyboard_bind_resource(wl_keyboard::Resource *resource) +{ +#ifndef QT_NO_WAYLAND_XKB + if (xkb_context) { + send_keymap(resource->handle, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, + keymap_fd, keymap_size); + } else +#endif + { + int null_fd = open("/dev/null", O_RDONLY); + send_keymap(resource->handle, 0 /* WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP */, + null_fd, 0); + close(null_fd); + } + checkFocusResource(resource); +} + +void QWaylandKeyboardPrivate::keyboard_destroy_resource(wl_keyboard::Resource *resource) +{ + if (focusResource == resource) + focusResource = 0; +} + +void QWaylandKeyboardPrivate::keyboard_release(wl_keyboard::Resource *resource) +{ + wl_resource_destroy(resource->handle); +} + +void QWaylandKeyboardPrivate::keyEvent(uint code, uint32_t state) +{ + uint key = code - 8; + if (state == WL_KEYBOARD_KEY_STATE_PRESSED) { + keys << key; + } else { + for (int i = 0; i < keys.size(); ++i) { + if (keys.at(i) == key) { + keys.remove(i); + } + } + } +} + +void QWaylandKeyboardPrivate::sendKeyEvent(uint code, uint32_t state) +{ + uint32_t time = compositor()->currentTimeMsecs(); + uint32_t serial = compositor()->nextSerial(); + uint key = code - 8; + if (focusResource) + send_key(focusResource->handle, serial, time, key, state); +} + +void QWaylandKeyboardPrivate::modifiers(uint32_t serial, uint32_t mods_depressed, + uint32_t mods_latched, uint32_t mods_locked, uint32_t group) +{ + if (focusResource) { + send_modifiers(focusResource->handle, serial, mods_depressed, mods_latched, mods_locked, group); + } +} + +void QWaylandKeyboardPrivate::updateModifierState(uint code, uint32_t state) +{ +#ifndef QT_NO_WAYLAND_XKB + if (!xkb_context) + return; + + xkb_state_update_key(xkb_state, code, state == WL_KEYBOARD_KEY_STATE_PRESSED ? XKB_KEY_DOWN : XKB_KEY_UP); + + uint32_t modsDepressed = xkb_state_serialize_mods(xkb_state, (xkb_state_component)XKB_STATE_DEPRESSED); + uint32_t modsLatched = xkb_state_serialize_mods(xkb_state, (xkb_state_component)XKB_STATE_LATCHED); + uint32_t modsLocked = xkb_state_serialize_mods(xkb_state, (xkb_state_component)XKB_STATE_LOCKED); + uint32_t group = xkb_state_serialize_group(xkb_state, (xkb_state_component)XKB_STATE_EFFECTIVE); + + if (this->modsDepressed == modsDepressed + && this->modsLatched == modsLatched + && this->modsLocked == modsLocked + && this->group == group) + return; + + this->modsDepressed = modsDepressed; + this->modsLatched = modsLatched; + this->modsLocked = modsLocked; + this->group = group; + + modifiers(compositor()->nextSerial(), modsDepressed, modsLatched, modsLocked, group); +#else + Q_UNUSED(code); + Q_UNUSED(state); +#endif +} + +void QWaylandKeyboardPrivate::updateKeymap() +{ + // There must be no keys pressed when changing the keymap, + // see http://lists.freedesktop.org/archives/wayland-devel/2013-October/011395.html + if (!pendingKeymap || !keys.isEmpty()) + return; + + pendingKeymap = false; +#ifndef QT_NO_WAYLAND_XKB + if (!xkb_context) + return; + + createXKBKeymap(); + foreach (Resource *res, resourceMap()) { + send_keymap(res->handle, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, keymap_fd, keymap_size); + } + + xkb_state_update_mask(xkb_state, 0, modsLatched, modsLocked, 0, 0, 0); + if (focusResource) + send_modifiers(focusResource->handle, + compositor()->nextSerial(), + modsDepressed, + modsLatched, + modsLocked, + group); +#endif +} + +#ifndef QT_NO_WAYLAND_XKB +static int createAnonymousFile(size_t size) +{ + QString path = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation); + if (path.isEmpty()) + return -1; + + QByteArray name = QFile::encodeName(path + QStringLiteral("/qtwayland-XXXXXX")); + + int fd = mkstemp(name.data()); + if (fd < 0) + return -1; + + long flags = fcntl(fd, F_GETFD); + if (flags == -1 || fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) { + close(fd); + fd = -1; + } + unlink(name.constData()); + + if (fd < 0) + return -1; + + if (ftruncate(fd, size) < 0) { + close(fd); + return -1; + } + + return fd; +} + +void QWaylandKeyboardPrivate::initXKB() +{ + xkb_context = xkb_context_new(static_cast<xkb_context_flags>(0)); + if (!xkb_context) { + qWarning("Failed to create a XKB context: keymap will not be supported"); + return; + } + + createXKBKeymap(); +} + + +void QWaylandKeyboardPrivate::createXKBState(xkb_keymap *keymap) +{ + char *keymap_str = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_FORMAT_TEXT_V1); + if (!keymap_str) { + qWarning("Failed to compile global XKB keymap"); + return; + } + + keymap_size = strlen(keymap_str) + 1; + if (keymap_fd >= 0) + close(keymap_fd); + keymap_fd = createAnonymousFile(keymap_size); + if (keymap_fd < 0) { + qWarning("Failed to create anonymous file of size %lu", static_cast<unsigned long>(keymap_size)); + return; + } + + keymap_area = static_cast<char *>(mmap(0, keymap_size, PROT_READ | PROT_WRITE, MAP_SHARED, keymap_fd, 0)); + if (keymap_area == MAP_FAILED) { + close(keymap_fd); + keymap_fd = -1; + qWarning("Failed to map shared memory segment"); + return; + } + + strcpy(keymap_area, keymap_str); + free(keymap_str); + + if (xkb_state) + xkb_state_unref(xkb_state); + xkb_state = xkb_state_new(keymap); +} + +void QWaylandKeyboardPrivate::createXKBKeymap() +{ + if (!xkb_context) + return; + + struct xkb_rule_names rule_names = { strdup(qPrintable(keymap.rules())), + strdup(qPrintable(keymap.model())), + strdup(qPrintable(keymap.layout())), + strdup(qPrintable(keymap.variant())), + strdup(qPrintable(keymap.options())) }; + struct xkb_keymap *keymap = xkb_keymap_new_from_names(xkb_context, &rule_names, static_cast<xkb_keymap_compile_flags>(0)); + + if (keymap) { + createXKBState(keymap); + xkb_keymap_unref(keymap); + } else { + qWarning("Failed to load the '%s' XKB keymap.", qPrintable(this->keymap.layout())); + } + + free((char *)rule_names.rules); + free((char *)rule_names.model); + free((char *)rule_names.layout); + free((char *)rule_names.variant); + free((char *)rule_names.options); +} +#endif + +/*! + * \class QWaylandKeyboard + * \inmodule QtWaylandCompositor + * \brief The QWaylandKeyboard class provides access to a keyboard device. + * + * This class provides access to the keyboard device in a QWaylandInputDevice. It corresponds to + * the Wayland interface wl_keyboard. + */ + +/*! + * Constructs a QWaylandKeyboard for the given \a inputDevice and with the given \a parent. + */ +QWaylandKeyboard::QWaylandKeyboard(QWaylandInputDevice *inputDevice, QObject *parent) + : QWaylandObject(* new QWaylandKeyboardPrivate(inputDevice), parent) +{ + Q_D(QWaylandKeyboard); + connect(&d->focusDestroyListener, &QWaylandDestroyListener::fired, this, &QWaylandKeyboard::focusDestroyed); +} + +/*! + * Returns the input device for this QWaylandKeyboard. + */ +QWaylandInputDevice *QWaylandKeyboard::inputDevice() const +{ + Q_D(const QWaylandKeyboard); + return d->seat; +} + +/*! + * Returns the compositor for this QWaylandKeyboard. + */ +QWaylandCompositor *QWaylandKeyboard::compositor() const +{ + Q_D(const QWaylandKeyboard); + return d->seat->compositor(); +} + +/*! + * \internal + */ +void QWaylandKeyboard::focusDestroyed(void *data) +{ + Q_UNUSED(data); + Q_D(QWaylandKeyboard); + d->focusDestroyListener.reset(); + + d->focus = 0; + d->focusResource = 0; +} + +/*! + * Returns the client that currently has keyboard focus. + */ +QWaylandClient *QWaylandKeyboard::focusClient() const +{ + Q_D(const QWaylandKeyboard); + if (!d->focusResource) + return Q_NULLPTR; + return QWaylandClient::fromWlClient(compositor(), d->focusResource->client()); +} + +/*! + * Sends the current key modifiers to \a client with the given \a serial. + */ +void QWaylandKeyboard::sendKeyModifiers(QWaylandClient *client, uint serial) +{ + Q_D(QWaylandKeyboard); + QtWaylandServer::wl_keyboard::Resource *resource = d->resourceMap().value(client->client()); + if (resource) + d->send_modifiers(resource->handle, serial, d->modsDepressed, d->modsLatched, d->modsLocked, d->group); +} + +/*! + * Sends a key press event with the key \a code to the current keyboard focus. + */ +void QWaylandKeyboard::sendKeyPressEvent(uint code) +{ + Q_D(QWaylandKeyboard); + d->sendKeyEvent(code, WL_KEYBOARD_KEY_STATE_PRESSED); +} + +/*! + * Sends a key release event with the key \a code to the current keyboard focus. + */ +void QWaylandKeyboard::sendKeyReleaseEvent(uint code) +{ + Q_D(QWaylandKeyboard); + d->sendKeyEvent(code, WL_KEYBOARD_KEY_STATE_RELEASED); +} + +/*! + * Returns the current repeat rate. + */ +quint32 QWaylandKeyboard::repeatRate() const +{ + Q_D(const QWaylandKeyboard); + return d->repeatRate; +} + +/*! + * Sets the repeat rate to \a rate. + */ +void QWaylandKeyboard::setRepeatRate(quint32 rate) +{ + Q_D(QWaylandKeyboard); + + if (d->repeatRate == rate) + return; + + // TODO: As of today 2015-11-25, we don't support Wayland 1.6 + // because of CI limitations. Once the protocol is updated + // we can send keyboard repeat information to the client as + // per wl_seat version 4 + + qWarning("Setting QWaylandKeyboard::repeatRate has no effect until QtWaylandCompositor support wl_seat 4"); + + d->repeatRate = rate; + Q_EMIT repeatRateChanged(rate); +} + +/*! + * Returns the current repeat delay. + */ +quint32 QWaylandKeyboard::repeatDelay() const +{ + Q_D(const QWaylandKeyboard); + return d->repeatDelay; +} + +/*! + * Sets the repeat delay to \a delay. + */ +void QWaylandKeyboard::setRepeatDelay(quint32 delay) +{ + Q_D(QWaylandKeyboard); + + if (d->repeatDelay == delay) + return; + + // TODO: As of today 2015-11-25, we don't support Wayland 1.6 + // because of CI limitations. Once the protocol is updated + // we can send keyboard repeat information to the client as + // per wl_seat version 4 + + qWarning("Setting QWaylandKeyboard::repeatDelay has no effect until QtWaylandCompositor support wl_seat 4"); + + d->repeatDelay = delay; + Q_EMIT repeatDelayChanged(delay); +} + +/*! + * Returns the currently focused surface. + */ +QWaylandSurface *QWaylandKeyboard::focus() const +{ + Q_D(const QWaylandKeyboard); + return d->focus; +} + +/*! + * Sets the current focus to \a surface. + */ +bool QWaylandKeyboard::setFocus(QWaylandSurface *surface) +{ + Q_D(QWaylandKeyboard); + QWaylandShellSurface *shellsurface = QWaylandShellSurface::findIn(surface); + if (shellsurface && shellsurface->focusPolicy() == QWaylandShellSurface::NoKeyboardFocus) + return false; + d->focused(surface); + return true; +} + +/*! + * Sets the keyboard's keymap to \a keymap. + */ +void QWaylandKeyboard::setKeymap(const QWaylandKeymap &keymap) +{ + Q_D(QWaylandKeyboard); + d->keymap = keymap; + d->pendingKeymap = true; + + // If there is no key currently pressed, update right away the keymap + // Otherwise, delay the update when keys are released + // see http://lists.freedesktop.org/archives/wayland-devel/2013-October/011395.html + if (d->keys.isEmpty()) { + d->updateKeymap(); + } +} + +/*! + * \internal + */ +void QWaylandKeyboard::addClient(QWaylandClient *client, uint32_t id, uint32_t version) +{ + Q_D(QWaylandKeyboard); + d->add(client->client(), id, qMin<uint32_t>(QtWaylandServer::wl_keyboard::interfaceVersion(), version)); +} + +QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandkeyboard.h b/src/compositor/compositor_api/qwaylandkeyboard.h new file mode 100644 index 000000000..3b2282ae7 --- /dev/null +++ b/src/compositor/compositor_api/qwaylandkeyboard.h @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB). +** 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 QWAYLANDKEYBOARD_H +#define QWAYLANDKEYBOARD_H + +#include <QtCore/QObject> + +#include <QtWaylandCompositor/QWaylandExtension> +#include <QtWaylandCompositor/QWaylandSurface> + +QT_BEGIN_NAMESPACE + +class QWaylandKeyboard; +class QWaylandKeyboardPrivate; +class QWaylandInputDevice; + +class Q_COMPOSITOR_EXPORT QWaylandKeymap +{ +public: + QWaylandKeymap(const QString &layout = QString(), const QString &variant = QString(), const QString &options = QString(), + const QString &model = QString(), const QString &rules = QString()); + + inline QString layout() const { return m_layout; } + inline QString variant() const { return m_variant; } + inline QString options() const { return m_options; } + inline QString rules() const { return m_rules; } + inline QString model() const { return m_model; } + +private: + QString m_layout; + QString m_variant; + QString m_options; + QString m_rules; + QString m_model; +}; + +class Q_COMPOSITOR_EXPORT QWaylandKeyboard : public QWaylandObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QWaylandKeyboard) + Q_PROPERTY(quint32 repeatRate READ repeatRate WRITE setRepeatRate NOTIFY repeatRateChanged) + Q_PROPERTY(quint32 repeatDelay READ repeatDelay WRITE setRepeatDelay NOTIFY repeatDelayChanged) +public: + QWaylandKeyboard(QWaylandInputDevice *inputDevice, QObject *parent = 0); + + QWaylandInputDevice *inputDevice() const; + QWaylandCompositor *compositor() const; + + quint32 repeatRate() const; + void setRepeatRate(quint32 rate); + + quint32 repeatDelay() const; + void setRepeatDelay(quint32 delay); + + virtual bool setFocus(QWaylandSurface *surface); + virtual void setKeymap(const QWaylandKeymap &keymap); + + virtual void sendKeyModifiers(QWaylandClient *client, uint32_t serial); + virtual void sendKeyPressEvent(uint code); + virtual void sendKeyReleaseEvent(uint code); + + QWaylandSurface *focus() const; + QWaylandClient *focusClient() const; + + virtual void addClient(QWaylandClient *client, uint32_t id, uint32_t version); + +Q_SIGNALS: + void focusChanged(QWaylandSurface *surface); + void repeatRateChanged(quint32 repeatRate); + void repeatDelayChanged(quint32 repeatDelay); + +private: + void focusDestroyed(void *data); +}; + +QT_END_NAMESPACE + +#endif //QWAYLANDKEYBOARD_H diff --git a/src/compositor/compositor_api/qwaylandkeyboard_p.h b/src/compositor/compositor_api/qwaylandkeyboard_p.h new file mode 100644 index 000000000..86e3e365f --- /dev/null +++ b/src/compositor/compositor_api/qwaylandkeyboard_p.h @@ -0,0 +1,139 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB). +** 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 QTWAYLAND_QWLKEYBOARD_P_H +#define QTWAYLAND_QWLKEYBOARD_P_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. +// + +#include <QtWaylandCompositor/qwaylandexport.h> +#include <QtWaylandCompositor/qwaylandinput.h> +#include <QtWaylandCompositor/qwaylandkeyboard.h> +#include <QtWaylandCompositor/qwaylanddestroylistener.h> + +#include <QtCore/private/qobject_p.h> +#include <QtWaylandCompositor/private/qwayland-server-wayland.h> + +#include <QtCore/QVector> + +#ifndef QT_NO_WAYLAND_XKB +#include <xkbcommon/xkbcommon.h> +#endif + + +QT_BEGIN_NAMESPACE + +class Q_COMPOSITOR_EXPORT QWaylandKeyboardPrivate : public QObjectPrivate + , public QtWaylandServer::wl_keyboard +{ +public: + Q_DECLARE_PUBLIC(QWaylandKeyboard) + + static QWaylandKeyboardPrivate *get(QWaylandKeyboard *keyboard); + + QWaylandKeyboardPrivate(QWaylandInputDevice *seat); + ~QWaylandKeyboardPrivate(); + + QWaylandCompositor *compositor() const { return seat->compositor(); } + + void focused(QWaylandSurface* surface); + void modifiers(uint32_t serial, uint32_t mods_depressed, + uint32_t mods_latched, uint32_t mods_locked, uint32_t group); + +#ifndef QT_NO_WAYLAND_XKB + struct xkb_state *xkbState() const { return xkb_state; } + uint32_t xkbModsMask() const { return modsDepressed | modsLatched | modsLocked; } +#endif + + void keyEvent(uint code, uint32_t state); + void sendKeyEvent(uint code, uint32_t state); + void updateModifierState(uint code, uint32_t state); + void updateKeymap(); + + void checkFocusResource(Resource *resource); + void sendEnter(QWaylandSurface *surface, Resource *resource); + +protected: + void keyboard_bind_resource(Resource *resource); + void keyboard_destroy_resource(Resource *resource); + void keyboard_release(Resource *resource) Q_DECL_OVERRIDE; + +private: +#ifndef QT_NO_WAYLAND_XKB + void initXKB(); + void createXKBKeymap(); + void createXKBState(xkb_keymap *keymap); +#endif + + QWaylandInputDevice *seat; + + QWaylandSurface *focus; + Resource *focusResource; + QWaylandDestroyListener focusDestroyListener; + + QVector<uint32_t> keys; + uint32_t modsDepressed; + uint32_t modsLatched; + uint32_t modsLocked; + uint32_t group; + + QWaylandKeymap keymap; + bool pendingKeymap; +#ifndef QT_NO_WAYLAND_XKB + size_t keymap_size; + int keymap_fd; + char *keymap_area; + struct xkb_context *xkb_context; + struct xkb_state *xkb_state; +#endif + + quint32 repeatRate; + quint32 repeatDelay; +}; + +QT_END_NAMESPACE + +#endif // QTWAYLAND_QWLKEYBOARD_P_H diff --git a/src/compositor/compositor_api/qwaylandoutput.cpp b/src/compositor/compositor_api/qwaylandoutput.cpp index ba9f39887..b3c94645d 100644 --- a/src/compositor/compositor_api/qwaylandoutput.cpp +++ b/src/compositor/compositor_api/qwaylandoutput.cpp @@ -4,254 +4,893 @@ ** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB). ** 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 "qwaylandoutput.h" +#include "qwaylandoutput_p.h" + +#include <QtWaylandCompositor/QWaylandCompositor> +#include <QtWaylandCompositor/QWaylandView> + +#include <QtWaylandCompositor/private/qwaylandsurface_p.h> +#include <QtWaylandCompositor/private/qwaylandcompositor_p.h> + #include <QtCore/QCoreApplication> #include <QtCore/QtMath> #include <QtGui/QWindow> #include <QtGui/QExposeEvent> #include <private/qobject_p.h> -#include "wayland_wrapper/qwlcompositor_p.h" -#include "wayland_wrapper/qwloutput_p.h" -#include "qwaylandcompositor.h" -#include "qwaylandoutput.h" -#include "qwaylandsurface.h" +QT_BEGIN_NAMESPACE -QWaylandOutput::QWaylandOutput(QWaylandCompositor *compositor, QWindow *window, - const QString &manufacturer, const QString &model) - : QObject() - , d_ptr(new QtWayland::Output(compositor->handle(), window)) +static QtWaylandServer::wl_output::subpixel toWlSubpixel(const QWaylandOutput::Subpixel &value) { - d_ptr->m_output = this; - d_ptr->setManufacturer(manufacturer); - d_ptr->setModel(model); - d_ptr->compositor()->addOutput(this); + switch (value) { + case QWaylandOutput::SubpixelUnknown: + return QtWaylandServer::wl_output::subpixel_unknown; + case QWaylandOutput::SubpixelNone: + return QtWaylandServer::wl_output::subpixel_none; + case QWaylandOutput::SubpixelHorizontalRgb: + return QtWaylandServer::wl_output::subpixel_horizontal_rgb; + case QWaylandOutput::SubpixelHorizontalBgr: + return QtWaylandServer::wl_output::subpixel_horizontal_bgr; + case QWaylandOutput::SubpixelVerticalRgb: + return QtWaylandServer::wl_output::subpixel_vertical_rgb; + case QWaylandOutput::SubpixelVerticalBgr: + return QtWaylandServer::wl_output::subpixel_vertical_bgr; + default: + break; + } + + return QtWaylandServer::wl_output::subpixel_unknown; +} + +static QtWaylandServer::wl_output::transform toWlTransform(const QWaylandOutput::Transform &value) +{ + switch (value) { + case QWaylandOutput::Transform90: + return QtWaylandServer::wl_output::transform_90; + case QWaylandOutput::Transform180: + return QtWaylandServer::wl_output::transform_180; + case QWaylandOutput::Transform270: + return QtWaylandServer::wl_output::transform_270; + case QWaylandOutput::TransformFlipped: + return QtWaylandServer::wl_output::transform_flipped; + case QWaylandOutput::TransformFlipped90: + return QtWaylandServer::wl_output::transform_flipped_90; + case QWaylandOutput::TransformFlipped180: + return QtWaylandServer::wl_output::transform_flipped_180; + case QWaylandOutput::TransformFlipped270: + return QtWaylandServer::wl_output::transform_flipped_270; + default: + break; + } + + return QtWaylandServer::wl_output::transform_normal; +} + +QWaylandOutputPrivate::QWaylandOutputPrivate() + : QtWaylandServer::wl_output() + , compositor(Q_NULLPTR) + , window(Q_NULLPTR) + , subpixel(QWaylandOutput::SubpixelUnknown) + , transform(QWaylandOutput::TransformNormal) + , scaleFactor(1) + , sizeFollowsWindow(true) + , initialized(false) +{ + mode.size = QSize(); + mode.refreshRate = 60; + + qRegisterMetaType<QWaylandOutput::Mode>("WaylandOutput::Mode"); } +QWaylandOutputPrivate::~QWaylandOutputPrivate() +{ +} + +void QWaylandOutputPrivate::output_bind_resource(Resource *resource) +{ + send_geometry(resource->handle, + position.x(), position.y(), + physicalSize.width(), physicalSize.height(), + toWlSubpixel(subpixel), manufacturer, model, + toWlTransform(transform)); + + send_mode(resource->handle, mode_current | mode_preferred, + mode.size.width(), mode.size.height(), + mode.refreshRate); + + if (resource->version() >= 2) { + send_scale(resource->handle, scaleFactor); + send_done(resource->handle); + } +} + +void QWaylandOutputPrivate::sendGeometryInfo() +{ + Q_FOREACH (Resource *resource, resourceMap().values()) { + send_geometry(resource->handle, + position.x(), position.x(), + physicalSize.width(), physicalSize.height(), + toWlSubpixel(subpixel), manufacturer, model, + toWlTransform(transform)); + if (resource->version() >= 2) + send_done(resource->handle); + } +} + + +void QWaylandOutputPrivate::addView(QWaylandView *view, QWaylandSurface *surface) +{ + for (int i = 0; i < surfaceViews.size(); i++) { + if (surface == surfaceViews.at(i).surface) { + if (!surfaceViews.at(i).views.contains(view)) { + surfaceViews[i].views.append(view); + } + return; + } + } + + surfaceViews.append(QWaylandSurfaceViewMapper(surface,view)); +} + +void QWaylandOutputPrivate::removeView(QWaylandView *view, QWaylandSurface *surface) +{ + Q_Q(QWaylandOutput); + for (int i = 0; i < surfaceViews.size(); i++) { + if (surface == surfaceViews.at(i).surface) { + bool removed = surfaceViews[i].views.removeOne(view); + if (surfaceViews.at(i).views.isEmpty() && removed) { + if (surfaceViews.at(i).has_entered) + q->surfaceLeave(surface); + surfaceViews.remove(i); + } + return; + } + } + qWarning("%s Could not find view %p for surface %p to remove. Possible invalid state", Q_FUNC_INFO, view, surface); +} + +QWaylandOutput::QWaylandOutput() + : QWaylandObject(*new QWaylandOutputPrivate()) +{ +} + +/*! + \qmltype WaylandOutput + \inqmlmodule QtWayland.Compositor + \brief Type providing access to a displayable area managed by the compositor. + + The WaylandOutput manages a rectangular part of the compositor's geometry that + can be used for displaying client content. This could, for instance, be a screen + managed by the WaylandCompositor. + + The type corresponds to the wl_output interface in the Wayland protocol. +*/ + +/*! + \class QWaylandOutput + \inmodule QtWaylandCompositor + \brief The QWaylandOutput class provides access to a displayable area managed by the compositor. + + The QWaylandOutput manages a rectangular part of the compositor's geometry that + can be used for displaying client content. This could, for instance, be a screen + managed by the QWaylandCompositor. + + The class corresponds to the wl_output interface in the Wayland protocol. +*/ + +/*! + * Constructs a QWaylandOutput in \a compositor and with the specified \a window. The + * \l{QWaylandCompositor::create()}{create()} function must have been called on the + * \a compositor before a QWaylandOutput is constructed for it. + * + * The QWaylandOutput object is initialized later, in reaction to an event. + * At this point it is added as an output for the \a compositor. If it is the + * first QWaylandOutput object created for this \a compositor, it becomes the + * \l{QWaylandCompositor::defaultOutput()}{default output}. + */ +QWaylandOutput::QWaylandOutput(QWaylandCompositor *compositor, QWindow *window) + : QWaylandObject(*new QWaylandOutputPrivate()) +{ + Q_D(QWaylandOutput); + d->compositor = compositor; + d->window = window; + QWaylandCompositorPrivate::get(compositor)->addPolishObject(this); +} + +/*! + * Destroys the QWaylandOutput. + */ QWaylandOutput::~QWaylandOutput() { - d_ptr->compositor()->removeOutput(this); - delete d_ptr; + Q_D(QWaylandOutput); + if (d->compositor) + QWaylandCompositorPrivate::get(d->compositor)->removeOutput(this); +} + +/*! + * \internal + */ +void QWaylandOutput::initialize() +{ + Q_D(QWaylandOutput); + + Q_ASSERT(!d->initialized); + Q_ASSERT(d->compositor); + Q_ASSERT(d->compositor->isCreated()); + Q_ASSERT(d->window); + + d->mode.size = d->window->size(); + + QWaylandCompositorPrivate::get(d->compositor)->addOutput(this); + + QObject::connect(d->window, &QWindow::widthChanged, this, &QWaylandOutput::setWidth); + QObject::connect(d->window, &QWindow::heightChanged, this, &QWaylandOutput::setHeight); + QObject::connect(d->window, &QObject::destroyed, this, &QWaylandOutput::handleWindowDestroyed); + + d->init(d->compositor->display(), 2); + + d->initialized = true; } +/*! + * Returns the QWaylandOutput corresponding to \a resource. + */ QWaylandOutput *QWaylandOutput::fromResource(wl_resource *resource) { - QtWayland::OutputResource *outputResource = static_cast<QtWayland::OutputResource *>( - QtWayland::Output::Resource::fromResource(resource)); - if (!outputResource) - return Q_NULLPTR; + return static_cast<QWaylandOutputPrivate *>(QWaylandOutputPrivate::Resource::fromResource(resource)->output_object)->q_func(); +} - QtWayland::Output *output = static_cast<QtWayland::Output *>(outputResource->output_object); - if (!output) - return Q_NULLPTR; +/*! + * \internal + */ +struct ::wl_resource *QWaylandOutput::resourceForClient(QWaylandClient *client) const +{ + Q_D(const QWaylandOutput); + QWaylandOutputPrivate::Resource *r = d->resourceMap().value(client->client()); + if (r) + return r->handle; - return output->output(); + return Q_NULLPTR; } +/*! + * Schedules a QEvent::UpdateRequest to be delivered to the QWaylandOutput's \l{window()}{window}. + * + * \sa QWindow::requestUpdate() + */ void QWaylandOutput::update() { - QRect rect(QPoint(0, 0), window()->size()); - QRegion region(rect); - QExposeEvent *event = new QExposeEvent(region); - QCoreApplication::postEvent(window(), event); + Q_D(QWaylandOutput); + if (!d->window) + return; + d->window->requestUpdate(); } +/*! + * \qmlproperty object QtWaylandCompositor::WaylandOutput::compositor + * + * This property holds the compositor displaying content on this QWaylandOutput. + * This property can only be set once, before the WaylandOutput component is completed. + */ + +/*! + * Returns the compositor for this QWaylandOutput. + */ QWaylandCompositor *QWaylandOutput::compositor() const { - return d_ptr->compositor()->waylandCompositor(); + return d_func()->compositor; +} + +/*! + * \internal + */ +void QWaylandOutput::setCompositor(QWaylandCompositor *compositor) +{ + Q_D(QWaylandOutput); + + if (d->compositor == compositor) + return; + + if (d->initialized) { + qWarning("Setting QWaylandCompositor %p on QWaylandOutput %p is not supported after QWaylandOutput has been initialized\n", compositor, this); + return; + } + if (d->compositor && d->compositor != compositor) { + qWarning("Possible initialization error. Moving QWaylandOutput %p between compositor instances.\n", this); + } + + d->compositor = compositor; + + QWaylandCompositorPrivate::get(compositor)->addPolishObject(this); } +/*! + * \qmlproperty string QtWaylandCompositor::WaylandOutput::manufacturer + * + * This property holds a textual description of the manufacturer of this WaylandOutput. + */ + +/*! + * \property QWaylandOutput::manufacturer + * + * This property holds a textual description of the manufacturer of this QWaylandOutput. + */ QString QWaylandOutput::manufacturer() const { - return d_ptr->manufacturer(); + return d_func()->manufacturer; } +void QWaylandOutput::setManufacturer(const QString &manufacturer) +{ + d_func()->manufacturer = manufacturer; +} + +/*! + * \qmlproperty string QtWaylandCompositor::WaylandOutput::model + * + * This property holds a textual description of the model of this WaylandOutput. + */ + +/*! + * \property QWaylandOutput::model + * + * This property holds a textual description of the model of this QWaylandOutput. + */ QString QWaylandOutput::model() const { - return d_ptr->model(); + return d_func()->model; +} + +void QWaylandOutput::setModel(const QString &model) +{ + d_func()->model = model; } +/*! + * \qmlproperty point QtWaylandCompositor::WaylandOutput::position + * + * This property holds the position of this WaylandOutput in the compositor's coordinate system. + */ + +/*! + * \property QWaylandOutput::position + * + * This property holds the position of this QWaylandOutput in the compositor's coordinate system. + */ QPoint QWaylandOutput::position() const { - return d_ptr->position(); + return d_func()->position; } void QWaylandOutput::setPosition(const QPoint &pt) { - if (d_ptr->position() == pt) + Q_D(QWaylandOutput); + if (d->position == pt) return; - d_ptr->setPosition(pt); + d->position = pt; + + d->sendGeometryInfo(); + Q_EMIT positionChanged(); Q_EMIT geometryChanged(); } +/*! + * \property QWaylandOutput::mode + * + * This property holds the output's size in pixels and refresh rate in Hz. + */ QWaylandOutput::Mode QWaylandOutput::mode() const { - return d_ptr->mode(); + return d_func()->mode; } void QWaylandOutput::setMode(const Mode &mode) { - if (d_ptr->mode().size == mode.size && d_ptr->mode().refreshRate == mode.refreshRate) + Q_D(QWaylandOutput); + if (d->mode.size == mode.size && d->mode.refreshRate == mode.refreshRate) return; - d_ptr->setMode(mode); + d->mode = mode; + + Q_FOREACH (QWaylandOutputPrivate::Resource *resource, d->resourceMap().values()) { + d->send_mode(resource->handle, d->mode_current, + d->mode.size.width(), d->mode.size.height(), + d->mode.refreshRate * 1000); + if (resource->version() >= 2) + d->send_done(resource->handle); + } + Q_EMIT modeChanged(); Q_EMIT geometryChanged(); - if (window()) { - window()->resize(mode.size); - window()->setMinimumSize(mode.size); - window()->setMaximumSize(mode.size); + if (d->window) { + d->window->resize(mode.size); + d->window->setMinimumSize(mode.size); + d->window->setMaximumSize(mode.size); } } +/*! + * \qmlproperty rect QtWaylandCompositor::WaylandOutput::geometry + * + * This property holds the geometry of the WaylandOutput. + */ + +/*! + * \property QWaylandOutput::geometry + * + * This property holds the geometry of the QWaylandOutput. + * + * \sa QWaylandOutput::mode + */ QRect QWaylandOutput::geometry() const { - return d_ptr->geometry(); + Q_D(const QWaylandOutput); + return QRect(d->position, d->mode.size); } void QWaylandOutput::setGeometry(const QRect &geometry) { - if (d_ptr->geometry() == geometry) + Q_D(QWaylandOutput); + if (d->position == geometry.topLeft() && d->mode.size == geometry.size()) return; - d_ptr->setGeometry(geometry); + d->position = geometry.topLeft(); + d->mode.size = geometry.size(); + + Q_FOREACH (QWaylandOutputPrivate::Resource *resource, d->resourceMap().values()) { + d->send_geometry(resource->handle, + d->position.x(), d->position.y(), + d->physicalSize.width(), d->physicalSize.height(), + toWlSubpixel(d->subpixel), d->manufacturer, d->model, + toWlTransform(d->transform)); + d->send_mode(resource->handle, d->mode_current, + d->mode.size.width(), d->mode.size.height(), + d->mode.refreshRate * 1000); + if (resource->version() >= 2) + d->send_done(resource->handle); + } Q_EMIT positionChanged(); Q_EMIT modeChanged(); - - if (window()) { - window()->resize(geometry.size()); - window()->setMinimumSize(geometry.size()); - window()->setMaximumSize(geometry.size()); - } } +/*! + * \qmlproperty rect QtWaylandCompositor::WaylandOutput::availableGeometry + * + * This property holds the geometry of the WaylandOutput available for displaying content. + * + * \sa QWaylandOutput::geometry + */ + +/*! + * \property QWaylandOutput::availableGeometry + * + * This property holds the geometry of the QWaylandOutput available for displaying content. + * + * \sa QWaylandOutput::mode, QWaylandOutput::geometry + */ QRect QWaylandOutput::availableGeometry() const { - if (!d_ptr->availableGeometry().isValid()) - return QRect(d_ptr->position(), d_ptr->mode().size); + Q_D(const QWaylandOutput); + if (!d->availableGeometry.isValid()) + return QRect(d->position, d->mode.size); - return d_ptr->availableGeometry(); + return d->availableGeometry; } void QWaylandOutput::setAvailableGeometry(const QRect &availableGeometry) { - if (d_ptr->availableGeometry() == availableGeometry) + Q_D(QWaylandOutput); + if (d->availableGeometry == availableGeometry) return; - d_ptr->setAvailableGeometry(availableGeometry); + d->availableGeometry = availableGeometry; + Q_EMIT availableGeometryChanged(); } +/*! + * \qmlproperty size QtWaylandCompositor::WaylandOutput::physicalSize + * + * This property holds the physical size of the WaylandOutput in millimeters. + * + * \sa QWaylandOutput::geometry + */ + +/*! + * \property QWaylandOutput::physicalSize + * + * This property holds the physical size of the QWaylandOutput in millimeters. + * + * \sa QWaylandOutput::geometry, QWaylandOutput::mode + */ QSize QWaylandOutput::physicalSize() const { - return d_ptr->physicalSize(); + return d_func()->physicalSize; } void QWaylandOutput::setPhysicalSize(const QSize &size) { - if (d_ptr->physicalSize() == size) + Q_D(QWaylandOutput); + if (d->physicalSize == size) return; - d_ptr->setPhysicalSize(size); + d->physicalSize = size; + + d->sendGeometryInfo(); + Q_EMIT physicalSizeChanged(); } +/*! + * \enum QWaylandOutput::Subpixel + * + * This enum type is used to specify the subpixel arrangement of a QWaylandOutput. + * + * \value SubpixelUnknown The subpixel arrangement is not set. + * \value SubpixelNone There are no subpixels. + * \value SubpixelHorizontalRgb The subpixels are arranged horizontally in red, green, blue order. + * \value SubpixelHorizontalBgr The subpixels are arranged horizontally in blue, green, red order. + * \value SubpixelVerticalRgb The subpixels are arranged vertically in red, green, blue order. + * \value SubpixelVerticalBgr The subpixels are arranged vertically in blue, green, red order. + * + * \sa QWaylandOutput::subpixel + */ + +/*! + * \qmlproperty enum QtWaylandCompositor::WaylandOutput::subpixel + * + * This property holds the subpixel arrangement of this WaylandOutput. + * + * \list + * \li WaylandOutput.SubpixelUnknown The subpixel arrangement is not set. + * \li WaylandOutput.SubpixelNone There are no subpixels. + * \li WaylandOutput.SubpixelHorizontalRgb The subpixels are arranged horizontally in red, green, blue order. + * \li WaylandOutput.SubpixelHorizontalBgr The subpixels are arranged horizontally in blue, green, red order. + * \li WaylandOutput.SubpixelVerticalRgb The subpixels are arranged vertically in red, green, blue order. + * \li WaylandOutput.SubpixelVerticalBgr The subpixels are arranged vertically in blue, green, red order. + * \endlist + * + * The default is WaylandOutput.SubpixelUnknown. + */ + +/*! + * \property QWaylandOutput::subpixel + * + * This property holds the subpixel arrangement of this QWaylandOutput. The default is + * QWaylandOutput::SubpixelUnknown. + */ QWaylandOutput::Subpixel QWaylandOutput::subpixel() const { - return d_ptr->subpixel(); + return d_func()->subpixel; } void QWaylandOutput::setSubpixel(const Subpixel &subpixel) { - if (d_ptr->subpixel() == subpixel) + Q_D(QWaylandOutput); + if (d->subpixel == subpixel) return; - d_ptr->setSubpixel(subpixel); + d->subpixel = subpixel; + + d->sendGeometryInfo(); + Q_EMIT subpixelChanged(); } +/*! \enum QWaylandOutput::Transform + * + * This enum type is used to specify the orientation of a QWaylandOutput. + * + * \value TransformNormal The QWaylandOutput orientation is normal. + * \value Transform90 The QWaylandOutput is rotated 90 degrees. + * \value Transform180 The QWaylandOutput is rotated 180 degrees. + * \value Transform270 The QWaylandOutput is rotated 270 degrees. + * \value TransformFlipped The QWaylandOutput is mirrored. + * \value TransformFlipped90 The QWaylandOutput is mirrored, and rotated 90 degrees. + * \value TransformFlipped180 The QWaylandOutput is mirrored, and rotated 180 degrees. + * \value TransformFlipped270 The QWaylandOutput is mirrored, and rotated 270 degrees. + * + * \sa QWaylandOutput::transform +*/ + +/*! + * \qmlproperty enum QtWaylandCompositor::WaylandOutput::transform + * + * This property holds the transformation that the QWaylandCompositor applies to a surface + * to compensate for the orientation of the QWaylandOutput. + * + * \list + * \li WaylandOutput.TransformNormal The QWaylandOutput orientation is normal. + * \li WaylandOutput.Transform90 The QWaylandOutput is rotated 90 degrees. + * \li WaylandOutput.Transform180 The QWaylandOutput is rotated 180 degrees. + * \li WaylandOutput.Transform270 The QWaylandOutput is rotated 270 degrees. + * \li WaylandOutput.TransformFlipped The QWaylandOutput is mirrored. + * \li WaylandOutput.TransformFlipped90 The QWaylandOutput is mirrored, then rotated 90 degrees. + * \li WaylandOutput.TransformFlipped180 The QWaylandOutput is mirrored, then rotated 180 degrees. + * \li WaylandOutput.TransformFlipped270 The QWaylandOutput is mirrored, then rotated 270 degrees. + * \endlist + * + * The default is WaylandOutput.TransformNormal. + */ + +/*! + * \property QWaylandOutput::transform + * + * This property holds the transformation that the QWaylandCompositor applies to a surface + * to compensate for the orientation of the QWaylandOutput. + * + * The default is QWaylandOutput::TransformNormal. + */ QWaylandOutput::Transform QWaylandOutput::transform() const { - return d_ptr->transform(); + return d_func()->transform; } void QWaylandOutput::setTransform(const Transform &transform) { - if (d_ptr->transform() == transform) + Q_D(QWaylandOutput); + if (d->transform == transform) return; - d_ptr->setTransform(transform); + d->transform = transform; + + d->sendGeometryInfo(); + Q_EMIT transformChanged(); } +/*! + * \qmlproperty int QtWaylandCompositor::WaylandOutput::scaleFactor + * + * This property holds the factor by which the WaylandCompositor scales surface buffers + * before they are displayed. This is used on high density output devices where unscaled content + * would be too small to be practical. The client can in turn set the scale factor of its + * buffer to match the output if it prefers to provide high resolution content that is + * suitable for the output device. + * + * The default is 1 (no scaling). + */ + +/*! + * \property QWaylandOutput::scaleFactor + * + * This property holds the factor by which the QWaylandCompositor scales surface buffers + * before they are displayed. This is used on high density output devices where unscaled content + * would be too small to be practical. The client can in turn set the scale factor of its + * buffer to match the output if it prefers to provide high resolution content that is + * suitable for the output device. + * + * The default is 1 (no scaling). + */ int QWaylandOutput::scaleFactor() const { - return d_ptr->scaleFactor(); + return d_func()->scaleFactor; } void QWaylandOutput::setScaleFactor(int scale) { - if (d_ptr->scaleFactor() == scale) + Q_D(QWaylandOutput); + if (d->scaleFactor == scale) return; - d_ptr->setScaleFactor(scale); + d->scaleFactor = scale; + + Q_FOREACH (QWaylandOutputPrivate::Resource *resource, d->resourceMap().values()) { + if (resource->version() >= 2) { + d->send_scale(resource->handle, scale); + d->send_done(resource->handle); + } + } + Q_EMIT scaleFactorChanged(); +} + +/*! + * \qmlproperty bool QtWaylandCompositor::WaylandOutput::sizeFollowsWindow + * + * This property controls whether the size of the WaylandOutput matches the + * size of its window. + * + * The default is true. + */ + +/*! + * \property QWaylandOutput::sizeFollowsWindow + * + * This property controls whether the size of the QWaylandOutput matches the + * size of its window. + * + * The default is true. + */ +bool QWaylandOutput::sizeFollowsWindow() const +{ + return d_func()->sizeFollowsWindow; +} +void QWaylandOutput::setSizeFollowsWindow(bool follow) +{ + Q_D(QWaylandOutput); + if (follow != d->sizeFollowsWindow) { + if (follow) { + QObject::connect(d->window, &QWindow::widthChanged, this, &QWaylandOutput::setWidth); + QObject::connect(d->window, &QWindow::heightChanged, this, &QWaylandOutput::setHeight); + } else { + QObject::disconnect(d->window, &QWindow::widthChanged, this, &QWaylandOutput::setWidth); + QObject::disconnect(d->window, &QWindow::heightChanged, this, &QWaylandOutput::setHeight); + } + d->sizeFollowsWindow = follow; + Q_EMIT sizeFollowsWindowChanged(); + } } +/*! + * \qmlproperty object QtWaylandCompositor::WaylandOutput::window + * + * This property holds the Window for this WaylandOutput. This property can only be set once, + * before the WaylandOutput component is completed. + */ + +/*! + * \property QWaylandOutput::window + * + * This property holds the QWindow for this QWaylandOutput. + */ QWindow *QWaylandOutput::window() const { - return d_ptr->window(); + return d_func()->window; } -QtWayland::Output *QWaylandOutput::handle() +void QWaylandOutput::setWindow(QWindow *window) { - return d_ptr; + Q_D(QWaylandOutput); + if (d->window == window) + return; + if (d->initialized) { + qWarning("Setting QWindow %p on QWaylandOutput %p is not supported after QWaylandOutput has been initialized\n", window, this); + return; + } + d->window = window; + emit windowChanged(); +} + +/*! + * Tells the QWaylandOutput that a frame has started. + */ +void QWaylandOutput::frameStarted() +{ + Q_D(QWaylandOutput); + for (int i = 0; i < d->surfaceViews.size(); i++) { + QWaylandSurfaceViewMapper &surfacemapper = d->surfaceViews[i]; + if (surfacemapper.maybeThrottelingView()) + surfacemapper.surface->frameStarted(); + } } -QList<QWaylandSurface *> QWaylandOutput::surfaces() const +/*! + * Sends pending frame callbacks. + */ +void QWaylandOutput::sendFrameCallbacks() { - QList<QWaylandSurface *> list; - Q_FOREACH (QWaylandSurface *surface, d_ptr->compositor()->waylandCompositor()->surfaces()) { - if (surface->outputs().contains(const_cast<QWaylandOutput *>(this))) - list.append(surface); + Q_D(QWaylandOutput); + for (int i = 0; i < d->surfaceViews.size(); i++) { + const QWaylandSurfaceViewMapper &surfacemapper = d->surfaceViews.at(i); + if (surfacemapper.surface && surfacemapper.surface->isMapped()) { + if (!surfacemapper.has_entered) { + surfaceEnter(surfacemapper.surface); + d->surfaceViews[i].has_entered = true; + } + if (surfacemapper.maybeThrottelingView()) + surfacemapper.surface->sendFrameCallbacks(); + } } - return list; + wl_display_flush_clients(d->compositor->display()); +} + +/*! + * \internal + */ +void QWaylandOutput::surfaceEnter(QWaylandSurface *surface) +{ + if (!surface) + return; + QWaylandSurfacePrivate::get(surface)->send_enter(resourceForClient(surface->client())); +} + +/*! + * \internal + */ +void QWaylandOutput::surfaceLeave(QWaylandSurface *surface) +{ + if (!surface || !surface->client()) + return; + QWaylandSurfacePrivate::get(surface)->send_leave(resourceForClient(surface->client())); +} + +/*! + * This functions sets the width of this QWaylandOutput to \a newWidth. + * + * \sa setHeight, QWaylandOutput::geometry + */ +void QWaylandOutput::setWidth(int newWidth) +{ + Q_D(QWaylandOutput); + if (d->mode.size.width() == newWidth) + return; + + QSize s = d->mode.size; + s.setWidth(newWidth); + setGeometry(QRect(d->position, s)); +} + +/*! + * This functions sets the height of this QWaylandOutput to \a newHeight. + * + * \sa setWidth, QWaylandOutput::geometry + */ +void QWaylandOutput::setHeight(int newHeight) +{ + Q_D(QWaylandOutput); + if (d->mode.size.height() == newHeight) + return; + + QSize s = d->mode.size; + s.setHeight(newHeight); + setGeometry(QRect(d->position, s)); +} + +/*! + * \internal + */ +void QWaylandOutput::handleWindowDestroyed() +{ + Q_D(QWaylandOutput); + d->window = Q_NULLPTR; + emit windowDestroyed(); } + +/*! + * \internal + */ +bool QWaylandOutput::event(QEvent *event) +{ + if (event->type() == QEvent::Polish) + initialize(); + return QObject::event(event); +} + +QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandoutput.h b/src/compositor/compositor_api/qwaylandoutput.h index 9c9dc3767..31e5fa566 100644 --- a/src/compositor/compositor_api/qwaylandoutput.h +++ b/src/compositor/compositor_api/qwaylandoutput.h @@ -4,36 +4,32 @@ ** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB). ** 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$ ** @@ -42,30 +38,33 @@ #ifndef QWAYLANDOUTPUT_H #define QWAYLANDOUTPUT_H -#include <QtCompositor/qwaylandexport.h> +#include <QtWaylandCompositor/qwaylandextension.h> +#include <QtCore/QObject> #include <QObject> #include <QRect> #include <QSize> -QT_BEGIN_NAMESPACE - struct wl_resource; +QT_BEGIN_NAMESPACE + +class QWaylandOutputPrivate; class QWaylandCompositor; class QWindow; class QWaylandSurface; +class QWaylandView; class QWaylandClient; +class QWaylandOutputSpace; -namespace QtWayland { - class Output; -} - -class Q_COMPOSITOR_EXPORT QWaylandOutput : public QObject +class Q_COMPOSITOR_EXPORT QWaylandOutput : public QWaylandObject { Q_OBJECT - Q_PROPERTY(QString manufacturer READ manufacturer CONSTANT) - Q_PROPERTY(QString model READ model CONSTANT) + Q_DECLARE_PRIVATE(QWaylandOutput) + Q_PROPERTY(QWaylandCompositor *compositor READ compositor WRITE setCompositor NOTIFY compositorChanged) + Q_PROPERTY(QWindow *window READ window WRITE setWindow NOTIFY windowChanged) + Q_PROPERTY(QString manufacturer READ manufacturer WRITE setManufacturer NOTIFY manufacturerChanged) + Q_PROPERTY(QString model READ model WRITE setModel NOTIFY modelChanged) Q_PROPERTY(QPoint position READ position WRITE setPosition NOTIFY positionChanged) Q_PROPERTY(QWaylandOutput::Mode mode READ mode WRITE setMode NOTIFY modeChanged) Q_PROPERTY(QRect geometry READ geometry NOTIFY geometryChanged) @@ -74,8 +73,9 @@ class Q_COMPOSITOR_EXPORT QWaylandOutput : public QObject Q_PROPERTY(QWaylandOutput::Subpixel subpixel READ subpixel WRITE setSubpixel NOTIFY subpixelChanged) Q_PROPERTY(QWaylandOutput::Transform transform READ transform WRITE setTransform NOTIFY transformChanged) Q_PROPERTY(int scaleFactor READ scaleFactor WRITE setScaleFactor NOTIFY scaleFactorChanged) - Q_PROPERTY(QWindow *window READ window CONSTANT) + Q_PROPERTY(bool sizeFollowsWindow READ sizeFollowsWindow WRITE setSizeFollowsWindow NOTIFY sizeFollowsWindowChanged) Q_ENUMS(Subpixel Transform) + public: enum Subpixel { SubpixelUnknown = 0, @@ -85,6 +85,7 @@ public: SubpixelVerticalRgb, SubpixelVerticalBgr }; + Q_ENUM(Subpixel) enum Transform { TransformNormal = 0, @@ -96,6 +97,7 @@ public: TransformFlipped180, TransformFlipped270 }; + Q_ENUM(Transform) struct Mode { @@ -103,19 +105,24 @@ public: int refreshRate; }; - QWaylandOutput(QWaylandCompositor *compositor, QWindow *window, - const QString &manufacturer, const QString &model); + QWaylandOutput(); + QWaylandOutput(QWaylandCompositor *compositor, QWindow *window); ~QWaylandOutput(); static QWaylandOutput *fromResource(wl_resource *resource); - - virtual void update(); + struct ::wl_resource *resourceForClient(QWaylandClient *client) const; QWaylandCompositor *compositor() const; + void setCompositor(QWaylandCompositor *compositor); + + QWindow *window() const; + void setWindow(QWindow *window); QString manufacturer() const; + void setManufacturer(const QString &manufacturer); QString model() const; + void setModel(const QString &model); QPoint position() const; void setPosition(const QPoint &pt); @@ -125,6 +132,8 @@ public: QRect geometry() const; void setGeometry(const QRect &geometry); + void setWidth(int newWidth); + void setHeight(int newHeight); QRect availableGeometry() const; void setAvailableGeometry(const QRect &availableGeometry); @@ -141,13 +150,23 @@ public: int scaleFactor() const; void setScaleFactor(int scale); - QWindow *window() const; + bool sizeFollowsWindow() const; + void setSizeFollowsWindow(bool follow); + + bool physicalSizeFollowsSize() const; + void setPhysicalSizeFollowsSize(bool follow); - QtWayland::Output *handle(); + void frameStarted(); + void sendFrameCallbacks(); - QList<QWaylandSurface *> surfaces() const; + void surfaceEnter(QWaylandSurface *surface); + void surfaceLeave(QWaylandSurface *surface); + + virtual void update(); Q_SIGNALS: + void compositorChanged(); + void windowChanged(); void positionChanged(); void geometryChanged(); void modeChanged(); @@ -156,13 +175,23 @@ Q_SIGNALS: void scaleFactorChanged(); void subpixelChanged(); void transformChanged(); + void sizeFollowsWindowChanged(); + void physicalSizeFollowsSizeChanged(); + void manufacturerChanged(); + void modelChanged(); + void windowDestroyed(); -private: - QtWayland::Output *const d_ptr; -}; +private Q_SLOTS: + void handleWindowDestroyed(); -Q_DECLARE_METATYPE(QWaylandOutput::Mode) +protected: + bool event(QEvent *event) Q_DECL_OVERRIDE; + + virtual void initialize(); +}; QT_END_NAMESPACE +Q_DECLARE_METATYPE(QWaylandOutput::Mode) + #endif // QWAYLANDOUTPUT_H diff --git a/src/compositor/compositor_api/qwaylandoutput_p.h b/src/compositor/compositor_api/qwaylandoutput_p.h new file mode 100644 index 000000000..c67e45a7f --- /dev/null +++ b/src/compositor/compositor_api/qwaylandoutput_p.h @@ -0,0 +1,134 @@ +/**************************************************************************** +** +** Copyright (C) 2014-2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> +** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB). +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** 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 QWAYLANDOUTPUT_P_H +#define QWAYLANDOUTPUT_P_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. +// + +#include <QtWaylandCompositor/qwaylandexport.h> +#include <QtWaylandCompositor/QWaylandOutput> +#include <QtWaylandCompositor/QWaylandClient> +#include <QtWaylandCompositor/QWaylandSurface> + +#include <QtWaylandCompositor/private/qwayland-server-wayland.h> + +#include <QtCore/QRect> +#include <QtCore/QVector> + +#include <QtCore/private/qobject_p.h> + +QT_BEGIN_NAMESPACE + +struct QWaylandSurfaceViewMapper +{ + QWaylandSurfaceViewMapper() + : surface(0) + , views() + , has_entered(false) + {} + + QWaylandSurfaceViewMapper(QWaylandSurface *s, QWaylandView *v) + : surface(s) + , views(1, v) + , has_entered(false) + {} + + QWaylandView *maybeThrottelingView() const + { + for (int i = 0; i < views.size(); i++) { + if (surface && surface->throttlingView() == views.at(i)) + return views.at(i); + } + return Q_NULLPTR; + } + + QWaylandSurface *surface; + QVector<QWaylandView *> views; + bool has_entered; +}; + +class Q_COMPOSITOR_EXPORT QWaylandOutputPrivate : public QObjectPrivate, public QtWaylandServer::wl_output +{ +public: + QWaylandOutputPrivate(); + + ~QWaylandOutputPrivate(); + static QWaylandOutputPrivate *get(QWaylandOutput *output) { return output->d_func(); } + + void addView(QWaylandView *view, QWaylandSurface *surface); + void removeView(QWaylandView *view, QWaylandSurface *surface); + void sendGeometryInfo(); + +protected: + void output_bind_resource(Resource *resource) Q_DECL_OVERRIDE; + + +private: + QWaylandCompositor *compositor; + QWindow *window; + QString manufacturer; + QString model; + QPoint position; + QWaylandOutput::Mode mode; + QRect availableGeometry; + QVector<QWaylandSurfaceViewMapper> surfaceViews; + QSize physicalSize; + QWaylandOutput::Subpixel subpixel; + QWaylandOutput::Transform transform; + int scaleFactor; + bool sizeFollowsWindow; + bool initialized; + + Q_DECLARE_PUBLIC(QWaylandOutput) + Q_DISABLE_COPY(QWaylandOutputPrivate) +}; + + +QT_END_NAMESPACE + +#endif /*QWAYLANDOUTPUT_P_H*/ diff --git a/src/compositor/compositor_api/qwaylandpointer.cpp b/src/compositor/compositor_api/qwaylandpointer.cpp new file mode 100644 index 000000000..51b1f791d --- /dev/null +++ b/src/compositor/compositor_api/qwaylandpointer.cpp @@ -0,0 +1,368 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** 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 "qwaylandpointer.h" +#include "qwaylandpointer_p.h" +#include <QtWaylandCompositor/QWaylandClient> +#include <QtWaylandCompositor/QWaylandCompositor> + +QT_BEGIN_NAMESPACE + +QWaylandPointerPrivate::QWaylandPointerPrivate(QWaylandPointer *pointer, QWaylandInputDevice *seat) + : QObjectPrivate() + , wl_pointer() + , seat(seat) + , output() + , focusResource() + , hasSentEnter(false) + , buttonCount() +{ +} + +void QWaylandPointerPrivate::pointer_destroy_resource(wl_pointer::Resource *resource) +{ + if (focusResource == resource->handle) + focusResource = 0; +} + +void QWaylandPointerPrivate::pointer_release(wl_pointer::Resource *resource) +{ + wl_resource_destroy(resource->handle); +} + +void QWaylandPointerPrivate::pointer_set_cursor(wl_pointer::Resource *resource, uint32_t serial, wl_resource *surface, int32_t hotspot_x, int32_t hotspot_y) +{ + Q_UNUSED(resource); + Q_UNUSED(serial); + + if (!surface) { + seat->cursorSurfaceRequest(Q_NULLPTR, 0, 0); + return; + } + + QWaylandSurface *s = QWaylandSurface::fromResource(surface); + s->markAsCursorSurface(true); + seat->cursorSurfaceRequest(s, hotspot_x, hotspot_y); +} + +/*! + * \class QWaylandPointer + * \inmodule QtWaylandCompositor + * \brief The QWaylandPointer class provides access to a pointer device. + * + * This class provides access to the pointer device in a QWaylandInputDevice. It corresponds to + * the Wayland interface wl_pointer. + */ + +/*! + * Constructs a QWaylandPointer for the given \a inputDevice and with the given \a parent. + */ +QWaylandPointer::QWaylandPointer(QWaylandInputDevice *inputDevice, QObject *parent) + : QWaylandObject(* new QWaylandPointerPrivate(this, inputDevice), parent) +{ + connect(&d_func()->focusDestroyListener, &QWaylandDestroyListener::fired, this, &QWaylandPointer::focusDestroyed); + connect(inputDevice, &QWaylandInputDevice::mouseFocusChanged, this, &QWaylandPointer::pointerFocusChanged); +} + +/*! + * Returns the input device for this QWaylandPointer. + */ +QWaylandInputDevice *QWaylandPointer::inputDevice() const +{ + Q_D(const QWaylandPointer); + return d->seat; +} + +/*! + * Returns the compositor for this QWaylandPointer. + */ +QWaylandCompositor *QWaylandPointer::compositor() const +{ + Q_D(const QWaylandPointer); + return d->compositor(); +} + +/*! + * Returns the output for this QWaylandPointer. + */ +QWaylandOutput *QWaylandPointer::output() const +{ + Q_D(const QWaylandPointer); + return d->output; +} + +/*! + * Sets the output for this QWaylandPointer to \a output. + */ +void QWaylandPointer::setOutput(QWaylandOutput *output) +{ + Q_D(QWaylandPointer); + if (d->output == output) return; + d->output = output; + outputChanged(); +} + +/*! + * Sends a mouse press event for \a button to the view currently holding mouse focus. + */ +void QWaylandPointer::sendMousePressEvent(Qt::MouseButton button) +{ + Q_D(QWaylandPointer); + uint32_t time = d->compositor()->currentTimeMsecs(); + d->buttonCount++; + if (d->focusResource) + sendButton(d->focusResource, time, button, WL_POINTER_BUTTON_STATE_PRESSED); + + if (d->buttonCount == 1) { + emit buttonPressedChanged(); + } +} + +/*! + * Sends a mouse release event for \a button to the view currently holding mouse focus. + */ +void QWaylandPointer::sendMouseReleaseEvent(Qt::MouseButton button) +{ + Q_D(QWaylandPointer); + uint32_t time = d->compositor()->currentTimeMsecs(); + d->buttonCount--; + + if (d->focusResource) + sendButton(d->focusResource, time, button, WL_POINTER_BUTTON_STATE_RELEASED); + + if (d->buttonCount == 0) + emit buttonPressedChanged(); +} + +/*! + * Sets the current mouse focus to \a view and sends a mouse move event to it with the + * local position \a localPos and output space position \a outputSpacePos. + */ +void QWaylandPointer::sendMouseMoveEvent(QWaylandView *view, const QPointF &localPos, const QPointF &outputSpacePos) +{ + Q_D(QWaylandPointer); + if (view && (!view->surface() || view->surface()->isCursorSurface())) + view = Q_NULLPTR; + d->seat->setMouseFocus(view); + d->localPosition = localPos; + d->spacePosition = outputSpacePos; + + //we adjust if the mouse position is on the edge + //to work around Qt's event propagation + if (view && view->surface()) { + QSizeF size(view->surface()->size()); + if (d->localPosition.x() == size.width()) + d->localPosition.rx() -= 0.01; + + if (d->localPosition.y() == size.height()) + d->localPosition.ry() -= 0.01; + } + + QWaylandPointerPrivate::Resource *resource = view ? d->resourceMap().value(view->surface()->waylandClient()) : 0; + if (resource && !d->hasSentEnter) { + uint32_t serial = d->compositor()->nextSerial(); + QWaylandKeyboard *keyboard = d->seat->keyboard(); + if (keyboard) { + keyboard->sendKeyModifiers(view->surface()->client(), serial); + } + d->send_enter(resource->handle, serial, view->surface()->resource(), + wl_fixed_from_double(d->localPosition.x()), wl_fixed_from_double(d->localPosition.y())); + + d->focusDestroyListener.listenForDestruction(view->surface()->resource()); + d->hasSentEnter = true; + } + + d->focusResource = resource ? resource->handle : 0; + + if (view && view->output()) + setOutput(view->output()); + + uint32_t time = d->compositor()->currentTimeMsecs(); + + if (d->focusResource) { + wl_fixed_t x = wl_fixed_from_double(currentLocalPosition().x()); + wl_fixed_t y = wl_fixed_from_double(currentLocalPosition().y()); + wl_pointer_send_motion(d->focusResource, time, x, y); + } +} + +/*! + * Sends a mouse wheel event with the given \a orientation and \a delta to the view that currently holds mouse focus. + */ +void QWaylandPointer::sendMouseWheelEvent(Qt::Orientation orientation, int delta) +{ + Q_D(QWaylandPointer); + if (!d->focusResource) + return; + + uint32_t time = d->compositor()->currentTimeMsecs(); + uint32_t axis = orientation == Qt::Horizontal ? WL_POINTER_AXIS_HORIZONTAL_SCROLL + : WL_POINTER_AXIS_VERTICAL_SCROLL; + d->send_axis(d->focusResource, time, axis, wl_fixed_from_int(-delta / 12)); +} + +/*! + * Returns the view that currently holds mouse focus. + */ +QWaylandView *QWaylandPointer::mouseFocus() const +{ + Q_D(const QWaylandPointer); + return d->seat->mouseFocus(); +} + +/*! + * Returns the current local position of the QWaylandPointer. + */ +QPointF QWaylandPointer::currentLocalPosition() const +{ + Q_D(const QWaylandPointer); + return d->localPosition; +} + +/*! + * Returns the current output space position of the QWaylandPointer. + */ +QPointF QWaylandPointer::currentSpacePosition() const +{ + Q_D(const QWaylandPointer); + return d->spacePosition; +} + +/*! + * Returns true if any button is currently pressed. Otherwise returns false. + */ +bool QWaylandPointer::isButtonPressed() const +{ + Q_D(const QWaylandPointer); + return d->buttonCount > 0; +} + +/*! + * \internal + */ +void QWaylandPointer::addClient(QWaylandClient *client, uint32_t id, uint32_t version) +{ + Q_D(QWaylandPointer); + d->add(client->client(), id, qMin<uint32_t>(QtWaylandServer::wl_pointer::interfaceVersion(), version)); +} + +/*! + * Returns the Wayland resource for this QWaylandPointer. + */ +struct wl_resource *QWaylandPointer::focusResource() const +{ + Q_D(const QWaylandPointer); + if (!d->focusResource) + return Q_NULLPTR; + + return d->focusResource; +} + +/*! + * \internal + */ +void QWaylandPointer::sendButton(struct wl_resource *resource, uint32_t time, Qt::MouseButton button, uint32_t state) +{ + Q_D(QWaylandPointer); + uint32_t serial = d->compositor()->nextSerial(); + d->send_button(resource, serial, time, toWaylandButton(button), state); +} + +/*! + * \internal + */ +uint32_t QWaylandPointer::toWaylandButton(Qt::MouseButton button) +{ +#ifndef BTN_LEFT + uint32_t BTN_LEFT = 0x110; +#endif + // the range of valid buttons (evdev module) is from 0x110 + // through 0x11f. 0x120 is the first 'Joystick' button. + switch (button) { + case Qt::LeftButton: return BTN_LEFT; + case Qt::RightButton: return uint32_t(0x111); + case Qt::MiddleButton: return uint32_t(0x112); + case Qt::ExtraButton1: return uint32_t(0x113); // AKA Qt::BackButton, Qt::XButton1 + case Qt::ExtraButton2: return uint32_t(0x114); // AKA Qt::ForwardButton, Qt::XButton2 + case Qt::ExtraButton3: return uint32_t(0x115); + case Qt::ExtraButton4: return uint32_t(0x116); + case Qt::ExtraButton5: return uint32_t(0x117); + case Qt::ExtraButton6: return uint32_t(0x118); + case Qt::ExtraButton7: return uint32_t(0x119); + case Qt::ExtraButton8: return uint32_t(0x11a); + case Qt::ExtraButton9: return uint32_t(0x11b); + case Qt::ExtraButton10: return uint32_t(0x11c); + case Qt::ExtraButton11: return uint32_t(0x11d); + case Qt::ExtraButton12: return uint32_t(0x11e); + case Qt::ExtraButton13: return uint32_t(0x11f); + // default should not occur; but if it does, then return Wayland's highest possible button number. + default: return uint32_t(0x11f); + } +} + +/*! + * \internal + */ +void QWaylandPointer::focusDestroyed(void *data) +{ + Q_D(QWaylandPointer); + Q_UNUSED(data) + d->focusDestroyListener.reset(); + + d->seat->setMouseFocus(Q_NULLPTR); + d->focusResource = 0; + d->buttonCount = 0; +} + +/*! + * \internal + */ +void QWaylandPointer::pointerFocusChanged(QWaylandView *newFocus, QWaylandView *oldFocus) +{ + Q_UNUSED(newFocus); + Q_D(QWaylandPointer); + d->localPosition = QPointF(); + d->hasSentEnter = false; + if (d->focusResource && oldFocus) { + uint32_t serial = d->compositor()->nextSerial(); + d->send_leave(d->focusResource, serial, oldFocus->surfaceResource()); + d->focusDestroyListener.reset(); + d->focusResource = 0; + } + +} + +QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandpointer.h b/src/compositor/compositor_api/qwaylandpointer.h new file mode 100644 index 000000000..78e2b527e --- /dev/null +++ b/src/compositor/compositor_api/qwaylandpointer.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** 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 QWAYLANDPOINTER_H +#define QWAYLANDPOINTER_H + +#include <QtWaylandCompositor/QWaylandExtension> + +QT_BEGIN_NAMESPACE + +class QWaylandPointer; +class QWaylandPointerPrivate; +class QWaylandInputDevice; +class QWaylandView; +class QWaylandOutput; +class QWaylandClient; + +class Q_COMPOSITOR_EXPORT QWaylandPointer : public QWaylandObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QWaylandPointer) + Q_PROPERTY(bool isButtonPressed READ isButtonPressed NOTIFY buttonPressedChanged) +public: + QWaylandPointer(QWaylandInputDevice *inputDevice, QObject *parent = 0); + + QWaylandInputDevice *inputDevice() const; + QWaylandCompositor *compositor() const; + + QWaylandOutput *output() const; + void setOutput(QWaylandOutput *output); + + virtual void sendMousePressEvent(Qt::MouseButton button); + virtual void sendMouseReleaseEvent(Qt::MouseButton button); + virtual void sendMouseMoveEvent(QWaylandView *view, const QPointF &localPos, const QPointF &outputSpacePos); + virtual void sendMouseWheelEvent(Qt::Orientation orientation, int delta); + + QWaylandView *mouseFocus() const; + QPointF currentLocalPosition() const; + QPointF currentSpacePosition() const; + + bool isButtonPressed() const; + + virtual void addClient(QWaylandClient *client, uint32_t id, uint32_t version); + + struct wl_resource *focusResource() const; + + static uint32_t toWaylandButton(Qt::MouseButton button); + void sendButton(struct wl_resource *resource, uint32_t time, Qt::MouseButton button, uint32_t state); +Q_SIGNALS: + void outputChanged(); + void buttonPressedChanged(); + +private: + void focusDestroyed(void *data); + void pointerFocusChanged(QWaylandView *newFocus, QWaylandView *oldFocus); +}; + +QT_END_NAMESPACE + +#endif /*QWAYLANDPOINTER_H*/ diff --git a/src/compositor/compositor_api/qwaylandpointer_p.h b/src/compositor/compositor_api/qwaylandpointer_p.h new file mode 100644 index 000000000..d7a6335a3 --- /dev/null +++ b/src/compositor/compositor_api/qwaylandpointer_p.h @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB). +** 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 QWAYLANDPOINTER_P_H +#define QWAYLANDPOINTER_P_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. +// + +#include <QtWaylandCompositor/qwaylandexport.h> +#include <QtWaylandCompositor/QWaylandDestroyListener> +#include <QtWaylandCompositor/QWaylandPointer> + +#include <QtCore/QList> +#include <QtCore/QPoint> +#include <QtCore/QObject> +#include <QtCore/private/qobject_p.h> + +#include <QtWaylandCompositor/private/qwayland-server-wayland.h> +#include <QtWaylandCompositor/QWaylandView> +#include <QtWaylandCompositor/QWaylandSurface> +#include <QtWaylandCompositor/QWaylandInputDevice> + +#include <stdint.h> + +QT_BEGIN_NAMESPACE + +class QWaylandView; + +class Q_COMPOSITOR_EXPORT QWaylandPointerPrivate : public QObjectPrivate + , public QtWaylandServer::wl_pointer +{ + Q_DECLARE_PUBLIC(QWaylandPointer) +public: + QWaylandPointerPrivate(QWaylandPointer *pointer, QWaylandInputDevice *seat); + + QWaylandCompositor *compositor() const { return seat->compositor(); } + +protected: + void pointer_set_cursor(Resource *resource, uint32_t serial, wl_resource *surface, int32_t hotspot_x, int32_t hotspot_y) Q_DECL_OVERRIDE; + void pointer_release(Resource *resource) Q_DECL_OVERRIDE; + void pointer_destroy_resource(Resource *resource) Q_DECL_OVERRIDE; + +private: + void focusDestroyed(void *data); + + QWaylandInputDevice *seat; + QWaylandOutput *output; + + QPointF localPosition; + QPointF spacePosition; + + struct ::wl_resource *focusResource; + bool hasSentEnter; + + int buttonCount; + + QWaylandDestroyListener focusDestroyListener; +}; + +QT_END_NAMESPACE + +#endif // QWAYLANDPOINTER_P_H diff --git a/src/compositor/compositor_api/qwaylandquickcompositor.cpp b/src/compositor/compositor_api/qwaylandquickcompositor.cpp index db84ea5f8..8a7ef7451 100644 --- a/src/compositor/compositor_api/qwaylandquickcompositor.cpp +++ b/src/compositor/compositor_api/qwaylandquickcompositor.cpp @@ -4,9 +4,9 @@ ** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.com> ** Contact: http://www.qt.io/licensing/ ** -** This file is part of the plugins of the Qt Toolkit. +** This file is part of the QtWaylandCompositor module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $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 @@ -17,74 +17,89 @@ ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** 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. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** 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 <QtCompositor/private/qwlcompositor_p.h> -#include <QtCompositor/private/qwlsurface_p.h> +#include <QtQml/QQmlEngine> #include "qwaylandclient.h" #include "qwaylandquickcompositor.h" #include "qwaylandquicksurface.h" -#include "qwaylandsurfaceitem.h" #include "qwaylandquickoutput.h" +#include "qwaylandquickitem.h" +#include "qwaylandoutput.h" +#include <QtWaylandCompositor/private/qwaylandcompositor_p.h> QT_BEGIN_NAMESPACE -class QWaylandQuickCompositorPrivate : public QtWayland::Compositor +class QWaylandQuickCompositorPrivate : public QWaylandCompositorPrivate { public: - QWaylandQuickCompositorPrivate(QWaylandQuickCompositor *compositor, QWaylandCompositor::ExtensionFlags extensions) - : QtWayland::Compositor(compositor, extensions) + QWaylandQuickCompositorPrivate(QWaylandCompositor *compositor) + : QWaylandCompositorPrivate(compositor) { } - - void compositor_create_surface(wl_compositor::Resource *resource, uint32_t id) Q_DECL_OVERRIDE +protected: + QWaylandSurface *createDefaultSurface() Q_DECL_OVERRIDE { - QWaylandQuickSurface *surface = new QWaylandQuickSurface(resource->client(), id, wl_resource_get_version(resource->handle), static_cast<QWaylandQuickCompositor *>(m_qt_compositor)); - surface->handle()->addToOutput(primaryOutput()->handle()); - m_surfaces << surface->handle(); - //BUG: This may not be an on-screen window surface though - m_qt_compositor->surfaceCreated(surface); + return new QWaylandQuickSurface(); } }; +QWaylandQuickCompositor::QWaylandQuickCompositor(QObject *parent) + : QWaylandCompositor(*new QWaylandQuickCompositorPrivate(this), parent) +{ +} -QWaylandQuickCompositor::QWaylandQuickCompositor(const char *socketName, ExtensionFlags extensions) - : QWaylandCompositor(socketName, new QWaylandQuickCompositorPrivate(this, extensions)) +/*! + * \qmlproperty list QtWaylandCompositor::WaylandCompositor::extensions + * + * A list of extensions that the compositor advertises to its clients. For + * any Wayland extension the compositor should support, instantiate its component, + * and add it to the list of extensions. + * + * For instance, the following code would allow the clients to request shell surfaces + * in the compositor using the wl_shell interface. + * + * \code + * import QtWayland.Compositor 1.0 + * + * WaylandCompositor { + * extensions: [ Shell { + * // ... + * } ] + * } + * \endcode + */ + +void QWaylandQuickCompositor::create() { - qmlRegisterUncreatableType<QWaylandSurfaceItem>("QtCompositor", 1, 0, "WaylandSurfaceItem", QObject::tr("Cannot create instance of WaylandSurfaceItem")); - qmlRegisterUncreatableType<QWaylandQuickSurface>("QtCompositor", 1, 0, "WaylandQuickSurface", QObject::tr("Cannot create instance of WaylandQuickSurface")); - qmlRegisterUncreatableType<QWaylandClient>("QtCompositor", 1, 0, "WaylandClient", QObject::tr("Cannot create instance of WaylandClient")); - qmlRegisterUncreatableType<QWaylandOutput>("QtCompositor", 1, 0, "WaylandOutput", QObject::tr("Cannot create instance of WaylandOutput")); + QWaylandCompositor::create(); } -QWaylandSurfaceView *QWaylandQuickCompositor::createView(QWaylandSurface *surf) + +void QWaylandQuickCompositor::classBegin() { - return new QWaylandSurfaceItem(static_cast<QWaylandQuickSurface *>(surf)); } -QWaylandOutput *QWaylandQuickCompositor::createOutput(QWindow *window, - const QString &manufacturer, - const QString &model) +void QWaylandQuickCompositor::componentComplete() { - QQuickWindow *quickWindow = qobject_cast<QQuickWindow *>(window); - if (!quickWindow) - qFatal("%s: couldn't cast QWindow to QQuickWindow. All output windows must " - "be QQuickWindow derivates when using QWaylandQuickCompositor", Q_FUNC_INFO); - return new QWaylandQuickOutput(this, quickWindow, manufacturer, model); + create(); } QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandquickcompositor.h b/src/compositor/compositor_api/qwaylandquickcompositor.h index e54018901..876508109 100644 --- a/src/compositor/compositor_api/qwaylandquickcompositor.h +++ b/src/compositor/compositor_api/qwaylandquickcompositor.h @@ -3,9 +3,9 @@ ** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.com> ** Contact: http://www.qt.io/licensing/ ** -** This file is part of the plugins of the Qt Toolkit. +** This file is part of the QtWaylandCompositor module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $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 @@ -16,16 +16,19 @@ ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** 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. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** 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$ ** @@ -34,24 +37,26 @@ #ifndef QWAYLANDQUICKCOMPOSITOR_H #define QWAYLANDQUICKCOMPOSITOR_H -#include <QtCompositor/qwaylandcompositor.h> +#include <QtWaylandCompositor/qwaylandcompositor.h> +#include <QtQml/QQmlParserStatus> QT_BEGIN_NAMESPACE class QQuickWindow; class QWaylandQuickCompositorPrivate; -class QWaylandSurfaceView; -class QWaylandOutput; +class QWaylandView; -class Q_COMPOSITOR_EXPORT QWaylandQuickCompositor : public QWaylandCompositor +class Q_COMPOSITOR_EXPORT QWaylandQuickCompositor : public QWaylandCompositor, public QQmlParserStatus { + Q_INTERFACES(QQmlParserStatus) + Q_OBJECT public: - QWaylandQuickCompositor(const char *socketName = 0, QWaylandCompositor::ExtensionFlags extensions = DefaultExtensions); + QWaylandQuickCompositor(QObject *parent = 0); + void create() Q_DECL_OVERRIDE; - QWaylandSurfaceView *createView(QWaylandSurface *surf) Q_DECL_OVERRIDE; - QWaylandOutput *createOutput(QWindow *window, - const QString &manufacturer, - const QString &model) Q_DECL_OVERRIDE; +protected: + void classBegin() Q_DECL_OVERRIDE; + void componentComplete() Q_DECL_OVERRIDE; }; QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandquickitem.cpp b/src/compositor/compositor_api/qwaylandquickitem.cpp new file mode 100644 index 000000000..f684f64c5 --- /dev/null +++ b/src/compositor/compositor_api/qwaylandquickitem.cpp @@ -0,0 +1,775 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** 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 "qwaylandquickitem.h" +#include "qwaylandquickitem_p.h" +#include "qwaylandquicksurface.h" +#include <QtWaylandCompositor/qwaylandcompositor.h> +#include <QtWaylandCompositor/qwaylandinput.h> +#include <QtWaylandCompositor/qwaylandbufferref.h> +#include <QtWaylandCompositor/private/qwlclientbufferintegration_p.h> + +#include <QtGui/QKeyEvent> +#include <QtGui/QGuiApplication> +#include <QtGui/QScreen> + +#include <QtQuick/QSGSimpleTextureNode> +#include <QtQuick/QQuickWindow> + +#include <QtCore/QMutexLocker> +#include <QtCore/QMutex> + +#include <wayland-server.h> +#include <QThread> +QT_BEGIN_NAMESPACE + +QMutex *QWaylandQuickItemPrivate::mutex = 0; + +class QWaylandSurfaceTextureProvider : public QSGTextureProvider +{ +public: + QWaylandSurfaceTextureProvider() + : m_smooth(false) + , m_sgTex(0) + { + } + + ~QWaylandSurfaceTextureProvider() + { + if (m_sgTex) + m_sgTex->deleteLater(); + } + + void setBufferRef(QWaylandQuickItem *surfaceItem, const QWaylandBufferRef &buffer) + { + Q_ASSERT(QThread::currentThread() == thread()); + m_ref = buffer; + delete m_sgTex; + m_sgTex = 0; + if (m_ref.hasBuffer()) { + if (buffer.isShm()) { + m_sgTex = surfaceItem->window()->createTextureFromImage(buffer.image()); + m_invertY = false; + if (m_sgTex) { + m_sgTex->bind(); + } + } else { + QQuickWindow::CreateTextureOptions opt = QQuickWindow::TextureOwnsGLTexture; + QWaylandQuickSurface *surface = qobject_cast<QWaylandQuickSurface *>(surfaceItem->surface()); + if (surface && surface->useTextureAlpha()) { + opt |= QQuickWindow::TextureHasAlphaChannel; + } + + GLuint texture; + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + buffer.bindToTexture(); + m_sgTex = surfaceItem->window()->createTextureFromId(texture , QSize(surfaceItem->width(), surfaceItem->height()), opt); + m_invertY = buffer.origin() == QWaylandSurface::OriginBottomLeft; + } + } + emit textureChanged(); + } + + QSGTexture *texture() const Q_DECL_OVERRIDE + { + if (m_sgTex) + m_sgTex->setFiltering(m_smooth ? QSGTexture::Linear : QSGTexture::Nearest); + return m_sgTex; + } + + void setSmooth(bool smooth) { m_smooth = smooth; } + bool invertY() const { return m_invertY; } +private: + bool m_smooth; + bool m_invertY; + QSGTexture *m_sgTex; + QWaylandBufferRef m_ref; +}; + +/*! + * \qmltype WaylandQuickItem + * \inqmlmodule QtWayland.Compositor + * \brief A Qt Quick item representing a WaylandView. + * + * When writing a WaylandCompositor in Qt Quick, this type can be used to display a + * client's contents on an output device and will pass user input to the + * client. + */ + +/*! + * \class QWaylandQuickItem + * \inmodule QtWaylandCompositor + * \brief A Qt Quick item representing a QWaylandView. + * + * When writing a QWaylandCompositor in Qt Quick, this class can be used to display a + * client's contents on an output device and will pass user input to the + * client. + */ + +/*! + * Constructs a QWaylandQuickItem with the given \a parent. + */ +QWaylandQuickItem::QWaylandQuickItem(QQuickItem *parent) + : QQuickItem(*new QWaylandQuickItemPrivate(), parent) +{ + d_func()->init(); +} + +/*! + * \internal + */ +QWaylandQuickItem::QWaylandQuickItem(QWaylandQuickItemPrivate &dd, QQuickItem *parent) + : QQuickItem(dd, parent) +{ + d_func()->init(); +} + +/*! + * Destroy the QWaylandQuickItem. + */ +QWaylandQuickItem::~QWaylandQuickItem() +{ + Q_D(QWaylandQuickItem); + disconnect(this, &QQuickItem::windowChanged, this, &QWaylandQuickItem::updateWindow); + QMutexLocker locker(d->mutex); + if (d->provider) + d->provider->deleteLater(); +} + +/*! + * \qmlproperty object QtWaylandCompositor::WaylandQuickItem::compositor + * + * This property holds the compositor for the surface rendered by this WaylandQuickItem. + */ + +/*! + * \property QWaylandQuickItem::compositor + * + * This property holds the compositor for the surface rendered by this QWaylandQuickItem. + */ +QWaylandCompositor *QWaylandQuickItem::compositor() const +{ + Q_D(const QWaylandQuickItem); + return d->view->surface() ? d->view->surface()->compositor() : Q_NULLPTR; +} + +/*! + * \qmlproperty object QWaylandQuickItem::view + * + * This property holds the view rendered by this WaylandQuickItem. + */ + +/*! + * \property QWaylandQuickItem::view + * + * This property holds the view rendered by this QWaylandQuickItem. + */ +QWaylandView *QWaylandQuickItem::view() const +{ + Q_D(const QWaylandQuickItem); + return d->view.data(); +} + +/*! + * \qmlproperty object QWaylandQuickItem::surface + * + * This property holds the surface rendered by this WaylandQuickItem. + */ + +/*! + * \property QWaylandQuickItem::surface + * + * This property holds the surface rendered by this QWaylandQuickItem. + */ + +QWaylandSurface *QWaylandQuickItem::surface() const +{ + Q_D(const QWaylandQuickItem); + return d->view->surface(); +} + +void QWaylandQuickItem::setSurface(QWaylandSurface *surface) +{ + Q_D(QWaylandQuickItem); + d->view->setSurface(surface); + update(); +} + +/*! + * \qmlproperty enum QtWaylandCompositor::WaylandQuickItem::origin + * + * This property holds the origin of the QWaylandQuickItem. + */ + +/*! + * \property QWaylandQuickItem::origin + * + * This property holds the origin of the QWaylandQuickItem. + */ +QWaylandSurface::Origin QWaylandQuickItem::origin() const +{ + Q_D(const QWaylandQuickItem); + return d->origin; +} + +/*! + * Returns the texture provider of this QWaylandQuickItem. + */ +QSGTextureProvider *QWaylandQuickItem::textureProvider() const +{ + Q_D(const QWaylandQuickItem); + return d->provider; +} + +/*! + * \internal + */ +void QWaylandQuickItem::mousePressEvent(QMouseEvent *event) +{ + Q_D(QWaylandQuickItem); + if (!d->shouldSendInputEvents()) { + event->ignore(); + return; + } + + if (!inputRegionContains(event->pos())) { + event->ignore(); + return; + } + + QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event); + + if (d->focusOnClick) + takeFocus(inputDevice); + + inputDevice->sendMousePressEvent(event->button()); +} + +/*! + * \internal + */ +void QWaylandQuickItem::mouseMoveEvent(QMouseEvent *event) +{ + Q_D(QWaylandQuickItem); + if (d->shouldSendInputEvents()) { + QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event); + inputDevice->sendMouseMoveEvent(d->view.data(), event->localPos(), event->windowPos()); + } else { + emit mouseMove(event->windowPos()); + event->ignore(); + } +} + +/*! + * \internal + */ +void QWaylandQuickItem::mouseReleaseEvent(QMouseEvent *event) +{ + Q_D(QWaylandQuickItem); + if (d->shouldSendInputEvents()) { + QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event); + inputDevice->sendMouseReleaseEvent(event->button()); + } else { + emit mouseRelease(); + event->ignore(); + } +} + +/*! + * \internal + */ +void QWaylandQuickItem::hoverEnterEvent(QHoverEvent *event) +{ + Q_D(QWaylandQuickItem); + if (!inputRegionContains(event->pos())) { + event->ignore(); + return; + } + if (d->shouldSendInputEvents()) { + QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event); + inputDevice->sendMouseMoveEvent(d->view.data(), event->pos(), mapToScene(event->pos())); + } else { + event->ignore(); + } +} + +/*! + * \internal + */ +void QWaylandQuickItem::hoverMoveEvent(QHoverEvent *event) +{ + Q_D(QWaylandQuickItem); + if (surface()) { + if (!inputRegionContains(event->pos())) { + event->ignore(); + return; + } + } + if (d->shouldSendInputEvents()) { + QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event); + inputDevice->sendMouseMoveEvent(d->view.data(), event->pos(), mapToScene(event->pos())); + } else { + event->ignore(); + } +} + +/*! + * \internal + */ +void QWaylandQuickItem::hoverLeaveEvent(QHoverEvent *event) +{ + Q_D(QWaylandQuickItem); + if (d->shouldSendInputEvents()) { + QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event); + inputDevice->setMouseFocus(Q_NULLPTR); + } else { + event->ignore(); + } +} + +/*! + * \internal + */ +void QWaylandQuickItem::wheelEvent(QWheelEvent *event) +{ + Q_D(QWaylandQuickItem); + if (d->shouldSendInputEvents()) { + if (!inputRegionContains(event->pos())) { + event->ignore(); + return; + } + + QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event); + inputDevice->sendMouseWheelEvent(event->orientation(), event->delta()); + } else { + event->ignore(); + } +} + +/*! + * \internal + */ +void QWaylandQuickItem::keyPressEvent(QKeyEvent *event) +{ + Q_D(QWaylandQuickItem); + if (d->shouldSendInputEvents()) { + QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event); + inputDevice->sendFullKeyEvent(event); + } else { + event->ignore(); + } +} + +/*! + * \internal + */ +void QWaylandQuickItem::keyReleaseEvent(QKeyEvent *event) +{ + Q_D(QWaylandQuickItem); + if (d->shouldSendInputEvents() && hasFocus()) { + QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event); + inputDevice->sendFullKeyEvent(event); + } else { + event->ignore(); + } +} + +/*! + * \internal + */ +void QWaylandQuickItem::touchEvent(QTouchEvent *event) +{ + Q_D(QWaylandQuickItem); + if (d->shouldSendInputEvents() && d->touchEventsEnabled) { + QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event); + + if (event->type() == QEvent::TouchBegin) { + QQuickItem *grabber = window()->mouseGrabberItem(); + if (grabber != this) + grabMouse(); + } + + QPoint pointPos; + const QList<QTouchEvent::TouchPoint> &points = event->touchPoints(); + if (!points.isEmpty()) + pointPos = points.at(0).pos().toPoint(); + + if (event->type() == QEvent::TouchBegin && !inputRegionContains(pointPos)) { + event->ignore(); + return; + } + + event->accept(); + if (inputDevice->mouseFocus() != d->view.data()) { + inputDevice->sendMouseMoveEvent(d->view.data(), pointPos, mapToScene(pointPos)); + } + inputDevice->sendFullTouchEvent(event); + } else { + event->ignore(); + } +} + +/*! + * \internal + */ +void QWaylandQuickItem::mouseUngrabEvent() +{ + if (surface()) { + QTouchEvent e(QEvent::TouchCancel); + touchEvent(&e); + } +} + +/*! + * \internal + */ +void QWaylandQuickItem::surfaceChangedEvent(QWaylandSurface *newSurface, QWaylandSurface *oldSurface) +{ + Q_UNUSED(newSurface); + Q_UNUSED(oldSurface); +} + +/*! + * \internal + */ +void QWaylandQuickItem::handleSurfaceChanged() +{ + Q_D(QWaylandQuickItem); + if (d->oldSurface) { + disconnect(d->oldSurface, &QWaylandSurface::mappedChanged, this, &QWaylandQuickItem::surfaceMappedChanged); + disconnect(d->oldSurface, &QWaylandSurface::parentChanged, this, &QWaylandQuickItem::parentChanged); + disconnect(d->oldSurface, &QWaylandSurface::sizeChanged, this, &QWaylandQuickItem::updateSize); + disconnect(d->oldSurface, &QWaylandSurface::configure, this, &QWaylandQuickItem::updateBuffer); + disconnect(d->oldSurface, &QWaylandSurface::redraw, this, &QQuickItem::update); + } + if (QWaylandSurface *newSurface = d->view->surface()) { + connect(newSurface, &QWaylandSurface::mappedChanged, this, &QWaylandQuickItem::surfaceMappedChanged); + connect(newSurface, &QWaylandSurface::parentChanged, this, &QWaylandQuickItem::parentChanged); + connect(newSurface, &QWaylandSurface::sizeChanged, this, &QWaylandQuickItem::updateSize); + connect(newSurface, &QWaylandSurface::configure, this, &QWaylandQuickItem::updateBuffer); + connect(newSurface, &QWaylandSurface::redraw, this, &QQuickItem::update); + if (d->sizeFollowsSurface) { + setWidth(newSurface->size().width()); + setHeight(newSurface->size().height()); + } + if (newSurface->origin() != d->origin) { + d->origin = newSurface->origin(); + emit originChanged(); + } + if (window()) { + QWaylandOutput *output = newSurface->compositor()->outputFor(window()); + d->view->setOutput(output); + } + } + surfaceChangedEvent(d->view->surface(), d->oldSurface); + d->oldSurface = d->view->surface(); +} + +/*! + * Calling this function causes the item to take the focus of the + * input \a device. + */ +void QWaylandQuickItem::takeFocus(QWaylandInputDevice *device) +{ + setFocus(true); + + if (!surface()) + return; + + QWaylandInputDevice *target = device; + if (!target) { + target = compositor()->defaultInputDevice(); + } + target->setKeyboardFocus(surface()); +} + +/*! + * \internal + */ +void QWaylandQuickItem::surfaceMappedChanged() +{ + update(); +} + +/*! + * \internal + */ +void QWaylandQuickItem::parentChanged(QWaylandSurface *newParent, QWaylandSurface *oldParent) +{ + Q_UNUSED(oldParent); + + if (newParent) { + setPaintEnabled(true); + setVisible(true); + setOpacity(1); + setEnabled(true); + } +} + +/*! + * \internal + */ +void QWaylandQuickItem::updateSize() +{ + Q_D(QWaylandQuickItem); + if (d->sizeFollowsSurface && surface()) { + setSize(surface()->size()); + } +} + +/*! + * \qmlproperty bool QtWaylandCompositor::WaylandQuickItem::focusOnClick + * + * This property specifies whether the WaylandQuickItem should take focus when + * it is clicked. + * + * The default is true. + */ + +/*! + * \property QWaylandQuickItem::focusOnClick + * + * This property specifies whether the QWaylandQuickItem should take focus when + * it is clicked. + * + * The default is true. + */ +bool QWaylandQuickItem::focusOnClick() const +{ + Q_D(const QWaylandQuickItem); + return d->focusOnClick; +} + +void QWaylandQuickItem::setFocusOnClick(bool focus) +{ + Q_D(QWaylandQuickItem); + if (d->focusOnClick == focus) + return; + + d->focusOnClick = focus; + emit focusOnClickChanged(); +} + +/*! + * Returns true if the input region of this item's surface contains the + * position given by \a localPosition. + */ +bool QWaylandQuickItem::inputRegionContains(const QPointF &localPosition) +{ + if (QWaylandSurface *s = surface()) + return s->inputRegionContains(localPosition.toPoint()); + return false; +} + +/*! + * \qmlproperty bool QtWaylandCompositor::WaylandQuickItem::sizeFollowsSurface + * + * This property specifies whether the size of the item should always match + * the size of its surface. + * + * The default is true. + */ + +/*! + * \property QWaylandQuickItem::sizeFollowsSurface + * + * This property specifies whether the size of the item should always match + * the size of its surface. + * + * The default is true. + */ +bool QWaylandQuickItem::sizeFollowsSurface() const +{ + Q_D(const QWaylandQuickItem); + return d->sizeFollowsSurface; +} + +void QWaylandQuickItem::setSizeFollowsSurface(bool sizeFollowsSurface) +{ + Q_D(QWaylandQuickItem); + if (d->sizeFollowsSurface == sizeFollowsSurface) + return; + d->sizeFollowsSurface = sizeFollowsSurface; + emit sizeFollowsSurfaceChanged(); +} + +/*! + \qmlproperty bool QtWayland::QWaylandSurfaceItem::paintEnabled + + If this property is true, the \l item is hidden, though the texture + will still be updated. As opposed to hiding the \l item by + setting \l{Item::visible}{visible} to false, setting this property to true + will not prevent mouse or keyboard input from reaching \l item. +*/ +bool QWaylandQuickItem::paintEnabled() const +{ + Q_D(const QWaylandQuickItem); + return d->paintEnabled; +} + +void QWaylandQuickItem::setPaintEnabled(bool enabled) +{ + Q_D(QWaylandQuickItem); + d->paintEnabled = enabled; + update(); +} + +bool QWaylandQuickItem::touchEventsEnabled() const +{ + Q_D(const QWaylandQuickItem); + return d->touchEventsEnabled; +} + +void QWaylandQuickItem::updateBuffer(bool hasBuffer) +{ + Q_D(QWaylandQuickItem); + Q_UNUSED(hasBuffer); + if (d->origin != surface()->origin()) { + d->origin = surface()->origin(); + emit originChanged(); + } +} + +void QWaylandQuickItem::updateWindow() +{ + Q_D(QWaylandQuickItem); + if (d->connectedWindow) { + disconnect(d->connectedWindow, &QQuickWindow::beforeSynchronizing, this, &QWaylandQuickItem::beforeSync); + } + + d->connectedWindow = window(); + + if (d->connectedWindow) { + connect(d->connectedWindow, &QQuickWindow::beforeSynchronizing, this, &QWaylandQuickItem::beforeSync, Qt::DirectConnection); + } + + if (compositor() && d->connectedWindow) { + QWaylandOutput *output = compositor()->outputFor(d->connectedWindow); + Q_ASSERT(output); + d->view->setOutput(output); + } +} + +void QWaylandQuickItem::beforeSync() +{ + Q_D(QWaylandQuickItem); + if (d->view->advance()) { + d->newTexture = true; + update(); + } +} + +QSGNode *QWaylandQuickItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) +{ + Q_D(QWaylandQuickItem); + bool mapped = (surface() && surface()->isMapped() && d->view->currentBuffer().hasBuffer()) + || (d->view->isBufferLocked() && d->provider); + + if (!mapped || !d->paintEnabled) { + delete oldNode; + return 0; + } + + QSGSimpleTextureNode *node = static_cast<QSGSimpleTextureNode *>(oldNode); + + if (!node) + node = new QSGSimpleTextureNode(); + + if (!d->provider) + d->provider = new QWaylandSurfaceTextureProvider(); + + if (d->newTexture) { + d->newTexture = false; + d->provider->setBufferRef(this, d->view->currentBuffer()); + node->setTexture(d->provider->texture()); + } + + d->provider->setSmooth(smooth()); + + if (d->provider->invertY()) { + node->setRect(0, height(), width(), -height()); + } else { + node->setRect(0, 0, width(), height()); + } + + return node; +} + +void QWaylandQuickItem::setTouchEventsEnabled(bool enabled) +{ + Q_D(QWaylandQuickItem); + if (d->touchEventsEnabled != enabled) { + d->touchEventsEnabled = enabled; + emit touchEventsEnabledChanged(); + } +} + +bool QWaylandQuickItem::inputEventsEnabled() const +{ + Q_D(const QWaylandQuickItem); + return d->inputEventsEnabled; +} + +void QWaylandQuickItem::setInputEventsEnabled(bool enabled) +{ + Q_D(QWaylandQuickItem); + if (d->inputEventsEnabled != enabled) { + d->inputEventsEnabled = enabled; + setAcceptHoverEvents(enabled); + emit inputEventsEnabledChanged(); + } +} + +void QWaylandQuickItem::lower() +{ + QQuickItem *parent = parentItem(); + Q_ASSERT(parent); + QQuickItem *bottom = parent->childItems().first(); + if (this != bottom) + stackBefore(bottom); +} + +void QWaylandQuickItem::raise() +{ + QQuickItem *parent = parentItem(); + Q_ASSERT(parent); + QQuickItem *top = parent->childItems().last(); + if (this != top) + stackAfter(top); +} + +QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandquickitem.h b/src/compositor/compositor_api/qwaylandquickitem.h new file mode 100644 index 000000000..41f1d533e --- /dev/null +++ b/src/compositor/compositor_api/qwaylandquickitem.h @@ -0,0 +1,152 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** 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 QWAYLANDSURFACEITEM_H +#define QWAYLANDSURFACEITEM_H + +#include <QtWaylandCompositor/qwaylandexport.h> + +#include <QtQuick/QQuickItem> +#include <QtQuick/qsgtexture.h> + +#include <QtQuick/qsgtextureprovider.h> + +#include <QtWaylandCompositor/qwaylandview.h> +#include <QtWaylandCompositor/qwaylandquicksurface.h> + +Q_DECLARE_METATYPE(QWaylandQuickSurface*) + +QT_BEGIN_NAMESPACE + +class QWaylandInputDevice; +class QWaylandQuickItemPrivate; + +class Q_COMPOSITOR_EXPORT QWaylandQuickItem : public QQuickItem +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QWaylandQuickItem) + Q_PROPERTY(QWaylandView *view READ view CONSTANT) + Q_PROPERTY(QWaylandCompositor *compositor READ compositor) + Q_PROPERTY(QWaylandSurface *surface READ surface WRITE setSurface NOTIFY surfaceChanged) + Q_PROPERTY(bool paintEnabled READ paintEnabled WRITE setPaintEnabled) + Q_PROPERTY(bool touchEventsEnabled READ touchEventsEnabled WRITE setTouchEventsEnabled NOTIFY touchEventsEnabledChanged) + Q_PROPERTY(QWaylandSurface::Origin origin READ origin NOTIFY originChanged) + Q_PROPERTY(bool inputEventsEnabled READ inputEventsEnabled WRITE setInputEventsEnabled NOTIFY inputEventsEnabledChanged) + Q_PROPERTY(bool focusOnClick READ focusOnClick WRITE setFocusOnClick NOTIFY focusOnClickChanged) + Q_PROPERTY(bool sizeFollowsSurface READ sizeFollowsSurface WRITE setSizeFollowsSurface NOTIFY sizeFollowsSurfaceChanged) + +public: + QWaylandQuickItem(QQuickItem *parent = 0); + ~QWaylandQuickItem(); + + QWaylandCompositor *compositor() const; + QWaylandView *view() const; + + QWaylandSurface *surface() const; + void setSurface(QWaylandSurface *surface); + + QWaylandSurface::Origin origin() const; + + bool isTextureProvider() const { return true; } + QSGTextureProvider *textureProvider() const; + + bool paintEnabled() const; + bool touchEventsEnabled() const; + + void setTouchEventsEnabled(bool enabled); + + bool inputEventsEnabled() const; + void setInputEventsEnabled(bool enabled); + + bool focusOnClick() const; + void setFocusOnClick(bool focus); + + bool inputRegionContains(const QPointF &localPosition); + + bool sizeFollowsSurface() const; + void setSizeFollowsSurface(bool sizeFollowsSurface); + +protected: + void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE; + void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE; + void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE; + void hoverEnterEvent(QHoverEvent *event) Q_DECL_OVERRIDE; + void hoverMoveEvent(QHoverEvent *event) Q_DECL_OVERRIDE; + void hoverLeaveEvent(QHoverEvent *event) Q_DECL_OVERRIDE; + void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE; + + void keyPressEvent(QKeyEvent *event) Q_DECL_OVERRIDE; + void keyReleaseEvent(QKeyEvent *event) Q_DECL_OVERRIDE; + + void touchEvent(QTouchEvent *event) Q_DECL_OVERRIDE; + void mouseUngrabEvent() Q_DECL_OVERRIDE; + + virtual void surfaceChangedEvent(QWaylandSurface *newSurface, QWaylandSurface *oldSurface); +public Q_SLOTS: + virtual void takeFocus(QWaylandInputDevice *device = 0); + void setPaintEnabled(bool paintEnabled); + void raise(); + void lower(); + +private Q_SLOTS: + void surfaceMappedChanged(); + void handleSurfaceChanged(); + void parentChanged(QWaylandSurface *newParent, QWaylandSurface *oldParent); + void updateSize(); + void updateBuffer(bool hasBuffer); + void updateWindow(); + void beforeSync(); + +Q_SIGNALS: + void surfaceChanged(); + void touchEventsEnabledChanged(); + void originChanged(); + void surfaceDestroyed(); + void inputEventsEnabledChanged(); + void focusOnClickChanged(); + void mouseMove(const QPointF &windowPosition); + void mouseRelease(); + void sizeFollowsSurfaceChanged(); + +protected: + QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) Q_DECL_OVERRIDE; + + QWaylandQuickItem(QWaylandQuickItemPrivate &dd, QQuickItem *parent = 0); +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/compositor/compositor_api/qwaylandquickitem_p.h b/src/compositor/compositor_api/qwaylandquickitem_p.h new file mode 100644 index 000000000..2a5686f33 --- /dev/null +++ b/src/compositor/compositor_api/qwaylandquickitem_p.h @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** 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 QWAYLANDQUICKITEM_P_H +#define QWAYLANDQUICKITEM_P_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. +// + +#include <QtQuick/private/qquickitem_p.h> + +#include "qwaylandquickitem.h" + +QT_BEGIN_NAMESPACE + +class QWaylandSurfaceTextureProvider; +class QMutex; + +class QWaylandQuickItemPrivate : public QQuickItemPrivate +{ + Q_DECLARE_PUBLIC(QWaylandQuickItem) +public: + QWaylandQuickItemPrivate() + : QQuickItemPrivate() + , view(Q_NULLPTR) + , oldSurface(Q_NULLPTR) + , provider(Q_NULLPTR) + , paintEnabled(true) + , touchEventsEnabled(false) + , inputEventsEnabled(true) + , newTexture(false) + , focusOnClick(true) + , sizeFollowsSurface(true) + , connectedWindow(Q_NULLPTR) + , origin(QWaylandSurface::OriginTopLeft) + { + } + + void init() + { + Q_Q(QWaylandQuickItem); + if (!mutex) + mutex = new QMutex; + + view.reset(new QWaylandView(q)); + q->setFlag(QQuickItem::ItemHasContents); + + q->update(); + + q->setSmooth(true); + + q->setAcceptedMouseButtons(Qt::LeftButton | Qt::MiddleButton | Qt::RightButton | + Qt::ExtraButton1 | Qt::ExtraButton2 | Qt::ExtraButton3 | Qt::ExtraButton4 | + Qt::ExtraButton5 | Qt::ExtraButton6 | Qt::ExtraButton7 | Qt::ExtraButton8 | + Qt::ExtraButton9 | Qt::ExtraButton10 | Qt::ExtraButton11 | + Qt::ExtraButton12 | Qt::ExtraButton13); + q->setAcceptHoverEvents(true); + + QObject::connect(q, &QQuickItem::windowChanged, q, &QWaylandQuickItem::updateWindow); + QObject::connect(view.data(), &QWaylandView::surfaceChanged, q, &QWaylandQuickItem::surfaceChanged); + QObject::connect(view.data(), &QWaylandView::surfaceChanged, q, &QWaylandQuickItem::handleSurfaceChanged); + QObject::connect(view.data(), &QWaylandView::surfaceDestroyed, q, &QWaylandQuickItem::surfaceDestroyed); + } + + bool shouldSendInputEvents() const { return view->surface() && inputEventsEnabled; } + + static QMutex *mutex; + + QScopedPointer<QWaylandView> view; + QWaylandSurface *oldSurface; + mutable QWaylandSurfaceTextureProvider *provider; + bool paintEnabled; + bool touchEventsEnabled; + bool inputEventsEnabled; + bool newTexture; + bool focusOnClick; + bool sizeFollowsSurface; + + QQuickWindow *connectedWindow; + QWaylandSurface::Origin origin; +}; + +QT_END_NAMESPACE + +#endif /*QWAYLANDQUICKITEM_P_H*/ diff --git a/src/compositor/compositor_api/qwaylandquickoutput.cpp b/src/compositor/compositor_api/qwaylandquickoutput.cpp index 9199ff84a..8abf6cbb1 100644 --- a/src/compositor/compositor_api/qwaylandquickoutput.cpp +++ b/src/compositor/compositor_api/qwaylandquickoutput.cpp @@ -4,9 +4,9 @@ ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** -** This file is part of the plugins of the Qt Toolkit. +** This file is part of the QtWaylandCompositor module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $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 @@ -17,16 +17,19 @@ ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** 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. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** 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$ ** @@ -37,34 +40,84 @@ QT_BEGIN_NAMESPACE -QWaylandQuickOutput::QWaylandQuickOutput(QWaylandCompositor *compositor, QQuickWindow *window, - const QString &manufacturer, const QString &model) - : QWaylandOutput(compositor, window, manufacturer, model) +QWaylandQuickOutput::QWaylandQuickOutput() + : QWaylandOutput() , m_updateScheduled(false) + , m_automaticFrameCallback(true) +{ +} + +QWaylandQuickOutput::QWaylandQuickOutput(QWaylandCompositor *compositor, QWindow *window) + : QWaylandOutput(compositor, window) + , m_updateScheduled(false) + , m_automaticFrameCallback(true) { - connect(window, &QQuickWindow::beforeSynchronizing, - this, &QWaylandQuickOutput::updateStarted, - Qt::DirectConnection); } -QQuickWindow *QWaylandQuickOutput::quickWindow() const +void QWaylandQuickOutput::initialize() { - return static_cast<QQuickWindow *>(window()); + QWaylandOutput::initialize(); + + QQuickWindow *quickWindow = qobject_cast<QQuickWindow *>(window()); + if (!quickWindow) { + qWarning("Initialization error: Could not locate QQuickWindow on initializing QWaylandQuickOutput %p.\n", this); + return; + } + connect(quickWindow, &QQuickWindow::beforeSynchronizing, + this, &QWaylandQuickOutput::updateStarted, + Qt::DirectConnection); + + connect(quickWindow, &QQuickWindow::beforeRendering, + this, &QWaylandQuickOutput::doFrameCallbacks); } void QWaylandQuickOutput::update() { if (!m_updateScheduled) { - quickWindow()->update(); + //don't qobject_cast since we have verified the type in initialize + static_cast<QQuickWindow *>(window())->update(); m_updateScheduled = true; } } +/*! + * \qmlproperty bool QtWaylandCompositor::WaylandOutput::automaticFrameCallback + * + * This property holds whether the WaylandOutput automatically sends frame + * callbacks when rendering. + * + * The default is true. + */ +bool QWaylandQuickOutput::automaticFrameCallback() const +{ + return m_automaticFrameCallback; +} + +void QWaylandQuickOutput::setAutomaticFrameCallback(bool automatic) +{ + if (m_automaticFrameCallback == automatic) + return; + + m_automaticFrameCallback = automatic; + automaticFrameCallbackChanged(); +} + +/*! + * \internal + */ void QWaylandQuickOutput::updateStarted() { m_updateScheduled = false; - compositor()->frameStarted(); - compositor()->cleanupGraphicsResources(); + + if (!compositor()) + return; + + frameStarted(); } +void QWaylandQuickOutput::doFrameCallbacks() +{ + if (m_automaticFrameCallback) + sendFrameCallbacks(); +} QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandquickoutput.h b/src/compositor/compositor_api/qwaylandquickoutput.h index 702867104..48f478456 100644 --- a/src/compositor/compositor_api/qwaylandquickoutput.h +++ b/src/compositor/compositor_api/qwaylandquickoutput.h @@ -4,9 +4,9 @@ ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** -** This file is part of the plugins of the Qt Toolkit. +** This file is part of the QtWaylandCompositor module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $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 @@ -17,16 +17,19 @@ ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** 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. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** 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$ ** @@ -36,7 +39,7 @@ #define QWAYLANDQUICKOUTPUT_H #include <QtQuick/QQuickWindow> -#include <QtCompositor/qwaylandoutput.h> +#include <QtWaylandCompositor/qwaylandoutput.h> QT_BEGIN_NAMESPACE @@ -46,19 +49,30 @@ class QQuickWindow; class Q_COMPOSITOR_EXPORT QWaylandQuickOutput : public QWaylandOutput { Q_OBJECT + Q_PROPERTY(bool automaticFrameCallback READ automaticFrameCallback WRITE setAutomaticFrameCallback NOTIFY automaticFrameCallbackChanged) public: - QWaylandQuickOutput(QWaylandCompositor *compositor, QQuickWindow *window, - const QString &manufacturer, const QString &model); - - QQuickWindow *quickWindow() const; + QWaylandQuickOutput(); + QWaylandQuickOutput(QWaylandCompositor *compositor, QWindow *window); void update() Q_DECL_OVERRIDE; + bool automaticFrameCallback() const; + void setAutomaticFrameCallback(bool automatic); + public Q_SLOTS: void updateStarted(); +Q_SIGNALS: + void automaticFrameCallbackChanged(); + +protected: + void initialize() Q_DECL_OVERRIDE; + private: + void doFrameCallbacks(); + bool m_updateScheduled; + bool m_automaticFrameCallback; }; QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandquicksurface.cpp b/src/compositor/compositor_api/qwaylandquicksurface.cpp index 3d52b8624..0fc07c6c5 100644 --- a/src/compositor/compositor_api/qwaylandquicksurface.cpp +++ b/src/compositor/compositor_api/qwaylandquicksurface.cpp @@ -3,9 +3,9 @@ ** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.com> ** Contact: http://www.qt.io/licensing/ ** -** This file is part of the plugins of the Qt Toolkit. +** This file is part of the QtWaylandCompositor module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $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 @@ -16,16 +16,19 @@ ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** 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. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** 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$ ** @@ -35,75 +38,59 @@ #include <QOpenGLTexture> #include <QQuickWindow> #include <QDebug> -#include <QQmlPropertyMap> #include "qwaylandquicksurface.h" #include "qwaylandquickcompositor.h" -#include "qwaylandsurfaceitem.h" -#include "qwaylandoutput.h" -#include <QtCompositor/private/qwaylandsurface_p.h> -#include <QtCompositor/private/qwaylandtexturebufferattacher_p.h> +#include "qwaylandquickitem.h" +#include <QtWaylandCompositor/qwaylandbufferref.h> +#include <QtWaylandCompositor/QWaylandView> +#include <QtWaylandCompositor/private/qwaylandsurface_p.h> + +#include <QtWaylandCompositor/private/qwayland-server-surface-extension.h> +#include <QtWaylandCompositor/private/qwlextendedsurface_p.h> QT_BEGIN_NAMESPACE class QWaylandQuickSurfacePrivate : public QWaylandSurfacePrivate { + Q_DECLARE_PUBLIC(QWaylandQuickSurface) public: - QWaylandQuickSurfacePrivate(wl_client *client, quint32 id, int version, QWaylandQuickCompositor *c, QWaylandQuickSurface *surf) - : QWaylandSurfacePrivate(client, id, version, c, surf) - , compositor(c) + QWaylandQuickSurfacePrivate() + : QWaylandSurfacePrivate() , useTextureAlpha(true) - , windowPropertyMap(new QQmlPropertyMap) , clientRenderingEnabled(true) { - } ~QWaylandQuickSurfacePrivate() { - windowPropertyMap->deleteLater(); - // buffer is deleted automatically by ~Surface(), since it is the assigned attacher - } - - void surface_commit(Resource *resource) Q_DECL_OVERRIDE - { - QWaylandSurfacePrivate::surface_commit(resource); - - Q_FOREACH (QtWayland::Output *output, outputs()) - output->waylandOutput()->update(); } - QWaylandQuickCompositor *compositor; bool useTextureAlpha; - QQmlPropertyMap *windowPropertyMap; bool clientRenderingEnabled; }; -QWaylandQuickSurface::QWaylandQuickSurface(wl_client *client, quint32 id, int version, QWaylandQuickCompositor *compositor) - : QWaylandSurface(new QWaylandQuickSurfacePrivate(client, id, version, compositor, this)) +QWaylandQuickSurface::QWaylandQuickSurface() + : QWaylandSurface(* new QWaylandQuickSurfacePrivate()) { - Q_D(QWaylandQuickSurface); - QWaylandSurface::setBufferAttacher(new QWaylandTextureBufferAttacher(this)); - connect(this, &QWaylandSurface::windowPropertyChanged, d->windowPropertyMap, &QQmlPropertyMap::insert); - connect(d->windowPropertyMap, &QQmlPropertyMap::valueChanged, this, &QWaylandSurface::setWindowProperty); } - -QWaylandQuickSurface::~QWaylandQuickSurface() +QWaylandQuickSurface::QWaylandQuickSurface(QWaylandCompositor *compositor, QWaylandClient *client, quint32 id, int version) + : QWaylandSurface(* new QWaylandQuickSurfacePrivate()) { - + initialize(compositor, client, id, version); } -QWaylandTextureBufferAttacher *QWaylandQuickSurface::textureBufferAttacher() const +QWaylandQuickSurface::~QWaylandQuickSurface() { - return static_cast<QWaylandTextureBufferAttacher*>(bufferAttacher()); -} -QSGTexture *QWaylandQuickSurface::texture() const -{ - return textureBufferAttacher()->texture(); } +/*! + * \qmlproperty QtWaylandCompositor::WaylandSurface::useTextureAlpha + * + * This property specifies whether the surface should use texture alpha. + */ bool QWaylandQuickSurface::useTextureAlpha() const { Q_D(const QWaylandQuickSurface); @@ -116,69 +103,15 @@ void QWaylandQuickSurface::setUseTextureAlpha(bool useTextureAlpha) if (d->useTextureAlpha != useTextureAlpha) { d->useTextureAlpha = useTextureAlpha; emit useTextureAlphaChanged(); - emit configure(textureBufferAttacher()->currentBuffer()); - } -} - -QObject *QWaylandQuickSurface::windowPropertyMap() const -{ - Q_D(const QWaylandQuickSurface); - return d->windowPropertyMap; -} - -bool QWaylandQuickSurface::event(QEvent *e) -{ - if (e->type() == static_cast<QEvent::Type>(QWaylandSurfaceLeaveEvent::WaylandSurfaceLeave)) { - QWaylandSurfaceLeaveEvent *event = static_cast<QWaylandSurfaceLeaveEvent *>(e); - - if (event->output()) { - QQuickWindow *oldWindow = static_cast<QQuickWindow *>(event->output()->window()); - disconnect(oldWindow, &QQuickWindow::beforeSynchronizing, - this, &QWaylandQuickSurface::updateTexture); - disconnect(oldWindow, &QQuickWindow::sceneGraphInvalidated, - this, &QWaylandQuickSurface::invalidateTexture); - } - - return true; - } - - if (e->type() == static_cast<QEvent::Type>(QWaylandSurfaceEnterEvent::WaylandSurfaceEnter)) { - QWaylandSurfaceEnterEvent *event = static_cast<QWaylandSurfaceEnterEvent *>(e); - - if (event->output()) { - QQuickWindow *window = static_cast<QQuickWindow *>(event->output()->window()); - connect(window, &QQuickWindow::beforeSynchronizing, - this, &QWaylandQuickSurface::updateTexture, - Qt::DirectConnection); - connect(window, &QQuickWindow::sceneGraphInvalidated, - this, &QWaylandQuickSurface::invalidateTexture, - Qt::DirectConnection); - } - - return true; + emit configure(d->bufferRef.hasBuffer()); } - - return QObject::event(e); -} - -void QWaylandQuickSurface::updateTexture() -{ - QWaylandTextureBufferAttacher *attacher = textureBufferAttacher(); - const bool update = attacher->isDirty(); - if (update) - attacher->updateTexture(); - foreach (QWaylandSurfaceView *view, views()) - static_cast<QWaylandSurfaceItem *>(view)->updateTexture(update); -} - -void QWaylandQuickSurface::invalidateTexture() -{ - textureBufferAttacher()->invalidateTexture(); - foreach (QWaylandSurfaceView *view, views()) - static_cast<QWaylandSurfaceItem *>(view)->updateTexture(true); - emit redraw(); } +/*! + * \qmlproperty QtWaylandCompositor::WaylandSurface::clientRenderingEnabled + * + * This property specifies whether client rendering is enabled for the surface. + */ bool QWaylandQuickSurface::clientRenderingEnabled() const { Q_D(const QWaylandQuickSurface); @@ -191,7 +124,8 @@ void QWaylandQuickSurface::setClientRenderingEnabled(bool enabled) if (d->clientRenderingEnabled != enabled) { d->clientRenderingEnabled = enabled; - sendOnScreenVisibilityChange(enabled); + if (QtWayland::ExtendedSurface *extSurface = QtWayland::ExtendedSurface::findIn(this)) + extSurface->setVisibility(enabled ? QWindow::AutomaticVisibility : QWindow::Hidden); emit clientRenderingEnabledChanged(); } diff --git a/src/compositor/compositor_api/qwaylandquicksurface.h b/src/compositor/compositor_api/qwaylandquicksurface.h index 9126f8ff1..ba53c82ff 100644 --- a/src/compositor/compositor_api/qwaylandquicksurface.h +++ b/src/compositor/compositor_api/qwaylandquicksurface.h @@ -3,9 +3,9 @@ ** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.com> ** Contact: http://www.qt.io/licensing/ ** -** This file is part of the plugins of the Qt Toolkit. +** This file is part of the QtWaylandCompositor module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $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 @@ -16,16 +16,19 @@ ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** 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. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** 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$ ** @@ -34,20 +37,14 @@ #ifndef QQUICKWAYLANDSURFACE_H #define QQUICKWAYLANDSURFACE_H -#include <QtCompositor/qwaylandsurface.h> -#include <QtCompositor/qwaylandbufferref.h> +#include <QtWaylandCompositor/qwaylandsurface.h> struct wl_client; QT_BEGIN_NAMESPACE -class QSGTexture; - -class QWaylandSurfaceItem; class QWaylandQuickSurfacePrivate; class QWaylandQuickCompositor; -class QWaylandQuickSurface; -class QWaylandTextureBufferAttacher; class Q_COMPOSITOR_EXPORT QWaylandQuickSurface : public QWaylandSurface { @@ -55,34 +52,20 @@ class Q_COMPOSITOR_EXPORT QWaylandQuickSurface : public QWaylandSurface Q_DECLARE_PRIVATE(QWaylandQuickSurface) Q_PROPERTY(bool useTextureAlpha READ useTextureAlpha WRITE setUseTextureAlpha NOTIFY useTextureAlphaChanged) Q_PROPERTY(bool clientRenderingEnabled READ clientRenderingEnabled WRITE setClientRenderingEnabled NOTIFY clientRenderingEnabledChanged) - Q_PROPERTY(QObject *windowProperties READ windowPropertyMap CONSTANT) public: - QWaylandQuickSurface(wl_client *client, quint32 id, int version, QWaylandQuickCompositor *compositor); + QWaylandQuickSurface(); + QWaylandQuickSurface(QWaylandCompositor *compositor, QWaylandClient *client, quint32 id, int version); ~QWaylandQuickSurface(); - QSGTexture *texture() const; - bool useTextureAlpha() const; void setUseTextureAlpha(bool useTextureAlpha); bool clientRenderingEnabled() const; void setClientRenderingEnabled(bool enabled); - QObject *windowPropertyMap() const; - - QWaylandTextureBufferAttacher *textureBufferAttacher() const; - -private: - bool event(QEvent *event) Q_DECL_OVERRIDE; - Q_SIGNALS: void useTextureAlphaChanged(); void clientRenderingEnabledChanged(); - -private: - void updateTexture(); - void invalidateTexture(); - }; QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandsurface.cpp b/src/compositor/compositor_api/qwaylandsurface.cpp index 64f78bd76..3ac791eb2 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 diff --git a/src/compositor/compositor_api/qwaylandsurface.h b/src/compositor/compositor_api/qwaylandsurface.h index acff69092..d3fe4f15e 100644 --- a/src/compositor/compositor_api/qwaylandsurface.h +++ b/src/compositor/compositor_api/qwaylandsurface.h @@ -4,36 +4,32 @@ ** 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$ ** @@ -42,7 +38,9 @@ #ifndef QWAYLANDSURFACE_H #define QWAYLANDSURFACE_H -#include <QtCompositor/qwaylandexport.h> +#include <QtWaylandCompositor/qwaylandexport.h> +#include <QtWaylandCompositor/qwaylandextension.h> +#include <QtWaylandCompositor/qwaylandclient.h> #include <QtCore/QScopedPointer> #include <QtGui/QImage> @@ -59,219 +57,87 @@ class QWaylandClient; class QWaylandSurfacePrivate; class QWaylandCompositor; class QWaylandBufferRef; -class QWaylandSurfaceView; -class QWaylandSurfaceInterface; +class QWaylandView; class QWaylandSurfaceOp; -class QWaylandOutput; - -namespace QtWayland { -class Surface; -class SurfacePrivate; -class ExtendedSurface; -} - -class Q_COMPOSITOR_EXPORT QWaylandBufferAttacher -{ -public: - virtual ~QWaylandBufferAttacher() {} - -protected: - virtual void attach(const QWaylandBufferRef &ref) = 0; - virtual void unmap() = 0; - friend class QtWayland::Surface; -}; - -class QWaylandSurfaceEnterEventPrivate; - -class Q_COMPOSITOR_EXPORT QWaylandSurfaceEnterEvent : public QEvent -{ -public: - QWaylandSurfaceEnterEvent(QWaylandOutput *output); - ~QWaylandSurfaceEnterEvent(); - - QWaylandOutput *output() const; - - static const QEvent::Type WaylandSurfaceEnter; - -private: - QWaylandSurfaceEnterEventPrivate *d; -}; - -class QWaylandSurfaceLeaveEventPrivate; - -class Q_COMPOSITOR_EXPORT QWaylandSurfaceLeaveEvent : public QEvent -{ -public: - QWaylandSurfaceLeaveEvent(QWaylandOutput *output); - ~QWaylandSurfaceLeaveEvent(); - - QWaylandOutput *output() const; - - static const QEvent::Type WaylandSurfaceLeave; - -private: - QWaylandSurfaceLeaveEventPrivate *d; -}; - -class Q_COMPOSITOR_EXPORT QWaylandSurface : public QObject +class Q_COMPOSITOR_EXPORT QWaylandSurface : public QWaylandObject { Q_OBJECT Q_DECLARE_PRIVATE(QWaylandSurface) Q_PROPERTY(QWaylandClient *client READ client CONSTANT) Q_PROPERTY(QSize size READ size NOTIFY sizeChanged) - Q_PROPERTY(QWaylandSurface::WindowFlags windowFlags READ windowFlags NOTIFY windowFlagsChanged) - Q_PROPERTY(QWaylandSurface::WindowType windowType READ windowType NOTIFY windowTypeChanged) Q_PROPERTY(Qt::ScreenOrientation contentOrientation READ contentOrientation NOTIFY contentOrientationChanged) - Q_PROPERTY(QString className READ className NOTIFY classNameChanged) - Q_PROPERTY(QString title READ title NOTIFY titleChanged) - Q_PROPERTY(Qt::ScreenOrientations orientationUpdateMask READ orientationUpdateMask NOTIFY orientationUpdateMaskChanged) - Q_PROPERTY(QWindow::Visibility visibility READ visibility WRITE setVisibility NOTIFY visibilityChanged) - Q_PROPERTY(QWaylandSurface *transientParent READ transientParent) - Q_PROPERTY(QPointF transientOffset READ transientOffset) - - Q_ENUMS(WindowFlag WindowType) - Q_FLAGS(WindowFlag WindowFlags) + Q_PROPERTY(QWaylandSurface::Origin origin READ origin NOTIFY originChanged) + Q_PROPERTY(bool isMapped READ isMapped NOTIFY mappedChanged) + Q_PROPERTY(bool cursorSurface READ isCursorSurface WRITE markAsCursorSurface) public: - enum WindowFlag { - OverridesSystemGestures = 0x0001, - StaysOnTop = 0x0002, - BypassWindowManager = 0x0004 + enum Origin { + OriginTopLeft, + OriginBottomLeft }; - Q_DECLARE_FLAGS(WindowFlags, WindowFlag) + Q_ENUM(Origin) - enum WindowType { - None, - Toplevel, - Transient, - Popup - }; - - enum Type { - Invalid, - Shm, - Texture - }; - - QWaylandSurface(wl_client *client, quint32 id, int version, QWaylandCompositor *compositor); + QWaylandSurface(); + QWaylandSurface(QWaylandCompositor *compositor, QWaylandClient *client, uint id, int version); virtual ~QWaylandSurface(); - QWaylandClient *client() const; + Q_INVOKABLE void initialize(QWaylandCompositor *compositor, QWaylandClient *client, uint id, int version); + bool isInitialized() const; - void addInterface(QWaylandSurfaceInterface *interface); - void removeInterface(QWaylandSurfaceInterface *interface); - - Type type() const; - bool isYInverted() const; + QWaylandClient *client() const; + struct wl_client *waylandClient() const { return client()->client(); } - bool visible() const; bool isMapped() const; QSize size() const; - Q_INVOKABLE void requestSize(const QSize &size); - Qt::ScreenOrientations orientationUpdateMask() const; Qt::ScreenOrientation contentOrientation() const; - WindowFlags windowFlags() const; - - WindowType windowType() const; - - QWindow::Visibility visibility() const; - void setVisibility(QWindow::Visibility visibility); - Q_INVOKABLE void sendOnScreenVisibilityChange(bool visible); // Compat - - QWaylandSurface *transientParent() const; - - QPointF transientOffset() const; - - QtWayland::Surface *handle(); - - QByteArray authenticationToken() const; - QVariantMap windowProperties() const; - void setWindowProperty(const QString &name, const QVariant &value); + Origin origin() const; QWaylandCompositor *compositor() const; - QWaylandOutput *mainOutput() const; - void setMainOutput(QWaylandOutput *mainOutput); - - QList<QWaylandOutput *> outputs() const; - - QString className() const; - - QString title() const; - bool hasInputPanelSurface() const; - bool transientInactive() const; - bool inputRegionContains(const QPoint &p) const; Q_INVOKABLE void destroy(); - Q_INVOKABLE void destroySurface(); - Q_INVOKABLE void ping(); + Q_INVOKABLE bool isDestroyed() const; - void ref(); - void setMapped(bool mapped); + Q_INVOKABLE void frameStarted(); + Q_INVOKABLE void sendFrameCallbacks(); - void setBufferAttacher(QWaylandBufferAttacher *attacher); - QWaylandBufferAttacher *bufferAttacher() const; + QWaylandView *throttlingView() const; + void setThrottlingView(QWaylandView *view); - QList<QWaylandSurfaceView *> views() const; - QList<QWaylandSurfaceInterface *> interfaces() const; - - bool sendInterfaceOp(QWaylandSurfaceOp &op); + QList<QWaylandView *> views() const; static QWaylandSurface *fromResource(::wl_resource *resource); + struct wl_resource *resource() const; + + void markAsCursorSurface(bool cursorSurface); + bool isCursorSurface() const; public Q_SLOTS: void updateSelection(); protected: - QWaylandSurface(QWaylandSurfacePrivate *dptr); + QWaylandSurface(QWaylandSurfacePrivate &dptr); Q_SIGNALS: - void mapped(); - void unmapped(); + void mappedChanged(); void damaged(const QRegion &rect); void parentChanged(QWaylandSurface *newParent, QWaylandSurface *oldParent); void sizeChanged(); - void windowPropertyChanged(const QString &name, const QVariant &value); - void windowFlagsChanged(WindowFlags flags); - void windowTypeChanged(WindowType type); + void offsetForNextFrame(const QPoint &offset); void contentOrientationChanged(); - void orientationUpdateMaskChanged(); - void extendedSurfaceReady(); - void classNameChanged(); - void titleChanged(); - void raiseRequested(); - void lowerRequested(); - void visibilityChanged(); void pong(); void surfaceDestroyed(); - - void viewAdded(QWaylandSurfaceView *view); - void viewRemoved(QWaylandSurfaceView *view); + void originChanged(); void configure(bool hasBuffer); void redraw(); - - friend class QWaylandSurfaceView; - friend class QWaylandSurfaceInterface; - friend class QtWayland::Surface; -}; - -class QWaylandUnmapLockPrivate; -class Q_COMPOSITOR_EXPORT QWaylandUnmapLock -{ -public: - QWaylandUnmapLock(QWaylandSurface *surface); - ~QWaylandUnmapLock(); - -private: - QWaylandUnmapLockPrivate *const d; }; QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandsurface_p.h b/src/compositor/compositor_api/qwaylandsurface_p.h index 383a523b2..1f3676bd9 100644 --- a/src/compositor/compositor_api/qwaylandsurface_p.h +++ b/src/compositor/compositor_api/qwaylandsurface_p.h @@ -4,9 +4,9 @@ ** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.com> ** Contact: http://www.qt.io/licensing/ ** -** This file is part of the plugins of the Qt Toolkit. +** This file is part of the QtWaylandCompositor module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $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 @@ -17,16 +17,19 @@ ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** 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. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** 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$ ** @@ -46,35 +49,132 @@ // We mean it. // -#include <QtCompositor/qwaylandexport.h> +#include <QtWaylandCompositor/qwaylandexport.h> #include <private/qobject_p.h> -#include <QtCompositor/private/qwlsurface_p.h> +#include <private/qwlsurfacebuffer_p.h> +#include <QtWaylandCompositor/qwaylandsurface.h> +#include <QtWaylandCompositor/qwaylandbufferref.h> + +#include <QtWaylandCompositor/private/qwlinputpanelsurface_p.h> +#include <QtWaylandCompositor/private/qwlregion_p.h> + +#include <QtCore/QVector> +#include <QtCore/QRect> +#include <QtGui/QRegion> +#include <QtGui/QImage> +#include <QtGui/QWindow> + +#include <QtCore/QTextStream> +#include <QtCore/QMetaType> + +#include <wayland-util.h> + +#include <QtWaylandCompositor/private/qwayland-server-wayland.h> QT_BEGIN_NAMESPACE class QWaylandCompositor; class QWaylandSurface; -class QWaylandSurfaceView; +class QWaylandView; class QWaylandSurfaceInterface; -class Q_COMPOSITOR_EXPORT QWaylandSurfacePrivate : public QObjectPrivate, public QtWayland::Surface +namespace QtWayland { +class FrameCallback; +} + +class Q_COMPOSITOR_EXPORT QWaylandSurfacePrivate : public QObjectPrivate, public QtWaylandServer::wl_surface { - Q_DECLARE_PUBLIC(QWaylandSurface) public: - QWaylandSurfacePrivate(wl_client *wlClient, quint32 id, int version, QWaylandCompositor *compositor, QWaylandSurface *surface); - void setType(QWaylandSurface::WindowType type); - void setTitle(const QString &title); - void setClassName(const QString &className); + static QWaylandSurfacePrivate *get(QWaylandSurface *surface); - bool closing; - int refCount; + QWaylandSurfacePrivate(); + ~QWaylandSurfacePrivate(); + + void ref(); + void deref(); + + void refView(QWaylandView *view); + void derefView(QWaylandView *view); + + using QtWaylandServer::wl_surface::resource; + + void setSize(const QSize &size); + + void removeFrameCallback(QtWayland::FrameCallback *callback); + + void notifyViewsAboutDestruction(); + + void setInputPanelSurface(QtWayland::InputPanelSurface *ips) { inputPanelSurface = ips; } +#ifndef QT_NO_DEBUG + static void addUninitializedSurface(QWaylandSurfacePrivate *surface); + static void removeUninitializedSurface(QWaylandSurfacePrivate *surface); + static bool hasUninitializedSurface(); +#endif +protected: + void surface_destroy_resource(Resource *resource) Q_DECL_OVERRIDE; + + void surface_destroy(Resource *resource) Q_DECL_OVERRIDE; + void surface_attach(Resource *resource, + struct wl_resource *buffer, int x, int y) Q_DECL_OVERRIDE; + void surface_damage(Resource *resource, + int32_t x, int32_t y, int32_t width, int32_t height) Q_DECL_OVERRIDE; + void surface_frame(Resource *resource, + uint32_t callback) Q_DECL_OVERRIDE; + void surface_set_opaque_region(Resource *resource, + struct wl_resource *region) Q_DECL_OVERRIDE; + void surface_set_input_region(Resource *resource, + struct wl_resource *region) Q_DECL_OVERRIDE; + void surface_commit(Resource *resource) Q_DECL_OVERRIDE; + void surface_set_buffer_transform(Resource *resource, int32_t transform) Q_DECL_OVERRIDE; + + void setBackBuffer(QtWayland::SurfaceBuffer *buffer, const QRegion &damage); + QtWayland::SurfaceBuffer *createSurfaceBuffer(struct ::wl_resource *buffer); + +protected: //member variables + QWaylandCompositor *compositor; + int refCount; QWaylandClient *client; + QList<QWaylandView *> views; + QRegion damage; + QtWayland::SurfaceBuffer *buffer; + QWaylandBufferRef bufferRef; + + struct { + QtWayland::SurfaceBuffer *buffer; + QRegion damage; + QPoint offset; + bool newlyAttached; + QRegion inputRegion; + } pending; + + QPoint lastLocalMousePos; + QPoint lastGlobalMousePos; - QWaylandSurface::WindowType windowType; - QList<QWaylandSurfaceView *> views; - QList<QWaylandSurfaceInterface *> interfaces; + QList<QtWayland::FrameCallback *> pendingFrameCallbacks; + QList<QtWayland::FrameCallback *> frameCallbacks; + + QtWayland::InputPanelSurface *inputPanelSurface; + + QRegion inputRegion; + QRegion opaqueRegion; + + QVector<QtWayland::SurfaceBuffer *> bufferPool; + + QSize size; + bool isCursorSurface; + bool destroyed; + bool mapped; + bool isInitialized; + Qt::ScreenOrientation contentOrientation; + QWindow::Visibility visibility; + +#ifndef QT_NO_DEBUG + static QList<QWaylandSurfacePrivate *> uninitializedSurfaces; +#endif + Q_DECLARE_PUBLIC(QWaylandSurface) + Q_DISABLE_COPY(QWaylandSurfacePrivate) }; QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandsurfaceinterface.cpp b/src/compositor/compositor_api/qwaylandsurfaceinterface.cpp deleted file mode 100644 index cddd231dd..000000000 --- a/src/compositor/compositor_api/qwaylandsurfaceinterface.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.com> -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Compositor. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "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. -** -** -** 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." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <wayland-server.h> - -#include "qwaylandsurfaceinterface.h" -#include "qwaylandsurface.h" -#include "qwaylandsurface_p.h" - -class QWaylandSurfaceInterface::Private -{ -public: - QWaylandSurface *surface; -}; - -QWaylandSurfaceInterface::QWaylandSurfaceInterface(QWaylandSurface *surface) - : d(new Private) -{ - d->surface = surface; - surface->addInterface(this); -} - -QWaylandSurfaceInterface::~QWaylandSurfaceInterface() -{ - d->surface->removeInterface(this); - delete d; -} - -QWaylandSurface *QWaylandSurfaceInterface::surface() const -{ - return d->surface; -} - -void QWaylandSurfaceInterface::setSurfaceType(QWaylandSurface::WindowType type) -{ - surface()->d_func()->setType(type); -} - -void QWaylandSurfaceInterface::setSurfaceClassName(const QString &name) -{ - surface()->d_func()->setClassName(name); -} - -void QWaylandSurfaceInterface::setSurfaceTitle(const QString &title) -{ - surface()->d_func()->setTitle(title); -} - - - -class QWaylandSurfaceOp::Private -{ -public: - int type; -}; - -QWaylandSurfaceOp::QWaylandSurfaceOp(int t) - : d(new Private) -{ - d->type = t; -} - -QWaylandSurfaceOp::~QWaylandSurfaceOp() -{ - delete d; -} - -int QWaylandSurfaceOp::type() const -{ - return d->type; -} - - - -QWaylandSurfaceSetVisibilityOp::QWaylandSurfaceSetVisibilityOp(QWindow::Visibility visibility) - : QWaylandSurfaceOp(QWaylandSurfaceOp::SetVisibility) - , m_visibility(visibility) -{ -} - -QWindow::Visibility QWaylandSurfaceSetVisibilityOp::visibility() const -{ - return m_visibility; -} - -QWaylandSurfaceResizeOp::QWaylandSurfaceResizeOp(const QSize &size) - : QWaylandSurfaceOp(QWaylandSurfaceOp::Resize) - , m_size(size) -{ -} - -QSize QWaylandSurfaceResizeOp::size() const -{ - return m_size; -} - -QWaylandSurfacePingOp::QWaylandSurfacePingOp(uint32_t serial) - : QWaylandSurfaceOp(QWaylandSurfaceOp::Ping) - , m_serial(serial) -{ -} - -uint32_t QWaylandSurfacePingOp::serial() const -{ - return m_serial; -} diff --git a/src/compositor/compositor_api/qwaylandsurfaceinterface.h b/src/compositor/compositor_api/qwaylandsurfaceinterface.h deleted file mode 100644 index 322037e6d..000000000 --- a/src/compositor/compositor_api/qwaylandsurfaceinterface.h +++ /dev/null @@ -1,127 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.com> -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Compositor. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "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. -** -** -** 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." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QWAYLANDSURFACEINTERFACE_H -#define QWAYLANDSURFACEINTERFACE_H - -#include <QWindow> - -#include <QtCompositor/qwaylandsurface.h> -#include <QtCompositor/qwaylandexport.h> - -QT_BEGIN_NAMESPACE - -class QWaylandSurface; - -class Q_COMPOSITOR_EXPORT QWaylandSurfaceOp -{ -public: - enum Type { - Close, - SetVisibility, - Resize, - Ping, - UserType = 1000 - }; - - QWaylandSurfaceOp(int t); - virtual ~QWaylandSurfaceOp(); - - int type() const; - -private: - class Private; - Private *const d; -}; - -class Q_COMPOSITOR_EXPORT QWaylandSurfaceSetVisibilityOp : public QWaylandSurfaceOp -{ -public: - QWaylandSurfaceSetVisibilityOp(QWindow::Visibility visibility); - QWindow::Visibility visibility() const; - -private: - QWindow::Visibility m_visibility; -}; - -class Q_COMPOSITOR_EXPORT QWaylandSurfaceResizeOp : public QWaylandSurfaceOp -{ -public: - QWaylandSurfaceResizeOp(const QSize &size); - QSize size() const; - -private: - QSize m_size; -}; - -class Q_COMPOSITOR_EXPORT QWaylandSurfacePingOp : public QWaylandSurfaceOp -{ -public: - QWaylandSurfacePingOp(quint32 serial); - quint32 serial() const; - -private: - quint32 m_serial; -}; - -class Q_COMPOSITOR_EXPORT QWaylandSurfaceInterface -{ -public: - QWaylandSurfaceInterface(QWaylandSurface *surf); - virtual ~QWaylandSurfaceInterface(); - - QWaylandSurface *surface() const; - -protected: - virtual bool runOperation(QWaylandSurfaceOp *op) = 0; - - void setSurfaceType(QWaylandSurface::WindowType type); - void setSurfaceClassName(const QString &name); - void setSurfaceTitle(const QString &title); - -private: - class Private; - Private *const d; - friend class QWaylandSurface; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/compositor/compositor_api/qwaylandsurfaceitem.cpp b/src/compositor/compositor_api/qwaylandsurfaceitem.cpp deleted file mode 100644 index e964c9177..000000000 --- a/src/compositor/compositor_api/qwaylandsurfaceitem.cpp +++ /dev/null @@ -1,425 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Compositor. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "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. -** -** -** 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." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qwaylandsurfaceitem.h" -#include "qwaylandquicksurface.h" -#include <QtCompositor/qwaylandcompositor.h> -#include <QtCompositor/qwaylandinput.h> - -#include <QtGui/QKeyEvent> -#include <QtGui/QGuiApplication> -#include <QtGui/QScreen> - -#include <QtQuick/QSGSimpleTextureNode> -#include <QtQuick/QQuickWindow> - -#include <QtCore/QMutexLocker> -#include <QtCore/QMutex> - -QT_BEGIN_NAMESPACE - -QMutex *QWaylandSurfaceItem::mutex = 0; - -class QWaylandSurfaceTextureProvider : public QSGTextureProvider -{ -public: - QWaylandSurfaceTextureProvider() : t(0) { } - - QSGTexture *texture() const Q_DECL_OVERRIDE - { - if (t) - t->setFiltering(smooth ? QSGTexture::Linear : QSGTexture::Nearest); - return t; - } - - bool smooth; - QSGTexture *t; -}; - -QWaylandSurfaceItem::QWaylandSurfaceItem(QWaylandQuickSurface *surface, QQuickItem *parent) - : QQuickItem(parent) - , QWaylandSurfaceView(surface) - , m_provider(0) - , m_paintEnabled(true) - , m_touchEventsEnabled(false) - , m_resizeSurfaceToItem(false) - , m_newTexture(false) - -{ - if (!mutex) - mutex = new QMutex; - - setFlag(ItemHasContents); - - update(); - - if (surface) { - setWidth(surface->size().width()); - setHeight(surface->size().height()); - } - - setSmooth(true); - - setAcceptedMouseButtons(Qt::LeftButton | Qt::MiddleButton | Qt::RightButton | - Qt::ExtraButton1 | Qt::ExtraButton2 | Qt::ExtraButton3 | Qt::ExtraButton4 | - Qt::ExtraButton5 | Qt::ExtraButton6 | Qt::ExtraButton7 | Qt::ExtraButton8 | - Qt::ExtraButton9 | Qt::ExtraButton10 | Qt::ExtraButton11 | - Qt::ExtraButton12 | Qt::ExtraButton13); - setAcceptHoverEvents(true); - if (surface) { - connect(surface, &QWaylandSurface::mapped, this, &QWaylandSurfaceItem::surfaceMapped); - connect(surface, &QWaylandSurface::unmapped, this, &QWaylandSurfaceItem::surfaceUnmapped); - connect(surface, &QWaylandSurface::surfaceDestroyed, this, &QWaylandSurfaceItem::surfaceDestroyed); - connect(surface, &QWaylandSurface::parentChanged, this, &QWaylandSurfaceItem::parentChanged); - connect(surface, &QWaylandSurface::sizeChanged, this, &QWaylandSurfaceItem::updateSize); - connect(surface, &QWaylandSurface::configure, this, &QWaylandSurfaceItem::updateBuffer); - connect(surface, &QWaylandSurface::redraw, this, &QQuickItem::update); - } - connect(this, &QWaylandSurfaceItem::widthChanged, this, &QWaylandSurfaceItem::updateSurfaceSize); - connect(this, &QWaylandSurfaceItem::heightChanged, this, &QWaylandSurfaceItem::updateSurfaceSize); - - - m_yInverted = surface ? surface->isYInverted() : true; - emit yInvertedChanged(); -} - -QWaylandSurfaceItem::~QWaylandSurfaceItem() -{ - QMutexLocker locker(mutex); - if (m_provider) - m_provider->deleteLater(); -} - -bool QWaylandSurfaceItem::isYInverted() const -{ - return m_yInverted; -} - -QSGTextureProvider *QWaylandSurfaceItem::textureProvider() const -{ - if (!m_provider) - m_provider = new QWaylandSurfaceTextureProvider(); - return m_provider; -} - -void QWaylandSurfaceItem::mousePressEvent(QMouseEvent *event) -{ - if (!surface()) - return; - - if (!surface()->inputRegionContains(event->pos())) { - event->ignore(); - return; - } - - QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event); - if (inputDevice->mouseFocus() != this) - inputDevice->setMouseFocus(this, event->localPos(), event->windowPos()); - inputDevice->sendMousePressEvent(event->button(), event->localPos(), event->windowPos()); -} - -void QWaylandSurfaceItem::mouseMoveEvent(QMouseEvent *event) -{ - if (surface()) { - QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event); - inputDevice->sendMouseMoveEvent(this, event->localPos(), event->windowPos()); - } -} - -void QWaylandSurfaceItem::mouseReleaseEvent(QMouseEvent *event) -{ - if (surface()) { - QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event); - inputDevice->sendMouseReleaseEvent(event->button(), event->localPos(), event->windowPos()); - } -} - -void QWaylandSurfaceItem::hoverEnterEvent(QHoverEvent *event) -{ - if (surface()) { - if (!surface()->inputRegionContains(event->pos())) { - event->ignore(); - return; - } - QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event); - inputDevice->sendMouseMoveEvent(this, event->pos()); - } -} - -void QWaylandSurfaceItem::hoverMoveEvent(QHoverEvent *event) -{ - if (surface()) { - if (!surface()->inputRegionContains(event->pos())) { - event->ignore(); - return; - } - QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event); - inputDevice->sendMouseMoveEvent(this, event->pos()); - } -} - -void QWaylandSurfaceItem::wheelEvent(QWheelEvent *event) -{ - if (surface()) { - if (!surface()->inputRegionContains(event->pos())) { - event->ignore(); - return; - } - - QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event); - inputDevice->sendMouseWheelEvent(event->orientation(), event->delta()); - } -} - -void QWaylandSurfaceItem::keyPressEvent(QKeyEvent *event) -{ - if (surface()) { - QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event); - inputDevice->sendFullKeyEvent(event); - } -} - -void QWaylandSurfaceItem::keyReleaseEvent(QKeyEvent *event) -{ - if (surface() && hasFocus()) { - QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event); - inputDevice->sendFullKeyEvent(event); - } -} - -void QWaylandSurfaceItem::touchEvent(QTouchEvent *event) -{ - if (m_touchEventsEnabled) { - QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event); - - if (event->type() == QEvent::TouchBegin) { - QQuickItem *grabber = window()->mouseGrabberItem(); - if (grabber != this) - grabMouse(); - } - - QPoint pointPos; - const QList<QTouchEvent::TouchPoint> &points = event->touchPoints(); - if (!points.isEmpty()) - pointPos = points.at(0).pos().toPoint(); - - if (event->type() == QEvent::TouchBegin && !surface()->inputRegionContains(pointPos)) { - event->ignore(); - return; - } - - event->accept(); - if (inputDevice->mouseFocus() != this) { - inputDevice->setMouseFocus(this, pointPos, pointPos); - } - inputDevice->sendFullTouchEvent(event); - - const bool isEnd = event->type() == QEvent::TouchEnd || event->type() == QEvent::TouchCancel; - if (isEnd && window()->mouseGrabberItem() == this) - ungrabMouse(); - } else { - event->ignore(); - } -} - -void QWaylandSurfaceItem::mouseUngrabEvent() -{ - if (surface()) { - QTouchEvent e(QEvent::TouchCancel); - touchEvent(&e); - } -} - -void QWaylandSurfaceItem::takeFocus(QWaylandInputDevice *device) -{ - setFocus(true); - - if (!surface()) - return; - - QWaylandInputDevice *target = device; - if (!target) { - target = compositor()->defaultInputDevice(); - } - target->setKeyboardFocus(surface()); -} - -void QWaylandSurfaceItem::surfaceMapped() -{ - update(); -} - -void QWaylandSurfaceItem::surfaceUnmapped() -{ - update(); -} - -void QWaylandSurfaceItem::parentChanged(QWaylandSurface *newParent, QWaylandSurface *oldParent) -{ - Q_UNUSED(oldParent); - - if (newParent) { - setPaintEnabled(true); - setVisible(true); - setOpacity(1); - setEnabled(true); - } -} - -void QWaylandSurfaceItem::updateSize() -{ - if (surface()) { - setSize(surface()->size()); - } -} - -void QWaylandSurfaceItem::updateSurfaceSize() -{ - if (surface() && m_resizeSurfaceToItem) { - surface()->requestSize(QSize(width(), height())); - } -} - -void QWaylandSurfaceItem::setPos(const QPointF &pos) -{ - setPosition(pos); -} - -QPointF QWaylandSurfaceItem::pos() const -{ - return position(); -} - -void QWaylandSurfaceItem::setParentView(QWaylandSurfaceView *view) -{ - setParentItem(static_cast<QWaylandSurfaceItem *>(view)); -} - -/*! - \qmlproperty bool QtWayland::QWaylandSurfaceItem::paintEnabled - - If this property is true, the \l item is hidden, though the texture - will still be updated. As opposed to hiding the \l item by - setting \l{Item::visible}{visible} to false, setting this property to true - will not prevent mouse or keyboard input from reaching \l item. -*/ -bool QWaylandSurfaceItem::paintEnabled() const -{ - return m_paintEnabled; -} - -void QWaylandSurfaceItem::setPaintEnabled(bool enabled) -{ - m_paintEnabled = enabled; - update(); -} - -void QWaylandSurfaceItem::updateBuffer(bool hasBuffer) -{ - Q_UNUSED(hasBuffer) - - bool inv = m_yInverted; - m_yInverted = surface()->isYInverted(); - if (inv != m_yInverted) - emit yInvertedChanged(); - - m_newTexture = true; -} - -void QWaylandSurfaceItem::updateTexture() -{ - updateTexture(false); -} - -void QWaylandSurfaceItem::updateTexture(bool changed) -{ - if (!m_provider) - m_provider = new QWaylandSurfaceTextureProvider(); - - m_provider->t = static_cast<QWaylandQuickSurface *>(surface())->texture(); - m_provider->smooth = smooth(); - if (m_newTexture || changed) - emit m_provider->textureChanged(); - m_newTexture = false; -} - -QSGNode *QWaylandSurfaceItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) -{ - bool mapped = surface() && surface()->isMapped(); - - if (!mapped || !m_provider || !m_provider->t || !m_paintEnabled) { - delete oldNode; - return 0; - } - - QSGSimpleTextureNode *node = static_cast<QSGSimpleTextureNode *>(oldNode); - - if (!node) - node = new QSGSimpleTextureNode(); - node->setTexture(m_provider->t); - // Surface textures come by default with the OpenGL coordinate system, which is inverted relative - // to the QtQuick one. So we're dealing with a double invertion here, and if isYInverted() returns - // true it means it is NOT inverted relative to QtQuick, while if it returns false it means it IS. - if (surface()->isYInverted()) { - node->setRect(0, 0, width(), height()); - } else { - node->setRect(0, height(), width(), -height()); - } - - return node; -} - -void QWaylandSurfaceItem::setTouchEventsEnabled(bool enabled) -{ - if (m_touchEventsEnabled != enabled) { - m_touchEventsEnabled = enabled; - emit touchEventsEnabledChanged(); - } -} - -void QWaylandSurfaceItem::setResizeSurfaceToItem(bool enabled) -{ - if (m_resizeSurfaceToItem != enabled) { - m_resizeSurfaceToItem = enabled; - emit resizeSurfaceToItemChanged(); - } -} - -QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandsurfaceitem.h b/src/compositor/compositor_api/qwaylandsurfaceitem.h deleted file mode 100644 index 529b839c6..000000000 --- a/src/compositor/compositor_api/qwaylandsurfaceitem.h +++ /dev/null @@ -1,146 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Compositor. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "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. -** -** -** 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." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QWAYLANDSURFACEITEM_H -#define QWAYLANDSURFACEITEM_H - -#include <QtCompositor/qwaylandexport.h> - -#include <QtQuick/QQuickItem> -#include <QtQuick/qsgtexture.h> - -#include <QtQuick/qsgtextureprovider.h> - -#include <QtCompositor/qwaylandsurfaceview.h> -#include <QtCompositor/qwaylandquicksurface.h> - -Q_DECLARE_METATYPE(QWaylandQuickSurface*) - -QT_BEGIN_NAMESPACE - -class QWaylandSurfaceTextureProvider; -class QMutex; -class QWaylandInputDevice; - -class Q_COMPOSITOR_EXPORT QWaylandSurfaceItem : public QQuickItem, public QWaylandSurfaceView -{ - Q_OBJECT - Q_PROPERTY(QWaylandSurface* surface READ surface CONSTANT) - Q_PROPERTY(bool paintEnabled READ paintEnabled WRITE setPaintEnabled) - Q_PROPERTY(bool touchEventsEnabled READ touchEventsEnabled WRITE setTouchEventsEnabled NOTIFY touchEventsEnabledChanged) - Q_PROPERTY(bool isYInverted READ isYInverted NOTIFY yInvertedChanged) - Q_PROPERTY(bool resizeSurfaceToItem READ resizeSurfaceToItem WRITE setResizeSurfaceToItem NOTIFY resizeSurfaceToItemChanged) - -public: - QWaylandSurfaceItem(QWaylandQuickSurface *surface, QQuickItem *parent = 0); - ~QWaylandSurfaceItem(); - - Q_INVOKABLE bool isYInverted() const; - - bool isTextureProvider() const { return true; } - QSGTextureProvider *textureProvider() const; - - bool paintEnabled() const; - bool touchEventsEnabled() const { return m_touchEventsEnabled; } - bool resizeSurfaceToItem() const { return m_resizeSurfaceToItem; } - void updateTexture(); - - void setTouchEventsEnabled(bool enabled); - void setResizeSurfaceToItem(bool enabled); - - void setPos(const QPointF &pos) Q_DECL_OVERRIDE; - QPointF pos() const Q_DECL_OVERRIDE; - - void setParentView(QWaylandSurfaceView *view) Q_DECL_OVERRIDE; - -protected: - void mousePressEvent(QMouseEvent *event); - void mouseMoveEvent(QMouseEvent *event); - void mouseReleaseEvent(QMouseEvent *event); - void hoverEnterEvent(QHoverEvent *event); - void hoverMoveEvent(QHoverEvent *event); - void wheelEvent(QWheelEvent *event); - - void keyPressEvent(QKeyEvent *event); - void keyReleaseEvent(QKeyEvent *event); - - void touchEvent(QTouchEvent *event); - void mouseUngrabEvent() Q_DECL_OVERRIDE; - -public Q_SLOTS: - virtual void takeFocus(QWaylandInputDevice *device = 0); - void setPaintEnabled(bool paintEnabled); - -private Q_SLOTS: - void surfaceMapped(); - void surfaceUnmapped(); - void parentChanged(QWaylandSurface *newParent, QWaylandSurface *oldParent); - void updateSize(); - void updateSurfaceSize(); - void updateBuffer(bool hasBuffer); - -Q_SIGNALS: - void touchEventsEnabledChanged(); - void yInvertedChanged(); - void resizeSurfaceToItemChanged(); - void surfaceDestroyed(); - -protected: - QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *); - -private: - friend class QWaylandSurfaceNode; - friend class QWaylandQuickSurface; - void init(QWaylandQuickSurface *); - void updateTexture(bool changed); - - static QMutex *mutex; - - mutable QWaylandSurfaceTextureProvider *m_provider; - bool m_paintEnabled; - bool m_touchEventsEnabled; - bool m_yInverted; - bool m_resizeSurfaceToItem; - bool m_newTexture; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/compositor/compositor_api/qwaylandsurfaceview.cpp b/src/compositor/compositor_api/qwaylandsurfaceview.cpp deleted file mode 100644 index 98ac81d5f..000000000 --- a/src/compositor/compositor_api/qwaylandsurfaceview.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.com> -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qwaylandsurfaceview.h" -#include "qwaylandsurface.h" -#include "qwaylandsurface_p.h" -#include "qwaylandcompositor.h" -#include "qwaylandinput.h" - -QT_BEGIN_NAMESPACE - -class QWaylandSurfaceViewPrivate -{ -public: - QWaylandSurface *surface; - QPointF pos; -}; - -QWaylandSurfaceView::QWaylandSurfaceView(QWaylandSurface *surf) - : d(new QWaylandSurfaceViewPrivate) -{ - d->surface = surf; - if (surf) { - surf->d_func()->views << this; - surf->ref(); - emit surf->viewAdded(this); - } -} - -QWaylandSurfaceView::~QWaylandSurfaceView() -{ - if (d->surface) { - QWaylandInputDevice *i = d->surface->compositor()->defaultInputDevice(); - if (i->mouseFocus() == this) - i->setMouseFocus(Q_NULLPTR, QPointF()); - - d->surface->destroy(); - d->surface->d_func()->views.removeOne(this); - emit d->surface->viewRemoved(this); - } - delete d; -} - -QWaylandSurface *QWaylandSurfaceView::surface() const -{ - return d->surface; -} - -QWaylandCompositor *QWaylandSurfaceView::compositor() const -{ - return d->surface ? d->surface->compositor() : 0; -} - -void QWaylandSurfaceView::setPos(const QPointF &pos) -{ - d->pos = pos; -} - -QPointF QWaylandSurfaceView::pos() const -{ - return d->pos; -} - -QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandsurfaceview.h b/src/compositor/compositor_api/qwaylandsurfaceview.h deleted file mode 100644 index dc0d93d91..000000000 --- a/src/compositor/compositor_api/qwaylandsurfaceview.h +++ /dev/null @@ -1,67 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.com> -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QWAYLANDSURFACEVIEW_H -#define QWAYLANDSURFACEVIEW_H - -#include <QPointF> - -#include <QtCompositor/qwaylandexport.h> - -QT_BEGIN_NAMESPACE - -class QWaylandSurface; -class QWaylandCompositor; - -class Q_COMPOSITOR_EXPORT QWaylandSurfaceView -{ -public: - QWaylandSurfaceView(QWaylandSurface *surface); - virtual ~QWaylandSurfaceView(); - - QWaylandCompositor *compositor() const; - QWaylandSurface *surface() const; - - virtual void setPos(const QPointF &pos); - virtual QPointF pos() const; - - virtual void setParentView(QWaylandSurfaceView *view) { Q_UNUSED(view) } - -private: - class QWaylandSurfaceViewPrivate *const d; - friend class QWaylandSurfaceViewPrivate; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/compositor/compositor_api/qwaylandtouch.cpp b/src/compositor/compositor_api/qwaylandtouch.cpp new file mode 100644 index 000000000..743730254 --- /dev/null +++ b/src/compositor/compositor_api/qwaylandtouch.cpp @@ -0,0 +1,271 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** 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 "qwaylandtouch.h" +#include "qwaylandtouch_p.h" + +#include <QtWaylandCompositor/QWaylandCompositor> +#include <QtWaylandCompositor/QWaylandInputDevice> +#include <QtWaylandCompositor/QWaylandView> +#include <QtWaylandCompositor/QWaylandClient> + +#include <QtWaylandCompositor/private/qwlqttouch_p.h> + +QT_BEGIN_NAMESPACE + +QWaylandTouchPrivate::QWaylandTouchPrivate(QWaylandTouch *touch, QWaylandInputDevice *seat) + : wl_touch() + , seat(seat) + , focusResource() +{ +} + +void QWaylandTouchPrivate::resetFocusState() +{ + focusDestroyListener.reset(); + focusResource = 0; +} + +void QWaylandTouchPrivate::touch_destroy_resource(Resource *resource) +{ + if (focusResource == resource) { + resetFocusState(); + } +} + +void QWaylandTouchPrivate::touch_release(Resource *resource) +{ + wl_resource_destroy(resource->handle); +} + +void QWaylandTouchPrivate::sendDown(uint32_t time, int touch_id, const QPointF &position) +{ + Q_Q(QWaylandTouch); + if (focusResource || q->mouseFocus()) + return; + + uint32_t serial = q->compositor()->nextSerial(); + + wl_touch_send_down(focusResource->handle, serial, time, q->mouseFocus()->surfaceResource(), touch_id, + wl_fixed_from_double(position.x()), wl_fixed_from_double(position.y())); +} + +void QWaylandTouchPrivate::sendUp(uint32_t time, int touch_id) +{ + if (focusResource) + return; + + uint32_t serial = compositor()->nextSerial(); + + wl_touch_send_up(focusResource->handle, serial, time, touch_id); +} +void QWaylandTouchPrivate::sendMotion(uint32_t time, int touch_id, const QPointF &position) +{ + if (!focusResource) + return; + + wl_touch_send_motion(focusResource->handle, time, touch_id, + wl_fixed_from_double(position.x()), wl_fixed_from_double(position.y())); +} + +/*! + * \class QWaylandTouch + * \inmodule QtWaylandCompositor + * \brief The QWaylandTouch class provides access to a touch device. + * + * This class provides access to the touch device in a QWaylandInputDevice. It corresponds to + * the Wayland interface wl_touch. + */ + +/*! + * Constructs a QWaylandTouch for the \a inputDevice and with the given \a parent. + */ +QWaylandTouch::QWaylandTouch(QWaylandInputDevice *inputDevice, QObject *parent) + : QWaylandObject(*new QWaylandTouchPrivate(this, inputDevice), parent) +{ + connect(&d_func()->focusDestroyListener, &QWaylandDestroyListener::fired, this, &QWaylandTouch::focusDestroyed); +} + +/*! + * Returns the input device for this QWaylandTouch. + */ +QWaylandInputDevice *QWaylandTouch::inputDevice() const +{ + Q_D(const QWaylandTouch); + return d->seat; +} + +/*! + * Returns the compositor for this QWaylandTouch. + */ +QWaylandCompositor *QWaylandTouch::compositor() const +{ + Q_D(const QWaylandTouch); + return d->compositor(); +} + +/*! + * Sends a touch point event for the touch device with the given \a id, + * \a position, and \a state. + * + * + * \sa mouseFocus() + */ +void QWaylandTouch::sendTouchPointEvent(int id, const QPointF &position, Qt::TouchPointState state) +{ + Q_D(QWaylandTouch); + uint32_t time = compositor()->currentTimeMsecs(); + switch (state) { + case Qt::TouchPointPressed: + d->sendDown(time, id, position); + break; + case Qt::TouchPointMoved: + d->sendMotion(time, id, position); + break; + case Qt::TouchPointReleased: + d->sendUp(time, id); + break; + case Qt::TouchPointStationary: + // stationary points are not sent through wayland, the client must cache them + break; + default: + break; + } +} + +/*! + * Sends a touch frame event for the touch device. This indicates the end of a + * contact point list. + */ +void QWaylandTouch::sendFrameEvent() +{ + Q_D(QWaylandTouch); + if (d->focusResource) + d->send_frame(d->focusResource->handle); +} + +/*! + * Sends a touch cancel event for the touch device. + */ +void QWaylandTouch::sendCancelEvent() +{ + Q_D(QWaylandTouch); + if (d->focusResource) + d->send_cancel(d->focusResource->handle); +} + +/*! + * Sends all the touch points in \a event for this touch device, followed + * by a touch frame event. + * + * \sa sendTouchPointEvent(), sendFrameEvent() + */ +void QWaylandTouch::sendFullTouchEvent(QTouchEvent *event) +{ + Q_D(QWaylandTouch); + if (event->type() == QEvent::TouchCancel) { + sendCancelEvent(); + return; + } + + QtWayland::TouchExtensionGlobal *ext = QtWayland::TouchExtensionGlobal::findIn(d->compositor()); + if (ext && ext->postTouchEvent(event, d->seat->mouseFocus())) + return; + + const QList<QTouchEvent::TouchPoint> points = event->touchPoints(); + if (points.isEmpty()) + return; + + const int pointCount = points.count(); + for (int i = 0; i < pointCount; ++i) { + const QTouchEvent::TouchPoint &tp(points.at(i)); + // Convert the local pos in the compositor window to surface-relative. + sendTouchPointEvent(tp.id(), tp.pos(), tp.state()); + } + sendFrameEvent(); +} + +/*! + * \internal + */ +void QWaylandTouch::addClient(QWaylandClient *client, uint32_t id, uint32_t version) +{ + Q_D(QWaylandTouch); + d->add(client->client(), id, qMin<uint32_t>(QtWaylandServer::wl_touch::interfaceVersion(), version)); +} + +/*! + * Returns the Wayland resource for this QWaylandTouch. + */ +struct wl_resource *QWaylandTouch::focusResource() const +{ + Q_D(const QWaylandTouch); + if (!d->focusResource) + return Q_NULLPTR; + return d->focusResource->handle; +} + +/*! + * Returns the view currently holding mouse focus in the input device. + */ +QWaylandView *QWaylandTouch::mouseFocus() const +{ + Q_D(const QWaylandTouch); + return d->seat->mouseFocus(); +} + +/*! + * \internal + */ +void QWaylandTouch::focusDestroyed(void *data) +{ + Q_UNUSED(data) + Q_D(QWaylandTouch); + d->resetFocusState(); +} + +/*! + * \internal + */ +void QWaylandTouch::mouseFocusChanged(QWaylandView *newFocus, QWaylandView *oldFocus) +{ + Q_UNUSED(newFocus); + Q_UNUSED(oldFocus); + Q_D(QWaylandTouch); + d->resetFocusState(); +} + +QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandtouch.h b/src/compositor/compositor_api/qwaylandtouch.h new file mode 100644 index 000000000..aa9ee34cb --- /dev/null +++ b/src/compositor/compositor_api/qwaylandtouch.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** 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 QWAYLANDTOUCH_H +#define QWAYLANDTOUCH_H + +#include <QtWaylandCompositor/QWaylandExtension> + +#include <QtCore/QObject> +#include <QtGui/QTouchEvent> + +QT_BEGIN_NAMESPACE + +class QWaylandTouch; +class QWaylandTouchPrivate; +class QWaylandInputDevice; +class QWaylandView; +class QWaylandClient; + +class Q_COMPOSITOR_EXPORT QWaylandTouch : public QWaylandObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QWaylandTouch) +public: + QWaylandTouch(QWaylandInputDevice *inputDevice, QObject *parent = 0); + + QWaylandInputDevice *inputDevice() const; + QWaylandCompositor *compositor() const; + + virtual void sendTouchPointEvent(int id, const QPointF &position, Qt::TouchPointState state); + virtual void sendFrameEvent(); + virtual void sendCancelEvent(); + + virtual void sendFullTouchEvent(QTouchEvent *event); + + virtual void addClient(QWaylandClient *client, uint32_t id, uint32_t version); + + struct wl_resource *focusResource() const; + + QWaylandView *mouseFocus() const; +private: + void focusDestroyed(void *data); + void mouseFocusChanged(QWaylandView *newFocus, QWaylandView *oldFocus); +}; + +QT_END_NAMESPACE + +#endif /*QWAYLANDTOUCH_H*/ diff --git a/src/compositor/compositor_api/qwaylandtouch_p.h b/src/compositor/compositor_api/qwaylandtouch_p.h new file mode 100644 index 000000000..fe36cd6e8 --- /dev/null +++ b/src/compositor/compositor_api/qwaylandtouch_p.h @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2013 Klarälvdalens Datakonsult AB (KDAB). +** 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 QTWAYLAND_QWLTOUCH_P_H +#define QTWAYLAND_QWLTOUCH_P_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. +// + +#include <QtWaylandCompositor/qwaylandexport.h> +#include <QtWaylandCompositor/QWaylandDestroyListener> +#include <QtWaylandCompositor/QWaylandTouch> +#include <QtWaylandCompositor/QWaylandInputDevice> +#include <QtWaylandCompositor/QWaylandView> +#include <QtWaylandCompositor/QWaylandCompositor> + +#include <QtCore/QPoint> +#include <QtCore/private/qobject_p.h> + +#include <QtWaylandCompositor/private/qwayland-server-wayland.h> + +QT_BEGIN_NAMESPACE + +class Q_COMPOSITOR_EXPORT QWaylandTouchPrivate : public QObjectPrivate, public QtWaylandServer::wl_touch +{ + Q_DECLARE_PUBLIC(QWaylandTouch) +public: + explicit QWaylandTouchPrivate(QWaylandTouch *touch, QWaylandInputDevice *seat); + + QWaylandCompositor *compositor() const { return seat->compositor(); } + + void sendDown(uint32_t time, int touch_id, const QPointF &position); + void sendMotion(uint32_t time, int touch_id, const QPointF &position); + void sendUp(uint32_t time, int touch_id); + + void setFocusResource() + { + if (focusResource) + return; + + QWaylandView *mouseFocus = seat->mouseFocus(); + if (!mouseFocus || !mouseFocus->surface()) + return; + + focusResource = resourceMap().value(mouseFocus->surface()->waylandClient()); + } +private: + void resetFocusState(); + void touch_destroy_resource(Resource *resource) Q_DECL_OVERRIDE; + void touch_release(Resource *resource) Q_DECL_OVERRIDE; + + QWaylandInputDevice *seat; + + Resource *focusResource; + QWaylandDestroyListener focusDestroyListener; +}; + +QT_END_NAMESPACE + +#endif // QTWAYLAND_QWLTOUCH_P_H diff --git a/src/compositor/compositor_api/qwaylandview.cpp b/src/compositor/compositor_api/qwaylandview.cpp new file mode 100644 index 000000000..dd27308ad --- /dev/null +++ b/src/compositor/compositor_api/qwaylandview.cpp @@ -0,0 +1,343 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.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 "qwaylandview.h" +#include "qwaylandview_p.h" +#include "qwaylandsurface.h" +#include <QtWaylandCompositor/QWaylandInputDevice> +#include <QtWaylandCompositor/QWaylandCompositor> + +#include <QtWaylandCompositor/private/qwaylandsurface_p.h> +#include <QtWaylandCompositor/private/qwaylandoutput_p.h> + +#include <QtCore/QMutex> + +QT_BEGIN_NAMESPACE + +void QWaylandViewPrivate::markSurfaceAsDestroyed(QWaylandSurface *surface) +{ + Q_Q(QWaylandView); + Q_ASSERT(surface == this->surface); + + q->setSurface(Q_NULLPTR); + emit q->surfaceDestroyed(); +} + +/*! + * \qmltype WaylandView + * \inqmlmodule QtWayland.Compositor + * \brief Represents a view of a surface on an output. + * + * The WaylandView corresponds to the presentation of a surface on a specific output, managing + * the buffers that contain the contents to be rendered. You can have several views into the same surface. + */ + +/*! + * \class QWaylandView + * \inmodule QtWaylandCompositor + * \brief Represents a view of a surface on an output. + * + * The WaylandView corresponds to the presentation of a surface on a specific output, managing + * the buffers that contain the contents to be rendered. You can have several views into the same surface. + */ + +/*! + * Constructs a QWaylandView with the given \a renderObject and \a parent. + */ +QWaylandView::QWaylandView(QObject *renderObject, QObject *parent) + : QObject(*new QWaylandViewPrivate(),parent) +{ + d_func()->renderObject = renderObject; +} + +/*! + * Destroys the QWaylandView. + */ +QWaylandView::~QWaylandView() +{ + Q_D(QWaylandView); + if (d->surface) { + if (d->output) + QWaylandOutputPrivate::get(d->output)->removeView(this, d->surface); + QWaylandInputDevice *i = d->surface->compositor()->defaultInputDevice(); + if (i->mouseFocus() == this) + i->setMouseFocus(Q_NULLPTR); + + QWaylandSurfacePrivate::get(d->surface)->derefView(this); + } + +} + +/*! + \internal Didn't we decide to remove this property? +*/ +QObject *QWaylandView::renderObject() const +{ + Q_D(const QWaylandView); + return d->renderObject; +} + +/*! + * \qmlproperty object QtWaylandCompositor::WaylandView::surface + * + * This property holds the surface viewed by this WaylandView. + */ + +/*! + * \property QWaylandView::surface + * + * This property holds the surface viewed by this QWaylandView. + */ +QWaylandSurface *QWaylandView::surface() const +{ + Q_D(const QWaylandView); + return d->surface; +} + +void QWaylandView::setSurface(QWaylandSurface *newSurface) +{ + Q_D(QWaylandView); + if (d->surface == newSurface) + return; + + + if (d->surface) { + QWaylandSurfacePrivate::get(d->surface)->derefView(this); + if (d->output) + QWaylandOutputPrivate::get(d->output)->removeView(this, d->surface); + } + + d->surface = newSurface; + + if (!d->bufferLock) { + d->currentBuffer = QWaylandBufferRef(); + d->currentDamage = QRegion(); + } + + d->nextBuffer = QWaylandBufferRef(); + d->nextDamage = QRegion(); + + if (d->surface) { + QWaylandSurfacePrivate::get(d->surface)->refView(this); + if (d->output) + QWaylandOutputPrivate::get(d->output)->addView(this, d->surface); + } + + emit surfaceChanged(); + +} + +/*! + * \qmlproperty object QtWaylandCompositor::WaylandView::surface + * + * This property holds the output on which this view displays its surface. + */ + +/*! + * \property QWaylandView::output + * + * This property holds the output on which this view displays its surface. + */ +QWaylandOutput *QWaylandView::output() const +{ + Q_D(const QWaylandView); + return d->output; +} + +void QWaylandView::setOutput(QWaylandOutput *newOutput) +{ + Q_D(QWaylandView); + if (d->output == newOutput) + return; + + if (d->output && d->surface) + QWaylandOutputPrivate::get(d->output)->removeView(this, d->surface); + + d->output = newOutput; + + if (d->output && d->surface) + QWaylandOutputPrivate::get(d->output)->addView(this, d->surface); + + emit outputChanged(); +} + +/*! + * Attaches a new buffer \a ref and \a damage region to this QWaylandView. These + * will become current the next time advance() is called. + */ +void QWaylandView::attach(const QWaylandBufferRef &ref, const QRegion &damage) +{ + Q_D(QWaylandView); + QMutexLocker locker(&d->bufferMutex); + d->nextBuffer = ref; + d->nextDamage = damage; +} + +/*! + * Sets the next buffer and damage to current and returns true. If the buffer + * is locked or if no new buffer has been attached since the last call to + * advance(), the function returns false and does nothing. + * + * If this view is set as its surface's throttling view, discardCurrentBuffer() + * will be called on all views of the same surface for which the + * \l{QWaylandView::discardFrontBuffers}{discardFrontBuffers} + * property is set to true and the current buffer is the same as the + * throttling view's current buffer. + * + * This allows for a design where a primary + * view can make sure that views running on a lower frequency will release their + * front buffer references so that the buffer can be reused on the client side, + * avoiding the situation where the lower frequency views throttle the frame rate + * of the client application. + */ +bool QWaylandView::advance() +{ + Q_D(QWaylandView); + if (d->currentBuffer == d->nextBuffer && !d->forceAdvanceSucceed) + return false; + + if (d->bufferLock) + return false; + + if (d->surface && d->surface->throttlingView() == this) { + Q_FOREACH (QWaylandView *view, d->surface->views()) { + if (view != this && view->discardFrontBuffers() && view->d_func()->currentBuffer == d->currentBuffer) + view->discardCurrentBuffer(); + } + } + + QMutexLocker locker(&d->bufferMutex); + d->forceAdvanceSucceed = false; + d->currentBuffer = d->nextBuffer; + d->currentDamage = d->nextDamage; + return true; +} + +/*! + * Force the view to discard its current buffer, to allow it to be reused on the client side. + */ +void QWaylandView::discardCurrentBuffer() +{ + Q_D(QWaylandView); + QMutexLocker locker(&d->bufferMutex); + d->currentBuffer = QWaylandBufferRef(); + d->forceAdvanceSucceed = true; +} + +/*! + * Returns a reference to this view's current buffer. + */ +QWaylandBufferRef QWaylandView::currentBuffer() +{ + Q_D(QWaylandView); + QMutexLocker locker(&d->bufferMutex); + return d->currentBuffer; +} + +/*! + * Returns the current damage region of this view. + */ +QRegion QWaylandView::currentDamage() +{ + Q_D(QWaylandView); + QMutexLocker locker(&d->bufferMutex); + return d->currentDamage; +} + +/*! + * \qmlproperty bool QtWaylandCompositor::WaylandView::bufferLock + * + * This property holds whether the view's buffer is currently locked. When + * the buffer is locked, advance() will not advance to the next buffer, + * but will instead return false. + * + * The default is false. + */ + +/*! + * \property QWaylandView::bufferLock + * + * This property holds whether the view's buffer is currently locked. When + * the buffer is locked, advance() will not advance to the next buffer, + * but will instead return false. + * + * The default is false. + */ +bool QWaylandView::isBufferLocked() const +{ + Q_D(const QWaylandView); + return d->bufferLock; +} + +void QWaylandView::setBufferLock(bool locked) +{ + Q_D(QWaylandView); + d->bufferLock = locked; +} + +/*! + * \property bool QWaylandView::discardFrontBuffers + * + * By default, the view locks the current buffer until advance() is called. Set this property + * to true to allow Qt to release the buffer when the throttling view is no longer using it. + */ +bool QWaylandView::discardFrontBuffers() const +{ + Q_D(const QWaylandView); + return d->discardFrontBuffers; +} + +void QWaylandView::setDiscardFrontBuffers(bool discard) +{ + Q_D(QWaylandView); + if (d->discardFrontBuffers == discard) + return; + d->discardFrontBuffers = discard; + emit discardFrontBuffersChanged(); +} + +/*! + * Returns the Wayland surface resource for this QWaylandView. + */ +struct wl_resource *QWaylandView::surfaceResource() const +{ + Q_D(const QWaylandView); + if (!d->surface) + return Q_NULLPTR; + return d->surface->resource(); +} + +QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandview.h b/src/compositor/compositor_api/qwaylandview.h new file mode 100644 index 000000000..5a820fb50 --- /dev/null +++ b/src/compositor/compositor_api/qwaylandview.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.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 QWAYLANDSURFACEVIEW_H +#define QWAYLANDSURFACEVIEW_H + +#include <QtWaylandCompositor/QWaylandBufferRef> +#include <QtWaylandCompositor/qwaylandexport.h> + +#include <QtCore/QPointF> +#include <QtCore/QObject> + +QT_BEGIN_NAMESPACE + +class QWaylandSurface; +class QWaylandViewPrivate; +class QWaylandOutput; + +class Q_COMPOSITOR_EXPORT QWaylandView : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QWaylandView) + Q_PROPERTY(QObject *renderObject READ renderObject CONSTANT) + Q_PROPERTY(QWaylandSurface *surface READ surface WRITE setSurface NOTIFY surfaceChanged) + Q_PROPERTY(QWaylandOutput *output READ output WRITE setOutput NOTIFY outputChanged) + Q_PROPERTY(bool bufferLock READ isBufferLocked WRITE setBufferLock NOTIFY bufferLockChanged) + Q_PROPERTY(bool discardFrontBuffers READ discardFrontBuffers WRITE setDiscardFrontBuffers NOTIFY discardFrontBuffersChanged) +public: + QWaylandView(QObject *renderObject = 0, QObject *parent = 0); + virtual ~QWaylandView(); + + QObject *renderObject() const; + + QWaylandSurface *surface() const; + void setSurface(QWaylandSurface *surface); + + QWaylandOutput *output() const; + void setOutput(QWaylandOutput *output); + + virtual void attach(const QWaylandBufferRef &ref, const QRegion &damage); + virtual bool advance(); + virtual void discardCurrentBuffer(); + virtual QWaylandBufferRef currentBuffer(); + virtual QRegion currentDamage(); + + bool isBufferLocked() const; + void setBufferLock(bool locked); + + bool discardFrontBuffers() const; + void setDiscardFrontBuffers(bool discard); + + struct wl_resource *surfaceResource() const; + +Q_SIGNALS: + void surfaceChanged(); + void surfaceDestroyed(); + void outputChanged(); + void bufferLockChanged(); + void discardFrontBuffersChanged(); +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/compositor/compositor_api/qwaylandview_p.h b/src/compositor/compositor_api/qwaylandview_p.h new file mode 100644 index 000000000..8c4cea085 --- /dev/null +++ b/src/compositor/compositor_api/qwaylandview_p.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** 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 QWAYLANDSURFACEVIEW_P_H +#define QWAYLANDSURFACEVIEW_P_H + +#include <QtCore/QPoint> +#include <QtCore/QMutex> +#include <QtCore/private/qobject_p.h> + +#include <QtWaylandCompositor/QWaylandBufferRef> + +// +// 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 QWaylandSurface; +class QWaylandOutput; + +class QWaylandViewPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QWaylandView) +public: + static QWaylandViewPrivate *get(QWaylandView *view) { return view->d_func(); } + + QWaylandViewPrivate() + : renderObject(Q_NULLPTR) + , surface(Q_NULLPTR) + , output(Q_NULLPTR) + , bufferLock(false) + , broadcastRequestedPositionChanged(false) + , forceAdvanceSucceed(false) + , discardFrontBuffers(false) + { } + + void markSurfaceAsDestroyed(QWaylandSurface *surface); + + QObject *renderObject; + QWaylandSurface *surface; + QWaylandOutput *output; + QPointF requestedPos; + QMutex bufferMutex; + QWaylandBufferRef currentBuffer; + QRegion currentDamage; + QWaylandBufferRef nextBuffer; + QRegion nextDamage; + bool bufferLock; + bool broadcastRequestedPositionChanged; + bool forceAdvanceSucceed; + bool discardFrontBuffers; +}; + +QT_END_NAMESPACE + +#endif /*QWAYLANDSURFACEVIEW_P_H*/ |