File indexing completed on 2024-05-12 15:56:45
0001 /* This file is part of the KDE project 0002 0003 SPDX-FileCopyrightText: 2006 Thorsten Zachmann <zachmann@kde.org> 0004 SPDX-FileCopyrightText: 2006 C. Boemann Rasmussen <cbo@boemann.dk> 0005 SPDX-FileCopyrightText: 2006-2007 Thomas Zander <zander@kde.org> 0006 SPDX-FileCopyrightText: 2021 Dmitry Kazakov <dimula73@gmail.com> 0007 0008 SPDX-License-Identifier: LGPL-2.0-or-later 0009 */ 0010 0011 #include "KoPointerEvent.h" 0012 #include <QTabletEvent> 0013 #include <QMouseEvent> 0014 #include <QWheelEvent> 0015 #include <cmath> 0016 #include <boost/variant2/variant.hpp> 0017 0018 namespace detail { 0019 0020 // Qt's events do not have copy-ctors yet, so we should emulate them 0021 // See https://bugreports.qt.io/browse/QTBUG-72488 0022 0023 template <class Event> void copyEventHack(const Event *src, QScopedPointer<QEvent> &dst); 0024 0025 template<> void copyEventHack(const QMouseEvent *src, QScopedPointer<QEvent> &dst) { 0026 QMouseEvent *tmp = new QMouseEvent(src->type(), 0027 src->localPos(), src->windowPos(), src->screenPos(), 0028 src->button(), src->buttons(), src->modifiers(), 0029 src->source()); 0030 tmp->setTimestamp(src->timestamp()); 0031 dst.reset(tmp); 0032 } 0033 0034 template<> void copyEventHack(const QTabletEvent *src, QScopedPointer<QEvent> &dst) { 0035 QTabletEvent *tmp = new QTabletEvent(src->type(), 0036 src->posF(), src->globalPosF(), 0037 src->device(), src->pointerType(), 0038 src->pressure(), 0039 src->xTilt(), src->yTilt(), 0040 src->tangentialPressure(), 0041 src->rotation(), 0042 src->z(), 0043 src->modifiers(), 0044 src->uniqueId(), 0045 src->button(), src->buttons()); 0046 tmp->setTimestamp(src->timestamp()); 0047 dst.reset(tmp); 0048 } 0049 0050 template<> void copyEventHack(const QTouchEvent *src, QScopedPointer<QEvent> &dst) { 0051 QTouchEvent *tmp = new QTouchEvent(src->type(), 0052 src->device(), 0053 src->modifiers(), 0054 src->touchPointStates(), 0055 src->touchPoints()); 0056 tmp->setTimestamp(src->timestamp()); 0057 dst.reset(tmp); 0058 } 0059 0060 } 0061 0062 class Q_DECL_HIDDEN KoPointerEvent::Private 0063 { 0064 public: 0065 template <typename Event> 0066 Private(Event *event) 0067 : eventPtr(event) 0068 { 0069 } 0070 0071 boost::variant2::variant<QMouseEvent*, QTabletEvent*, QTouchEvent*> eventPtr; 0072 }; 0073 0074 KoPointerEvent::KoPointerEvent(QMouseEvent *ev, const QPointF &pnt) 0075 : point(pnt), 0076 d(new Private(ev)) 0077 { 0078 } 0079 0080 KoPointerEvent::KoPointerEvent(QTabletEvent *ev, const QPointF &pnt) 0081 : point(pnt), 0082 d(new Private(ev)) 0083 { 0084 } 0085 0086 KoPointerEvent::KoPointerEvent(QTouchEvent* ev, const QPointF &pnt) 0087 : point(pnt), 0088 d(new Private(ev)) 0089 { 0090 } 0091 0092 KoPointerEvent::KoPointerEvent(KoPointerEvent *event, const QPointF &point) 0093 : point(point) 0094 , d(new Private(*(event->d))) 0095 { 0096 } 0097 0098 KoPointerEvent::KoPointerEvent(const KoPointerEvent &rhs) 0099 : point(rhs.point) 0100 , d(new Private(*(rhs.d))) 0101 { 0102 } 0103 0104 KoPointerEvent &KoPointerEvent::operator=(const KoPointerEvent &rhs) 0105 { 0106 if (&rhs != this) { 0107 *d = *rhs.d; 0108 point = rhs.point; 0109 } 0110 0111 return *this; 0112 } 0113 0114 KoPointerEvent::~KoPointerEvent() 0115 { 0116 } 0117 0118 template <typename Event> 0119 KoPointerEventWrapper::KoPointerEventWrapper(Event *_event, const QPointF &point) 0120 : event(_event, point), 0121 baseQtEvent(QSharedPointer<QEvent>(static_cast<QEvent*>(_event))) 0122 { 0123 } 0124 0125 struct DeepCopyVisitor 0126 { 0127 QPointF point; 0128 0129 template <typename T> 0130 KoPointerEventWrapper operator() (const T *event) { 0131 QScopedPointer<QEvent> baseEvent; 0132 detail::copyEventHack(event, baseEvent); 0133 return {static_cast<T*>(baseEvent.take()), point}; 0134 } 0135 }; 0136 0137 KoPointerEventWrapper KoPointerEvent::deepCopyEvent() const 0138 { 0139 return visit(DeepCopyVisitor{point}, d->eventPtr); 0140 } 0141 0142 Qt::MouseButton KoPointerEvent::button() const 0143 { 0144 struct Visitor { 0145 Qt::MouseButton operator() (const QMouseEvent *event) { 0146 return event->button(); 0147 } 0148 Qt::MouseButton operator() (const QTabletEvent *event) { 0149 return event->button(); 0150 } 0151 Qt::MouseButton operator() (const QTouchEvent *) { 0152 return Qt::LeftButton; 0153 } 0154 }; 0155 0156 return visit(Visitor(), d->eventPtr); 0157 } 0158 0159 Qt::MouseButtons KoPointerEvent::buttons() const 0160 { 0161 struct Visitor { 0162 Qt::MouseButtons operator() (const QMouseEvent *event) { 0163 return event->buttons(); 0164 } 0165 Qt::MouseButtons operator() (const QTabletEvent *event) { 0166 return event->buttons(); 0167 } 0168 Qt::MouseButtons operator() (const QTouchEvent *) { 0169 return Qt::LeftButton; 0170 } 0171 }; 0172 0173 return visit(Visitor(), d->eventPtr); 0174 } 0175 0176 QPoint KoPointerEvent::globalPos() const 0177 { 0178 struct Visitor { 0179 QPoint operator() (const QMouseEvent *event) { 0180 return event->globalPos(); 0181 } 0182 QPoint operator() (const QTabletEvent *event) { 0183 return event->globalPos(); 0184 } 0185 QPoint operator() (const QTouchEvent *) { 0186 return QPoint(); 0187 } 0188 }; 0189 0190 return visit(Visitor(), d->eventPtr); 0191 } 0192 0193 QPoint KoPointerEvent::pos() const 0194 { 0195 struct Visitor { 0196 QPoint operator() (const QMouseEvent *event) { 0197 return event->pos(); 0198 } 0199 QPoint operator() (const QTabletEvent *event) { 0200 return event->pos(); 0201 } 0202 QPoint operator() (const QTouchEvent *event) { 0203 return event->touchPoints().at(0).pos().toPoint(); 0204 } 0205 }; 0206 0207 return visit(Visitor(), d->eventPtr); 0208 } 0209 0210 int KoPointerEvent::x() const 0211 { 0212 return pos().x(); 0213 } 0214 0215 int KoPointerEvent::y() const 0216 { 0217 return pos().y(); 0218 } 0219 0220 qreal KoPointerEvent::pressure() const 0221 { 0222 struct Visitor { 0223 qreal operator() (const QTabletEvent *event) { 0224 return event->pressure(); 0225 } 0226 qreal operator() (const QTouchEvent *event) { 0227 return event->touchPoints().at(0).pressure(); 0228 } 0229 qreal operator() (...) { 0230 return 1.0; 0231 } 0232 }; 0233 0234 return visit(Visitor(), d->eventPtr); 0235 } 0236 0237 qreal KoPointerEvent::rotation() const 0238 { 0239 struct Visitor { 0240 qreal operator() (const QTabletEvent *event) { 0241 return event->rotation(); 0242 } 0243 qreal operator() (const QTouchEvent *event) { 0244 return event->touchPoints().at(0).rotation(); 0245 } 0246 qreal operator() (...) { 0247 return 0.0; 0248 } 0249 }; 0250 0251 return visit(Visitor(), d->eventPtr); 0252 } 0253 0254 qreal KoPointerEvent::tangentialPressure() const 0255 { 0256 struct Visitor { 0257 qreal operator() (const QTabletEvent *event) { 0258 return std::fmod((event->tangentialPressure() - (-1.0)) / (1.0 - (-1.0)), 2.0); 0259 } 0260 qreal operator() (...) { 0261 return 0.0; 0262 } 0263 }; 0264 0265 return visit(Visitor(), d->eventPtr); 0266 } 0267 0268 int KoPointerEvent::xTilt() const 0269 { 0270 struct Visitor { 0271 int operator() (const QTabletEvent *event) { 0272 return event->xTilt(); 0273 } 0274 int operator() (...) { 0275 return 0; 0276 } 0277 }; 0278 0279 return visit(Visitor(), d->eventPtr); 0280 } 0281 0282 0283 int KoPointerEvent::yTilt() const 0284 { 0285 struct Visitor { 0286 int operator() (const QTabletEvent *event) { 0287 return event->yTilt(); 0288 } 0289 int operator() (...) { 0290 return 0; 0291 } 0292 }; 0293 0294 return visit(Visitor(), d->eventPtr); 0295 } 0296 0297 int KoPointerEvent::z() const 0298 { 0299 struct Visitor { 0300 int operator() (const QTabletEvent *event) { 0301 return event->z(); 0302 } 0303 int operator() (...) { 0304 return 0; 0305 } 0306 }; 0307 0308 return visit(Visitor(), d->eventPtr); 0309 } 0310 0311 ulong KoPointerEvent::time() const 0312 { 0313 struct Visitor { 0314 ulong operator() (const QInputEvent *event) { 0315 return event->timestamp(); 0316 } 0317 }; 0318 0319 return visit(Visitor(), d->eventPtr); 0320 } 0321 0322 bool KoPointerEvent::isTabletEvent() 0323 { 0324 return d->eventPtr.index() == 1; 0325 } 0326 0327 Qt::KeyboardModifiers KoPointerEvent::modifiers() const 0328 { 0329 struct Visitor { 0330 Qt::KeyboardModifiers operator() (const QInputEvent *event) { 0331 return event->modifiers(); 0332 } 0333 }; 0334 0335 return visit(Visitor(), d->eventPtr); 0336 } 0337 0338 void KoPointerEvent::accept() 0339 { 0340 struct Visitor { 0341 void operator() (QInputEvent *event) { 0342 event->accept(); 0343 } 0344 }; 0345 0346 return visit(Visitor(), d->eventPtr); 0347 } 0348 0349 void KoPointerEvent::ignore() 0350 { 0351 struct Visitor { 0352 void operator() (QInputEvent *event) { 0353 event->ignore(); 0354 } 0355 }; 0356 0357 return visit(Visitor(), d->eventPtr); 0358 } 0359 0360 bool KoPointerEvent::isAccepted() const 0361 { 0362 struct Visitor { 0363 bool operator() (const QInputEvent *event) { 0364 return event->isAccepted(); 0365 } 0366 }; 0367 0368 return visit(Visitor(), d->eventPtr); 0369 } 0370 0371 bool KoPointerEvent::spontaneous() const 0372 { 0373 struct Visitor { 0374 bool operator() (const QInputEvent *event) { 0375 return event->spontaneous(); 0376 } 0377 }; 0378 0379 return visit(Visitor(), d->eventPtr); 0380 } 0381 0382 void KoPointerEvent::copyQtPointerEvent(const QMouseEvent *event, QScopedPointer<QEvent> &dst) 0383 { 0384 detail::copyEventHack(event, dst); 0385 } 0386 0387 void KoPointerEvent::copyQtPointerEvent(const QTabletEvent *event, QScopedPointer<QEvent> &dst) 0388 { 0389 detail::copyEventHack(event, dst); 0390 } 0391 0392 void KoPointerEvent::copyQtPointerEvent(const QTouchEvent *event, QScopedPointer<QEvent> &dst) 0393 { 0394 detail::copyEventHack(event, dst); 0395 }