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{