From 1e04bb374fafe4a00d0fd4b8d5a0c5588781f888 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antti=20M=C3=A4=C3=A4tt=C3=A4?= Date: Tue, 22 Nov 2016 13:45:45 +0200 Subject: Move event forwarding to frontend MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the event forwarding to frontend so that the target object destruction can be handled properly. Change-Id: I6bdee731760cee69334aad7ca39f0dd16c44a471 Reviewed-by: Tomi Korpipää Reviewed-by: Sean Harmer --- src/render/picking/eventforward.cpp | 41 ++++++++------- src/render/picking/eventforward_p.h | 4 +- src/render/picking/picking.pri | 6 ++- src/render/picking/posteventstofrontend.cpp | 74 ++++++++++++++++++++++++++ src/render/picking/posteventstofrontend_p.h | 81 +++++++++++++++++++++++++++++ src/render/picking/qeventforward.cpp | 31 +++++++++++ src/render/picking/qeventforward.h | 4 ++ src/render/picking/qeventforward_p.h | 1 + 8 files changed, 217 insertions(+), 25 deletions(-) create mode 100644 src/render/picking/posteventstofrontend.cpp create mode 100644 src/render/picking/posteventstofrontend_p.h diff --git a/src/render/picking/eventforward.cpp b/src/render/picking/eventforward.cpp index 132e022ce..0216542bd 100644 --- a/src/render/picking/eventforward.cpp +++ b/src/render/picking/eventforward.cpp @@ -40,6 +40,7 @@ #include #include +#include #include #include @@ -51,7 +52,7 @@ namespace Qt3DRender { namespace Render { EventForward::EventForward() - : m_target(nullptr) + : BackendNode(QBackendNode::ReadWrite) , m_forwardMouseEvents(false) , m_forwardKeyboardEvents(false) , m_focus(false) @@ -67,7 +68,6 @@ EventForward::~EventForward() void EventForward::cleanup() { setEnabled(false); - m_target = nullptr; m_coordinateAttribute = ""; m_coordinateTransform.setToIdentity(); m_forwardMouseEvents = false; @@ -75,11 +75,6 @@ void EventForward::cleanup() m_focus = false; } -QObject *EventForward::target() const -{ - return m_target; -} - QString EventForward::coordinateAttribute() const { return m_coordinateAttribute; @@ -105,11 +100,6 @@ bool EventForward::focus() const return m_focus; } -void EventForward::setTarget(QObject *target) -{ - m_target = target; -} - void EventForward::setCoordinateTransform(const QMatrix4x4 &transform) { m_coordinateTransform = transform; @@ -139,7 +129,6 @@ void EventForward::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr { const auto typedChange = qSharedPointerCast>(change); const auto &data = typedChange->data; - setTarget(data.target); setCoordinateAttribute(data.coordinateAttribute); setCoordinateTransform(data.coordinateTransform); setForwardMouseEvents(data.forwardMouseEvents); @@ -153,9 +142,7 @@ void EventForward::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) const Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast(e); - if (propertyChange->propertyName() == QByteArrayLiteral("target")) - setTarget(propertyChange->value().value()); - else if (propertyChange->propertyName() == QByteArrayLiteral("coordinateTransform")) + if (propertyChange->propertyName() == QByteArrayLiteral("coordinateTransform")) setCoordinateTransform(propertyChange->value().value()); else if (propertyChange->propertyName() == QByteArrayLiteral("coordinateAttribute")) setCoordinateAttribute(propertyChange->value().toString()); @@ -177,16 +164,30 @@ void EventForward::forward(const QMouseEvent &event, const QVector4D &coordinate QMouseEvent *mouseEvent = new QMouseEvent(event.type(), local, local, local, event.button(), event.buttons(), event.modifiers(), Qt::MouseEventSynthesizedByApplication); - QCoreApplication::postEvent(m_target, mouseEvent); + + PostEventsToFrontendPtr events = PostEventsToFrontendPtr::create(mouseEvent); + + auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); + e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); + e->setPropertyName("events"); + e->setValue(QVariant::fromValue(events)); + notifyObservers(e); } -void EventForward::forward(const QList &events) +void EventForward::forward(const QList &keyEvents) { - for (const QKeyEvent &e : events) { + QVector eventsToSend; + for (const QKeyEvent &e : keyEvents) { QKeyEvent *keyEvent = new QKeyEvent(e.type(), e.key(), e.modifiers(), e.nativeScanCode(), e.nativeVirtualKey(), e.nativeModifiers()); - QCoreApplication::postEvent(m_target, keyEvent); + eventsToSend.append(keyEvent); } + PostEventsToFrontendPtr events = PostEventsToFrontendPtr::create(eventsToSend); + auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); + e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); + e->setPropertyName("events"); + e->setValue(QVariant::fromValue(events)); + notifyObservers(e); } } // Render diff --git a/src/render/picking/eventforward_p.h b/src/render/picking/eventforward_p.h index e090ba5e4..663298e40 100644 --- a/src/render/picking/eventforward_p.h +++ b/src/render/picking/eventforward_p.h @@ -69,7 +69,6 @@ public: void cleanup(); - QObject *target() const; QString coordinateAttribute() const; QMatrix4x4 coordinateTransform() const; bool forwardMouseEvents() const; @@ -86,12 +85,11 @@ public: void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) Q_DECL_FINAL; void forward(const QMouseEvent &event, const QVector4D &coordinate); - void forward(const QList &events); + void forward(const QList &keyEvents); private: void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL; - QObject *m_target; QString m_coordinateAttribute; QMatrix4x4 m_coordinateTransform; bool m_forwardMouseEvents; diff --git a/src/render/picking/picking.pri b/src/render/picking/picking.pri index e581a8f8a..c2eb8f50b 100644 --- a/src/render/picking/picking.pri +++ b/src/render/picking/picking.pri @@ -10,7 +10,8 @@ HEADERS += \ $$PWD/qobjectpicker_p.h \ $$PWD/qeventforward.h \ $$PWD/qeventforward_p.h \ - $$PWD/eventforward_p.h + $$PWD/eventforward_p.h \ + $$PWD/posteventstofrontend_p.h SOURCES += \ $$PWD/qobjectpicker.cpp \ @@ -19,4 +20,5 @@ SOURCES += \ $$PWD/objectpicker.cpp \ $$PWD/pickeventfilter.cpp \ $$PWD/qeventforward.cpp \ - $$PWD/eventforward.cpp + $$PWD/eventforward.cpp \ + $$PWD/posteventstofrontend.cpp diff --git a/src/render/picking/posteventstofrontend.cpp b/src/render/picking/posteventstofrontend.cpp new file mode 100644 index 000000000..51f986902 --- /dev/null +++ b/src/render/picking/posteventstofrontend.cpp @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt3D 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 "posteventstofrontend_p.h" + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +PostEventsToFrontend::PostEventsToFrontend() + : QObject() +{ + +} + +PostEventsToFrontend::PostEventsToFrontend(QEvent *event) + : QObject() +{ + m_events.append(event); +} + +PostEventsToFrontend::PostEventsToFrontend(const QVector &events) + : QObject() +{ + m_events = events; +} + +PostEventsToFrontend::~PostEventsToFrontend() +{ + for (QEvent *e : m_events) + delete e; +} + +QVector &PostEventsToFrontend::events() +{ + return m_events; +} + +} + +QT_END_NAMESPACE diff --git a/src/render/picking/posteventstofrontend_p.h b/src/render/picking/posteventstofrontend_p.h new file mode 100644 index 000000000..5dd29b047 --- /dev/null +++ b/src/render/picking/posteventstofrontend_p.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt3D 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 QT3DRENDER_POSTEVENTSTOFRONTEND_P_H +#define QT3DRENDER_POSTEVENTSTOFRONTEND_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +class Q_AUTOTEST_EXPORT PostEventsToFrontend : public QObject +{ + Q_OBJECT +public: + PostEventsToFrontend(); + PostEventsToFrontend(QEvent *event); + PostEventsToFrontend(const QVector &events); + ~PostEventsToFrontend(); + + QVector &events(); +private: + QVector m_events; +}; + +typedef QSharedPointer PostEventsToFrontendPtr; + +} // Qt3DRender + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(Qt3DRender::PostEventsToFrontend*) + +#endif // QT3DRENDER_POSTEVENTSTOFRONTEND_P_H diff --git a/src/render/picking/qeventforward.cpp b/src/render/picking/qeventforward.cpp index 8aa22e276..08546fabd 100644 --- a/src/render/picking/qeventforward.cpp +++ b/src/render/picking/qeventforward.cpp @@ -36,8 +36,12 @@ #include "qeventforward.h" #include "qeventforward_p.h" +#include "posteventstofrontend_p.h" #include +#include + +#include QT_BEGIN_NAMESPACE @@ -148,11 +152,24 @@ QObject *QEventForward::target() const return d->m_target; } +void QEventForward::targetDestroyed(QObject *target) +{ + Q_D(QEventForward); + Q_ASSERT(target == d->m_target); + setTarget(nullptr); +} + void QEventForward::setTarget(QObject *target) { Q_D(QEventForward); if (target != d->m_target) { + if (d->m_target != nullptr) + QObject::disconnect(d->m_destructionConnection); d->m_target = target; + if (d->m_target) { + d->m_destructionConnection = QObject::connect(target, &QObject::destroyed, + this, &QEventForward::targetDestroyed); + } emit targetChanged(target); } } @@ -249,6 +266,20 @@ Qt3DCore::QNodeCreatedChangeBasePtr QEventForward::createNodeCreationChange() co return creationChange; } +void QEventForward::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) +{ + Q_D(QEventForward); + Qt3DCore::QPropertyUpdatedChangePtr e + = qSharedPointerCast(change); + if (e->type() == Qt3DCore::PropertyUpdated && d->m_target != nullptr) { + if (e->propertyName() == QByteArrayLiteral("events")) { + PostEventsToFrontendPtr postedEvents = e->value().value(); + for (QEvent *event : postedEvents->events()) + QCoreApplication::sendEvent(d->m_target, event); + } + } +} + } // Qt3DRender QT_END_NAMESPACE diff --git a/src/render/picking/qeventforward.h b/src/render/picking/qeventforward.h index 28659606b..ee8100318 100644 --- a/src/render/picking/qeventforward.h +++ b/src/render/picking/qeventforward.h @@ -87,9 +87,13 @@ Q_SIGNALS: void forwardKeyboardEventsChanged(bool forward); void focusChanged(bool focus); +protected: + void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) Q_DECL_OVERRIDE; + private: Q_DECLARE_PRIVATE(QEventForward) Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const Q_DECL_OVERRIDE; + void targetDestroyed(QObject *target); }; } // Qt3DRender diff --git a/src/render/picking/qeventforward_p.h b/src/render/picking/qeventforward_p.h index 4aa6834df..c087bc8f5 100644 --- a/src/render/picking/qeventforward_p.h +++ b/src/render/picking/qeventforward_p.h @@ -81,6 +81,7 @@ public: bool m_forwardMouseEvents; bool m_forwardKeyboardEvents; bool m_focus; + QMetaObject::Connection m_destructionConnection; }; struct QEventForwardData -- cgit v1.2.3