File: pointer_input.h

package info (click to toggle)
kwin 4%3A6.3.6-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 56,600 kB
  • sloc: cpp: 241,670; xml: 3,228; javascript: 2,214; ansic: 775; sh: 67; python: 15; makefile: 8
file content (299 lines) | stat: -rw-r--r-- 9,305 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
/*
    KWin - the KDE window manager
    This file is part of the KDE project.

    SPDX-FileCopyrightText: 2013, 2016 Martin Gräßlin <mgraesslin@kde.org>
    SPDX-FileCopyrightText: 2018 Roman Gilg <subdiff@gmail.com>
    SPDX-FileCopyrightText: 2019 Vlad Zahorodnii <vlad.zahorodnii@kde.org>

    SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once

#include "cursor.h"
#include "input.h"
#include "utils/cursortheme.h"

#include <QElapsedTimer>
#include <QObject>
#include <QPointF>
#include <QPointer>

class QWindow;

namespace KWin
{
class Window;
class CursorImage;
class InputDevice;
class InputRedirection;
class CursorShape;
class ShapeCursorSource;
class SurfaceCursorSource;
class PointerSurfaceCursor;
class SurfaceInterface;

namespace Decoration
{
class DecoratedWindowImpl;
}


class KWIN_EXPORT PointerInputRedirection : public InputDeviceHandler
{
    Q_OBJECT
public:
    explicit PointerInputRedirection(InputRedirection *parent);
    ~PointerInputRedirection() override;

    void init() override;

    CursorTheme cursorTheme() const; // TODO: Make it a Cursor property

    void updateAfterScreenChange();
    bool supportsWarping() const;
    void warp(const QPointF &pos);

    QPointF pos() const
    {
        return m_pos;
    }
    Qt::MouseButtons buttons() const
    {
        return m_qtButtons;
    }
    bool areButtonsPressed() const;

    void setEffectsOverrideCursor(Qt::CursorShape shape);
    void removeEffectsOverrideCursor();
    void setWindowSelectionCursor(const QByteArray &shape);
    void removeWindowSelectionCursor();

    void updatePointerConstraints();

    void setEnableConstraints(bool set);

    bool isConstrained() const
    {
        return m_confined || m_locked;
    }

    bool focusUpdatesBlocked() override;

    /**
     * @internal
     */
    void processMotionAbsolute(const QPointF &pos, std::chrono::microseconds time, InputDevice *device = nullptr);
    /**
     * @internal
     */
    void processMotion(const QPointF &delta, const QPointF &deltaNonAccelerated, std::chrono::microseconds time, InputDevice *device);
    /**
     * @internal
     */
    void processButton(uint32_t button, PointerButtonState state, std::chrono::microseconds time, InputDevice *device = nullptr);
    /**
     * @internal
     */
    void processAxis(PointerAxis axis, qreal delta, qint32 deltaV120, PointerAxisSource source, bool inverted, std::chrono::microseconds time, InputDevice *device = nullptr);
    /**
     * @internal
     */
    void processSwipeGestureBegin(int fingerCount, std::chrono::microseconds time, KWin::InputDevice *device = nullptr);
    /**
     * @internal
     */
    void processSwipeGestureUpdate(const QPointF &delta, std::chrono::microseconds time, KWin::InputDevice *device = nullptr);
    /**
     * @internal
     */
    void processSwipeGestureEnd(std::chrono::microseconds time, KWin::InputDevice *device = nullptr);
    /**
     * @internal
     */
    void processSwipeGestureCancelled(std::chrono::microseconds time, KWin::InputDevice *device = nullptr);
    /**
     * @internal
     */
    void processPinchGestureBegin(int fingerCount, std::chrono::microseconds time, KWin::InputDevice *device = nullptr);
    /**
     * @internal
     */
    void processPinchGestureUpdate(qreal scale, qreal angleDelta, const QPointF &delta, std::chrono::microseconds time, KWin::InputDevice *device = nullptr);
    /**
     * @internal
     */
    void processPinchGestureEnd(std::chrono::microseconds time, KWin::InputDevice *device = nullptr);
    /**
     * @internal
     */
    void processPinchGestureCancelled(std::chrono::microseconds time, KWin::InputDevice *device = nullptr);
    /**
     * @internal
     */
    void processHoldGestureBegin(int fingerCount, std::chrono::microseconds time, KWin::InputDevice *device = nullptr);
    /**
     * @internal
     */
    void processHoldGestureEnd(std::chrono::microseconds time, KWin::InputDevice *device = nullptr);
    /**
     * @internal
     */
    void processHoldGestureCancelled(std::chrono::microseconds time, KWin::InputDevice *device = nullptr);
    /**
     * @internal
     */
    void processFrame(KWin::InputDevice *device = nullptr);

private:
    enum class EdgeBarrierType {
        NormalBarrier,
        WindowMoveBarrier,
        // WindowResize is separate from WindowMove since there is edge snapping during resize, so a different resistance might be desirable
        WindowResizeBarrier,
        EdgeElementBarrier,
        CornerBarrier,
    };
    void processWarp(const QPointF &pos, std::chrono::microseconds time, InputDevice *device = nullptr);
    enum class MotionType {
        Motion,
        Warp
    };
    void processMotionInternal(const QPointF &pos, const QPointF &delta, const QPointF &deltaNonAccelerated, std::chrono::microseconds time, InputDevice *device, MotionType type);
    void cleanupDecoration(Decoration::DecoratedWindowImpl *old, Decoration::DecoratedWindowImpl *now) override;

    void focusUpdate(Window *focusOld, Window *focusNow) override;

    QPointF position() const override;

    void updateOnStartMoveResize();
    void updateToReset();
    void updatePosition(const QPointF &pos, std::chrono::microseconds time);
    void updateButton(uint32_t button, PointerButtonState state);
    QPointF applyEdgeBarrier(const QPointF &pos, const Output *currentOutput, std::chrono::microseconds time);
    EdgeBarrierType edgeBarrierType(const QPointF &pos, const QRectF &lastOutputGeometry) const;
    qreal edgeBarrier(EdgeBarrierType type) const;
    QPointF applyPointerConfinement(const QPointF &pos) const;
    void disconnectConfinedPointerRegionConnection();
    void disconnectLockedPointerAboutToBeUnboundConnection();
    void disconnectPointerConstraintsConnection();
    void breakPointerConstraints(SurfaceInterface *surface);
    CursorImage *m_cursor;
    QPointF m_pos;
    QHash<uint32_t, PointerButtonState> m_buttons;
    Qt::MouseButtons m_qtButtons;
    QMetaObject::Connection m_focusGeometryConnection;
    QMetaObject::Connection m_constraintsConnection;
    QMetaObject::Connection m_constraintsActivatedConnection;
    QMetaObject::Connection m_confinedPointerRegionConnection;
    QMetaObject::Connection m_lockedPointerAboutToBeUnboundConnection;
    QMetaObject::Connection m_decorationGeometryConnection;
    QMetaObject::Connection m_decorationDestroyedConnection;
    QMetaObject::Connection m_decorationClosedConnection;
    bool m_confined = false;
    bool m_locked = false;
    bool m_enableConstraints = true;
    bool m_lastOutputWasPlaceholder = true;
    QPointF m_movementInEdgeBarrier;
    std::chrono::microseconds m_lastMoveTime = std::chrono::microseconds::zero();
    friend class PositionUpdateBlocker;
    EdgeBarrierType m_lastEdgeBarrierType = EdgeBarrierType::NormalBarrier;
};

class WaylandCursorImage : public QObject
{
    Q_OBJECT
public:
    explicit WaylandCursorImage(QObject *parent = nullptr);

    CursorTheme theme() const;

Q_SIGNALS:
    void themeChanged();

private:
    void updateCursorTheme();

    CursorTheme m_cursorTheme;
};

class CursorImage : public QObject
{
    Q_OBJECT
public:
    explicit CursorImage(PointerInputRedirection *parent = nullptr);
    ~CursorImage() override;

    void setEffectsOverrideCursor(Qt::CursorShape shape);
    void removeEffectsOverrideCursor();
    void setWindowSelectionCursor(const QByteArray &shape);
    void removeWindowSelectionCursor();

    CursorTheme theme() const;
    CursorSource *source() const;
    void setSource(CursorSource *source);

    void updateCursorOutputs(const QPointF &pos);

Q_SIGNALS:
    void changed();

private:
    void reevaluteSource();
    void updateServerCursor(const std::variant<PointerSurfaceCursor *, QByteArray> &cursor);
    void updateDecoration();
    void updateDecorationCursor();
    void updateMoveResize();
    void updateDragCursor();

    void handleFocusedSurfaceChanged();

    PointerInputRedirection *m_pointer;
    CursorSource *m_currentSource = nullptr;
    WaylandCursorImage m_waylandImage;

    std::unique_ptr<ShapeCursorSource> m_effectsCursor;
    std::unique_ptr<ShapeCursorSource> m_fallbackCursor;
    std::unique_ptr<ShapeCursorSource> m_moveResizeCursor;
    std::unique_ptr<ShapeCursorSource> m_windowSelectionCursor;
    std::unique_ptr<ShapeCursorSource> m_dragCursor;

    struct
    {
        std::unique_ptr<ShapeCursorSource> cursor;
        QMetaObject::Connection connection;
    } m_decoration;
    struct
    {
        QMetaObject::Connection connection;
        std::unique_ptr<SurfaceCursorSource> surface;
        std::unique_ptr<ShapeCursorSource> shape;
        CursorSource *cursor = nullptr;
    } m_serverCursor;
};

/**
 * @brief Implementation using the InputRedirection framework to get pointer positions.
 *
 * Does not support warping of cursor.
 */
class InputRedirectionCursor : public KWin::Cursor
{
    Q_OBJECT
public:
    explicit InputRedirectionCursor();
    ~InputRedirectionCursor() override;

protected:
    void doSetPos() override;

private Q_SLOTS:
    void slotPosChanged(const QPointF &pos);
    void slotPointerButtonChanged();
    void slotModifiersChanged(Qt::KeyboardModifiers mods, Qt::KeyboardModifiers oldMods);

private:
    Qt::MouseButtons m_currentButtons;
};

}