mirror of
https://github.com/KDE/latte-dock.git
synced 2025-01-24 18:03:53 +03:00
81e4b19b59
--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.
257 lines
8.3 KiB
C++
257 lines
8.3 KiB
C++
/*
|
|
* Copyright 2020 Michail Vourlakos <mvourlakos@gmail.com>
|
|
*
|
|
* This file is part of Latte-Dock
|
|
*
|
|
* Latte-Dock is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License as
|
|
* published by the Free Software Foundation; either version 2 of
|
|
* the License, or (at your option) any later version.
|
|
*
|
|
* Latte-Dock is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "eventssink.h"
|
|
|
|
// local
|
|
#include "view.h"
|
|
#include "positioner.h"
|
|
|
|
// Qt
|
|
#include <QDragEnterEvent>
|
|
#include <QDragMoveEvent>
|
|
#include <QDropEvent>
|
|
#include <QMouseEvent>
|
|
#include <QPointF>
|
|
#include <QRectF>
|
|
|
|
|
|
namespace Latte {
|
|
namespace ViewPart {
|
|
|
|
EventsSink::EventsSink(Latte::View *parent)
|
|
: QObject(parent),
|
|
m_view(parent)
|
|
{
|
|
}
|
|
|
|
EventsSink::~EventsSink()
|
|
{
|
|
}
|
|
|
|
QQuickItem *EventsSink::originParentItem() const
|
|
{
|
|
return m_originParentItem;
|
|
}
|
|
|
|
QQuickItem *EventsSink::destinationItem() const
|
|
{
|
|
return m_destinationItem;
|
|
}
|
|
|
|
void EventsSink::setSink(QQuickItem *originParent, QQuickItem *destination)
|
|
{
|
|
if ((m_originParentItem == originParent) && (m_destinationItem == destination)) {
|
|
return;
|
|
}
|
|
|
|
m_originParentItem = originParent;
|
|
m_destinationItem = destination;
|
|
|
|
emit itemsChanged();
|
|
}
|
|
|
|
bool EventsSink::isActive()
|
|
{
|
|
return ((m_originParentItem != nullptr) && (m_destinationItem != nullptr));
|
|
}
|
|
|
|
void EventsSink::release()
|
|
{
|
|
setSink(nullptr, nullptr);
|
|
}
|
|
|
|
QEvent *EventsSink::onEvent(QEvent *e)
|
|
{
|
|
if (!e) {
|
|
return nullptr;
|
|
}
|
|
|
|
if (!isActive()) {
|
|
return e;
|
|
}
|
|
|
|
QEvent *sunkevent = e;
|
|
|
|
switch (e->type()) {
|
|
case QEvent::Leave:
|
|
release();
|
|
break;
|
|
case QEvent::DragEnter:
|
|
if (auto de = static_cast<QDragEnterEvent *>(e)) {
|
|
QPointF point = de->posF();
|
|
if (originSinksContain(point)) {
|
|
auto de2 = new QDragEnterEvent(positionAdjustedForDestination(point).toPoint(),
|
|
de->possibleActions(),
|
|
de->mimeData(),
|
|
de->mouseButtons(),
|
|
de->keyboardModifiers());
|
|
sunkevent = de2;
|
|
} else if (!destinationContains(point)) {
|
|
release();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case QEvent::DragMove:
|
|
if (auto de = static_cast<QDragMoveEvent *>(e)) {
|
|
QPointF point = de->posF();
|
|
if (originSinksContain(point)) {
|
|
auto de2 = new QDragMoveEvent(positionAdjustedForDestination(point).toPoint(),
|
|
de->possibleActions(),
|
|
de->mimeData(),
|
|
de->mouseButtons(),
|
|
de->keyboardModifiers());
|
|
|
|
sunkevent = de2;
|
|
} else if (!destinationContains(point)) {
|
|
release();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case QEvent::Drop:
|
|
if (auto de = static_cast<QDropEvent *>(e)) {
|
|
QPointF point = de->posF();
|
|
if (originSinksContain(point)) {
|
|
auto de2 = new QDropEvent(positionAdjustedForDestination(point).toPoint(),
|
|
de->possibleActions(),
|
|
de->mimeData(),
|
|
de->mouseButtons(),
|
|
de->keyboardModifiers());
|
|
|
|
sunkevent = de2;
|
|
} else if (!destinationContains(point)) {
|
|
release();
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case QEvent::MouseMove:
|
|
if (auto me = dynamic_cast<QMouseEvent *>(e)) {
|
|
if (m_view->positioner() && m_view->positioner()->isCursorInsideView() && originSinksContain(me->windowPos())) {
|
|
auto positionadjusted = positionAdjustedForDestination(me->windowPos());
|
|
auto me2 = new QMouseEvent(me->type(),
|
|
positionadjusted,
|
|
positionadjusted,
|
|
positionadjusted + m_view->position(),
|
|
me->button(), me->buttons(), me->modifiers());
|
|
|
|
sunkevent = me2;
|
|
} else if (!destinationContains(me->windowPos())) {
|
|
release();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case QEvent::MouseButtonPress:
|
|
if (auto me = dynamic_cast<QMouseEvent *>(e)) {
|
|
if (originSinksContain(me->windowPos())) {
|
|
auto positionadjusted = positionAdjustedForDestination(me->windowPos());
|
|
auto me2 = new QMouseEvent(me->type(),
|
|
positionadjusted,
|
|
positionadjusted,
|
|
positionadjusted + m_view->position(),
|
|
me->button(), me->buttons(), me->modifiers());
|
|
|
|
qDebug() << "Sunk Event:: sunk event pressed...";
|
|
sunkevent = me2;
|
|
} else if (!destinationContains(me->windowPos())) {
|
|
release();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case QEvent::MouseButtonRelease:
|
|
if (auto me = dynamic_cast<QMouseEvent *>(e)) {
|
|
if (originSinksContain(me->windowPos())) {
|
|
auto positionadjusted = positionAdjustedForDestination(me->windowPos());
|
|
auto me2 = new QMouseEvent(me->type(),
|
|
positionadjusted,
|
|
positionadjusted,
|
|
positionadjusted + m_view->position(),
|
|
me->button(), me->buttons(), me->modifiers());
|
|
|
|
sunkevent = me2;
|
|
} else if (!destinationContains(me->windowPos())) {
|
|
release();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case QEvent::Wheel:
|
|
if (auto we = dynamic_cast<QWheelEvent *>(e)) {
|
|
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
|
|
QPoint pos = QPoint(we->x(), we->y());
|
|
#else
|
|
QPoint pos = we->position().toPoint();
|
|
#endif
|
|
|
|
if (originSinksContain(pos)) {
|
|
auto positionadjusted = positionAdjustedForDestination(pos);
|
|
auto we2 = new QWheelEvent(positionadjusted,
|
|
positionadjusted + m_view->position(),
|
|
we->pixelDelta(), we->angleDelta(), we->angleDelta().y(),
|
|
we->orientation(), we->buttons(), we->modifiers(), we->phase());
|
|
|
|
sunkevent = we2;
|
|
} else if (!destinationContains(pos)) {
|
|
release();
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return sunkevent;
|
|
}
|
|
|
|
QPointF EventsSink::positionAdjustedForDestination(const QPointF &point) const
|
|
{
|
|
QRectF destinationRectToScene = m_destinationItem->mapRectToScene(QRectF(0, 0, m_destinationItem->width() - 1, m_destinationItem->height() - 1));
|
|
|
|
return QPointF(qBound(destinationRectToScene.left(), point.x(), destinationRectToScene.right()),
|
|
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());
|
|
}
|
|
|
|
}
|
|
}
|
|
|