session: Tablet support

woo
This commit is contained in:
Vaxry 2024-07-03 19:12:17 +02:00
parent a0cfad9ec0
commit f48653cf0e
9 changed files with 564 additions and 34 deletions

View file

@ -11,13 +11,13 @@
#include "Session.hpp" #include "Session.hpp"
namespace Aquamarine { namespace Aquamarine {
enum eBackendType { enum eBackendType : uint32_t {
AQ_BACKEND_WAYLAND = 0, AQ_BACKEND_WAYLAND = 0,
AQ_BACKEND_DRM, AQ_BACKEND_DRM,
AQ_BACKEND_HEADLESS, AQ_BACKEND_HEADLESS,
}; };
enum eBackendRequestMode { enum eBackendRequestMode : uint32_t {
/* /*
Require the provided backend, will error out if it's not available. Require the provided backend, will error out if it's not available.
*/ */
@ -32,7 +32,7 @@ namespace Aquamarine {
AQ_BACKEND_REQUEST_FALLBACK, AQ_BACKEND_REQUEST_FALLBACK,
}; };
enum eBackendLogLevel { enum eBackendLogLevel : uint32_t {
AQ_LOG_TRACE = 0, AQ_LOG_TRACE = 0,
AQ_LOG_DEBUG, AQ_LOG_DEBUG,
AQ_LOG_WARNING, AQ_LOG_WARNING,

View file

@ -13,6 +13,7 @@ struct libseat;
struct libinput; struct libinput;
struct libinput_event; struct libinput_event;
struct libinput_device; struct libinput_device;
struct libinput_tablet_tool;
namespace Aquamarine { namespace Aquamarine {
class CBackend; class CBackend;
@ -34,7 +35,7 @@ namespace Aquamarine {
dev_t dev; dev_t dev;
std::string path; std::string path;
enum eChangeEventType { enum eChangeEventType : uint32_t {
AQ_SESSION_EVENT_CHANGE_HOTPLUG = 0, AQ_SESSION_EVENT_CHANGE_HOTPLUG = 0,
AQ_SESSION_EVENT_CHANGE_LEASE, AQ_SESSION_EVENT_CHANGE_LEASE,
}; };
@ -69,6 +70,8 @@ namespace Aquamarine {
private: private:
Hyprutils::Memory::CWeakPointer<CLibinputDevice> device; Hyprutils::Memory::CWeakPointer<CLibinputDevice> device;
friend class CLibinputDevice;
}; };
class CLibinputMouse : public IPointer { class CLibinputMouse : public IPointer {
@ -83,6 +86,8 @@ namespace Aquamarine {
private: private:
Hyprutils::Memory::CWeakPointer<CLibinputDevice> device; Hyprutils::Memory::CWeakPointer<CLibinputDevice> device;
friend class CLibinputDevice;
}; };
class CLibinputTouch : public ITouch { class CLibinputTouch : public ITouch {
@ -97,6 +102,8 @@ namespace Aquamarine {
private: private:
Hyprutils::Memory::CWeakPointer<CLibinputDevice> device; Hyprutils::Memory::CWeakPointer<CLibinputDevice> device;
friend class CLibinputDevice;
}; };
class CLibinputSwitch : public ISwitch { class CLibinputSwitch : public ISwitch {
@ -114,6 +121,55 @@ namespace Aquamarine {
private: private:
Hyprutils::Memory::CWeakPointer<CLibinputDevice> device; Hyprutils::Memory::CWeakPointer<CLibinputDevice> device;
friend class CLibinputDevice;
};
class CLibinputTablet : public ITablet {
public:
CLibinputTablet(Hyprutils::Memory::CSharedPointer<CLibinputDevice> dev);
virtual ~CLibinputTablet() {
;
}
virtual libinput_device* getLibinputHandle();
virtual const std::string& getName();
private:
Hyprutils::Memory::CWeakPointer<CLibinputDevice> device;
friend class CLibinputDevice;
};
class CLibinputTabletTool : public ITabletTool {
public:
CLibinputTabletTool(Hyprutils::Memory::CSharedPointer<CLibinputDevice> dev, libinput_tablet_tool* tool);
virtual ~CLibinputTabletTool();
virtual libinput_device* getLibinputHandle();
virtual const std::string& getName();
private:
Hyprutils::Memory::CWeakPointer<CLibinputDevice> device;
libinput_tablet_tool* libinputTool = nullptr;
friend class CLibinputDevice;
};
class CLibinputTabletPad : public ITabletPad {
public:
CLibinputTabletPad(Hyprutils::Memory::CSharedPointer<CLibinputDevice> dev);
virtual ~CLibinputTabletPad();
virtual libinput_device* getLibinputHandle();
virtual const std::string& getName();
private:
Hyprutils::Memory::CWeakPointer<CLibinputDevice> device;
Hyprutils::Memory::CSharedPointer<ITabletPad::STabletPadGroup> createGroupFromID(int id);
friend class CLibinputDevice;
}; };
class CLibinputDevice { class CLibinputDevice {
@ -121,17 +177,22 @@ namespace Aquamarine {
CLibinputDevice(libinput_device* device, Hyprutils::Memory::CWeakPointer<CSession> session_); CLibinputDevice(libinput_device* device, Hyprutils::Memory::CWeakPointer<CSession> session_);
~CLibinputDevice(); ~CLibinputDevice();
void init(); void init();
libinput_device* device; libinput_device* device;
Hyprutils::Memory::CWeakPointer<CLibinputDevice> self; Hyprutils::Memory::CWeakPointer<CLibinputDevice> self;
Hyprutils::Memory::CWeakPointer<CSession> session; Hyprutils::Memory::CWeakPointer<CSession> session;
std::string name; std::string name;
Hyprutils::Memory::CSharedPointer<CLibinputKeyboard> keyboard; Hyprutils::Memory::CSharedPointer<CLibinputKeyboard> keyboard;
Hyprutils::Memory::CSharedPointer<CLibinputMouse> mouse; Hyprutils::Memory::CSharedPointer<CLibinputMouse> mouse;
Hyprutils::Memory::CSharedPointer<CLibinputTouch> touch; Hyprutils::Memory::CSharedPointer<CLibinputTouch> touch;
Hyprutils::Memory::CSharedPointer<CLibinputSwitch> switchy; // :) Hyprutils::Memory::CSharedPointer<CLibinputSwitch> switchy; // :)
Hyprutils::Memory::CSharedPointer<CLibinputTablet> tablet;
Hyprutils::Memory::CSharedPointer<CLibinputTabletPad> tabletPad;
std::vector<Hyprutils::Memory::CSharedPointer<CLibinputTabletTool>> tabletTools;
Hyprutils::Memory::CSharedPointer<CLibinputTabletTool> toolFrom(libinput_tablet_tool* tool);
}; };
class CSession { class CSession {

View file

@ -7,11 +7,11 @@
#include "../misc/Attachment.hpp" #include "../misc/Attachment.hpp"
namespace Aquamarine { namespace Aquamarine {
enum eBufferCapability { enum eBufferCapability : uint32_t {
BUFFER_CAPABILITY_DATAPTR = (1 << 0), BUFFER_CAPABILITY_DATAPTR = (1 << 0),
}; };
enum eBufferType { enum eBufferType : uint32_t {
BUFFER_TYPE_DMABUF = 0, BUFFER_TYPE_DMABUF = 0,
BUFFER_TYPE_SHM, BUFFER_TYPE_SHM,
BUFFER_TYPE_MISC, BUFFER_TYPE_MISC,

View file

@ -6,6 +6,8 @@
struct libinput_device; struct libinput_device;
namespace Aquamarine { namespace Aquamarine {
class ITabletTool;
class IKeyboard { class IKeyboard {
public: public:
virtual ~IKeyboard() { virtual ~IKeyboard() {
@ -41,19 +43,19 @@ namespace Aquamarine {
virtual libinput_device* getLibinputHandle(); virtual libinput_device* getLibinputHandle();
virtual const std::string& getName() = 0; virtual const std::string& getName() = 0;
enum ePointerAxis { enum ePointerAxis : uint32_t {
AQ_POINTER_AXIS_VERTICAL = 0, AQ_POINTER_AXIS_VERTICAL = 0,
AQ_POINTER_AXIS_HORIZONTAL, AQ_POINTER_AXIS_HORIZONTAL,
}; };
enum ePointerAxisSource { enum ePointerAxisSource : uint32_t {
AQ_POINTER_AXIS_SOURCE_WHEEL = 0, AQ_POINTER_AXIS_SOURCE_WHEEL = 0,
AQ_POINTER_AXIS_SOURCE_FINGER, AQ_POINTER_AXIS_SOURCE_FINGER,
AQ_POINTER_AXIS_SOURCE_CONTINUOUS, AQ_POINTER_AXIS_SOURCE_CONTINUOUS,
AQ_POINTER_AXIS_SOURCE_TILT, AQ_POINTER_AXIS_SOURCE_TILT,
}; };
enum ePointerAxisRelativeDirection { enum ePointerAxisRelativeDirection : uint32_t {
AQ_POINTER_AXIS_RELATIVE_IDENTICAL = 0, AQ_POINTER_AXIS_RELATIVE_IDENTICAL = 0,
AQ_POINTER_AXIS_RELATIVE_INVERTED, AQ_POINTER_AXIS_RELATIVE_INVERTED,
}; };
@ -198,7 +200,7 @@ namespace Aquamarine {
virtual libinput_device* getLibinputHandle(); virtual libinput_device* getLibinputHandle();
virtual const std::string& getName() = 0; virtual const std::string& getName() = 0;
enum eSwitchType { enum eSwitchType : uint32_t {
AQ_SWITCH_TYPE_UNKNOWN = 0, AQ_SWITCH_TYPE_UNKNOWN = 0,
AQ_SWITCH_TYPE_LID, AQ_SWITCH_TYPE_LID,
AQ_SWITCH_TYPE_TABLET_MODE, AQ_SWITCH_TYPE_TABLET_MODE,
@ -216,18 +218,107 @@ namespace Aquamarine {
} events; } 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 { class ITablet {
public: 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<std::string> paths;
struct SAxisEvent {
Hyprutils::Memory::CSharedPointer<ITabletTool> 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<ITabletTool> tool;
uint32_t timeMs = 0;
Hyprutils::Math::Vector2D absolute;
bool in = false;
};
struct STipEvent {
Hyprutils::Memory::CSharedPointer<ITabletTool> tool;
uint32_t timeMs = 0;
Hyprutils::Math::Vector2D absolute;
bool down = false;
};
struct SButtonEvent {
Hyprutils::Memory::CSharedPointer<ITabletTool> tool;
uint32_t timeMs = 0, button = 0;
bool down = false;
};
struct { struct {
Hyprutils::Signal::CSignal axis;
Hyprutils::Signal::CSignal proximity;
Hyprutils::Signal::CSignal tip;
Hyprutils::Signal::CSignal button;
Hyprutils::Signal::CSignal destroy; Hyprutils::Signal::CSignal destroy;
} events; } events;
}; };
class ITabletTool { class ITabletTool {
public: 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 { struct {
Hyprutils::Signal::CSignal destroy; Hyprutils::Signal::CSignal destroy;
@ -236,10 +327,63 @@ namespace Aquamarine {
class ITabletPad { class ITabletPad {
public: public:
// FIXME: virtual ~ITabletPad() {
events.destroy.emit();
}
struct STabletPadGroup {
std::vector<uint32_t> 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<std::string> paths;
std::vector<Hyprutils::Memory::CSharedPointer<STabletPadGroup>> 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 { struct {
Hyprutils::Signal::CSignal destroy; Hyprutils::Signal::CSignal destroy;
Hyprutils::Signal::CSignal button;
Hyprutils::Signal::CSignal ring;
Hyprutils::Signal::CSignal strip;
Hyprutils::Signal::CSignal attach;
} events; } events;
}; };
} }

View file

@ -4,7 +4,7 @@
#include <hyprutils/memory/SharedPtr.hpp> #include <hyprutils/memory/SharedPtr.hpp>
namespace Aquamarine { namespace Aquamarine {
enum eAttachmentType { enum eAttachmentType : uint32_t {
AQ_ATTACHMENT_DRM_BUFFER = 0, AQ_ATTACHMENT_DRM_BUFFER = 0,
AQ_ATTACHMENT_DRM_KMS_UNIMPORTABLE, AQ_ATTACHMENT_DRM_KMS_UNIMPORTABLE,
}; };

View file

@ -21,12 +21,12 @@ namespace Aquamarine {
std::optional<drmModeModeInfo> modeInfo; // if this is a drm mode, this will be populated. std::optional<drmModeModeInfo> 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_VSYNC = 0,
AQ_OUTPUT_PRESENTATION_IMMEDIATE, // likely tearing AQ_OUTPUT_PRESENTATION_IMMEDIATE, // likely tearing
}; };
enum eSubpixelMode { enum eSubpixelMode : uint32_t {
AQ_SUBPIXEL_UNKNOWN = 0, AQ_SUBPIXEL_UNKNOWN = 0,
AQ_SUBPIXEL_NONE, AQ_SUBPIXEL_NONE,
AQ_SUBPIXEL_HORIZONTAL_RGB, AQ_SUBPIXEL_HORIZONTAL_RGB,

View file

@ -8,6 +8,7 @@ extern "C" {
#include <xf86drm.h> #include <xf86drm.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <xf86drmMode.h> #include <xf86drmMode.h>
#include <linux/input.h>
} }
using namespace Aquamarine; using namespace Aquamarine;
@ -270,8 +271,14 @@ void Aquamarine::CSession::onReady() {
backend->events.newTouch.emit(SP<ITouch>(d->touch)); backend->events.newTouch.emit(SP<ITouch>(d->touch));
if (d->switchy) if (d->switchy)
backend->events.newSwitch.emit(SP<ITouch>(d->touch)); backend->events.newSwitch.emit(SP<ITouch>(d->touch));
if (d->tablet)
backend->events.newTablet.emit(SP<ITablet>(d->tablet));
if (d->tabletPad)
backend->events.newTabletPad.emit(SP<ITabletPad>(d->tabletPad));
// FIXME: other devices. for (auto& t : d->tabletTools) {
backend->events.newTabletTool.emit(SP<ITabletTool>(t));
}
} }
} }
@ -400,7 +407,8 @@ void Aquamarine::CSession::handleLibinputEvent(libinput_event* e) {
return; return;
} }
auto hlDevice = ((CLibinputDevice*)data)->self.lock(); auto hlDevice = ((CLibinputDevice*)data)->self.lock();
bool destroyTool = false;
switch (eventType) { switch (eventType) {
case LIBINPUT_EVENT_DEVICE_ADDED: case LIBINPUT_EVENT_DEVICE_ADDED:
@ -640,7 +648,145 @@ void Aquamarine::CSession::handleLibinputEvent(libinput_event* e) {
// --------- tbalet // --------- 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; default: break;
} }
@ -686,13 +832,50 @@ void Aquamarine::CLibinputDevice::init() {
session->backend->events.newSwitch.emit(SP<ISwitch>(switchy)); session->backend->events.newSwitch.emit(SP<ISwitch>(switchy));
} }
// FIXME: other devices if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_TABLET_TOOL)) {
tablet = makeShared<CLibinputTablet>(self.lock());
if (session->backend->ready)
session->backend->events.newTablet.emit(SP<ITablet>(tablet));
}
if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_TABLET_PAD)) {
tabletPad = makeShared<CLibinputTabletPad>(self.lock());
if (session->backend->ready)
session->backend->events.newTabletPad.emit(SP<ITabletPad>(tabletPad));
}
} }
Aquamarine::CLibinputDevice::~CLibinputDevice() { Aquamarine::CLibinputDevice::~CLibinputDevice() {
libinput_device_unref(device); libinput_device_unref(device);
} }
SP<CLibinputTabletTool> Aquamarine::CLibinputDevice::toolFrom(libinput_tablet_tool* tool) {
for (auto& t : tabletTools) {
if (t->libinputTool == tool)
return t;
}
auto newt = makeShared<CLibinputTabletTool>(self.lock(), tool);
tabletTools.emplace_back(newt);
if (session->backend->ready)
session->backend->events.newTabletTool.emit(SP<ITabletTool>(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<CLibinputDevice> dev) : device(dev) {} Aquamarine::CLibinputKeyboard::CLibinputKeyboard(SP<CLibinputDevice> dev) : device(dev) {}
libinput_device* Aquamarine::CLibinputKeyboard::getLibinputHandle() { libinput_device* Aquamarine::CLibinputKeyboard::getLibinputHandle() {
@ -760,3 +943,135 @@ const std::string& Aquamarine::CLibinputSwitch::getName() {
return AQ_UNKNOWN_DEVICE_NAME; return AQ_UNKNOWN_DEVICE_NAME;
return device->name; return device->name;
} }
Aquamarine::CLibinputTablet::CLibinputTablet(Hyprutils::Memory::CSharedPointer<CLibinputDevice> 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<CLibinputDevice> 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<CLibinputDevice> 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<ITabletPad::STabletPadGroup> Aquamarine::CLibinputTabletPad::createGroupFromID(int id) {
auto libinputGroup = libinput_device_tablet_pad_get_mode_group(device->device, id);
auto group = makeShared<STabletPadGroup>();
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;
}

View file

@ -16,6 +16,18 @@ libinput_device* Aquamarine::ISwitch::getLibinputHandle() {
return nullptr; 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) { void Aquamarine::IKeyboard::updateLEDs(uint32_t leds) {
; ;
} }

View file

@ -6,10 +6,8 @@ bool Aquamarine::envEnabled(const std::string& env) {
return e && e == std::string{"1"}; return e && e == std::string{"1"};
} }
static bool trace = []() -> bool { static bool trace = []() -> bool { return Aquamarine::envEnabled("AQ_TRACE"); }();
return Aquamarine::envEnabled("AQ_TRACE");
}();
bool Aquamarine::isTrace() { bool Aquamarine::isTrace() {
return trace; return trace;
} }