Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
Loading...
Searching...
No Matches
qwaylandinputdevice.cpp
Go to the documentation of this file.
1
// Copyright (C) 2016 The Qt Company Ltd.
2
// Copyright (C) 2024 Jie Liu <liujie01@kylinos.cn>
3
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
// Qt-Security score:significant reason:default
5
6
#
include
"qwaylandinputdevice_p.h"
7
8
#
include
"qwaylandintegration_p.h"
9
#
include
"qwaylandtextinputv3_p.h"
10
#
include
"qwaylandwindow_p.h"
11
#
include
"qwaylandsurface_p.h"
12
#
include
"qwaylandbuffer_p.h"
13
#
if
QT_CONFIG
(
wayland_datadevice
)
14
#
include
"qwaylanddatadevice_p.h"
15
#
include
"qwaylanddatadevicemanager_p.h"
16
#
endif
17
#
if
QT_CONFIG
(
clipboard
)
18
#
include
"qwaylanddatacontrolv1_p.h"
19
#
endif
20
#
if
QT_CONFIG
(
wayland_client_primary_selection
)
21
#
include
"qwaylandprimaryselectionv1_p.h"
22
#
endif
23
#
if
QT_CONFIG
(
tabletevent
)
24
#
include
"qwaylandtabletv2_p.h"
25
#
endif
26
#
include
"qwaylandpointergestures_p.h"
27
#
include
"qwaylandscreen_p.h"
28
#
include
"qwaylandcursor_p.h"
29
#
include
"qwaylanddisplay_p.h"
30
#
include
"qwaylandshmbackingstore_p.h"
31
#
include
"qwaylandtextinputv1_p.h"
32
#
include
"qwaylandtextinputv2_p.h"
33
#
include
"qwaylandtextinputinterface_p.h"
34
#
include
"qwaylandinputcontext_p.h"
35
#
include
"qwaylandinputmethodcontext_p.h"
36
#
include
"qwaylandcallback_p.h"
37
#
include
"qwaylandcursorsurface_p.h"
38
#
include
"qwaylanddecorationhandler_p.h"
39
40
#
include
<
QtGui
/
private
/
qpixmap_raster_p
.
h
>
41
#
include
<
QtGui
/
private
/
qguiapplication_p
.
h
>
42
#
include
<
qpa
/
qplatformwindow
.
h
>
43
#
include
<
qpa
/
qplatforminputcontext
.
h
>
44
#
include
<
qpa
/
qplatformtheme
.
h
>
45
#
include
<
QDebug
>
46
#
include
<
QtCore
/
qbytearrayview
.
h
>
47
#
include
<
QtCore
/
qscopeguard
.
h
>
48
49
#
include
<
unistd
.
h
>
50
#
include
<
fcntl
.
h
>
51
#
include
<
sys
/
mman
.
h
>
52
53
#
if
QT_CONFIG
(
cursor
)
54
#
include
<
wayland
-
cursor
.
h
>
55
#
endif
56
57
#
include
<
QtGui
/
QGuiApplication
>
58
#
include
<
QtGui
/
QPointingDevice
>
59
60
QT_BEGIN_NAMESPACE
61
62
namespace
QtWaylandClient
{
63
64
Q_LOGGING_CATEGORY
(
lcQpaWaylandInput
,
"qt.qpa.wayland.input"
);
65
66
// The maximum number of concurrent touchpoints is not exposed in wayland, so we assume a
67
// reasonable number of them. As of 2021 most touchscreen panels support 10 concurrent touchpoints.
68
static
const
int
MaxTouchPoints
= 10;
69
70
QWaylandEventCompressionPrivate
::
QWaylandEventCompressionPrivate
()
71
{
72
timeElapsed.start();
73
delayTimer.setSingleShot(
true
);
74
}
75
76
bool
QWaylandEventCompressionPrivate
::
compressEvent
()
77
{
78
using
namespace
std::chrono_literals;
79
80
if
(!QCoreApplication::testAttribute(Qt::AA_CompressHighFrequencyEvents))
81
return
false
;
82
83
const
auto
elapsed = timeElapsed.durationElapsed();
84
timeElapsed.start();
85
if
(elapsed < 100us || delayTimer.isActive())
86
{
87
// The highest USB HID polling rate is 8 kHz (125 μs). Most mice use lowe polling rate [125 Hz - 1000 Hz].
88
// Reject all events faster than 100 μs, because it definitely means the application main thread is
89
// freezed by long operation and events are delivered one after another from the queue. Since now we rely
90
// on the 0 ms timer to deliver the last pending event when application main thread is no longer freezed.
91
delayTimer.start(0);
92
return
true
;
93
}
94
95
return
false
;
96
}
97
98
QWaylandInputDevice
::
Keyboard
::
Keyboard
(
QWaylandInputDevice
*
p
)
99
:
mParent
(
p
)
100
{
101
init
(
p
->
get_keyboard
());
102
mRepeatTimer
.
callOnTimeout
(
this
, [&]() {
103
if
(!
focusSurface
()) {
104
// We destroyed the keyboard focus surface, but the server didn't get the message yet...
105
// or the server didn't send an enter event first.
106
return
;
107
}
108
mRepeatTimer
.
setInterval
(1000 /
mRepeatRate
);
109
Qt
::
KeyboardModifiers
modifiers
=
this
->
modifiers
();
110
handleKey
(
mRepeatKey
.
time
,
QEvent
::
KeyRelease
,
mRepeatKey
.
key
,
modifiers
,
111
mRepeatKey
.
code
,
mRepeatKey
.
nativeVirtualKey
,
this
->
mNativeModifiers
,
112
mRepeatKey
.
text
,
true
);
113
handleKey
(
mRepeatKey
.
time
,
QEvent
::
KeyPress
,
mRepeatKey
.
key
,
modifiers
,
114
mRepeatKey
.
code
,
mRepeatKey
.
nativeVirtualKey
,
this
->
mNativeModifiers
,
115
mRepeatKey
.
text
,
true
);
116
});
117
}
118
119
#
if
QT_CONFIG
(
xkbcommon
)
120
bool
QWaylandInputDevice
::
Keyboard
::
createDefaultKeymap
()
121
{
122
struct
xkb_context
*
ctx
=
mParent
->
mQDisplay
->
xkbContext
();
123
if
(!
ctx
)
124
return
false
;
125
126
struct
xkb_rule_names
names
;
127
names
.
rules
=
"evdev"
;
128
names
.
model
=
"pc105"
;
129
names
.
layout
=
"us"
;
130
names
.
variant
=
""
;
131
names
.
options
=
""
;
132
133
mXkbKeymap
.
reset
(
xkb_keymap_new_from_names
(
ctx
, &
names
,
XKB_KEYMAP_COMPILE_NO_FLAGS
));
134
if
(
mXkbKeymap
)
135
mXkbState
.
reset
(
xkb_state_new
(
mXkbKeymap
.
get
()));
136
137
if
(!
mXkbKeymap
|| !
mXkbState
) {
138
qCWarning
(
lcQpaWayland
,
"failed to create default keymap"
);
139
return
false
;
140
}
141
142
return
true
;
143
}
144
#
endif
145
146
QWaylandInputDevice
::
Keyboard
::~
Keyboard
()
147
{
148
if
(
mFocus
)
149
QWindowSystemInterface
::
handleFocusWindowChanged
(
nullptr
);
150
if
(
version
() >= 3)
151
wl_keyboard_release
(
object
());
152
else
153
wl_keyboard_destroy
(
object
());
154
}
155
156
QWaylandSurface
*
QWaylandInputDevice
::
Keyboard
::
focusSurface
()
const
157
{
158
return
mFocus
;
159
}
160
161
QWaylandInputDevice
::
Pointer
::
Pointer
(
QWaylandInputDevice
*
seat
)
162
:
mParent
(
seat
)
163
{
164
init
(
seat
->
get_pointer
());
165
#
if
QT_CONFIG
(
cursor
)
166
if
(
auto
cursorShapeManager
=
seat
->
mQDisplay
->
cursorShapeManager
()) {
167
mCursor
.
shape
.
reset
(
new
QWaylandCursorShape
(
cursorShapeManager
->
get_pointer
(
object
())));
168
}
169
170
mCursor
.
frameTimer
.
setSingleShot
(
true
);
171
mCursor
.
frameTimer
.
callOnTimeout
(
this
, [&]() {
172
cursorTimerCallback
();
173
});
174
#
endif
175
176
mEventCompression
.
delayTimer
.
callOnTimeout
(
this
, &
QWaylandInputDevice
::
Pointer
::
flushFrameEvent
);
177
}
178
179
QWaylandInputDevice
::
Pointer
::~
Pointer
()
180
{
181
if
(
version
() >= 3)
182
wl_pointer_release
(
object
());
183
else
184
wl_pointer_destroy
(
object
());
185
}
186
187
QWaylandSurface
*
QWaylandInputDevice
::
Pointer
::
focusSurface
()
const
188
{
189
return
mFocus
;
190
}
191
192
#
if
QT_CONFIG
(
cursor
)
193
194
int
QWaylandInputDevice
::
Pointer
::
idealCursorScale
()
const
195
{
196
if
(
seat
()->
mQDisplay
->
compositor
()->
version
() < 3) {
197
return
1;
198
}
199
200
if
(
auto
*
s
=
mCursor
.
surface
.
get
()) {
201
if
(
s
->
outputScale
() > 0)
202
return
s
->
outputScale
();
203
}
204
205
return
seat
()->
mCursor
.
fallbackOutputScale
;
206
}
207
208
void
QWaylandInputDevice
::
Pointer
::
updateCursorTheme
()
209
{
210
QString
cursorThemeName
;
211
QSize
cursorSize
;
212
213
if
(
const
QPlatformTheme
*
platformTheme
=
QGuiApplicationPrivate
::
platformTheme
()) {
214
cursorThemeName
=
platformTheme
->
themeHint
(
QPlatformTheme
::
MouseCursorTheme
).
toString
();
215
cursorSize
=
platformTheme
->
themeHint
(
QPlatformTheme
::
MouseCursorSize
).
toSize
();
216
}
217
218
if
(
cursorThemeName
.
isEmpty
())
219
cursorThemeName
=
QStringLiteral
(
"default"
);
220
if
(
cursorSize
.
isEmpty
())
221
cursorSize
=
QSize
(24, 24);
222
223
int
scale
=
idealCursorScale
();
224
int
pixelSize
=
cursorSize
.
width
() *
scale
;
225
auto
*
display
=
seat
()->
mQDisplay
;
226
mCursor
.
theme
=
display
->
loadCursorTheme
(
cursorThemeName
,
pixelSize
);
227
228
if
(!
mCursor
.
theme
)
229
return
;
// A warning has already been printed in loadCursorTheme
230
231
if
(
auto
*
arrow
=
mCursor
.
theme
->
cursor
(
Qt
::
ArrowCursor
)) {
232
int
arrowPixelSize
=
qMax
(
arrow
->
images
[0]->
width
,
arrow
->
images
[0]->
height
);
// Not all cursor themes are square
233
while
(
scale
> 1 &&
arrowPixelSize
/
scale
<
cursorSize
.
width
())
234
--
scale
;
235
}
else
{
236
qCWarning
(
lcQpaWayland
) <<
"Cursor theme does not support the arrow cursor"
;
237
}
238
mCursor
.
themeBufferScale
=
scale
;
239
}
240
241
void
QWaylandInputDevice
::
Pointer
::
updateCursor
()
242
{
243
if
(
mEnterSerial
== 0)
244
return
;
245
246
auto
shape
=
seat
()->
mCursor
.
shape
;
247
248
if
(
shape
==
Qt
::
BlankCursor
) {
249
if
(
mCursor
.
surface
)
250
mCursor
.
surface
->
reset
();
251
set_cursor
(
mEnterSerial
,
nullptr
, 0, 0);
252
return
;
253
}
254
255
if
(
shape
==
Qt
::
BitmapCursor
) {
256
auto
buffer
=
seat
()->
mCursor
.
bitmapBuffer
;
257
if
(!
buffer
) {
258
qCWarning
(
lcQpaWayland
) <<
"No buffer for bitmap cursor, can't set cursor"
;
259
return
;
260
}
261
auto
hotspot
=
seat
()->
mCursor
.
hotspot
;
262
int
bufferScale
=
seat
()->
mCursor
.
bitmapScale
;
263
getOrCreateCursorSurface
()->
update
(
buffer
->
buffer
(),
hotspot
,
buffer
->
size
(),
bufferScale
);
264
return
;
265
}
266
267
if
(
mCursor
.
shape
) {
268
if
(
mCursor
.
surface
) {
269
mCursor
.
surface
->
reset
();
270
}
271
mCursor
.
shape
->
setShape
(
mEnterSerial
,
shape
);
272
return
;
273
}
274
275
if
(!
mCursor
.
theme
||
idealCursorScale
() !=
mCursor
.
themeBufferScale
)
276
updateCursorTheme
();
277
278
if
(!
mCursor
.
theme
)
279
return
;
280
281
// Set from shape using theme
282
const
QElapsedTimer
&
timer
=
seat
()->
mCursor
.
animationTimer
;
283
const
uint
time
=
timer
.
isValid
() ?
timer
.
elapsed
() : 0;
284
285
if
(
struct
::
wl_cursor
*
waylandCursor
=
mCursor
.
theme
->
cursor
(
shape
)) {
286
uint
duration
= 0;
287
int
frame
=
wl_cursor_frame_and_duration
(
waylandCursor
,
time
, &
duration
);
288
::
wl_cursor_image
*
image
=
waylandCursor
->
images
[
frame
];
289
290
struct
wl_buffer
*
buffer
=
wl_cursor_image_get_buffer
(
image
);
291
if
(!
buffer
) {
292
qCWarning
(
lcQpaWayland
) <<
"Could not find buffer for cursor"
<<
shape
;
293
return
;
294
}
295
int
bufferScale
=
mCursor
.
themeBufferScale
;
296
QPoint
hotspot
=
QPoint
(
image
->
hotspot_x
,
image
->
hotspot_y
) /
bufferScale
;
297
QSize
size
=
QSize
(
image
->
width
,
image
->
height
) /
bufferScale
;
298
bool
animated
=
duration
> 0;
299
if
(
animated
) {
300
mCursor
.
gotFrameCallback
=
false
;
301
mCursor
.
gotTimerCallback
=
false
;
302
mCursor
.
frameTimer
.
start
(
duration
);
303
}
304
getOrCreateCursorSurface
()->
update
(
buffer
,
hotspot
,
size
,
bufferScale
,
animated
);
305
return
;
306
}
307
308
qCWarning
(
lcQpaWayland
) <<
"Unable to change to cursor"
<<
shape
;
309
}
310
311
CursorSurface
<
QWaylandInputDevice
::
Pointer
> *
312
QWaylandInputDevice
::
Pointer
::
getOrCreateCursorSurface
()
313
{
314
if
(!
mCursor
.
surface
)
315
mCursor
.
surface
.
reset
(
new
CursorSurface
(
this
,
seat
()->
mQDisplay
));
316
return
mCursor
.
surface
.
get
();
317
}
318
319
void
QWaylandInputDevice
::
Pointer
::
cursorTimerCallback
()
320
{
321
mCursor
.
gotTimerCallback
=
true
;
322
if
(
mCursor
.
gotFrameCallback
) {
323
updateCursor
();
324
}
325
}
326
327
void
QWaylandInputDevice
::
Pointer
::
cursorFrameCallback
()
328
{
329
mCursor
.
gotFrameCallback
=
true
;
330
if
(
mCursor
.
gotTimerCallback
) {
331
updateCursor
();
332
}
333
}
334
335
#
endif
// QT_CONFIG(cursor)
336
337
QWaylandInputDevice
::
Touch
::
Touch
(
QWaylandInputDevice
*
p
)
338
:
mParent
(
p
)
339
{
340
init
(
p
->
get_touch
());
341
}
342
343
QWaylandInputDevice
::
Touch
::~
Touch
()
344
{
345
if
(
version
() >= 3)
346
wl_touch_release
(
object
());
347
else
348
wl_touch_destroy
(
object
());
349
}
350
351
QWaylandInputDevice
::
QWaylandInputDevice
(
QWaylandDisplay
*
display
,
int
version
,
uint32_t
id
)
352
:
QtWayland
::
wl_seat
(
display
->
wl_registry
(),
id
,
qMin
(
version
, 10))
353
,
mQDisplay
(
display
)
354
,
mDisplay
(
display
->
wl_display
())
355
,
mId
(
id
)
356
{
357
358
#
if
QT_CONFIG
(
clipboard
)
359
if
(
auto
*
dataControlManager
=
mQDisplay
->
dataControlManager
()) {
360
setDataControlDevice
(
dataControlManager
->
createDevice
(
this
));
361
}
362
#
endif
363
364
#
if
QT_CONFIG
(
wayland_datadevice
)
365
if
(
mQDisplay
->
dndSelectionHandler
()) {
366
mDataDevice
=
mQDisplay
->
dndSelectionHandler
()->
getDataDevice
(
this
);
367
}
368
#
endif
369
370
#
if
QT_CONFIG
(
wayland_client_primary_selection
)
371
// TODO: Could probably decouple this more if there was a signal for new seat added
372
if
(
auto
*
psm
=
mQDisplay
->
primarySelectionManager
())
373
setPrimarySelectionDevice
(
psm
->
createDevice
(
this
));
374
#
endif
375
376
if
(
mQDisplay
->
textInputManagerv1
()) {
377
auto
textInput
=
new
QWaylandTextInputv1
(
mQDisplay
,
mQDisplay
->
textInputManagerv1
()->
create_text_input
());
378
textInput
->
setSeat
(
wl_seat
());
379
mTextInput
.
reset
(
textInput
);
380
}
381
382
if
(
mQDisplay
->
textInputManagerv2
())
383
mTextInput
.
reset
(
new
QWaylandTextInputv2
(
mQDisplay
,
mQDisplay
->
textInputManagerv2
()->
get_text_input
(
wl_seat
())));
384
385
if
(
mQDisplay
->
textInputManagerv3
())
386
mTextInput
.
reset
(
new
QWaylandTextInputv3
(
mQDisplay
,
mQDisplay
->
textInputManagerv3
()->
get_text_input
(
wl_seat
())));
387
388
if
(
mQDisplay
->
textInputMethodManager
())
389
mTextInputMethod
.
reset
(
new
QWaylandTextInputMethod
(
mQDisplay
,
mQDisplay
->
textInputMethodManager
()->
get_text_input_method
(
wl_seat
())));
390
391
#
if
QT_CONFIG
(
tabletevent
)
392
if
(
auto
*
tm
=
mQDisplay
->
tabletManager
())
393
mTabletSeat
.
reset
(
new
QWaylandTabletSeatV2
(
tm
,
this
));
394
#
endif
395
}
396
397
QWaylandInputDevice
::~
QWaylandInputDevice
()
398
{
399
if
(
version
() >=
WL_SEAT_RELEASE_SINCE_VERSION
)
400
release
();
401
else
402
wl_seat_destroy
(
object
());
403
}
404
405
void
QWaylandInputDevice
::
seat_capabilities
(
uint32_t
caps
)
406
{
407
mCaps
=
caps
;
408
409
if
(
mCaps
&
WL_SEAT_CAPABILITY_KEYBOARD
&& !
mKeyboard
) {
410
mKeyboard
.
reset
(
createKeyboard
(
this
));
411
}
else
if
(!(
mCaps
&
WL_SEAT_CAPABILITY_KEYBOARD
) &&
mKeyboard
) {
412
mKeyboard
.
reset
();
413
}
414
415
if
(
mCaps
&
WL_SEAT_CAPABILITY_POINTER
&& !
mPointer
) {
416
mPointer
.
reset
(
createPointer
(
this
));
417
418
auto
*
pointerGestures
=
mQDisplay
->
pointerGestures
();
419
if
(
pointerGestures
) {
420
// NOTE: The name of the device and its system ID are not exposed on Wayland.
421
mTouchPadDevice
=
new
QPointingDevice
(
422
QLatin1StringView
(
"touchpad"
), 0,
QInputDevice
::
DeviceType
::
TouchPad
,
423
QPointingDevice
::
PointerType
::
Finger
,
QInputDevice
::
Capability
::
Position
,
424
MaxTouchPoints
, 0,
mSeatName
,
QPointingDeviceUniqueId
(),
this
);
425
QWindowSystemInterface
::
registerInputDevice
(
mTouchPadDevice
);
426
mPointerGesturePinch
.
reset
(
pointerGestures
->
createPointerGesturePinch
(
this
));
427
mPointerGestureSwipe
.
reset
(
pointerGestures
->
createPointerGestureSwipe
(
this
));
428
}
429
}
else
if
(!(
mCaps
&
WL_SEAT_CAPABILITY_POINTER
) &&
mPointer
) {
430
mPointer
.
reset
();
431
mPointerGesturePinch
.
reset
();
432
mPointerGestureSwipe
.
reset
();
433
}
434
435
if
(
mCaps
&
WL_SEAT_CAPABILITY_TOUCH
&& !
mTouch
) {
436
mTouch
.
reset
(
createTouch
(
this
));
437
438
if
(!
mTouchDevice
) {
439
// TODO number of touchpoints, actual name and ID
440
mTouchDevice
=
new
QPointingDevice
(
441
QLatin1StringView
(
"touchscreen"
), 0,
QInputDevice
::
DeviceType
::
TouchScreen
,
442
QPointingDevice
::
PointerType
::
Finger
,
QInputDevice
::
Capability
::
Position
,
443
MaxTouchPoints
, 0,
mSeatName
,
QPointingDeviceUniqueId
(),
this
);
444
QWindowSystemInterface
::
registerInputDevice
(
mTouchDevice
);
445
}
446
}
else
if
(!(
mCaps
&
WL_SEAT_CAPABILITY_TOUCH
) &&
mTouch
) {
447
mTouch
.
reset
();
448
}
449
}
450
451
void
QWaylandInputDevice
::
seat_name
(
const
QString
&
name
)
452
{
453
mSeatName
=
name
;
454
}
455
456
QWaylandInputDevice
::
Keyboard
*
QWaylandInputDevice
::
createKeyboard
(
QWaylandInputDevice
*
device
)
457
{
458
return
new
Keyboard
(
device
);
459
}
460
461
QWaylandInputDevice
::
Pointer
*
QWaylandInputDevice
::
createPointer
(
QWaylandInputDevice
*
device
)
462
{
463
return
new
Pointer
(
device
);
464
}
465
466
QWaylandInputDevice
::
Touch
*
QWaylandInputDevice
::
createTouch
(
QWaylandInputDevice
*
device
)
467
{
468
return
new
Touch
(
device
);
469
}
470
471
QWaylandInputDevice
::
Keyboard
*
QWaylandInputDevice
::
keyboard
()
const
472
{
473
return
mKeyboard
.
get
();
474
}
475
476
QWaylandInputDevice
::
Pointer
*
QWaylandInputDevice
::
pointer
()
const
477
{
478
return
mPointer
.
get
();
479
}
480
481
QWaylandPointerGestureSwipe
*
QWaylandInputDevice
::
pointerGestureSwipe
()
const
482
{
483
return
mPointerGestureSwipe
.
get
();
484
}
485
486
QWaylandPointerGesturePinch
*
QWaylandInputDevice
::
pointerGesturePinch
()
const
487
{
488
return
mPointerGesturePinch
.
get
();
489
}
490
491
QWaylandInputDevice
::
Touch
*
QWaylandInputDevice
::
touch
()
const
492
{
493
return
mTouch
.
get
();
494
}
495
496
void
QWaylandInputDevice
::
handleEndDrag
()
497
{
498
if
(
mTouch
)
499
mTouch
->
releasePoints
();
500
if
(
mPointer
)
501
mPointer
->
releaseButtons
();
502
}
503
504
void
QWaylandInputDevice
::
handleStartDrag
()
505
{
506
if
(
mPointer
)
507
mPointer
->
leavePointers
();
508
}
509
510
#
if
QT_CONFIG
(
wayland_datadevice
)
511
void
QWaylandInputDevice
::
setDataDevice
(
QWaylandDataDevice
*
device
)
512
{
513
mDataDevice
=
device
;
514
}
515
516
QWaylandDataDevice
*
QWaylandInputDevice
::
dataDevice
()
const
517
{
518
return
mDataDevice
;
519
}
520
#
endif
521
522
#
if
QT_CONFIG
(
clipboard
)
523
void
QWaylandInputDevice
::
setDataControlDevice
(
QWaylandDataControlDeviceV1
*
dataControlDevice
)
524
{
525
mDataControlDevice
.
reset
(
dataControlDevice
);
526
}
527
528
QWaylandDataControlDeviceV1
*
QWaylandInputDevice
::
dataControlDevice
()
const
529
{
530
return
mDataControlDevice
.
get
();
531
}
532
#
endif
533
534
#
if
QT_CONFIG
(
wayland_client_primary_selection
)
535
void
QWaylandInputDevice
::
setPrimarySelectionDevice
(
QWaylandPrimarySelectionDeviceV1
*
primarySelectionDevice
)
536
{
537
mPrimarySelectionDevice
.
reset
(
primarySelectionDevice
);
538
}
539
540
QWaylandPrimarySelectionDeviceV1
*
QWaylandInputDevice
::
primarySelectionDevice
()
const
541
{
542
return
mPrimarySelectionDevice
.
get
();
543
}
544
#
endif
545
546
void
QWaylandInputDevice
::
setTextInput
(
QWaylandTextInputInterface
*
textInput
)
547
{
548
mTextInput
.
reset
(
textInput
);
549
}
550
551
#
if
QT_CONFIG
(
tabletevent
)
552
void
QWaylandInputDevice
::
setTabletSeat
(
QWaylandTabletSeatV2
*
tabletSeat
)
553
{
554
mTabletSeat
.
reset
(
tabletSeat
);
555
}
556
557
QWaylandTabletSeatV2
*
QWaylandInputDevice
::
tabletSeat
()
const
558
{
559
return
mTabletSeat
.
get
();
560
}
561
#
endif
562
563
void
QWaylandInputDevice
::
setTextInputMethod
(
QWaylandTextInputMethod
*
textInputMethod
)
564
{
565
mTextInputMethod
.
reset
(
textInputMethod
);
566
}
567
568
QWaylandTextInputInterface
*
QWaylandInputDevice
::
textInput
()
const
569
{
570
return
mTextInput
.
get
();
571
}
572
573
QWaylandTextInputMethod
*
QWaylandInputDevice
::
textInputMethod
()
const
574
{
575
return
mTextInputMethod
.
get
();
576
}
577
578
void
QWaylandInputDevice
::
removeMouseButtonFromState
(
Qt
::
MouseButton
button
)
579
{
580
if
(
mPointer
)
581
mPointer
->
mButtons
=
mPointer
->
mButtons
& !
button
;
582
}
583
584
QWaylandWindow
*
QWaylandInputDevice
::
pointerFocus
()
const
585
{
586
return
mPointer
&&
mPointer
->
focusSurface
() ?
mPointer
->
focusSurface
()->
waylandWindow
() :
nullptr
;
587
}
588
589
QWaylandWindow
*
QWaylandInputDevice
::
keyboardFocus
()
const
590
{
591
return
mKeyboard
&&
mKeyboard
->
focusSurface
() ?
mKeyboard
->
focusSurface
()->
waylandWindow
() :
nullptr
;
592
}
593
594
QWaylandWindow
*
QWaylandInputDevice
::
touchFocus
()
const
595
{
596
return
mTouch
&&
mTouch
->
mFocus
?
mTouch
->
mFocus
->
waylandWindow
() :
nullptr
;
597
}
598
599
QPointF
QWaylandInputDevice
::
pointerSurfacePosition
()
const
600
{
601
return
mPointer
?
mPointer
->
mSurfacePos
:
QPointF
();
602
}
603
604
QList
<
int
>
QWaylandInputDevice
::
possibleKeys
(
const
QKeyEvent
*
event
)
const
605
{
606
#
if
QT_CONFIG
(
xkbcommon
)
607
if
(
mKeyboard
&&
mKeyboard
->
mXkbState
)
608
return
QXkbCommon
::
possibleKeys
(
mKeyboard
->
mXkbState
.
get
(),
event
);
609
#
else
610
Q_UNUSED
(
event
);
611
#
endif
612
return
{};
613
}
614
615
Qt
::
KeyboardModifiers
QWaylandInputDevice
::
modifiers
()
const
616
{
617
if
(!
mKeyboard
)
618
return
Qt
::
NoModifier
;
619
620
return
mKeyboard
->
modifiers
();
621
}
622
623
Qt
::
KeyboardModifiers
QWaylandInputDevice
::
Keyboard
::
modifiers
()
const
624
{
625
Qt
::
KeyboardModifiers
ret
=
Qt
::
NoModifier
;
626
627
#
if
QT_CONFIG
(
xkbcommon
)
628
if
(!
mXkbState
)
629
return
ret
;
630
631
ret
=
QXkbCommon
::
modifiers
(
mXkbState
.
get
());
632
#
endif
633
634
return
ret
;
635
}
636
637
#
if
QT_CONFIG
(
cursor
)
638
void
QWaylandInputDevice
::
setCursor
(
const
QCursor
*
cursor
,
const
QSharedPointer
<
QWaylandBuffer
> &
cachedBuffer
,
int
fallbackOutputScale
)
639
{
640
CursorState
oldCursor
=
mCursor
;
641
mCursor
=
CursorState
();
// Clear any previous state
642
mCursor
.
shape
=
cursor
?
cursor
->
shape
() :
Qt
::
ArrowCursor
;
643
mCursor
.
hotspot
=
cursor
?
cursor
->
hotSpot
() :
QPoint
();
644
mCursor
.
fallbackOutputScale
=
fallbackOutputScale
;
645
mCursor
.
animationTimer
.
start
();
646
647
if
(
mCursor
.
shape
==
Qt
::
BitmapCursor
) {
648
mCursor
.
bitmapBuffer
=
cachedBuffer
?
cachedBuffer
:
QWaylandCursor
::
cursorBitmapBuffer
(
mQDisplay
,
cursor
);
649
qreal
dpr
=
cursor
->
pixmap
().
devicePixelRatio
();
650
mCursor
.
bitmapScale
=
int
(
dpr
);
// Wayland doesn't support fractional buffer scale
651
// If there was a fractional part of the dpr, we need to scale the hotspot accordingly
652
if
(
mCursor
.
bitmapScale
<
dpr
)
653
mCursor
.
hotspot
*=
dpr
/
mCursor
.
bitmapScale
;
654
}
655
656
// Return early if setCursor was called redundantly (mostly happens from decorations)
657
if
(
mCursor
.
shape
!=
Qt
::
BitmapCursor
658
&&
mCursor
.
shape
==
oldCursor
.
shape
659
&&
mCursor
.
hotspot
==
oldCursor
.
hotspot
660
&&
mCursor
.
fallbackOutputScale
==
oldCursor
.
fallbackOutputScale
) {
661
return
;
662
}
663
664
if
(
mPointer
)
665
mPointer
->
updateCursor
();
666
667
#
if
QT_CONFIG
(
tabletevent
)
668
if
(
mTabletSeat
)
669
mTabletSeat
->
updateCursor
();
670
#
endif
671
}
672
#
endif
673
674
class
EnterEvent
:
public
QWaylandPointerEvent
675
{
676
public
:
677
EnterEvent
(
QWaylandSurface
*surface,
const
QPointF &local,
const
QPointF &global)
678
:
QWaylandPointerEvent
(
QEvent
::
Enter
,
Qt
::
NoScrollPhase
,
surface
, 0,
679
local
,
global
,
Qt
::
NoButton
,
Qt
::
NoButton
,
Qt
::
NoModifier
)
680
{}
681
};
682
683
void
QWaylandInputDevice
::
Pointer
::
pointer_enter
(
uint32_t
serial
,
struct
wl_surface
*
wlSurface
,
684
wl_fixed_t
sx
,
wl_fixed_t
sy
)
685
{
686
if
(!
wlSurface
)
687
return
;
688
689
QWaylandSurface
*
surface
=
QWaylandSurface
::
fromWlSurface
(
wlSurface
);
690
691
if
(!
surface
)
692
return
;
// Ignore foreign surfaces
693
694
if
(
mFocus
) {
695
qCWarning
(
lcQpaWayland
) <<
"The compositor sent a wl_pointer.enter event before sending a"
696
<<
"leave event first, this is not allowed by the wayland protocol"
697
<<
"attempting to work around it by invalidating the current focus"
;
698
invalidateFocus
();
699
}
700
mFocus
=
surface
;
701
connect
(
mFocus
.
data
(), &
QObject
::
destroyed
,
this
, &
Pointer
::
handleFocusDestroyed
);
702
703
mSurfacePos
=
QPointF
(
wl_fixed_to_double
(
sx
),
wl_fixed_to_double
(
sy
));
704
if
(
auto
*
ww
=
surface
->
waylandWindow
())
705
mGlobalPos
=
ww
->
mapToGlobalF
(
mSurfacePos
);
706
else
if
(
auto
*
decoration
=
surface
->
decoration
())
707
mGlobalPos
=
decoration
->
mapToGlobal
(
mSurfacePos
);
708
709
mParent
->
mSerial
=
serial
;
710
mEnterSerial
=
serial
;
711
712
if
(!
mParent
->
mQDisplay
->
lastInputDevice
()) {
713
mParent
->
mQDisplay
->
setLastInputDevice
(
mParent
,
serial
,
surface
);
714
}
715
716
#
if
QT_CONFIG
(
cursor
)
717
// Depends on mEnterSerial being updated
718
updateCursor
();
719
#
endif
720
721
QWaylandWindow
*
grab
=
QWaylandWindow
::
mouseGrab
();
722
if
(!
grab
)
723
setFrameEvent
(
new
EnterEvent
(
surface
,
mSurfacePos
,
mGlobalPos
));
724
}
725
726
class
LeaveEvent
:
public
QWaylandPointerEvent
727
{
728
public
:
729
LeaveEvent
(
QWaylandSurface
*surface,
const
QPointF &localPos,
const
QPointF &globalPos)
730
:
QWaylandPointerEvent
(
QEvent
::
Leave
,
Qt
::
NoScrollPhase
,
surface
, 0,
731
localPos
,
globalPos
,
Qt
::
NoButton
,
Qt
::
NoButton
,
Qt
::
NoModifier
)
732
{}
733
};
734
735
void
QWaylandInputDevice
::
Pointer
::
pointer_leave
(
uint32_t
serial
,
struct
wl_surface
*
wlSurface
)
736
{
737
Q_UNUSED
(
serial
);
738
739
invalidateFocus
();
740
mButtons
=
Qt
::
NoButton
;
741
742
// The event may arrive after destroying the window, indicated by
743
// a null surface.
744
if
(!
wlSurface
)
745
return
;
746
747
auto
*
surface
=
QWaylandSurface
::
fromWlSurface
(
wlSurface
);
748
if
(!
surface
)
749
return
;
// Ignore foreign surfaces
750
751
if
(!
QWaylandWindow
::
mouseGrab
())
752
setFrameEvent
(
new
LeaveEvent
(
surface
,
mSurfacePos
,
mGlobalPos
));
753
}
754
755
class
MotionEvent
:
public
QWaylandPointerEvent
756
{
757
public
:
758
MotionEvent
(
QWaylandSurface
*surface, ulong timestamp,
const
QPointF &localPos,
759
const
QPointF &globalPos, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
760
:
QWaylandPointerEvent
(
QEvent
::
MouseMove
,
Qt
::
NoScrollPhase
,
surface
,
761
timestamp
,
localPos
,
globalPos
,
buttons
,
Qt
::
NoButton
,
modifiers
)
762
{
763
}
764
};
765
766
void
QWaylandInputDevice
::
Pointer
::
pointer_motion
(
uint32_t
time
,
wl_fixed_t
surface_x
,
wl_fixed_t
surface_y
)
767
{
768
QWaylandSurface
*
surface
=
focusSurface
();
769
if
(!
surface
) {
770
// We destroyed the pointer focus surface, but the server didn't get the message yet...
771
// or the server didn't send an enter event first. In either case, ignore the event.
772
return
;
773
}
774
775
QPointF
pos
(
wl_fixed_to_double
(
surface_x
),
wl_fixed_to_double
(
surface_y
));
776
QPointF
global
;
777
if
(
auto
*
ww
=
surface
->
waylandWindow
())
778
global
=
ww
->
mapToGlobalF
(
pos
);
779
else
if
(
auto
*
decoration
=
surface
->
decoration
())
780
global
=
decoration
->
mapToGlobal
(
pos
);
781
782
mSurfacePos
=
pos
;
783
mGlobalPos
=
global
;
784
mParent
->
mTime
=
time
;
785
786
QWaylandWindow
*
grab
=
QWaylandWindow
::
mouseGrab
();
787
if
(
grab
&&
grab
->
waylandSurface
() !=
surface
) {
788
// We can't know the true position since we're getting events for another surface,
789
// so we just set it outside of the window boundaries.
790
pos
=
QPointF
(-1, -1);
791
global
=
grab
->
mapToGlobalF
(
pos
);
792
surface
=
grab
->
waylandSurface
();
793
}
794
setFrameEvent
(
new
MotionEvent
(
surface
,
time
,
pos
,
global
,
mButtons
,
mParent
->
modifiers
()));
795
}
796
797
class
PressEvent
:
public
QWaylandPointerEvent
798
{
799
public
:
800
PressEvent
(
QWaylandSurface
*surface, ulong timestamp,
const
QPointF &localPos,
801
const
QPointF &globalPos, Qt::MouseButtons buttons, Qt::MouseButton button,
802
Qt::KeyboardModifiers modifiers)
803
:
QWaylandPointerEvent
(
QEvent
::
MouseButtonPress
,
Qt
::
NoScrollPhase
,
surface
,
804
timestamp
,
localPos
,
globalPos
,
buttons
,
button
,
modifiers
)
805
{
806
}
807
};
808
809
class
ReleaseEvent
:
public
QWaylandPointerEvent
810
{
811
public
:
812
ReleaseEvent
(
QWaylandSurface
*surface, ulong timestamp,
const
QPointF &localPos,
813
const
QPointF &globalPos, Qt::MouseButtons buttons, Qt::MouseButton button,
814
Qt::KeyboardModifiers modifiers)
815
:
QWaylandPointerEvent
(
QEvent
::
MouseButtonRelease
,
Qt
::
NoScrollPhase
,
surface
,
816
timestamp
,
localPos
,
globalPos
,
buttons
,
button
,
modifiers
)
817
{
818
}
819
};
820
821
void
QWaylandInputDevice
::
Pointer
::
pointer_button
(
uint32_t
serial
,
uint32_t
time
,
822
uint32_t
button
,
uint32_t
state
)
823
{
824
QWaylandSurface
*
surface
=
focusSurface
();
825
if
(!
surface
) {
826
// We destroyed the pointer focus surface, but the server didn't get the message yet...
827
// or the server didn't send an enter event first. In either case, ignore the event.
828
return
;
829
}
830
831
Qt
::
MouseButton
qt_button
;
832
833
// translate from kernel (input.h) 'button' to corresponding Qt:MouseButton.
834
// The range of mouse values is 0x110 <= mouse_button < 0x120, the first Joystick button.
835
switch
(
button
) {
836
case
0x110:
qt_button
=
Qt
::
LeftButton
;
break
;
// kernel BTN_LEFT
837
case
0x111:
qt_button
=
Qt
::
RightButton
;
break
;
838
case
0x112:
qt_button
=
Qt
::
MiddleButton
;
break
;
839
case
0x113:
qt_button
=
Qt
::
ExtraButton1
;
break
;
// AKA Qt::BackButton
840
case
0x114:
qt_button
=
Qt
::
ExtraButton2
;
break
;
// AKA Qt::ForwardButton
841
case
0x115:
qt_button
=
Qt
::
ExtraButton3
;
break
;
// AKA Qt::TaskButton
842
case
0x116:
qt_button
=
Qt
::
ExtraButton4
;
break
;
843
case
0x117:
qt_button
=
Qt
::
ExtraButton5
;
break
;
844
case
0x118:
qt_button
=
Qt
::
ExtraButton6
;
break
;
845
case
0x119:
qt_button
=
Qt
::
ExtraButton7
;
break
;
846
case
0x11a:
qt_button
=
Qt
::
ExtraButton8
;
break
;
847
case
0x11b:
qt_button
=
Qt
::
ExtraButton9
;
break
;
848
case
0x11c:
qt_button
=
Qt
::
ExtraButton10
;
break
;
849
case
0x11d:
qt_button
=
Qt
::
ExtraButton11
;
break
;
850
case
0x11e:
qt_button
=
Qt
::
ExtraButton12
;
break
;
851
case
0x11f:
qt_button
=
Qt
::
ExtraButton13
;
break
;
852
default
:
return
;
// invalid button number (as far as Qt is concerned)
853
}
854
855
mLastButton
=
qt_button
;
856
const
bool
firstPress
=
state
&&
mButtons
==
Qt
::
NoButton
;
857
858
if
(
state
)
859
mButtons
|=
qt_button
;
860
else
861
mButtons
&= ~
qt_button
;
862
863
mParent
->
mTime
=
time
;
864
mParent
->
mSerial
=
serial
;
865
if
(
state
)
866
mParent
->
mQDisplay
->
setLastInputDevice
(
mParent
,
serial
,
surface
);
867
868
QWaylandWindow
*
grab
=
QWaylandWindow
::
mouseGrab
();
869
870
QPointF
pos
=
mSurfacePos
;
871
QPointF
global
=
mGlobalPos
;
872
if
(
grab
&&
grab
->
waylandSurface
() !=
focusSurface
()) {
873
pos
=
QPointF
(-1, -1);
874
global
=
grab
->
mapToGlobalF
(
pos
);
875
876
surface
=
grab
->
waylandSurface
();
877
}
878
879
if
(
firstPress
)
880
mPressedSurface
=
surface
;
881
882
if
(
state
) {
883
if
(
auto
*
window
=
surface
->
waylandWindow
())
884
window
->
handleMousePressActivation
();
885
setFrameEvent
(
new
PressEvent
(
surface
,
time
,
pos
,
global
,
mButtons
,
qt_button
,
mParent
->
modifiers
()));
886
}
else
{
887
setFrameEvent
(
new
ReleaseEvent
(
surface
,
time
,
pos
,
global
,
mButtons
,
qt_button
,
mParent
->
modifiers
()));
888
if
(
mButtons
==
Qt
::
NoButton
)
889
mPressedSurface
.
clear
();
890
}
891
}
892
893
void
QWaylandInputDevice
::
Pointer
::
invalidateFocus
()
894
{
895
if
(
mFocus
) {
896
disconnect
(
mFocus
.
data
(), &
QObject
::
destroyed
,
this
, &
Pointer
::
handleFocusDestroyed
);
897
mFocus
=
nullptr
;
898
}
899
mEnterSerial
= 0;
900
}
901
902
void
QWaylandInputDevice
::
Pointer
::
releaseButtons
()
903
{
904
QWaylandSurface
*
pressedSurface
=
mPressedSurface
;
905
mPressedSurface
.
clear
();
906
mButtons
=
Qt
::
NoButton
;
907
908
setFrameEvent
(
new
ReleaseEvent
(
pressedSurface
,
mParent
->
mTime
,
mSurfacePos
,
mGlobalPos
,
909
Qt
::
NoButton
,
Qt
::
NoButton
,
mParent
->
modifiers
()));
910
flushFrameEvent
();
911
}
912
913
void
QWaylandInputDevice
::
Pointer
::
leavePointers
()
914
{
915
if
(
auto
*
surface
=
focusSurface
()) {
916
LeaveEvent
e
(
focusSurface
(),
mSurfacePos
,
mGlobalPos
);
917
if
(
auto
*
decoration
=
surface
->
decoration
())
918
decoration
->
handleMouse
(
mParent
,
e
);
919
if
(
auto
*
ww
=
surface
->
waylandWindow
())
920
ww
->
handleMouse
(
mParent
,
e
);
921
}
922
}
923
924
class
WheelEvent
:
public
QWaylandPointerEvent
925
{
926
public
:
927
WheelEvent
(
QWaylandSurface
*surface, Qt::ScrollPhase phase, ulong timestamp,
const
QPointF &local,
928
const
QPointF &global,
const
QPoint &pixelDelta,
const
QPoint &angleDelta,
929
Qt::MouseEventSource source, Qt::KeyboardModifiers modifiers,
bool
inverted)
930
:
QWaylandPointerEvent
(
QEvent
::
Wheel
,
phase
,
surface
,
timestamp
,
local
,
global
,
931
modifiers
&
Qt
::
AltModifier
?
pixelDelta
.
transposed
() :
pixelDelta
,
932
modifiers
&
Qt
::
AltModifier
?
angleDelta
.
transposed
() :
angleDelta
,
933
source
,
modifiers
,
inverted
)
934
{
935
}
936
};
937
938
void
QWaylandInputDevice
::
Pointer
::
pointer_axis
(
uint32_t
time
,
uint32_t
axis
,
int32_t
value
)
939
{
940
if
(!
focusSurface
()) {
941
// We destroyed the pointer focus surface, but the server didn't get the message yet...
942
// or the server didn't send an enter event first. In either case, ignore the event.
943
return
;
944
}
945
946
// Get the delta and convert it into the expected range
947
switch
(
axis
) {
948
case
WL_POINTER_AXIS_VERTICAL_SCROLL
:
949
mFrameData
.
delta
.
ry
() +=
wl_fixed_to_double
(
value
);
950
qCDebug
(
lcQpaWaylandInput
) <<
"wl_pointer.axis vertical:"
<<
mFrameData
.
delta
.
y
();
951
break
;
952
case
WL_POINTER_AXIS_HORIZONTAL_SCROLL
:
953
mFrameData
.
delta
.
rx
() +=
wl_fixed_to_double
(
value
);
954
qCDebug
(
lcQpaWaylandInput
) <<
"wl_pointer.axis horizontal:"
<<
mFrameData
.
delta
.
x
();
955
break
;
956
default
:
957
//TODO: is this really needed?
958
qCWarning
(
lcQpaWaylandInput
) <<
"wl_pointer.axis: Unknown axis:"
<<
axis
;
959
return
;
960
}
961
962
mParent
->
mTime
=
time
;
963
964
maybePointerFrame
();
965
}
966
967
void
QWaylandInputDevice
::
Pointer
::
pointer_frame
()
968
{
969
if
(
mEventCompression
.
compressEvent
()) {
970
qCDebug
(
lcQpaWaylandInput
) <<
"compressed pointer_frame event"
;
971
return
;
972
}
973
974
flushFrameEvent
();
975
}
976
977
void
QWaylandInputDevice
::
Pointer
::
pointer_axis_source
(
uint32_t
source
)
978
{
979
switch
(
source
) {
980
case
axis_source_wheel
:
981
qCDebug
(
lcQpaWaylandInput
) <<
"Axis source wheel"
;
982
break
;
983
case
axis_source_finger
:
984
qCDebug
(
lcQpaWaylandInput
) <<
"Axis source finger"
;
985
break
;
986
case
axis_source_continuous
:
987
qCDebug
(
lcQpaWaylandInput
) <<
"Axis source continuous"
;
988
break
;
989
case
axis_source_wheel_tilt
:
990
qCDebug
(
lcQpaWaylandInput
) <<
"Axis source wheel tilt"
;
991
}
992
mFrameData
.
axisSource
=
axis_source
(
source
);
993
}
994
995
void
QWaylandInputDevice
::
Pointer
::
pointer_axis_stop
(
uint32_t
time
,
uint32_t
axis
)
996
{
997
if
(!
focusSurface
())
998
return
;
999
1000
mParent
->
mTime
=
time
;
1001
switch
(
axis
) {
1002
case
axis_vertical_scroll
:
1003
qCDebug
(
lcQpaWaylandInput
) <<
"Received vertical wl_pointer.axis_stop"
;
1004
break
;
1005
case
axis_horizontal_scroll
:
1006
qCDebug
(
lcQpaWaylandInput
) <<
"Received horizontal wl_pointer.axis_stop"
;
1007
break
;
1008
default
:
1009
qCWarning
(
lcQpaWaylandInput
) <<
"wl_pointer.axis_stop: Unknown axis: "
<<
axis
1010
<<
"This is most likely a compositor bug"
;
1011
return
;
1012
}
1013
1014
mScrollEnd
=
true
;
1015
}
1016
1017
void
QWaylandInputDevice
::
Pointer
::
pointer_axis_discrete
(
uint32_t
axis
,
int32_t
value
)
1018
{
1019
if
(!
focusSurface
())
1020
return
;
1021
1022
const
int32_t
delta120
=
value
* 15 * 8;
1023
1024
switch
(
axis
) {
1025
case
axis_vertical_scroll
:
1026
qCDebug
(
lcQpaWaylandInput
) <<
"wl_pointer.axis_discrete vertical:"
<<
value
;
1027
mFrameData
.
delta120
.
ry
() +=
delta120
;
1028
break
;
1029
case
axis_horizontal_scroll
:
1030
qCDebug
(
lcQpaWaylandInput
) <<
"wl_pointer.axis_discrete horizontal:"
<<
value
;
1031
mFrameData
.
delta120
.
rx
() +=
delta120
;
1032
break
;
1033
default
:
1034
//TODO: is this really needed?
1035
qCWarning
(
lcQpaWaylandInput
) <<
"wl_pointer.axis_discrete: Unknown axis:"
<<
axis
;
1036
return
;
1037
}
1038
}
1039
1040
void
QWaylandInputDevice
::
Pointer
::
pointer_axis_value120
(
uint32_t
axis
,
int32_t
value
)
1041
{
1042
if
(!
focusSurface
())
1043
return
;
1044
1045
switch
(
axis
) {
1046
case
axis_vertical_scroll
:
1047
qCDebug
(
lcQpaWaylandInput
) <<
"wl_pointer.axis_value120 vertical:"
<<
value
;
1048
mFrameData
.
delta120
.
ry
() +=
value
;
1049
break
;
1050
case
axis_horizontal_scroll
:
1051
qCDebug
(
lcQpaWaylandInput
) <<
"wl_pointer.axis_value120 horizontal:"
<<
value
;
1052
mFrameData
.
delta120
.
rx
() +=
value
;
1053
break
;
1054
default
:
1055
qCWarning
(
lcQpaWaylandInput
) <<
"wl_pointer.axis_value120: Unknown axis:"
<<
axis
;
1056
return
;
1057
}
1058
}
1059
1060
void
QWaylandInputDevice
::
Pointer
::
pointer_axis_relative_direction
(
uint32_t
axis
,
uint32_t
direction
)
1061
{
1062
const
bool
inverted
=
direction
==
axis_relative_direction_inverted
;
1063
switch
(
axis
) {
1064
case
axis_vertical_scroll
:
1065
mFrameData
.
verticalAxisInverted
=
inverted
;
1066
break
;
1067
case
axis_horizontal_scroll
:
1068
mFrameData
.
horizontalAxisInverted
=
inverted
;
1069
break
;
1070
default
:
1071
qCWarning
(
lcQpaWaylandInput
) <<
"wl_pointer.axis_relative_direction: Unknown axis:"
<<
axis
;
1072
}
1073
}
1074
1075
inline
void
QWaylandInputDevice
::
Pointer
::
maybePointerFrame
()
1076
{
1077
if
(
version
() <
WL_POINTER_FRAME_SINCE_VERSION
) {
1078
qCDebug
(
lcQpaWaylandInput
) <<
"Flushing new event; no frame event in this version"
;
1079
pointer_frame
();
1080
}
1081
}
1082
1083
void
QWaylandInputDevice
::
Pointer
::
setFrameEvent
(
QWaylandPointerEvent
*
event
)
1084
{
1085
qCDebug
(
lcQpaWaylandInput
) <<
"Setting frame event "
<<
event
->
type
;
1086
if
(
mFrameData
.
event
&&
mFrameData
.
event
->
type
!=
event
->
type
) {
1087
qCDebug
(
lcQpaWaylandInput
) <<
"Flushing; previous was "
<<
mFrameData
.
event
->
type
;
1088
flushFrameEvent
();
1089
}
1090
1091
mFrameData
.
event
.
reset
(
event
);
1092
1093
maybePointerFrame
();
1094
}
1095
1096
void
QWaylandInputDevice
::
Pointer
::
FrameData
::
resetScrollData
()
1097
{
1098
delta120
=
QPoint
();
1099
delta
=
QPointF
();
1100
axisSource
=
axis_source_wheel
;
1101
horizontalAxisInverted
=
false
;
1102
verticalAxisInverted
=
false
;
1103
}
1104
1105
QPoint
QWaylandInputDevice
::
Pointer
::
FrameData
::
pixelDeltaAndError
(
QPointF
*
accumulatedError
)
const
1106
{
1107
Q_ASSERT
(
accumulatedError
);
1108
// Add accumulated rounding error before rounding again
1109
QPoint
pixelDelta
= (
delta
+ *
accumulatedError
).
toPoint
();
1110
*
accumulatedError
+=
delta
-
pixelDelta
;
1111
Q_ASSERT
(
qAbs
(
accumulatedError
->
x
()) < 1.0);
1112
Q_ASSERT
(
qAbs
(
accumulatedError
->
y
()) < 1.0);
1113
1114
// for continuous scroll events things should be
1115
// in the same direction
1116
// i.e converted so downwards surface co-ordinates (positive axis_value)
1117
// goes to downwards in wheel event (negative value)
1118
pixelDelta
*= -1;
1119
return
pixelDelta
;
1120
}
1121
1122
QPoint
QWaylandInputDevice
::
Pointer
::
FrameData
::
angleDelta
()
const
1123
{
1124
if
(
delta120
.
isNull
()) {
1125
// If we didn't get any discrete events, then we need to fall back to
1126
// the continuous information.
1127
return
(
delta
* -12).
toPoint
();
//TODO: why multiply by 12?
1128
}
1129
1130
// The angle delta is in eights of degrees, and our docs says most mice have
1131
// 1 click = 15 degrees, i.e. 120 is one click. It's also in the opposite
1132
// direction of surface space.
1133
return
-
delta120
;
1134
}
1135
1136
Qt
::
MouseEventSource
QWaylandInputDevice
::
Pointer
::
FrameData
::
wheelEventSource
()
const
1137
{
1138
switch
(
axisSource
) {
1139
case
axis_source_wheel_tilt
:
// sideways tilt of the wheel
1140
case
axis_source_wheel
:
1141
return
Qt
::
MouseEventNotSynthesized
;
1142
case
axis_source_finger
:
1143
case
axis_source_continuous
:
1144
default
:
// Whatever other sources might be added are probably not mouse wheels
1145
return
Qt
::
MouseEventSynthesizedBySystem
;
1146
}
1147
}
1148
1149
void
QWaylandInputDevice
::
Pointer
::
flushScrollEvent
()
1150
{
1151
QPoint
angleDelta
=
mFrameData
.
angleDelta
();
1152
1153
// The wayland protocol has separate horizontal and vertical axes, Qt has just the one inverted flag
1154
// Pragmatically it should't come up
1155
const
bool
inverted
=
mFrameData
.
verticalAxisInverted
||
mFrameData
.
horizontalAxisInverted
;
1156
1157
// Angle delta is required for Qt wheel events, so don't try to send events if it's zero
1158
if
(!
angleDelta
.
isNull
()) {
1159
QWaylandSurface
*
target
=
mScrollTarget
;
1160
if
(!
mScrollBeginSent
) {
1161
if
(!
target
&&
QWaylandWindow
::
mouseGrab
())
1162
target
=
QWaylandWindow
::
mouseGrab
()->
waylandSurface
();
1163
if
(!
target
)
1164
target
=
focusSurface
();
1165
}
1166
if
(!
target
) {
1167
qCDebug
(
lcQpaWaylandInput
) <<
"Flushing scroll event aborted - no scroll target"
;
1168
mFrameData
.
resetScrollData
();
1169
return
;
1170
}
1171
1172
if
(
isDefinitelyTerminated
(
mFrameData
.
axisSource
) && !
mScrollBeginSent
) {
1173
qCDebug
(
lcQpaWaylandInput
) <<
"Flushing scroll event sending ScrollBegin"
;
1174
if
(
auto
*
ww
=
target
->
waylandWindow
())
1175
ww
->
handleMouse
(
mParent
,
WheelEvent
(
focusSurface
(),
Qt
::
ScrollBegin
,
mParent
->
mTime
,
1176
mSurfacePos
,
mGlobalPos
,
QPoint
(),
QPoint
(),
1177
Qt
::
MouseEventNotSynthesized
,
1178
mParent
->
modifiers
(),
false
));
1179
mScrollBeginSent
=
true
;
1180
mScrollDeltaRemainder
=
QPointF
();
1181
mScrollTarget
=
target
;
1182
}
1183
1184
Qt
::
ScrollPhase
phase
=
mScrollBeginSent
?
Qt
::
ScrollUpdate
:
Qt
::
NoScrollPhase
;
1185
QPoint
pixelDelta
=
mFrameData
.
pixelDeltaAndError
(&
mScrollDeltaRemainder
);
1186
1187
qCDebug
(
lcQpaWaylandInput
) <<
"Flushing scroll event"
<<
phase
<<
pixelDelta
<<
angleDelta
;
1188
if
(
auto
*
ww
=
target
->
waylandWindow
())
1189
ww
->
handleMouse
(
mParent
,
WheelEvent
(
focusSurface
(),
phase
,
mParent
->
mTime
,
mSurfacePos
,
mGlobalPos
,
1190
pixelDelta
,
angleDelta
,
mFrameData
.
wheelEventSource
(),
mParent
->
modifiers
(),
inverted
));
1191
}
1192
1193
if
(
mScrollEnd
) {
1194
if
(
mScrollBeginSent
) {
1195
if
(
auto
target
=
mScrollTarget
.
get
()) {
1196
qCDebug
(
lcQpaWaylandInput
) <<
"Flushing scroll end event"
;
1197
if
(
auto
*
ww
=
target
->
waylandWindow
())
1198
ww
->
handleMouse
(
mParent
,
WheelEvent
(
focusSurface
(),
Qt
::
ScrollEnd
,
mParent
->
mTime
,
mSurfacePos
,
mGlobalPos
,
1199
QPoint
(),
QPoint
(),
mFrameData
.
wheelEventSource
(),
mParent
->
modifiers
(),
inverted
));
1200
}
1201
mScrollBeginSent
=
false
;
1202
mScrollDeltaRemainder
=
QPointF
();
1203
}
else
{
1204
// May receive axis_stop for events we haven't sent a ScrollBegin for because
1205
// most axis_sources do not mandate an axis_stop event to be sent.
1206
1207
// TODO: For now, we just ignore these events, but we could perhaps take this as an
1208
// indication that this compositor will in fact send axis_stop events for these sources
1209
// and send a ScrollBegin the next time an axis_source event with this type is encountered.
1210
}
1211
mScrollEnd
=
false
;
1212
mScrollTarget
.
clear
();
1213
}
1214
1215
mFrameData
.
resetScrollData
();
1216
}
1217
1218
void
QWaylandInputDevice
::
Pointer
::
flushFrameEvent
()
1219
{
1220
mEventCompression
.
delayTimer
.
stop
();
1221
1222
if
(
auto
*
event
=
mFrameData
.
event
.
get
()) {
1223
if
(
auto
surface
=
event
->
surface
) {
1224
if
(
auto
*
decoration
=
surface
->
decoration
())
1225
decoration
->
handleMouse
(
mParent
, *
event
);
1226
if
(
auto
*
ww
=
surface
->
waylandWindow
())
1227
ww
->
handleMouse
(
mParent
, *
event
);
1228
}
else
if
(
mFrameData
.
event
->
type
==
QEvent
::
MouseButtonRelease
) {
1229
// If the window has been destroyed, we still need to report an up event, but it can't
1230
// be handled by the destroyed window (obviously), so send the event here instead.
1231
QWindowSystemInterface
::
handleMouseEvent
(
1232
nullptr
,
event
->
timestamp
,
1233
QPointingDevice
::
primaryPointingDevice
(
mParent
->
seatname
()),
event
->
local
,
1234
event
->
global
,
event
->
buttons
,
event
->
button
,
event
->
type
,
1235
event
->
modifiers
);
// , Qt::MouseEventSource source =
1236
// Qt::MouseEventNotSynthesized);
1237
}
1238
mFrameData
.
event
.
reset
();
1239
}
1240
1241
//TODO: do modifiers get passed correctly here?
1242
flushScrollEvent
();
1243
}
1244
1245
bool
QWaylandInputDevice
::
Pointer
::
isDefinitelyTerminated
(
QtWayland
::
wl_pointer
::
axis_source
source
)
const
1246
{
1247
return
source
==
axis_source_finger
;
1248
}
1249
1250
void
QWaylandInputDevice
::
Keyboard
::
keyboard_keymap
(
uint32_t
format
,
int32_t
fd
,
uint32_t
size
)
1251
{
1252
const
auto
fdCloser
=
qScopeGuard
([
fd
] {
close
(
fd
); });
1253
mKeymapFormat
=
format
;
1254
#
if
QT_CONFIG
(
xkbcommon
)
1255
if
(
format
==
WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP
)
1256
return
;
1257
1258
if
(
format
!=
WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1
) {
1259
qCWarning
(
lcQpaWayland
) <<
"unknown keymap format:"
<<
format
;
1260
return
;
1261
}
1262
1263
char
*
map_str
=
static_cast
<
char
*>(
mmap
(
nullptr
,
size
,
PROT_READ
,
MAP_PRIVATE
,
fd
, 0));
1264
if
(
map_str
==
MAP_FAILED
)
1265
return
;
1266
1267
// We need to be able to cope with a non 0-terminated map_str, but we also need to make
1268
// sure that map_str does not contain any 0-bytes at all, as older libxkbcommon cannot
1269
// deal with those and fail (e.g. RHEL 9.6 and Ubuntu 22.04)
1270
mXkbKeymap
.
reset
(
xkb_keymap_new_from_buffer
(
mParent
->
mQDisplay
->
xkbContext
(),
1271
map_str
,
1272
strnlen
(
map_str
,
size
),
1273
XKB_KEYMAP_FORMAT_TEXT_V1
,
1274
XKB_KEYMAP_COMPILE_NO_FLAGS
));
1275
1276
if
(
mXkbKeymap
) {
1277
QXkbCommon
::
verifyHasLatinLayout
(
mXkbKeymap
.
get
());
1278
}
else
{
1279
qCDebug
(
lcQpaWaylandInput
) <<
"failed to compile a keymap, size ="
<<
size
1280
<<
", keymap string:\n"
1281
<<
QByteArrayView
(
map_str
,
strnlen
(
map_str
,
size
));
1282
}
1283
1284
munmap
(
map_str
,
size
);
1285
1286
if
(
mXkbKeymap
)
1287
mXkbState
.
reset
(
xkb_state_new
(
mXkbKeymap
.
get
()));
1288
else
1289
mXkbState
.
reset
(
nullptr
);
1290
#
else
1291
Q_UNUSED
(
size
);
1292
#
endif
1293
}
1294
1295
void
QWaylandInputDevice
::
Keyboard
::
keyboard_enter
(
uint32_t
serial
,
struct
wl_surface
*
surface
,
struct
wl_array *
keys
)
1296
{
1297
Q_UNUSED
(
serial
);
1298
Q_UNUSED
(
keys
);
1299
1300
if
(!
surface
) {
1301
// Ignoring wl_keyboard.enter event with null surface. This is either a compositor bug,
1302
// or it's a race with a wl_surface.destroy request. In either case, ignore the event.
1303
return
;
1304
}
1305
1306
QWaylandWindow
*
window
=
QWaylandWindow
::
fromWlSurface
(
surface
);
1307
if
(!
window
)
1308
return
;
1309
1310
if
(
mFocus
) {
1311
qCWarning
(
lcQpaWayland
()) <<
"Unexpected wl_keyboard.enter event. Keyboard already has focus"
;
1312
disconnect
(
mFocus
, &
QWaylandSurface
::
destroyed
,
this
, &
Keyboard
::
handleFocusDestroyed
);
1313
}
1314
1315
mFocus
=
window
->
waylandSurface
();
1316
connect
(
mFocus
, &
QWaylandSurface
::
destroyed
,
this
, &
Keyboard
::
handleFocusDestroyed
);
1317
1318
mParent
->
mQDisplay
->
handleKeyboardFocusChanged
(
mParent
);
1319
}
1320
1321
void
QWaylandInputDevice
::
Keyboard
::
keyboard_leave
(
uint32_t
serial
,
struct
wl_surface
*
surface
)
1322
{
1323
Q_UNUSED
(
serial
);
1324
1325
if
(!
surface
) {
1326
// Either a compositor bug, or a race condition with wl_surface.destroy, ignore the event.
1327
return
;
1328
}
1329
1330
auto
qtSurface
=
QWaylandSurface
::
fromWlSurface
(
surface
);
1331
if
(!
qtSurface
)
1332
return
;
1333
QWaylandWindow
*
window
=
qtSurface
->
waylandWindow
();
1334
if
(!
window
)
1335
return
;
1336
1337
if
(
window
->
waylandSurface
() !=
mFocus
) {
1338
qCWarning
(
lcQpaWayland
) <<
"Ignoring unexpected wl_keyboard.leave event."
1339
<<
"wl_surface argument does not match the current focus"
1340
<<
"This is most likely a compositor bug"
;
1341
return
;
1342
}
1343
disconnect
(
mFocus
, &
QWaylandSurface
::
destroyed
,
this
, &
Keyboard
::
handleFocusDestroyed
);
1344
handleFocusLost
();
1345
}
1346
1347
void
QWaylandInputDevice
::
Keyboard
::
handleKey
(
ulong
timestamp
,
QEvent
::
Type
type
,
int
key
,
1348
Qt
::
KeyboardModifiers
modifiers
,
quint32
nativeScanCode
,
1349
quint32
nativeVirtualKey
,
quint32
nativeModifiers
,
1350
const
QString
&
text
,
bool
autorepeat
,
ushort
count
)
1351
{
1352
QPlatformInputContext
*
inputContext
=
QGuiApplicationPrivate
::
platformIntegration
()->
inputContext
();
1353
bool
filtered
=
false
;
1354
1355
if
(
inputContext
) {
1356
QKeyEvent
event
(
type
,
key
,
modifiers
,
nativeScanCode
,
nativeVirtualKey
,
1357
nativeModifiers
,
text
,
autorepeat
,
count
);
1358
event
.
setTimestamp
(
timestamp
);
1359
filtered
=
inputContext
->
filterEvent
(&
event
);
1360
}
1361
1362
if
(!
filtered
) {
1363
QWindow
*
window
=
nullptr
;
1364
if
(
auto
*
activeSubSurface
=
mParent
->
mQDisplay
->
activeSubSurface
()) {
1365
window
=
activeSubSurface
->
window
();
1366
}
else
if
(
auto
*
surface
=
focusSurface
()) {
1367
if
(
auto
*
ww
=
surface
->
waylandWindow
())
1368
window
=
ww
->
window
();
1369
}
1370
if
(!
window
)
1371
return
;
1372
1373
if
(
type
==
QEvent
::
KeyPress
&&
key
==
Qt
::
Key_Menu
) {
1374
auto
cursor
=
window
->
screen
()->
handle
()->
cursor
();
1375
if
(
cursor
) {
1376
const
QPoint
globalPos
=
cursor
->
pos
();
1377
const
QPoint
pos
=
window
->
mapFromGlobal
(
globalPos
);
1378
QWindowSystemInterface
::
handleContextMenuEvent
(
window
,
false
,
pos
,
globalPos
,
modifiers
);
1379
}
1380
}
1381
1382
QWindowSystemInterface
::
handleExtendedKeyEvent
(
window
,
timestamp
,
type
,
key
,
modifiers
,
1383
nativeScanCode
,
nativeVirtualKey
,
nativeModifiers
,
text
,
autorepeat
,
count
);
1384
}
1385
}
1386
1387
void
QWaylandInputDevice
::
Keyboard
::
keyboard_key
(
uint32_t
serial
,
uint32_t
time
,
uint32_t
key
,
uint32_t
state
)
1388
{
1389
if
(
mKeymapFormat
!=
WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1
&&
mKeymapFormat
!=
WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP
) {
1390
qCWarning
(
lcQpaWayland
) <<
Q_FUNC_INFO
<<
"unknown keymap format:"
<<
mKeymapFormat
;
1391
return
;
1392
}
1393
1394
auto
*
surface
=
focusSurface
();
1395
if
(!
surface
) {
1396
// We destroyed the keyboard focus surface, but the server didn't get the message yet...
1397
// or the server didn't send an enter event first. In either case, ignore the event.
1398
return
;
1399
}
1400
1401
mParent
->
mSerial
=
serial
;
1402
1403
const
bool
isDown
=
state
!=
WL_KEYBOARD_KEY_STATE_RELEASED
;
1404
if
(
isDown
)
1405
mParent
->
mQDisplay
->
setLastInputDevice
(
mParent
,
serial
,
surface
);
1406
1407
if
(
mKeymapFormat
==
WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1
) {
1408
#
if
QT_CONFIG
(
xkbcommon
)
1409
if
((!
mXkbKeymap
|| !
mXkbState
) && !
createDefaultKeymap
())
1410
return
;
1411
1412
auto
code
=
key
+ 8;
// map to wl_keyboard::keymap_format::keymap_format_xkb_v1
1413
1414
xkb_keysym_t
sym
=
xkb_state_key_get_one_sym
(
mXkbState
.
get
(),
code
);
1415
Qt
::
KeyboardModifiers
modifiers
=
QXkbCommon
::
modifiers
(
mXkbState
.
get
(),
sym
);
1416
1417
int
qtkey
=
keysymToQtKey
(
sym
,
modifiers
,
mXkbState
.
get
(),
code
);
1418
QString
text
=
QXkbCommon
::
lookupString
(
mXkbState
.
get
(),
code
);
1419
1420
QEvent
::
Type
type
=
isDown
?
QEvent
::
KeyPress
:
QEvent
::
KeyRelease
;
1421
bool
isAutoRepeat
=
state
==
WL_KEYBOARD_KEY_STATE_REPEATED
;
1422
if
(
isAutoRepeat
&&
mRepeatRate
> 0) {
1423
qCWarning
(
lcQpaWayland
,
"received key repeat event while repeat rate is non-zero"
);
1424
return
;
1425
}
1426
if
(
isAutoRepeat
&& !
xkb_keymap_key_repeats
(
mXkbKeymap
.
get
(),
code
)) {
1427
qCWarning
(
lcQpaWayland
,
"received key repeat event for a key that should not be repeated"
);
1428
return
;
1429
}
1430
if
(
isAutoRepeat
)
1431
handleKey
(
time
,
QEvent
::
KeyRelease
,
qtkey
,
modifiers
,
code
,
sym
,
mNativeModifiers
,
text
,
isAutoRepeat
);
1432
1433
handleKey
(
time
,
type
,
qtkey
,
modifiers
,
code
,
sym
,
mNativeModifiers
,
text
,
isAutoRepeat
);
1434
1435
if
(
state
==
WL_KEYBOARD_KEY_STATE_PRESSED
&&
xkb_keymap_key_repeats
(
mXkbKeymap
.
get
(),
code
) &&
mRepeatRate
> 0) {
1436
mRepeatKey
.
key
=
qtkey
;
1437
mRepeatKey
.
code
=
code
;
1438
mRepeatKey
.
time
=
time
;
1439
mRepeatKey
.
text
=
text
;
1440
mRepeatKey
.
nativeVirtualKey
=
sym
;
1441
mRepeatTimer
.
setInterval
(
mRepeatDelay
);
1442
mRepeatTimer
.
start
();
1443
}
else
if
(
mRepeatKey
.
code
==
code
) {
1444
mRepeatTimer
.
stop
();
1445
}
1446
#
else
1447
Q_UNUSED
(
time
);
1448
Q_UNUSED
(
key
);
1449
qCWarning
(
lcQpaWayland
,
"xkbcommon not available on this build, not performing key mapping"
);
1450
return
;
1451
#
endif
1452
}
else
if
(
mKeymapFormat
==
WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP
) {
1453
// raw scan code
1454
return
;
1455
}
1456
}
1457
1458
void
QWaylandInputDevice
::
Keyboard
::
handleFocusDestroyed
()
1459
{
1460
handleFocusLost
();
1461
}
1462
1463
void
QWaylandInputDevice
::
Keyboard
::
handleFocusLost
()
1464
{
1465
mFocus
=
nullptr
;
1466
mParent
->
mQDisplay
->
handleKeyboardFocusChanged
(
mParent
);
1467
mRepeatTimer
.
stop
();
1468
}
1469
1470
void
QWaylandInputDevice
::
Keyboard
::
keyboard_modifiers
(
uint32_t
serial
,
1471
uint32_t
mods_depressed
,
1472
uint32_t
mods_latched
,
1473
uint32_t
mods_locked
,
1474
uint32_t
group
)
1475
{
1476
Q_UNUSED
(
serial
);
1477
#
if
QT_CONFIG
(
xkbcommon
)
1478
if
(
mXkbState
)
1479
xkb_state_update_mask
(
mXkbState
.
get
(),
1480
mods_depressed
,
mods_latched
,
mods_locked
,
1481
0, 0,
group
);
1482
mNativeModifiers
=
mods_depressed
|
mods_latched
|
mods_locked
;
1483
#
else
1484
Q_UNUSED
(
mods_depressed
);
1485
Q_UNUSED
(
mods_latched
);
1486
Q_UNUSED
(
mods_locked
);
1487
Q_UNUSED
(
group
);
1488
#
endif
1489
}
1490
1491
void
QWaylandInputDevice
::
Keyboard
::
keyboard_repeat_info
(
int32_t
rate
,
int32_t
delay
)
1492
{
1493
mRepeatRate
=
rate
;
1494
mRepeatDelay
=
delay
;
1495
}
1496
1497
void
QWaylandInputDevice
::
Touch
::
touch_down
(
uint32_t
serial
,
1498
uint32_t
time
,
1499
struct
wl_surface
*
surface
,
1500
int32_t
id
,
1501
wl_fixed_t
x
,
1502
wl_fixed_t
y
)
1503
{
1504
if
(!
surface
)
1505
return
;
1506
1507
auto
*
window
=
QWaylandSurface
::
fromWlSurface
(
surface
);
1508
if
(!
window
)
1509
return
;
// Ignore foreign surfaces
1510
1511
mParent
->
mTime
=
time
;
1512
mParent
->
mSerial
=
serial
;
1513
mFocus
=
window
;
1514
mParent
->
mQDisplay
->
setLastInputDevice
(
mParent
,
serial
,
mFocus
);
1515
QPointF
position
(
wl_fixed_to_double
(
x
),
wl_fixed_to_double
(
y
));
1516
mParent
->
handleTouchPoint
(
id
,
QEventPoint
::
Pressed
,
position
);
1517
}
1518
1519
void
QWaylandInputDevice
::
Touch
::
touch_up
(
uint32_t
serial
,
uint32_t
time
,
int32_t
id
)
1520
{
1521
Q_UNUSED
(
serial
);
1522
mParent
->
mTime
=
time
;
1523
mParent
->
handleTouchPoint
(
id
,
QEventPoint
::
Released
);
1524
1525
if
(
allTouchPointsReleased
()) {
1526
mFocus
=
nullptr
;
1527
1528
// As of Weston 7.0.0 there is no touch_frame after the last touch_up
1529
// (i.e. when the last finger is released). To accommodate for this, issue a
1530
// touch_frame. This cannot hurt since it is safe to call the touch_frame
1531
// handler multiple times when there are no points left.
1532
// See: https://gitlab.freedesktop.org/wayland/weston/issues/44
1533
// TODO: change logging category to lcQpaWaylandInput in newer versions.
1534
qCDebug
(
lcQpaWayland
,
"Generating fake frame event to work around Weston bug"
);
1535
touch_frame
();
1536
}
1537
}
1538
1539
void
QWaylandInputDevice
::
Touch
::
touch_motion
(
uint32_t
time
,
int32_t
id
,
wl_fixed_t
x
,
wl_fixed_t
y
)
1540
{
1541
QPointF
position
(
wl_fixed_to_double
(
x
),
wl_fixed_to_double
(
y
));
1542
mParent
->
mTime
=
time
;
1543
mParent
->
handleTouchPoint
(
id
,
QEventPoint
::
Updated
,
position
);
1544
}
1545
1546
void
QWaylandInputDevice
::
Touch
::
touch_cancel
()
1547
{
1548
mPendingTouchPoints
.
clear
();
1549
1550
mFocus
=
nullptr
;
1551
QWindowSystemInterface
::
handleTouchCancelEvent
(
nullptr
,
mParent
->
mTouchDevice
);
1552
}
1553
1554
void
QWaylandInputDevice
::
handleTouchPoint
(
int
id
,
QEventPoint
::
State
state
,
const
QPointF
&
surfacePosition
)
1555
{
1556
auto
end
=
mTouch
->
mPendingTouchPoints
.
end
();
1557
auto
it
=
std
::
find_if
(
mTouch
->
mPendingTouchPoints
.
begin
(),
end
, [
id
](
const
QWindowSystemInterface
::
TouchPoint
&
tp
){
return
tp
.
id
==
id
; });
1558
if
(
it
==
end
) {
1559
it
=
mTouch
->
mPendingTouchPoints
.
insert
(
end
,
QWindowSystemInterface
::
TouchPoint
());
1560
it
->
id
=
id
;
1561
}
1562
// If the touch points were up and down in same frame, send out frame right away
1563
else
if
((
it
->
state
==
QEventPoint
::
Pressed
&&
state
==
QEventPoint
::
Released
)
1564
|| (
it
->
state
==
QEventPoint
::
Released
&&
state
==
QEventPoint
::
Pressed
)) {
1565
mTouch
->
touch_frame
();
1566
it
=
mTouch
->
mPendingTouchPoints
.
insert
(
mTouch
->
mPendingTouchPoints
.
end
(),
QWindowSystemInterface
::
TouchPoint
());
1567
it
->
id
=
id
;
1568
}
1569
1570
QWindowSystemInterface
::
TouchPoint
&
tp
= *
it
;
1571
1572
// Only moved and pressed needs to update/set position
1573
if
(
state
==
QEventPoint
::
Updated
||
state
==
QEventPoint
::
Pressed
) {
1574
// We need a global (screen) position.
1575
QWaylandSurface
*
surface
=
mTouch
->
mFocus
;
1576
1577
//is it possible that mTouchFocus is null;
1578
if
(!
surface
&&
mPointer
)
1579
surface
=
mPointer
->
focusSurface
();
1580
if
(!
surface
&&
mKeyboard
)
1581
surface
=
mKeyboard
->
focusSurface
();
1582
if
(!
surface
)
1583
return
;
1584
1585
auto
*
ww
=
surface
->
waylandWindow
();
1586
if
(!
ww
|| !
ww
->
window
())
1587
return
;
1588
1589
tp
.
area
=
QRectF
(0, 0, 8, 8);
1590
const
QPointF
globalPosition
=
ww
->
mapToGlobalF
(
surfacePosition
);
1591
tp
.
area
.
moveCenter
(
globalPosition
);
1592
}
1593
1594
// If the touch point was pressed earlier this frame, we don't want to overwrite its state.
1595
if
(
tp
.
state
!=
QEventPoint
::
Pressed
)
1596
tp
.
state
=
QEventPoint
::
State
(
state
);
1597
1598
tp
.
pressure
=
tp
.
state
==
QEventPoint
::
Released
? 0 : 1;
1599
}
1600
1601
bool
QWaylandInputDevice
::
Touch
::
allTouchPointsReleased
()
1602
{
1603
for
(
const
auto
&
tp
:
std
::
as_const
(
mPendingTouchPoints
)) {
1604
if
(
tp
.
state
!=
QEventPoint
::
Released
)
1605
return
false
;
1606
}
1607
return
true
;
1608
}
1609
1610
void
QWaylandInputDevice
::
Touch
::
releasePoints
()
1611
{
1612
if
(
mPendingTouchPoints
.
empty
())
1613
return
;
1614
1615
for
(
QWindowSystemInterface
::
TouchPoint
&
tp
:
mPendingTouchPoints
)
1616
tp
.
state
=
QEventPoint
::
Released
;
1617
1618
touch_frame
();
1619
}
1620
1621
void
QWaylandInputDevice
::
Touch
::
touch_frame
()
1622
{
1623
// TODO: early return if no events?
1624
1625
QWindow
*
window
=
nullptr
;
1626
if
(
mFocus
) {
1627
if
(
auto
*
ww
=
mFocus
->
waylandWindow
())
1628
window
=
ww
->
window
();
1629
}
1630
1631
if
(
mFocus
) {
1632
// Returns a reference to the last item in the list. The list must not be empty.
1633
// If the list can be empty, call isEmpty() before calling this function.
1634
// See: https://doc.qt.io/qt-5.15/qlist.html#last
1635
if
(
mPendingTouchPoints
.
empty
())
1636
return
;
1637
}
1638
1639
QWindowSystemInterface
::
handleTouchEvent
(
window
,
mParent
->
mTime
,
mParent
->
mTouchDevice
,
mPendingTouchPoints
,
mParent
->
modifiers
());
1640
1641
// Prepare state for next frame
1642
const
auto
prevTouchPoints
=
mPendingTouchPoints
;
1643
mPendingTouchPoints
.
clear
();
1644
for
(
const
auto
&
prevPoint
:
prevTouchPoints
) {
1645
// All non-released touch points should be part of the next touch event
1646
if
(
prevPoint
.
state
!=
QEventPoint
::
Released
) {
1647
QWindowSystemInterface
::
TouchPoint
tp
=
prevPoint
;
1648
tp
.
state
=
QEventPoint
::
Stationary
;
// ... as stationary (unless proven otherwise)
1649
mPendingTouchPoints
.
append
(
tp
);
1650
}
1651
}
1652
1653
}
1654
1655
}
1656
1657
QT_END_NAMESPACE
1658
1659
#
include
"moc_qwaylandinputdevice_p.cpp"
QtWaylandClient::EnterEvent
Definition
qwaylandinputdevice.cpp:675
QtWaylandClient::EnterEvent::EnterEvent
EnterEvent(QWaylandSurface *surface, const QPointF &local, const QPointF &global)
Definition
qwaylandinputdevice.cpp:677
QtWaylandClient::LeaveEvent
Definition
qwaylandinputdevice.cpp:727
QtWaylandClient::LeaveEvent::LeaveEvent
LeaveEvent(QWaylandSurface *surface, const QPointF &localPos, const QPointF &globalPos)
Definition
qwaylandinputdevice.cpp:729
QtWaylandClient::MotionEvent
Definition
qwaylandinputdevice.cpp:756
QtWaylandClient::MotionEvent::MotionEvent
MotionEvent(QWaylandSurface *surface, ulong timestamp, const QPointF &localPos, const QPointF &globalPos, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
Definition
qwaylandinputdevice.cpp:758
QtWaylandClient::PressEvent
Definition
qwaylandinputdevice.cpp:798
QtWaylandClient::PressEvent::PressEvent
PressEvent(QWaylandSurface *surface, ulong timestamp, const QPointF &localPos, const QPointF &globalPos, Qt::MouseButtons buttons, Qt::MouseButton button, Qt::KeyboardModifiers modifiers)
Definition
qwaylandinputdevice.cpp:800
QtWaylandClient::QWaylandPointerEvent
Definition
qwaylandinputdevice_p.h:443
QtWaylandClient::QWaylandSurface
Definition
qwaylandsurface_p.h:37
QtWaylandClient::ReleaseEvent
Definition
qwaylandinputdevice.cpp:810
QtWaylandClient::ReleaseEvent::ReleaseEvent
ReleaseEvent(QWaylandSurface *surface, ulong timestamp, const QPointF &localPos, const QPointF &globalPos, Qt::MouseButtons buttons, Qt::MouseButton button, Qt::KeyboardModifiers modifiers)
Definition
qwaylandinputdevice.cpp:812
QtWaylandClient::WheelEvent
Definition
qwaylandinputdevice.cpp:925
QtWaylandClient::WheelEvent::WheelEvent
WheelEvent(QWaylandSurface *surface, Qt::ScrollPhase phase, ulong timestamp, const QPointF &local, const QPointF &global, const QPoint &pixelDelta, const QPoint &angleDelta, Qt::MouseEventSource source, Qt::KeyboardModifiers modifiers, bool inverted)
Definition
qwaylandinputdevice.cpp:927
QtWaylandClient
Definition
qwaylandclientextension.h:16
QtWaylandClient::Q_LOGGING_CATEGORY
Q_LOGGING_CATEGORY(lcQpaWayland, "qt.qpa.wayland")
QtWaylandClient::MaxTouchPoints
static const int MaxTouchPoints
Definition
qwaylandinputdevice.cpp:68
QtWaylandClient::Q_DECLARE_LOGGING_CATEGORY
Q_DECLARE_LOGGING_CATEGORY(lcQpaWaylandInput)
QtWaylandClient::QWaylandEventCompressionPrivate
Definition
qwaylandinputdevice_p.h:82
QtWaylandClient::QWaylandEventCompressionPrivate::QWaylandEventCompressionPrivate
QWaylandEventCompressionPrivate()
Definition
qwaylandinputdevice.cpp:70
QtWaylandClient::QWaylandEventCompressionPrivate::compressEvent
bool compressEvent()
Definition
qwaylandinputdevice.cpp:76
qtbase
src
plugins
platforms
wayland
qwaylandinputdevice.cpp
Generated on
for Qt by
1.18.0