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