Tablet: move to new impl

Ring and strip are not implemented. Will I implement this? God fucking knows. Nobody seems to have that anyways.
This commit is contained in:
Vaxry 2024-05-06 02:15:26 +01:00 committed by Vaxry
parent ed411f53bd
commit 84e8d1810d
21 changed files with 1926 additions and 1606 deletions

View file

@ -8,6 +8,7 @@ enum eHIDCapabilityType : uint32_t {
HID_INPUT_CAPABILITY_KEYBOARD = (1 << 0),
HID_INPUT_CAPABILITY_POINTER = (1 << 1),
HID_INPUT_CAPABILITY_TOUCH = (1 << 2),
HID_INPUT_CAPABILITY_TABLET = (1 << 3),
};
enum eHIDType {
@ -16,6 +17,8 @@ enum eHIDType {
HID_TYPE_KEYBOARD,
HID_TYPE_TOUCH,
HID_TYPE_TABLET,
HID_TYPE_TABLET_TOOL,
HID_TYPE_TABLET_PAD,
};
/*

326
src/devices/Tablet.cpp Normal file
View file

@ -0,0 +1,326 @@
#include "Tablet.hpp"
#include "../defines.hpp"
#include "../protocols/Tablet.hpp"
SP<CTablet> CTablet::create(wlr_tablet* tablet) {
SP<CTablet> pTab = SP<CTablet>(new CTablet(tablet));
pTab->self = pTab;
PROTO::tablet->registerDevice(pTab);
return pTab;
}
SP<CTabletTool> CTabletTool::create(wlr_tablet_tool* tablet) {
SP<CTabletTool> pTab = SP<CTabletTool>(new CTabletTool(tablet));
pTab->self = pTab;
PROTO::tablet->registerDevice(pTab);
return pTab;
}
SP<CTabletPad> CTabletPad::create(wlr_tablet_pad* tablet) {
SP<CTabletPad> pTab = SP<CTabletPad>(new CTabletPad(tablet));
pTab->self = pTab;
PROTO::tablet->registerDevice(pTab);
return pTab;
}
SP<CTabletTool> CTabletTool::fromWlr(wlr_tablet_tool* tool) {
return ((CTabletTool*)tool->data)->self.lock();
}
SP<CTablet> CTablet::fromWlr(wlr_tablet* tablet) {
return ((CTablet*)tablet->data)->self.lock();
}
static uint32_t wlrUpdateToHl(uint32_t wlr) {
uint32_t result = 0;
if (wlr & WLR_TABLET_TOOL_AXIS_X)
result |= CTablet::eTabletToolAxes::HID_TABLET_TOOL_AXIS_X;
if (wlr & WLR_TABLET_TOOL_AXIS_Y)
result |= CTablet::eTabletToolAxes::HID_TABLET_TOOL_AXIS_Y;
if (wlr & WLR_TABLET_TOOL_AXIS_DISTANCE)
result |= CTablet::eTabletToolAxes::HID_TABLET_TOOL_AXIS_DISTANCE;
if (wlr & WLR_TABLET_TOOL_AXIS_PRESSURE)
result |= CTablet::eTabletToolAxes::HID_TABLET_TOOL_AXIS_PRESSURE;
if (wlr & WLR_TABLET_TOOL_AXIS_TILT_X)
result |= CTablet::eTabletToolAxes::HID_TABLET_TOOL_AXIS_TILT_X;
if (wlr & WLR_TABLET_TOOL_AXIS_TILT_Y)
result |= CTablet::eTabletToolAxes::HID_TABLET_TOOL_AXIS_TILT_Y;
if (wlr & WLR_TABLET_TOOL_AXIS_ROTATION)
result |= CTablet::eTabletToolAxes::HID_TABLET_TOOL_AXIS_ROTATION;
if (wlr & WLR_TABLET_TOOL_AXIS_SLIDER)
result |= CTablet::eTabletToolAxes::HID_TABLET_TOOL_AXIS_SLIDER;
if (wlr & WLR_TABLET_TOOL_AXIS_WHEEL)
result |= CTablet::eTabletToolAxes::HID_TABLET_TOOL_AXIS_WHEEL;
return result;
}
uint32_t CTablet::getCapabilities() {
return HID_INPUT_CAPABILITY_POINTER | HID_INPUT_CAPABILITY_TABLET;
}
wlr_tablet* CTablet::wlr() {
return tablet;
}
CTablet::CTablet(wlr_tablet* tablet_) : tablet(tablet_) {
if (!tablet)
return;
tablet->data = this;
// clang-format off
hyprListener_destroy.initCallback(&tablet->base.events.destroy, [this] (void* owner, void* data) {
tablet = nullptr;
disconnectCallbacks();
events.destroy.emit();
}, this, "CTablet");
hyprListener_axis.initCallback(&tablet->events.axis, [this] (void* owner, void* data) {
auto E = (wlr_tablet_tool_axis_event*)data;
tabletEvents.axis.emit(SAxisEvent{
.tool = E->tool,
.tablet = self.lock(),
.timeMs = E->time_msec,
.updatedAxes = wlrUpdateToHl(E->updated_axes),
.axis = {E->x, E->y},
.axisDelta = {E->dx, E->dy},
.tilt = {E->tilt_x, E->tilt_y},
.pressure = E->pressure,
.distance = E->distance,
.rotation = E->rotation,
.slider = E->slider,
.wheelDelta = E->wheel_delta,
});
}, this, "CTablet");
hyprListener_proximity.initCallback(&tablet->events.proximity, [this] (void* owner, void* data) {
auto E = (wlr_tablet_tool_proximity_event*)data;
tabletEvents.proximity.emit(SProximityEvent{
.tool = E->tool,
.tablet = self.lock(),
.timeMs = E->time_msec,
.proximity = {E->x, E->y},
.in = E->state == WLR_TABLET_TOOL_PROXIMITY_IN,
});
}, this, "CTablet");
hyprListener_tip.initCallback(&tablet->events.tip, [this] (void* owner, void* data) {
auto E = (wlr_tablet_tool_tip_event*)data;
tabletEvents.tip.emit(STipEvent{
.tool = E->tool,
.tablet = self.lock(),
.timeMs = E->time_msec,
.tip = {E->x, E->y},
.in = E->state == WLR_TABLET_TOOL_TIP_DOWN,
});
}, this, "CTablet");
hyprListener_button.initCallback(&tablet->events.button, [this] (void* owner, void* data) {
auto E = (wlr_tablet_tool_button_event*)data;
tabletEvents.button.emit(SButtonEvent{
.tool = E->tool,
.tablet = self.lock(),
.timeMs = E->time_msec,
.button = E->button,
.down = E->state == WLR_BUTTON_PRESSED,
});
}, this, "CTablet");
// clang-format on
deviceName = tablet->base.name ? tablet->base.name : "UNKNOWN";
}
CTablet::~CTablet() {
if (tablet)
tablet->data = nullptr;
PROTO::tablet->recheckRegisteredDevices();
}
void CTablet::disconnectCallbacks() {
hyprListener_axis.removeCallback();
hyprListener_button.removeCallback();
hyprListener_destroy.removeCallback();
hyprListener_proximity.removeCallback();
hyprListener_tip.removeCallback();
}
eHIDType CTablet::getType() {
return HID_TYPE_TABLET;
}
uint32_t CTabletPad::getCapabilities() {
return HID_INPUT_CAPABILITY_TABLET;
}
wlr_tablet_pad* CTabletPad::wlr() {
return pad;
}
eHIDType CTabletPad::getType() {
return HID_TYPE_TABLET_PAD;
}
CTabletPad::CTabletPad(wlr_tablet_pad* pad_) : pad(pad_) {
if (!pad)
return;
// clang-format off
hyprListener_destroy.initCallback(&pad->base.events.destroy, [this] (void* owner, void* data) {
pad = nullptr;
disconnectCallbacks();
events.destroy.emit();
}, this, "CTabletPad");
hyprListener_button.initCallback(&pad->events.button, [this] (void* owner, void* data) {
auto E = (wlr_tablet_pad_button_event*)data;
padEvents.button.emit(SButtonEvent{
.timeMs = E->time_msec,
.button = E->button,
.down = E->state == WLR_BUTTON_PRESSED,
.mode = E->mode,
.group = E->group,
});
}, this, "CTabletPad");
hyprListener_ring.initCallback(&pad->events.ring, [this] (void* owner, void* data) {
auto E = (wlr_tablet_pad_ring_event*)data;
padEvents.ring.emit(SRingEvent{
.timeMs = E->time_msec,
.finger = E->source == WLR_TABLET_PAD_RING_SOURCE_FINGER,
.ring = E->ring,
.position = E->position,
.mode = E->mode,
});
}, this, "CTabletPad");
hyprListener_strip.initCallback(&pad->events.strip, [this] (void* owner, void* data) {
auto E = (wlr_tablet_pad_strip_event*)data;
padEvents.strip.emit(SStripEvent{
.timeMs = E->time_msec,
.finger = E->source == WLR_TABLET_PAD_STRIP_SOURCE_FINGER,
.strip = E->strip,
.position = E->position,
.mode = E->mode,
});
}, this, "CTabletPad");
hyprListener_attach.initCallback(&pad->events.attach_tablet, [this] (void* owner, void* data) {
if (!data)
return;
padEvents.attach.emit(CTabletTool::fromWlr((wlr_tablet_tool*)data));
}, this, "CTabletPad");
// clang-format on
deviceName = pad->base.name ? pad->base.name : "UNKNOWN";
}
CTabletPad::~CTabletPad() {
PROTO::tablet->recheckRegisteredDevices();
}
void CTabletPad::disconnectCallbacks() {
hyprListener_ring.removeCallback();
hyprListener_button.removeCallback();
hyprListener_destroy.removeCallback();
hyprListener_strip.removeCallback();
hyprListener_attach.removeCallback();
}
uint32_t CTabletTool::getCapabilities() {
return HID_INPUT_CAPABILITY_POINTER | HID_INPUT_CAPABILITY_TABLET;
}
wlr_tablet_tool* CTabletTool::wlr() {
return tool;
}
eHIDType CTabletTool::getType() {
return HID_TYPE_TABLET_TOOL;
}
CTabletTool::CTabletTool(wlr_tablet_tool* tool_) : tool(tool_) {
if (!tool)
return;
// clang-format off
hyprListener_destroy.initCallback(&tool->events.destroy, [this] (void* owner, void* data) {
tool = nullptr;
disconnectCallbacks();
events.destroy.emit();
}, this, "CTabletTool");
// clang-format on
if (tool->tilt)
toolCapabilities |= HID_TABLET_TOOL_CAPABILITY_TILT;
if (tool->pressure)
toolCapabilities |= HID_TABLET_TOOL_CAPABILITY_PRESSURE;
if (tool->distance)
toolCapabilities |= HID_TABLET_TOOL_CAPABILITY_DISTANCE;
if (tool->rotation)
toolCapabilities |= HID_TABLET_TOOL_CAPABILITY_ROTATION;
if (tool->slider)
toolCapabilities |= HID_TABLET_TOOL_CAPABILITY_SLIDER;
if (tool->wheel)
toolCapabilities |= HID_TABLET_TOOL_CAPABILITY_WHEEL;
tool->data = this;
deviceName = std::to_string(tool->hardware_serial) + std::to_string(tool->hardware_wacom);
}
CTabletTool::~CTabletTool() {
if (tool)
tool->data = nullptr;
PROTO::tablet->recheckRegisteredDevices();
}
void CTabletTool::disconnectCallbacks() {
hyprListener_destroy.removeCallback();
hyprListener_destroySurface.removeCallback();
}
wlr_surface* CTabletTool::getSurface() {
return pSurface;
}
void CTabletTool::setSurface(wlr_surface* surf) {
if (surf == pSurface)
return;
if (pSurface) {
hyprListener_destroySurface.removeCallback();
pSurface = nullptr;
}
pSurface = surf;
if (surf) {
hyprListener_destroySurface.initCallback(
&surf->events.destroy,
[this](void* owner, void* data) {
PROTO::tablet->proximityOut(self.lock());
pSurface = nullptr;
hyprListener_destroySurface.removeCallback();
},
this, "CTabletTool");
}
}

228
src/devices/Tablet.hpp Normal file
View file

@ -0,0 +1,228 @@
#pragma once
#include "IHID.hpp"
#include "../helpers/WLListener.hpp"
#include "../macros.hpp"
#include "../helpers/Vector2D.hpp"
#include "../helpers/Box.hpp"
struct wlr_tablet;
struct wlr_tablet_tool;
struct wlr_tablet_pad;
class CTabletTool;
class CTabletPad;
/*
A tablet device
Tablets don't have an interface for now,
if there will be a need it's trivial to do.
*/
class CTablet : public IHID {
public:
static SP<CTablet> create(wlr_tablet* tablet);
static SP<CTablet> fromWlr(wlr_tablet* tablet);
~CTablet();
virtual uint32_t getCapabilities();
virtual eHIDType getType();
wlr_tablet* wlr();
enum eTabletToolAxes {
HID_TABLET_TOOL_AXIS_X = (1 << 0),
HID_TABLET_TOOL_AXIS_Y = (1 << 1),
HID_TABLET_TOOL_AXIS_TILT_X = (1 << 2),
HID_TABLET_TOOL_AXIS_TILT_Y = (1 << 3),
HID_TABLET_TOOL_AXIS_DISTANCE = (1 << 4),
HID_TABLET_TOOL_AXIS_PRESSURE = (1 << 5),
HID_TABLET_TOOL_AXIS_ROTATION = (1 << 6),
HID_TABLET_TOOL_AXIS_SLIDER = (1 << 7),
HID_TABLET_TOOL_AXIS_WHEEL = (1 << 8),
};
struct SAxisEvent {
wlr_tablet_tool* tool;
SP<CTablet> tablet;
uint32_t timeMs = 0;
uint32_t updatedAxes = 0; // eTabletToolAxes
Vector2D axis;
Vector2D axisDelta;
Vector2D tilt;
double pressure = 0;
double distance = 0;
double rotation = 0;
double slider = 0;
double wheelDelta = 0;
};
struct SProximityEvent {
wlr_tablet_tool* tool;
SP<CTablet> tablet;
uint32_t timeMs = 0;
Vector2D proximity;
bool in = false;
};
struct STipEvent {
wlr_tablet_tool* tool;
SP<CTablet> tablet;
uint32_t timeMs = 0;
Vector2D tip;
bool in = false;
};
struct SButtonEvent {
wlr_tablet_tool* tool;
SP<CTablet> tablet;
uint32_t timeMs = 0;
uint32_t button;
bool down = false;
};
struct {
CSignal axis;
CSignal proximity;
CSignal tip;
CSignal button;
} tabletEvents;
WP<CTablet> self;
bool relativeInput = false;
std::string hlName = "";
std::string boundOutput = "";
CBox activeArea;
CBox boundBox; // output-local
private:
CTablet(wlr_tablet* tablet);
void disconnectCallbacks();
wlr_tablet* tablet = nullptr;
DYNLISTENER(destroy);
DYNLISTENER(axis);
DYNLISTENER(proximity);
DYNLISTENER(tip);
DYNLISTENER(button);
};
class CTabletPad : public IHID {
public:
static SP<CTabletPad> create(wlr_tablet_pad* pad);
~CTabletPad();
virtual uint32_t getCapabilities();
virtual eHIDType getType();
wlr_tablet_pad* wlr();
struct SButtonEvent {
uint32_t timeMs = 0;
uint32_t button = 0;
bool down = false;
uint32_t mode = 0;
uint32_t group = 0;
};
struct SRingEvent {
uint32_t timeMs = 0;
bool finger = false;
uint32_t ring = 0;
double position = 0;
uint32_t mode = 0;
};
struct SStripEvent {
uint32_t timeMs = 0;
bool finger = false;
uint32_t strip = 0;
double position = 0;
uint32_t mode = 0;
};
struct {
CSignal button;
CSignal ring;
CSignal strip;
CSignal attach;
} padEvents;
WP<CTabletPad> self;
WP<CTabletTool> parent;
std::string hlName;
private:
CTabletPad(wlr_tablet_pad* pad);
void disconnectCallbacks();
wlr_tablet_pad* pad = nullptr;
DYNLISTENER(destroy);
DYNLISTENER(ring);
DYNLISTENER(strip);
DYNLISTENER(button);
DYNLISTENER(attach);
};
class CTabletTool : public IHID {
public:
static SP<CTabletTool> create(wlr_tablet_tool* tool);
static SP<CTabletTool> fromWlr(wlr_tablet_tool* tool);
~CTabletTool();
enum eTabletToolType {
HID_TABLET_TOOL_TYPE_PEN = 1,
HID_TABLET_TOOL_TYPE_ERASER,
HID_TABLET_TOOL_TYPE_BRUSH,
HID_TABLET_TOOL_TYPE_PENCIL,
HID_TABLET_TOOL_TYPE_AIRBRUSH,
HID_TABLET_TOOL_TYPE_MOUSE,
HID_TABLET_TOOL_TYPE_LENS,
HID_TABLET_TOOL_TYPE_TOTEM,
};
enum eTabletToolCapabilities {
HID_TABLET_TOOL_CAPABILITY_TILT = (1 << 0),
HID_TABLET_TOOL_CAPABILITY_PRESSURE = (1 << 1),
HID_TABLET_TOOL_CAPABILITY_DISTANCE = (1 << 2),
HID_TABLET_TOOL_CAPABILITY_ROTATION = (1 << 3),
HID_TABLET_TOOL_CAPABILITY_SLIDER = (1 << 4),
HID_TABLET_TOOL_CAPABILITY_WHEEL = (1 << 5),
};
virtual uint32_t getCapabilities();
wlr_tablet_tool* wlr();
virtual eHIDType getType();
wlr_surface* getSurface();
void setSurface(wlr_surface*);
WP<CTabletTool> self;
Vector2D tilt;
bool active = false; // true if in proximity
uint32_t toolCapabilities = 0;
bool isDown = false;
std::vector<uint32_t> buttonsDown;
Vector2D absolutePos; // last known absolute position.
std::string hlName;
private:
CTabletTool(wlr_tablet_tool* tool);
void disconnectCallbacks();
wlr_surface* pSurface = nullptr;
wlr_tablet_tool* tool = nullptr;
DYNLISTENER(destroy);
DYNLISTENER(destroySurface);
};