1
0
mirror of https://github.com/KDE/latte-dock.git synced 2025-01-24 18:03:53 +03:00

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.
This commit is contained in:
Michail Vourlakos 2021-01-15 22:29:00 +02:00
parent 33d08c92a0
commit 81e4b19b59
4 changed files with 200 additions and 98 deletions

View File

@ -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<QDragEnterEvent *>(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<QDragMoveEvent *>(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<QDropEvent *>(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<QMouseEvent *>(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<QMouseEvent *>(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<QMouseEvent *>(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());
}
}
}

View File

@ -23,6 +23,7 @@
// Qt
#include <QEvent>
#include <QObject>
#include <QList>
#include <QPointer>
#include <QQuickItem>
@ -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<Latte::View> m_view;
QPointer<QQuickItem> m_originItem;
QPointer<QQuickItem> m_originParentItem;
QPointer<QQuickItem> m_destinationItem;
};

View File

@ -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
//! 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
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;
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;
}
}
]
}
}
}

View File

@ -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{