From 617651d93ee855c4abeb9e57e462c4bfc84e1c31 Mon Sep 17 00:00:00 2001 From: Aleix Pol Date: Tue, 22 Dec 2020 17:34:10 +0100 Subject: [PATCH] tablet_v2: Use libinput device groups to deduce the device's tablet We can have pads without tools, tools without pads. This changes how we figure out which tablet belongs to the input device. --- debug_console.cpp | 14 ++++---- debug_console.h | 6 ++-- input.cpp | 71 +++++++++++++++++++++-------------------- input.h | 7 ++-- input_event.h | 8 ++++- input_event_spy.cpp | 12 +++---- input_event_spy.h | 7 ++-- libinput/connection.cpp | 25 ++++++++------- libinput/connection.h | 6 ++-- libinput/device.cpp | 7 ++++ libinput/device.h | 2 ++ tablet_input.cpp | 18 +++++------ tablet_input.h | 6 ++-- 13 files changed, 105 insertions(+), 84 deletions(-) diff --git a/debug_console.cpp b/debug_console.cpp index a90985e912..f981a7fec9 100644 --- a/debug_console.cpp +++ b/debug_console.cpp @@ -506,46 +506,46 @@ void DebugConsoleFilter::tabletToolButtonEvent(uint button, bool pressed, const QString text = s_hr + s_tableStart + tableHeaderRow(i18n("Tablet Tool Button")) + tableRow(i18n("Button"), button) + tableRow(i18n("Pressed"), pressed) - + tableRow(i18n("Tablet"), tabletToolId.m_tabletSysName) + + tableRow(i18n("Tablet"), qHash(tabletToolId.m_deviceGroupData)) + s_tableEnd; m_textEdit->insertHtml(text); m_textEdit->ensureCursorVisible(); } -void DebugConsoleFilter::tabletPadButtonEvent(uint button, bool pressed, const QString &deviceSysName) +void DebugConsoleFilter::tabletPadButtonEvent(uint button, bool pressed, const TabletPadId &tabletPadId) { QString text = s_hr + s_tableStart + tableHeaderRow(i18n("Tablet Pad Button")) + tableRow(i18n("Button"), button) + tableRow(i18n("Pressed"), pressed) - + tableRow(i18n("Tablet"), deviceSysName) + + tableRow(i18n("Tablet"), qHash(tabletPadId.data)) + s_tableEnd; m_textEdit->insertHtml(text); m_textEdit->ensureCursorVisible(); } -void DebugConsoleFilter::tabletPadStripEvent(int number, int position, bool isFinger, const QString &deviceSysName) +void DebugConsoleFilter::tabletPadStripEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId) { QString text = s_hr + s_tableStart + tableHeaderRow(i18n("Tablet Pad Strip")) + tableRow(i18n("Number"), number) + tableRow(i18n("Position"), position) + tableRow(i18n("isFinger"), isFinger) - + tableRow(i18n("Tablet"), deviceSysName) + + tableRow(i18n("Tablet"), qHash(tabletPadId.data)) + s_tableEnd; m_textEdit->insertHtml(text); m_textEdit->ensureCursorVisible(); } -void DebugConsoleFilter::tabletPadRingEvent(int number, int position, bool isFinger, const QString &deviceSysName) +void DebugConsoleFilter::tabletPadRingEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId) { QString text = s_hr + s_tableStart + tableHeaderRow(i18n("Tablet Pad Ring")) + tableRow(i18n("Number"), number) + tableRow(i18n("Position"), position) + tableRow(i18n("isFinger"), isFinger) - + tableRow(i18n("Tablet"), deviceSysName) + + tableRow(i18n("Tablet"), qHash(tabletPadId.data)) + s_tableEnd; m_textEdit->insertHtml(text); diff --git a/debug_console.h b/debug_console.h index fc02af8a95..dc2822dd5a 100644 --- a/debug_console.h +++ b/debug_console.h @@ -149,9 +149,9 @@ public: void tabletToolEvent(TabletEvent *event) override; void tabletToolButtonEvent(uint button, bool pressed, const TabletToolId &tabletToolId) override; - void tabletPadButtonEvent(uint button, bool pressed, const QString &deviceSysName) override; - void tabletPadStripEvent(int number, int position, bool isFinger, const QString &deviceSysName) override; - void tabletPadRingEvent(int number, int position, bool isFinger, const QString &deviceSysName) override; + void tabletPadButtonEvent(uint button, bool pressed, const TabletPadId &tabletPadId) override; + void tabletPadStripEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId) override; + void tabletPadRingEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId) override; private: QTextEdit *m_textEdit; diff --git a/input.cpp b/input.cpp index 611c7c1827..8156bef083 100644 --- a/input.cpp +++ b/input.cpp @@ -183,29 +183,29 @@ bool InputEventFilter::tabletToolButtonEvent(uint button, bool pressed, const Ta return false; } -bool InputEventFilter::tabletPadButtonEvent(uint button, bool pressed, const QString &deviceSysName) +bool InputEventFilter::tabletPadButtonEvent(uint button, bool pressed, const TabletPadId &tabletPadId) { Q_UNUSED(button) Q_UNUSED(pressed) - Q_UNUSED(deviceSysName) + Q_UNUSED(tabletPadId) return false; } -bool InputEventFilter::tabletPadStripEvent(int number, int position, bool isFinger, const QString &deviceSysName) +bool InputEventFilter::tabletPadStripEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId) { Q_UNUSED(number) Q_UNUSED(position) Q_UNUSED(isFinger) - Q_UNUSED(deviceSysName) + Q_UNUSED(tabletPadId) return false; } -bool InputEventFilter::tabletPadRingEvent(int number, int position, bool isFinger, const QString &deviceSysName) +bool InputEventFilter::tabletPadRingEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId) { Q_UNUSED(number) Q_UNUSED(position) Q_UNUSED(isFinger) - Q_UNUSED(deviceSysName) + Q_UNUSED(tabletPadId) return false; } @@ -1578,34 +1578,33 @@ public: void integrateDevice(LibInput::Device *device) { - if (device->isTabletTool()) { - KWaylandServer::TabletSeatV2Interface *tabletSeat = findTabletSeat(); - if (!tabletSeat) { - qCCritical(KWIN_CORE) << "Could not find tablet seat"; - return; - } - struct udev_device *const udev_device = libinput_device_get_udev_device(device->device()); - const char *devnode = udev_device_get_syspath(udev_device); + if (!device->isTabletTool() && !device->isTabletPad()) { + return; + } - tabletSeat->addTablet(device->vendor(), device->product(), device->sysName(), device->name(), {QString::fromUtf8(devnode)}); + KWaylandServer::TabletSeatV2Interface *tabletSeat = findTabletSeat(); + if (!tabletSeat) { + qCCritical(KWIN_CORE) << "Could not find tablet seat"; + return; + } + struct udev_device *const udev_device = libinput_device_get_udev_device(device->device()); + const char *devnode = udev_device_get_syspath(udev_device); + + auto deviceGroup = libinput_device_get_device_group(device->device()); + auto tablet = static_cast(libinput_device_group_get_user_data(deviceGroup)); + if (!tablet) { + tablet = tabletSeat->addTablet(device->vendor(), device->product(), device->sysName(), device->name(), {QString::fromUtf8(devnode)}); + libinput_device_group_set_user_data(deviceGroup, tablet); } if (device->isTabletPad()) { - KWaylandServer::TabletSeatV2Interface *tabletSeat = findTabletSeat(); - if (!tabletSeat) { - qCCritical(KWIN_CORE) << "Could not find tablet seat"; - return; - } - struct udev_device *const udev_device = libinput_device_get_udev_device(device->device()); - const char *devnode = udev_device_get_syspath(udev_device); - const int buttonsCount = libinput_device_tablet_pad_get_num_buttons(device->device()); const int ringsCount = libinput_device_tablet_pad_get_num_rings(device->device()); const int stripsCount = libinput_device_tablet_pad_get_num_strips(device->device()); const int modes = libinput_device_tablet_pad_get_num_mode_groups(device->device()); auto firstGroup = libinput_device_tablet_pad_get_mode_group(device->device(), 0); - tabletSeat->addTabletPad(device->sysName(), device->name(), {QString::fromUtf8(devnode)}, buttonsCount, ringsCount, stripsCount, modes, libinput_tablet_pad_mode_group_get_mode(firstGroup)); + tabletSeat->addTabletPad(device->sysName(), device->name(), {QString::fromUtf8(devnode)}, buttonsCount, ringsCount, stripsCount, modes, libinput_tablet_pad_mode_group_get_mode(firstGroup), tablet); } } void removeDevice(const QString &sysname) @@ -1729,7 +1728,7 @@ public: tool = createTool(event->tabletId()); } - KWaylandServer::TabletV2Interface *tablet = tabletSeat->tabletByName(event->tabletId().m_tabletSysName); + auto tablet = static_cast(event->tabletId().m_deviceGroupData); Toplevel *toplevel = input()->findToplevel(event->globalPos()); if (!toplevel || !toplevel->surface()) { @@ -1816,7 +1815,7 @@ public: return true; } - KWaylandServer::TabletPadV2Interface *findPad(const QString &deviceSysName) const + KWaylandServer::TabletPadV2Interface *findAndAdoptPad(const TabletPadId &tabletPadId) const { Toplevel *toplevel = workspace()->activeClient(); auto seat = findTabletSeat(); @@ -1824,15 +1823,19 @@ public: return nullptr; } + auto tablet = static_cast(tabletPadId.data); KWaylandServer::SurfaceInterface *surface = toplevel->surface(); - auto pad = seat->padByName(deviceSysName); - pad->setCurrentSurface(surface); + auto pad = tablet->pad(); + if (!pad) { + return nullptr; + } + pad->setCurrentSurface(surface, tablet); return pad; } - bool tabletPadButtonEvent(uint button, bool pressed, const QString &deviceSysName) override + bool tabletPadButtonEvent(uint button, bool pressed, const TabletPadId &tabletPadId) override { - auto pad = findPad(deviceSysName); + auto pad = findAndAdoptPad(tabletPadId); if (!pad) { return false; } @@ -1840,9 +1843,9 @@ public: return true; } - bool tabletPadRingEvent(int number, int angle, bool isFinger, const QString &deviceSysName) override + bool tabletPadRingEvent(int number, int angle, bool isFinger, const TabletPadId &tabletPadId) override { - auto pad = findPad(deviceSysName); + auto pad = findAndAdoptPad(tabletPadId); if (!pad) { return false; } @@ -1856,9 +1859,9 @@ public: return true; } - bool tabletPadStripEvent(int number, int position, bool isFinger, const QString &deviceSysName) override + bool tabletPadStripEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId) override { - auto pad = findPad(deviceSysName); + auto pad = findAndAdoptPad(tabletPadId); if (!pad) { return false; } diff --git a/input.h b/input.h index 213f73906c..786453dd59 100644 --- a/input.h +++ b/input.h @@ -44,6 +44,7 @@ class SwitchEvent; class TabletEvent; class TabletInputFilter; class TabletToolId; +class TabletPadId; namespace Decoration { @@ -402,9 +403,9 @@ public: virtual bool tabletToolEvent(TabletEvent *event); virtual bool tabletToolButtonEvent(uint button, bool pressed, const TabletToolId &tabletToolId); - virtual bool tabletPadButtonEvent(uint button, bool pressed, const QString &deviceSysName); - virtual bool tabletPadStripEvent(int number, int position, bool isFinger, const QString &deviceSysName); - virtual bool tabletPadRingEvent(int number, int position, bool isFinger, const QString &deviceSysName); + virtual bool tabletPadButtonEvent(uint button, bool pressed, const TabletPadId &tabletPadId); + virtual bool tabletPadStripEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId); + virtual bool tabletPadRingEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId); protected: void passToWaylandServer(QKeyEvent *event); diff --git a/input_event.h b/input_event.h index e122569a95..bbe01772c5 100644 --- a/input_event.h +++ b/input_event.h @@ -172,7 +172,13 @@ public: const QVector m_capabilities; const quint64 m_serialId; const quint64 m_uniqueId; - const QString m_tabletSysName; + void *const m_deviceGroupData; +}; + +class TabletPadId +{ +public: + void *data; }; class TabletEvent : public QTabletEvent diff --git a/input_event_spy.cpp b/input_event_spy.cpp index 6dfb1d0d43..9c5d7d27cc 100644 --- a/input_event_spy.cpp +++ b/input_event_spy.cpp @@ -122,26 +122,26 @@ void InputEventSpy::tabletToolButtonEvent(uint button, bool pressed, const Table Q_UNUSED(tabletToolId) } -void InputEventSpy::tabletPadButtonEvent(uint button, bool pressed, const QString &deviceSysName) +void InputEventSpy::tabletPadButtonEvent(uint button, bool pressed, const TabletPadId &tabletPadId) { Q_UNUSED(button) Q_UNUSED(pressed) - Q_UNUSED(deviceSysName) + Q_UNUSED(tabletPadId) } -void InputEventSpy::tabletPadStripEvent(int number, int position, bool isFinger, const QString &deviceSysName) +void InputEventSpy::tabletPadStripEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId) { Q_UNUSED(number) Q_UNUSED(position) Q_UNUSED(isFinger) - Q_UNUSED(deviceSysName) + Q_UNUSED(tabletPadId) } -void InputEventSpy::tabletPadRingEvent(int number, int position, bool isFinger, const QString &deviceSysName) +void InputEventSpy::tabletPadRingEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId) { Q_UNUSED(number) Q_UNUSED(position) Q_UNUSED(isFinger) - Q_UNUSED(deviceSysName) + Q_UNUSED(tabletPadId) } } diff --git a/input_event_spy.h b/input_event_spy.h index bac6a52df8..a82fd9fdff 100644 --- a/input_event_spy.h +++ b/input_event_spy.h @@ -24,6 +24,7 @@ class WheelEvent; class SwitchEvent; class TabletEvent; class TabletToolId; +class TabletPadId; /** * Base class for spying on input events inside InputRedirection. @@ -77,9 +78,9 @@ public: virtual void tabletToolEvent(TabletEvent *event); virtual void tabletToolButtonEvent(uint button, bool pressed, const TabletToolId &tabletToolId); - virtual void tabletPadButtonEvent(uint button, bool pressed, const QString &deviceSysName); - virtual void tabletPadStripEvent(int number, int position, bool isFinger, const QString &deviceSysName); - virtual void tabletPadRingEvent(int number, int position, bool isFinger, const QString &deviceSysName); + virtual void tabletPadButtonEvent(uint button, bool pressed, const TabletPadId &tabletPadId); + virtual void tabletPadStripEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId); + virtual void tabletPadRingEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId); }; diff --git a/libinput/connection.cpp b/libinput/connection.cpp index c86d632737..cfec8c7829 100644 --- a/libinput/connection.cpp +++ b/libinput/connection.cpp @@ -16,6 +16,8 @@ #include "../abstract_wayland_output.h" #include "../main.h" #include "../platform.h" +#include "../workspace.h" +#include "../abstract_client.h" #include "../screens.h" #endif @@ -271,7 +273,7 @@ QPointF devicePointToGlobalPosition(const QPointF &devicePos, const AbstractWayl } #endif -KWin::TabletToolId createTabletId(libinput_tablet_tool *tool, const QString &sysName) +KWin::TabletToolId createTabletId(libinput_tablet_tool *tool, void *userData) { auto serial = libinput_tablet_tool_get_serial(tool); auto toolId = libinput_tablet_tool_get_tool_id(tool); @@ -324,7 +326,7 @@ KWin::TabletToolId createTabletId(libinput_tablet_tool *tool, const QString &sys if (libinput_tablet_tool_has_wheel(tool)) { capabilities << InputRedirection::Wheel; } - return {toolType, capabilities, serial, toolId, sysName}; + return {toolType, capabilities, serial, toolId, userData}; } void Connection::processEvents() @@ -574,8 +576,9 @@ void Connection::processEvents() } #ifndef KWIN_BUILD_TESTING + auto client = workspace()->activeClient(); const auto *output = static_cast( - kwinApp()->platform()->enabledOutputs()[tte->device()->screenId()]); + kwinApp()->platform()->enabledOutputs()[client->screen()]); const QPointF globalPos = devicePointToGlobalPosition(tte->transformedPosition(output->modeSize()), output); @@ -585,21 +588,21 @@ void Connection::processEvents() emit tabletToolEvent(tabletEventType, globalPos, tte->pressure(), tte->xTilt(), tte->yTilt(), tte->rotation(), - tte->isTipDown(), tte->isNearby(), createTabletId(tte->tool(), event->device()->sysName()), tte->time()); + tte->isTipDown(), tte->isNearby(), createTabletId(tte->tool(), event->device()->groupUserData()), tte->time()); break; } case LIBINPUT_EVENT_TABLET_TOOL_BUTTON: { auto *tabletEvent = static_cast(event.data()); emit tabletToolButtonEvent(tabletEvent->buttonId(), tabletEvent->isButtonPressed(), - createTabletId(tabletEvent->tool(), event->device()->sysName())); + createTabletId(tabletEvent->tool(), event->device()->groupUserData())); break; } case LIBINPUT_EVENT_TABLET_PAD_BUTTON: { auto *tabletEvent = static_cast(event.data()); emit tabletPadButtonEvent(tabletEvent->buttonId(), tabletEvent->isButtonPressed(), - event->device()->sysName()); + { event->device()->groupUserData() }); break; } case LIBINPUT_EVENT_TABLET_PAD_RING: { @@ -607,18 +610,16 @@ void Connection::processEvents() tabletEvent->position(); emit tabletPadRingEvent(tabletEvent->number(), tabletEvent->position(), - tabletEvent->source() == - LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER, - event->device()->sysName()); + tabletEvent->source() == LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER, + { event->device()->groupUserData() }); break; } case LIBINPUT_EVENT_TABLET_PAD_STRIP: { auto *tabletEvent = static_cast(event.data()); emit tabletPadStripEvent(tabletEvent->number(), tabletEvent->position(), - tabletEvent->source() == - LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER, - event->device()->sysName()); + tabletEvent->source() == LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER, + { event->device()->groupUserData() }); break; } default: diff --git a/libinput/connection.h b/libinput/connection.h index ba2de82f60..bc79d94faa 100644 --- a/libinput/connection.h +++ b/libinput/connection.h @@ -125,9 +125,9 @@ Q_SIGNALS: bool tipNear, const TabletToolId &tabletToolId, quint32 time); void tabletToolButtonEvent(uint button, bool isPressed, const TabletToolId &tabletToolId); - void tabletPadButtonEvent(uint button, bool isPressed, const QString &sysName); - void tabletPadStripEvent(int number, int position, bool isFinger, const QString &sysName); - void tabletPadRingEvent(int number, int position, bool isFinger, const QString &sysName); + void tabletPadButtonEvent(uint button, bool isPressed, const TabletPadId &tabletPadId); + void tabletPadStripEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId); + void tabletPadRingEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId); void eventsRead(); diff --git a/libinput/device.cpp b/libinput/device.cpp index 6687ff5435..690af2acb6 100644 --- a/libinput/device.cpp +++ b/libinput/device.cpp @@ -433,6 +433,13 @@ int Device::ringsCount() const return libinput_device_tablet_pad_get_num_rings(m_device); } +void *Device::groupUserData() const +{ + auto deviceGroup = libinput_device_get_device_group(m_device); + return libinput_device_group_get_user_data(deviceGroup); +} + + #define CONFIG(method, condition, function, variable, key) \ void Device::method(bool set) \ { \ diff --git a/libinput/device.h b/libinput/device.h index 593f1c5853..380b12b8b7 100644 --- a/libinput/device.h +++ b/libinput/device.h @@ -474,6 +474,8 @@ public: int stripsCount() const; int ringsCount() const; + void *groupUserData() const; + /** * All created Devices */ diff --git a/tablet_input.cpp b/tablet_input.cpp index 5222071dc7..d6569bdfc6 100644 --- a/tablet_input.cpp +++ b/tablet_input.cpp @@ -95,30 +95,30 @@ void KWin::TabletInputRedirection::tabletToolButtonEvent(uint button, bool isPre } void KWin::TabletInputRedirection::tabletPadButtonEvent(uint button, bool isPressed, - const QString &deviceSysName) + const TabletPadId &tabletPadId) { input()->processSpies(std::bind( &InputEventSpy::tabletPadButtonEvent, - std::placeholders::_1, button, isPressed, deviceSysName)); + std::placeholders::_1, button, isPressed, tabletPadId)); input()->processFilters(std::bind( &InputEventFilter::tabletPadButtonEvent, - std::placeholders::_1, button, isPressed, deviceSysName)); + std::placeholders::_1, button, isPressed, tabletPadId)); } void KWin::TabletInputRedirection::tabletPadStripEvent(int number, int position, bool isFinger, - const QString &deviceSysName) + const TabletPadId &tabletPadId) { input()->processSpies(std::bind( &InputEventSpy::tabletPadStripEvent, - std::placeholders::_1, number, position, isFinger, deviceSysName)); + std::placeholders::_1, number, position, isFinger, tabletPadId)); input()->processFilters(std::bind( &InputEventFilter::tabletPadStripEvent, - std::placeholders::_1, number, position, isFinger, deviceSysName)); + std::placeholders::_1, number, position, isFinger, tabletPadId)); } void KWin::TabletInputRedirection::tabletPadRingEvent(int number, int position, bool isFinger, - const QString &deviceSysName) + const TabletPadId &tabletPadId) { input()->processSpies(std::bind( &InputEventSpy::tabletPadRingEvent, - std::placeholders::_1, number, position, isFinger, deviceSysName)); + std::placeholders::_1, number, position, isFinger, tabletPadId)); input()->processFilters(std::bind( &InputEventFilter::tabletPadRingEvent, - std::placeholders::_1, number, position, isFinger, deviceSysName)); + std::placeholders::_1, number, position, isFinger, tabletPadId)); } void TabletInputRedirection::cleanupDecoration(Decoration::DecoratedClientImpl *old, diff --git a/tablet_input.h b/tablet_input.h index 6c49b9bc5a..ad529138b5 100644 --- a/tablet_input.h +++ b/tablet_input.h @@ -46,9 +46,9 @@ public: quint32 time); void tabletToolButtonEvent(uint button, bool isPressed, const TabletToolId &tabletToolId); - void tabletPadButtonEvent(uint button, bool isPressed, const QString &deviceSysName); - void tabletPadStripEvent(int number, int position, bool isFinger, const QString &deviceSysName); - void tabletPadRingEvent(int number, int position, bool isFinger, const QString &deviceSysName); + void tabletPadButtonEvent(uint button, bool isPressed, const TabletPadId &tabletPadId); + void tabletPadStripEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId); + void tabletPadRingEvent(int number, int position, bool isFinger, const TabletPadId &tabletPadId); bool positionValid() const override {