File indexing completed on 2024-04-28 05:30:28

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