From 81e4b19b59d7053170b6db541de7729af4f71b5f Mon Sep 17 00:00:00 2001 From: Michail Vourlakos Date: Fri, 15 Jan 2021 22:29:00 +0200 Subject: [PATCH] improve SunkEvents implementation --each origin mouse area is now informin the SunkEvents handler for the relevant origin areas at the same time and this way there is no events breakage when changing from one sunked event origin area to another --the sunked events origin and destination areas are now released only when the event is NOT inside any origin area or any destination. This way no events breakage is appearing when changing from destination area to origin area and vice versa. --- app/view/eventssink.cpp | 73 ++++--- app/view/eventssink.h | 16 +- .../package/contents/ui/applet/EventsSink.qml | 205 +++++++++++++----- .../ui/applet/EventsSinkOriginArea.qml | 6 +- 4 files changed, 201 insertions(+), 99 deletions(-) diff --git a/app/view/eventssink.cpp b/app/view/eventssink.cpp index d20c770df..bf4e9d52c 100644 --- a/app/view/eventssink.cpp +++ b/app/view/eventssink.cpp @@ -45,9 +45,9 @@ EventsSink::~EventsSink() { } -QQuickItem *EventsSink::originItem() const +QQuickItem *EventsSink::originParentItem() const { - return m_originItem; + return m_originParentItem; } QQuickItem *EventsSink::destinationItem() const @@ -55,22 +55,21 @@ QQuickItem *EventsSink::destinationItem() const return m_destinationItem; } -void EventsSink::setSink(QQuickItem *origin, QQuickItem *destination) +void EventsSink::setSink(QQuickItem *originParent, QQuickItem *destination) { - if ((m_originItem == origin) && (m_destinationItem == destination)) { + if ((m_originParentItem == originParent) && (m_destinationItem == destination)) { return; } - m_originItem = origin; + m_originParentItem = originParent; m_destinationItem = destination; - emit itemsChanged(); } bool EventsSink::isActive() { - return ((m_originItem != nullptr) && (m_destinationItem != nullptr)); + return ((m_originParentItem != nullptr) && (m_destinationItem != nullptr)); } void EventsSink::release() @@ -97,16 +96,14 @@ QEvent *EventsSink::onEvent(QEvent *e) case QEvent::DragEnter: if (auto de = static_cast(e)) { QPointF point = de->posF(); - QPointF originInternal = m_originItem->mapFromScene(point); - - if (m_originItem->contains(originInternal)) { + if (originSinksContain(point)) { auto de2 = new QDragEnterEvent(positionAdjustedForDestination(point).toPoint(), de->possibleActions(), de->mimeData(), de->mouseButtons(), de->keyboardModifiers()); sunkevent = de2; - } else { + } else if (!destinationContains(point)) { release(); } } @@ -115,9 +112,7 @@ QEvent *EventsSink::onEvent(QEvent *e) case QEvent::DragMove: if (auto de = static_cast(e)) { QPointF point = de->posF(); - QPointF originInternal = m_originItem->mapFromScene(point); - - if (m_originItem->contains(originInternal)) { + if (originSinksContain(point)) { auto de2 = new QDragMoveEvent(positionAdjustedForDestination(point).toPoint(), de->possibleActions(), de->mimeData(), @@ -125,7 +120,7 @@ QEvent *EventsSink::onEvent(QEvent *e) de->keyboardModifiers()); sunkevent = de2; - } else { + } else if (!destinationContains(point)) { release(); } } @@ -134,9 +129,7 @@ QEvent *EventsSink::onEvent(QEvent *e) case QEvent::Drop: if (auto de = static_cast(e)) { QPointF point = de->posF(); - QPointF originInternal = m_originItem->mapFromScene(point); - - if (m_originItem->contains(originInternal)) { + if (originSinksContain(point)) { auto de2 = new QDropEvent(positionAdjustedForDestination(point).toPoint(), de->possibleActions(), de->mimeData(), @@ -144,7 +137,7 @@ QEvent *EventsSink::onEvent(QEvent *e) de->keyboardModifiers()); sunkevent = de2; - } else { + } else if (!destinationContains(point)) { release(); } } @@ -153,9 +146,7 @@ QEvent *EventsSink::onEvent(QEvent *e) case QEvent::MouseMove: if (auto me = dynamic_cast(e)) { - QPointF originInternal = m_originItem->mapFromScene(me->windowPos()); - - if (m_view->positioner() && m_view->positioner()->isCursorInsideView() && m_originItem->contains(originInternal)) { + if (m_view->positioner() && m_view->positioner()->isCursorInsideView() && originSinksContain(me->windowPos())) { auto positionadjusted = positionAdjustedForDestination(me->windowPos()); auto me2 = new QMouseEvent(me->type(), positionadjusted, @@ -164,7 +155,7 @@ QEvent *EventsSink::onEvent(QEvent *e) me->button(), me->buttons(), me->modifiers()); sunkevent = me2; - } else { + } else if (!destinationContains(me->windowPos())) { release(); } } @@ -172,9 +163,7 @@ QEvent *EventsSink::onEvent(QEvent *e) case QEvent::MouseButtonPress: if (auto me = dynamic_cast(e)) { - QPointF originInternal = m_originItem->mapFromScene(me->windowPos()); - - if (m_originItem->contains(originInternal)) { + if (originSinksContain(me->windowPos())) { auto positionadjusted = positionAdjustedForDestination(me->windowPos()); auto me2 = new QMouseEvent(me->type(), positionadjusted, @@ -184,7 +173,7 @@ QEvent *EventsSink::onEvent(QEvent *e) qDebug() << "Sunk Event:: sunk event pressed..."; sunkevent = me2; - } else { + } else if (!destinationContains(me->windowPos())) { release(); } } @@ -192,9 +181,7 @@ QEvent *EventsSink::onEvent(QEvent *e) case QEvent::MouseButtonRelease: if (auto me = dynamic_cast(e)) { - QPointF originInternal = m_originItem->mapFromScene(me->windowPos()); - - if (m_originItem->contains(originInternal)) { + if (originSinksContain(me->windowPos())) { auto positionadjusted = positionAdjustedForDestination(me->windowPos()); auto me2 = new QMouseEvent(me->type(), positionadjusted, @@ -203,7 +190,7 @@ QEvent *EventsSink::onEvent(QEvent *e) me->button(), me->buttons(), me->modifiers()); sunkevent = me2; - } else { + } else if (!destinationContains(me->windowPos())) { release(); } } @@ -216,9 +203,8 @@ QEvent *EventsSink::onEvent(QEvent *e) #else QPoint pos = we->position().toPoint(); #endif - QPointF originInternal = m_originItem->mapFromScene(pos); - if (m_originItem->contains(originInternal)) { + if (originSinksContain(pos)) { auto positionadjusted = positionAdjustedForDestination(pos); auto we2 = new QWheelEvent(positionadjusted, positionadjusted + m_view->position(), @@ -226,7 +212,7 @@ QEvent *EventsSink::onEvent(QEvent *e) we->orientation(), we->buttons(), we->modifiers(), we->phase()); sunkevent = we2; - } else { + } else if (!destinationContains(pos)) { release(); } } @@ -246,6 +232,25 @@ QPointF EventsSink::positionAdjustedForDestination(const QPointF &point) const qBound(destinationRectToScene.top(), point.y(), destinationRectToScene.bottom())); } +bool EventsSink::destinationContains(const QPointF &point) const +{ + QRectF destinationRectToScene = m_destinationItem->mapRectToScene(QRectF(0, 0, m_destinationItem->width() - 1, m_destinationItem->height() - 1)); + + return destinationRectToScene.contains(point); +} + +bool EventsSink::originSinksContain(const QPointF &point) const +{ + QRegion originsRegion; + + for(const auto currentOrigin: m_originParentItem->childItems()) { + QRectF currentOriginGeometry = currentOrigin->mapRectToScene(QRectF(0, 0, currentOrigin->width(), currentOrigin->height())); + originsRegion = originsRegion.united(currentOriginGeometry.toRect()); + } + + return originsRegion.contains(point.toPoint()); +} + } } diff --git a/app/view/eventssink.h b/app/view/eventssink.h index 8d390a9e3..1000ec3ee 100644 --- a/app/view/eventssink.h +++ b/app/view/eventssink.h @@ -23,6 +23,7 @@ // Qt #include #include +#include #include #include @@ -33,11 +34,16 @@ class View; namespace Latte { namespace ViewPart { +//! This class is used in order to sunk events from children rects of originParentItem +//! into the destination Item. Each applet container from containment qml part is responsible +//! to initialize properly the originParentItem and the destinationItem to be used for +//! sunk events + class EventsSink: public QObject { Q_OBJECT - Q_PROPERTY(QQuickItem *originItem READ originItem NOTIFY itemsChanged) + Q_PROPERTY(QQuickItem *originParentItem READ originParentItem NOTIFY itemsChanged) Q_PROPERTY(QQuickItem *destinationItem READ destinationItem NOTIFY itemsChanged) public: @@ -46,11 +52,11 @@ public: bool isActive(); - QQuickItem *originItem() const; + QQuickItem *originParentItem() const; QQuickItem *destinationItem() const; public slots: - Q_INVOKABLE void setSink(QQuickItem *origin, QQuickItem *destination); + Q_INVOKABLE void setSink(QQuickItem *originParent, QQuickItem *destination); QEvent *onEvent(QEvent *e); @@ -63,10 +69,12 @@ private slots: private: QPointF positionAdjustedForDestination(const QPointF &point) const; + bool originSinksContain(const QPointF &point) const; + bool destinationContains(const QPointF &point) const; private: QPointer m_view; - QPointer m_originItem; + QPointer m_originParentItem; QPointer m_destinationItem; }; diff --git a/containment/package/contents/ui/applet/EventsSink.qml b/containment/package/contents/ui/applet/EventsSink.qml index bce6980ef..6ae3b6376 100644 --- a/containment/package/contents/ui/applet/EventsSink.qml +++ b/containment/package/contents/ui/applet/EventsSink.qml @@ -27,11 +27,12 @@ Item { readonly property int headThickness: appletItem.metrics.margin.thickness readonly property int tailThickness: destination ? destination.tailThicknessMargin : headThickness + readonly property int thickness: headThickness + tailThickness + (root.isHorizontal ? destination.height : destination.width) readonly property int lengthPadding: { if ( (root.panelAlignment === LatteCore.Types.Justify && appletItem.firstChildOfStartLayout) - || (root.panelAlignment === LatteCore.Types.Justify && appletItem.lastChildOfEndLayout) - || (root.panelAlignment !== LatteCore.Types.Justify && appletItem.firstChildOfMainLayout) - || (root.panelAlignment !== LatteCore.Types.Justify && appletItem.lastChildOfMainLayout)) { + || (root.panelAlignment === LatteCore.Types.Justify && appletItem.lastChildOfEndLayout) + || (root.panelAlignment !== LatteCore.Types.Justify && appletItem.firstChildOfMainLayout) + || (root.panelAlignment !== LatteCore.Types.Justify && appletItem.lastChildOfMainLayout)) { //! Fitts Law on corners return appletItem.lengthAppletFullMargin; } @@ -41,6 +42,7 @@ Item { readonly property bool active: parent ? parent.active : false + Loader{ anchors.fill: parent active: appletItem.debug.eventsSinkEnabled && active @@ -53,72 +55,159 @@ Item { } } + Item { + id: originParentItem + anchors.fill: parent - EventsSinkOriginArea { - id: topArea - anchors.bottom: parent.top - anchors.horizontalCenter: parent.horizontalCenter - - width: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? destination.width + 2 * lengthPadding : destination.width - height: { - if (plasmoid.formFactor === PlasmaCore.Types.Vertical) { - return lengthPadding; - } else if (plasmoid.location === PlasmaCore.Types.TopEdge) { - return tailThickness; - } else { - return headThickness; + //! NOTICE: Do not add any more child items. These child items are used from SinkedEvents handler in order + //! to identify the areas from which mouse events should be sunk into the destination item + + EventsSinkOriginArea { + id: topArea + width: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? destination.width + 2 * lengthPadding : thickness + height: { + if (plasmoid.formFactor === PlasmaCore.Types.Vertical) { + return lengthPadding; + } else if (plasmoid.location === PlasmaCore.Types.TopEdge) { + return tailThickness; + } else { + return headThickness; + } } + + states:[ + State{ + name: "horizontal" + when: plasmoid.formFactor === PlasmaCore.Types.Horizontal + + AnchorChanges{ + target: topArea; + anchors.horizontalCenter: parent.horizontalCenter; anchors.verticalCenter: undefined; + anchors.right: undefined; anchors.left: undefined; anchors.top: undefined; anchors.bottom: parent.top; + } + }, + State{ + name: "vertical" + when: plasmoid.formFactor === PlasmaCore.Types.Vertical + + AnchorChanges{ + target: topArea; + anchors.horizontalCenter: undefined; anchors.verticalCenter: undefined; + anchors.right: undefined; anchors.left: leftArea.left; anchors.top: leftArea.top; anchors.bottom: undefined; + } + } + ] } - } - EventsSinkOriginArea { - id: bottomArea - anchors.top: parent.bottom - anchors.horizontalCenter: parent.horizontalCenter - - width: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? destination.width + 2 * lengthPadding : parent.width - height: { - if (plasmoid.formFactor === PlasmaCore.Types.Vertical) { - return lengthPadding; - } else if (plasmoid.location === PlasmaCore.Types.BottomEdge) { - return tailThickness; - } else { - return headThickness; + EventsSinkOriginArea { + id: bottomArea + width: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? destination.width + 2 * lengthPadding : thickness + height: { + if (plasmoid.formFactor === PlasmaCore.Types.Vertical) { + return lengthPadding; + } else if (plasmoid.location === PlasmaCore.Types.BottomEdge) { + return tailThickness; + } else { + return headThickness; + } } + + states:[ + State{ + name: "horizontal" + when: plasmoid.formFactor === PlasmaCore.Types.Horizontal + + AnchorChanges{ + target: bottomArea; + anchors.horizontalCenter: parent.horizontalCenter; anchors.verticalCenter: undefined; + anchors.right: undefined; anchors.left: undefined; anchors.top: parent.bottom; anchors.bottom: undefined; + } + }, + State{ + name: "vertical" + when: plasmoid.formFactor === PlasmaCore.Types.Vertical + + AnchorChanges{ + target: bottomArea; + anchors.horizontalCenter: undefined; anchors.verticalCenter: undefined; + anchors.right: undefined; anchors.left: leftArea.left; anchors.top: undefined; anchors.bottom: leftArea.bottom; + } + } + ] } - } - EventsSinkOriginArea { - id: leftArea - anchors.right: parent.left - anchors.verticalCenter: parent.verticalCenter - - height: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? parent.height : destination.height + 2 * lengthPadding - width: { - if (plasmoid.formFactor === PlasmaCore.Types.Horizontal) { - return lengthPadding; - } else if (plasmoid.location === PlasmaCore.Types.LeftEdge) { - return tailThickness; - } else { - return headThickness; + EventsSinkOriginArea { + id: leftArea + height: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? thickness : destination.height + 2 * lengthPadding + width: { + if (plasmoid.formFactor === PlasmaCore.Types.Horizontal) { + return lengthPadding; + } else if (plasmoid.location === PlasmaCore.Types.LeftEdge) { + return tailThickness; + } else { + return headThickness; + } } + + states:[ + State{ + name: "horizontal" + when: plasmoid.formFactor === PlasmaCore.Types.Horizontal + + AnchorChanges{ + target: leftArea; + anchors.horizontalCenter: undefined; anchors.verticalCenter: undefined; + anchors.right: undefined; anchors.left: bottomArea.left; anchors.top: undefined; anchors.bottom: bottomArea.bottom; + } + }, + State{ + name: "vertical" + when: plasmoid.formFactor === PlasmaCore.Types.Vertical + + AnchorChanges{ + target: leftArea; + anchors.horizontalCenter: undefined; anchors.verticalCenter: parent.verticalCenter; + anchors.right: parent.left; anchors.left: undefined; anchors.top: undefined; anchors.bottom: undefined; + } + } + ] } - } - EventsSinkOriginArea { - id: rightArea - anchors.left: parent.right - anchors.verticalCenter: parent.verticalCenter - - height: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? parent.height : destination.height + 2 * lengthPadding - width: { - if (plasmoid.formFactor === PlasmaCore.Types.Horizontal) { - return lengthPadding; - } else if (plasmoid.location === PlasmaCore.Types.RightEdge) { - return tailThickness; - } else { - return headThickness; + EventsSinkOriginArea { + id: rightArea + height: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? thickness : destination.height + 2 * lengthPadding + width: { + if (plasmoid.formFactor === PlasmaCore.Types.Horizontal) { + return lengthPadding; + } else if (plasmoid.location === PlasmaCore.Types.RightEdge) { + return tailThickness; + } else { + return headThickness; + } } + + states:[ + State{ + name: "horizontal" + when: plasmoid.formFactor === PlasmaCore.Types.Horizontal + + AnchorChanges{ + target: rightArea; + anchors.horizontalCenter: undefined; anchors.verticalCenter: undefined; + anchors.right: bottomArea.right; anchors.left: undefined; anchors.top: undefined; anchors.bottom: bottomArea.bottom; + } + }, + State{ + name: "vertical" + when: plasmoid.formFactor === PlasmaCore.Types.Vertical + + AnchorChanges{ + target: rightArea; + anchors.horizontalCenter: undefined; anchors.verticalCenter: parent.verticalCenter; + anchors.right: undefined; anchors.left: parent.right; anchors.top: undefined; anchors.bottom: undefined; + } + } + ] } } } diff --git a/containment/package/contents/ui/applet/EventsSinkOriginArea.qml b/containment/package/contents/ui/applet/EventsSinkOriginArea.qml index 9b603cffc..725f70ab1 100644 --- a/containment/package/contents/ui/applet/EventsSinkOriginArea.qml +++ b/containment/package/contents/ui/applet/EventsSinkOriginArea.qml @@ -20,13 +20,13 @@ import QtQuick 2.7 MouseArea { - id: __destinationArea + id: __originArea enabled: visible hoverEnabled: true - visible: root.latteView && root.latteView.sink.originItem !== __destinationArea && width>0 && height>0 + visible: root.latteView && root.latteView.sink.originParentItem !== originParentItem && width>0 && height>0 onEntered: { - root.latteView.sink.setSink(__destinationArea, destination) + root.latteView.sink.setSink(originParentItem, destination); } Loader{