File indexing completed on 2024-05-19 16:35:29
0001 /* 0002 SPDX-FileCopyrightText: 2019 Aleix Pol Gonzalez <aleixpol@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 0007 #include "tablet_v2_interface.h" 0008 #include "display.h" 0009 #include "seat_interface.h" 0010 #include "surface_interface.h" 0011 0012 #include "qwayland-server-tablet-unstable-v2.h" 0013 #include <QHash> 0014 0015 namespace KWaylandServer 0016 { 0017 static int s_version = 1; 0018 0019 class TabletV2InterfacePrivate : public QtWaylandServer::zwp_tablet_v2 0020 { 0021 public: 0022 TabletV2InterfacePrivate(TabletV2Interface *q, uint32_t vendorId, uint32_t productId, const QString &name, const QStringList &paths) 0023 : zwp_tablet_v2() 0024 , q(q) 0025 , m_vendorId(vendorId) 0026 , m_productId(productId) 0027 , m_name(name) 0028 , m_paths(paths) 0029 { 0030 } 0031 0032 wl_resource *resourceForSurface(SurfaceInterface *surface) const 0033 { 0034 ClientConnection *client = surface->client(); 0035 Resource *r = resourceMap().value(*client); 0036 return r ? r->handle : nullptr; 0037 } 0038 0039 TabletV2Interface *const q; 0040 TabletPadV2Interface *m_pad = nullptr; 0041 const uint32_t m_vendorId; 0042 const uint32_t m_productId; 0043 const QString m_name; 0044 const QStringList m_paths; 0045 }; 0046 0047 TabletV2Interface::TabletV2Interface(uint32_t vendorId, uint32_t productId, const QString &name, const QStringList &paths, QObject *parent) 0048 : QObject(parent) 0049 , d(new TabletV2InterfacePrivate(this, vendorId, productId, name, paths)) 0050 { 0051 } 0052 0053 TabletV2Interface::~TabletV2Interface() 0054 { 0055 const auto tabletResources = d->resourceMap(); 0056 for (TabletV2InterfacePrivate::Resource *resource : tabletResources) { 0057 d->send_removed(resource->handle); 0058 } 0059 } 0060 0061 bool TabletV2Interface::isSurfaceSupported(SurfaceInterface *surface) const 0062 { 0063 return d->resourceForSurface(surface); 0064 } 0065 0066 TabletPadV2Interface *TabletV2Interface::pad() const 0067 { 0068 return d->m_pad; 0069 } 0070 0071 class TabletCursorV2Private 0072 { 0073 public: 0074 TabletCursorV2Private(TabletCursorV2 *q) 0075 : q(q) 0076 { 0077 } 0078 0079 void update(quint32 serial, SurfaceInterface *surface, const QPoint &hotspot) 0080 { 0081 const bool diff = m_serial != serial || m_surface != surface || m_hotspot != hotspot; 0082 if (diff) { 0083 m_serial = serial; 0084 m_surface = surface; 0085 m_hotspot = hotspot; 0086 0087 Q_EMIT q->changed(); 0088 } 0089 } 0090 0091 TabletCursorV2 *const q; 0092 0093 quint32 m_serial = 0; 0094 QPointer<SurfaceInterface> m_surface; 0095 QPoint m_hotspot; 0096 }; 0097 0098 TabletCursorV2::TabletCursorV2() 0099 : QObject() 0100 , d(new TabletCursorV2Private(this)) 0101 { 0102 } 0103 0104 TabletCursorV2::~TabletCursorV2() = default; 0105 0106 QPoint TabletCursorV2::hotspot() const 0107 { 0108 return d->m_hotspot; 0109 } 0110 0111 quint32 TabletCursorV2::enteredSerial() const 0112 { 0113 return d->m_serial; 0114 } 0115 0116 SurfaceInterface *TabletCursorV2::surface() const 0117 { 0118 return d->m_surface; 0119 } 0120 0121 class TabletToolV2InterfacePrivate : public QtWaylandServer::zwp_tablet_tool_v2 0122 { 0123 public: 0124 TabletToolV2InterfacePrivate(TabletToolV2Interface *q, 0125 Display *display, 0126 TabletToolV2Interface::Type type, 0127 uint32_t hsh, 0128 uint32_t hsl, 0129 uint32_t hih, 0130 uint32_t hil, 0131 const QVector<TabletToolV2Interface::Capability> &capabilities) 0132 : zwp_tablet_tool_v2() 0133 , m_display(display) 0134 , m_type(type) 0135 , m_hardwareSerialHigh(hsh) 0136 , m_hardwareSerialLow(hsl) 0137 , m_hardwareIdHigh(hih) 0138 , m_hardwareIdLow(hil) 0139 , m_capabilities(capabilities) 0140 , q(q) 0141 { 0142 } 0143 0144 wl_resource *targetResource() 0145 { 0146 if (!m_surface) 0147 return nullptr; 0148 0149 ClientConnection *client = m_surface->client(); 0150 const Resource *r = resourceMap().value(*client); 0151 return r ? r->handle : nullptr; 0152 } 0153 0154 quint64 hardwareId() const 0155 { 0156 return quint64(quint64(m_hardwareIdHigh) << 32) + m_hardwareIdLow; 0157 } 0158 quint64 hardwareSerial() const 0159 { 0160 return quint64(quint64(m_hardwareSerialHigh) << 32) + m_hardwareSerialLow; 0161 } 0162 0163 void zwp_tablet_tool_v2_bind_resource(QtWaylandServer::zwp_tablet_tool_v2::Resource *resource) override 0164 { 0165 TabletCursorV2 *&c = m_cursors[resource->handle]; 0166 if (!c) 0167 c = new TabletCursorV2; 0168 } 0169 0170 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 0171 { 0172 TabletCursorV2 *c = m_cursors[resource->handle]; 0173 c->d->update(serial, SurfaceInterface::get(_surface), {hotspot_x, hotspot_y}); 0174 if (resource->handle == targetResource()) 0175 q->cursorChanged(c); 0176 } 0177 0178 void zwp_tablet_tool_v2_destroy_resource(Resource *resource) override 0179 { 0180 delete m_cursors.take(resource->handle); 0181 if (m_removed && resourceMap().isEmpty()) { 0182 delete q; 0183 } 0184 } 0185 0186 void zwp_tablet_tool_v2_destroy(Resource *resource) override 0187 { 0188 wl_resource_destroy(resource->handle); 0189 } 0190 0191 Display *const m_display; 0192 bool m_cleanup = false; 0193 bool m_removed = false; 0194 QPointer<SurfaceInterface> m_surface; 0195 QPointer<TabletV2Interface> m_lastTablet; 0196 const uint32_t m_type; 0197 const uint32_t m_hardwareSerialHigh, m_hardwareSerialLow; 0198 const uint32_t m_hardwareIdHigh, m_hardwareIdLow; 0199 const QVector<TabletToolV2Interface::Capability> m_capabilities; 0200 QHash<wl_resource *, TabletCursorV2 *> m_cursors; 0201 TabletToolV2Interface *const q; 0202 }; 0203 0204 TabletToolV2Interface::TabletToolV2Interface(Display *display, 0205 Type type, 0206 uint32_t hsh, 0207 uint32_t hsl, 0208 uint32_t hih, 0209 uint32_t hil, 0210 const QVector<Capability> &capabilities) 0211 : d(new TabletToolV2InterfacePrivate(this, display, type, hsh, hsl, hih, hil, capabilities)) 0212 { 0213 } 0214 0215 TabletToolV2Interface::~TabletToolV2Interface() 0216 { 0217 const auto toolResources = d->resourceMap(); 0218 for (TabletToolV2InterfacePrivate::Resource *resource : toolResources) { 0219 d->send_removed(resource->handle); 0220 } 0221 } 0222 0223 bool TabletToolV2Interface::hasCapability(Capability capability) const 0224 { 0225 return d->m_capabilities.contains(capability); 0226 } 0227 0228 void TabletToolV2Interface::setCurrentSurface(SurfaceInterface *surface) 0229 { 0230 if (d->m_surface == surface) 0231 return; 0232 0233 TabletV2Interface *const lastTablet = d->m_lastTablet; 0234 if (d->m_surface && d->resourceMap().contains(*d->m_surface->client())) { 0235 sendProximityOut(); 0236 sendFrame(0); 0237 } 0238 0239 d->m_surface = surface; 0240 0241 if (lastTablet && lastTablet->d->resourceForSurface(surface)) { 0242 sendProximityIn(lastTablet); 0243 } else { 0244 d->m_lastTablet = lastTablet; 0245 } 0246 0247 Q_EMIT cursorChanged(d->m_cursors.value(d->targetResource())); 0248 } 0249 0250 bool TabletToolV2Interface::isClientSupported() const 0251 { 0252 return d->m_surface && d->targetResource(); 0253 } 0254 0255 void TabletToolV2Interface::sendButton(uint32_t button, bool pressed) 0256 { 0257 d->send_button(d->targetResource(), 0258 d->m_display->nextSerial(), 0259 button, 0260 pressed ? QtWaylandServer::zwp_tablet_tool_v2::button_state_pressed : QtWaylandServer::zwp_tablet_tool_v2::button_state_released); 0261 } 0262 0263 void TabletToolV2Interface::sendMotion(const QPointF &pos) 0264 { 0265 const QPointF surfacePos = d->m_surface->toSurfaceLocal(pos); 0266 d->send_motion(d->targetResource(), wl_fixed_from_double(surfacePos.x()), wl_fixed_from_double(surfacePos.y())); 0267 } 0268 0269 void TabletToolV2Interface::sendDistance(uint32_t distance) 0270 { 0271 d->send_distance(d->targetResource(), distance); 0272 } 0273 0274 void TabletToolV2Interface::sendFrame(uint32_t time) 0275 { 0276 d->send_frame(d->targetResource(), time); 0277 0278 if (d->m_cleanup) { 0279 d->m_surface = nullptr; 0280 d->m_lastTablet = nullptr; 0281 d->m_cleanup = false; 0282 } 0283 } 0284 0285 void TabletToolV2Interface::sendPressure(uint32_t pressure) 0286 { 0287 d->send_pressure(d->targetResource(), pressure); 0288 } 0289 0290 void TabletToolV2Interface::sendRotation(qreal rotation) 0291 { 0292 d->send_rotation(d->targetResource(), wl_fixed_from_double(rotation)); 0293 } 0294 0295 void TabletToolV2Interface::sendSlider(int32_t position) 0296 { 0297 d->send_slider(d->targetResource(), position); 0298 } 0299 0300 void TabletToolV2Interface::sendTilt(qreal degreesX, qreal degreesY) 0301 { 0302 d->send_tilt(d->targetResource(), wl_fixed_from_double(degreesX), wl_fixed_from_double(degreesY)); 0303 } 0304 0305 void TabletToolV2Interface::sendWheel(int32_t degrees, int32_t clicks) 0306 { 0307 d->send_wheel(d->targetResource(), degrees, clicks); 0308 } 0309 0310 void TabletToolV2Interface::sendProximityIn(TabletV2Interface *tablet) 0311 { 0312 wl_resource *tabletResource = tablet->d->resourceForSurface(d->m_surface); 0313 d->send_proximity_in(d->targetResource(), d->m_display->nextSerial(), tabletResource, d->m_surface->resource()); 0314 d->m_lastTablet = tablet; 0315 } 0316 0317 void TabletToolV2Interface::sendProximityOut() 0318 { 0319 d->send_proximity_out(d->targetResource()); 0320 d->m_cleanup = true; 0321 } 0322 0323 void TabletToolV2Interface::sendDown() 0324 { 0325 d->send_down(d->targetResource(), d->m_display->nextSerial()); 0326 } 0327 0328 void TabletToolV2Interface::sendUp() 0329 { 0330 d->send_up(d->targetResource()); 0331 } 0332 0333 class TabletPadRingV2InterfacePrivate : public QtWaylandServer::zwp_tablet_pad_ring_v2 0334 { 0335 public: 0336 TabletPadRingV2InterfacePrivate(TabletPadRingV2Interface *q) 0337 : zwp_tablet_pad_ring_v2() 0338 , q(q) 0339 { 0340 } 0341 0342 wl_resource *resourceForSurface(SurfaceInterface *surface) const 0343 { 0344 ClientConnection *client = surface->client(); 0345 Resource *r = resourceMap().value(*client); 0346 return r ? r->handle : nullptr; 0347 } 0348 0349 void zwp_tablet_pad_ring_v2_destroy(Resource *resource) override 0350 { 0351 wl_resource_destroy(resource->handle); 0352 } 0353 TabletPadRingV2Interface *const q; 0354 TabletPadV2Interface *m_pad; 0355 }; 0356 0357 TabletPadRingV2Interface::TabletPadRingV2Interface(TabletPadV2Interface *parent) 0358 : QObject(parent) 0359 , d(new TabletPadRingV2InterfacePrivate(this)) 0360 { 0361 d->m_pad = parent; 0362 } 0363 0364 TabletPadRingV2Interface::~TabletPadRingV2Interface() = default; 0365 0366 void TabletPadRingV2Interface::sendAngle(qreal angle) 0367 { 0368 d->send_angle(d->resourceForSurface(d->m_pad->currentSurface()), wl_fixed_from_double(angle)); 0369 } 0370 0371 void TabletPadRingV2Interface::sendFrame(quint32 time) 0372 { 0373 d->send_frame(d->resourceForSurface(d->m_pad->currentSurface()), time); 0374 } 0375 0376 void TabletPadRingV2Interface::sendSource(Source source) 0377 { 0378 d->send_source(d->resourceForSurface(d->m_pad->currentSurface()), source); 0379 } 0380 0381 void TabletPadRingV2Interface::sendStop() 0382 { 0383 d->send_stop(d->resourceForSurface(d->m_pad->currentSurface())); 0384 } 0385 0386 class TabletPadStripV2InterfacePrivate : public QtWaylandServer::zwp_tablet_pad_strip_v2 0387 { 0388 public: 0389 TabletPadStripV2InterfacePrivate(TabletPadStripV2Interface *q) 0390 : zwp_tablet_pad_strip_v2() 0391 , q(q) 0392 { 0393 } 0394 0395 wl_resource *resourceForSurface(SurfaceInterface *surface) const 0396 { 0397 ClientConnection *client = surface->client(); 0398 Resource *r = resourceMap().value(*client); 0399 return r ? r->handle : nullptr; 0400 } 0401 0402 void zwp_tablet_pad_strip_v2_destroy(Resource *resource) override 0403 { 0404 wl_resource_destroy(resource->handle); 0405 } 0406 TabletPadV2Interface *m_pad = nullptr; 0407 TabletPadStripV2Interface *const q; 0408 }; 0409 0410 TabletPadStripV2Interface::TabletPadStripV2Interface(TabletPadV2Interface *parent) 0411 : QObject(parent) 0412 , d(new TabletPadStripV2InterfacePrivate(this)) 0413 { 0414 d->m_pad = parent; 0415 } 0416 0417 TabletPadStripV2Interface::~TabletPadStripV2Interface() = default; 0418 0419 void TabletPadStripV2Interface::sendFrame(quint32 time) 0420 { 0421 d->send_frame(d->resourceForSurface(d->m_pad->currentSurface()), time); 0422 } 0423 0424 void TabletPadStripV2Interface::sendPosition(quint32 position) 0425 { 0426 d->send_position(d->resourceForSurface(d->m_pad->currentSurface()), position); 0427 } 0428 0429 void TabletPadStripV2Interface::sendSource(Source source) 0430 { 0431 d->send_source(d->resourceForSurface(d->m_pad->currentSurface()), source); 0432 } 0433 0434 void TabletPadStripV2Interface::sendStop() 0435 { 0436 d->send_stop(d->resourceForSurface(d->m_pad->currentSurface())); 0437 } 0438 0439 class TabletPadGroupV2InterfacePrivate : public QtWaylandServer::zwp_tablet_pad_group_v2 0440 { 0441 public: 0442 TabletPadGroupV2InterfacePrivate(quint32 currentMode, TabletPadGroupV2Interface *q) 0443 : zwp_tablet_pad_group_v2() 0444 , q(q) 0445 , m_currentMode(currentMode) 0446 { 0447 } 0448 0449 wl_resource *resourceForSurface(SurfaceInterface *surface) const 0450 { 0451 ClientConnection *client = surface->client(); 0452 Resource *r = resourceMap().value(*client); 0453 return r ? r->handle : nullptr; 0454 } 0455 0456 void zwp_tablet_pad_group_v2_destroy(Resource *resource) override 0457 { 0458 wl_resource_destroy(resource->handle); 0459 } 0460 0461 TabletPadGroupV2Interface *const q; 0462 TabletPadV2Interface *m_pad = nullptr; 0463 quint32 m_currentMode; 0464 }; 0465 0466 TabletPadGroupV2Interface::TabletPadGroupV2Interface(quint32 currentMode, TabletPadV2Interface *parent) 0467 : QObject(parent) 0468 , d(new TabletPadGroupV2InterfacePrivate(currentMode, this)) 0469 { 0470 d->m_pad = parent; 0471 } 0472 0473 TabletPadGroupV2Interface::~TabletPadGroupV2Interface() = default; 0474 0475 void TabletPadGroupV2Interface::sendModeSwitch(quint32 time, quint32 serial, quint32 mode) 0476 { 0477 d->m_currentMode = mode; 0478 d->send_mode_switch(d->resourceForSurface(d->m_pad->currentSurface()), time, serial, mode); 0479 } 0480 0481 class TabletPadV2InterfacePrivate : public QtWaylandServer::zwp_tablet_pad_v2 0482 { 0483 public: 0484 TabletPadV2InterfacePrivate(const QString &path, 0485 quint32 buttons, 0486 quint32 rings, 0487 quint32 strips, 0488 quint32 modes, 0489 quint32 currentMode, 0490 Display *display, 0491 TabletPadV2Interface *q) 0492 : zwp_tablet_pad_v2() 0493 , q(q) 0494 , m_path(path) 0495 , m_buttons(buttons) 0496 , m_modes(modes) 0497 , m_padGroup(new TabletPadGroupV2Interface(currentMode, q)) 0498 , m_display(display) 0499 { 0500 for (uint i = 0; i < buttons; ++i) { 0501 m_buttons[i] = i; 0502 } 0503 0504 m_rings.reserve(rings); 0505 for (quint32 i = 0; i < rings; ++i) { 0506 m_rings += new TabletPadRingV2Interface(q); 0507 } 0508 0509 m_strips.reserve(strips); 0510 for (quint32 i = 0; i < strips; ++i) { 0511 m_strips += new TabletPadStripV2Interface(q); 0512 } 0513 } 0514 0515 ~TabletPadV2InterfacePrivate() override 0516 { 0517 qDeleteAll(m_rings); 0518 qDeleteAll(m_strips); 0519 } 0520 0521 void zwp_tablet_pad_v2_destroy(Resource *resource) override 0522 { 0523 wl_resource_destroy(resource->handle); 0524 } 0525 0526 void zwp_tablet_pad_v2_set_feedback(Resource *resource, quint32 button, const QString &description, quint32 serial) override 0527 { 0528 Q_EMIT q->feedback(m_display->getConnection(resource->client()), button, description, serial); 0529 } 0530 0531 wl_resource *resourceForSurface(SurfaceInterface *surface) const 0532 { 0533 ClientConnection *client = surface->client(); 0534 Resource *r = resourceMap().value(*client); 0535 return r ? r->handle : nullptr; 0536 } 0537 0538 TabletPadV2Interface *const q; 0539 0540 const QString m_path; 0541 QVector<quint32> m_buttons; 0542 const int m_modes; 0543 0544 QVector<TabletPadRingV2Interface *> m_rings; 0545 QVector<TabletPadStripV2Interface *> m_strips; 0546 TabletPadGroupV2Interface *const m_padGroup; 0547 TabletSeatV2Interface *m_seat = nullptr; 0548 QPointer<SurfaceInterface> m_currentSurface; 0549 Display *const m_display; 0550 }; 0551 0552 TabletPadV2Interface::TabletPadV2Interface(const QString &path, 0553 quint32 buttons, 0554 quint32 rings, 0555 quint32 strips, 0556 quint32 modes, 0557 quint32 currentMode, 0558 Display *display, 0559 TabletSeatV2Interface *parent) 0560 : QObject(parent) 0561 , d(new TabletPadV2InterfacePrivate(path, buttons, rings, strips, modes, currentMode, display, this)) 0562 { 0563 d->m_seat = parent; 0564 } 0565 0566 TabletPadV2Interface::~TabletPadV2Interface() 0567 { 0568 const auto tabletPadResources = d->resourceMap(); 0569 for (TabletPadV2InterfacePrivate::Resource *resource : tabletPadResources) { 0570 d->send_removed(resource->handle); 0571 } 0572 } 0573 0574 void TabletPadV2Interface::sendButton(std::chrono::microseconds time, quint32 button, bool pressed) 0575 { 0576 d->send_button(d->resourceForSurface(currentSurface()), std::chrono::duration_cast<std::chrono::milliseconds>(time).count(), button, pressed); 0577 } 0578 0579 TabletPadRingV2Interface *TabletPadV2Interface::ring(uint at) const 0580 { 0581 return d->m_rings[at]; 0582 } 0583 0584 TabletPadStripV2Interface *TabletPadV2Interface::strip(uint at) const 0585 { 0586 return d->m_strips[at]; 0587 } 0588 0589 void TabletPadV2Interface::setCurrentSurface(SurfaceInterface *surface, TabletV2Interface *tablet) 0590 { 0591 if (surface == d->m_currentSurface) { 0592 return; 0593 } 0594 0595 if (d->m_currentSurface) { 0596 d->send_leave(d->resourceForSurface(d->m_currentSurface), d->m_display->nextSerial(), d->m_currentSurface->resource()); 0597 } 0598 0599 d->m_currentSurface = surface; 0600 if (surface) { 0601 wl_resource *tabletResource = tablet->d->resourceForSurface(surface); 0602 0603 d->send_enter(d->resourceForSurface(surface), d->m_display->nextSerial(), tabletResource, surface->resource()); 0604 d->m_padGroup->sendModeSwitch(0, d->m_display->nextSerial(), d->m_padGroup->d->m_currentMode); 0605 } 0606 } 0607 0608 SurfaceInterface *TabletPadV2Interface::currentSurface() const 0609 { 0610 return d->m_currentSurface; 0611 } 0612 0613 class TabletSeatV2InterfacePrivate : public QtWaylandServer::zwp_tablet_seat_v2 0614 { 0615 public: 0616 TabletSeatV2InterfacePrivate(Display *display, TabletSeatV2Interface *q) 0617 : zwp_tablet_seat_v2() 0618 , q(q) 0619 , m_display(display) 0620 { 0621 } 0622 0623 void zwp_tablet_seat_v2_bind_resource(Resource *resource) override 0624 { 0625 for (auto tablet : std::as_const(m_tablets)) { 0626 sendTabletAdded(resource, tablet); 0627 } 0628 0629 for (auto pad : std::as_const(m_pads)) { 0630 sendPadAdded(resource, pad); 0631 } 0632 0633 for (const auto &tools : std::as_const(m_tools)) { 0634 for (auto *tool : tools) { 0635 sendToolAdded(resource, tool); 0636 } 0637 } 0638 } 0639 0640 void zwp_tablet_seat_v2_destroy(Resource *resource) override 0641 { 0642 wl_resource_destroy(resource->handle); 0643 } 0644 0645 void sendToolAdded(Resource *resource, TabletToolV2Interface *tool) 0646 { 0647 wl_resource *toolResource = tool->d->add(resource->client(), resource->version())->handle; 0648 send_tool_added(resource->handle, toolResource); 0649 0650 tool->d->send_type(toolResource, tool->d->m_type); 0651 tool->d->send_hardware_serial(toolResource, tool->d->m_hardwareSerialHigh, tool->d->m_hardwareSerialLow); 0652 tool->d->send_hardware_id_wacom(toolResource, tool->d->m_hardwareIdHigh, tool->d->m_hardwareIdLow); 0653 for (uint32_t cap : std::as_const(tool->d->m_capabilities)) { 0654 tool->d->send_capability(toolResource, cap); 0655 } 0656 tool->d->send_done(toolResource); 0657 } 0658 void sendTabletAdded(Resource *resource, TabletV2Interface *tablet) 0659 { 0660 wl_resource *tabletResource = tablet->d->add(resource->client(), resource->version())->handle; 0661 send_tablet_added(resource->handle, tabletResource); 0662 0663 tablet->d->send_name(tabletResource, tablet->d->m_name); 0664 if (tablet->d->m_vendorId && tablet->d->m_productId) { 0665 tablet->d->send_id(tabletResource, tablet->d->m_vendorId, tablet->d->m_productId); 0666 } 0667 for (const QString &path : std::as_const(tablet->d->m_paths)) { 0668 tablet->d->send_path(tabletResource, path); 0669 } 0670 tablet->d->send_done(tabletResource); 0671 } 0672 0673 void sendPadAdded(Resource *resource, TabletPadV2Interface *pad) 0674 { 0675 wl_resource *tabletResource = pad->d->add(resource->client(), resource->version())->handle; 0676 send_pad_added(resource->handle, tabletResource); 0677 0678 pad->d->send_buttons(tabletResource, pad->d->m_buttons.size()); 0679 pad->d->send_path(tabletResource, pad->d->m_path); 0680 0681 auto groupResource = pad->d->m_padGroup->d->add(resource->client(), resource->version()); 0682 pad->d->send_group(tabletResource, groupResource->handle); 0683 pad->d->m_padGroup->d->send_modes(groupResource->handle, pad->d->m_modes); 0684 0685 pad->d->m_padGroup->d->send_buttons( 0686 groupResource->handle, 0687 QByteArray::fromRawData(reinterpret_cast<const char *>(pad->d->m_buttons.data()), pad->d->m_buttons.size() * sizeof(quint32))); 0688 0689 for (auto ring : std::as_const(pad->d->m_rings)) { 0690 auto ringResource = ring->d->add(resource->client(), resource->version()); 0691 pad->d->m_padGroup->d->send_ring(groupResource->handle, ringResource->handle); 0692 } 0693 0694 for (auto strip : std::as_const(pad->d->m_strips)) { 0695 auto stripResource = strip->d->add(resource->client(), resource->version()); 0696 pad->d->m_padGroup->d->send_strip(groupResource->handle, stripResource->handle); 0697 } 0698 pad->d->m_padGroup->d->send_done(groupResource->handle); 0699 pad->d->send_done(tabletResource); 0700 } 0701 0702 TabletSeatV2Interface *const q; 0703 QHash<QString, QVector<TabletToolV2Interface *>> m_tools; 0704 QHash<QString, TabletV2Interface *> m_tablets; 0705 QHash<QString, TabletPadV2Interface *> m_pads; 0706 Display *const m_display; 0707 }; 0708 0709 TabletSeatV2Interface::TabletSeatV2Interface(Display *display, QObject *parent) 0710 : QObject(parent) 0711 , d(new TabletSeatV2InterfacePrivate(display, this)) 0712 { 0713 } 0714 0715 TabletSeatV2Interface::~TabletSeatV2Interface() = default; 0716 0717 TabletToolV2Interface *TabletSeatV2Interface::addTool(TabletToolV2Interface::Type type, 0718 quint64 hardwareSerial, 0719 quint64 hardwareId, 0720 const QVector<TabletToolV2Interface::Capability> &capabilities, 0721 const QString &deviceSysName) 0722 { 0723 constexpr auto MAX_UINT_32 = std::numeric_limits<quint32>::max(); 0724 auto tool = new TabletToolV2Interface(d->m_display, 0725 type, 0726 hardwareSerial >> 32, 0727 hardwareSerial & MAX_UINT_32, 0728 hardwareId >> 32, 0729 hardwareId & MAX_UINT_32, 0730 capabilities); 0731 for (QtWaylandServer::zwp_tablet_seat_v2::Resource *resource : d->resourceMap()) { 0732 d->sendToolAdded(resource, tool); 0733 } 0734 0735 d->m_tools[deviceSysName].append(tool); 0736 return tool; 0737 } 0738 0739 TabletV2Interface * 0740 TabletSeatV2Interface::addTablet(uint32_t vendorId, uint32_t productId, const QString &sysname, const QString &name, const QStringList &paths) 0741 { 0742 Q_ASSERT(!d->m_tablets.contains(sysname)); 0743 0744 auto iface = new TabletV2Interface(vendorId, productId, name, paths, this); 0745 0746 for (QtWaylandServer::zwp_tablet_seat_v2::Resource *r : d->resourceMap()) { 0747 d->sendTabletAdded(r, iface); 0748 } 0749 0750 d->m_tablets[sysname] = iface; 0751 return iface; 0752 } 0753 0754 TabletPadV2Interface *TabletSeatV2Interface::addTabletPad(const QString &sysname, 0755 const QString &name, 0756 const QStringList &paths, 0757 quint32 buttons, 0758 quint32 rings, 0759 quint32 strips, 0760 quint32 modes, 0761 quint32 currentMode, 0762 TabletV2Interface *tablet) 0763 { 0764 auto iface = new TabletPadV2Interface(paths.at(0), buttons, rings, strips, modes, currentMode, d->m_display, this); 0765 iface->d->m_seat = this; 0766 for (auto r : d->resourceMap()) { 0767 d->sendPadAdded(r, iface); 0768 } 0769 0770 tablet->d->m_pad = iface; 0771 0772 d->m_pads[sysname] = iface; 0773 return iface; 0774 } 0775 0776 void TabletSeatV2Interface::removeDevice(const QString &sysname) 0777 { 0778 delete d->m_tablets.take(sysname); 0779 delete d->m_pads.take(sysname); 0780 0781 qDeleteAll(d->m_tools.take(sysname)); 0782 } 0783 0784 TabletToolV2Interface *TabletSeatV2Interface::toolByHardwareId(quint64 hardwareId) const 0785 { 0786 for (const auto &tools : std::as_const(d->m_tools)) { 0787 for (TabletToolV2Interface *tool : tools) { 0788 if (tool->d->hardwareId() == hardwareId) { 0789 return tool; 0790 } 0791 } 0792 } 0793 return nullptr; 0794 } 0795 0796 TabletToolV2Interface *TabletSeatV2Interface::toolByHardwareSerial(quint64 hardwareSerial, TabletToolV2Interface::Type type) const 0797 { 0798 for (const auto &tools : std::as_const(d->m_tools)) { 0799 for (TabletToolV2Interface *tool : tools) { 0800 if (tool->d->hardwareSerial() == hardwareSerial && tool->d->m_type == type) { 0801 return tool; 0802 } 0803 } 0804 } 0805 return nullptr; 0806 } 0807 0808 TabletPadV2Interface *TabletSeatV2Interface::padByName(const QString &name) const 0809 { 0810 Q_ASSERT(d->m_pads.contains(name)); 0811 return d->m_pads.value(name); 0812 } 0813 0814 class TabletManagerV2InterfacePrivate : public QtWaylandServer::zwp_tablet_manager_v2 0815 { 0816 public: 0817 TabletManagerV2InterfacePrivate(Display *display, TabletManagerV2Interface *q) 0818 : zwp_tablet_manager_v2(*display, s_version) 0819 , q(q) 0820 , m_display(display) 0821 { 0822 } 0823 0824 void zwp_tablet_manager_v2_get_tablet_seat(Resource *resource, uint32_t tablet_seat, struct ::wl_resource *seat_resource) override 0825 { 0826 SeatInterface *seat = SeatInterface::get(seat_resource); 0827 TabletSeatV2Interface *tsi = get(seat); 0828 tsi->d->add(resource->client(), tablet_seat, s_version); 0829 } 0830 0831 TabletSeatV2Interface *get(SeatInterface *seat) 0832 { 0833 TabletSeatV2Interface *&tabletSeat = m_seats[seat]; 0834 if (!tabletSeat) { 0835 tabletSeat = new TabletSeatV2Interface(m_display, q); 0836 } 0837 return tabletSeat; 0838 } 0839 0840 TabletManagerV2Interface *const q; 0841 Display *const m_display; 0842 QHash<SeatInterface *, TabletSeatV2Interface *> m_seats; 0843 }; 0844 0845 TabletManagerV2Interface::TabletManagerV2Interface(Display *display, QObject *parent) 0846 : QObject(parent) 0847 , d(new TabletManagerV2InterfacePrivate(display, this)) 0848 { 0849 } 0850 0851 TabletSeatV2Interface *TabletManagerV2Interface::seat(SeatInterface *seat) const 0852 { 0853 return d->get(seat); 0854 } 0855 0856 bool TabletSeatV2Interface::isClientSupported(ClientConnection *client) const 0857 { 0858 return d->resourceMap().value(*client); 0859 } 0860 0861 TabletManagerV2Interface::~TabletManagerV2Interface() = default; 0862 0863 } // namespace KWaylandServer