From f48653cf0edbae5943e82e233f54cf24316a63be Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 3 Jul 2024 19:12:17 +0200 Subject: [PATCH] session: Tablet support woo --- include/aquamarine/backend/Backend.hpp | 6 +- include/aquamarine/backend/Session.hpp | 81 +++++- include/aquamarine/buffer/Buffer.hpp | 4 +- include/aquamarine/input/Input.hpp | 158 +++++++++++- include/aquamarine/misc/Attachment.hpp | 2 +- include/aquamarine/output/Output.hpp | 4 +- src/backend/Session.cpp | 325 ++++++++++++++++++++++++- src/input/Input.cpp | 12 + src/utils/Shared.cpp | 6 +- 9 files changed, 564 insertions(+), 34 deletions(-) diff --git a/include/aquamarine/backend/Backend.hpp b/include/aquamarine/backend/Backend.hpp index b2c2432..1f9d3f8 100644 --- a/include/aquamarine/backend/Backend.hpp +++ b/include/aquamarine/backend/Backend.hpp @@ -11,13 +11,13 @@ #include "Session.hpp" namespace Aquamarine { - enum eBackendType { + enum eBackendType : uint32_t { AQ_BACKEND_WAYLAND = 0, AQ_BACKEND_DRM, AQ_BACKEND_HEADLESS, }; - enum eBackendRequestMode { + enum eBackendRequestMode : uint32_t { /* Require the provided backend, will error out if it's not available. */ @@ -32,7 +32,7 @@ namespace Aquamarine { AQ_BACKEND_REQUEST_FALLBACK, }; - enum eBackendLogLevel { + enum eBackendLogLevel : uint32_t { AQ_LOG_TRACE = 0, AQ_LOG_DEBUG, AQ_LOG_WARNING, diff --git a/include/aquamarine/backend/Session.hpp b/include/aquamarine/backend/Session.hpp index 2236e84..313cd3f 100644 --- a/include/aquamarine/backend/Session.hpp +++ b/include/aquamarine/backend/Session.hpp @@ -13,6 +13,7 @@ struct libseat; struct libinput; struct libinput_event; struct libinput_device; +struct libinput_tablet_tool; namespace Aquamarine { class CBackend; @@ -34,7 +35,7 @@ namespace Aquamarine { dev_t dev; std::string path; - enum eChangeEventType { + enum eChangeEventType : uint32_t { AQ_SESSION_EVENT_CHANGE_HOTPLUG = 0, AQ_SESSION_EVENT_CHANGE_LEASE, }; @@ -69,6 +70,8 @@ namespace Aquamarine { private: Hyprutils::Memory::CWeakPointer device; + + friend class CLibinputDevice; }; class CLibinputMouse : public IPointer { @@ -83,6 +86,8 @@ namespace Aquamarine { private: Hyprutils::Memory::CWeakPointer device; + + friend class CLibinputDevice; }; class CLibinputTouch : public ITouch { @@ -97,6 +102,8 @@ namespace Aquamarine { private: Hyprutils::Memory::CWeakPointer device; + + friend class CLibinputDevice; }; class CLibinputSwitch : public ISwitch { @@ -114,6 +121,55 @@ namespace Aquamarine { private: Hyprutils::Memory::CWeakPointer device; + + friend class CLibinputDevice; + }; + + class CLibinputTablet : public ITablet { + public: + CLibinputTablet(Hyprutils::Memory::CSharedPointer dev); + virtual ~CLibinputTablet() { + ; + } + + virtual libinput_device* getLibinputHandle(); + virtual const std::string& getName(); + + private: + Hyprutils::Memory::CWeakPointer device; + + friend class CLibinputDevice; + }; + + class CLibinputTabletTool : public ITabletTool { + public: + CLibinputTabletTool(Hyprutils::Memory::CSharedPointer dev, libinput_tablet_tool* tool); + virtual ~CLibinputTabletTool(); + + virtual libinput_device* getLibinputHandle(); + virtual const std::string& getName(); + + private: + Hyprutils::Memory::CWeakPointer device; + libinput_tablet_tool* libinputTool = nullptr; + + friend class CLibinputDevice; + }; + + class CLibinputTabletPad : public ITabletPad { + public: + CLibinputTabletPad(Hyprutils::Memory::CSharedPointer dev); + virtual ~CLibinputTabletPad(); + + virtual libinput_device* getLibinputHandle(); + virtual const std::string& getName(); + + private: + Hyprutils::Memory::CWeakPointer device; + + Hyprutils::Memory::CSharedPointer createGroupFromID(int id); + + friend class CLibinputDevice; }; class CLibinputDevice { @@ -121,17 +177,22 @@ namespace Aquamarine { CLibinputDevice(libinput_device* device, Hyprutils::Memory::CWeakPointer session_); ~CLibinputDevice(); - void init(); + void init(); - libinput_device* device; - Hyprutils::Memory::CWeakPointer self; - Hyprutils::Memory::CWeakPointer session; - std::string name; + libinput_device* device; + Hyprutils::Memory::CWeakPointer self; + Hyprutils::Memory::CWeakPointer session; + std::string name; - Hyprutils::Memory::CSharedPointer keyboard; - Hyprutils::Memory::CSharedPointer mouse; - Hyprutils::Memory::CSharedPointer touch; - Hyprutils::Memory::CSharedPointer switchy; // :) + Hyprutils::Memory::CSharedPointer keyboard; + Hyprutils::Memory::CSharedPointer mouse; + Hyprutils::Memory::CSharedPointer touch; + Hyprutils::Memory::CSharedPointer switchy; // :) + Hyprutils::Memory::CSharedPointer tablet; + Hyprutils::Memory::CSharedPointer tabletPad; + std::vector> tabletTools; + + Hyprutils::Memory::CSharedPointer toolFrom(libinput_tablet_tool* tool); }; class CSession { diff --git a/include/aquamarine/buffer/Buffer.hpp b/include/aquamarine/buffer/Buffer.hpp index 4fe2309..b9356dc 100644 --- a/include/aquamarine/buffer/Buffer.hpp +++ b/include/aquamarine/buffer/Buffer.hpp @@ -7,11 +7,11 @@ #include "../misc/Attachment.hpp" namespace Aquamarine { - enum eBufferCapability { + enum eBufferCapability : uint32_t { BUFFER_CAPABILITY_DATAPTR = (1 << 0), }; - enum eBufferType { + enum eBufferType : uint32_t { BUFFER_TYPE_DMABUF = 0, BUFFER_TYPE_SHM, BUFFER_TYPE_MISC, diff --git a/include/aquamarine/input/Input.hpp b/include/aquamarine/input/Input.hpp index 146717b..5486913 100644 --- a/include/aquamarine/input/Input.hpp +++ b/include/aquamarine/input/Input.hpp @@ -6,6 +6,8 @@ struct libinput_device; namespace Aquamarine { + class ITabletTool; + class IKeyboard { public: virtual ~IKeyboard() { @@ -41,19 +43,19 @@ namespace Aquamarine { virtual libinput_device* getLibinputHandle(); virtual const std::string& getName() = 0; - enum ePointerAxis { + enum ePointerAxis : uint32_t { AQ_POINTER_AXIS_VERTICAL = 0, AQ_POINTER_AXIS_HORIZONTAL, }; - enum ePointerAxisSource { + enum ePointerAxisSource : uint32_t { AQ_POINTER_AXIS_SOURCE_WHEEL = 0, AQ_POINTER_AXIS_SOURCE_FINGER, AQ_POINTER_AXIS_SOURCE_CONTINUOUS, AQ_POINTER_AXIS_SOURCE_TILT, }; - enum ePointerAxisRelativeDirection { + enum ePointerAxisRelativeDirection : uint32_t { AQ_POINTER_AXIS_RELATIVE_IDENTICAL = 0, AQ_POINTER_AXIS_RELATIVE_INVERTED, }; @@ -198,7 +200,7 @@ namespace Aquamarine { virtual libinput_device* getLibinputHandle(); virtual const std::string& getName() = 0; - enum eSwitchType { + enum eSwitchType : uint32_t { AQ_SWITCH_TYPE_UNKNOWN = 0, AQ_SWITCH_TYPE_LID, AQ_SWITCH_TYPE_TABLET_MODE, @@ -216,18 +218,107 @@ namespace Aquamarine { } events; }; + enum eTabletToolAxes : uint32_t { + AQ_TABLET_TOOL_AXIS_X = (1 << 0), + AQ_TABLET_TOOL_AXIS_Y = (1 << 1), + AQ_TABLET_TOOL_AXIS_DISTANCE = (1 << 2), + AQ_TABLET_TOOL_AXIS_PRESSURE = (1 << 3), + AQ_TABLET_TOOL_AXIS_TILT_X = (1 << 4), + AQ_TABLET_TOOL_AXIS_TILT_Y = (1 << 5), + AQ_TABLET_TOOL_AXIS_ROTATION = (1 << 6), + AQ_TABLET_TOOL_AXIS_SLIDER = (1 << 7), + AQ_TABLET_TOOL_AXIS_WHEEL = (1 << 8), + }; + class ITablet { public: - // FIXME: + virtual ~ITablet() { + events.destroy.emit(); + } + + virtual libinput_device* getLibinputHandle(); + virtual const std::string& getName() = 0; + + uint16_t usbVendorID = 0, usbProductID = 0; + Hyprutils::Math::Vector2D physicalSize; // mm + std::vector paths; + + struct SAxisEvent { + Hyprutils::Memory::CSharedPointer tool; + + uint32_t timeMs = 0, updatedAxes = 0; + Hyprutils::Math::Vector2D absolute; + Hyprutils::Math::Vector2D delta; + Hyprutils::Math::Vector2D tilt; + double pressure = 0.0, distance = 0.0, rotation = 0.0, slider = 0.0, wheelDelta = 0.0; + }; + + struct SProximityEvent { + Hyprutils::Memory::CSharedPointer tool; + + uint32_t timeMs = 0; + Hyprutils::Math::Vector2D absolute; + bool in = false; + }; + + struct STipEvent { + Hyprutils::Memory::CSharedPointer tool; + + uint32_t timeMs = 0; + Hyprutils::Math::Vector2D absolute; + bool down = false; + }; + + struct SButtonEvent { + Hyprutils::Memory::CSharedPointer tool; + + uint32_t timeMs = 0, button = 0; + bool down = false; + }; struct { + Hyprutils::Signal::CSignal axis; + Hyprutils::Signal::CSignal proximity; + Hyprutils::Signal::CSignal tip; + Hyprutils::Signal::CSignal button; Hyprutils::Signal::CSignal destroy; } events; }; class ITabletTool { public: - // FIXME: + virtual ~ITabletTool() { + events.destroy.emit(); + } + + virtual libinput_device* getLibinputHandle(); + virtual const std::string& getName() = 0; + + enum eTabletToolType : uint32_t { + AQ_TABLET_TOOL_TYPE_INVALID = 0, + AQ_TABLET_TOOL_TYPE_PEN, + AQ_TABLET_TOOL_TYPE_ERASER, + AQ_TABLET_TOOL_TYPE_BRUSH, + AQ_TABLET_TOOL_TYPE_PENCIL, + AQ_TABLET_TOOL_TYPE_AIRBRUSH, + AQ_TABLET_TOOL_TYPE_MOUSE, + AQ_TABLET_TOOL_TYPE_LENS, + AQ_TABLET_TOOL_TYPE_TOTEM, + }; + + eTabletToolType type = AQ_TABLET_TOOL_TYPE_INVALID; + uint64_t serial = 0, id = 0; + + enum eTabletToolCapabilities : uint32_t { + AQ_TABLET_TOOL_CAPABILITY_TILT = (1 << 0), + AQ_TABLET_TOOL_CAPABILITY_PRESSURE = (1 << 1), + AQ_TABLET_TOOL_CAPABILITY_DISTANCE = (1 << 2), + AQ_TABLET_TOOL_CAPABILITY_ROTATION = (1 << 3), + AQ_TABLET_TOOL_CAPABILITY_SLIDER = (1 << 4), + AQ_TABLET_TOOL_CAPABILITY_WHEEL = (1 << 5), + }; + + uint32_t capabilities = 0; // enum eTabletToolCapabilities struct { Hyprutils::Signal::CSignal destroy; @@ -236,10 +327,63 @@ namespace Aquamarine { class ITabletPad { public: - // FIXME: + virtual ~ITabletPad() { + events.destroy.emit(); + } + + struct STabletPadGroup { + std::vector buttons, strips, rings; + uint16_t modes = 0; + }; + + virtual libinput_device* getLibinputHandle(); + virtual const std::string& getName() = 0; + + uint16_t buttons = 0, rings = 0, strips = 0; + + std::vector paths; + std::vector> groups; + + // + + struct SButtonEvent { + uint32_t timeMs = 0, button = 0; + bool down = false; + uint16_t mode = 0, group = 0; + }; + + enum eTabletPadRingSource : uint16_t { + AQ_TABLET_PAD_RING_SOURCE_UNKNOWN = 0, + AQ_TABLET_PAD_RING_SOURCE_FINGER, + }; + + enum eTabletPadStripSource : uint16_t { + AQ_TABLET_PAD_STRIP_SOURCE_UNKNOWN = 0, + AQ_TABLET_PAD_STRIP_SOURCE_FINGER, + }; + + struct SRingEvent { + uint32_t timeMs = 0; + eTabletPadRingSource source = AQ_TABLET_PAD_RING_SOURCE_UNKNOWN; + uint16_t ring = 0; + double pos = 0.0; + uint16_t mode = 0; + }; + + struct SStripEvent { + uint32_t timeMs = 0; + eTabletPadStripSource source = AQ_TABLET_PAD_STRIP_SOURCE_UNKNOWN; + uint16_t strip = 0; + double pos = 0.0; + uint16_t mode = 0; + }; struct { Hyprutils::Signal::CSignal destroy; + Hyprutils::Signal::CSignal button; + Hyprutils::Signal::CSignal ring; + Hyprutils::Signal::CSignal strip; + Hyprutils::Signal::CSignal attach; } events; }; } \ No newline at end of file diff --git a/include/aquamarine/misc/Attachment.hpp b/include/aquamarine/misc/Attachment.hpp index eb21b2c..94cb47e 100644 --- a/include/aquamarine/misc/Attachment.hpp +++ b/include/aquamarine/misc/Attachment.hpp @@ -4,7 +4,7 @@ #include namespace Aquamarine { - enum eAttachmentType { + enum eAttachmentType : uint32_t { AQ_ATTACHMENT_DRM_BUFFER = 0, AQ_ATTACHMENT_DRM_KMS_UNIMPORTABLE, }; diff --git a/include/aquamarine/output/Output.hpp b/include/aquamarine/output/Output.hpp index a4a5f6b..8bb6e18 100644 --- a/include/aquamarine/output/Output.hpp +++ b/include/aquamarine/output/Output.hpp @@ -21,12 +21,12 @@ namespace Aquamarine { std::optional modeInfo; // if this is a drm mode, this will be populated. }; - enum eOutputPresentationMode { + enum eOutputPresentationMode : uint32_t { AQ_OUTPUT_PRESENTATION_VSYNC = 0, AQ_OUTPUT_PRESENTATION_IMMEDIATE, // likely tearing }; - enum eSubpixelMode { + enum eSubpixelMode : uint32_t { AQ_SUBPIXEL_UNKNOWN = 0, AQ_SUBPIXEL_NONE, AQ_SUBPIXEL_HORIZONTAL_RGB, diff --git a/src/backend/Session.cpp b/src/backend/Session.cpp index cd9ea6b..5ec4b48 100644 --- a/src/backend/Session.cpp +++ b/src/backend/Session.cpp @@ -8,6 +8,7 @@ extern "C" { #include #include #include +#include } using namespace Aquamarine; @@ -270,8 +271,14 @@ void Aquamarine::CSession::onReady() { backend->events.newTouch.emit(SP(d->touch)); if (d->switchy) backend->events.newSwitch.emit(SP(d->touch)); + if (d->tablet) + backend->events.newTablet.emit(SP(d->tablet)); + if (d->tabletPad) + backend->events.newTabletPad.emit(SP(d->tabletPad)); - // FIXME: other devices. + for (auto& t : d->tabletTools) { + backend->events.newTabletTool.emit(SP(t)); + } } } @@ -400,7 +407,8 @@ void Aquamarine::CSession::handleLibinputEvent(libinput_event* e) { return; } - auto hlDevice = ((CLibinputDevice*)data)->self.lock(); + auto hlDevice = ((CLibinputDevice*)data)->self.lock(); + bool destroyTool = false; switch (eventType) { case LIBINPUT_EVENT_DEVICE_ADDED: @@ -640,7 +648,145 @@ void Aquamarine::CSession::handleLibinputEvent(libinput_event* e) { // --------- tbalet - // FIXME: other events + case LIBINPUT_EVENT_TABLET_PAD_BUTTON: { + auto tpe = libinput_event_get_tablet_pad_event(e); + + hlDevice->tabletPad->events.button.emit(ITabletPad::SButtonEvent{ + .timeMs = (uint32_t)(libinput_event_tablet_pad_get_time_usec(tpe) / 1000), + .button = libinput_event_tablet_pad_get_button_number(tpe), + .down = libinput_event_tablet_pad_get_button_state(tpe) == LIBINPUT_BUTTON_STATE_PRESSED, + .mode = (uint16_t)libinput_event_tablet_pad_get_mode(tpe), + .group = (uint16_t)libinput_tablet_pad_mode_group_get_index(libinput_event_tablet_pad_get_mode_group(tpe)), + }); + break; + } + case LIBINPUT_EVENT_TABLET_PAD_RING: { + auto tpe = libinput_event_get_tablet_pad_event(e); + + hlDevice->tabletPad->events.ring.emit(ITabletPad::SRingEvent{ + .timeMs = (uint32_t)(libinput_event_tablet_pad_get_time_usec(tpe) / 1000), + .source = libinput_event_tablet_pad_get_ring_source(tpe) == LIBINPUT_TABLET_PAD_RING_SOURCE_UNKNOWN ? ITabletPad::AQ_TABLET_PAD_RING_SOURCE_UNKNOWN : + ITabletPad::AQ_TABLET_PAD_RING_SOURCE_FINGER, + .ring = (uint16_t)libinput_event_tablet_pad_get_ring_number(tpe), + .pos = libinput_event_tablet_pad_get_ring_position(tpe), + .mode = (uint16_t)libinput_event_tablet_pad_get_mode(tpe), + }); + break; + } + case LIBINPUT_EVENT_TABLET_PAD_STRIP: { + auto tpe = libinput_event_get_tablet_pad_event(e); + + hlDevice->tabletPad->events.strip.emit(ITabletPad::SStripEvent{ + .timeMs = (uint32_t)(libinput_event_tablet_pad_get_time_usec(tpe) / 1000), + .source = libinput_event_tablet_pad_get_strip_source(tpe) == LIBINPUT_TABLET_PAD_STRIP_SOURCE_UNKNOWN ? ITabletPad::AQ_TABLET_PAD_STRIP_SOURCE_UNKNOWN : + ITabletPad::AQ_TABLET_PAD_STRIP_SOURCE_FINGER, + .strip = (uint16_t)libinput_event_tablet_pad_get_strip_number(tpe), + .pos = libinput_event_tablet_pad_get_strip_position(tpe), + .mode = (uint16_t)libinput_event_tablet_pad_get_mode(tpe), + }); + break; + } + + case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY: { + auto tte = libinput_event_get_tablet_tool_event(e); + auto tool = hlDevice->toolFrom(libinput_event_tablet_tool_get_tool(tte)); + + hlDevice->tablet->events.proximity.emit(ITablet::SProximityEvent{ + .tool = tool, + .timeMs = (uint32_t)(libinput_event_tablet_tool_get_time_usec(tte) / 1000), + .absolute = {libinput_event_tablet_tool_get_x_transformed(tte, 1), libinput_event_tablet_tool_get_y_transformed(tte, 1)}, + .in = libinput_event_tablet_tool_get_proximity_state(tte) == LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN, + }); + + destroyTool = !libinput_tablet_tool_is_unique(libinput_event_tablet_tool_get_tool(tte)) && + libinput_event_tablet_tool_get_proximity_state(tte) == LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT; + + if (libinput_event_tablet_tool_get_proximity_state(tte) == LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT) { + std::erase(hlDevice->tabletTools, tool); + break; + } + + // fallthrough. If this is proximity in, also process axis. + } + case LIBINPUT_EVENT_TABLET_TOOL_AXIS: { + auto tte = libinput_event_get_tablet_tool_event(e); + auto tool = hlDevice->toolFrom(libinput_event_tablet_tool_get_tool(tte)); + + ITablet::SAxisEvent event = { + .tool = tool, + .timeMs = (uint32_t)(libinput_event_tablet_tool_get_time_usec(tte) / 1000), + }; + + if (libinput_event_tablet_tool_x_has_changed(tte)) { + event.updatedAxes |= AQ_TABLET_TOOL_AXIS_X; + event.absolute.x = libinput_event_tablet_tool_get_x_transformed(tte, 1); + event.delta.x = libinput_event_tablet_tool_get_dx(tte); + } + if (libinput_event_tablet_tool_y_has_changed(tte)) { + event.updatedAxes |= AQ_TABLET_TOOL_AXIS_Y; + event.absolute.y = libinput_event_tablet_tool_get_y_transformed(tte, 1); + event.delta.y = libinput_event_tablet_tool_get_dy(tte); + } + if (libinput_event_tablet_tool_pressure_has_changed(tte)) { + event.updatedAxes |= AQ_TABLET_TOOL_AXIS_PRESSURE; + event.pressure = libinput_event_tablet_tool_get_pressure(tte); + } + if (libinput_event_tablet_tool_distance_has_changed(tte)) { + event.updatedAxes |= AQ_TABLET_TOOL_AXIS_DISTANCE; + event.distance = libinput_event_tablet_tool_get_distance(tte); + } + if (libinput_event_tablet_tool_tilt_x_has_changed(tte)) { + event.updatedAxes |= AQ_TABLET_TOOL_AXIS_TILT_X; + event.tilt.x = libinput_event_tablet_tool_get_tilt_x(tte); + } + if (libinput_event_tablet_tool_tilt_y_has_changed(tte)) { + event.updatedAxes |= AQ_TABLET_TOOL_AXIS_TILT_Y; + event.tilt.y = libinput_event_tablet_tool_get_tilt_y(tte); + } + if (libinput_event_tablet_tool_rotation_has_changed(tte)) { + event.updatedAxes |= AQ_TABLET_TOOL_AXIS_ROTATION; + event.rotation = libinput_event_tablet_tool_get_rotation(tte); + } + if (libinput_event_tablet_tool_slider_has_changed(tte)) { + event.updatedAxes |= AQ_TABLET_TOOL_AXIS_SLIDER; + event.slider = libinput_event_tablet_tool_get_slider_position(tte); + } + if (libinput_event_tablet_tool_wheel_has_changed(tte)) { + event.updatedAxes |= AQ_TABLET_TOOL_AXIS_WHEEL; + event.wheelDelta = libinput_event_tablet_tool_get_wheel_delta(tte); + } + + hlDevice->tablet->events.axis.emit(event); + + if (destroyTool) + std::erase(hlDevice->tabletTools, tool); + + break; + } + case LIBINPUT_EVENT_TABLET_TOOL_TIP: { + auto tte = libinput_event_get_tablet_tool_event(e); + auto tool = hlDevice->toolFrom(libinput_event_tablet_tool_get_tool(tte)); + + hlDevice->tablet->events.tip.emit(ITablet::STipEvent{ + .tool = tool, + .timeMs = (uint32_t)(libinput_event_tablet_tool_get_time_usec(tte) / 1000), + .absolute = {libinput_event_tablet_tool_get_x_transformed(tte, 1), libinput_event_tablet_tool_get_y_transformed(tte, 1)}, + .down = libinput_event_tablet_tool_get_tip_state(tte) == LIBINPUT_TABLET_TOOL_TIP_DOWN, + }); + break; + } + case LIBINPUT_EVENT_TABLET_TOOL_BUTTON: { + auto tte = libinput_event_get_tablet_tool_event(e); + auto tool = hlDevice->toolFrom(libinput_event_tablet_tool_get_tool(tte)); + + hlDevice->tablet->events.button.emit(ITablet::SButtonEvent{ + .tool = tool, + .timeMs = (uint32_t)(libinput_event_tablet_tool_get_time_usec(tte) / 1000), + .button = libinput_event_tablet_tool_get_button(tte), + .down = libinput_event_tablet_tool_get_button_state(tte) == LIBINPUT_BUTTON_STATE_PRESSED, + }); + break; + } default: break; } @@ -686,13 +832,50 @@ void Aquamarine::CLibinputDevice::init() { session->backend->events.newSwitch.emit(SP(switchy)); } - // FIXME: other devices + if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_TABLET_TOOL)) { + tablet = makeShared(self.lock()); + if (session->backend->ready) + session->backend->events.newTablet.emit(SP(tablet)); + } + + if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_TABLET_PAD)) { + tabletPad = makeShared(self.lock()); + if (session->backend->ready) + session->backend->events.newTabletPad.emit(SP(tabletPad)); + } } Aquamarine::CLibinputDevice::~CLibinputDevice() { libinput_device_unref(device); } +SP Aquamarine::CLibinputDevice::toolFrom(libinput_tablet_tool* tool) { + for (auto& t : tabletTools) { + if (t->libinputTool == tool) + return t; + } + + auto newt = makeShared(self.lock(), tool); + tabletTools.emplace_back(newt); + if (session->backend->ready) + session->backend->events.newTabletTool.emit(SP(newt)); + return newt; +} + +static ITabletTool::eTabletToolType aqTypeFromLibinput(libinput_tablet_tool_type value) { + switch (value) { + case LIBINPUT_TABLET_TOOL_TYPE_PEN: return ITabletTool::AQ_TABLET_TOOL_TYPE_PEN; + case LIBINPUT_TABLET_TOOL_TYPE_ERASER: return ITabletTool::AQ_TABLET_TOOL_TYPE_ERASER; + case LIBINPUT_TABLET_TOOL_TYPE_BRUSH: return ITabletTool::AQ_TABLET_TOOL_TYPE_BRUSH; + case LIBINPUT_TABLET_TOOL_TYPE_PENCIL: return ITabletTool::AQ_TABLET_TOOL_TYPE_PENCIL; + case LIBINPUT_TABLET_TOOL_TYPE_AIRBRUSH: return ITabletTool::AQ_TABLET_TOOL_TYPE_AIRBRUSH; + case LIBINPUT_TABLET_TOOL_TYPE_MOUSE: return ITabletTool::AQ_TABLET_TOOL_TYPE_MOUSE; + case LIBINPUT_TABLET_TOOL_TYPE_LENS: return ITabletTool::AQ_TABLET_TOOL_TYPE_LENS; + case LIBINPUT_TABLET_TOOL_TYPE_TOTEM: return ITabletTool::AQ_TABLET_TOOL_TYPE_TOTEM; + } + return ITabletTool::AQ_TABLET_TOOL_TYPE_INVALID; +} + Aquamarine::CLibinputKeyboard::CLibinputKeyboard(SP dev) : device(dev) {} libinput_device* Aquamarine::CLibinputKeyboard::getLibinputHandle() { @@ -759,4 +942,136 @@ const std::string& Aquamarine::CLibinputSwitch::getName() { if (!device) return AQ_UNKNOWN_DEVICE_NAME; return device->name; -} \ No newline at end of file +} + +Aquamarine::CLibinputTablet::CLibinputTablet(Hyprutils::Memory::CSharedPointer dev) : device(dev) { + if (libinput_device_get_id_bustype(device->device) == BUS_USB) { + usbVendorID = libinput_device_get_id_vendor(device->device); + usbProductID = libinput_device_get_id_product(device->device); + } + + double w = 0, h = 0; + libinput_device_get_size(dev->device, &w, &h); + physicalSize = {w, h}; + + auto udevice = libinput_device_get_udev_device(device->device); + paths.emplace_back(udev_device_get_syspath(udevice)); +} + +libinput_device* Aquamarine::CLibinputTablet::getLibinputHandle() { + if (!device) + return nullptr; + return device->device; +} + +const std::string& Aquamarine::CLibinputTablet::getName() { + if (!device) + return AQ_UNKNOWN_DEVICE_NAME; + return device->name; +} + +Aquamarine::CLibinputTabletTool::CLibinputTabletTool(Hyprutils::Memory::CSharedPointer dev, libinput_tablet_tool* tool) : device(dev), libinputTool(tool) { + type = aqTypeFromLibinput(libinput_tablet_tool_get_type(libinputTool)); + serial = libinput_tablet_tool_get_serial(libinputTool); + id = libinput_tablet_tool_get_tool_id(libinputTool); + + libinput_tablet_tool_ref(tool); + + capabilities = 0; + if (libinput_tablet_tool_has_distance(tool)) + capabilities |= AQ_TABLET_TOOL_CAPABILITY_DISTANCE; + if (libinput_tablet_tool_has_pressure(tool)) + capabilities |= AQ_TABLET_TOOL_CAPABILITY_PRESSURE; + if (libinput_tablet_tool_has_tilt(tool)) + capabilities |= AQ_TABLET_TOOL_CAPABILITY_TILT; + if (libinput_tablet_tool_has_rotation(tool)) + capabilities |= AQ_TABLET_TOOL_CAPABILITY_ROTATION; + if (libinput_tablet_tool_has_slider(tool)) + capabilities |= AQ_TABLET_TOOL_CAPABILITY_SLIDER; + if (libinput_tablet_tool_has_wheel(tool)) + capabilities |= AQ_TABLET_TOOL_CAPABILITY_WHEEL; + + libinput_tablet_tool_set_user_data(tool, this); +} + +Aquamarine::CLibinputTabletTool::~CLibinputTabletTool() { + libinput_tablet_tool_unref(libinputTool); +} + +libinput_device* Aquamarine::CLibinputTabletTool::getLibinputHandle() { + if (!device) + return nullptr; + return device->device; +} + +const std::string& Aquamarine::CLibinputTabletTool::getName() { + if (!device) + return AQ_UNKNOWN_DEVICE_NAME; + return device->name; +} + +Aquamarine::CLibinputTabletPad::CLibinputTabletPad(Hyprutils::Memory::CSharedPointer dev) : device(dev) { + buttons = libinput_device_tablet_pad_get_num_buttons(device->device); + rings = libinput_device_tablet_pad_get_num_rings(device->device); + strips = libinput_device_tablet_pad_get_num_strips(device->device); + + auto udevice = libinput_device_get_udev_device(device->device); + paths.emplace_back(udev_device_get_syspath(udevice)); + + int groupsno = libinput_device_tablet_pad_get_num_mode_groups(device->device); + for (size_t i = 0; i < groupsno; ++i) { + auto g = createGroupFromID(i); + if (g) + groups.emplace_back(g); + } +} + +Aquamarine::CLibinputTabletPad::~CLibinputTabletPad() { + int groups = libinput_device_tablet_pad_get_num_mode_groups(device->device); + for (int i = 0; i < groups; ++i) { + auto g = libinput_device_tablet_pad_get_mode_group(device->device, i); + libinput_tablet_pad_mode_group_unref(g); + } +} + +libinput_device* Aquamarine::CLibinputTabletPad::getLibinputHandle() { + if (!device) + return nullptr; + return device->device; +} + +const std::string& Aquamarine::CLibinputTabletPad::getName() { + if (!device) + return AQ_UNKNOWN_DEVICE_NAME; + return device->name; +} + +SP Aquamarine::CLibinputTabletPad::createGroupFromID(int id) { + auto libinputGroup = libinput_device_tablet_pad_get_mode_group(device->device, id); + + auto group = makeShared(); + for (size_t i = 0; i < rings; ++i) { + if (!libinput_tablet_pad_mode_group_has_ring(libinputGroup, i)) + continue; + + group->rings.push_back(i); + } + + for (size_t i = 0; i < strips; ++i) { + if (!libinput_tablet_pad_mode_group_has_strip(libinputGroup, i)) + continue; + + group->strips.push_back(i); + } + + for (size_t i = 0; i < buttons; ++i) { + if (!libinput_tablet_pad_mode_group_has_button(libinputGroup, i)) + continue; + + group->buttons.push_back(i); + } + + group->modes = libinput_tablet_pad_mode_group_get_num_modes(libinputGroup); + + return group; +} diff --git a/src/input/Input.cpp b/src/input/Input.cpp index e1266ad..a3c9450 100644 --- a/src/input/Input.cpp +++ b/src/input/Input.cpp @@ -16,6 +16,18 @@ libinput_device* Aquamarine::ISwitch::getLibinputHandle() { return nullptr; } +libinput_device* Aquamarine::ITabletTool::getLibinputHandle() { + return nullptr; +} + +libinput_device* Aquamarine::ITablet::getLibinputHandle() { + return nullptr; +} + +libinput_device* Aquamarine::ITabletPad::getLibinputHandle() { + return nullptr; +} + void Aquamarine::IKeyboard::updateLEDs(uint32_t leds) { ; } diff --git a/src/utils/Shared.cpp b/src/utils/Shared.cpp index f5d8a05..5dd7a78 100644 --- a/src/utils/Shared.cpp +++ b/src/utils/Shared.cpp @@ -6,10 +6,8 @@ bool Aquamarine::envEnabled(const std::string& env) { return e && e == std::string{"1"}; } -static bool trace = []() -> bool { - return Aquamarine::envEnabled("AQ_TRACE"); -}(); +static bool trace = []() -> bool { return Aquamarine::envEnabled("AQ_TRACE"); }(); -bool Aquamarine::isTrace() { +bool Aquamarine::isTrace() { return trace; }