File indexing completed on 2024-05-12 04:19:51

0001 /*
0002 Gwenview: an image viewer
0003 Copyright 2019 Steffen Hartleib <steffenhartleib@t-online.de>
0004 
0005 This program is free software; you can redistribute it and/or
0006 modify it under the terms of the GNU General Public License
0007 as published by the Free Software Foundation; either version 2
0008 of the License, or (at your option) any later version.
0009 
0010 This program is distributed in the hope that it will be useful,
0011 but WITHOUT ANY WARRANTY; without even the implied warranty of
0012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0013 GNU General Public License for more details.
0014 
0015 You should have received a copy of the GNU General Public License
0016 along with this program; if not, write to the Free Software
0017 Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
0018 
0019 */
0020 // Self
0021 #include "doubletap.h"
0022 
0023 // Qt
0024 #include <QGraphicsWidget>
0025 #include <QTouchEvent>
0026 
0027 // KF
0028 
0029 // Local
0030 #include "gwenview_lib_debug.h"
0031 #include "lib/touch/touch_helper.h"
0032 
0033 namespace Gwenview
0034 {
0035 struct DoubleTapRecognizerPrivate {
0036     DoubleTapRecognizer *q = nullptr;
0037     bool mTargetIsGrapicsWidget = false;
0038     qint64 mTouchBeginnTimestamp;
0039     bool mIsOnlyTap;
0040     qint64 mLastTapTimestamp = 0;
0041     qint64 mLastDoupleTapTimestamp = 0;
0042 };
0043 
0044 DoubleTapRecognizer::DoubleTapRecognizer()
0045     : QGestureRecognizer()
0046     , d(new DoubleTapRecognizerPrivate)
0047 {
0048     d->q = this;
0049 }
0050 
0051 DoubleTapRecognizer::~DoubleTapRecognizer()
0052 {
0053     delete d;
0054 }
0055 
0056 QGesture *DoubleTapRecognizer::create(QObject *)
0057 {
0058     return static_cast<QGesture *>(new DoubleTap());
0059 }
0060 
0061 QGestureRecognizer::Result DoubleTapRecognizer::recognize(QGesture *state, QObject *watched, QEvent *event)
0062 {
0063     // Because of a bug in Qt in a gesture event in a graphicsview, all gestures are trigger twice
0064     // https://bugreports.qt.io/browse/QTBUG-13103
0065     if (qobject_cast<QGraphicsWidget *>(watched))
0066         d->mTargetIsGrapicsWidget = true;
0067     if (d->mTargetIsGrapicsWidget && watched->isWidgetType())
0068         return Ignore;
0069 
0070     switch (event->type()) {
0071     case QEvent::TouchBegin: {
0072         auto touchEvent = static_cast<QTouchEvent *>(event);
0073         d->mTouchBeginnTimestamp = touchEvent->timestamp();
0074         d->mIsOnlyTap = true;
0075         if (d->mLastDoupleTapTimestamp == 0)
0076             d->mLastDoupleTapTimestamp = touchEvent->timestamp() - Touch_Helper::Touch::doubleTapInterval;
0077         state->setHotSpot(touchEvent->touchPoints().first().screenPos());
0078         return MayBeGesture;
0079     }
0080 
0081     case QEvent::TouchUpdate: {
0082         auto touchEvent = static_cast<QTouchEvent *>(event);
0083         const qint64 now = touchEvent->timestamp();
0084         state->setHotSpot(touchEvent->touchPoints().first().screenPos());
0085 
0086         if (d->mIsOnlyTap && now - d->mTouchBeginnTimestamp < Touch_Helper::Touch::maxTimeForTap && Touch_Helper::touchStationary(event)) {
0087             d->mIsOnlyTap = true;
0088             return MayBeGesture;
0089         } else {
0090             d->mIsOnlyTap = false;
0091             return CancelGesture;
0092         }
0093         break;
0094     }
0095 
0096     case QEvent::TouchEnd: {
0097         auto touchEvent = static_cast<QTouchEvent *>(event);
0098         const qint64 now = touchEvent->timestamp();
0099 
0100         if (now - d->mLastTapTimestamp <= Touch_Helper::Touch::doubleTapInterval && d->mIsOnlyTap) {
0101             // Interval between two double tap gesture need to be bigger than Touch_Helper::Touch::doupleTapIntervall,
0102             // to suppress fast successively double tap gestures
0103             if (now - d->mLastDoupleTapTimestamp > Touch_Helper::Touch::doubleTapInterval) {
0104                 d->mLastTapTimestamp = 0;
0105                 state->setHotSpot(touchEvent->touchPoints().first().screenPos());
0106                 d->mLastDoupleTapTimestamp = now;
0107                 return FinishGesture;
0108             }
0109         }
0110 
0111         if (d->mIsOnlyTap)
0112             d->mLastTapTimestamp = now;
0113 
0114         break;
0115     }
0116 
0117     default:
0118         return Ignore;
0119     }
0120     return Ignore;
0121 }
0122 
0123 DoubleTap::DoubleTap(QObject *parent)
0124     : QGesture(parent)
0125 {
0126 }
0127 
0128 } // namespace