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)
41struct wl_cursor_image;
42#endif
43
44QT_BEGIN_NAMESPACE
45
46namespace QtWayland {
47class zwp_primary_selection_device_v1;
48} //namespace QtWayland
49
50namespace QtWaylandClient {
51
52class QWaylandDataDevice;
53class QWaylandDisplay;
54#if QT_CONFIG(wayland_client_primary_selection)
55class QWaylandPrimarySelectionDeviceV1;
56#endif
57#if QT_CONFIG(tabletevent)
58class QWaylandTabletSeatV2;
59#endif
60class QWaylandPointerGestures;
61class QWaylandPointerGestureSwipe;
62class QWaylandPointerGesturePinch;
63class QWaylandTextInputInterface;
64class QWaylandTextInputMethod;
65#if QT_CONFIG(cursor)
66class QWaylandCursorTheme;
67class QWaylandCursorShape;
68template <typename T>
69class CursorSurface;
70#endif
71
72Q_DECLARE_LOGGING_CATEGORY(lcQpaWaylandInput);
73
74class Q_WAYLANDCLIENT_EXPORT QWaylandInputDevice
75 : public QObject
76 , public QtWayland::wl_seat
77{
78 Q_OBJECT
79public:
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
145protected:
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
202inline uint32_t QWaylandInputDevice::serial() const
203{
204 return mSerial;
205}
206
207
208class Q_WAYLANDCLIENT_EXPORT QWaylandInputDevice::Keyboard : public QObject, public QtWayland::wl_keyboard
209{
210 Q_OBJECT
211
212public:
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
264private Q_SLOTS:
265 void handleFocusDestroyed();
266 void handleFocusLost();
267
268private:
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
283class Q_WAYLANDCLIENT_EXPORT QWaylandInputDevice::Pointer : public QObject, public QtWayland::wl_pointer
284{
285 Q_OBJECT
286public:
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
302protected:
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
320private Q_SLOTS:
321 void handleFocusDestroyed() { invalidateFocus(); }
322
323private:
324 void invalidateFocus();
325
326public:
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();
372private: //TODO: should other methods be private as well?
373 bool isDefinitelyTerminated(axis_source source) const;
374};
375
376class Q_WAYLANDCLIENT_EXPORT QWaylandInputDevice::Touch : public QtWayland::wl_touch
377{
378public:
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
408class QWaylandPointerEvent
409{
410 Q_GADGET
411public:
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
460class QWaylandPointerGestureSwipeEvent
461{
462 Q_GADGET
463public:
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
485class QWaylandPointerGesturePinchEvent
486{
487 Q_GADGET
488public:
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
518QT_END_NAMESPACE
519
520#endif
521

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

source code of qtwayland/src/client/qwaylandinputdevice_p.h