diff options
author | Johan Klokkhammer Helsing <johan.helsing@qt.io> | 2016-05-11 14:28:56 +0200 |
---|---|---|
committer | Johan Helsing <johan.helsing@qt.io> | 2016-05-20 12:11:17 +0000 |
commit | 5e5e866c8c1fc8234c25770d84e9591041e67d69 (patch) | |
tree | 111913497f39e6cbad7403743ab40a5d9aed734c /src | |
parent | 8817a981389b4f22a614f258f3575360645f2fd9 (diff) | |
download | qtwayland-5e5e866c8c1fc8234c25770d84e9591041e67d69.tar.gz |
Create a general ShellSurfaceItem to avoid duplication
XdgSurfaceItem and WlShellSurfaceItem have been removed in favor
of the more general ShellSurfaceItem. An XdgSurface or a WlShellSurface
can be assigned to the shellSurface property of a ShellSurfaceItem
and leaves open the possibility for additional shells.
A shared base class for QWaylandXdgSurface and QWaylandWlShellSurface
has been added which has a factory method for creating
a QWaylandQuickShellIntegration for that shell implementation.
The property "shellSurface" on the ShellSurfaceItem allows QML code to
attach to signals regardless of whether it's a WlShell or XdgShell
client. The pure-qml example has been updated to take advantage of this.
Change-Id: I9d3427586e100d6c44a24f319dd8e1486ff062ee
Reviewed-by: Giulio Camuffo <giulio.camuffo@kdab.com>
Diffstat (limited to 'src')
18 files changed, 872 insertions, 858 deletions
diff --git a/src/compositor/extensions/extensions.pri b/src/compositor/extensions/extensions.pri index 71716243..4ab26727 100644 --- a/src/compositor/extensions/extensions.pri +++ b/src/compositor/extensions/extensions.pri @@ -21,6 +21,7 @@ HEADERS += \ extensions/qwaylandwindowmanagerextension_p.h \ extensions/qwaylandxdgshell.h \ extensions/qwaylandxdgshell_p.h \ + extensions/qwaylandshellsurface.h \ SOURCES += \ extensions/qwlextendedsurface.cpp \ @@ -34,14 +35,15 @@ SOURCES += \ qtHaveModule(quick) { HEADERS += \ - extensions/qwaylandquickwlshellsurfaceitem.h \ - extensions/qwaylandquickwlshellsurfaceitem_p.h \ - extensions/qwaylandquickxdgsurfaceitem.h \ - extensions/qwaylandquickxdgsurfaceitem_p.h \ + extensions/qwaylandquickshellsurfaceitem.h \ + extensions/qwaylandquickshellsurfaceitem_p.h \ + extensions/qwaylandwlshellintegration_p.h \ + extensions/qwaylandxdgshellintegration_p.h \ SOURCES += \ - extensions/qwaylandquickwlshellsurfaceitem.cpp \ - extensions/qwaylandquickxdgsurfaceitem.cpp \ + extensions/qwaylandquickshellsurfaceitem.cpp \ + extensions/qwaylandwlshellintegration.cpp \ + extensions/qwaylandxdgshellintegration.cpp \ } diff --git a/src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp b/src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp new file mode 100644 index 00000000..4b087183 --- /dev/null +++ b/src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp @@ -0,0 +1,151 @@ +/**************************************************************************** +** +** Copyright (C) 2016 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 "qwaylandquickshellsurfaceitem.h" +#include "qwaylandquickshellsurfaceitem_p.h" + +#include <QtWaylandCompositor/QWaylandShellSurface> + +QT_BEGIN_NAMESPACE + +/*! + * \qmltype ShellSurfaceItem + * \inqmlmodule QtWayland.Compositor + * \preliminary + * \brief An item representing a WlShellSurface. + * + * This type is used to render wl_shell or xdg_shell surfaces as part of a Qt Quick + * scene. It handles moving and resizing triggered by clicking on the window decorations. + */ + +/*! + * \class QWaylandQuickShellSurfaceItem + * \inmodule QtWaylandCompositor + * \preliminary + * \brief A Qt Quick item for QWaylandShellSurface. + * + * This class is used to render wl_shell or xdg_shell surfaces as part of a Qt Quick + * scene. It handles moving and resizing triggered by clicking on the window decorations. + * + * \sa QWaylandQuickItem + */ + +/*! + * Constructs a QWaylandQuickWlShellSurfaceItem with the given \a parent. + */ +QWaylandQuickShellSurfaceItem::QWaylandQuickShellSurfaceItem(QQuickItem *parent) + : QWaylandQuickItem(*new QWaylandQuickShellSurfaceItemPrivate(), parent) +{ +} + +/*! + * \internal + */ +QWaylandQuickShellSurfaceItem::QWaylandQuickShellSurfaceItem(QWaylandQuickShellSurfaceItemPrivate &dd, QQuickItem *parent) + : QWaylandQuickItem(dd, parent) +{ +} + +/*! + * \qmlproperty object QtWaylandCompositor::ShellSurfaceItem::shellSurface + * + * This property holds the shell surface rendered by this ShellSurfaceItem. + * It may either be an XdgSurface or a WlShellSurface depending on which + * shell protocol is in use. + */ + +/*! + * \property QWaylandQuickShellSurfaceItem::shellSurface + * + * This property holds the shell surface rendered by this + * QWaylandQuickShellSurfaceItem. It may either be a QWaylandXdgSurface or a + * QWaylandWlShellSurface depending on which shell protocol is in use. + * + */ +QWaylandShellSurface *QWaylandQuickShellSurfaceItem::shellSurface() const +{ + Q_D(const QWaylandQuickShellSurfaceItem); + return d->m_shellSurface; +} + +void QWaylandQuickShellSurfaceItem::setShellSurface(QWaylandShellSurface *shellSurface) +{ + Q_D(QWaylandQuickShellSurfaceItem); + if (d->m_shellSurface == shellSurface) + return; + + d->m_shellSurface = shellSurface; + + d->m_shellIntegration = shellSurface->createIntegration(this); + emit shellSurfaceChanged(); +} + +/*! + * \property QWaylandQuickShellSurfaceItem::moveItem + * + * This property holds the move item for this QWaylandQuickShellSurfaceItem. + */ +QQuickItem *QWaylandQuickShellSurfaceItem::moveItem() const +{ + Q_D(const QWaylandQuickShellSurfaceItem); + return d->m_moveItem ? d->m_moveItem : const_cast<QWaylandQuickShellSurfaceItem *>(this); +} + +void QWaylandQuickShellSurfaceItem::setMoveItem(QQuickItem *moveItem) +{ + Q_D(QWaylandQuickShellSurfaceItem); + moveItem = moveItem ? moveItem : this; + if (this->moveItem() == moveItem) + return; + d->m_moveItem = moveItem; + moveItemChanged(); +} + +void QWaylandQuickShellSurfaceItem::mouseMoveEvent(QMouseEvent *event) +{ + Q_D(QWaylandQuickShellSurfaceItem); + if (!d->m_shellIntegration->mouseMoveEvent(event)) + QWaylandQuickItem::mouseMoveEvent(event); +} + +void QWaylandQuickShellSurfaceItem::mouseReleaseEvent(QMouseEvent *event) +{ + Q_D(QWaylandQuickShellSurfaceItem); + if (!d->m_shellIntegration->mouseReleaseEvent(event)) + QWaylandQuickItem::mouseReleaseEvent(event); +} + +QT_END_NAMESPACE diff --git a/src/compositor/extensions/qwaylandquickxdgsurfaceitem.h b/src/compositor/extensions/qwaylandquickshellsurfaceitem.h index d19d03c2..e233c99e 100644 --- a/src/compositor/extensions/qwaylandquickxdgsurfaceitem.h +++ b/src/compositor/extensions/qwaylandquickshellsurfaceitem.h @@ -34,54 +34,43 @@ ** ****************************************************************************/ -#ifndef QWAYLANDQUICKXDGSURFACEITEM_H -#define QWAYLANDQUICKXDGSURFACEITEM_H +#ifndef QWAYLANDQUICKSHELLSURFACEITEM_H +#define QWAYLANDQUICKSHELLSURFACEITEM_H +#include <QtWaylandCompositor/QWaylandCompositorExtension> #include <QtWaylandCompositor/QWaylandQuickItem> -#include <QtWaylandCompositor/QWaylandXdgSurface> QT_BEGIN_NAMESPACE -class QWaylandQuickXdgSurfaceItemPrivate; +class QWaylandQuickShellSurfaceItemPrivate; +class QWaylandShellSurface; -class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandQuickXdgSurfaceItem : public QWaylandQuickItem +class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandQuickShellSurfaceItem : public QWaylandQuickItem { Q_OBJECT - Q_DECLARE_PRIVATE(QWaylandQuickXdgSurfaceItem) - Q_PROPERTY(QWaylandXdgSurface *xdgSurface READ xdgSurface WRITE setXdgSurface NOTIFY xdgSurfaceChanged) + Q_DECLARE_PRIVATE(QWaylandQuickShellSurfaceItem) + Q_PROPERTY(QWaylandShellSurface *shellSurface READ shellSurface WRITE setShellSurface NOTIFY shellSurfaceChanged) Q_PROPERTY(QQuickItem *moveItem READ moveItem WRITE setMoveItem NOTIFY moveItemChanged) + QWaylandQuickShellSurfaceItem(QWaylandQuickShellSurfaceItemPrivate &dd, QQuickItem *parent); public: - QWaylandQuickXdgSurfaceItem(QQuickItem *parent = nullptr); + QWaylandQuickShellSurfaceItem(QQuickItem *parent = nullptr); - QWaylandXdgSurface *xdgSurface() const; - void setXdgSurface(QWaylandXdgSurface *xdgSurface); + QWaylandShellSurface *shellSurface() const; + void setShellSurface(QWaylandShellSurface *shellSurface); QQuickItem *moveItem() const; void setMoveItem(QQuickItem *moveItem); Q_SIGNALS: - void xdgSurfaceChanged(); + void shellSurfaceChanged(); void moveItemChanged(); -private Q_SLOTS: - void handleStartMove(QWaylandInputDevice *inputDevice); - void handleStartResize(QWaylandInputDevice *inputDevice, QWaylandXdgSurface::ResizeEdge edges); - void handleSetMaximized(); - void handleUnsetMaximized(); - void handleMaximizedChanged(); - void handleActivatedChanged(); - void handleSurfaceSizeChanged(); - protected: - QWaylandQuickXdgSurfaceItem(QWaylandQuickXdgSurfaceItemPrivate &dd, QQuickItem *parent); - void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE; void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE; - - void surfaceChangedEvent(QWaylandSurface *newSurface, QWaylandSurface *oldSurface) Q_DECL_OVERRIDE; }; QT_END_NAMESPACE -#endif /*QWAYLANDQUICKXDGSURFACEITEM_H*/ +#endif // QWAYLANDQUICKSHELLSURFACEITEM_H diff --git a/src/compositor/extensions/qwaylandquickshellsurfaceitem_p.h b/src/compositor/extensions/qwaylandquickshellsurfaceitem_p.h new file mode 100644 index 00000000..34771037 --- /dev/null +++ b/src/compositor/extensions/qwaylandquickshellsurfaceitem_p.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2016 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 QWAYLANDQUICKSHELLSURFACEITEM_P_H +#define QWAYLANDQUICKSHELLSURFACEITEM_P_H + +#include <QtWaylandCompositor/private/qwaylandquickitem_p.h> + +QT_BEGIN_NAMESPACE + +// +// 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. +// + +class QWaylandQuickShellIntegration; +class QWaylandShellSurface; + +class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandQuickShellSurfaceItemPrivate : public QWaylandQuickItemPrivate +{ +public: + QWaylandQuickShellSurfaceItemPrivate() + : QWaylandQuickItemPrivate() + , m_shellIntegration(nullptr) + , m_shellSurface(nullptr) + , m_moveItem(nullptr) + {} + QWaylandQuickShellIntegration *m_shellIntegration; + QWaylandShellSurface *m_shellSurface; + QQuickItem *m_moveItem; +}; + +class QWaylandQuickShellIntegration : public QObject +{ + Q_OBJECT +public: + QWaylandQuickShellIntegration(QObject *parent = nullptr) : QObject(parent) {} + virtual bool mouseMoveEvent(QMouseEvent *) { return false; } + virtual bool mouseReleaseEvent(QMouseEvent *) { return false; } +}; + +#endif // QWAYLANDQUICKSHELLSURFACEITEM_P_H diff --git a/src/compositor/extensions/qwaylandquickwlshellsurfaceitem.cpp b/src/compositor/extensions/qwaylandquickwlshellsurfaceitem.cpp deleted file mode 100644 index 393a054c..00000000 --- a/src/compositor/extensions/qwaylandquickwlshellsurfaceitem.cpp +++ /dev/null @@ -1,378 +0,0 @@ -/**************************************************************************** -** -** 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 "qwaylandquickwlshellsurfaceitem.h" -#include "qwaylandquickwlshellsurfaceitem_p.h" - -#include <QtWaylandCompositor/QWaylandCompositor> -#include <QtWaylandCompositor/QWaylandInputDevice> -#include <QGuiApplication> - -QT_BEGIN_NAMESPACE - -/*! - * \qmltype WlShellSurfaceItem - * \inqmlmodule QtWayland.Compositor - * \preliminary - * \preliminary - * \brief An item representing a WlShellSurface. - * - * This type can be used to render wl_shell_surfaces as part of a Qt Quick scene. - * It handles moving and resizing triggered by clicking on the window decorations. - */ - -/*! - * \class QWaylandQuickWlShellSurfaceItem - * \inmodule QtWaylandCompositor - * \preliminary - * \preliminary - * \brief A Qt Quick item for QWaylandWlShellSurface. - * - * This class can be used to create Qt Quick items representing wl_shell_surfaces. - * It handles moving and resizing triggered by clicking on the window decorations. - * - * \sa QWaylandQuickItem - */ - -/*! - * Constructs a QWaylandQuickWlShellSurfaceItem with the given \a parent. - */ -QWaylandQuickWlShellSurfaceItem::QWaylandQuickWlShellSurfaceItem(QQuickItem *parent) - : QWaylandQuickItem(*new QWaylandQuickWlShellSurfaceItemPrivate(), parent) -{ -} - -/*! - * \internal - */ -QWaylandQuickWlShellSurfaceItem::QWaylandQuickWlShellSurfaceItem(QWaylandQuickWlShellSurfaceItemPrivate &dd, QQuickItem *parent) - : QWaylandQuickItem(dd, parent) -{ -} - -/*! - * \qmlproperty object QtWaylandCompositor::WlShellSurfaceItem::shellSurface - * - * This property holds the wl_shell_surface rendered by this WlShellSurfaceItem. - */ - -/*! - * \property QWaylandQuickWlShellSurfaceItem::shellSurface - * - * This property holds the wl_shell_surface rendered by this QWaylandQuickWlShellSurfaceItem. - */ -QWaylandWlShellSurface *QWaylandQuickWlShellSurfaceItem::shellSurface() const -{ - Q_D(const QWaylandQuickWlShellSurfaceItem); - return d->shellSurface; -} - -void QWaylandQuickWlShellSurfaceItem::setShellSurface(QWaylandWlShellSurface *shellSurface) -{ - Q_D(QWaylandQuickWlShellSurfaceItem); - if (shellSurface == d->shellSurface) - return; - - if (d->shellSurface) { - disconnect(d->shellSurface, &QWaylandWlShellSurface::startMove, this, &QWaylandQuickWlShellSurfaceItem::handleStartMove); - disconnect(d->shellSurface, &QWaylandWlShellSurface::startResize, this, &QWaylandQuickWlShellSurfaceItem::handleStartResize); - disconnect(d->shellSurface, &QWaylandWlShellSurface::setPopup, this, &QWaylandQuickWlShellSurfaceItem::handleSetPopup); - disconnect(d->shellSurface, &QWaylandWlShellSurface::destroyed, this, &QWaylandQuickWlShellSurfaceItem::handleShellSurfaceDestroyed); - } - d->shellSurface = shellSurface; - if (d->shellSurface) { - connect(d->shellSurface, &QWaylandWlShellSurface::startMove, this, &QWaylandQuickWlShellSurfaceItem::handleStartMove); - connect(d->shellSurface, &QWaylandWlShellSurface::startResize, this, &QWaylandQuickWlShellSurfaceItem::handleStartResize); - connect(d->shellSurface, &QWaylandWlShellSurface::setPopup, this, &QWaylandQuickWlShellSurfaceItem::handleSetPopup); - connect(d->shellSurface, &QWaylandWlShellSurface::destroyed, this, &QWaylandQuickWlShellSurfaceItem::handleShellSurfaceDestroyed); - } - setSurface(shellSurface ? shellSurface->surface() : nullptr); - emit shellSurfaceChanged(); -} - -/*! - * \internal - * \property QWaylandQuickWlShellSurfaceItem::moveItem - * - * This property holds the move item for this QWaylandQuickWlShellSurfaceItem. - */ -QQuickItem *QWaylandQuickWlShellSurfaceItem::moveItem() const -{ - Q_D(const QWaylandQuickWlShellSurfaceItem); - return d->moveItem; -} - -void QWaylandQuickWlShellSurfaceItem::setMoveItem(QQuickItem *moveItem) -{ - Q_D(QWaylandQuickWlShellSurfaceItem); - if (d->moveItem == moveItem) - return; - d->moveItem = moveItem; - moveItemChanged(); -} - -/*! - * \internal - */ -void QWaylandQuickWlShellSurfaceItem::handleStartMove(QWaylandInputDevice *inputDevice) -{ - Q_D(QWaylandQuickWlShellSurfaceItem); - d->grabberState = QWaylandQuickWlShellSurfaceItemPrivate::MoveState; - d->moveState.inputDevice = inputDevice; - d->moveState.initialized = false; -} - -/*! - * \internal - */ -void QWaylandQuickWlShellSurfaceItem::handleStartResize(QWaylandInputDevice *inputDevice, QWaylandWlShellSurface::ResizeEdge edges) -{ - Q_D(QWaylandQuickWlShellSurfaceItem); - d->grabberState = QWaylandQuickWlShellSurfaceItemPrivate::ResizeState; - d->resizeState.inputDevice = inputDevice; - d->resizeState.resizeEdges = edges; - d->resizeState.initialSize = surface()->size() / d->scaleFactor(); - d->resizeState.initialized = false; -} - -/*! - * \internal - */ -void QWaylandQuickWlShellSurfaceItem::handleSetPopup(QWaylandInputDevice *inputDevice, QWaylandSurface *parent, const QPoint &relativeToParent) -{ - Q_UNUSED(inputDevice); - Q_D(QWaylandQuickWlShellSurfaceItem); - - QWaylandQuickWlShellSurfaceItem* parentItem = qobject_cast<QWaylandQuickWlShellSurfaceItem*>(parent->views().first()->renderObject()); - if (parentItem) { - // Clear all the transforms for this ShellSurfaceItem. They are not - // applicable when the item becomes a child to a surface that has its - // own transforms. Otherwise the transforms would be applied twice. - QQmlListProperty<QQuickTransform> t = transform(); - t.clear(&t); - setRotation(0); - setScale(1.0); - setX(relativeToParent.x()); - setY(relativeToParent.y()); - setParentItem(parentItem); - } - - d->setIsPopup(true); -} - -/*! - * \internal - */ -void QWaylandQuickWlShellSurfaceItem::handleShellSurfaceDestroyed() { - Q_D(QWaylandQuickWlShellSurfaceItem); - d->setIsPopup(false); - d->shellSurface = NULL; -} - -void QWaylandQuickWlShellSurfaceItem::handleSurfaceUnmapped() -{ - Q_D(QWaylandQuickWlShellSurfaceItem); - if (!d->shellSurface || !d->shellSurface->surface()->size().isEmpty()) - return; - d->setIsPopup(false); -} - -/*! - * \internal - */ -void QWaylandQuickWlShellSurfaceItem::adjustOffsetForNextFrame(const QPointF &offset) -{ - Q_D(QWaylandQuickWlShellSurfaceItem); - QQuickItem *moveItem = d->moveItem ? d->moveItem : this; - moveItem->setPosition(moveItem->position() + offset * d->scaleFactor()); -} - -/*! - * \internal - */ -void QWaylandQuickWlShellSurfaceItem::mouseMoveEvent(QMouseEvent *event) -{ - Q_D(QWaylandQuickWlShellSurfaceItem); - if (d->grabberState == QWaylandQuickWlShellSurfaceItemPrivate::ResizeState) { - Q_ASSERT(d->resizeState.inputDevice == compositor()->inputDeviceFor(event)); - if (!d->resizeState.initialized) { - d->resizeState.initialMousePos = event->windowPos(); - d->resizeState.initialized = true; - return; - } - QPointF delta = (event->windowPos() - d->resizeState.initialMousePos) / d->scaleFactor(); - QSize newSize = shellSurface()->sizeForResize(d->resizeState.initialSize, delta, d->resizeState.resizeEdges); - shellSurface()->sendConfigure(newSize, d->resizeState.resizeEdges); - } else if (d->grabberState == QWaylandQuickWlShellSurfaceItemPrivate::MoveState) { - Q_ASSERT(d->moveState.inputDevice == compositor()->inputDeviceFor(event)); - QQuickItem *moveItem = d->moveItem ? d->moveItem : this; - if (!d->moveState.initialized) { - d->moveState.initialOffset = moveItem->mapFromItem(Q_NULLPTR, event->windowPos()); - d->moveState.initialized = true; - return; - } - if (!moveItem->parentItem()) - return; - QPointF parentPos = moveItem->parentItem()->mapFromItem(Q_NULLPTR, event->windowPos()); - moveItem->setPosition(parentPos - d->moveState.initialOffset); - } else { - QWaylandQuickItem::mouseMoveEvent(event); - } -} - -/*! - * \internal - */ -void QWaylandQuickWlShellSurfaceItem::mouseReleaseEvent(QMouseEvent *event) -{ - Q_D(QWaylandQuickWlShellSurfaceItem); - if (d->grabberState != QWaylandQuickWlShellSurfaceItemPrivate::DefaultState) { - d->grabberState = QWaylandQuickWlShellSurfaceItemPrivate::DefaultState; - return; - } - QWaylandQuickItem::mouseReleaseEvent(event); -} - -/*! - * \internal - */ -void QWaylandQuickWlShellSurfaceItem::surfaceChangedEvent(QWaylandSurface *newSurface, QWaylandSurface *oldSurface) -{ - if (oldSurface) - disconnect(oldSurface, &QWaylandSurface::offsetForNextFrame, this, &QWaylandQuickWlShellSurfaceItem::adjustOffsetForNextFrame); - - if (newSurface) - connect(newSurface, &QWaylandSurface::offsetForNextFrame, this, &QWaylandQuickWlShellSurfaceItem::adjustOffsetForNextFrame); -} - -QVector<QWaylandWlShellSurface*> QWaylandQuickWlShellSurfaceItemPrivate::popupShellSurfaces; -bool QWaylandQuickWlShellSurfaceItemPrivate::eventFilterInstalled = false; -bool QWaylandQuickWlShellSurfaceItemPrivate::waitForRelease = false; - -/*! - * \internal - */ -void QWaylandQuickWlShellSurfaceItemPrivate::closePopups() -{ - if (!popupShellSurfaces.isEmpty()) { - Q_FOREACH (QWaylandWlShellSurface* shellSurface, popupShellSurfaces) { - shellSurface->sendPopupDone(); - } - popupShellSurfaces.clear(); - } -} - -bool QWaylandQuickWlShellSurfaceItem::eventFilter(QObject *receiver, QEvent *e) -{ - Q_D(QWaylandQuickWlShellSurfaceItem); - if (e->type() == QEvent::MouseButtonPress || e->type() == QEvent::MouseButtonRelease) { - QQuickItem *item = qobject_cast<QQuickItem*>(receiver); - if (!item) - return false; - - QMouseEvent *event = static_cast<QMouseEvent*>(e); - QWaylandQuickWlShellSurfaceItem *shellSurfaceItem = qobject_cast<QWaylandQuickWlShellSurfaceItem*>(item); - bool press = event->type() == QEvent::MouseButtonPress; - bool finalRelease = (event->type() == QEvent::MouseButtonRelease) && (event->buttons() == Qt::NoButton); - bool popupClient = shellSurfaceItem && shellSurfaceItem->shellSurface()->surface()->client() == shellSurface()->surface()->client(); - - if (d->waitForRelease) { - // We are eating events until all mouse buttons are released - if (finalRelease) { - d->waitForRelease = false; - d->setFilterEnabled(false); - } - return true; - } - - if (press && !popupClient) { - // The user clicked outside the active popup's client. The popups should - // be closed, but the event filter will stay to catch the release- - // event before removing itself. - d->waitForRelease = true; - d->closePopups(); - return true; - } else if (press) { - // There is a surface belonging to this client at this coordinate, so we can - // remove the event filter and let the normal event handler handle - // this event. - d->setFilterEnabled(false); - } - } - - return false; -} - -void QWaylandQuickWlShellSurfaceItemPrivate::setIsPopup(bool popup) -{ - Q_Q(QWaylandQuickWlShellSurfaceItem); - isPopup = popup; - if (popup) { - if (!eventFilterInstalled) - setFilterEnabled(true); - - if (!popupShellSurfaces.contains(shellSurface)) { - popupShellSurfaces.append(shellSurface); - QObject::connect(shellSurface->surface(), &QWaylandSurface::mappedChanged, - q, &QWaylandQuickWlShellSurfaceItem::handleSurfaceUnmapped); - } - } else { - if (shellSurface) { - popupShellSurfaces.removeOne(shellSurface); - QObject::disconnect(shellSurface->surface(), &QWaylandSurface::mappedChanged, - q, &QWaylandQuickWlShellSurfaceItem::handleSurfaceUnmapped); - } - if (!waitForRelease && eventFilterInstalled && popupShellSurfaces.isEmpty()) - setFilterEnabled(false); - } -} - -void QWaylandQuickWlShellSurfaceItemPrivate::setFilterEnabled(bool enabled) -{ - Q_Q(QWaylandQuickWlShellSurfaceItem); - static QPointer<QObject> filter; - - if (enabled && filter.isNull()) { - qGuiApp->installEventFilter(q); - filter = q; - } else if (!enabled && !filter.isNull()){ - qGuiApp->removeEventFilter(filter); - filter = nullptr; - } - eventFilterInstalled = enabled; -} - -QT_END_NAMESPACE diff --git a/src/compositor/extensions/qwaylandquickwlshellsurfaceitem.h b/src/compositor/extensions/qwaylandquickwlshellsurfaceitem.h deleted file mode 100644 index b456b95f..00000000 --- a/src/compositor/extensions/qwaylandquickwlshellsurfaceitem.h +++ /dev/null @@ -1,90 +0,0 @@ -/**************************************************************************** -** -** 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 QWAYLANDQUICKWLSHELLSURFACEITEM_H -#define QWAYLANDQUICKWLSHELLSURFACEITEM_H - -#include <QtWaylandCompositor/QWaylandCompositorExtension> -#include <QtWaylandCompositor/QWaylandQuickItem> -#include <QtWaylandCompositor/QWaylandWlShellSurface> - -QT_BEGIN_NAMESPACE - -class QWaylandQuickWlShellSurfaceItemPrivate; - -class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandQuickWlShellSurfaceItem : public QWaylandQuickItem -{ - Q_OBJECT - Q_DECLARE_PRIVATE(QWaylandQuickWlShellSurfaceItem) - Q_PROPERTY(QWaylandWlShellSurface *shellSurface READ shellSurface WRITE setShellSurface NOTIFY shellSurfaceChanged) - Q_PROPERTY(QQuickItem *moveItem READ moveItem WRITE setMoveItem NOTIFY moveItemChanged) - -public: - QWaylandQuickWlShellSurfaceItem(QQuickItem *parent = 0); - - static QWaylandQuickWlShellSurfaceItemPrivate *get(QWaylandQuickWlShellSurfaceItem *item) { return item->d_func(); } - - QWaylandWlShellSurface *shellSurface() const; - void setShellSurface(QWaylandWlShellSurface *shellSurface); - - QQuickItem *moveItem() const; - void setMoveItem(QQuickItem *moveItem); -Q_SIGNALS: - void shellSurfaceChanged(); - void moveItemChanged(); - -private Q_SLOTS: - void handleStartMove(QWaylandInputDevice *inputDevice); - void handleStartResize(QWaylandInputDevice *inputDevice, QWaylandWlShellSurface::ResizeEdge edges); - void handleSetPopup(QWaylandInputDevice *inputDevice, QWaylandSurface *parent, const QPoint &relativeToParent); - void handleShellSurfaceDestroyed(); - void adjustOffsetForNextFrame(const QPointF &offset); - - void handleSurfaceUnmapped(); -protected: - QWaylandQuickWlShellSurfaceItem(QWaylandQuickWlShellSurfaceItemPrivate &dd, QQuickItem *parent); - - void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE; - void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE; - - void surfaceChangedEvent(QWaylandSurface *newSurface, QWaylandSurface *oldSurface) Q_DECL_OVERRIDE; - - bool eventFilter(QObject *, QEvent *) Q_DECL_OVERRIDE; -}; - -QT_END_NAMESPACE - -#endif /*QWAYLANDQUICKWLSHELLSURFACEITEM_H*/ diff --git a/src/compositor/extensions/qwaylandquickxdgsurfaceitem.cpp b/src/compositor/extensions/qwaylandquickxdgsurfaceitem.cpp deleted file mode 100644 index e5d4cdbc..00000000 --- a/src/compositor/extensions/qwaylandquickxdgsurfaceitem.cpp +++ /dev/null @@ -1,287 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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 "qwaylandquickxdgsurfaceitem.h" -#include "qwaylandquickxdgsurfaceitem_p.h" - -#include <QtWaylandCompositor/QWaylandCompositor> -#include <QtWaylandCompositor/QWaylandInputDevice> - -QT_BEGIN_NAMESPACE - -/*! - * \qmltype XdgSurfaceItem - * \inqmlmodule QtWayland.Compositor - * \preliminary - * \brief An item representing a XdgSurface. - * - * This type can be used to render xdg surfaces as part of a Qt Quick scene. - * It handles moving and resizing triggered by clicking on the window decorations. - */ - -/*! - * \class QWaylandQuickXdgSurfaceItem - * \inmodule QtWaylandCompositor - * \preliminary - * \brief A Qt Quick item for QWaylandXdgSurface. - * - * This class can be used to create Qt Quick items representing xdg surfaces. - * It handles moving and resizing triggered by clicking on the window decorations. - * - * \sa QWaylandQuickItem - */ - -/*! - * Constructs a QWaylandQuickXdgSurfaceItem with the given \a parent. - */ -QWaylandQuickXdgSurfaceItem::QWaylandQuickXdgSurfaceItem(QQuickItem *parent) - : QWaylandQuickItem(*new QWaylandQuickXdgSurfaceItemPrivate(), parent) -{ -} - -/*! - * \internal - */ -QWaylandQuickXdgSurfaceItem::QWaylandQuickXdgSurfaceItem(QWaylandQuickXdgSurfaceItemPrivate &dd, QQuickItem *parent) - : QWaylandQuickItem(dd, parent) -{ -} - -/*! - * \qmlproperty object QtWaylandCompositor::XdgSurfaceItem::xdgSurface - * - * This property holds the xdg surface rendered by this XdgSurfaceItem. - */ - -/*! - * \property QWaylandQuickXdgSurfaceItem::xdgSurface - * - * This property holds the xdg surface rendered by this QWaylandQuickXdgSurfaceItem. - */ -QWaylandXdgSurface *QWaylandQuickXdgSurfaceItem::xdgSurface() const -{ - Q_D(const QWaylandQuickXdgSurfaceItem); - return d->xdgSurface; -} - -void QWaylandQuickXdgSurfaceItem::setXdgSurface(QWaylandXdgSurface *xdgSurface) -{ - Q_D(QWaylandQuickXdgSurfaceItem); - if (xdgSurface == d->xdgSurface) - return; - - if (d->xdgSurface) { - disconnect(d->xdgSurface, &QWaylandXdgSurface::startMove, this, &QWaylandQuickXdgSurfaceItem::handleStartMove); - disconnect(d->xdgSurface, &QWaylandXdgSurface::startResize, this, &QWaylandQuickXdgSurfaceItem::handleStartResize); - disconnect(d->xdgSurface, &QWaylandXdgSurface::setMaximized, this, &QWaylandQuickXdgSurfaceItem::handleSetMaximized); - disconnect(d->xdgSurface, &QWaylandXdgSurface::unsetMaximized, this, &QWaylandQuickXdgSurfaceItem::handleUnsetMaximized); - disconnect(d->xdgSurface, &QWaylandXdgSurface::maximizedChanged, this, &QWaylandQuickXdgSurfaceItem::handleMaximizedChanged); - disconnect(d->xdgSurface, &QWaylandXdgSurface::activatedChanged, this, &QWaylandQuickXdgSurfaceItem::handleActivatedChanged); - } - d->xdgSurface = xdgSurface; - if (d->xdgSurface) { - connect(d->xdgSurface, &QWaylandXdgSurface::startMove, this, &QWaylandQuickXdgSurfaceItem::handleStartMove); - connect(d->xdgSurface, &QWaylandXdgSurface::startResize, this, &QWaylandQuickXdgSurfaceItem::handleStartResize); - connect(d->xdgSurface, &QWaylandXdgSurface::setMaximized, this, &QWaylandQuickXdgSurfaceItem::handleSetMaximized); - connect(d->xdgSurface, &QWaylandXdgSurface::unsetMaximized, this, &QWaylandQuickXdgSurfaceItem::handleUnsetMaximized); - connect(d->xdgSurface, &QWaylandXdgSurface::maximizedChanged, this, &QWaylandQuickXdgSurfaceItem::handleMaximizedChanged); - connect(d->xdgSurface, &QWaylandXdgSurface::activatedChanged, this, &QWaylandQuickXdgSurfaceItem::handleActivatedChanged); - } - setSurface(xdgSurface ? xdgSurface->surface() : nullptr); - emit xdgSurfaceChanged(); -} - -/*! - * \internal - * \property QWaylandQuickXdgSurfaceItem::moveItem - * - * This property holds the move item for this QWaylandQuickXdgSurfaceItem. - */ -QQuickItem *QWaylandQuickXdgSurfaceItem::moveItem() const -{ - Q_D(const QWaylandQuickXdgSurfaceItem); - return d->moveItem; -} - -void QWaylandQuickXdgSurfaceItem::setMoveItem(QQuickItem *moveItem) -{ - Q_D(QWaylandQuickXdgSurfaceItem); - if (d->moveItem == moveItem) - return; - d->moveItem = moveItem; - moveItemChanged(); -} - -/*! - * \internal - */ -void QWaylandQuickXdgSurfaceItem::handleStartMove(QWaylandInputDevice *inputDevice) -{ - Q_D(QWaylandQuickXdgSurfaceItem); - d->grabberState = QWaylandQuickXdgSurfaceItemPrivate::MoveState; - d->moveState.inputDevice = inputDevice; - d->moveState.initialized = false; -} - -/*! - * \internal - */ -void QWaylandQuickXdgSurfaceItem::handleStartResize(QWaylandInputDevice *inputDevice, QWaylandXdgSurface::ResizeEdge edges) -{ - Q_D(QWaylandQuickXdgSurfaceItem); - d->grabberState = QWaylandQuickXdgSurfaceItemPrivate::ResizeState; - d->resizeState.inputDevice = inputDevice; - d->resizeState.resizeEdges = edges; - d->resizeState.initialWindowSize = xdgSurface()->windowGeometry().size(); - d->resizeState.initialPosition = position(); - d->resizeState.initialSurfaceSize = surface()->size(); - d->resizeState.initialized = false; -} - -void QWaylandQuickXdgSurfaceItem::handleSetMaximized() -{ - Q_D(QWaylandQuickXdgSurfaceItem); - - d->maximizeState.initialWindowSize = xdgSurface()->windowGeometry().size(); - d->maximizeState.initialPosition = position(); - - QWaylandOutput *output = compositor()->outputs().first(); - xdgSurface()->requestMaximized(output->geometry().size() / output->scaleFactor()); -} - -void QWaylandQuickXdgSurfaceItem::handleUnsetMaximized() -{ - Q_D(QWaylandQuickXdgSurfaceItem); - xdgSurface()->requestUnMaximized(d->maximizeState.initialWindowSize); -} - -void QWaylandQuickXdgSurfaceItem::handleMaximizedChanged() -{ - Q_D(QWaylandQuickXdgSurfaceItem); - if (xdgSurface()->maximized()) { - QWaylandOutput *output = compositor()->outputs().first(); - setPosition(output->geometry().topLeft()); - } else { - setPosition(d->maximizeState.initialPosition); - } -} - -void QWaylandQuickXdgSurfaceItem::handleActivatedChanged() -{ - if (xdgSurface()->activated()) - raise(); -} - -void QWaylandQuickXdgSurfaceItem::handleSurfaceSizeChanged() -{ - Q_D(QWaylandQuickXdgSurfaceItem); - if (d->grabberState == QWaylandQuickXdgSurfaceItemPrivate::ResizeState) { - float x = d->resizeState.initialPosition.x(); - float y = d->resizeState.initialPosition.y(); - if (d->resizeState.resizeEdges & QWaylandXdgSurface::ResizeEdge::TopEdge) - y += d->resizeState.initialSurfaceSize.height() - surface()->size().height(); - - if (d->resizeState.resizeEdges & QWaylandXdgSurface::ResizeEdge::LeftEdge) - x += d->resizeState.initialSurfaceSize.width() - surface()->size().width(); - setPosition(QPoint(x,y)); - } -} - -/*! - * \internal - */ -void QWaylandQuickXdgSurfaceItem::mouseMoveEvent(QMouseEvent *event) -{ - Q_D(QWaylandQuickXdgSurfaceItem); - if (d->grabberState == QWaylandQuickXdgSurfaceItemPrivate::ResizeState) { - Q_ASSERT(d->resizeState.inputDevice == compositor()->inputDeviceFor(event)); - if (!d->resizeState.initialized) { - d->resizeState.initialMousePos = event->windowPos(); - d->resizeState.initialized = true; - return; - } - QPointF delta = (event->windowPos() - d->resizeState.initialMousePos) / d->scaleFactor(); - QSize newSize = xdgSurface()->sizeForResize(d->resizeState.initialWindowSize, delta, d->resizeState.resizeEdges); - xdgSurface()->requestResizing(newSize); - } else if (d->grabberState == QWaylandQuickXdgSurfaceItemPrivate::MoveState) { - Q_ASSERT(d->moveState.inputDevice == compositor()->inputDeviceFor(event)); - QQuickItem *moveItem = d->moveItem ? d->moveItem : this; - if (!d->moveState.initialized) { - d->moveState.initialOffset = moveItem->mapFromItem(Q_NULLPTR, event->windowPos()); - d->moveState.initialized = true; - return; - } - if (!moveItem->parentItem()) - return; - QPointF parentPos = moveItem->parentItem()->mapFromItem(Q_NULLPTR, event->windowPos()); - moveItem->setPosition(parentPos - d->moveState.initialOffset); - } else { - QWaylandQuickItem::mouseMoveEvent(event); - } -} - -/*! - * \internal - */ -void QWaylandQuickXdgSurfaceItem::mouseReleaseEvent(QMouseEvent *event) -{ - Q_D(QWaylandQuickXdgSurfaceItem); - if (d->grabberState == QWaylandQuickXdgSurfaceItemPrivate::ResizeState) { - QPointF delta = (event->windowPos() - d->resizeState.initialMousePos) / d->scaleFactor(); - QSize newSize = xdgSurface()->sizeForResize(d->resizeState.initialWindowSize, delta, d->resizeState.resizeEdges); - xdgSurface()->requestUnMaximized(newSize); - d->grabberState = QWaylandQuickXdgSurfaceItemPrivate::DefaultState; - return; - } else if (d->grabberState == QWaylandQuickXdgSurfaceItemPrivate::MoveState) { - d->grabberState = QWaylandQuickXdgSurfaceItemPrivate::DefaultState; - return; - } - QWaylandQuickItem::mouseReleaseEvent(event); -} - -/*! - * \internal - */ -void QWaylandQuickXdgSurfaceItem::surfaceChangedEvent(QWaylandSurface *newSurface, QWaylandSurface *oldSurface) -{ - if (oldSurface) - disconnect(oldSurface, &QWaylandSurface::sizeChanged, this, &QWaylandQuickXdgSurfaceItem::handleSurfaceSizeChanged); - - if (newSurface) - connect(newSurface, &QWaylandSurface::sizeChanged, this, &QWaylandQuickXdgSurfaceItem::handleSurfaceSizeChanged); -} - -QT_END_NAMESPACE diff --git a/src/compositor/extensions/qwaylandshellsurface.h b/src/compositor/extensions/qwaylandshellsurface.h new file mode 100644 index 00000000..1e9fcb5a --- /dev/null +++ b/src/compositor/extensions/qwaylandshellsurface.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2016 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 QWAYLANDSHELLSURFACE_H +#define QWAYLANDSHELLSURFACE_H + +#include <QtWaylandCompositor/QWaylandCompositorExtension> + +QT_BEGIN_NAMESPACE + +class QWaylandQuickShellIntegration; +class QWaylandQuickShellSurfaceItem; +class QWaylandShellSurfacePrivate; +class QWaylandShellSurfaceTemplatePrivate; + +class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandShellSurface : public QWaylandCompositorExtension +{ + Q_OBJECT +public: + virtual QWaylandQuickShellIntegration *createIntegration(QWaylandQuickShellSurfaceItem *item) = 0; + QWaylandShellSurface(QWaylandObject *waylandObject) : QWaylandCompositorExtension(waylandObject) {} + +protected: + QWaylandShellSurface(QWaylandCompositorExtensionPrivate &dd) : QWaylandCompositorExtension(dd){} + QWaylandShellSurface(QWaylandObject *container, QWaylandCompositorExtensionPrivate &dd) : QWaylandCompositorExtension(container, dd) {} +}; + +template <typename T> +class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandShellSurfaceTemplate : public QWaylandShellSurface +{ +public: + QWaylandShellSurfaceTemplate(QWaylandObject *container) + : QWaylandShellSurface(container) + { } + + const struct wl_interface *extensionInterface() const Q_DECL_OVERRIDE + { + return T::interface(); + } + + static T *findIn(QWaylandObject *container) + { + if (!container) return nullptr; + return qobject_cast<T *>(container->extension(T::interfaceName())); + } + +protected: + QWaylandShellSurfaceTemplate(QWaylandCompositorExtensionPrivate &dd) + : QWaylandShellSurface(dd) + { } + + QWaylandShellSurfaceTemplate(QWaylandObject *container, QWaylandCompositorExtensionPrivate &dd) + : QWaylandShellSurface(container,dd) + { } +}; + +QT_END_NAMESPACE + +#endif // QWAYLANDSHELLSURFACE_H diff --git a/src/compositor/extensions/qwaylandwlshell.cpp b/src/compositor/extensions/qwaylandwlshell.cpp index ecd206f8..4e993768 100644 --- a/src/compositor/extensions/qwaylandwlshell.cpp +++ b/src/compositor/extensions/qwaylandwlshell.cpp @@ -38,6 +38,8 @@ #include "qwaylandwlshell.h" #include "qwaylandwlshell_p.h" +#include "qwaylandwlshellintegration_p.h" + #include <QtWaylandCompositor/QWaylandCompositor> #include <QtWaylandCompositor/QWaylandView> #include <QtWaylandCompositor/QWaylandOutput> @@ -370,7 +372,7 @@ QByteArray QWaylandWlShell::interfaceName() * Constructs a QWaylandWlShellSurface. */ QWaylandWlShellSurface::QWaylandWlShellSurface() - : QWaylandCompositorExtensionTemplate<QWaylandWlShellSurface>(*new QWaylandWlShellSurfacePrivate) + : QWaylandShellSurfaceTemplate<QWaylandWlShellSurface>(*new QWaylandWlShellSurfacePrivate) { } @@ -378,7 +380,7 @@ QWaylandWlShellSurface::QWaylandWlShellSurface() * Constructs a QWaylandWlShellSurface for \a surface and initializes it with the given \a shell and \a resource. */ QWaylandWlShellSurface::QWaylandWlShellSurface(QWaylandWlShell *shell, QWaylandSurface *surface, const QWaylandResource &res) - : QWaylandCompositorExtensionTemplate<QWaylandWlShellSurface>(*new QWaylandWlShellSurfacePrivate) + : QWaylandShellSurfaceTemplate<QWaylandWlShellSurface>(*new QWaylandWlShellSurfacePrivate) { initialize(shell, surface, res); } @@ -408,7 +410,7 @@ void QWaylandWlShellSurface::initialize(QWaylandWlShell *shell, QWaylandSurface */ void QWaylandWlShellSurface::initialize() { - QWaylandCompositorExtensionTemplate::initialize(); + QWaylandCompositorExtension::initialize(); } const struct wl_interface *QWaylandWlShellSurface::interface() @@ -494,6 +496,11 @@ void QWaylandWlShellSurface::sendPopupDone() d->send_popup_done(); } +QWaylandQuickShellIntegration *QWaylandWlShellSurface::createIntegration(QWaylandQuickShellSurfaceItem *item) +{ + return new QtWayland::WlShellIntegration(item); +} + /*! * \qmlproperty object QtWaylandCompositor::WlShellSurface::surface * diff --git a/src/compositor/extensions/qwaylandwlshell.h b/src/compositor/extensions/qwaylandwlshell.h index 93022a4f..441c5452 100644 --- a/src/compositor/extensions/qwaylandwlshell.h +++ b/src/compositor/extensions/qwaylandwlshell.h @@ -39,6 +39,7 @@ #include <QtWaylandCompositor/QWaylandCompositorExtension> #include <QtWaylandCompositor/QWaylandResource> +#include <QtWaylandCompositor/QWaylandShellSurface> #include <QtCore/QSize> @@ -71,7 +72,7 @@ Q_SIGNALS: void shellSurfaceCreated(QWaylandWlShellSurface *shellSurface); }; -class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandWlShellSurface : public QWaylandCompositorExtensionTemplate<QWaylandWlShellSurface> +class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandWlShellSurface : public QWaylandShellSurfaceTemplate<QWaylandWlShellSurface> { Q_OBJECT Q_DECLARE_PRIVATE(QWaylandWlShellSurface) @@ -130,6 +131,8 @@ public: Q_INVOKABLE void sendConfigure(const QSize &size, ResizeEdge edges); Q_INVOKABLE void sendPopupDone(); + QWaylandQuickShellIntegration *createIntegration(QWaylandQuickShellSurfaceItem *item) Q_DECL_OVERRIDE; + public Q_SLOTS: void ping(); diff --git a/src/compositor/extensions/qwaylandwlshellintegration.cpp b/src/compositor/extensions/qwaylandwlshellintegration.cpp new file mode 100644 index 00000000..8eb0ba3b --- /dev/null +++ b/src/compositor/extensions/qwaylandwlshellintegration.cpp @@ -0,0 +1,249 @@ +/**************************************************************************** +** +** Copyright (C) 2016 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 "qwaylandwlshellintegration_p.h" + +#include <QtWaylandCompositor/QWaylandCompositor> +#include <QtWaylandCompositor/QWaylandWlShellSurface> +#include <QtWaylandCompositor/QWaylandQuickShellSurfaceItem> +#include <QtWaylandCompositor/QWaylandInputDevice> +#include <QGuiApplication> + +namespace QtWayland { + +WlShellIntegration::WlShellIntegration(QWaylandQuickShellSurfaceItem *item) + : QWaylandQuickShellIntegration(item) + , m_item(item) + , m_shellSurface(qobject_cast<QWaylandWlShellSurface *>(item->shellSurface())) + , grabberState(GrabberState::Default) + , isPopup(false) +{ + m_item->setSurface(m_shellSurface->surface()); + connect(m_shellSurface, &QWaylandWlShellSurface::startMove, this, &WlShellIntegration::handleStartMove); + connect(m_shellSurface, &QWaylandWlShellSurface::startResize, this, &WlShellIntegration::handleStartResize); + connect(m_shellSurface->surface(), &QWaylandSurface::offsetForNextFrame, this, &WlShellIntegration::adjustOffsetForNextFrame); + connect(m_shellSurface, &QWaylandWlShellSurface::setPopup, this, &WlShellIntegration::handleSetPopup); + connect(m_shellSurface, &QWaylandWlShellSurface::destroyed, this, &WlShellIntegration::handleShellSurfaceDestroyed); +} + +void WlShellIntegration::handleStartMove(QWaylandInputDevice *inputDevice) +{ + grabberState = GrabberState::Move; + moveState.inputDevice = inputDevice; + moveState.initialized = false; +} + +void WlShellIntegration::handleStartResize(QWaylandInputDevice *inputDevice, QWaylandWlShellSurface::ResizeEdge edges) +{ + grabberState = GrabberState::Resize; + resizeState.inputDevice = inputDevice; + resizeState.resizeEdges = edges; + float scaleFactor = m_item->view()->output()->scaleFactor(); + resizeState.initialSize = m_shellSurface->surface()->size() / scaleFactor; + resizeState.initialized = false; +} + +void WlShellIntegration::handleSetPopup(QWaylandInputDevice *inputDevice, QWaylandSurface *parent, const QPoint &relativeToParent) +{ + Q_UNUSED(inputDevice); + + QWaylandQuickShellSurfaceItem* parentItem = qobject_cast<QWaylandQuickShellSurfaceItem*>(parent->views().first()->renderObject()); + if (parentItem) { + // Clear all the transforms for this ShellSurfaceItem. They are not + // applicable when the item becomes a child to a surface that has its + // own transforms. Otherwise the transforms would be applied twice. + QQmlListProperty<QQuickTransform> t = m_item->transform(); + t.clear(&t); + m_item->setRotation(0); + m_item->setScale(1.0); + m_item->setX(relativeToParent.x()); + m_item->setY(relativeToParent.y()); + m_item->setParentItem(parentItem); + } + + setIsPopup(true); +} + +void WlShellIntegration::handleShellSurfaceDestroyed() { + setIsPopup(false); + m_shellSurface = nullptr; +} + +void WlShellIntegration::handleSurfaceUnmapped() +{ + if (!m_shellSurface || !m_shellSurface->surface()->size().isEmpty()) + return; + setIsPopup(false); +} + +void WlShellIntegration::adjustOffsetForNextFrame(const QPointF &offset) +{ + float scaleFactor = m_item->view()->output()->scaleFactor(); + QQuickItem *moveItem = m_item->moveItem(); + moveItem->setPosition(moveItem->position() + offset * scaleFactor); +} + +bool WlShellIntegration::mouseMoveEvent(QMouseEvent *event) +{ + if (grabberState == GrabberState::Resize) { + Q_ASSERT(resizeState.inputDevice == m_item->compositor()->inputDeviceFor(event)); + if (!resizeState.initialized) { + resizeState.initialMousePos = event->windowPos(); + resizeState.initialized = true; + return true; + } + float scaleFactor = m_item->view()->output()->scaleFactor(); + QPointF delta = (event->windowPos() - resizeState.initialMousePos) / scaleFactor; + QSize newSize = m_shellSurface->sizeForResize(resizeState.initialSize, delta, resizeState.resizeEdges); + m_shellSurface->sendConfigure(newSize, resizeState.resizeEdges); + } else if (grabberState == GrabberState::Move) { + Q_ASSERT(moveState.inputDevice == m_item->compositor()->inputDeviceFor(event)); + QQuickItem *moveItem = m_item->moveItem(); + if (!moveState.initialized) { + moveState.initialOffset = moveItem->mapFromItem(nullptr, event->windowPos()); + moveState.initialized = true; + return true; + } + if (!moveItem->parentItem()) + return true; + QPointF parentPos = moveItem->parentItem()->mapFromItem(nullptr, event->windowPos()); + moveItem->setPosition(parentPos - moveState.initialOffset); + } + return false; +} + +bool WlShellIntegration::mouseReleaseEvent(QMouseEvent *event) +{ + Q_UNUSED(event); + if (grabberState != GrabberState::Default) { + grabberState = GrabberState::Default; + return true; + } + return false; +} + +QVector<QWaylandWlShellSurface*> WlShellIntegration::popupShellSurfaces; +bool WlShellIntegration::eventFilterInstalled = false; +bool WlShellIntegration::waitForRelease = false; + +void WlShellIntegration::closePopups() +{ + if (!popupShellSurfaces.isEmpty()) { + Q_FOREACH (QWaylandWlShellSurface* shellSurface, popupShellSurfaces) { + shellSurface->sendPopupDone(); + } + popupShellSurfaces.clear(); + } +} + +bool WlShellIntegration::eventFilter(QObject *receiver, QEvent *e) +{ + if (e->type() == QEvent::MouseButtonPress || e->type() == QEvent::MouseButtonRelease) { + QQuickItem *item = qobject_cast<QQuickItem*>(receiver); + if (!item) + return false; + + QMouseEvent *event = static_cast<QMouseEvent*>(e); + QWaylandQuickShellSurfaceItem *shellSurfaceItem = qobject_cast<QWaylandQuickShellSurfaceItem*>(item); + bool press = event->type() == QEvent::MouseButtonPress; + bool finalRelease = (event->type() == QEvent::MouseButtonRelease) && (event->buttons() == Qt::NoButton); + bool popupClient = shellSurfaceItem && shellSurfaceItem->surface()->client() == m_shellSurface->surface()->client(); + + if (waitForRelease) { + // We are eating events until all mouse buttons are released + if (finalRelease) { + waitForRelease = false; + setFilterEnabled(false); + } + return true; + } + + if (press && !popupClient) { + // The user clicked outside the active popup's client. The popups should + // be closed, but the event filter will stay to catch the release- + // event before removing itself. + waitForRelease = true; + closePopups(); + return true; + } else if (press) { + // There is a surface belonging to this client at this coordinate, so we can + // remove the event filter and let the normal event handler handle + // this event. + setFilterEnabled(false); + } + } + + return false; +} + +void WlShellIntegration::setIsPopup(bool popup) +{ + isPopup = popup; + if (popup) { + if (!eventFilterInstalled) + setFilterEnabled(true); + + if (!popupShellSurfaces.contains(m_shellSurface)) { + popupShellSurfaces.append(m_shellSurface); + QObject::connect(m_shellSurface->surface(), &QWaylandSurface::mappedChanged, + this, &WlShellIntegration::handleSurfaceUnmapped); + } + } else { + if (m_shellSurface) { + popupShellSurfaces.removeOne(m_shellSurface); + QObject::disconnect(m_shellSurface->surface(), &QWaylandSurface::mappedChanged, + this, &WlShellIntegration::handleSurfaceUnmapped); + } + if (!waitForRelease && eventFilterInstalled && popupShellSurfaces.isEmpty()) + setFilterEnabled(false); + } +} + +void WlShellIntegration::setFilterEnabled(bool enabled) +{ + static QPointer<QObject> filter; + + if (enabled && filter.isNull()) { + qGuiApp->installEventFilter(this); + filter = this; + } else if (!enabled && !filter.isNull()){ + qGuiApp->removeEventFilter(filter); + filter = nullptr; + } + eventFilterInstalled = enabled; +} + +} diff --git a/src/compositor/extensions/qwaylandquickwlshellsurfaceitem_p.h b/src/compositor/extensions/qwaylandwlshellintegration_p.h index c4adb28d..48607720 100644 --- a/src/compositor/extensions/qwaylandquickwlshellsurfaceitem_p.h +++ b/src/compositor/extensions/qwaylandwlshellintegration_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtWaylandCompositor module of the Qt Toolkit. @@ -34,10 +34,12 @@ ** ****************************************************************************/ -#ifndef QWAYLANDQUICKWLSHELLSURFACEITEM_P_H -#define QWAYLANDQUICKWLSHELLSURFACEITEM_P_H +#ifndef QWAYLANDWLSHELLINTEGRATION_H +#define QWAYLANDWLSHELLINTEGRATION_H -#include <QtWaylandCompositor/private/qwaylandquickitem_p.h> +#include <QtWaylandCompositor/private/qwaylandquickshellsurfaceitem_p.h> + +#include <QtWaylandCompositor/QWaylandWlShellSurface> QT_BEGIN_NAMESPACE @@ -52,40 +54,45 @@ QT_BEGIN_NAMESPACE // We mean it. // -class QWaylandQuickWlShellSurfaceItem; +namespace QtWayland { -class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandQuickWlShellSurfaceItemPrivate : public QWaylandQuickItemPrivate +class WlShellIntegration : public QWaylandQuickShellIntegration { - Q_DECLARE_PUBLIC(QWaylandQuickWlShellSurfaceItem) + Q_OBJECT public: - enum GrabberState { - DefaultState, - ResizeState, - MoveState + WlShellIntegration(QWaylandQuickShellSurfaceItem *item); + bool mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE; + bool mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE; + +private Q_SLOTS: + void handleStartMove(QWaylandInputDevice *inputDevice); + void handleStartResize(QWaylandInputDevice *inputDevice, QWaylandWlShellSurface::ResizeEdge edges); + void handleSetPopup(QWaylandInputDevice *inputDevice, QWaylandSurface *parent, const QPoint &relativeToParent); + void handleShellSurfaceDestroyed(); + void handleSurfaceUnmapped(); + void adjustOffsetForNextFrame(const QPointF &offset); + +private: + enum class GrabberState { + Default, + Resize, + Move }; - QWaylandQuickWlShellSurfaceItemPrivate() - : QWaylandQuickItemPrivate() - , shellSurface(Q_NULLPTR) - , moveItem(Q_NULLPTR) - , grabberState(DefaultState) - , isPopup(false) - {} + bool eventFilter(QObject *, QEvent *) Q_DECL_OVERRIDE; void setIsPopup(bool popup); void setFilterEnabled(bool enabled); static void closePopups(); - QWaylandWlShellSurface *shellSurface; - QQuickItem *moveItem; - + QWaylandQuickShellSurfaceItem *m_item; + QWaylandWlShellSurface *m_shellSurface; GrabberState grabberState; struct { QWaylandInputDevice *inputDevice; QPointF initialOffset; bool initialized; } moveState; - struct { QWaylandInputDevice *inputDevice; QWaylandWlShellSurface::ResizeEdge resizeEdges; @@ -100,6 +107,8 @@ public: bool isPopup; }; +} + QT_END_NAMESPACE -#endif /*QWAYLANDQUICKWLSHELLSURFACEITEM_P_H*/ +#endif // QWAYLANDWLSHELLINTEGRATION_H diff --git a/src/compositor/extensions/qwaylandxdgshell.cpp b/src/compositor/extensions/qwaylandxdgshell.cpp index a392ef63..dfc68e25 100644 --- a/src/compositor/extensions/qwaylandxdgshell.cpp +++ b/src/compositor/extensions/qwaylandxdgshell.cpp @@ -36,6 +36,7 @@ #include "qwaylandxdgshell.h" #include "qwaylandxdgshell_p.h" +#include "qwaylandxdgshellintegration_p.h" #include <QtWaylandCompositor/QWaylandCompositor> #include <QtWaylandCompositor/QWaylandSurface> @@ -592,7 +593,7 @@ void QWaylandXdgShell::handleFocusChanged(QWaylandSurface *newSurface, QWaylandS * Constructs a QWaylandXdgSurface. */ QWaylandXdgSurface::QWaylandXdgSurface() - : QWaylandCompositorExtensionTemplate<QWaylandXdgSurface>(*new QWaylandXdgSurfacePrivate) + : QWaylandShellSurfaceTemplate<QWaylandXdgSurface>(*new QWaylandXdgSurfacePrivate) { } @@ -601,7 +602,7 @@ QWaylandXdgSurface::QWaylandXdgSurface() * given \a xdgShell, \a surface and \a resource. */ QWaylandXdgSurface::QWaylandXdgSurface(QWaylandXdgShell *xdgShell, QWaylandSurface *surface, const QWaylandResource &res) - : QWaylandCompositorExtensionTemplate<QWaylandXdgSurface>(*new QWaylandXdgSurfacePrivate) + : QWaylandShellSurfaceTemplate<QWaylandXdgSurface>(*new QWaylandXdgSurfacePrivate) { initialize(xdgShell, surface, res); } @@ -636,7 +637,7 @@ void QWaylandXdgSurface::initialize(QWaylandXdgShell *xdgShell, QWaylandSurface */ void QWaylandXdgSurface::initialize() { - QWaylandCompositorExtensionTemplate::initialize(); + QWaylandCompositorExtension::initialize(); } QList<int> QWaylandXdgSurface::statesAsInts() const @@ -917,6 +918,11 @@ uint QWaylandXdgSurface::requestResizing(const QSize &maxSize) return sendConfigure(maxSize, conf.states); } +QWaylandQuickShellIntegration *QWaylandXdgSurface::createIntegration(QWaylandQuickShellSurfaceItem *item) +{ + return new QtWayland::XdgShellIntegration(item); +} + /*! * \class QWaylandXdgPopup * \inmodule QtWaylandCompositor diff --git a/src/compositor/extensions/qwaylandxdgshell.h b/src/compositor/extensions/qwaylandxdgshell.h index c994d993..c01726ac 100644 --- a/src/compositor/extensions/qwaylandxdgshell.h +++ b/src/compositor/extensions/qwaylandxdgshell.h @@ -39,6 +39,7 @@ #include <QtWaylandCompositor/QWaylandCompositorExtension> #include <QtWaylandCompositor/QWaylandResource> +#include <QtWaylandCompositor/QWaylandShellSurface> #include <QtCore/QRect> @@ -88,7 +89,7 @@ private Q_SLOTS: }; -class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandXdgSurface : public QWaylandCompositorExtensionTemplate<QWaylandXdgSurface> +class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandXdgSurface : public QWaylandShellSurfaceTemplate<QWaylandXdgSurface> { Q_OBJECT Q_DECLARE_PRIVATE(QWaylandXdgSurface) @@ -158,6 +159,8 @@ public: Q_INVOKABLE uint requestFullscreen(const QSize &size); Q_INVOKABLE uint requestResizing(const QSize &maxSize); + QWaylandQuickShellIntegration *createIntegration(QWaylandQuickShellSurfaceItem *item) Q_DECL_OVERRIDE; + Q_SIGNALS: void surfaceChanged(); void titleChanged(); diff --git a/src/compositor/extensions/qwaylandxdgshellintegration.cpp b/src/compositor/extensions/qwaylandxdgshellintegration.cpp new file mode 100644 index 00000000..3a22cce0 --- /dev/null +++ b/src/compositor/extensions/qwaylandxdgshellintegration.cpp @@ -0,0 +1,169 @@ +/**************************************************************************** +** +** Copyright (C) 2016 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 "qwaylandxdgshellintegration_p.h" + +#include <QtWaylandCompositor/QWaylandQuickShellSurfaceItem> +#include <QtWaylandCompositor/QWaylandCompositor> +#include <QtWaylandCompositor/QWaylandInputDevice> +#include <QMouseEvent> + +namespace QtWayland { + +XdgShellIntegration::XdgShellIntegration(QWaylandQuickShellSurfaceItem *item) + : QWaylandQuickShellIntegration(item) + , m_item(item) + , m_xdgSurface(qobject_cast<QWaylandXdgSurface *>(item->shellSurface())) + , grabberState(GrabberState::Default) +{ + m_item->setSurface(m_xdgSurface->surface()); + connect(m_xdgSurface, &QWaylandXdgSurface::startMove, this, &XdgShellIntegration::handleStartMove); + connect(m_xdgSurface, &QWaylandXdgSurface::startResize, this, &XdgShellIntegration::handleStartResize); + connect(m_xdgSurface, &QWaylandXdgSurface::setMaximized, this, &XdgShellIntegration::handleSetMaximized); + connect(m_xdgSurface, &QWaylandXdgSurface::unsetMaximized, this, &XdgShellIntegration::handleUnsetMaximized); + connect(m_xdgSurface, &QWaylandXdgSurface::maximizedChanged, this, &XdgShellIntegration::handleMaximizedChanged); + connect(m_xdgSurface, &QWaylandXdgSurface::activatedChanged, this, &XdgShellIntegration::handleActivatedChanged); + connect(m_xdgSurface->surface(), &QWaylandSurface::sizeChanged, this, &XdgShellIntegration::handleSurfaceSizeChanged); +} + +bool XdgShellIntegration::mouseMoveEvent(QMouseEvent *event) +{ + if (grabberState == GrabberState::Resize) { + Q_ASSERT(resizeState.inputDevice == m_item->compositor()->inputDeviceFor(event)); + if (!resizeState.initialized) { + resizeState.initialMousePos = event->windowPos(); + resizeState.initialized = true; + return true; + } + float scaleFactor = m_item->view()->output()->scaleFactor(); + QPointF delta = (event->windowPos() - resizeState.initialMousePos) / scaleFactor; + QSize newSize = m_xdgSurface->sizeForResize(resizeState.initialWindowSize, delta, resizeState.resizeEdges); + m_xdgSurface->requestResizing(newSize); + } else if (grabberState == GrabberState::Move) { + Q_ASSERT(moveState.inputDevice == m_item->compositor()->inputDeviceFor(event)); + QQuickItem *moveItem = m_item->moveItem(); + if (!moveState.initialized) { + moveState.initialOffset = moveItem->mapFromItem(nullptr, event->windowPos()); + moveState.initialized = true; + return true; + } + if (!moveItem->parentItem()) + return true; + QPointF parentPos = moveItem->parentItem()->mapFromItem(nullptr, event->windowPos()); + moveItem->setPosition(parentPos - moveState.initialOffset); + } + return false; +} + +bool XdgShellIntegration::mouseReleaseEvent(QMouseEvent *event) +{ + if (grabberState == GrabberState::Resize) { + float scaleFactor = m_item->view()->output()->scaleFactor(); + QPointF delta = (event->windowPos() - resizeState.initialMousePos) / scaleFactor; + QSize newSize = m_xdgSurface->sizeForResize(resizeState.initialWindowSize, delta, resizeState.resizeEdges); + m_xdgSurface->requestUnMaximized(newSize); + grabberState = GrabberState::Default; + return true; + } else if (grabberState == GrabberState::Move) { + grabberState = GrabberState::Default; + return true; + } + return false; +} + +void XdgShellIntegration::handleStartMove(QWaylandInputDevice *inputDevice) +{ + grabberState = GrabberState::Move; + moveState.inputDevice = inputDevice; + moveState.initialized = false; +} + +void XdgShellIntegration::handleStartResize(QWaylandInputDevice *inputDevice, QWaylandXdgSurface::ResizeEdge edges) +{ + grabberState = GrabberState::Resize; + resizeState.inputDevice = inputDevice; + resizeState.resizeEdges = edges; + resizeState.initialWindowSize = m_xdgSurface->windowGeometry().size(); + resizeState.initialPosition = m_item->position(); + resizeState.initialSurfaceSize = m_item->surface()->size(); + resizeState.initialized = false; +} + +void XdgShellIntegration::handleSetMaximized() +{ + maximizeState.initialWindowSize = m_xdgSurface->windowGeometry().size(); + maximizeState.initialPosition = m_item->position(); + + QWaylandOutput *output = m_item->compositor()->outputs().first(); + m_xdgSurface->requestMaximized(output->geometry().size() / output->scaleFactor()); +} + +void XdgShellIntegration::handleUnsetMaximized() +{ + m_xdgSurface->requestUnMaximized(maximizeState.initialWindowSize); +} + +void XdgShellIntegration::handleMaximizedChanged() +{ + if (m_xdgSurface->maximized()) { + QWaylandOutput *output = m_item->compositor()->outputs().first(); + m_item->setPosition(output->geometry().topLeft()); + } else { + m_item->setPosition(maximizeState.initialPosition); + } +} + +void XdgShellIntegration::handleActivatedChanged() +{ + if (m_xdgSurface->activated()) + m_item->raise(); +} + +void XdgShellIntegration::handleSurfaceSizeChanged() +{ + if (grabberState == GrabberState::Resize) { + qreal x = resizeState.initialPosition.x(); + qreal y = resizeState.initialPosition.y(); + if (resizeState.resizeEdges & QWaylandXdgSurface::ResizeEdge::TopEdge) + y += resizeState.initialSurfaceSize.height() - m_item->surface()->size().height(); + + if (resizeState.resizeEdges & QWaylandXdgSurface::ResizeEdge::LeftEdge) + x += resizeState.initialSurfaceSize.width() - m_item->surface()->size().width(); + m_item->setPosition(QPointF(x, y)); + } +} + +} diff --git a/src/compositor/extensions/qwaylandquickxdgsurfaceitem_p.h b/src/compositor/extensions/qwaylandxdgshellintegration_p.h index 4ac2853d..df2fa8b8 100644 --- a/src/compositor/extensions/qwaylandquickxdgsurfaceitem_p.h +++ b/src/compositor/extensions/qwaylandxdgshellintegration_p.h @@ -34,10 +34,11 @@ ** ****************************************************************************/ -#ifndef QWAYLANDQUICKXDGSURFACEITEM_P_H -#define QWAYLANDQUICKXDGSURFACEITEM_P_H +#ifndef QWAYLANDXDGSHELLINTEGRATION_H +#define QWAYLANDXDGSHELLINTEGRATION_H -#include <QtWaylandCompositor/private/qwaylandquickitem_p.h> +#include <QtWaylandCompositor/private/qwaylandquickshellsurfaceitem_p.h> +#include <QtWaylandCompositor/QWaylandXdgSurface> QT_BEGIN_NAMESPACE @@ -52,24 +53,33 @@ QT_BEGIN_NAMESPACE // We mean it. // -class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandQuickXdgSurfaceItemPrivate : public QWaylandQuickItemPrivate +namespace QtWayland { + +class XdgShellIntegration : public QWaylandQuickShellIntegration { + Q_OBJECT public: - enum GrabberState { - DefaultState, - ResizeState, - MoveState - }; + XdgShellIntegration(QWaylandQuickShellSurfaceItem *item); + bool mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE; + bool mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE; - QWaylandQuickXdgSurfaceItemPrivate() - : QWaylandQuickItemPrivate() - , xdgSurface(Q_NULLPTR) - , moveItem(Q_NULLPTR) - , grabberState(DefaultState) - {} +private Q_SLOTS: + void handleStartMove(QWaylandInputDevice *inputDevice); + void handleStartResize(QWaylandInputDevice *inputDevice, QWaylandXdgSurface::ResizeEdge edges); + void handleSetMaximized(); + void handleUnsetMaximized(); + void handleMaximizedChanged(); + void handleActivatedChanged(); + void handleSurfaceSizeChanged(); - QWaylandXdgSurface *xdgSurface; - QQuickItem *moveItem; +private: + enum class GrabberState { + Default, + Resize, + Move + }; + QWaylandQuickShellSurfaceItem *m_item; + QWaylandXdgSurface *m_xdgSurface; GrabberState grabberState; struct { @@ -94,6 +104,8 @@ public: } maximizeState; }; +} + QT_END_NAMESPACE -#endif /*QWAYLANDQUICKXDGSURFACEITEM_P_H*/ +#endif // QWAYLANDXDGSHELLINTEGRATION_H diff --git a/src/imports/compositor/plugins.qmltypes b/src/imports/compositor/plugins.qmltypes index db104c05..54b3bfcc 100644 --- a/src/imports/compositor/plugins.qmltypes +++ b/src/imports/compositor/plugins.qmltypes @@ -230,6 +230,14 @@ Module { Method { name: "updateStarted" } } Component { + name: "QWaylandQuickShellSurfaceItem" + defaultProperty: "data" + prototype: "QWaylandQuickItem" + exports: ["QtWayland.Compositor/ShellSurfaceItem 1.0"] + exportMetaObjectRevisions: [0] + Property { name: "shellSurface"; type: "QWaylandShellSurface"; isPointer: true } + } + Component { name: "QWaylandQuickSurface" prototype: "QWaylandSurface" exports: ["QtWayland.Compositor/WaylandSurface 1.0"] @@ -238,26 +246,15 @@ Module { Property { name: "clientRenderingEnabled"; type: "bool" } } Component { - name: "QWaylandQuickWlShellSurfaceItem" - defaultProperty: "data" - prototype: "QWaylandQuickItem" - exports: ["QtWayland.Compositor/WlShellSurfaceItem 1.0"] - exportMetaObjectRevisions: [0] - Property { name: "shellSurface"; type: "QWaylandWlShellSurface"; isPointer: true } - Property { name: "moveItem"; type: "QQuickItem"; isPointer: true } - } - Component { - name: "QWaylandQuickXdgSurfaceItem" - defaultProperty: "data" - prototype: "QWaylandQuickItem" - exports: ["QtWayland.Compositor/XdgSurfaceItem 1.0"] + name: "QWaylandResource" + exports: ["QtWayland.Compositor/WaylandResource 1.0"] + isCreatable: false exportMetaObjectRevisions: [0] - Property { name: "xdgSurface"; type: "QWaylandXdgSurface"; isPointer: true } - Property { name: "moveItem"; type: "QQuickItem"; isPointer: true } } Component { - name: "QWaylandResource" - exports: ["QtWayland.Compositor/WaylandResource 1.0"] + name: "QWaylandShellSurface" + prototype: "QWaylandCompositorExtension" + exports: ["QtWayland.Compositor/ShellSurface 1.0"] isCreatable: false exportMetaObjectRevisions: [0] } @@ -392,7 +389,7 @@ Module { } Component { name: "QWaylandWlShellSurface" - prototype: "QWaylandCompositorExtension" + prototype: "QWaylandShellSurface" exports: [ "QtWayland.Compositor/WlShellSurface 1.0", "QtWayland.Compositor/WlShellSurfaceBase 1.0" @@ -532,7 +529,7 @@ Module { } Component { name: "QWaylandXdgSurface" - prototype: "QWaylandCompositorExtension" + prototype: "QWaylandShellSurface" exports: [ "QtWayland.Compositor/XdgSurface 1.0", "QtWayland.Compositor/XdgSurfaceBase 1.0" diff --git a/src/imports/compositor/qwaylandquickcompositorplugin.cpp b/src/imports/compositor/qwaylandquickcompositorplugin.cpp index 960d2926..6f00351c 100644 --- a/src/imports/compositor/qwaylandquickcompositorplugin.cpp +++ b/src/imports/compositor/qwaylandquickcompositorplugin.cpp @@ -47,8 +47,7 @@ #include <QtWaylandCompositor/QWaylandCompositorExtension> #include <QtWaylandCompositor/QWaylandQuickExtension> #include <QtWaylandCompositor/QWaylandInputDevice> -#include <QtWaylandCompositor/QWaylandQuickWlShellSurfaceItem> -#include <QtWaylandCompositor/QWaylandQuickXdgSurfaceItem> +#include <QtWaylandCompositor/QWaylandQuickShellSurfaceItem> #include <QtWaylandCompositor/QWaylandResource> #include <QtWaylandCompositor/QWaylandWindowManagerExtension> @@ -141,6 +140,7 @@ public: qmlRegisterUncreatableType<QWaylandInputDevice>(uri, 1, 0, "WaylandInputDevice", QObject::tr("Cannot create instance of WaylandInputDevice")); qmlRegisterUncreatableType<QWaylandCompositor>(uri, 1, 0, "WaylandCompositorBase", QObject::tr("Cannot create instance of WaylandCompositorBase, use WaylandCompositor instead")); qmlRegisterUncreatableType<QWaylandSurface>(uri, 1, 0, "WaylandSurfaceBase", QObject::tr("Cannot create instance of WaylandSurfaceBase, use WaylandSurface instead")); + qmlRegisterUncreatableType<QWaylandShellSurface>(uri, 1, 0, "ShellSurface", QObject::tr("Cannot create instance of ShellSurface")); qmlRegisterUncreatableType<QWaylandWlShellSurface>(uri, 1, 0, "WlShellSurfaceBase", QObject::tr("Cannot create instance of WlShellSurfaceBase, use WlShellSurface instead")); qmlRegisterUncreatableType<QWaylandXdgSurface>(uri, 1, 0, "XdgSurfaceBase", QObject::tr("Cannot create instance of XdgSurfaceBase, use XdgSurface instead")); qmlRegisterUncreatableType<QWaylandResource>(uri, 1, 0, "WaylandResource", QObject::tr("Cannot create instance of WaylandResource")); @@ -149,10 +149,9 @@ public: qmlRegisterType<QWaylandWindowManagerExtensionQuickExtension>(uri, 1, 0, "WindowManager"); qmlRegisterType<QWaylandWlShellQuickExtension>(uri, 1, 0, "WlShell"); qmlRegisterType<QWaylandWlShellSurface>(uri, 1, 0, "WlShellSurface"); - qmlRegisterType<QWaylandQuickWlShellSurfaceItem>(uri, 1, 0, "WlShellSurfaceItem"); + qmlRegisterType<QWaylandQuickShellSurfaceItem>(uri, 1, 0, "ShellSurfaceItem"); qmlRegisterType<QWaylandXdgShellQuickExtension>(uri, 1, 0, "XdgShell"); qmlRegisterType<QWaylandXdgSurface>(uri, 1, 0, "XdgSurface"); - qmlRegisterType<QWaylandQuickXdgSurfaceItem>(uri, 1, 0, "XdgSurfaceItem"); qmlRegisterType<QWaylandTextInputManagerQuickExtension>(uri, 1, 0, "TextInputManager"); } }; |