File indexing completed on 2024-12-01 11:10:42

0001 /*
0002     SPDX-FileCopyrightText: 2020 Michail Vourlakos <mvourlakos@gmail.com>
0003     SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 
0006 #include "eventssink.h"
0007 
0008 // local
0009 #include "view.h"
0010 #include "positioner.h"
0011 
0012 // Qt
0013 #include <QDragEnterEvent>
0014 #include <QDragMoveEvent>
0015 #include <QDropEvent>
0016 #include <QMouseEvent>
0017 #include <QPointF>
0018 #include <QRectF>
0019 
0020 
0021 namespace Latte {
0022 namespace ViewPart {
0023 
0024 EventsSink::EventsSink(Latte::View *parent)
0025     : QObject(parent),
0026       m_view(parent)
0027 {
0028 }
0029 
0030 EventsSink::~EventsSink()
0031 {
0032 }
0033 
0034 QQuickItem *EventsSink::originParentItem() const
0035 {
0036     return m_originParentItem;
0037 }
0038 
0039 QQuickItem *EventsSink::destinationItem() const
0040 {
0041     return m_destinationItem;
0042 }
0043 
0044 void EventsSink::setSink(QQuickItem *originParent, QQuickItem *destination)
0045 {
0046     if ((m_originParentItem == originParent) && (m_destinationItem == destination)) {
0047         return;
0048     }
0049 
0050     m_originParentItem = originParent;
0051     m_destinationItem = destination;
0052 
0053     emit itemsChanged();
0054 }
0055 
0056 bool EventsSink::isActive()
0057 {
0058     return ((m_originParentItem != nullptr) && (m_destinationItem != nullptr));
0059 }
0060 
0061 void EventsSink::release()
0062 {
0063     setSink(nullptr, nullptr);
0064 }
0065 
0066 QEvent *EventsSink::onEvent(QEvent *e)
0067 {
0068     if (!e) {
0069         return nullptr;
0070     }
0071 
0072     if (!isActive()) {
0073         return e;
0074     }
0075 
0076     QEvent *sunkevent = e;
0077 
0078     switch (e->type()) {
0079     case QEvent::Leave:
0080         release();
0081         break;
0082     case QEvent::DragEnter:
0083         if (auto de = static_cast<QDragEnterEvent *>(e)) {
0084             QPointF point = de->posF();
0085             if (originSinksContain(point)) {
0086                 auto de2 = new QDragEnterEvent(positionAdjustedForDestination(point).toPoint(),
0087                                                de->possibleActions(),
0088                                                de->mimeData(),
0089                                                de->mouseButtons(),
0090                                                de->keyboardModifiers());
0091                 sunkevent = de2;
0092             } else if (!destinationContains(point)) {
0093                 release();
0094             }
0095         }
0096         break;
0097 
0098     case QEvent::DragMove:
0099         if (auto de = static_cast<QDragMoveEvent *>(e)) {
0100             QPointF point = de->posF();
0101             if (originSinksContain(point)) {
0102                 auto de2 = new QDragMoveEvent(positionAdjustedForDestination(point).toPoint(),
0103                                               de->possibleActions(),
0104                                               de->mimeData(),
0105                                               de->mouseButtons(),
0106                                               de->keyboardModifiers());
0107 
0108                 sunkevent = de2;
0109             } else if (!destinationContains(point)) {
0110                 release();
0111             }
0112         }
0113         break;
0114 
0115     case QEvent::Drop:
0116         if (auto de = static_cast<QDropEvent *>(e)) {
0117             QPointF point = de->posF();
0118             if (originSinksContain(point)) {
0119                 auto de2 = new QDropEvent(positionAdjustedForDestination(point).toPoint(),
0120                                           de->possibleActions(),
0121                                           de->mimeData(),
0122                                           de->mouseButtons(),
0123                                           de->keyboardModifiers());
0124 
0125                 sunkevent = de2;
0126             } else if (!destinationContains(point)) {
0127                 release();
0128             }
0129         }
0130 
0131         break;
0132 
0133     case QEvent::MouseMove:
0134         if (auto me = dynamic_cast<QMouseEvent *>(e)) {
0135             if (m_view->positioner() && m_view->positioner()->isCursorInsideView() && originSinksContain(me->windowPos())) {
0136                 auto positionadjusted = positionAdjustedForDestination(me->windowPos());
0137                 auto me2 = new QMouseEvent(me->type(),
0138                                            positionadjusted,
0139                                            positionadjusted,
0140                                            positionadjusted + m_view->position(),
0141                                            me->button(), me->buttons(), me->modifiers());
0142 
0143                 sunkevent = me2;
0144             } else if (!destinationContains(me->windowPos())) {
0145                 release();
0146             }
0147         }
0148         break;
0149 
0150     case QEvent::MouseButtonPress:
0151         if (auto me = dynamic_cast<QMouseEvent *>(e)) {
0152             if (originSinksContain(me->windowPos())) {
0153                 auto positionadjusted = positionAdjustedForDestination(me->windowPos());
0154                 auto me2 = new QMouseEvent(me->type(),
0155                                            positionadjusted,
0156                                            positionadjusted,
0157                                            positionadjusted + m_view->position(),
0158                                            me->button(), me->buttons(), me->modifiers());
0159 
0160                 qDebug() << "Sunk Event:: sunk event pressed...";
0161                 sunkevent = me2;
0162             } else if (!destinationContains(me->windowPos())) {
0163                 release();
0164             }
0165         }
0166         break;
0167 
0168     case QEvent::MouseButtonRelease:
0169         if (auto me = dynamic_cast<QMouseEvent *>(e)) {
0170             if (originSinksContain(me->windowPos())) {
0171                 auto positionadjusted = positionAdjustedForDestination(me->windowPos());
0172                 auto me2 = new QMouseEvent(me->type(),
0173                                            positionadjusted,
0174                                            positionadjusted,
0175                                            positionadjusted + m_view->position(),
0176                                            me->button(), me->buttons(), me->modifiers());
0177 
0178                 sunkevent = me2;
0179             } else if (!destinationContains(me->windowPos())) {
0180                 release();
0181             }
0182         }
0183         break;
0184 
0185     case QEvent::Wheel:
0186         if (auto we = dynamic_cast<QWheelEvent *>(e)) {
0187             QPoint pos = we->position().toPoint();
0188             if (originSinksContain(pos)) {
0189                 auto positionadjusted = positionAdjustedForDestination(pos);
0190                 auto we2 = new QWheelEvent(positionadjusted,
0191                                            positionadjusted + m_view->position(),
0192                                            we->pixelDelta(), we->angleDelta(), we->angleDelta().y(),
0193                                            we->orientation(), we->buttons(), we->modifiers(), we->phase());
0194 
0195                 sunkevent = we2;
0196             } else if (!destinationContains(pos)) {
0197                 release();
0198             }
0199         }
0200         break;
0201     default:
0202         break;
0203     }
0204 
0205     return sunkevent;
0206 }
0207 
0208 QPointF EventsSink::positionAdjustedForDestination(const QPointF &point) const
0209 {
0210     QRectF destinationRectToScene = m_destinationItem->mapRectToScene(QRectF(0, 0, m_destinationItem->width() - 1, m_destinationItem->height() - 1));
0211 
0212     return QPointF(qBound(destinationRectToScene.left(), point.x(), destinationRectToScene.right()),
0213                    qBound(destinationRectToScene.top(), point.y(), destinationRectToScene.bottom()));
0214 }
0215 
0216 bool EventsSink::destinationContains(const QPointF &point) const
0217 {
0218     QRectF destinationRectToScene = m_destinationItem->mapRectToScene(QRectF(0, 0, m_destinationItem->width() - 1, m_destinationItem->height() - 1));
0219 
0220     return destinationRectToScene.contains(point);
0221 }
0222 
0223 bool EventsSink::originSinksContain(const QPointF &point) const
0224 {
0225     QRegion originsRegion;
0226 
0227     for(const auto currentOrigin: m_originParentItem->childItems()) {
0228         QRectF currentOriginGeometry = currentOrigin->mapRectToScene(QRectF(0, 0, currentOrigin->width(), currentOrigin->height()));
0229         originsRegion = originsRegion.united(currentOriginGeometry.toRect());
0230     }
0231 
0232     return originsRegion.contains(point.toPoint());
0233 }
0234 
0235 }
0236 }
0237