KWin
Loading...
Searching...
No Matches
tablet_v2.cpp
Go to the documentation of this file.
1/*
2 SPDX-FileCopyrightText: 2019 Aleix Pol Gonzalez <aleixpol@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5*/
6
7#include "tablet_v2.h"
8#include "clientconnection.h"
9#include "display.h"
10#include "seat.h"
11#include "surface.h"
12#include "utils/resource.h"
13
14#include "qwayland-server-tablet-unstable-v2.h"
15
16#include <QHash>
17#include <QPointer>
18#include <ranges>
19
20namespace KWin
21{
22static int s_version = 1;
23
24class TabletV2InterfacePrivate : public QtWaylandServer::zwp_tablet_v2
25{
26public:
27 TabletV2InterfacePrivate(TabletV2Interface *q, uint32_t vendorId, uint32_t productId, const QString &name, const QStringList &paths)
28 : zwp_tablet_v2()
29 , q(q)
30 , m_vendorId(vendorId)
31 , m_productId(productId)
32 , m_name(name)
33 , m_paths(paths)
34 {
35 }
36
37 wl_resource *resourceForSurface(SurfaceInterface *surface) const
38 {
39 ClientConnection *client = surface->client();
40 Resource *r = resourceMap().value(*client);
41 return r ? r->handle : nullptr;
42 }
43
46 const uint32_t m_vendorId;
47 const uint32_t m_productId;
48 const QString m_name;
49 const QStringList m_paths;
50};
51
52TabletV2Interface::TabletV2Interface(uint32_t vendorId, uint32_t productId, const QString &name, const QStringList &paths, QObject *parent)
53 : QObject(parent)
54 , d(new TabletV2InterfacePrivate(this, vendorId, productId, name, paths))
55{
56}
57
59{
60 const auto tabletResources = d->resourceMap();
61 for (TabletV2InterfacePrivate::Resource *resource : tabletResources) {
62 d->send_removed(resource->handle);
63 }
64}
65
67{
68 return d->resourceForSurface(surface);
69}
70
72{
73 return d->m_pad;
74}
75
77{
78public:
83
84 void update(quint32 serial, SurfaceInterface *surface, const QPoint &hotspot)
85 {
86 const bool diff = m_serial != serial || m_surface != surface || m_hotspot != hotspot;
87 if (diff) {
88 m_serial = serial;
89 m_surface = surface;
90 m_hotspot = hotspot;
91
92 Q_EMIT q->changed();
93 }
94 }
95
97
98 quint32 m_serial = 0;
99 QPointer<SurfaceInterface> m_surface;
100 QPoint m_hotspot;
101};
102
103TabletSurfaceCursorV2::TabletSurfaceCursorV2()
104 : QObject()
105 , d(new TabletSurfaceCursorV2Private(this))
106{
107}
108
110
112{
113 return d->m_hotspot;
114}
115
117{
118 return d->m_serial;
119}
120
122{
123 return d->m_surface;
124}
125
126class TabletToolV2InterfacePrivate : public QtWaylandServer::zwp_tablet_tool_v2
127{
128public:
130 Display *display,
132 uint32_t hsh,
133 uint32_t hsl,
134 uint32_t hih,
135 uint32_t hil,
136 const QList<TabletToolV2Interface::Capability> &capabilities)
137 : zwp_tablet_tool_v2()
138 , m_display(display)
139 , m_type(type)
142 , m_hardwareIdHigh(hih)
143 , m_hardwareIdLow(hil)
144 , m_capabilities(capabilities)
145 , q(q)
146 {
147 }
148
149 std::ranges::subrange<QMultiMap<struct ::wl_client *, Resource *>::const_iterator> targetResources() const
150 {
151 if (!m_surface)
152 return {};
153
154 ClientConnection *client = m_surface->client();
155 const auto [start, end] = resourceMap().equal_range(*client);
156 return std::ranges::subrange(start, end);
157 }
158
159 quint64 hardwareId() const
160 {
161 return quint64(quint64(m_hardwareIdHigh) << 32) + m_hardwareIdLow;
162 }
163 quint64 hardwareSerial() const
164 {
165 return quint64(quint64(m_hardwareSerialHigh) << 32) + m_hardwareSerialLow;
166 }
167
168 void zwp_tablet_tool_v2_bind_resource(QtWaylandServer::zwp_tablet_tool_v2::Resource *resource) override
169 {
170 TabletSurfaceCursorV2 *&c = m_cursors[resource->client()];
171 if (!c)
172 c = new TabletSurfaceCursorV2;
173 }
174
175 void zwp_tablet_tool_v2_set_cursor(Resource *resource, uint32_t serial, struct ::wl_resource *_surface, int32_t hotspot_x, int32_t hotspot_y) override
176 {
177 SurfaceInterface *surface = SurfaceInterface::get(_surface);
178 if (surface) {
179 static SurfaceRole cursorRole(QByteArrayLiteral("tablet_cursor_v2"));
180 if (const SurfaceRole *role = surface->role()) {
181 if (role != &cursorRole) {
182 wl_resource_post_error(resource->handle, 0,
183 "the wl_surface already has a role assigned %s", role->name().constData());
184 return;
185 }
186 } else {
187 surface->setRole(&cursorRole);
188 }
189 }
190
191 TabletSurfaceCursorV2 *c = m_cursors[resource->client()];
192 c->d->update(serial, surface, {hotspot_x, hotspot_y});
193 const auto resources = targetResources();
194 if (std::any_of(resources.begin(), resources.end(), [resource](const Resource *res) {
195 return res->handle == resource->handle;
196 })) {
197 Q_EMIT q->cursorChanged(c);
198 }
199 }
200
201 void zwp_tablet_tool_v2_destroy_resource(Resource *resource) override
202 {
203 if (!resourceMap().contains(resource->client())) {
204 delete m_cursors.take(resource->client());
205 }
206 if (m_removed && resourceMap().isEmpty()) {
207 delete q;
208 }
209 }
210
211 void zwp_tablet_tool_v2_destroy(Resource *resource) override
212 {
213 wl_resource_destroy(resource->handle);
214 }
215
217 quint32 m_proximitySerial = 0;
218 std::optional<quint32> m_downSerial;
219 bool m_cleanup = false;
220 bool m_removed = false;
221 QPointer<SurfaceInterface> m_surface;
222 QPointer<TabletV2Interface> m_lastTablet;
223 const uint32_t m_type;
226 const QList<TabletToolV2Interface::Capability> m_capabilities;
227 QHash<wl_client *, TabletSurfaceCursorV2 *> m_cursors;
229};
230
231TabletToolV2Interface::TabletToolV2Interface(Display *display,
232 Type type,
233 uint32_t hsh,
234 uint32_t hsl,
235 uint32_t hih,
236 uint32_t hil,
237 const QList<Capability> &capabilities)
238 : d(new TabletToolV2InterfacePrivate(this, display, type, hsh, hsl, hih, hil, capabilities))
239{
240}
241
243{
244 const auto toolResources = d->resourceMap();
245 for (TabletToolV2InterfacePrivate::Resource *resource : toolResources) {
246 d->send_removed(resource->handle);
247 }
248}
249
251{
252 if (TabletToolV2InterfacePrivate *tabletToolPrivate = resource_cast<TabletToolV2InterfacePrivate *>(resource)) {
253 return tabletToolPrivate->q;
254 }
255 return nullptr;
256}
257
259{
260 return d->m_capabilities.contains(capability);
261}
262
264{
265 return d->m_surface;
266}
267
269{
270 if (d->m_surface == surface)
271 return;
272
273 TabletV2Interface *const lastTablet = d->m_lastTablet;
274 if (d->m_surface && d->resourceMap().contains(*d->m_surface->client())) {
276 sendFrame(0);
277 }
278
279 d->m_surface = surface;
280
281 if (lastTablet && lastTablet->d->resourceForSurface(surface)) {
282 sendProximityIn(lastTablet);
283 } else {
284 d->m_lastTablet = lastTablet;
285 }
286
287 if (surface != nullptr) {
288 if (auto *const cursor = d->m_cursors.value(*surface->client())) {
289 Q_EMIT cursorChanged(cursor);
290 }
291 }
292}
293
295{
296 return d->m_proximitySerial;
297}
298
299std::optional<quint32> TabletToolV2Interface::downSerial() const
300{
301 return d->m_downSerial;
302}
303
305{
306 return d->m_surface && !d->targetResources().empty();
307}
308
309void TabletToolV2Interface::sendButton(uint32_t button, bool pressed)
310{
311 const auto serial = d->m_display->nextSerial();
312 for (auto *resource : d->targetResources()) {
313 d->send_button(resource->handle,
314 serial,
315 button,
316 pressed ? QtWaylandServer::zwp_tablet_tool_v2::button_state_pressed : QtWaylandServer::zwp_tablet_tool_v2::button_state_released);
317 }
318}
319
320void TabletToolV2Interface::sendMotion(const QPointF &pos)
321{
322 const QPointF surfacePos = d->m_surface->toSurfaceLocal(pos);
323 for (auto *resource : d->targetResources()) {
324 d->send_motion(resource->handle, wl_fixed_from_double(surfacePos.x()), wl_fixed_from_double(surfacePos.y()));
325 }
326}
327
329{
330 for (auto *resource : d->targetResources()) {
331 d->send_distance(resource->handle, distance);
332 }
333}
334
336{
337 for (auto *resource : d->targetResources()) {
338 d->send_frame(resource->handle, time);
339 }
340
341 if (d->m_cleanup) {
342 d->m_surface = nullptr;
343 d->m_lastTablet = nullptr;
344 d->m_cleanup = false;
345 }
346}
347
349{
350 for (auto *resource : d->targetResources()) {
351 d->send_pressure(resource->handle, pressure);
352 }
353}
354
356{
357 for (auto *resource : d->targetResources()) {
358 d->send_rotation(resource->handle, wl_fixed_from_double(rotation));
359 }
360}
361
363{
364 for (auto *resource : d->targetResources()) {
365 d->send_slider(resource->handle, position);
366 }
367}
368
369void TabletToolV2Interface::sendTilt(qreal degreesX, qreal degreesY)
370{
371 for (auto *resource : d->targetResources()) {
372 d->send_tilt(resource->handle, wl_fixed_from_double(degreesX), wl_fixed_from_double(degreesY));
373 }
374}
375
376void TabletToolV2Interface::sendWheel(int32_t degrees, int32_t clicks)
377{
378 for (auto *resource : d->targetResources()) {
379 d->send_wheel(resource->handle, degrees, clicks);
380 }
381}
382
384{
385 wl_resource *tabletResource = tablet->d->resourceForSurface(d->m_surface);
386 const auto serial = d->m_display->nextSerial();
387 for (auto *resource : d->targetResources()) {
388 d->send_proximity_in(resource->handle, serial, tabletResource, d->m_surface->resource());
389 }
390 d->m_proximitySerial = serial;
391 d->m_lastTablet = tablet;
392}
393
395{
396 for (auto *resource : d->targetResources()) {
397 d->send_proximity_out(resource->handle);
398 }
399 d->m_cleanup = true;
400}
401
403{
404 const auto serial = d->m_display->nextSerial();
405 for (auto *resource : d->targetResources()) {
406 d->send_down(resource->handle, serial);
407 }
408 d->m_downSerial = serial;
409}
410
412{
413 for (auto *resource : d->targetResources()) {
414 d->send_up(resource->handle);
415 }
416 d->m_downSerial.reset();
417}
418
419class TabletPadRingV2InterfacePrivate : public QtWaylandServer::zwp_tablet_pad_ring_v2
420{
421public:
423 : zwp_tablet_pad_ring_v2()
424 , q(q)
425 {
426 }
427
428 std::ranges::subrange<QMultiMap<struct ::wl_client *, Resource *>::const_iterator> resourcesForSurface(SurfaceInterface *surface) const
429 {
430 ClientConnection *client = surface->client();
431 const auto [start, end] = resourceMap().equal_range(*client);
432 return std::ranges::subrange(start, end);
433 }
434
435 void zwp_tablet_pad_ring_v2_destroy(Resource *resource) override
436 {
437 wl_resource_destroy(resource->handle);
438 }
441};
442
443TabletPadRingV2Interface::TabletPadRingV2Interface(TabletPadV2Interface *parent)
444 : QObject(parent)
446{
447 d->m_pad = parent;
448}
449
451
453{
454 for (auto *resource : d->resourcesForSurface(d->m_pad->currentSurface())) {
455 d->send_angle(resource->handle, wl_fixed_from_double(angle));
456 }
457}
458
460{
461 for (auto *resource : d->resourcesForSurface(d->m_pad->currentSurface())) {
462 d->send_frame(resource->handle, time);
463 }
464}
465
467{
468 for (auto *resource : d->resourcesForSurface(d->m_pad->currentSurface())) {
469 d->send_source(resource->handle, source);
470 }
471}
472
474{
475 for (auto *resource : d->resourcesForSurface(d->m_pad->currentSurface())) {
476 d->send_stop(resource->handle);
477 }
478}
479
480class TabletPadStripV2InterfacePrivate : public QtWaylandServer::zwp_tablet_pad_strip_v2
481{
482public:
484 : zwp_tablet_pad_strip_v2()
485 , q(q)
486 {
487 }
488
489 std::ranges::subrange<QMultiMap<struct ::wl_client *, Resource *>::const_iterator> resourcesForSurface(SurfaceInterface *surface) const
490 {
491 ClientConnection *client = surface->client();
492 const auto [start, end] = resourceMap().equal_range(*client);
493 return std::ranges::subrange(start, end);
494 }
495
496 void zwp_tablet_pad_strip_v2_destroy(Resource *resource) override
497 {
498 wl_resource_destroy(resource->handle);
499 }
502};
503
504TabletPadStripV2Interface::TabletPadStripV2Interface(TabletPadV2Interface *parent)
505 : QObject(parent)
507{
508 d->m_pad = parent;
509}
510
512
514{
515 for (auto *resource : d->resourcesForSurface(d->m_pad->currentSurface())) {
516 d->send_frame(resource->handle, time);
517 }
518}
519
521{
522 for (auto *resource : d->resourcesForSurface(d->m_pad->currentSurface())) {
523 d->send_position(resource->handle, position);
524 }
525}
526
528{
529 for (auto *resource : d->resourcesForSurface(d->m_pad->currentSurface())) {
530 d->send_source(resource->handle, source);
531 }
532}
533
535{
536 for (auto *resource : d->resourcesForSurface(d->m_pad->currentSurface())) {
537 d->send_stop(resource->handle);
538 }
539}
540
541class TabletPadGroupV2InterfacePrivate : public QtWaylandServer::zwp_tablet_pad_group_v2
542{
543public:
545 : zwp_tablet_pad_group_v2()
546 , q(q)
547 , m_currentMode(currentMode)
548 {
549 }
550
551 std::ranges::subrange<QMultiMap<struct ::wl_client *, Resource *>::const_iterator> resourcesForSurface(SurfaceInterface *surface) const
552 {
553 ClientConnection *client = surface->client();
554 const auto [start, end] = resourceMap().equal_range(*client);
555 return std::ranges::subrange(start, end);
556 }
557
558 void zwp_tablet_pad_group_v2_destroy(Resource *resource) override
559 {
560 wl_resource_destroy(resource->handle);
561 }
562
566};
567
568TabletPadGroupV2Interface::TabletPadGroupV2Interface(quint32 currentMode, TabletPadV2Interface *parent)
569 : QObject(parent)
570 , d(new TabletPadGroupV2InterfacePrivate(currentMode, this))
571{
572 d->m_pad = parent;
573}
574
576
577void TabletPadGroupV2Interface::sendModeSwitch(quint32 time, quint32 serial, quint32 mode)
578{
579 d->m_currentMode = mode;
580 for (auto *resource : d->resourcesForSurface(d->m_pad->currentSurface())) {
581 d->send_mode_switch(resource->handle, time, serial, mode);
582 }
583}
584
585class TabletPadV2InterfacePrivate : public QtWaylandServer::zwp_tablet_pad_v2
586{
587public:
588 TabletPadV2InterfacePrivate(const QString &path,
589 quint32 buttons,
590 quint32 rings,
591 quint32 strips,
592 quint32 modes,
593 quint32 currentMode,
594 Display *display,
596 : zwp_tablet_pad_v2()
597 , q(q)
598 , m_path(path)
599 , m_buttons(buttons)
600 , m_modes(modes)
601 , m_padGroup(new TabletPadGroupV2Interface(currentMode, q))
602 , m_display(display)
603 {
604 for (uint i = 0; i < buttons; ++i) {
605 m_buttons[i] = i;
606 }
607
608 m_rings.reserve(rings);
609 for (quint32 i = 0; i < rings; ++i) {
611 }
612
613 m_strips.reserve(strips);
614 for (quint32 i = 0; i < strips; ++i) {
616 }
617 }
618
620 {
621 qDeleteAll(m_rings);
622 qDeleteAll(m_strips);
623 }
624
625 void zwp_tablet_pad_v2_destroy(Resource *resource) override
626 {
627 wl_resource_destroy(resource->handle);
628 }
629
630 void zwp_tablet_pad_v2_set_feedback(Resource *resource, quint32 button, const QString &description, quint32 serial) override
631 {
632 Q_EMIT q->feedback(m_display->getConnection(resource->client()), button, description, serial);
633 }
634
635 std::ranges::subrange<QMultiMap<struct ::wl_client *, Resource *>::const_iterator> resourcesForSurface(SurfaceInterface *surface) const
636 {
637 ClientConnection *client = surface->client();
638 const auto [start, end] = resourceMap().equal_range(*client);
639 return std::ranges::subrange(start, end);
640 }
641
643
644 const QString m_path;
645 QList<quint32> m_buttons;
646 const int m_modes;
647
648 QList<TabletPadRingV2Interface *> m_rings;
649 QList<TabletPadStripV2Interface *> m_strips;
652 QPointer<SurfaceInterface> m_currentSurface;
654};
655
656TabletPadV2Interface::TabletPadV2Interface(const QString &path,
657 quint32 buttons,
658 quint32 rings,
659 quint32 strips,
660 quint32 modes,
661 quint32 currentMode,
662 Display *display,
663 TabletSeatV2Interface *parent)
664 : QObject(parent)
665 , d(new TabletPadV2InterfacePrivate(path, buttons, rings, strips, modes, currentMode, display, this))
666{
667 d->m_seat = parent;
668}
669
671{
672 const auto tabletPadResources = d->resourceMap();
673 for (TabletPadV2InterfacePrivate::Resource *resource : tabletPadResources) {
674 d->send_removed(resource->handle);
675 }
676}
677
678void TabletPadV2Interface::sendButton(std::chrono::microseconds time, quint32 button, bool pressed)
679{
680 const auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(time).count();
681 for (auto *resource : d->resourcesForSurface(currentSurface())) {
682 d->send_button(resource->handle, milliseconds, button, pressed);
683 }
684}
685
687{
688 return d->m_rings[at];
689}
690
692{
693 return d->m_strips[at];
694}
695
697{
698 if (surface == d->m_currentSurface) {
699 return;
700 }
701
702 if (d->m_currentSurface) {
703 auto serial = d->m_display->nextSerial();
704 for (auto *resource : d->resourcesForSurface(d->m_currentSurface)) {
705 d->send_leave(resource->handle, serial, d->m_currentSurface->resource());
706 }
707 }
708
709 d->m_currentSurface = surface;
710 if (surface) {
711 wl_resource *tabletResource = tablet->d->resourceForSurface(surface);
712
713 auto serial = d->m_display->nextSerial();
714 for (auto *resource : d->resourcesForSurface(surface)) {
715 d->send_enter(resource->handle, serial, tabletResource, surface->resource());
716 }
717 d->m_padGroup->sendModeSwitch(0, d->m_display->nextSerial(), d->m_padGroup->d->m_currentMode);
718 }
719}
720
722{
723 return d->m_currentSurface;
724}
725
726class TabletSeatV2InterfacePrivate : public QtWaylandServer::zwp_tablet_seat_v2
727{
728public:
730 : zwp_tablet_seat_v2()
731 , q(q)
732 , m_display(display)
733 {
734 }
735
736 void zwp_tablet_seat_v2_bind_resource(Resource *resource) override
737 {
738 for (auto tablet : std::as_const(m_tablets)) {
739 sendTabletAdded(resource, tablet);
740 }
741
742 for (auto pad : std::as_const(m_pads)) {
743 sendPadAdded(resource, pad);
744 }
745
746 for (const auto &tools : std::as_const(m_tools)) {
747 for (auto *tool : tools) {
748 sendToolAdded(resource, tool);
749 }
750 }
751 }
752
753 void zwp_tablet_seat_v2_destroy(Resource *resource) override
754 {
755 wl_resource_destroy(resource->handle);
756 }
757
758 void sendToolAdded(Resource *resource, TabletToolV2Interface *tool)
759 {
760 wl_resource *toolResource = tool->d->add(resource->client(), resource->version())->handle;
761 send_tool_added(resource->handle, toolResource);
762
763 tool->d->send_type(toolResource, tool->d->m_type);
764 tool->d->send_hardware_serial(toolResource, tool->d->m_hardwareSerialHigh, tool->d->m_hardwareSerialLow);
765 tool->d->send_hardware_id_wacom(toolResource, tool->d->m_hardwareIdHigh, tool->d->m_hardwareIdLow);
766 for (uint32_t cap : std::as_const(tool->d->m_capabilities)) {
767 tool->d->send_capability(toolResource, cap);
768 }
769 tool->d->send_done(toolResource);
770 }
771 void sendTabletAdded(Resource *resource, TabletV2Interface *tablet)
772 {
773 wl_resource *tabletResource = tablet->d->add(resource->client(), resource->version())->handle;
774 send_tablet_added(resource->handle, tabletResource);
775
776 tablet->d->send_name(tabletResource, tablet->d->m_name);
777 if (tablet->d->m_vendorId && tablet->d->m_productId) {
778 tablet->d->send_id(tabletResource, tablet->d->m_vendorId, tablet->d->m_productId);
779 }
780 for (const QString &path : std::as_const(tablet->d->m_paths)) {
781 tablet->d->send_path(tabletResource, path);
782 }
783 tablet->d->send_done(tabletResource);
784 }
785
786 void sendPadAdded(Resource *resource, TabletPadV2Interface *pad)
787 {
788 wl_resource *tabletResource = pad->d->add(resource->client(), resource->version())->handle;
789 send_pad_added(resource->handle, tabletResource);
790
791 pad->d->send_buttons(tabletResource, pad->d->m_buttons.size());
792 pad->d->send_path(tabletResource, pad->d->m_path);
793
794 auto groupResource = pad->d->m_padGroup->d->add(resource->client(), resource->version());
795 pad->d->send_group(tabletResource, groupResource->handle);
796 pad->d->m_padGroup->d->send_modes(groupResource->handle, pad->d->m_modes);
797
798 pad->d->m_padGroup->d->send_buttons(
799 groupResource->handle,
800 QByteArray::fromRawData(reinterpret_cast<const char *>(pad->d->m_buttons.data()), pad->d->m_buttons.size() * sizeof(quint32)));
801
802 for (auto ring : std::as_const(pad->d->m_rings)) {
803 auto ringResource = ring->d->add(resource->client(), resource->version());
804 pad->d->m_padGroup->d->send_ring(groupResource->handle, ringResource->handle);
805 }
806
807 for (auto strip : std::as_const(pad->d->m_strips)) {
808 auto stripResource = strip->d->add(resource->client(), resource->version());
809 pad->d->m_padGroup->d->send_strip(groupResource->handle, stripResource->handle);
810 }
811 pad->d->m_padGroup->d->send_done(groupResource->handle);
812 pad->d->send_done(tabletResource);
813 }
814
816 QHash<QString, QList<TabletToolV2Interface *>> m_tools;
817 QHash<QString, TabletV2Interface *> m_tablets;
818 QHash<QString, TabletPadV2Interface *> m_pads;
820};
821
822TabletSeatV2Interface::TabletSeatV2Interface(Display *display, QObject *parent)
823 : QObject(parent)
824 , d(new TabletSeatV2InterfacePrivate(display, this))
825{
826}
827
829
831 quint64 hardwareSerial,
832 quint64 hardwareId,
833 const QList<TabletToolV2Interface::Capability> &capabilities,
834 const QString &deviceSysName)
835{
836 constexpr auto MAX_UINT_32 = std::numeric_limits<quint32>::max();
837 auto tool = new TabletToolV2Interface(d->m_display,
838 type,
839 hardwareSerial >> 32,
840 hardwareSerial & MAX_UINT_32,
841 hardwareId >> 32,
842 hardwareId & MAX_UINT_32,
843 capabilities);
844 for (QtWaylandServer::zwp_tablet_seat_v2::Resource *resource : d->resourceMap()) {
845 d->sendToolAdded(resource, tool);
846 }
847
848 d->m_tools[deviceSysName].append(tool);
849 return tool;
850}
851
853TabletSeatV2Interface::addTablet(uint32_t vendorId, uint32_t productId, const QString &sysname, const QString &name, const QStringList &paths)
854{
855 Q_ASSERT(!d->m_tablets.contains(sysname));
856
857 auto iface = new TabletV2Interface(vendorId, productId, name, paths, this);
858
859 for (QtWaylandServer::zwp_tablet_seat_v2::Resource *r : d->resourceMap()) {
860 d->sendTabletAdded(r, iface);
861 }
862
863 d->m_tablets[sysname] = iface;
864 return iface;
865}
866
868 const QString &name,
869 const QStringList &paths,
870 quint32 buttons,
871 quint32 rings,
872 quint32 strips,
873 quint32 modes,
874 quint32 currentMode,
875 TabletV2Interface *tablet)
876{
877 auto iface = new TabletPadV2Interface(paths.at(0), buttons, rings, strips, modes, currentMode, d->m_display, this);
878 iface->d->m_seat = this;
879 for (auto r : d->resourceMap()) {
880 d->sendPadAdded(r, iface);
881 }
882
883 tablet->d->m_pad = iface;
884
885 d->m_pads[sysname] = iface;
886 return iface;
887}
888
889void TabletSeatV2Interface::removeDevice(const QString &sysname)
890{
891 delete d->m_tablets.take(sysname);
892 delete d->m_pads.take(sysname);
893
894 qDeleteAll(d->m_tools.take(sysname));
895}
896
898{
899 for (const auto &tools : std::as_const(d->m_tools)) {
900 for (TabletToolV2Interface *tool : tools) {
901 if (tool->d->hardwareId() == hardwareId) {
902 return tool;
903 }
904 }
905 }
906 return nullptr;
907}
908
910{
911 for (const auto &tools : std::as_const(d->m_tools)) {
912 for (TabletToolV2Interface *tool : tools) {
913 if (tool->d->hardwareSerial() == hardwareSerial && tool->d->m_type == type) {
914 return tool;
915 }
916 }
917 }
918 return nullptr;
919}
920
922{
923 Q_ASSERT(d->m_pads.contains(name));
924 return d->m_pads.value(name);
925}
926
927class TabletManagerV2InterfacePrivate : public QtWaylandServer::zwp_tablet_manager_v2
928{
929public:
931 : zwp_tablet_manager_v2(*display, s_version)
932 , q(q)
933 , m_display(display)
934 {
935 }
936
937 void zwp_tablet_manager_v2_get_tablet_seat(Resource *resource, uint32_t tablet_seat, struct ::wl_resource *seat_resource) override
938 {
939 SeatInterface *seat = SeatInterface::get(seat_resource);
940 TabletSeatV2Interface *tsi = get(seat);
941 tsi->d->add(resource->client(), tablet_seat, s_version);
942 }
943
945 {
946 TabletSeatV2Interface *&tabletSeat = m_seats[seat];
947 if (!tabletSeat) {
948 tabletSeat = new TabletSeatV2Interface(m_display, q);
949 }
950 return tabletSeat;
951 }
952
955 QHash<SeatInterface *, TabletSeatV2Interface *> m_seats;
956};
957
959 : QObject(parent)
960 , d(new TabletManagerV2InterfacePrivate(display, this))
961{
962}
963
965{
966 return d->get(seat);
967}
968
970{
971 return d->resourceMap().value(*client);
972}
973
975{
976 return std::any_of(d->m_tools.cbegin(), d->m_tools.cend(), [serial](const auto &tools) {
977 return std::any_of(tools.cbegin(), tools.cend(), [serial](const auto tool) {
978 return tool->downSerial() == serial;
979 });
980 });
981}
982
983TabletManagerV2Interface::~TabletManagerV2Interface() = default;
984
985} // namespace KWin
986
987#include "moc_tablet_v2.cpp"
Convenient Class which represents a wl_client.
wl_client * client() const
Class holding the Wayland server display loop.
Definition display.h:34
ClientConnection * getConnection(wl_client *client)
Definition display.cpp:200
Represents a Seat on the Wayland Display.
Definition seat.h:134
static SeatInterface * get(wl_resource *native)
Definition seat.cpp:429
Resource representing a wl_surface.
Definition surface.h:80
ClientConnection * client() const
Definition surface.cpp:444
static SurfaceInterface * get(wl_resource *native)
Definition surface.cpp:819
SurfaceRole * role() const
Definition surface.cpp:429
wl_resource * resource() const
Definition surface.cpp:449
void setRole(SurfaceRole *role)
Definition surface.cpp:434
TabletManagerV2Interface(Display *d, QObject *parent)
TabletSeatV2Interface * seat(SeatInterface *seat) const
TabletSeatV2Interface * get(SeatInterface *seat)
TabletManagerV2Interface *const q
TabletManagerV2InterfacePrivate(Display *display, TabletManagerV2Interface *q)
QHash< SeatInterface *, TabletSeatV2Interface * > m_seats
void zwp_tablet_manager_v2_get_tablet_seat(Resource *resource, uint32_t tablet_seat, struct ::wl_resource *seat_resource) override
void sendModeSwitch(quint32 time, quint32 serial, quint32 mode)
std::ranges::subrange< QMultiMap< struct ::wl_client *, Resource * >::const_iterator > resourcesForSurface(SurfaceInterface *surface) const
TabletPadGroupV2Interface *const q
TabletPadGroupV2InterfacePrivate(quint32 currentMode, TabletPadGroupV2Interface *q)
void zwp_tablet_pad_group_v2_destroy(Resource *resource) override
void sendFrame(quint32 time)
void sendSource(Source source)
void zwp_tablet_pad_ring_v2_destroy(Resource *resource) override
std::ranges::subrange< QMultiMap< struct ::wl_client *, Resource * >::const_iterator > resourcesForSurface(SurfaceInterface *surface) const
TabletPadRingV2Interface *const q
TabletPadRingV2InterfacePrivate(TabletPadRingV2Interface *q)
void sendPosition(quint32 position)
void sendSource(Source source)
void zwp_tablet_pad_strip_v2_destroy(Resource *resource) override
TabletPadStripV2InterfacePrivate(TabletPadStripV2Interface *q)
TabletPadStripV2Interface *const q
std::ranges::subrange< QMultiMap< struct ::wl_client *, Resource * >::const_iterator > resourcesForSurface(SurfaceInterface *surface) const
SurfaceInterface * currentSurface() const
TabletPadRingV2Interface * ring(uint at) const
void sendButton(std::chrono::microseconds time, quint32 button, bool pressed)
TabletPadStripV2Interface * strip(uint at) const
void feedback(KWin::ClientConnection *client, quint32 button, const QString &description, quint32 serial)
void setCurrentSurface(SurfaceInterface *surface, TabletV2Interface *tablet)
QList< TabletPadRingV2Interface * > m_rings
TabletPadV2InterfacePrivate(const QString &path, quint32 buttons, quint32 rings, quint32 strips, quint32 modes, quint32 currentMode, Display *display, TabletPadV2Interface *q)
TabletSeatV2Interface * m_seat
std::ranges::subrange< QMultiMap< struct ::wl_client *, Resource * >::const_iterator > resourcesForSurface(SurfaceInterface *surface) const
TabletPadV2Interface *const q
QList< TabletPadStripV2Interface * > m_strips
QPointer< SurfaceInterface > m_currentSurface
TabletPadGroupV2Interface *const m_padGroup
void zwp_tablet_pad_v2_set_feedback(Resource *resource, quint32 button, const QString &description, quint32 serial) override
void zwp_tablet_pad_v2_destroy(Resource *resource) override
bool isClientSupported(ClientConnection *client) const
TabletPadV2Interface * addTabletPad(const QString &sysname, const QString &name, const QStringList &paths, quint32 buttons, quint32 rings, quint32 strips, quint32 modes, quint32 currentMode, TabletV2Interface *tablet)
TabletPadV2Interface * padByName(const QString &sysname) const
TabletToolV2Interface * toolByHardwareSerial(quint64 hardwareSerial, TabletToolV2Interface::Type type) const
TabletToolV2Interface * addTool(TabletToolV2Interface::Type type, quint64 hardwareSerial, quint64 hardwareId, const QList< TabletToolV2Interface::Capability > &capabilities, const QString &deviceSysName)
void removeDevice(const QString &sysname)
TabletV2Interface * addTablet(quint32 vendorId, quint32 productId, const QString &sysname, const QString &name, const QStringList &paths)
TabletToolV2Interface * toolByHardwareId(quint64 hardwareId) const
bool hasImplicitGrab(quint32 serial) const
TabletSeatV2InterfacePrivate(Display *display, TabletSeatV2Interface *q)
void sendToolAdded(Resource *resource, TabletToolV2Interface *tool)
void sendPadAdded(Resource *resource, TabletPadV2Interface *pad)
void sendTabletAdded(Resource *resource, TabletV2Interface *tablet)
void zwp_tablet_seat_v2_destroy(Resource *resource) override
QHash< QString, TabletPadV2Interface * > m_pads
QHash< QString, QList< TabletToolV2Interface * > > m_tools
void zwp_tablet_seat_v2_bind_resource(Resource *resource) override
QHash< QString, TabletV2Interface * > m_tablets
TabletSeatV2Interface *const q
quint32 enteredSerial() const
SurfaceInterface * surface() const
TabletSurfaceCursorV2 *const q
Definition tablet_v2.cpp:96
void update(quint32 serial, SurfaceInterface *surface, const QPoint &hotspot)
Definition tablet_v2.cpp:84
TabletSurfaceCursorV2Private(TabletSurfaceCursorV2 *q)
Definition tablet_v2.cpp:79
QPointer< SurfaceInterface > m_surface
Definition tablet_v2.cpp:99
void sendSlider(qint32 position)
void sendMotion(const QPointF &pos)
void sendProximityIn(TabletV2Interface *tablet)
std::optional< quint32 > downSerial() const
void sendWheel(qint32 degrees, qint32 clicks)
void cursorChanged(const TabletCursorSourceV2 &cursor)
void sendRotation(qreal degrees)
void sendPressure(quint32 pressure)
bool hasCapability(Capability capability) const
static TabletToolV2Interface * get(wl_resource *resource)
void sendTilt(qreal degreesX, qreal degreesY)
void sendFrame(quint32 time)
void setCurrentSurface(SurfaceInterface *surface)
void sendButton(quint32 button, bool pressed)
quint32 proximitySerial() const
void sendDistance(quint32 distance)
SurfaceInterface * currentSurface() const
const QList< TabletToolV2Interface::Capability > m_capabilities
void zwp_tablet_tool_v2_set_cursor(Resource *resource, uint32_t serial, struct ::wl_resource *_surface, int32_t hotspot_x, int32_t hotspot_y) override
std::ranges::subrange< QMultiMap< struct ::wl_client *, Resource * >::const_iterator > targetResources() const
QPointer< TabletV2Interface > m_lastTablet
void zwp_tablet_tool_v2_destroy_resource(Resource *resource) override
QPointer< SurfaceInterface > m_surface
void zwp_tablet_tool_v2_destroy(Resource *resource) override
TabletToolV2Interface *const q
TabletToolV2InterfacePrivate(TabletToolV2Interface *q, Display *display, TabletToolV2Interface::Type type, uint32_t hsh, uint32_t hsl, uint32_t hih, uint32_t hil, const QList< TabletToolV2Interface::Capability > &capabilities)
void zwp_tablet_tool_v2_bind_resource(QtWaylandServer::zwp_tablet_tool_v2::Resource *resource) override
QHash< wl_client *, TabletSurfaceCursorV2 * > m_cursors
std::optional< quint32 > m_downSerial
TabletPadV2Interface * pad() const
Definition tablet_v2.cpp:71
bool isSurfaceSupported(SurfaceInterface *surface) const
Definition tablet_v2.cpp:66
TabletPadV2Interface * m_pad
Definition tablet_v2.cpp:45
TabletV2InterfacePrivate(TabletV2Interface *q, uint32_t vendorId, uint32_t productId, const QString &name, const QStringList &paths)
Definition tablet_v2.cpp:27
TabletV2Interface *const q
Definition tablet_v2.cpp:44
wl_resource * resourceForSurface(SurfaceInterface *surface) const
Definition tablet_v2.cpp:37
Session::Type type
Definition session.cpp:17