File indexing completed on 2024-12-08 10:56:16

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 2013, 2016 Martin Gräßlin <mgraesslin@kde.org>
0006     SPDX-FileCopyrightText: 2018 Roman Gilg <subdiff@gmail.com>
0007     SPDX-FileCopyrightText: 2019 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
0008 
0009     SPDX-License-Identifier: GPL-2.0-or-later
0010 */
0011 #pragma once
0012 
0013 #include "cursor.h"
0014 #include "input.h"
0015 #include "utils/xcursortheme.h"
0016 
0017 #include <QElapsedTimer>
0018 #include <QObject>
0019 #include <QPointF>
0020 #include <QPointer>
0021 
0022 class QWindow;
0023 
0024 namespace KWaylandServer
0025 {
0026 class SurfaceInterface;
0027 }
0028 
0029 namespace KWin
0030 {
0031 class Window;
0032 class CursorImage;
0033 class InputDevice;
0034 class InputRedirection;
0035 class CursorShape;
0036 class ImageCursorSource;
0037 class ShapeCursorSource;
0038 class SurfaceCursorSource;
0039 
0040 namespace Decoration
0041 {
0042 class DecoratedClientImpl;
0043 }
0044 
0045 
0046 class KWIN_EXPORT PointerInputRedirection : public InputDeviceHandler
0047 {
0048     Q_OBJECT
0049 public:
0050     explicit PointerInputRedirection(InputRedirection *parent);
0051     ~PointerInputRedirection() override;
0052 
0053     void init() override;
0054 
0055     void updateAfterScreenChange();
0056     bool supportsWarping() const;
0057     void warp(const QPointF &pos);
0058 
0059     QPointF pos() const
0060     {
0061         return m_pos;
0062     }
0063     Qt::MouseButtons buttons() const
0064     {
0065         return m_qtButtons;
0066     }
0067     bool areButtonsPressed() const;
0068 
0069     void setEffectsOverrideCursor(Qt::CursorShape shape);
0070     void removeEffectsOverrideCursor();
0071     void setWindowSelectionCursor(const QByteArray &shape);
0072     void removeWindowSelectionCursor();
0073 
0074     void updatePointerConstraints();
0075     void updateCursorOutputs();
0076 
0077     void setEnableConstraints(bool set);
0078 
0079     bool isConstrained() const
0080     {
0081         return m_confined || m_locked;
0082     }
0083 
0084     bool focusUpdatesBlocked() override;
0085 
0086     /**
0087      * @internal
0088      */
0089     void processMotionAbsolute(const QPointF &pos, std::chrono::microseconds time, InputDevice *device = nullptr);
0090     /**
0091      * @internal
0092      */
0093     void processMotion(const QPointF &delta, const QPointF &deltaNonAccelerated, std::chrono::microseconds time, InputDevice *device);
0094     /**
0095      * @internal
0096      */
0097     void processButton(uint32_t button, InputRedirection::PointerButtonState state, std::chrono::microseconds time, InputDevice *device = nullptr);
0098     /**
0099      * @internal
0100      */
0101     void processAxis(InputRedirection::PointerAxis axis, qreal delta, qint32 deltaV120, InputRedirection::PointerAxisSource source, std::chrono::microseconds time, InputDevice *device = nullptr);
0102     /**
0103      * @internal
0104      */
0105     void processSwipeGestureBegin(int fingerCount, std::chrono::microseconds time, KWin::InputDevice *device = nullptr);
0106     /**
0107      * @internal
0108      */
0109     void processSwipeGestureUpdate(const QPointF &delta, std::chrono::microseconds time, KWin::InputDevice *device = nullptr);
0110     /**
0111      * @internal
0112      */
0113     void processSwipeGestureEnd(std::chrono::microseconds time, KWin::InputDevice *device = nullptr);
0114     /**
0115      * @internal
0116      */
0117     void processSwipeGestureCancelled(std::chrono::microseconds time, KWin::InputDevice *device = nullptr);
0118     /**
0119      * @internal
0120      */
0121     void processPinchGestureBegin(int fingerCount, std::chrono::microseconds time, KWin::InputDevice *device = nullptr);
0122     /**
0123      * @internal
0124      */
0125     void processPinchGestureUpdate(qreal scale, qreal angleDelta, const QPointF &delta, std::chrono::microseconds time, KWin::InputDevice *device = nullptr);
0126     /**
0127      * @internal
0128      */
0129     void processPinchGestureEnd(std::chrono::microseconds time, KWin::InputDevice *device = nullptr);
0130     /**
0131      * @internal
0132      */
0133     void processPinchGestureCancelled(std::chrono::microseconds time, KWin::InputDevice *device = nullptr);
0134     /**
0135      * @internal
0136      */
0137     void processHoldGestureBegin(int fingerCount, std::chrono::microseconds time, KWin::InputDevice *device = nullptr);
0138     /**
0139      * @internal
0140      */
0141     void processHoldGestureEnd(std::chrono::microseconds time, KWin::InputDevice *device = nullptr);
0142     /**
0143      * @internal
0144      */
0145     void processHoldGestureCancelled(std::chrono::microseconds time, KWin::InputDevice *device = nullptr);
0146 
0147 private:
0148     void processMotionInternal(const QPointF &pos, const QPointF &delta, const QPointF &deltaNonAccelerated, std::chrono::microseconds time, InputDevice *device);
0149     void cleanupDecoration(Decoration::DecoratedClientImpl *old, Decoration::DecoratedClientImpl *now) override;
0150 
0151     void focusUpdate(Window *focusOld, Window *focusNow) override;
0152 
0153     QPointF position() const override;
0154 
0155     void updateOnStartMoveResize();
0156     void updateToReset();
0157     void updatePosition(const QPointF &pos);
0158     void updateButton(uint32_t button, InputRedirection::PointerButtonState state);
0159     QPointF applyPointerConfinement(const QPointF &pos) const;
0160     void disconnectConfinedPointerRegionConnection();
0161     void disconnectLockedPointerAboutToBeUnboundConnection();
0162     void disconnectPointerConstraintsConnection();
0163     void breakPointerConstraints(KWaylandServer::SurfaceInterface *surface);
0164     CursorImage *m_cursor;
0165     QPointF m_pos;
0166     QHash<uint32_t, InputRedirection::PointerButtonState> m_buttons;
0167     Qt::MouseButtons m_qtButtons;
0168     QMetaObject::Connection m_focusGeometryConnection;
0169     QMetaObject::Connection m_constraintsConnection;
0170     QMetaObject::Connection m_constraintsActivatedConnection;
0171     QMetaObject::Connection m_confinedPointerRegionConnection;
0172     QMetaObject::Connection m_lockedPointerAboutToBeUnboundConnection;
0173     QMetaObject::Connection m_decorationGeometryConnection;
0174     QMetaObject::Connection m_decorationDestroyedConnection;
0175     bool m_confined = false;
0176     bool m_locked = false;
0177     bool m_enableConstraints = true;
0178     friend class PositionUpdateBlocker;
0179 };
0180 
0181 class WaylandCursorImage : public QObject
0182 {
0183     Q_OBJECT
0184 public:
0185     explicit WaylandCursorImage(QObject *parent = nullptr);
0186 
0187     KXcursorTheme theme() const;
0188 
0189     void loadThemeCursor(const CursorShape &shape, ImageCursorSource *source);
0190     void loadThemeCursor(const QByteArray &name, ImageCursorSource *source);
0191 
0192 Q_SIGNALS:
0193     void themeChanged();
0194 
0195 private:
0196     bool loadThemeCursor_helper(const QByteArray &name, ImageCursorSource *source);
0197     void updateCursorTheme();
0198 
0199     KXcursorTheme m_cursorTheme;
0200 };
0201 
0202 class CursorImage : public QObject
0203 {
0204     Q_OBJECT
0205 public:
0206     explicit CursorImage(PointerInputRedirection *parent = nullptr);
0207     ~CursorImage() override;
0208 
0209     void setEffectsOverrideCursor(Qt::CursorShape shape);
0210     void removeEffectsOverrideCursor();
0211     void setWindowSelectionCursor(const QByteArray &shape);
0212     void removeWindowSelectionCursor();
0213 
0214     KXcursorTheme theme() const;
0215     CursorSource *source() const;
0216     void setSource(CursorSource *source);
0217     void markAsRendered(std::chrono::milliseconds timestamp);
0218 
0219 Q_SIGNALS:
0220     void changed();
0221 
0222 private:
0223     void reevaluteSource();
0224     void updateServerCursor();
0225     void updateDecoration();
0226     void updateDecorationCursor();
0227     void updateMoveResize();
0228 
0229     void handleFocusedSurfaceChanged();
0230 
0231     PointerInputRedirection *m_pointer;
0232     CursorSource *m_currentSource = nullptr;
0233     WaylandCursorImage m_waylandImage;
0234 
0235     std::unique_ptr<ShapeCursorSource> m_effectsCursor;
0236     std::unique_ptr<ShapeCursorSource> m_fallbackCursor;
0237     std::unique_ptr<ShapeCursorSource> m_moveResizeCursor;
0238     std::unique_ptr<ShapeCursorSource> m_windowSelectionCursor;
0239 
0240     struct
0241     {
0242         std::unique_ptr<ShapeCursorSource> cursor;
0243         QMetaObject::Connection connection;
0244     } m_decoration;
0245     struct
0246     {
0247         QMetaObject::Connection connection;
0248         std::unique_ptr<SurfaceCursorSource> cursor;
0249     } m_serverCursor;
0250 };
0251 
0252 /**
0253  * @brief Implementation using the InputRedirection framework to get pointer positions.
0254  *
0255  * Does not support warping of cursor.
0256  */
0257 class InputRedirectionCursor : public KWin::Cursor
0258 {
0259     Q_OBJECT
0260 public:
0261     explicit InputRedirectionCursor(QObject *parent);
0262     ~InputRedirectionCursor() override;
0263 
0264 protected:
0265     void doSetPos() override;
0266 
0267 private Q_SLOTS:
0268     void slotPosChanged(const QPointF &pos);
0269     void slotPointerButtonChanged();
0270     void slotModifiersChanged(Qt::KeyboardModifiers mods, Qt::KeyboardModifiers oldMods);
0271 
0272 private:
0273     Qt::MouseButtons m_currentButtons;
0274 };
0275 
0276 }