File indexing completed on 2024-05-19 15:09:24

0001 /*
0002     SPDX-FileCopyrightText: 2011 Marco Martin <notmart@gmail.com>
0003     SPDX-FileCopyrightText: 2013 Sebastian Kügler <sebas@kde.org>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #ifndef MOUSEEVENTLISTENER_H
0009 #define MOUSEEVENTLISTENER_H
0010 
0011 #include <QQuickItem>
0012 
0013 /**
0014  * This item spies on mouse events from all child objects including child MouseAreas regardless
0015  * of whether the child MouseArea propagates events. It does not accept the event.
0016  *
0017  * In addition unlike MouseArea events include the mouse position in global coordinates and provides
0018  * the screen the mouse is in.
0019  */
0020 
0021 class KDeclarativeMouseEvent : public QObject
0022 {
0023     Q_OBJECT
0024     Q_PROPERTY(int x READ x)
0025     Q_PROPERTY(int y READ y)
0026     Q_PROPERTY(int screenX READ screenX)
0027     Q_PROPERTY(int screenY READ screenY)
0028     Q_PROPERTY(int button READ button)
0029     Q_PROPERTY(Qt::MouseButtons buttons READ buttons)
0030     Q_PROPERTY(Qt::KeyboardModifiers modifiers READ modifiers)
0031     Q_PROPERTY(QScreen *screen READ screen CONSTANT)
0032     Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted NOTIFY acceptedChanged)
0033     Q_PROPERTY(int source READ source)
0034 
0035 public:
0036     KDeclarativeMouseEvent(int x,
0037                            int y,
0038                            int screenX,
0039                            int screenY,
0040                            Qt::MouseButton button,
0041                            Qt::MouseButtons buttons,
0042                            Qt::KeyboardModifiers modifiers,
0043                            QScreen *screen,
0044                            Qt::MouseEventSource source)
0045         : m_x(x)
0046         , m_y(y)
0047         , m_screenX(screenX)
0048         , m_screenY(screenY)
0049         , m_button(button)
0050         , m_buttons(buttons)
0051         , m_modifiers(modifiers)
0052         , m_screen(screen)
0053         , m_source(source)
0054     {
0055     }
0056 
0057     int x() const
0058     {
0059         return m_x;
0060     }
0061     int y() const
0062     {
0063         return m_y;
0064     }
0065     int screenX() const
0066     {
0067         return m_screenX;
0068     }
0069     int screenY() const
0070     {
0071         return m_screenY;
0072     }
0073     int button() const
0074     {
0075         return m_button;
0076     }
0077     Qt::MouseButtons buttons() const
0078     {
0079         return m_buttons;
0080     }
0081     Qt::KeyboardModifiers modifiers() const
0082     {
0083         return m_modifiers;
0084     }
0085     QScreen *screen() const
0086     {
0087         return m_screen;
0088     }
0089     int source() const
0090     {
0091         return m_source;
0092     }
0093 
0094     bool isAccepted() const
0095     {
0096         return m_accepted;
0097     }
0098     void setAccepted(bool accepted)
0099     {
0100         if (m_accepted != accepted) {
0101             m_accepted = accepted;
0102             Q_EMIT acceptedChanged();
0103         }
0104     }
0105 
0106     // only for internal usage
0107     void setX(int x)
0108     {
0109         m_x = x;
0110     }
0111     void setY(int y)
0112     {
0113         m_y = y;
0114     }
0115 
0116 Q_SIGNALS:
0117     void acceptedChanged();
0118 
0119 private:
0120     int m_x;
0121     int m_y;
0122     int m_screenX;
0123     int m_screenY;
0124     Qt::MouseButton m_button;
0125     Qt::MouseButtons m_buttons;
0126     Qt::KeyboardModifiers m_modifiers;
0127     QScreen *m_screen;
0128     bool m_accepted = false;
0129     int m_source;
0130 };
0131 
0132 class KDeclarativeWheelEvent : public QObject
0133 {
0134     Q_OBJECT
0135     Q_PROPERTY(int x READ x CONSTANT)
0136     Q_PROPERTY(int y READ y CONSTANT)
0137     Q_PROPERTY(int screenX READ screenX CONSTANT)
0138     Q_PROPERTY(int screenY READ screenY CONSTANT)
0139     Q_PROPERTY(int deltaX READ deltaX CONSTANT)
0140     Q_PROPERTY(int deltaY READ deltaY CONSTANT)
0141     Q_PROPERTY(int delta READ deltaY CONSTANT) // deprecated in favor of deltaY. TODO KF6: remove
0142     Q_PROPERTY(Qt::MouseButtons buttons READ buttons CONSTANT)
0143     Q_PROPERTY(Qt::KeyboardModifiers modifiers READ modifiers CONSTANT)
0144     Q_PROPERTY(Qt::Orientation orientation READ orientation CONSTANT) // deprecated. TODO KF6: remove
0145 
0146 public:
0147     KDeclarativeWheelEvent(QPointF pos,
0148                            QPoint screenPos,
0149                            QPoint angleDelta,
0150                            Qt::MouseButtons buttons,
0151                            Qt::KeyboardModifiers modifiers,
0152                            Qt::Orientation orientation)
0153         : m_x(pos.x())
0154         , m_y(pos.y())
0155         , m_screenX(screenPos.x())
0156         , m_screenY(screenPos.y())
0157         , m_angleDelta(angleDelta)
0158         , m_buttons(buttons)
0159         , m_modifiers(modifiers)
0160         , m_orientation(orientation)
0161     {
0162     }
0163 
0164     int x() const
0165     {
0166         return m_x;
0167     }
0168     int y() const
0169     {
0170         return m_y;
0171     }
0172     int screenX() const
0173     {
0174         return m_screenX;
0175     }
0176     int screenY() const
0177     {
0178         return m_screenY;
0179     }
0180     int deltaX() const
0181     {
0182         return m_angleDelta.x();
0183     }
0184     int deltaY() const
0185     {
0186         return m_angleDelta.y();
0187     }
0188     Qt::MouseButtons buttons() const
0189     {
0190         return m_buttons;
0191     }
0192     Qt::KeyboardModifiers modifiers() const
0193     {
0194         return m_modifiers;
0195     }
0196     Qt::Orientation orientation()
0197     {
0198         return m_orientation;
0199     } // TODO KF6: remove
0200 
0201     // only for internal usage
0202     void setX(int x)
0203     {
0204         m_x = x;
0205     }
0206     void setY(int y)
0207     {
0208         m_y = y;
0209     }
0210 
0211 private:
0212     int m_x;
0213     int m_y;
0214     int m_screenX;
0215     int m_screenY;
0216     QPoint m_angleDelta;
0217     Qt::MouseButtons m_buttons;
0218     Qt::KeyboardModifiers m_modifiers;
0219     Qt::Orientation m_orientation;
0220 };
0221 
0222 class MouseEventListener : public QQuickItem
0223 {
0224     Q_OBJECT
0225     /**
0226      * This property holds whether hover events are handled.
0227      * By default hover events are disabled
0228      */
0229     Q_PROPERTY(bool hoverEnabled READ hoverEnabled WRITE setHoverEnabled NOTIFY hoverEnabledChanged)
0230 
0231     /**
0232      * True if this MouseEventListener or any of its children contains the mouse cursor:
0233      * this property will change only when the mouse button is pressed if hoverEnabled is false.
0234      */
0235     Q_PROPERTY(bool containsMouse READ containsMouse NOTIFY containsMouseChanged)
0236 
0237     Q_PROPERTY(Qt::MouseButtons acceptedButtons READ acceptedButtons WRITE setAcceptedButtons NOTIFY acceptedButtonsChanged)
0238 
0239     /**
0240      * This property holds the cursor shape for this mouse area.
0241      * Note that on platforms that do not display a mouse cursor this may have no effect.
0242      */
0243     Q_PROPERTY(Qt::CursorShape cursorShape READ cursorShape WRITE setCursorShape RESET unsetCursor NOTIFY cursorShapeChanged)
0244 
0245     /**
0246      * True if the mouse is pressed in the item or any of its children
0247      */
0248     Q_PROPERTY(bool pressed READ isPressed NOTIFY pressedChanged)
0249 
0250 public:
0251     MouseEventListener(QQuickItem *parent = nullptr);
0252     ~MouseEventListener() override;
0253 
0254     bool containsMouse() const;
0255     void setHoverEnabled(bool enable);
0256     bool hoverEnabled() const;
0257     bool isPressed() const;
0258 
0259     Qt::MouseButtons acceptedButtons() const;
0260     void setAcceptedButtons(Qt::MouseButtons buttons);
0261 
0262     Qt::CursorShape cursorShape() const;
0263     void setCursorShape(Qt::CursorShape shape);
0264 
0265 protected:
0266     void hoverEnterEvent(QHoverEvent *event) override;
0267     void hoverLeaveEvent(QHoverEvent *event) override;
0268     void hoverMoveEvent(QHoverEvent *event) override;
0269     void mousePressEvent(QMouseEvent *event) override;
0270     void mouseMoveEvent(QMouseEvent *event) override;
0271     void mouseReleaseEvent(QMouseEvent *event) override;
0272     void wheelEvent(QWheelEvent *event) override;
0273     bool childMouseEventFilter(QQuickItem *item, QEvent *event) override;
0274     void mouseUngrabEvent() override;
0275     void touchUngrabEvent() override;
0276 
0277 Q_SIGNALS:
0278     void pressed(KDeclarativeMouseEvent *mouse);
0279     void positionChanged(KDeclarativeMouseEvent *mouse);
0280     void released(KDeclarativeMouseEvent *mouse);
0281     void clicked(KDeclarativeMouseEvent *mouse);
0282     void pressAndHold(KDeclarativeMouseEvent *mouse);
0283     void wheelMoved(KDeclarativeWheelEvent *wheel);
0284     void containsMouseChanged(bool containsMouseChanged);
0285     void hoverEnabledChanged(bool hoverEnabled);
0286     void acceptedButtonsChanged();
0287     void cursorShapeChanged();
0288     void pressedChanged();
0289     void canceled();
0290 
0291 private Q_SLOTS:
0292     void handlePressAndHold();
0293     void handleUngrab();
0294 
0295 private:
0296     static QScreen *screenForGlobalPos(const QPoint &globalPos);
0297 
0298     bool m_pressed;
0299     KDeclarativeMouseEvent *m_pressAndHoldEvent;
0300     QPointF m_buttonDownPos;
0301     // Important: used only for comparison. If you will ever need to access this pointer, make it a QWeakPointer
0302     QEvent *m_lastEvent;
0303     QTimer *m_pressAndHoldTimer;
0304     bool m_containsMouse;
0305     Qt::MouseButtons m_acceptedButtons;
0306 };
0307 
0308 #endif