Libplasma

edgeeventforwarder.cpp
1/*
2 SPDX-FileCopyrightText: 2023 David Edmundson <davidedmundson@kde.org>
3 SPDX-License-Identifier: LGPL-2.0-or-later
4*/
5
6#include "edgeeventforwarder.h"
7
8#include <QCoreApplication>
9#include <QDragEnterEvent>
10#include <QDropEvent>
11#include <QEvent>
12#include <QMouseEvent>
13#include <QWindow>
14
15using namespace PlasmaQuick;
16
17class EdgeEventForwarderPrivate
18{
19public:
20 QWindow *window;
21 QMargins margins;
22 Qt::Edges activeEdges;
23 QMargins activeMargins() const;
24 bool mainItemContainsPosition(const QPointF &position) const;
25 QPointF positionAdjustedForMainItem(const QPointF &position) const;
26};
27
29 : QObject(parent)
30 , d(new EdgeEventForwarderPrivate)
31{
32 d->window = parent;
33 d->window->installEventFilter(this);
34}
35
36EdgeEventForwarder::~EdgeEventForwarder()
37{
38 d->window->removeEventFilter(this);
39}
40
42{
43 d->margins = margins;
44}
45
46QMargins EdgeEventForwarder::margins()
47{
48 return d->margins;
49}
50
52{
53 d->activeEdges = edges;
54}
55
56Qt::Edges EdgeEventForwarder::activeEdges()
57{
58 return d->activeEdges;
59}
60
61bool EdgeEventForwarder::eventFilter(QObject *watched, QEvent *event)
62{
63 Q_UNUSED(watched)
64
65 switch (event->type()) {
69 QMouseEvent *me = static_cast<QMouseEvent *>(event);
70 // don't mess with position if the cursor is actually outside the view:
71 // somebody is doing a click and drag that must not break when the cursor is outside
72
73 if (d->window->geometry().contains(me->globalPosition().toPoint()) && !d->mainItemContainsPosition(me->scenePosition())) {
74 QMouseEvent me2(me->type(),
75 d->positionAdjustedForMainItem(me->scenePosition()),
76 d->positionAdjustedForMainItem(me->scenePosition()),
77 d->positionAdjustedForMainItem(me->scenePosition()) + d->window->position(),
78 me->button(),
79 me->buttons(),
80 me->modifiers());
81 me2.setTimestamp(me->timestamp());
82
83 if (d->window->isVisible()) {
84 QCoreApplication::sendEvent(d->window, &me2);
85 }
86 return true;
87 }
88 break;
89 }
90
91 case QEvent::Wheel: {
92 QWheelEvent *we = static_cast<QWheelEvent *>(event);
93
94 const QPoint pos = we->position().toPoint();
95
96 if (!d->mainItemContainsPosition(pos)) {
97 QWheelEvent we2(d->positionAdjustedForMainItem(pos),
98 d->positionAdjustedForMainItem(pos) + d->window->position(),
99 we->pixelDelta(),
100 we->angleDelta(),
101 we->buttons(),
102 we->modifiers(),
103 we->phase(),
104 false /*inverted*/);
105 we2.setTimestamp(we->timestamp());
106
107 if (d->window->isVisible()) {
108 QCoreApplication::sendEvent(this, &we2);
109 }
110 return true;
111 }
112 break;
113 }
114
115 case QEvent::DragEnter: {
116 QDragEnterEvent *de = static_cast<QDragEnterEvent *>(event);
117 if (!d->mainItemContainsPosition(de->position())) {
118 QDragEnterEvent de2(d->positionAdjustedForMainItem(de->position()).toPoint(),
119 de->possibleActions(),
120 de->mimeData(),
121 de->buttons(),
122 de->modifiers());
123
124 if (d->window->isVisible()) {
125 QCoreApplication::sendEvent(this, &de2);
126 }
127 return true;
128 }
129 break;
130 }
131 // DragLeave just works
133 break;
134 case QEvent::DragMove: {
135 QDragMoveEvent *de = static_cast<QDragMoveEvent *>(event);
136 if (!d->mainItemContainsPosition(de->position())) {
137 QDragMoveEvent de2(d->positionAdjustedForMainItem(de->position()).toPoint(), de->possibleActions(), de->mimeData(), de->buttons(), de->modifiers());
138
139 if (d->window->isVisible()) {
140 QCoreApplication::sendEvent(this, &de2);
141 }
142 return true;
143 }
144 break;
145 }
146 case QEvent::Drop: {
147 QDropEvent *de = static_cast<QDropEvent *>(event);
148 if (!d->mainItemContainsPosition(de->position())) {
149 QDropEvent de2(d->positionAdjustedForMainItem(de->position()), de->possibleActions(), de->mimeData(), de->buttons(), de->modifiers());
150
151 if (d->window->isVisible()) {
152 QCoreApplication::sendEvent(this, &de2);
153 }
154 return true;
155 }
156 break;
157 }
158
159 default:
160 break;
161 }
162 return false;
163}
164
165QMargins EdgeEventForwarderPrivate::activeMargins() const
166{
167 return QMargins(activeEdges.testFlag(Qt::LeftEdge) ? margins.left() : 0,
168 activeEdges.testFlag(Qt::TopEdge) ? margins.top() : 0,
169 activeEdges.testFlag(Qt::RightEdge) ? margins.right() : 0,
170 activeEdges.testFlag(Qt::BottomEdge) ? margins.bottom() : 0);
171}
172
173bool EdgeEventForwarderPrivate::mainItemContainsPosition(const QPointF &position) const
174{
175 const QRectF itemRect = QRectF(QPointF(0, 0), window->size()).marginsRemoved(activeMargins());
176 return itemRect.contains(position);
177}
178
179QPointF EdgeEventForwarderPrivate::positionAdjustedForMainItem(const QPointF &position) const
180{
181 const QRectF itemRect = QRectF(QPointF(0, 0), window->size()).marginsRemoved(activeMargins());
182 return QPointF(qBound(itemRect.left(), position.x(), itemRect.right()), qBound(itemRect.top(), position.y(), itemRect.bottom()));
183}
184
185#include "moc_edgeeventforwarder.cpp"
void setActiveEdges(Qt::Edges edges)
setActiveEdges sets which margins should be active for edge forwarding typically this should match ed...
void setMargins(const QMargins &margins)
setMargins sets the margins to use for the event forwarding
EdgeEventForwarder(QWindow *parent)
EdgeEventForwarder constructor.
KGUIADDONS_EXPORT QWindow * window(QObject *job)
The EdgeEventForwarder class This class forwards edge events to be replayed within the given margin T...
Definition action.h:20
bool sendEvent(QObject *receiver, QEvent *event)
Qt::MouseButtons buttons() const const
const QMimeData * mimeData() const const
Qt::KeyboardModifiers modifiers() const const
QPointF position() const const
Qt::DropActions possibleActions() const const
Type type() const const
Qt::KeyboardModifiers modifiers() const const
quint64 timestamp() const const
virtual bool event(QEvent *e)
QObject * parent() const const
QPoint toPoint() const const
qreal x() const const
qreal y() const const
qreal bottom() const const
bool contains(const QPointF &point) const const
qreal left() const const
QRectF marginsRemoved(const QMarginsF &margins) const const
qreal right() const const
qreal top() const const
Qt::MouseButton button() const const
Qt::MouseButtons buttons() const const
QPointF globalPosition() const const
QPointF position() const const
QPointF scenePosition() const const
typedef Edges
QPoint angleDelta() const const
Qt::ScrollPhase phase() const const
QPoint pixelDelta() const const
virtual QSize size() const const override
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Sat Dec 21 2024 17:01:35 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.