Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qwaylandtabletv2.cpp
Go to the documentation of this file.
1
// Copyright (C) 2019 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
// Qt-Security score:significant reason:default
4
5
#
include
"qwaylandtabletv2_p.h"
6
#
include
"qwaylandinputdevice_p.h"
7
#
include
"qwaylanddisplay_p.h"
8
#
include
"qwaylandsurface_p.h"
9
#
include
"qwaylandscreen_p.h"
10
#
include
"qwaylandbuffer_p.h"
11
#
include
"qwaylandcursorsurface_p.h"
12
#
include
"qwaylandcursor_p.h"
13
14
#
include
<
QtGui
/
private
/
qguiapplication_p
.
h
>
15
#
include
<
QtGui
/
private
/
qpointingdevice_p
.
h
>
16
#
include
<
QtGui
/
qpa
/
qplatformtheme
.
h
>
17
#
include
<
QtGui
/
qpa
/
qwindowsysteminterface_p
.
h
>
18
19
#
include
<
wayland
-
cursor
.
h
>
20
21
QT_BEGIN_NAMESPACE
22
23
namespace
QtWaylandClient
{
24
25
using
namespace
Qt
::
StringLiterals
;
26
27
#
if
QT_CONFIG
(
cursor
)
28
int
QWaylandTabletToolV2
::
idealCursorScale
()
const
29
{
30
if
(
m_tabletSeat
->
seat
()->
mQDisplay
->
compositor
()->
version
() < 3) {
31
return
1;
32
}
33
34
if
(
auto
*
s
=
mCursor
.
surface
.
get
()) {
35
if
(
s
->
outputScale
() > 0)
36
return
s
->
outputScale
();
37
}
38
39
return
m_tabletSeat
->
seat
()->
mCursor
.
fallbackOutputScale
;
40
}
41
42
void
QWaylandTabletToolV2
::
updateCursorTheme
()
43
{
44
QString
cursorThemeName
;
45
QSize
cursorSize
;
46
47
if
(
const
QPlatformTheme
*
platformTheme
=
QGuiApplicationPrivate
::
platformTheme
()) {
48
cursorThemeName
=
platformTheme
->
themeHint
(
QPlatformTheme
::
MouseCursorTheme
).
toString
();
49
cursorSize
=
platformTheme
->
themeHint
(
QPlatformTheme
::
MouseCursorSize
).
toSize
();
50
}
51
52
if
(
cursorThemeName
.
isEmpty
())
53
cursorThemeName
=
QStringLiteral
(
"default"
);
54
if
(
cursorSize
.
isEmpty
())
55
cursorSize
=
QSize
(24, 24);
56
57
int
scale
=
idealCursorScale
();
58
int
pixelSize
=
cursorSize
.
width
() *
scale
;
59
auto
*
display
=
m_tabletSeat
->
seat
()->
mQDisplay
;
60
mCursor
.
theme
=
display
->
loadCursorTheme
(
cursorThemeName
,
pixelSize
);
61
62
if
(!
mCursor
.
theme
)
63
return
;
// A warning has already been printed in loadCursorTheme
64
65
if
(
auto
*
arrow
=
mCursor
.
theme
->
cursor
(
Qt
::
ArrowCursor
)) {
66
int
arrowPixelSize
=
qMax
(
arrow
->
images
[0]->
width
,
67
arrow
->
images
[0]->
height
);
// Not all cursor themes are square
68
while
(
scale
> 1 &&
arrowPixelSize
/
scale
<
cursorSize
.
width
())
69
--
scale
;
70
}
else
{
71
qCWarning
(
lcQpaWayland
) <<
"Cursor theme does not support the arrow cursor"
;
72
}
73
mCursor
.
themeBufferScale
=
scale
;
74
}
75
76
void
QWaylandTabletToolV2
::
updateCursor
()
77
{
78
if
(
mEnterSerial
== 0)
79
return
;
80
81
auto
shape
=
m_tabletSeat
->
seat
()->
mCursor
.
shape
;
82
83
if
(
shape
==
Qt
::
BlankCursor
) {
84
if
(
mCursor
.
surface
)
85
mCursor
.
surface
->
reset
();
86
set_cursor
(
mEnterSerial
,
nullptr
, 0, 0);
87
return
;
88
}
89
90
if
(
shape
==
Qt
::
BitmapCursor
) {
91
auto
buffer
=
m_tabletSeat
->
seat
()->
mCursor
.
bitmapBuffer
;
92
if
(!
buffer
) {
93
qCWarning
(
lcQpaWayland
) <<
"No buffer for bitmap cursor, can't set cursor"
;
94
return
;
95
}
96
auto
hotspot
=
m_tabletSeat
->
seat
()->
mCursor
.
hotspot
;
97
int
bufferScale
=
m_tabletSeat
->
seat
()->
mCursor
.
bitmapScale
;
98
getOrCreateCursorSurface
()->
update
(
buffer
->
buffer
(),
hotspot
,
buffer
->
size
(),
bufferScale
);
99
return
;
100
}
101
102
if
(
mCursor
.
shape
) {
103
if
(
mCursor
.
surface
) {
104
mCursor
.
surface
->
reset
();
105
}
106
mCursor
.
shape
->
setShape
(
mEnterSerial
,
shape
);
107
return
;
108
}
109
110
if
(!
mCursor
.
theme
||
idealCursorScale
() !=
mCursor
.
themeBufferScale
)
111
updateCursorTheme
();
112
113
if
(!
mCursor
.
theme
)
114
return
;
115
116
// Set from shape using theme
117
QElapsedTimer
&
timer
=
m_tabletSeat
->
seat
()->
mCursor
.
animationTimer
;
118
const
uint
time
=
timer
.
isValid
() ?
timer
.
elapsed
() : 0;
119
120
if
(
struct
::
wl_cursor
*
waylandCursor
=
mCursor
.
theme
->
cursor
(
shape
)) {
121
uint
duration
= 0;
122
int
frame
=
wl_cursor_frame_and_duration
(
waylandCursor
,
time
, &
duration
);
123
::
wl_cursor_image
*
image
=
waylandCursor
->
images
[
frame
];
124
125
struct
wl_buffer
*
buffer
=
wl_cursor_image_get_buffer
(
image
);
126
if
(!
buffer
) {
127
qCWarning
(
lcQpaWayland
) <<
"Could not find buffer for cursor"
<<
shape
;
128
return
;
129
}
130
int
bufferScale
=
mCursor
.
themeBufferScale
;
131
QPoint
hotspot
=
QPoint
(
image
->
hotspot_x
,
image
->
hotspot_y
) /
bufferScale
;
132
QSize
size
=
QSize
(
image
->
width
,
image
->
height
) /
bufferScale
;
133
bool
animated
=
duration
> 0;
134
if
(
animated
) {
135
mCursor
.
gotFrameCallback
=
false
;
136
mCursor
.
gotTimerCallback
=
false
;
137
mCursor
.
frameTimer
.
start
(
duration
);
138
}
139
getOrCreateCursorSurface
()->
update
(
buffer
,
hotspot
,
size
,
bufferScale
,
animated
);
140
return
;
141
}
142
143
qCWarning
(
lcQpaWayland
) <<
"Unable to change to cursor"
<<
shape
;
144
}
145
146
CursorSurface
<
QWaylandTabletToolV2
> *
QWaylandTabletToolV2
::
getOrCreateCursorSurface
()
147
{
148
if
(!
mCursor
.
surface
)
149
mCursor
.
surface
.
reset
(
150
new
CursorSurface
<
QWaylandTabletToolV2
>(
this
,
m_tabletSeat
->
seat
()->
mQDisplay
));
151
return
mCursor
.
surface
.
get
();
152
}
153
154
void
QWaylandTabletToolV2
::
cursorTimerCallback
()
155
{
156
mCursor
.
gotTimerCallback
=
true
;
157
if
(
mCursor
.
gotFrameCallback
)
158
updateCursor
();
159
}
160
161
void
QWaylandTabletToolV2
::
cursorFrameCallback
()
162
{
163
mCursor
.
gotFrameCallback
=
true
;
164
if
(
mCursor
.
gotTimerCallback
)
165
updateCursor
();
166
}
167
168
#
endif
// QT_CONFIG(cursor)
169
170
QWaylandTabletManagerV2
::
QWaylandTabletManagerV2
(
QWaylandDisplay
*
display
,
uint
id
,
uint
version
)
171
:
zwp_tablet_manager_v2
(
display
->
wl_registry
(),
id
,
qMin
(
version
,
uint
(1)))
172
{
173
qCDebug
(
lcQpaInputDevices
,
"new tablet manager: ID %d version %d"
,
id
,
version
);
174
}
175
176
QWaylandTabletManagerV2
::~
QWaylandTabletManagerV2
()
177
{
178
destroy
();
179
}
180
181
QWaylandTabletSeatV2
::
QWaylandTabletSeatV2
(
QWaylandTabletManagerV2
*
manager
,
QWaylandInputDevice
*
seat
,
QObject
*
parent
)
182
:
QObject
(
parent
)
183
,
QtWayland
::
zwp_tablet_seat_v2
(
manager
->
get_tablet_seat
(
seat
->
wl_seat
()))
184
,
m_seat
(
seat
)
185
{
186
qCDebug
(
lcQpaInputDevices
) <<
"new tablet seat"
<<
seat
->
seatname
() <<
"id"
<<
seat
->
id
();
187
}
188
189
QWaylandTabletSeatV2
::~
QWaylandTabletSeatV2
()
190
{
191
qDeleteAll
(
m_tablets
);
192
qDeleteAll
(
m_tools
);
193
qDeleteAll
(
m_deadTools
);
194
qDeleteAll
(
m_pads
);
195
destroy
();
196
}
197
198
void
QWaylandTabletSeatV2
::
zwp_tablet_seat_v2_tablet_added
(
zwp_tablet_v2
*
id
)
199
{
200
auto
*
tablet
=
new
QWaylandTabletV2
(
id
,
m_seat
->
seatname
());
201
qCDebug
(
lcQpaInputDevices
) <<
"seat"
<<
this
<<
id
<<
"has tablet"
<<
tablet
;
202
tablet
->
setParent
(
this
);
203
m_tablets
.
push_back
(
tablet
);
204
connect
(
tablet
, &
QWaylandTabletV2
::
destroyed
,
this
, [
this
,
tablet
] {
m_tablets
.
removeOne
(
tablet
); });
205
}
206
207
void
QWaylandTabletSeatV2
::
zwp_tablet_seat_v2_tool_added
(
zwp_tablet_tool_v2
*
id
)
208
{
209
qDeleteAll
(
m_deadTools
);
210
auto
*
tool
=
new
QWaylandTabletToolV2
(
this
,
id
);
211
if
(
m_tablets
.
size
() == 1) {
212
tool
->
setParent
(
m_tablets
.
first
());
213
QPointingDevicePrivate
*
d
=
QPointingDevicePrivate
::
get
(
tool
);
214
d
->
name
=
m_tablets
.
first
()->
name
() + u" stylus";
215
}
else
{
216
qCDebug
(
lcQpaInputDevices
) <<
"seat"
<<
this
<<
"has tool"
<<
tool
<<
"for one of these tablets:"
<<
m_tablets
;
217
// TODO identify which tablet if there are several; then tool->setParent(tablet)
218
}
219
m_tools
.
push_back
(
tool
);
220
connect
(
tool
, &
QWaylandTabletToolV2
::
destroyed
,
this
, [
this
,
tool
] {
221
m_tools
.
removeOne
(
tool
);
222
m_deadTools
.
removeOne
(
tool
);
223
});
224
}
225
226
void
QWaylandTabletSeatV2
::
zwp_tablet_seat_v2_pad_added
(
zwp_tablet_pad_v2
*
id
)
227
{
228
auto
*
pad
=
new
QWaylandTabletPadV2
(
id
);
229
if
(
m_tablets
.
size
() == 1) {
230
pad
->
setParent
(
m_tablets
.
first
());
231
QPointingDevicePrivate
*
d
=
QPointingDevicePrivate
::
get
(
pad
);
232
d
->
name
=
m_tablets
.
first
()->
name
() + u" touchpad";
233
}
else
{
234
qCDebug
(
lcQpaInputDevices
) <<
"seat"
<<
this
<<
"has touchpad"
<<
pad
<<
"for one of these tablets:"
<<
m_tablets
;
235
// TODO identify which tablet if there are several
236
}
237
m_pads
.
push_back
(
pad
);
238
connect
(
pad
, &
QWaylandTabletPadV2
::
destroyed
,
this
, [
this
,
pad
] {
m_pads
.
removeOne
(
pad
); });
239
}
240
241
QWaylandTabletV2
::
QWaylandTabletV2
(::
zwp_tablet_v2
*
tablet
,
const
QString
&
seatName
,
QObject
*
parent
)
242
:
QPointingDevice
(u"unknown"_s, -1,
DeviceType
::
Stylus
,
PointerType
::
Pen
,
243
Capability
::
Position
|
Capability
::
Hover
,
244
1, 1,
seatName
,
245
QPointingDeviceUniqueId
{},
246
parent
)
247
,
QtWayland
::
zwp_tablet_v2
(
tablet
)
248
{
249
qCDebug
(
lcQpaInputDevices
) <<
"new tablet on seat"
<<
seatName
;
250
QPointingDevicePrivate
*
d
=
QPointingDevicePrivate
::
get
(
this
);
251
d
->
seatName
=
seatName
;
252
}
253
254
QWaylandTabletV2
::~
QWaylandTabletV2
()
255
{
256
destroy
();
257
}
258
259
void
QWaylandTabletV2
::
zwp_tablet_v2_name
(
const
QString
&
name
)
260
{
261
QPointingDevicePrivate
*
d
=
QPointingDevicePrivate
::
get
(
this
);
262
d
->
name
=
name
;
263
}
264
265
void
QWaylandTabletV2
::
zwp_tablet_v2_id
(
uint32_t
vid
,
uint32_t
pid
)
266
{
267
QPointingDevicePrivate
*
d
=
QPointingDevicePrivate
::
get
(
this
);
268
d
->
systemId
= (
quint64
(
vid
) << 32) |
pid
;
269
qCDebug
(
lcQpaInputDevices
) <<
"vid"
<<
vid
<<
"pid"
<<
pid
<<
"stored as systemId in"
<<
this
;
270
}
271
272
void
QWaylandTabletV2
::
zwp_tablet_v2_path
(
const
QString
&
path
)
273
{
274
QPointingDevicePrivate
*
d
=
QPointingDevicePrivate
::
get
(
this
);
275
d
->
busId
=
path
;
276
}
277
278
void
QWaylandTabletV2
::
zwp_tablet_v2_done
()
279
{
280
QWindowSystemInterface
::
registerInputDevice
(
this
);
281
}
282
283
void
QWaylandTabletSeatV2
::
updateCursor
()
284
{
285
for
(
auto
tool
:
m_tools
)
286
tool
->
updateCursor
();
287
}
288
289
void
QWaylandTabletSeatV2
::
toolRemoved
(
QWaylandTabletToolV2
*
tool
)
290
{
291
m_tools
.
removeOne
(
tool
);
292
m_deadTools
.
append
(
tool
);
293
}
294
295
void
QWaylandTabletV2
::
zwp_tablet_v2_removed
()
296
{
297
deleteLater
();
298
}
299
300
QWaylandTabletToolV2
::
QWaylandTabletToolV2
(
QWaylandTabletSeatV2
*
tabletSeat
, ::
zwp_tablet_tool_v2
*
tool
,
QObject
*
parent
)
301
:
QPointingDevice
(u"tool"_s, -1,
DeviceType
::
Stylus
,
PointerType
::
Pen
,
302
Capability
::
Position
|
Capability
::
Hover
,
303
1, 1,
tabletSeat
->
seat
()->
seatname
(),
304
QPointingDeviceUniqueId
{},
305
parent
)
306
,
QtWayland
::
zwp_tablet_tool_v2
(
tool
)
307
,
m_tabletSeat
(
tabletSeat
)
308
{
309
// TODO get the number of buttons somehow?
310
311
#
if
QT_CONFIG
(
cursor
)
312
if
(
auto
cursorShapeManager
=
m_tabletSeat
->
seat
()->
mQDisplay
->
cursorShapeManager
()) {
313
mCursor
.
shape
.
reset
(
314
new
QWaylandCursorShape
(
cursorShapeManager
->
get_tablet_tool_v2
(
object
())));
315
}
316
317
mCursor
.
frameTimer
.
setSingleShot
(
true
);
318
mCursor
.
frameTimer
.
callOnTimeout
(
this
, [&]() {
cursorTimerCallback
(); });
319
#
endif
320
}
321
322
QWaylandTabletToolV2
::~
QWaylandTabletToolV2
()
323
{
324
destroy
();
325
}
326
327
void
QWaylandTabletToolV2
::
zwp_tablet_tool_v2_type
(
uint32_t
tool_type
)
328
{
329
QPointingDevicePrivate
*
d
=
QPointingDevicePrivate
::
get
(
this
);
330
331
switch
(
tool_type
) {
332
case
type_airbrush
:
333
case
type_brush
:
334
case
type_pencil
:
335
case
type_pen
:
336
d
->
pointerType
=
QPointingDevice
::
PointerType
::
Pen
;
337
break
;
338
case
type_eraser
:
339
d
->
pointerType
=
QPointingDevice
::
PointerType
::
Eraser
;
340
break
;
341
case
type_mouse
:
342
case
type_lens
:
343
d
->
pointerType
=
QPointingDevice
::
PointerType
::
Cursor
;
344
break
;
345
case
type_finger
:
346
d
->
pointerType
=
QPointingDevice
::
PointerType
::
Unknown
;
347
break
;
348
}
349
350
switch
(
tool_type
) {
351
case
type
::
type_airbrush
:
352
d
->
deviceType
=
QInputDevice
::
DeviceType
::
Airbrush
;
353
d
->
capabilities
.
setFlag
(
QInputDevice
::
Capability
::
TangentialPressure
);
354
break
;
355
case
type
::
type_brush
:
356
case
type
::
type_pencil
:
357
case
type
::
type_pen
:
358
case
type
::
type_eraser
:
359
d
->
deviceType
=
QInputDevice
::
DeviceType
::
Stylus
;
360
break
;
361
case
type
::
type_lens
:
362
d
->
deviceType
=
QInputDevice
::
DeviceType
::
Puck
;
363
break
;
364
case
type
::
type_mouse
:
365
case
type
::
type_finger
:
366
d
->
deviceType
=
QInputDevice
::
DeviceType
::
Unknown
;
367
break
;
368
}
369
}
370
371
void
QWaylandTabletToolV2
::
zwp_tablet_tool_v2_hardware_serial
(
uint32_t
hardware_serial_hi
,
uint32_t
hardware_serial_lo
)
372
{
373
QPointingDevicePrivate
*
d
=
QPointingDevicePrivate
::
get
(
this
);
374
d
->
uniqueId
=
QPointingDeviceUniqueId
::
fromNumericId
((
quint64
(
hardware_serial_hi
) << 32) +
hardware_serial_lo
);
375
}
376
377
void
QWaylandTabletToolV2
::
zwp_tablet_tool_v2_hardware_id_wacom
(
uint32_t
hardware_id_hi
,
uint32_t
hardware_id_lo
)
378
{
379
QPointingDevicePrivate
*
d
=
QPointingDevicePrivate
::
get
(
this
);
380
d
->
systemId
= (
quint64
(
hardware_id_hi
) << 32) +
hardware_id_lo
;
381
}
382
383
void
QWaylandTabletToolV2
::
zwp_tablet_tool_v2_capability
(
uint32_t
capability
)
384
{
385
QPointingDevicePrivate
*
d
=
QPointingDevicePrivate
::
get
(
this
);
386
switch
(
capability
) {
387
case
capability_tilt
:
388
// no distinction... we have to assume it has both axes
389
d
->
capabilities
.
setFlag
(
QInputDevice
::
Capability
::
XTilt
);
390
d
->
capabilities
.
setFlag
(
QInputDevice
::
Capability
::
YTilt
);
391
break
;
392
case
capability_pressure
:
393
d
->
capabilities
.
setFlag
(
QInputDevice
::
Capability
::
Pressure
);
394
break
;
395
case
capability_distance
:
396
d
->
capabilities
.
setFlag
(
QInputDevice
::
Capability
::
ZPosition
);
397
break
;
398
case
capability_rotation
:
399
d
->
capabilities
.
setFlag
(
QInputDevice
::
Capability
::
Rotation
);
400
break
;
401
case
capability_slider
:
402
// nothing to represent that so far
403
break
;
404
case
capability_wheel
:
405
d
->
capabilities
.
setFlag
(
QInputDevice
::
Capability
::
Scroll
);
406
d
->
capabilities
.
setFlag
(
QInputDevice
::
Capability
::
PixelScroll
);
407
break
;
408
}
409
qCDebug
(
lcQpaInputDevices
) <<
capability
<<
"->"
<<
this
;
410
}
411
412
void
QWaylandTabletToolV2
::
zwp_tablet_tool_v2_done
()
413
{
414
QWindowSystemInterface
::
registerInputDevice
(
this
);
415
}
416
417
void
QWaylandTabletToolV2
::
zwp_tablet_tool_v2_removed
()
418
{
419
m_tabletSeat
->
toolRemoved
(
this
);
420
}
421
422
void
QWaylandTabletToolV2
::
zwp_tablet_tool_v2_proximity_in
(
uint32_t
serial
,
zwp_tablet_v2
*
tablet
,
wl_surface
*
surface
)
423
{
424
Q_UNUSED
(
tablet
);
425
426
m_tabletSeat
->
seat
()->
mSerial
=
serial
;
427
mEnterSerial
=
serial
;
428
429
if
(
Q_UNLIKELY
(!
surface
)) {
430
qCDebug
(
lcQpaWayland
) <<
"Ignoring zwp_tablet_tool_v2_proximity_v2 with no surface"
;
431
return
;
432
}
433
m_pending
.
enteredSurface
=
true
;
434
m_pending
.
proximitySurface
=
QWaylandSurface
::
fromWlSurface
(
surface
);
435
436
#
if
QT_CONFIG
(
cursor
)
437
// Depends on mEnterSerial being updated
438
updateCursor
();
439
#
endif
440
}
441
442
void
QWaylandTabletToolV2
::
zwp_tablet_tool_v2_proximity_out
()
443
{
444
m_pending
.
enteredSurface
=
false
;
445
m_pending
.
proximitySurface
=
nullptr
;
446
}
447
448
void
QWaylandTabletToolV2
::
zwp_tablet_tool_v2_down
(
uint32_t
serial
)
449
{
450
m_pending
.
down
=
true
;
451
452
m_tabletSeat
->
seat
()->
mSerial
=
serial
;
453
454
if
(
m_pending
.
proximitySurface
) {
455
if
(
QWaylandSurface
*
window
=
m_pending
.
proximitySurface
) {
456
QWaylandInputDevice
*
seat
=
m_tabletSeat
->
seat
();
457
seat
->
display
()->
setLastInputDevice
(
seat
,
serial
,
window
);
458
}
459
}
460
}
461
462
void
QWaylandTabletToolV2
::
zwp_tablet_tool_v2_up
()
463
{
464
m_pending
.
down
=
false
;
465
}
466
467
void
QWaylandTabletToolV2
::
zwp_tablet_tool_v2_motion
(
wl_fixed_t
x
,
wl_fixed_t
y
)
468
{
469
m_pending
.
surfacePosition
=
QPointF
(
wl_fixed_to_double
(
x
),
wl_fixed_to_double
(
y
));
470
}
471
472
void
QWaylandTabletToolV2
::
zwp_tablet_tool_v2_pressure
(
uint32_t
pressure
)
473
{
474
const
int
maxPressure
= 65535;
475
m_pending
.
pressure
=
qreal
(
pressure
)/
maxPressure
;
476
}
477
478
void
QWaylandTabletToolV2
::
zwp_tablet_tool_v2_distance
(
uint32_t
distance
)
479
{
480
m_pending
.
distance
=
distance
;
481
}
482
483
void
QWaylandTabletToolV2
::
zwp_tablet_tool_v2_tilt
(
wl_fixed_t
tilt_x
,
wl_fixed_t
tilt_y
)
484
{
485
m_pending
.
xTilt
=
wl_fixed_to_double
(
tilt_x
);
486
m_pending
.
yTilt
=
wl_fixed_to_double
(
tilt_y
);
487
}
488
489
void
QWaylandTabletToolV2
::
zwp_tablet_tool_v2_rotation
(
wl_fixed_t
degrees
)
490
{
491
m_pending
.
rotation
=
wl_fixed_to_double
(
degrees
);
492
}
493
494
void
QWaylandTabletToolV2
::
zwp_tablet_tool_v2_slider
(
int32_t
position
)
495
{
496
m_pending
.
slider
=
qreal
(
position
) / 65535;
497
}
498
499
static
Qt
::
MouseButton
mouseButtonFromTablet
(uint button)
500
{
501
switch
(button) {
502
case
0x110:
return
Qt::MouseButton::LeftButton;
// BTN_LEFT
503
case
0x14b:
return
Qt::MouseButton::MiddleButton;
// BTN_STYLUS
504
case
0x14c:
return
Qt::MouseButton::RightButton;
// BTN_STYLUS2
505
default
:
506
return
Qt::NoButton;
507
}
508
}
509
510
void
QWaylandTabletToolV2
::
zwp_tablet_tool_v2_button
(
uint32_t
serial
,
uint32_t
button
,
uint32_t
state
)
511
{
512
m_tabletSeat
->
seat
()->
mSerial
=
serial
;
513
514
QPointingDevicePrivate
*
d
=
QPointingDevicePrivate
::
get
(
this
);
515
Qt
::
MouseButton
mouseButton
=
mouseButtonFromTablet
(
button
);
516
if
(
state
==
button_state_pressed
)
517
m_pending
.
buttons
|=
mouseButton
;
518
else
519
m_pending
.
buttons
&= ~
mouseButton
;
520
// ideally we'd get button count when the tool is discovered; seems to be a shortcoming in tablet-unstable-v2
521
// but if we get events from buttons we didn't know existed, increase it
522
if
(
mouseButton
==
Qt
::
RightButton
)
523
d
->
buttonCount
=
qMax
(
d
->
buttonCount
, 2);
524
else
if
(
mouseButton
==
Qt
::
MiddleButton
)
525
d
->
buttonCount
=
qMax
(
d
->
buttonCount
, 3);
526
}
527
528
void
QWaylandTabletToolV2
::
zwp_tablet_tool_v2_frame
(
uint32_t
time
)
529
{
530
if
(!
m_pending
.
proximitySurface
) {
531
if
(
m_applied
.
enteredSurface
) {
532
// leaving proximity
533
QWindowSystemInterface
::
handleTabletEnterLeaveProximityEvent
(
nullptr
,
this
,
false
);
534
m_pending
=
State
();
// Don't leave pressure etc. lying around when we enter the next surface
535
m_applied
=
State
();
536
}
else
{
537
qCWarning
(
lcQpaWayland
) <<
"Can't send tablet event with no proximity surface, ignoring"
;
538
}
539
return
;
540
}
541
542
QWaylandWindow
*
waylandWindow
=
QWaylandWindow
::
fromWlSurface
(
m_pending
.
proximitySurface
->
object
());
543
QWindow
*
window
=
waylandWindow
->
window
();
544
const
bool
needsTabletEvent
= !(
m_pending
==
m_applied
);
545
546
if
(!
m_applied
.
proximitySurface
||
needsTabletEvent
) {
547
ulong
timestamp
=
time
;
548
const
QPointF
localPosition
=
waylandWindow
->
mapFromWlSurface
(
m_pending
.
surfacePosition
);
549
const
QPointF
globalPosition
=
waylandWindow
->
mapToGlobalF
(
localPosition
);
550
const
Qt
::
MouseButtons
buttons
=
m_pending
.
buttons
|
551
(
m_pending
.
down
?
Qt
::
MouseButton
::
LeftButton
:
Qt
::
MouseButton
::
NoButton
);
552
const
qreal
pressure
=
m_pending
.
pressure
;
553
const
qreal
xTilt
=
m_pending
.
xTilt
;
554
const
qreal
yTilt
=
m_pending
.
yTilt
;
555
const
qreal
tangentialPressure
=
m_pending
.
slider
;
556
const
qreal
rotation
=
m_pending
.
rotation
;
557
const
int
z
=
int
(
m_pending
.
distance
);
558
559
if
(!
m_applied
.
proximitySurface
) {
560
QWindowSystemInterface
::
handleTabletEnterLeaveProximityEvent
(
window
,
this
,
true
,
localPosition
,
globalPosition
,
561
buttons
,
xTilt
,
yTilt
,
tangentialPressure
,
rotation
,
z
,
562
m_tabletSeat
->
seat
()->
modifiers
());
563
m_applied
.
proximitySurface
=
m_pending
.
proximitySurface
;
564
}
565
566
if
(
needsTabletEvent
) {
567
// do not use localPosition here since that is in Qt window coordinates
568
// but we need surface coordinates to include the decoration
569
bool
decorationHandledEvent
=
waylandWindow
->
handleTabletEventDecoration
(
570
m_tabletSeat
->
seat
(),
m_pending
.
surfacePosition
,
571
window
->
mapToGlobal
(
m_pending
.
surfacePosition
),
buttons
,
572
m_tabletSeat
->
seat
()->
modifiers
());
573
574
if
(!
decorationHandledEvent
) {
575
QWindowSystemInterface
::
handleTabletEvent
(
window
,
timestamp
,
this
,
localPosition
,
globalPosition
,
576
buttons
,
pressure
,
577
xTilt
,
yTilt
,
tangentialPressure
,
rotation
,
z
,
578
m_tabletSeat
->
seat
()->
modifiers
());
579
m_tabletSeat
->
seat
()->
display
()->
waylandCursor
()->
setPosFromEnterEvent
(
globalPosition
.
toPoint
());
580
}
581
}
582
}
583
584
m_applied
=
m_pending
;
585
}
586
587
// TODO: delete when upgrading to c++20
588
bool
QWaylandTabletToolV2
::
State
::
operator
==(
const
QWaylandTabletToolV2
::
State
&
o
)
const
{
589
return
590
down
==
o
.
down
&&
591
proximitySurface
.
data
() ==
o
.
proximitySurface
.
data
() &&
592
enteredSurface
==
o
.
enteredSurface
&&
593
surfacePosition
==
o
.
surfacePosition
&&
594
distance
==
o
.
distance
&&
595
pressure
==
o
.
pressure
&&
596
rotation
==
o
.
rotation
&&
597
xTilt
==
o
.
xTilt
&&
598
yTilt
==
o
.
yTilt
&&
599
slider
==
o
.
slider
&&
600
buttons
==
o
.
buttons
;
601
}
602
603
QWaylandTabletPadV2
::
QWaylandTabletPadV2
(::
zwp_tablet_pad_v2
*
pad
,
QObject
*
parent
)
604
:
QPointingDevice
(u"tablet touchpad"_s, -1,
DeviceType
::
TouchPad
,
PointerType
::
Finger
,
605
Capability
::
Position
,
606
1, 1,
QString
{},
607
QPointingDeviceUniqueId
{},
608
parent
)
609
,
QtWayland
::
zwp_tablet_pad_v2
(
pad
)
610
{
611
}
612
613
QWaylandTabletPadV2
::~
QWaylandTabletPadV2
()
614
{
615
destroy
();
616
}
617
618
void
QWaylandTabletPadV2
::
zwp_tablet_pad_v2_path
(
const
QString
&
path
)
619
{
620
QPointingDevicePrivate
*
d
=
QPointingDevicePrivate
::
get
(
this
);
621
d
->
busId
=
path
;
622
}
623
624
void
QWaylandTabletPadV2
::
zwp_tablet_pad_v2_buttons
(
uint32_t
buttons
)
625
{
626
QPointingDevicePrivate
*
d
=
QPointingDevicePrivate
::
get
(
this
);
627
d
->
buttonCount
=
buttons
;
628
}
629
630
void
QWaylandTabletPadV2
::
zwp_tablet_pad_v2_group
(
zwp_tablet_pad_group_v2
*
pad_group
)
631
{
632
// As of writing Qt does not handle tablet pads group and the controls on it
633
// This proxy is server created so it is just deleted here to not leak it
634
zwp_tablet_pad_group_v2_destroy
(
pad_group
);
635
}
636
637
void
QWaylandTabletPadV2
::
zwp_tablet_pad_v2_done
()
638
{
639
QWindowSystemInterface
::
registerInputDevice
(
this
);
640
}
641
642
void
QWaylandTabletPadV2
::
zwp_tablet_pad_v2_removed
()
643
{
644
delete
this
;
645
}
646
647
}
// namespace QtWaylandClient
648
649
QT_END_NAMESPACE
650
651
#
include
"moc_qwaylandtabletv2_p.cpp"
QtWaylandClient
Definition
qwaylandclientextension.h:16
QtWaylandClient::mouseButtonFromTablet
static Qt::MouseButton mouseButtonFromTablet(uint button)
Definition
qwaylandtabletv2.cpp:499
qtbase
src
plugins
platforms
wayland
qwaylandtabletv2.cpp
Generated on
for Qt by
1.16.1