diff --git a/src/server/tablet_interface.cpp b/src/server/tablet_interface.cpp index 5b09f9f..e6104d2 100644 --- a/src/server/tablet_interface.cpp +++ b/src/server/tablet_interface.cpp @@ -1,529 +1,535 @@ /******************************************************************** Copyright 2019 Aleix Pol Gonzalez This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . *********************************************************************/ #include "tablet_interface.h" #include "resource_p.h" #include "seat_interface.h" #include "display.h" #include "surface_interface.h" #include #include "qwayland-server-tablet-unstable-v2.h" using namespace KWayland; using namespace Server; static int s_version = 1; class TabletToolInterface::Private : public QtWaylandServer::zwp_tablet_tool_v2 { public: Private(Type type, uint32_t hsh, uint32_t hsl, uint32_t hih, uint32_t hil, const QVector& capabilities) : zwp_tablet_tool_v2() , m_type(type) , m_hardwareSerialHigh(hsh) , m_hardwareSerialLow(hsl) , m_hardwareIdHigh(hih) , m_hardwareIdLow(hil) , m_capabilities(capabilities) {} void zwp_tablet_tool_v2_bind_resource(Resource * resource) override { send_type(resource->handle, m_type); send_hardware_serial(resource->handle, m_hardwareSerialHigh, m_hardwareSerialLow); send_hardware_id_wacom(resource->handle, m_hardwareIdHigh, m_hardwareIdLow); for (uint32_t cap : qAsConst(m_capabilities)) send_capability(resource->handle, cap); send_done(resource->handle); } const uint32_t m_type; const uint32_t m_hardwareSerialHigh, m_hardwareSerialLow; const uint32_t m_hardwareIdHigh, m_hardwareIdLow; const QVector m_capabilities; }; TabletToolInterface::TabletToolInterface(Type type, uint32_t hsh, uint32_t hsl, uint32_t hih, uint32_t hil, const QVector& capabilities, QObject *parent) : QObject(parent) , d(new Private(type, hsh, hsl, hih, hil, capabilities)) {} TabletToolInterface::~TabletToolInterface() = default; void TabletToolInterface::sendButton(uint32_t serial, uint32_t button, bool pressed) { for (auto *resource : d->resourceMap()) { d->send_button(resource->handle, serial, button, pressed ? QtWaylandServer::zwp_tablet_tool_v2::button_state_pressed : QtWaylandServer::zwp_tablet_tool_v2::button_state_released); } } void TabletToolInterface::sendMotion(const QPoint& pos) { for (auto *resource : d->resourceMap()) { d->send_motion(resource->handle, pos.x(), pos.y()); } } void TabletToolInterface::sendDistance(uint32_t distance) { for (auto *resource : d->resourceMap()) { d->send_distance(resource->handle, distance); } } void TabletToolInterface::sendFrame(uint32_t time) { for (auto *resource : d->resourceMap()) { d->send_frame(resource->handle, time); } } void TabletToolInterface::sendPressure(uint32_t pressure) { for (auto *resource : d->resourceMap()) { d->send_pressure(resource->handle, pressure); } } void TabletToolInterface::sendRotation(uint32_t degrees) { for (auto *resource : d->resourceMap()) { d->send_rotation(resource->handle, degrees); } } void TabletToolInterface::sendSlider(int32_t position) { for (auto *resource : d->resourceMap()) { d->send_slider(resource->handle, position); } } void TabletToolInterface::sendTilt(uint32_t degreesX, uint32_t degreesY) { for (auto *resource : d->resourceMap()) { d->send_tilt(resource->handle, degreesX, degreesY); } } void TabletToolInterface::sendWheel(int32_t degrees, int32_t clicks) { for (auto *resource : d->resourceMap()) { d->send_wheel(resource->handle, degrees, clicks); } } void TabletToolInterface::sendProximityIn(uint32_t serial, wl_resource* tablet, wl_resource* surface) { for (auto *resource : d->resourceMap()) { d->send_proximity_in(resource->handle, serial, tablet, surface); } } void TabletToolInterface::sendProximityOut() { for (auto *resource : d->resourceMap()) { d->send_proximity_out(resource->handle); } } void TabletToolInterface::sendDown(uint32_t serial) { for (auto *resource : d->resourceMap()) { d->send_down(resource->handle, serial); } } void TabletToolInterface::sendUp() { for (auto *resource : d->resourceMap()) { d->send_up(resource->handle); } } void TabletToolInterface::sendRemoved() { for (auto *resource : d->resourceMap()) { d->send_removed(resource->handle); } } wl_resource * TabletToolInterface::resource() const { return d->resource()->handle; } class TabletSeatInterface::Private : public QtWaylandServer::zwp_tablet_seat_v2 { public: - Private() + Private(TabletSeatInterface* q) : zwp_tablet_seat_v2() + , q(q) { } void zwp_tablet_seat_v2_bind_resource(Resource *resource) override { for (auto *tool : m_tools) sendToolAdded(resource, tool); for (auto iface : qAsConst(m_tablets)) send_tablet_added(resource->handle, iface->resource()); // for (auto r : qAsConst(m_pads)) // send_pad_added(resource->handle, r->resource()); } void sendToolAdded(Resource* resource, TabletToolInterface* tool) { auto *toolResource = tool->d->add(resource->client(), resource->version())->handle; send_tool_added(resource->handle, toolResource); } + TabletInterface* defaultTablet() { + if (!m_defaultTablet) + m_defaultTablet = q->addTablet(0, 0, QStringLiteral("whatever"), {}); + return m_defaultTablet; + } + TabletSeatInterface* const q; TabletInterface* m_defaultTablet = nullptr; QVector m_tools; QHash m_tablets; }; TabletSeatInterface::TabletSeatInterface(QObject* parent) : QObject(parent) - , d(new Private) + , d(new Private(this)) { - d->m_defaultTablet = addTablet(0, 0, QStringLiteral("whatever"), {}); } TabletSeatInterface::~TabletSeatInterface() = default; TabletToolInterface* TabletSeatInterface::addTool(TabletToolInterface::Type type, quint64 hardwareSerial, quint64 hardwareId, const QVector &capabilities) { const auto MAX_UINT_32 = std::numeric_limits::max(); auto tool = new TabletToolInterface(type, hardwareSerial >> 32, hardwareSerial & MAX_UINT_32, hardwareId >> 32, hardwareId & MAX_UINT_32, capabilities, this); for (auto *resource : d->resourceMap()) { d->sendToolAdded(resource, tool); } d->m_tools.append(tool); QObject::connect(tool, &QObject::destroyed, this, [this] (QObject* object) { d->m_tools.removeAll(static_cast(object)); } ); return tool; } TabletInterface* TabletSeatInterface::addTablet(uint32_t vendorId, uint32_t productId, const QString &name, const QStringList &paths) { auto iface = new TabletInterface(vendorId, productId, name, paths, this); if (d->resource()) for (auto r : d->resourceMap()) d->send_tablet_added(r->handle); d->m_tablets[name] = iface; QObject::connect(iface, &QObject::destroyed, this, [this, name] { d->m_tablets.remove(name); } ); return iface; } TabletInterface * TabletSeatInterface::tabletByName(const QString& name) const { - return d->m_tablets.value(name, d->m_defaultTablet); + return d->m_tablets.value(name, d->defaultTablet()); } class TabletManagerInterface::Private : public QtWaylandServer::zwp_tablet_manager_v2 { public: Private(Display *display, TabletManagerInterface* q) : zwp_tablet_manager_v2(*display, s_version) , q(q) {} void zwp_tablet_manager_v2_get_tablet_seat(Resource * resource, uint32_t tablet_seat, struct ::wl_resource * seat_resource) override { auto seat = SeatInterface::get(seat_resource); qCritical() << "get tablet seat" << resource << tablet_seat << seat; TabletSeatInterface* tsi = get(seat); tsi->d->add(resource->client(), tablet_seat, s_version); } TabletSeatInterface* get(SeatInterface* seat) { auto& tabletSeat = m_seats[seat]; if (!tabletSeat) { tabletSeat = new TabletSeatInterface(q); } return tabletSeat; } TabletManagerInterface* const q; QHash m_seats; }; TabletManagerInterface::TabletManagerInterface(Display *display, QObject *parent) : QObject(parent) , d(new Private(display, this)) { } TabletSeatInterface* TabletManagerInterface::seat(SeatInterface* seat) const { return d->m_seats.value(seat); } TabletManagerInterface::~TabletManagerInterface() = default; // TabletSeatInterface* TabletManagerInterface::seat(SeatInterface* seat) // { // return d->get(seat); // } // // void TabletManagerInterface::cancel() // { // Q_D(); // if (!d->resource) { // return; // } // wl_tablet_send_cancel(d->resource); // d->client->flush(); // } // // TabletManagerInterface::Private *TabletManagerInterface::d_func() const // { // return reinterpret_cast(d.data()); // } class TabletInterface::Private : public QtWaylandServer::zwp_tablet_v2 { public: Private(uint32_t vendorId, uint32_t productId, const QString name, const QStringList &paths) : zwp_tablet_v2() , m_vendorId(vendorId) , m_productId(productId) , m_name(name) , m_paths(paths) {} void zwp_tablet_v2_bind_resource(Resource * /*resource*/) override { send_name(m_name); send_id(m_vendorId, m_productId); for (const auto &path : qAsConst(m_paths)) send_path(path); send_done(); } const uint32_t m_vendorId; const uint32_t m_productId; const QString m_name; const QStringList m_paths; }; TabletInterface::TabletInterface(uint32_t vendorId, uint32_t productId, const QString &name, const QStringList &paths, QObject* parent) : QObject(parent) , d(new Private(vendorId, productId, name, paths)) { } TabletInterface::~TabletInterface() = default; wl_resource * TabletInterface::resource() const { return d->resource()->handle; } TabletToolInterface * TabletSeatInterface::toolByHardwareId(quint64 serialId) const { for (auto tool : d->m_tools) { if (tool->hardwareSerial() == serialId) return tool; } return nullptr; } quint64 TabletToolInterface::hardwareSerial() const { return quint64(quint64(d->m_hardwareIdHigh) << 32) + d->m_hardwareIdLow; } #if 0 class TabletPadInterface::Private : public QtWaylandServer::zwp_tablet_pad_v2 { public: Private(const QStringList &paths) : zwp_tablet_pad_v2() , m_paths(paths) {} void zwp_tablet_pad_v2_bind_resource(Resource * /*resource*/) override { // zwp_tablet_pad_group_v2_send_strip(); for (const auto &path : qAsConst(m_paths)) send_path(path); send_done(); } const QStringList m_paths; }; TabletPadInterface::TabletPadInterface(const QStringList & paths, QObject* parent) : QObject(parent) , d(new Private(paths)) { } TabletPadInterface::~TabletPadInterface() = default; void TabletPadInterface::sendEnter(quint32 serial, struct ::wl_resource *tablet, struct ::wl_resource *surface) { d->send_enter(serial, tablet, surface); } void TabletPadInterface::sendLeave(quint32 serial, struct ::wl_resource *surface) { d->send_leave(serial, surface); } class TabletPadStripInterface::Private : public QtWaylandServer::zwp_tablet_pad_strip_v2 { public: Private(TabletPadStripInterface* q) : zwp_tablet_pad_strip_v2() , q(q) {} void zwp_tablet_pad_strip_v2_set_feedback(Resource * resource, const QString & description, uint32_t serial) override { Q_UNUSED(resource); Q_UNUSED(serial); if (m_description != description) { m_description = description; Q_EMIT q->descriptionChanged(description); } } QString m_description; TabletPadStripInterface* const q; }; TabletPadStripInterface::TabletPadStripInterface(QObject* parent) : QObject(parent) , d(new Private(this)) { } TabletPadStripInterface::~TabletPadStripInterface() = default; QString TabletPadStripInterface::description() const { return d->m_description; } void TabletPadStripInterface::sendSource(Source source) { d->send_source(source); } void TabletPadStripInterface::sendFrame(quint32 timestamp) { d->send_frame(timestamp); } void TabletPadStripInterface::sendPosition(quint32 position) { d->send_position(position); } void TabletPadStripInterface::sendStop() { d->send_stop(); } class TabletPadRingInterface::Private : public QtWaylandServer::zwp_tablet_pad_ring_v2 { public: Private(TabletPadRingInterface* q) : zwp_tablet_pad_ring_v2() , q(q) {} void zwp_tablet_pad_ring_v2_set_feedback(Resource * resource, const QString & description, uint32_t serial) override { Q_UNUSED(resource); Q_UNUSED(serial); if (m_description != description) { m_description = description; Q_EMIT q->descriptionChanged(description); } } QString m_description; TabletPadRingInterface* const q; }; TabletPadRingInterface::TabletPadRingInterface(QObject* parent) : QObject(parent) , d(new Private(this)) { } TabletPadRingInterface::~TabletPadRingInterface() = default; void TabletPadRingInterface::sendAngle(quint32 degrees) { d->send_angle(degrees); } void TabletPadRingInterface::sendFrame(quint32 time) { d->send_frame(time); } void TabletPadRingInterface::sendSource(TabletPadRingInterface::Source source) { d->send_source(source); } void TabletPadRingInterface::sendStop() { d->send_stop(); } class TabletPadGroupInterface::Private : public QtWaylandServer::zwp_tablet_pad_group_v2 { public: Private(TabletPadInterface* pad) : zwp_tablet_pad_group_v2() , pad(pad) {} void zwp_tablet_pad_group_v2_bind_resource(Resource * resource) override { send_buttons({}); send_done(); } TabletPadInterface* const pad; }; TabletPadGroupInterface::TabletPadGroupInterface(TabletPadInterface* pad, QObject* parent) : QObject(parent) , d(new Private(pad)) { } TabletPadGroupInterface::~TabletPadGroupInterface() = default; #endif