File indexing completed on 2025-03-16 05:04:48
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 }