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
12
13#include <QtGui/private/qguiapplication_p.h>
14#include <QtGui/private/qpointingdevice_p.h>
15#include <QtGui/qpa/qplatformtheme.h>
16#include <QtGui/qpa/qwindowsysteminterface_p.h>
17
18#include <wayland-cursor.h>
19
20QT_BEGIN_NAMESPACE
21
22namespace QtWaylandClient {
23
24using namespace Qt::StringLiterals;
25
26#if QT_CONFIG(cursor)
28{
29 if (m_tabletSeat->seat()->mQDisplay->compositor()->version() < 3) {
30 return 1;
31 }
32
33 if (auto *s = mCursor.surface.data()) {
34 if (s->outputScale() > 0)
35 return s->outputScale();
36 }
37
39}
40
42{
45
49 }
50
53 if (cursorSize.isEmpty())
54 cursorSize = QSize(24, 24);
55
56 int scale = idealCursorScale();
60
61 if (!mCursor.theme)
62 return; // A warning has already been printed in loadCursorTheme
63
64 if (auto *arrow = mCursor.theme->cursor(Qt::ArrowCursor)) {
66 arrow->images[0]->height); // Not all cursor themes are square
67 while (scale > 1 && arrowPixelSize / scale < cursorSize.width())
68 --scale;
69 } else {
70 qCWarning(lcQpaWayland) << "Cursor theme does not support the arrow cursor";
71 }
73}
74
76{
77 if (mEnterSerial == 0)
78 return;
79
81
82 if (shape == Qt::BlankCursor) {
83 if (mCursor.surface)
85 set_cursor(mEnterSerial, nullptr, 0, 0);
86 return;
87 }
88
89 if (shape == Qt::BitmapCursor) {
91 if (!buffer) {
92 qCWarning(lcQpaWayland) << "No buffer for bitmap cursor, can't set cursor";
93 return;
94 }
98 return;
99 }
100
101 if (mCursor.shape) {
102 if (mCursor.surface) {
104 }
106 return;
107 }
108
111
112 if (!mCursor.theme)
113 return;
114
115 // Set from shape using theme
117 const uint time = timer.isValid() ? timer.elapsed() : 0;
118
119 if (struct ::wl_cursor *waylandCursor = mCursor.theme->cursor(shape)) {
120 uint duration = 0;
123
125 if (!buffer) {
126 qCWarning(lcQpaWayland) << "Could not find buffer for cursor" << shape;
127 return;
128 }
132 bool animated = duration > 0;
133 if (animated) {
137 }
139 return;
140 }
141
142 qCWarning(lcQpaWayland) << "Unable to change to cursor" << shape;
143}
144
146{
147 if (!mCursor.surface)
150 return mCursor.surface.get();
151}
152
154{
157 updateCursor();
158}
159
161{
164 updateCursor();
165}
166
167#endif // QT_CONFIG(cursor)
168
174
179
186
195
204
206{
208 auto *tool = new QWaylandTabletToolV2(this, id);
209 if (m_tablets.size() == 1) {
212 d->name = m_tablets.first()->name() + u" stylus";
213 } else {
214 qCDebug(lcQpaInputDevices) << "seat" << this << "has tool" << tool << "for one of these tablets:" << m_tablets;
215 // TODO identify which tablet if there are several; then tool->setParent(tablet)
216 }
221 });
222}
223
225{
226 auto *pad = new QWaylandTabletPadV2(id);
227 if (m_tablets.size() == 1) {
230 d->name = m_tablets.first()->name() + u" touchpad";
231 } else {
232 qCDebug(lcQpaInputDevices) << "seat" << this << "has touchpad" << pad << "for one of these tablets:" << m_tablets;
233 // TODO identify which tablet if there are several
234 }
237}
238
249
254
260
262{
264 d->systemId = (quint64(vid) << 32) | pid;
265 qCDebug(lcQpaInputDevices) << "vid" << vid << "pid" << pid << "stored as systemId in" << this;
266}
267
273
278
280{
281 for (auto tool : m_tools)
283}
284
290
295
315
320
322{
324
325 switch (tool_type) {
326 case type_airbrush:
327 case type_brush:
328 case type_pencil:
329 case type_pen:
331 break;
332 case type_eraser:
334 break;
335 case type_mouse:
336 case type_lens:
338 break;
339 case type_finger:
341 break;
342 }
343
344 switch (tool_type) {
345 case type::type_airbrush:
348 break;
349 case type::type_brush:
350 case type::type_pencil:
351 case type::type_pen:
352 case type::type_eraser:
354 break;
355 case type::type_lens:
357 break;
358 case type::type_mouse:
359 case type::type_finger:
361 break;
362 }
363}
364
370
376
378{
380 switch (capability) {
381 case capability_tilt:
382 // no distinction... we have to assume it has both axes
385 break;
388 break;
391 break;
394 break;
396 // nothing to represent that so far
397 break;
398 case capability_wheel:
401 break;
402 }
403 qCDebug(lcQpaInputDevices) << capability << "->" << this;
404}
405
410
415
417{
419
422
423 if (Q_UNLIKELY(!surface)) {
424 qCDebug(lcQpaWayland) << "Ignoring zwp_tablet_tool_v2_proximity_v2 with no surface";
425 return;
426 }
429
430#if QT_CONFIG(cursor)
431 // Depends on mEnterSerial being updated
432 updateCursor();
433#endif
434}
435
441
455
460
465
471
476
482
487
492
494{
495 switch (button) {
496 case 0x110: return Qt::MouseButton::LeftButton; // BTN_LEFT
497 case 0x14b: return Qt::MouseButton::MiddleButton; // BTN_STYLUS
498 case 0x14c: return Qt::MouseButton::RightButton; // BTN_STYLUS2
499 default:
500 return Qt::NoButton;
501 }
502}
503
505{
507
512 else
514 // ideally we'd get button count when the tool is discovered; seems to be a shortcoming in tablet-unstable-v2
515 // but if we get events from buttons we didn't know existed, increase it
516 if (mouseButton == Qt::RightButton)
518 else if (mouseButton == Qt::MiddleButton)
520}
521
523{
526 // leaving proximity
528 m_pending = State(); // Don't leave pressure etc. lying around when we enter the next surface
529 m_applied = State();
530 } else {
531 qCWarning(lcQpaWayland) << "Can't send tablet event with no proximity surface, ignoring";
532 }
533 return;
534 }
535
538
540 // TODO get position etc. as below
543 }
544
545 if (!(m_pending == m_applied)) {
548
550
558 int z = int(m_pending.distance);
559
560 // do not use localPosition here since that is in Qt window coordinates
561 // but we need surface coordinates to include the decoration
566
572 }
573 }
574
576}
577
578// TODO: delete when upgrading to c++20
580 return
581 down == o.down &&
585 distance == o.distance &&
586 pressure == o.pressure &&
587 rotation == o.rotation &&
588 xTilt == o.xTilt &&
589 yTilt == o.yTilt &&
590 slider == o.slider &&
591 buttons == o.buttons;
592}
593
601
606
612
618
620{
621 // As of writing Qt does not handle tablet pads group and the controls on it
622 // This proxy is server created so it is just deleted here to not leak it
624}
625
630
632{
633 delete this;
634}
635
636} // namespace QtWaylandClient
637
638QT_END_NAMESPACE
639
640#include "moc_qwaylandtabletv2_p.cpp"
static Qt::MouseButton mouseButtonFromTablet(uint button)