1 | // Copyright (C) 2016 The Qt Company Ltd. |
---|---|
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #ifndef QWAYLANDINPUTDEVICE_H |
5 | #define QWAYLANDINPUTDEVICE_H |
6 | |
7 | // |
8 | // W A R N I N G |
9 | // ------------- |
10 | // |
11 | // This file is not part of the Qt API. It exists purely as an |
12 | // implementation detail. This header file may change from version to |
13 | // version without notice, or even be removed. |
14 | // |
15 | // We mean it. |
16 | // |
17 | |
18 | #include <QtWaylandClient/private/qtwaylandclientglobal_p.h> |
19 | #include <QtWaylandClient/private/qwaylandwindow_p.h> |
20 | |
21 | #include <QtCore/QScopedPointer> |
22 | #include <QSocketNotifier> |
23 | #include <QObject> |
24 | #include <QTimer> |
25 | #include <qpa/qplatformintegration.h> |
26 | #include <qpa/qplatformscreen.h> |
27 | #include <qpa/qwindowsysteminterface.h> |
28 | |
29 | #include <QtWaylandClient/private/qwayland-wayland.h> |
30 | #include <QtWaylandClient/private/qwayland-pointer-gestures-unstable-v1.h> |
31 | |
32 | #if QT_CONFIG(xkbcommon) |
33 | #include <QtGui/private/qxkbcommon_p.h> |
34 | #endif |
35 | |
36 | #include <QtCore/QDebug> |
37 | #include <QtCore/QElapsedTimer> |
38 | #include <QtCore/QPointer> |
39 | |
40 | #if QT_CONFIG(cursor) |
41 | struct wl_cursor_image; |
42 | #endif |
43 | |
44 | QT_BEGIN_NAMESPACE |
45 | |
46 | namespace QtWayland { |
47 | class zwp_primary_selection_device_v1; |
48 | } //namespace QtWayland |
49 | |
50 | namespace QtWaylandClient { |
51 | |
52 | class QWaylandDataDevice; |
53 | class QWaylandDisplay; |
54 | #if QT_CONFIG(wayland_client_primary_selection) |
55 | class QWaylandPrimarySelectionDeviceV1; |
56 | #endif |
57 | #if QT_CONFIG(tabletevent) |
58 | class QWaylandTabletSeatV2; |
59 | #endif |
60 | class QWaylandPointerGestures; |
61 | class QWaylandPointerGestureSwipe; |
62 | class QWaylandPointerGesturePinch; |
63 | class QWaylandTextInputInterface; |
64 | class QWaylandTextInputMethod; |
65 | #if QT_CONFIG(cursor) |
66 | class QWaylandCursorTheme; |
67 | class QWaylandCursorShape; |
68 | template <typename T> |
69 | class CursorSurface; |
70 | #endif |
71 | |
72 | Q_DECLARE_LOGGING_CATEGORY(lcQpaWaylandInput); |
73 | |
74 | class Q_WAYLANDCLIENT_EXPORT QWaylandInputDevice |
75 | : public QObject |
76 | , public QtWayland::wl_seat |
77 | { |
78 | Q_OBJECT |
79 | public: |
80 | class Keyboard; |
81 | class Pointer; |
82 | class Touch; |
83 | |
84 | QWaylandInputDevice(QWaylandDisplay *display, int version, uint32_t id); |
85 | ~QWaylandInputDevice() override; |
86 | |
87 | uint32_t id() const { return mId; } |
88 | uint32_t capabilities() const { return mCaps; } |
89 | QString seatname() const { return mSeatName; } |
90 | |
91 | QWaylandDisplay *display() const { return mQDisplay; } |
92 | struct ::wl_seat *wl_seat() { return QtWayland::wl_seat::object(); } |
93 | |
94 | #if QT_CONFIG(cursor) |
95 | void setCursor(const QCursor *cursor, const QSharedPointer<QWaylandBuffer> &cachedBuffer = {}, int fallbackOutputScale = 1); |
96 | #endif |
97 | void handleStartDrag(); |
98 | void handleEndDrag(); |
99 | |
100 | #if QT_CONFIG(wayland_datadevice) |
101 | void setDataDevice(QWaylandDataDevice *device); |
102 | QWaylandDataDevice *dataDevice() const; |
103 | #endif |
104 | |
105 | #if QT_CONFIG(wayland_client_primary_selection) |
106 | void setPrimarySelectionDevice(QWaylandPrimarySelectionDeviceV1 *primarySelectionDevice); |
107 | QWaylandPrimarySelectionDeviceV1 *primarySelectionDevice() const; |
108 | #endif |
109 | |
110 | #if QT_CONFIG(tabletevent) |
111 | void setTabletSeat(QWaylandTabletSeatV2 *tabletSeat); |
112 | QWaylandTabletSeatV2* tabletSeat() const; |
113 | #endif |
114 | |
115 | void setTextInput(QWaylandTextInputInterface *textInput); |
116 | QWaylandTextInputInterface *textInput() const; |
117 | |
118 | void setTextInputMethod(QWaylandTextInputMethod *textInputMethod); |
119 | QWaylandTextInputMethod *textInputMethod() const; |
120 | |
121 | void removeMouseButtonFromState(Qt::MouseButton button); |
122 | |
123 | QWaylandWindow *pointerFocus() const; |
124 | QWaylandWindow *keyboardFocus() const; |
125 | QWaylandWindow *touchFocus() const; |
126 | |
127 | QList<int> possibleKeys(const QKeyEvent *event) const; |
128 | |
129 | QPointF pointerSurfacePosition() const; |
130 | |
131 | Qt::KeyboardModifiers modifiers() const; |
132 | |
133 | uint32_t serial() const; |
134 | |
135 | virtual Keyboard *createKeyboard(QWaylandInputDevice *device); |
136 | virtual Pointer *createPointer(QWaylandInputDevice *device); |
137 | virtual Touch *createTouch(QWaylandInputDevice *device); |
138 | |
139 | Keyboard *keyboard() const; |
140 | Pointer *pointer() const; |
141 | QWaylandPointerGestureSwipe *pointerGestureSwipe() const; |
142 | QWaylandPointerGesturePinch *pointerGesturePinch() const; |
143 | Touch *touch() const; |
144 | |
145 | protected: |
146 | QWaylandDisplay *mQDisplay = nullptr; |
147 | struct wl_display *mDisplay = nullptr; |
148 | |
149 | uint32_t mId = -1; |
150 | uint32_t mCaps = 0; |
151 | QString mSeatName; |
152 | |
153 | #if QT_CONFIG(cursor) |
154 | struct CursorState { |
155 | QSharedPointer<QWaylandBuffer> bitmapBuffer; // not used with shape cursors |
156 | int bitmapScale = 1; |
157 | Qt::CursorShape shape = Qt::ArrowCursor; |
158 | int fallbackOutputScale = 1; |
159 | QPoint hotspot; |
160 | QElapsedTimer animationTimer; |
161 | } mCursor; |
162 | #endif |
163 | |
164 | #if QT_CONFIG(wayland_datadevice) |
165 | QWaylandDataDevice *mDataDevice = nullptr; |
166 | #endif |
167 | |
168 | #if QT_CONFIG(wayland_client_primary_selection) |
169 | QScopedPointer<QWaylandPrimarySelectionDeviceV1> mPrimarySelectionDevice; |
170 | #endif |
171 | |
172 | QScopedPointer<Keyboard> mKeyboard; |
173 | QScopedPointer<Pointer> mPointer; |
174 | QScopedPointer<QWaylandPointerGestureSwipe> mPointerGestureSwipe; |
175 | QScopedPointer<QWaylandPointerGesturePinch> mPointerGesturePinch; |
176 | QScopedPointer<Touch> mTouch; |
177 | |
178 | QScopedPointer<QWaylandTextInputInterface> mTextInput; |
179 | QScopedPointer<QWaylandTextInputMethod> mTextInputMethod; |
180 | #if QT_CONFIG(tabletevent) |
181 | QScopedPointer<QWaylandTabletSeatV2> mTabletSeat; |
182 | #endif |
183 | |
184 | uint32_t mTime = 0; |
185 | uint32_t mSerial = 0; |
186 | |
187 | void seat_capabilities(uint32_t caps) override; |
188 | void seat_name(const QString &name) override; |
189 | void handleTouchPoint(int id, QEventPoint::State state, const QPointF &surfacePosition = QPoint()); |
190 | |
191 | QPointingDevice *mTouchDevice = nullptr; |
192 | QPointingDevice *mTouchPadDevice = nullptr; |
193 | |
194 | friend class QWaylandTouchExtension; |
195 | friend class QWaylandQtKeyExtension; |
196 | friend class QWaylandPointerGestureSwipe; |
197 | friend class QWaylandPointerGesturePinch; |
198 | friend class QWaylandWindow; |
199 | friend class QWaylandTabletToolV2; |
200 | }; |
201 | |
202 | inline uint32_t QWaylandInputDevice::serial() const |
203 | { |
204 | return mSerial; |
205 | } |
206 | |
207 | |
208 | class Q_WAYLANDCLIENT_EXPORT QWaylandInputDevice::Keyboard : public QObject, public QtWayland::wl_keyboard |
209 | { |
210 | Q_OBJECT |
211 | |
212 | public: |
213 | Keyboard(QWaylandInputDevice *p); |
214 | ~Keyboard() override; |
215 | |
216 | QWaylandWindow *focusWindow() const; |
217 | |
218 | void keyboard_keymap(uint32_t format, |
219 | int32_t fd, |
220 | uint32_t size) override; |
221 | void keyboard_enter(uint32_t time, |
222 | struct wl_surface *surface, |
223 | struct wl_array *keys) override; |
224 | void keyboard_leave(uint32_t time, |
225 | struct wl_surface *surface) override; |
226 | void keyboard_key(uint32_t serial, uint32_t time, |
227 | uint32_t key, uint32_t state) override; |
228 | void keyboard_modifiers(uint32_t serial, |
229 | uint32_t mods_depressed, |
230 | uint32_t mods_latched, |
231 | uint32_t mods_locked, |
232 | uint32_t group) override; |
233 | void keyboard_repeat_info(int32_t rate, int32_t delay) override; |
234 | |
235 | QWaylandInputDevice *mParent = nullptr; |
236 | QPointer<QWaylandSurface> mFocus; |
237 | |
238 | uint32_t mNativeModifiers = 0; |
239 | |
240 | struct repeatKey { |
241 | int key = 0; |
242 | uint32_t code = 0; |
243 | uint32_t time = 0 ; |
244 | QString text; |
245 | uint32_t nativeVirtualKey = 0; |
246 | } mRepeatKey; |
247 | |
248 | QTimer mRepeatTimer; |
249 | int mRepeatRate = 25; |
250 | int mRepeatDelay = 400; |
251 | |
252 | uint32_t mKeymapFormat = WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1; |
253 | |
254 | Qt::KeyboardModifiers modifiers() const; |
255 | |
256 | struct ::wl_keyboard *wl_keyboard() { return QtWayland::wl_keyboard::object(); } |
257 | |
258 | #if QT_CONFIG(xkbcommon) |
259 | virtual int keysymToQtKey(xkb_keysym_t keysym, Qt::KeyboardModifiers modifiers, xkb_state *state, xkb_keycode_t code) { |
260 | return QXkbCommon::keysymToQtKey(keysym, modifiers, state, code); |
261 | } |
262 | #endif |
263 | |
264 | private Q_SLOTS: |
265 | void handleFocusDestroyed(); |
266 | void handleFocusLost(); |
267 | |
268 | private: |
269 | #if QT_CONFIG(xkbcommon) |
270 | bool createDefaultKeymap(); |
271 | #endif |
272 | void handleKey(ulong timestamp, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers, |
273 | quint32 nativeScanCode, quint32 nativeVirtualKey, quint32 nativeModifiers, |
274 | const QString &text, bool autorepeat = false, ushort count = 1); |
275 | |
276 | #if QT_CONFIG(xkbcommon) |
277 | QXkbCommon::ScopedXKBKeymap mXkbKeymap; |
278 | QXkbCommon::ScopedXKBState mXkbState; |
279 | #endif |
280 | friend class QWaylandInputDevice; |
281 | }; |
282 | |
283 | class Q_WAYLANDCLIENT_EXPORT QWaylandInputDevice::Pointer : public QObject, public QtWayland::wl_pointer |
284 | { |
285 | Q_OBJECT |
286 | public: |
287 | explicit Pointer(QWaylandInputDevice *seat); |
288 | ~Pointer() override; |
289 | QWaylandWindow *focusWindow() const; |
290 | #if QT_CONFIG(cursor) |
291 | int idealCursorScale() const; |
292 | void updateCursorTheme(); |
293 | void updateCursor(); |
294 | void cursorTimerCallback(); |
295 | void cursorFrameCallback(); |
296 | CursorSurface<QWaylandInputDevice::Pointer> *getOrCreateCursorSurface(); |
297 | #endif |
298 | QWaylandInputDevice *seat() const { return mParent; } |
299 | |
300 | struct ::wl_pointer *wl_pointer() { return QtWayland::wl_pointer::object(); } |
301 | |
302 | protected: |
303 | void pointer_enter(uint32_t serial, struct wl_surface *surface, |
304 | wl_fixed_t sx, wl_fixed_t sy) override; |
305 | void pointer_leave(uint32_t time, struct wl_surface *surface) override; |
306 | void pointer_motion(uint32_t time, |
307 | wl_fixed_t sx, wl_fixed_t sy) override; |
308 | void pointer_button(uint32_t serial, uint32_t time, |
309 | uint32_t button, uint32_t state) override; |
310 | void pointer_axis(uint32_t time, |
311 | uint32_t axis, |
312 | wl_fixed_t value) override; |
313 | void pointer_axis_source(uint32_t source) override; |
314 | void pointer_axis_stop(uint32_t time, uint32_t axis) override; |
315 | void pointer_axis_discrete(uint32_t axis, int32_t value) override; |
316 | void pointer_frame() override; |
317 | void pointer_axis_value120(uint32_t axis, int32_t value120) override; |
318 | void pointer_axis_relative_direction(uint32_t axis, uint32_t direction) override; |
319 | |
320 | private Q_SLOTS: |
321 | void handleFocusDestroyed() { invalidateFocus(); } |
322 | |
323 | private: |
324 | void invalidateFocus(); |
325 | |
326 | public: |
327 | void releaseButtons(); |
328 | void leavePointers(); |
329 | |
330 | QWaylandInputDevice *mParent = nullptr; |
331 | QPointer<QWaylandSurface> mFocus; |
332 | uint32_t mEnterSerial = 0; |
333 | #if QT_CONFIG(cursor) |
334 | struct { |
335 | QScopedPointer<QWaylandCursorShape> shape; |
336 | QWaylandCursorTheme *theme = nullptr; |
337 | int themeBufferScale = 0; |
338 | QScopedPointer<CursorSurface<QWaylandInputDevice::Pointer>> surface; |
339 | QTimer frameTimer; |
340 | bool gotFrameCallback = false; |
341 | bool gotTimerCallback = false; |
342 | } mCursor; |
343 | #endif |
344 | QPointF mSurfacePos; |
345 | QPointF mGlobalPos; |
346 | Qt::MouseButtons mButtons = Qt::NoButton; |
347 | Qt::MouseButton mLastButton = Qt::NoButton; |
348 | |
349 | struct FrameData { |
350 | QWaylandPointerEvent *event = nullptr; |
351 | |
352 | QPointF delta; |
353 | QPoint delta120; |
354 | axis_source axisSource = axis_source_wheel; |
355 | bool verticalAxisInverted = false; |
356 | bool horizontalAxisInverted = false; |
357 | |
358 | void resetScrollData(); |
359 | bool hasPixelDelta() const; |
360 | QPoint pixelDeltaAndError(QPointF *accumulatedError) const; |
361 | QPoint pixelDelta() const { return hasPixelDelta() ? delta.toPoint() : QPoint(); } |
362 | QPoint angleDelta() const; |
363 | Qt::MouseEventSource wheelEventSource() const; |
364 | } mFrameData; |
365 | |
366 | bool mScrollBeginSent = false; |
367 | QPointF mScrollDeltaRemainder; |
368 | |
369 | void setFrameEvent(QWaylandPointerEvent *event); |
370 | void flushScrollEvent(); |
371 | void flushFrameEvent(); |
372 | private: //TODO: should other methods be private as well? |
373 | bool isDefinitelyTerminated(axis_source source) const; |
374 | }; |
375 | |
376 | class Q_WAYLANDCLIENT_EXPORT QWaylandInputDevice::Touch : public QtWayland::wl_touch |
377 | { |
378 | public: |
379 | Touch(QWaylandInputDevice *p); |
380 | ~Touch() override; |
381 | |
382 | void touch_down(uint32_t serial, |
383 | uint32_t time, |
384 | struct wl_surface *surface, |
385 | int32_t id, |
386 | wl_fixed_t x, |
387 | wl_fixed_t y) override; |
388 | void touch_up(uint32_t serial, |
389 | uint32_t time, |
390 | int32_t id) override; |
391 | void touch_motion(uint32_t time, |
392 | int32_t id, |
393 | wl_fixed_t x, |
394 | wl_fixed_t y) override; |
395 | void touch_frame() override; |
396 | void touch_cancel() override; |
397 | |
398 | bool allTouchPointsReleased(); |
399 | void releasePoints(); |
400 | |
401 | struct ::wl_touch *wl_touch() { return QtWayland::wl_touch::object(); } |
402 | |
403 | QWaylandInputDevice *mParent = nullptr; |
404 | QPointer<QWaylandWindow> mFocus; |
405 | QList<QWindowSystemInterface::TouchPoint> mPendingTouchPoints; |
406 | }; |
407 | |
408 | class QWaylandPointerEvent |
409 | { |
410 | Q_GADGET |
411 | public: |
412 | inline QWaylandPointerEvent(QEvent::Type type, Qt::ScrollPhase phase, QWaylandWindow *surface, |
413 | ulong timestamp, const QPointF &localPos, const QPointF &globalPos, |
414 | Qt::MouseButtons buttons, Qt::MouseButton button, |
415 | Qt::KeyboardModifiers modifiers) |
416 | : type(type) |
417 | , phase(phase) |
418 | , timestamp(timestamp) |
419 | , local(localPos) |
420 | , global(globalPos) |
421 | , buttons(buttons) |
422 | , button(button) |
423 | , modifiers(modifiers) |
424 | , surface(surface) |
425 | {} |
426 | inline QWaylandPointerEvent(QEvent::Type type, Qt::ScrollPhase phase, QWaylandWindow *surface, |
427 | ulong timestamp, const QPointF &local, const QPointF &global, |
428 | const QPoint &pixelDelta, const QPoint &angleDelta, |
429 | Qt::MouseEventSource source, |
430 | Qt::KeyboardModifiers modifiers, bool inverted) |
431 | : type(type) |
432 | , phase(phase) |
433 | , timestamp(timestamp) |
434 | , local(local) |
435 | , global(global) |
436 | , modifiers(modifiers) |
437 | , pixelDelta(pixelDelta) |
438 | , angleDelta(angleDelta) |
439 | , source(source) |
440 | , surface(surface) |
441 | , inverted(inverted) |
442 | {} |
443 | |
444 | QEvent::Type type = QEvent::None; |
445 | Qt::ScrollPhase phase = Qt::NoScrollPhase; |
446 | ulong timestamp = 0; |
447 | QPointF local; |
448 | QPointF global; |
449 | Qt::MouseButtons buttons; |
450 | Qt::MouseButton button = Qt::NoButton; // Button that caused the event (QMouseEvent::button) |
451 | Qt::KeyboardModifiers modifiers; |
452 | QPoint pixelDelta; |
453 | QPoint angleDelta; |
454 | Qt::MouseEventSource source = Qt::MouseEventNotSynthesized; |
455 | QPointer<QWaylandWindow> surface; |
456 | bool inverted = false; |
457 | }; |
458 | |
459 | #ifndef QT_NO_GESTURES |
460 | class QWaylandPointerGestureSwipeEvent |
461 | { |
462 | Q_GADGET |
463 | public: |
464 | inline QWaylandPointerGestureSwipeEvent(QWaylandWindow *surface, Qt::GestureState state, |
465 | ulong timestamp, const QPointF &local, |
466 | const QPointF &global, uint fingers, const QPointF& delta) |
467 | : surface(surface) |
468 | , state(state) |
469 | , timestamp(timestamp) |
470 | , local(local) |
471 | , global(global) |
472 | , fingers(fingers) |
473 | , delta(delta) |
474 | {} |
475 | |
476 | QPointer<QWaylandWindow> surface; |
477 | Qt::GestureState state = Qt::GestureState::NoGesture; |
478 | ulong timestamp = 0; |
479 | QPointF local; |
480 | QPointF global; |
481 | uint fingers = 0; |
482 | QPointF delta; |
483 | }; |
484 | |
485 | class QWaylandPointerGesturePinchEvent |
486 | { |
487 | Q_GADGET |
488 | public: |
489 | inline QWaylandPointerGesturePinchEvent(QWaylandWindow *surface, Qt::GestureState state, |
490 | ulong timestamp, const QPointF &local, |
491 | const QPointF &global, uint fingers, const QPointF& delta, |
492 | qreal scale_delta, qreal rotation_delta) |
493 | : surface(surface) |
494 | , state(state) |
495 | , timestamp(timestamp) |
496 | , local(local) |
497 | , global(global) |
498 | , fingers(fingers) |
499 | , delta(delta) |
500 | , scale_delta(scale_delta) |
501 | , rotation_delta(rotation_delta) |
502 | {} |
503 | |
504 | QPointer<QWaylandWindow> surface; |
505 | Qt::GestureState state = Qt::GestureState::NoGesture; |
506 | ulong timestamp = 0; |
507 | QPointF local; |
508 | QPointF global; |
509 | uint fingers = 0; |
510 | QPointF delta; |
511 | qreal scale_delta = 0; |
512 | qreal rotation_delta = 0; |
513 | }; |
514 | #endif // #ifndef QT_NO_GESTURES |
515 | |
516 | } |
517 | |
518 | QT_END_NAMESPACE |
519 | |
520 | #endif |
521 |
Definitions
- QWaylandInputDevice
- id
- capabilities
- seatname
- display
- wl_seat
- CursorState
- serial
- Keyboard
- repeatKey
- wl_keyboard
- keysymToQtKey
- Pointer
- seat
- wl_pointer
- handleFocusDestroyed
- FrameData
- pixelDelta
- Touch
- wl_touch
- QWaylandPointerEvent
- QWaylandPointerEvent
- QWaylandPointerEvent
- QWaylandPointerGestureSwipeEvent
- QWaylandPointerGestureSwipeEvent
- QWaylandPointerGesturePinchEvent
Learn Advanced QML with KDAB
Find out more