File indexing completed on 2025-07-13 05:03:00
0001 // SPDX-FileCopyrightText: 2023 Devin Lin <espidev@gmail.com> 0002 // SPDX-License-Identifier: LGPL-2.0-or-later 0003 0004 #pragma once 0005 0006 #include <QMouseEvent> 0007 #include <QPointF> 0008 #include <QPointerEvent> 0009 #include <QQmlListProperty> 0010 #include <QQuickItem> 0011 #include <QTouchEvent> 0012 0013 /** 0014 * @short A component that provides access to swipes over its children, similar to Flickable. 0015 * However, it does not do any of the positioning Flickable does, and so it 0016 * can be used to build custom components with specialized swiping needs (ex. panels) 0017 * 0018 * TODO: New fingers that come in should steal from the old finger 0019 * 0020 * @author Devin Lin <devin@kde.org> 0021 */ 0022 class SwipeArea : public QQuickItem 0023 { 0024 Q_OBJECT 0025 QML_ELEMENT 0026 Q_PROPERTY(SwipeArea::Mode mode READ mode WRITE setMode NOTIFY modeChanged) 0027 Q_PROPERTY(bool interactive READ interactive WRITE setInteractive NOTIFY interactiveChanged) 0028 Q_PROPERTY(bool moving READ moving NOTIFY movingChanged) 0029 Q_PROPERTY(bool pressed READ pressed NOTIFY pressedChanged) 0030 0031 public: 0032 SwipeArea(QQuickItem *parent = nullptr); 0033 0034 enum Mode { BothAxis = 0, VerticalOnly, HorizontalOnly }; 0035 Q_ENUM(Mode) 0036 0037 Mode mode() const; 0038 void setMode(Mode mode); 0039 0040 bool interactive() const; 0041 void setInteractive(bool interactive); 0042 0043 bool moving() const; 0044 bool pressed() const; 0045 0046 Q_INVOKABLE void setSkipSwipeThreshold(bool value); 0047 0048 Q_SIGNALS: 0049 void modeChanged(); 0050 void interactiveChanged(); 0051 void movingChanged(); 0052 void pressedChanged(); 0053 0054 void swipeEnded(); 0055 void swipeStarted(QPointF point); 0056 0057 // deltaX, deltaY - amount moved since last swipeMove() 0058 // totalDeltaX, totalDeltaY - amount move since startedSwipe() 0059 void swipeMove(qreal totalDeltaX, qreal totalDeltaY, qreal deltaX, qreal deltaY); 0060 0061 protected: 0062 bool childMouseEventFilter(QQuickItem *item, QEvent *event) override; 0063 void mouseMoveEvent(QMouseEvent *event) override; 0064 void mousePressEvent(QMouseEvent *event) override; 0065 void mouseReleaseEvent(QMouseEvent *event) override; 0066 void mouseUngrabEvent() override; 0067 void touchEvent(QTouchEvent *event) override; 0068 void touchUngrabEvent() override; 0069 0070 private: 0071 void setMoving(bool moving); 0072 void setPressed(bool pressed); 0073 0074 bool filterPointerEvent(QQuickItem *receiver, QPointerEvent *event); 0075 0076 void handlePressEvent(QPointerEvent *event, QPointF point); 0077 void handleReleaseEvent(QPointerEvent *event, QPointF point); 0078 void handleMoveEvent(QPointerEvent *event, QPointF point); 0079 0080 void resetSwipe(); 0081 0082 Mode m_mode = Mode::BothAxis; 0083 bool m_interactive = true; 0084 bool m_pressed = false; 0085 0086 // whether we have started a flick 0087 bool m_moving = false; 0088 0089 // whether on this current flick, we want to steal the mouse/touch event from children 0090 bool m_stealMouse = false; 0091 0092 // the point where the user pressed down on at the start of the interaction 0093 QPointF m_pressPos; 0094 0095 // the point where the swipe actually started being registered (can be some distance from the pressed position) 0096 QPointF m_startPos; 0097 0098 // the previous point where interaction was at 0099 QPointF m_lastPos; 0100 0101 // whether to skip trying to measure the swipe threshold 0102 bool m_skipSwipeThreshold; 0103 }; 0104 0105 QML_DECLARE_TYPE(SwipeArea)