File indexing completed on 2025-09-14 03:50:00

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