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 }