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
.
data
()) {
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
)
182
:
QtWayland
::
zwp_tablet_seat_v2
(
manager
->
get_tablet_seat
(
seat
->
wl_seat
()))
183
,
m_seat
(
seat
)
184
{
185
qCDebug
(
lcQpaInputDevices
) <<
"new tablet seat"
<<
seat
->
seatname
() <<
"id"
<<
seat
->
id
();
186
}
187
188
QWaylandTabletSeatV2
::~
QWaylandTabletSeatV2
()
189
{
190
qDeleteAll
(
m_tablets
);
191
qDeleteAll
(
m_tools
);
192
qDeleteAll
(
m_deadTools
);
193
qDeleteAll
(
m_pads
);
194
destroy
();
195
}
196
197
void
QWaylandTabletSeatV2
::
zwp_tablet_seat_v2_tablet_added
(
zwp_tablet_v2
*
id
)
198
{
199
auto
*
tablet
=
new
QWaylandTabletV2
(
id
,
m_seat
->
seatname
());
200
qCDebug
(
lcQpaInputDevices
) <<
"seat"
<<
this
<<
id
<<
"has tablet"
<<
tablet
;
201
tablet
->
setParent
(
this
);
202
m_tablets
.
push_back
(
tablet
);
203
connect
(
tablet
, &
QWaylandTabletV2
::
destroyed
,
this
, [
this
,
tablet
] {
m_tablets
.
removeOne
(
tablet
); });
204
}
205
206
void
QWaylandTabletSeatV2
::
zwp_tablet_seat_v2_tool_added
(
zwp_tablet_tool_v2
*
id
)
207
{
208
qDeleteAll
(
m_deadTools
);
209
auto
*
tool
=
new
QWaylandTabletToolV2
(
this
,
id
);
210
if
(
m_tablets
.
size
() == 1) {
211
tool
->
setParent
(
m_tablets
.
first
());
212
QPointingDevicePrivate
*
d
=
QPointingDevicePrivate
::
get
(
tool
);
213
d
->
name
=
m_tablets
.
first
()->
name
() + u" stylus";
214
}
else
{
215
qCDebug
(
lcQpaInputDevices
) <<
"seat"
<<
this
<<
"has tool"
<<
tool
<<
"for one of these tablets:"
<<
m_tablets
;
216
// TODO identify which tablet if there are several; then tool->setParent(tablet)
217
}
218
m_tools
.
push_back
(
tool
);
219
connect
(
tool
, &
QWaylandTabletToolV2
::
destroyed
,
this
, [
this
,
tool
] {
220
m_tools
.
removeOne
(
tool
);
221
m_deadTools
.
removeOne
(
tool
);
222
});
223
}
224
225
void
QWaylandTabletSeatV2
::
zwp_tablet_seat_v2_pad_added
(
zwp_tablet_pad_v2
*
id
)
226
{
227
auto
*
pad
=
new
QWaylandTabletPadV2
(
id
);
228
if
(
m_tablets
.
size
() == 1) {
229
pad
->
setParent
(
m_tablets
.
first
());
230
QPointingDevicePrivate
*
d
=
QPointingDevicePrivate
::
get
(
pad
);
231
d
->
name
=
m_tablets
.
first
()->
name
() + u" touchpad";
232
}
else
{
233
qCDebug
(
lcQpaInputDevices
) <<
"seat"
<<
this
<<
"has touchpad"
<<
pad
<<
"for one of these tablets:"
<<
m_tablets
;
234
// TODO identify which tablet if there are several
235
}
236
m_pads
.
push_back
(
pad
);
237
connect
(
pad
, &
QWaylandTabletPadV2
::
destroyed
,
this
, [
this
,
pad
] {
m_pads
.
removeOne
(
pad
); });
238
}
239
240
QWaylandTabletV2
::
QWaylandTabletV2
(::
zwp_tablet_v2
*
tablet
,
const
QString
&
seatName
)
241
:
QPointingDevice
(u"unknown"_s, -1,
DeviceType
::
Stylus
,
PointerType
::
Pen
,
242
Capability
::
Position
|
Capability
::
Hover
,
243
1, 1,
seatName
)
244
,
QtWayland
::
zwp_tablet_v2
(
tablet
)
245
{
246
qCDebug
(
lcQpaInputDevices
) <<
"new tablet on seat"
<<
seatName
;
247
QPointingDevicePrivate
*
d
=
QPointingDevicePrivate
::
get
(
this
);
248
d
->
seatName
=
seatName
;
249
}
250
251
QWaylandTabletV2
::~
QWaylandTabletV2
()
252
{
253
destroy
();
254
}
255
256
void
QWaylandTabletV2
::
zwp_tablet_v2_name
(
const
QString
&
name
)
257
{
258
QPointingDevicePrivate
*
d
=
QPointingDevicePrivate
::
get
(
this
);
259
d
->
name
=
name
;
260
}
261
262
void
QWaylandTabletV2
::
zwp_tablet_v2_id
(
uint32_t
vid
,
uint32_t
pid
)
263
{
264
QPointingDevicePrivate
*
d
=
QPointingDevicePrivate
::
get
(
this
);
265
d
->
systemId
= (
quint64
(
vid
) << 32) |
pid
;
266
qCDebug
(
lcQpaInputDevices
) <<
"vid"
<<
vid
<<
"pid"
<<
pid
<<
"stored as systemId in"
<<
this
;
267
}
268
269
void
QWaylandTabletV2
::
zwp_tablet_v2_path
(
const
QString
&
path
)
270
{
271
QPointingDevicePrivate
*
d
=
QPointingDevicePrivate
::
get
(
this
);
272
d
->
busId
=
path
;
273
}
274
275
void
QWaylandTabletV2
::
zwp_tablet_v2_done
()
276
{
277
QWindowSystemInterface
::
registerInputDevice
(
this
);
278
}
279
280
void
QWaylandTabletSeatV2
::
updateCursor
()
281
{
282
for
(
auto
tool
:
m_tools
)
283
tool
->
updateCursor
();
284
}
285
286
void
QWaylandTabletSeatV2
::
toolRemoved
(
QWaylandTabletToolV2
*
tool
)
287
{
288
m_tools
.
removeOne
(
tool
);
289
m_deadTools
.
append
(
tool
);
290
}
291
292
void
QWaylandTabletV2
::
zwp_tablet_v2_removed
()
293
{
294
deleteLater
();
295
}
296
297
QWaylandTabletToolV2
::
QWaylandTabletToolV2
(
QWaylandTabletSeatV2
*
tabletSeat
, ::
zwp_tablet_tool_v2
*
tool
)
298
:
QPointingDevice
(u"tool"_s, -1,
DeviceType
::
Stylus
,
PointerType
::
Pen
,
299
Capability
::
Position
|
Capability
::
Hover
,
300
1, 1,
tabletSeat
->
seat
()->
seatname
())
301
,
QtWayland
::
zwp_tablet_tool_v2
(
tool
)
302
,
m_tabletSeat
(
tabletSeat
)
303
{
304
// TODO get the number of buttons somehow?
305
306
#
if
QT_CONFIG
(
cursor
)
307
if
(
auto
cursorShapeManager
=
m_tabletSeat
->
seat
()->
mQDisplay
->
cursorShapeManager
()) {
308
mCursor
.
shape
.
reset
(
309
new
QWaylandCursorShape
(
cursorShapeManager
->
get_tablet_tool_v2
(
object
())));
310
}
311
312
mCursor
.
frameTimer
.
setSingleShot
(
true
);
313
mCursor
.
frameTimer
.
callOnTimeout
(
this
, [&]() {
cursorTimerCallback
(); });
314
#
endif
315
}
316
317
QWaylandTabletToolV2
::~
QWaylandTabletToolV2
()
318
{
319
destroy
();
320
}
321
322
void
QWaylandTabletToolV2
::
zwp_tablet_tool_v2_type
(
uint32_t
tool_type
)
323
{
324
QPointingDevicePrivate
*
d
=
QPointingDevicePrivate
::
get
(
this
);
325
326
switch
(
tool_type
) {
327
case
type_airbrush
:
328
case
type_brush
:
329
case
type_pencil
:
330
case
type_pen
:
331
d
->
pointerType
=
QPointingDevice
::
PointerType
::
Pen
;
332
break
;
333
case
type_eraser
:
334
d
->
pointerType
=
QPointingDevice
::
PointerType
::
Eraser
;
335
break
;
336
case
type_mouse
:
337
case
type_lens
:
338
d
->
pointerType
=
QPointingDevice
::
PointerType
::
Cursor
;
339
break
;
340
case
type_finger
:
341
d
->
pointerType
=
QPointingDevice
::
PointerType
::
Unknown
;
342
break
;
343
}
344
345
switch
(
tool_type
) {
346
case
type
::
type_airbrush
:
347
d
->
deviceType
=
QInputDevice
::
DeviceType
::
Airbrush
;
348
d
->
capabilities
.
setFlag
(
QInputDevice
::
Capability
::
TangentialPressure
);
349
break
;
350
case
type
::
type_brush
:
351
case
type
::
type_pencil
:
352
case
type
::
type_pen
:
353
case
type
::
type_eraser
:
354
d
->
deviceType
=
QInputDevice
::
DeviceType
::
Stylus
;
355
break
;
356
case
type
::
type_lens
:
357
d
->
deviceType
=
QInputDevice
::
DeviceType
::
Puck
;
358
break
;
359
case
type
::
type_mouse
:
360
case
type
::
type_finger
:
361
d
->
deviceType
=
QInputDevice
::
DeviceType
::
Unknown
;
362
break
;
363
}
364
}
365
366
void
QWaylandTabletToolV2
::
zwp_tablet_tool_v2_hardware_serial
(
uint32_t
hardware_serial_hi
,
uint32_t
hardware_serial_lo
)
367
{
368
QPointingDevicePrivate
*
d
=
QPointingDevicePrivate
::
get
(
this
);
369
d
->
uniqueId
=
QPointingDeviceUniqueId
::
fromNumericId
((
quint64
(
hardware_serial_hi
) << 32) +
hardware_serial_lo
);
370
}
371
372
void
QWaylandTabletToolV2
::
zwp_tablet_tool_v2_hardware_id_wacom
(
uint32_t
hardware_id_hi
,
uint32_t
hardware_id_lo
)
373
{
374
QPointingDevicePrivate
*
d
=
QPointingDevicePrivate
::
get
(
this
);
375
d
->
systemId
= (
quint64
(
hardware_id_hi
) << 32) +
hardware_id_lo
;
376
}
377
378
void
QWaylandTabletToolV2
::
zwp_tablet_tool_v2_capability
(
uint32_t
capability
)
379
{
380
QPointingDevicePrivate
*
d
=
QPointingDevicePrivate
::
get
(
this
);
381
switch
(
capability
) {
382
case
capability_tilt
:
383
// no distinction... we have to assume it has both axes
384
d
->
capabilities
.
setFlag
(
QInputDevice
::
Capability
::
XTilt
);
385
d
->
capabilities
.
setFlag
(
QInputDevice
::
Capability
::
YTilt
);
386
break
;
387
case
capability_pressure
:
388
d
->
capabilities
.
setFlag
(
QInputDevice
::
Capability
::
Pressure
);
389
break
;
390
case
capability_distance
:
391
d
->
capabilities
.
setFlag
(
QInputDevice
::
Capability
::
ZPosition
);
392
break
;
393
case
capability_rotation
:
394
d
->
capabilities
.
setFlag
(
QInputDevice
::
Capability
::
Rotation
);
395
break
;
396
case
capability_slider
:
397
// nothing to represent that so far
398
break
;
399
case
capability_wheel
:
400
d
->
capabilities
.
setFlag
(
QInputDevice
::
Capability
::
Scroll
);
401
d
->
capabilities
.
setFlag
(
QInputDevice
::
Capability
::
PixelScroll
);
402
break
;
403
}
404
qCDebug
(
lcQpaInputDevices
) <<
capability
<<
"->"
<<
this
;
405
}
406
407
void
QWaylandTabletToolV2
::
zwp_tablet_tool_v2_done
()
408
{
409
QWindowSystemInterface
::
registerInputDevice
(
this
);
410
}
411
412
void
QWaylandTabletToolV2
::
zwp_tablet_tool_v2_removed
()
413
{
414
m_tabletSeat
->
toolRemoved
(
this
);
415
}
416
417
void
QWaylandTabletToolV2
::
zwp_tablet_tool_v2_proximity_in
(
uint32_t
serial
,
zwp_tablet_v2
*
tablet
,
wl_surface
*
surface
)
418
{
419
Q_UNUSED
(
tablet
);
420
421
m_tabletSeat
->
seat
()->
mSerial
=
serial
;
422
mEnterSerial
=
serial
;
423
424
if
(
Q_UNLIKELY
(!
surface
)) {
425
qCDebug
(
lcQpaWayland
) <<
"Ignoring zwp_tablet_tool_v2_proximity_v2 with no surface"
;
426
return
;
427
}
428
m_pending
.
enteredSurface
=
true
;
429
m_pending
.
proximitySurface
=
QWaylandSurface
::
fromWlSurface
(
surface
);
430
431
#
if
QT_CONFIG
(
cursor
)
432
// Depends on mEnterSerial being updated
433
updateCursor
();
434
#
endif
435
}
436
437
void
QWaylandTabletToolV2
::
zwp_tablet_tool_v2_proximity_out
()
438
{
439
m_pending
.
enteredSurface
=
false
;
440
m_pending
.
proximitySurface
=
nullptr
;
441
}
442
443
void
QWaylandTabletToolV2
::
zwp_tablet_tool_v2_down
(
uint32_t
serial
)
444
{
445
m_pending
.
down
=
true
;
446
447
m_tabletSeat
->
seat
()->
mSerial
=
serial
;
448
449
if
(
m_pending
.
proximitySurface
) {
450
if
(
QWaylandWindow
*
window
=
m_pending
.
proximitySurface
->
waylandWindow
()) {
451
QWaylandInputDevice
*
seat
=
m_tabletSeat
->
seat
();
452
seat
->
display
()->
setLastInputDevice
(
seat
,
serial
,
window
);
453
}
454
}
455
}
456
457
void
QWaylandTabletToolV2
::
zwp_tablet_tool_v2_up
()
458
{
459
m_pending
.
down
=
false
;
460
}
461
462
void
QWaylandTabletToolV2
::
zwp_tablet_tool_v2_motion
(
wl_fixed_t
x
,
wl_fixed_t
y
)
463
{
464
m_pending
.
surfacePosition
=
QPointF
(
wl_fixed_to_double
(
x
),
wl_fixed_to_double
(
y
));
465
}
466
467
void
QWaylandTabletToolV2
::
zwp_tablet_tool_v2_pressure
(
uint32_t
pressure
)
468
{
469
const
int
maxPressure
= 65535;
470
m_pending
.
pressure
=
qreal
(
pressure
)/
maxPressure
;
471
}
472
473
void
QWaylandTabletToolV2
::
zwp_tablet_tool_v2_distance
(
uint32_t
distance
)
474
{
475
m_pending
.
distance
=
distance
;
476
}
477
478
void
QWaylandTabletToolV2
::
zwp_tablet_tool_v2_tilt
(
wl_fixed_t
tilt_x
,
wl_fixed_t
tilt_y
)
479
{
480
m_pending
.
xTilt
=
wl_fixed_to_double
(
tilt_x
);
481
m_pending
.
yTilt
=
wl_fixed_to_double
(
tilt_y
);
482
}
483
484
void
QWaylandTabletToolV2
::
zwp_tablet_tool_v2_rotation
(
wl_fixed_t
degrees
)
485
{
486
m_pending
.
rotation
=
wl_fixed_to_double
(
degrees
);
487
}
488
489
void
QWaylandTabletToolV2
::
zwp_tablet_tool_v2_slider
(
int32_t
position
)
490
{
491
m_pending
.
slider
=
qreal
(
position
) / 65535;
492
}
493
494
static
Qt
::
MouseButton
mouseButtonFromTablet
(uint button)
495
{
496
switch
(button) {
497
case
0x110:
return
Qt::MouseButton::LeftButton;
// BTN_LEFT
498
case
0x14b:
return
Qt::MouseButton::MiddleButton;
// BTN_STYLUS
499
case
0x14c:
return
Qt::MouseButton::RightButton;
// BTN_STYLUS2
500
default
:
501
return
Qt::NoButton;
502
}
503
}
504
505
void
QWaylandTabletToolV2
::
zwp_tablet_tool_v2_button
(
uint32_t
serial
,
uint32_t
button
,
uint32_t
state
)
506
{
507
m_tabletSeat
->
seat
()->
mSerial
=
serial
;
508
509
QPointingDevicePrivate
*
d
=
QPointingDevicePrivate
::
get
(
this
);
510
Qt
::
MouseButton
mouseButton
=
mouseButtonFromTablet
(
button
);
511
if
(
state
==
button_state_pressed
)
512
m_pending
.
buttons
|=
mouseButton
;
513
else
514
m_pending
.
buttons
&= ~
mouseButton
;
515
// ideally we'd get button count when the tool is discovered; seems to be a shortcoming in tablet-unstable-v2
516
// but if we get events from buttons we didn't know existed, increase it
517
if
(
mouseButton
==
Qt
::
RightButton
)
518
d
->
buttonCount
=
qMax
(
d
->
buttonCount
, 2);
519
else
if
(
mouseButton
==
Qt
::
MiddleButton
)
520
d
->
buttonCount
=
qMax
(
d
->
buttonCount
, 3);
521
}
522
523
void
QWaylandTabletToolV2
::
zwp_tablet_tool_v2_frame
(
uint32_t
time
)
524
{
525
if
(!
m_pending
.
proximitySurface
) {
526
if
(
m_applied
.
enteredSurface
) {
527
// leaving proximity
528
QWindowSystemInterface
::
handleTabletEnterLeaveProximityEvent
(
nullptr
,
this
,
false
);
529
m_pending
=
State
();
// Don't leave pressure etc. lying around when we enter the next surface
530
m_applied
=
State
();
531
}
else
{
532
qCWarning
(
lcQpaWayland
) <<
"Can't send tablet event with no proximity surface, ignoring"
;
533
}
534
return
;
535
}
536
537
QWaylandWindow
*
waylandWindow
=
QWaylandWindow
::
fromWlSurface
(
m_pending
.
proximitySurface
->
object
());
538
QWindow
*
window
=
waylandWindow
->
window
();
539
540
if
(!
m_applied
.
proximitySurface
) {
541
// TODO get position etc. as below
542
QWindowSystemInterface
::
handleTabletEnterLeaveProximityEvent
(
window
,
this
,
true
);
543
m_applied
.
proximitySurface
=
m_pending
.
proximitySurface
;
544
}
545
546
if
(!(
m_pending
==
m_applied
)) {
547
ulong
timestamp
=
time
;
548
const
QPointF
localPosition
=
waylandWindow
->
mapFromWlSurface
(
m_pending
.
surfacePosition
);
549
550
const
QPointF
globalPosition
=
waylandWindow
->
mapToGlobalF
(
localPosition
);
551
552
Qt
::
MouseButtons
buttons
=
m_pending
.
down
?
Qt
::
MouseButton
::
LeftButton
:
Qt
::
MouseButton
::
NoButton
;
553
buttons
|=
m_pending
.
buttons
;
554
qreal
pressure
=
m_pending
.
pressure
;
555
qreal
xTilt
=
m_pending
.
xTilt
;
556
qreal
yTilt
=
m_pending
.
yTilt
;
557
qreal
tangentialPressure
=
m_pending
.
slider
;
558
qreal
rotation
=
m_pending
.
rotation
;
559
int
z
=
int
(
m_pending
.
distance
);
560
561
// do not use localPosition here since that is in Qt window coordinates
562
// but we need surface coordinates to include the decoration
563
bool
decorationHandledEvent
=
waylandWindow
->
handleTabletEventDecoration
(
564
m_tabletSeat
->
seat
(),
m_pending
.
surfacePosition
,
565
window
->
mapToGlobal
(
m_pending
.
surfacePosition
),
buttons
,
566
m_tabletSeat
->
seat
()->
modifiers
());
567
568
if
(!
decorationHandledEvent
) {
569
QWindowSystemInterface
::
handleTabletEvent
(
window
,
timestamp
,
this
,
localPosition
,
globalPosition
,
570
buttons
,
pressure
,
571
xTilt
,
yTilt
,
tangentialPressure
,
rotation
,
z
,
572
m_tabletSeat
->
seat
()->
modifiers
());
573
}
574
}
575
576
m_applied
=
m_pending
;
577
}
578
579
// TODO: delete when upgrading to c++20
580
bool
QWaylandTabletToolV2
::
State
::
operator
==(
const
QWaylandTabletToolV2
::
State
&
o
)
const
{
581
return
582
down
==
o
.
down
&&
583
proximitySurface
.
data
() ==
o
.
proximitySurface
.
data
() &&
584
enteredSurface
==
o
.
enteredSurface
&&
585
surfacePosition
==
o
.
surfacePosition
&&
586
distance
==
o
.
distance
&&
587
pressure
==
o
.
pressure
&&
588
rotation
==
o
.
rotation
&&
589
xTilt
==
o
.
xTilt
&&
590
yTilt
==
o
.
yTilt
&&
591
slider
==
o
.
slider
&&
592
buttons
==
o
.
buttons
;
593
}
594
595
QWaylandTabletPadV2
::
QWaylandTabletPadV2
(::
zwp_tablet_pad_v2
*
pad
)
596
:
QPointingDevice
(u"tablet touchpad"_s, -1,
DeviceType
::
TouchPad
,
PointerType
::
Finger
,
597
Capability
::
Position
,
598
1, 1)
599
,
QtWayland
::
zwp_tablet_pad_v2
(
pad
)
600
{
601
}
602
603
QWaylandTabletPadV2
::~
QWaylandTabletPadV2
()
604
{
605
destroy
();
606
}
607
608
void
QWaylandTabletPadV2
::
zwp_tablet_pad_v2_path
(
const
QString
&
path
)
609
{
610
QPointingDevicePrivate
*
d
=
QPointingDevicePrivate
::
get
(
this
);
611
d
->
busId
=
path
;
612
}
613
614
void
QWaylandTabletPadV2
::
zwp_tablet_pad_v2_buttons
(
uint32_t
buttons
)
615
{
616
QPointingDevicePrivate
*
d
=
QPointingDevicePrivate
::
get
(
this
);
617
d
->
buttonCount
=
buttons
;
618
}
619
620
void
QWaylandTabletPadV2
::
zwp_tablet_pad_v2_group
(
zwp_tablet_pad_group_v2
*
pad_group
)
621
{
622
// As of writing Qt does not handle tablet pads group and the controls on it
623
// This proxy is server created so it is just deleted here to not leak it
624
zwp_tablet_pad_group_v2_destroy
(
pad_group
);
625
}
626
627
void
QWaylandTabletPadV2
::
zwp_tablet_pad_v2_done
()
628
{
629
QWindowSystemInterface
::
registerInputDevice
(
this
);
630
}
631
632
void
QWaylandTabletPadV2
::
zwp_tablet_pad_v2_removed
()
633
{
634
delete
this
;
635
}
636
637
}
// namespace QtWaylandClient
638
639
QT_END_NAMESPACE
640
641
#
include
"moc_qwaylandtabletv2_p.cpp"
QtWaylandClient
Definition
qwaylandclientextension.h:16
QtWaylandClient::mouseButtonFromTablet
static Qt::MouseButton mouseButtonFromTablet(uint button)
Definition
qwaylandtabletv2.cpp:494
qtbase
src
plugins
platforms
wayland
qwaylandtabletv2.cpp
Generated on
for Qt by
1.16.1