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 }