tablet_v2: Support remaining controls

Adds support for tablet buttons, rings and strips.
This commit is contained in:
Aleix Pol 2020-11-20 02:28:05 +01:00
parent 8f9fcd7eb3
commit 1a32c64603
13 changed files with 360 additions and 258 deletions

View file

@ -501,53 +501,51 @@ void DebugConsoleFilter::tabletToolEvent(TabletEvent *event)
m_textEdit->ensureCursorVisible(); m_textEdit->ensureCursorVisible();
} }
void DebugConsoleFilter::tabletToolButtonEvent(const QSet<uint> &pressedButtons) void DebugConsoleFilter::tabletToolButtonEvent(uint button, bool pressed, const TabletToolId &tabletToolId)
{ {
QString buttons;
for (uint b : pressedButtons) {
buttons += QString::number(b) + ' ';
}
QString text = s_hr + s_tableStart + tableHeaderRow(i18n("Tablet Tool Button")) QString text = s_hr + s_tableStart + tableHeaderRow(i18n("Tablet Tool Button"))
+ tableRow(i18n("Pressed Buttons"), buttons) + tableRow(i18n("Button"), button)
+ tableRow(i18n("Pressed"), pressed)
+ tableRow(i18n("Tablet"), tabletToolId.m_tabletSysName)
+ s_tableEnd; + s_tableEnd;
m_textEdit->insertHtml(text); m_textEdit->insertHtml(text);
m_textEdit->ensureCursorVisible(); m_textEdit->ensureCursorVisible();
} }
void DebugConsoleFilter::tabletPadButtonEvent(const QSet<uint> &pressedButtons) void DebugConsoleFilter::tabletPadButtonEvent(uint button, bool pressed, const QString &deviceSysName)
{ {
QString buttons;
for (uint b : pressedButtons) {
buttons += QString::number(b) + ' ';
}
QString text = s_hr + s_tableStart QString text = s_hr + s_tableStart
+ tableHeaderRow(i18n("Tablet Pad Button")) + tableHeaderRow(i18n("Tablet Pad Button"))
+ tableRow(i18n("Pressed Buttons"), buttons) + tableRow(i18n("Button"), button)
+ tableRow(i18n("Pressed"), pressed)
+ tableRow(i18n("Tablet"), deviceSysName)
+ s_tableEnd; + s_tableEnd;
m_textEdit->insertHtml(text); m_textEdit->insertHtml(text);
m_textEdit->ensureCursorVisible(); m_textEdit->ensureCursorVisible();
} }
void DebugConsoleFilter::tabletPadStripEvent(int number, int position, bool isFinger) void DebugConsoleFilter::tabletPadStripEvent(int number, int position, bool isFinger, const QString &deviceSysName)
{ {
QString text = s_hr + s_tableStart + tableHeaderRow(i18n("Tablet Pad Strip")) QString text = s_hr + s_tableStart + tableHeaderRow(i18n("Tablet Pad Strip"))
+ tableRow(i18n("Number"), number) + tableRow(i18n("Number"), number)
+ tableRow(i18n("Position"), position) + tableRow(i18n("Position"), position)
+ tableRow(i18n("isFinger"), isFinger) + tableRow(i18n("isFinger"), isFinger)
+ tableRow(i18n("Tablet"), deviceSysName)
+ s_tableEnd; + s_tableEnd;
m_textEdit->insertHtml(text); m_textEdit->insertHtml(text);
m_textEdit->ensureCursorVisible(); m_textEdit->ensureCursorVisible();
} }
void DebugConsoleFilter::tabletPadRingEvent(int number, int position, bool isFinger) void DebugConsoleFilter::tabletPadRingEvent(int number, int position, bool isFinger, const QString &deviceSysName)
{ {
QString text = s_hr + s_tableStart + tableHeaderRow(i18n("Tablet Pad Ring")) QString text = s_hr + s_tableStart + tableHeaderRow(i18n("Tablet Pad Ring"))
+ tableRow(i18n("Number"), number) + tableRow(i18n("Number"), number)
+ tableRow(i18n("Position"), position) + tableRow(i18n("Position"), position)
+ tableRow(i18n("isFinger"), isFinger) + tableRow(i18n("isFinger"), isFinger)
+ tableRow(i18n("Tablet"), deviceSysName)
+ s_tableEnd; + s_tableEnd;
m_textEdit->insertHtml(text); m_textEdit->insertHtml(text);

View file

@ -148,10 +148,10 @@ public:
void switchEvent(SwitchEvent *event) override; void switchEvent(SwitchEvent *event) override;
void tabletToolEvent(TabletEvent *event) override; void tabletToolEvent(TabletEvent *event) override;
void tabletToolButtonEvent(const QSet<uint> &pressedButtons) override; void tabletToolButtonEvent(uint button, bool pressed, const TabletToolId &tabletToolId) override;
void tabletPadButtonEvent(const QSet<uint> &pressedButtons) override; void tabletPadButtonEvent(uint button, bool pressed, const QString &deviceSysName) override;
void tabletPadStripEvent(int number, int position, bool isFinger) override; void tabletPadStripEvent(int number, int position, bool isFinger, const QString &deviceSysName) override;
void tabletPadRingEvent(int number, int position, bool isFinger) override; void tabletPadRingEvent(int number, int position, bool isFinger, const QString &deviceSysName) override;
private: private:
QTextEdit *m_textEdit; QTextEdit *m_textEdit;

303
input.cpp
View file

@ -175,31 +175,37 @@ bool InputEventFilter::tabletToolEvent(TabletEvent *event)
return false; return false;
} }
bool InputEventFilter::tabletToolButtonEvent(const QSet<uint> &pressedButtons) bool InputEventFilter::tabletToolButtonEvent(uint button, bool pressed, const TabletToolId &tabletId)
{ {
Q_UNUSED(pressedButtons) Q_UNUSED(button)
Q_UNUSED(pressed)
Q_UNUSED(tabletId)
return false; return false;
} }
bool InputEventFilter::tabletPadButtonEvent(const QSet<uint> &pressedButtons) bool InputEventFilter::tabletPadButtonEvent(uint button, bool pressed, const QString &deviceSysName)
{ {
Q_UNUSED(pressedButtons) Q_UNUSED(button)
Q_UNUSED(pressed)
Q_UNUSED(deviceSysName)
return false; return false;
} }
bool InputEventFilter::tabletPadStripEvent(int number, int position, bool isFinger) bool InputEventFilter::tabletPadStripEvent(int number, int position, bool isFinger, const QString &deviceSysName)
{ {
Q_UNUSED(number) Q_UNUSED(number)
Q_UNUSED(position) Q_UNUSED(position)
Q_UNUSED(isFinger) Q_UNUSED(isFinger)
Q_UNUSED(deviceSysName)
return false; return false;
} }
bool InputEventFilter::tabletPadRingEvent(int number, int position, bool isFinger) bool InputEventFilter::tabletPadRingEvent(int number, int position, bool isFinger, const QString &deviceSysName)
{ {
Q_UNUSED(number) Q_UNUSED(number)
Q_UNUSED(position) Q_UNUSED(position)
Q_UNUSED(isFinger) Q_UNUSED(isFinger)
Q_UNUSED(deviceSysName)
return false; return false;
} }
@ -1575,23 +1581,138 @@ public:
if (device->isTabletTool()) { if (device->isTabletTool()) {
KWaylandServer::TabletSeatV2Interface *tabletSeat = findTabletSeat(); KWaylandServer::TabletSeatV2Interface *tabletSeat = findTabletSeat();
if (!tabletSeat) { if (!tabletSeat) {
qCCritical(KWIN_CORE) << "Could not find tablet manager"; qCCritical(KWIN_CORE) << "Could not find tablet seat";
return; return;
} }
struct udev_device *const udev_device = libinput_device_get_udev_device(device->device()); struct udev_device *const udev_device = libinput_device_get_udev_device(device->device());
const char *devnode = udev_device_get_devnode(udev_device); const char *devnode = udev_device_get_syspath(udev_device);
tabletSeat->addTablet(device->vendor(), device->product(), device->sysName(), device->name(), {QString::fromUtf8(devnode)}); tabletSeat->addTablet(device->vendor(), device->product(), device->sysName(), device->name(), {QString::fromUtf8(devnode)});
} }
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));
}
} }
void removeDevice(const QString &sysname) void removeDevice(const QString &sysname)
{ {
KWaylandServer::TabletSeatV2Interface *tabletSeat = findTabletSeat(); KWaylandServer::TabletSeatV2Interface *tabletSeat = findTabletSeat();
if (tabletSeat) if (tabletSeat)
tabletSeat->removeTablet(sysname); tabletSeat->removeDevice(sysname);
else else
qCCritical(KWIN_CORE) << "Could not find tablet to remove" << sysname; qCCritical(KWIN_CORE) << "Could not find tablet to remove" << sysname;
} }
KWaylandServer::TabletToolV2Interface *createTool(const KWin::TabletToolId &tabletToolId)
{
using namespace KWaylandServer;
KWaylandServer::TabletSeatV2Interface *tabletSeat = findTabletSeat();
const auto f = [](InputRedirection::Capability cap) {
switch (cap) {
case InputRedirection::Tilt:
return TabletToolV2Interface::Tilt;
case InputRedirection::Pressure:
return TabletToolV2Interface::Pressure;
case InputRedirection::Distance:
return TabletToolV2Interface::Distance;
case InputRedirection::Rotation:
return TabletToolV2Interface::Rotation;
case InputRedirection::Slider:
return TabletToolV2Interface::Slider;
case InputRedirection::Wheel:
return TabletToolV2Interface::Wheel;
}
return TabletToolV2Interface::Wheel;
};
QVector<TabletToolV2Interface::Capability> ifaceCapabilities;
ifaceCapabilities.resize(tabletToolId.m_capabilities.size());
std::transform(tabletToolId.m_capabilities.constBegin(), tabletToolId.m_capabilities.constEnd(), ifaceCapabilities.begin(), f);
TabletToolV2Interface::Type toolType = TabletToolV2Interface::Type::Pen;
switch (tabletToolId.m_toolType) {
case InputRedirection::Pen:
toolType = TabletToolV2Interface::Type::Pen;
break;
case InputRedirection::Eraser:
toolType = TabletToolV2Interface::Type::Eraser;
break;
case InputRedirection::Brush:
toolType = TabletToolV2Interface::Type::Brush;
break;
case InputRedirection::Pencil:
toolType = TabletToolV2Interface::Type::Pencil;
break;
case InputRedirection::Airbrush:
toolType = TabletToolV2Interface::Type::Airbrush;
break;
case InputRedirection::Finger:
toolType = TabletToolV2Interface::Type::Finger;
break;
case InputRedirection::Mouse:
toolType = TabletToolV2Interface::Type::Mouse;
break;
case InputRedirection::Lens:
toolType = TabletToolV2Interface::Type::Lens;
break;
case InputRedirection::Totem:
toolType = TabletToolV2Interface::Type::Totem;
break;
}
TabletToolV2Interface *tool = tabletSeat->addTool(toolType, tabletToolId.m_serialId, tabletToolId.m_uniqueId, ifaceCapabilities);
const auto cursor = new Cursor(tool);
Cursors::self()->addCursor(cursor);
m_cursorByTool[tool] = cursor;
connect(tool, &TabletToolV2Interface::cursorChanged, cursor, &Cursor::cursorChanged);
connect(tool, &TabletToolV2Interface::cursorChanged, cursor, [cursor] (TabletCursorV2 *tcursor) {
static const auto createDefaultCursor = [] {
WaylandCursorImage defaultCursor;
WaylandCursorImage::Image ret;
defaultCursor.loadThemeCursor(CursorShape(Qt::CrossCursor), &ret);
return ret;
};
static const auto defaultCursor = createDefaultCursor();
if (!tcursor) {
cursor->updateCursor(defaultCursor.image, defaultCursor.hotspot);
return;
}
auto cursorSurface = tcursor->surface();
if (!cursorSurface) {
cursor->updateCursor(defaultCursor.image, defaultCursor.hotspot);
return;
}
auto buffer = cursorSurface->buffer();
if (!buffer) {
cursor->updateCursor(defaultCursor.image, defaultCursor.hotspot);
return;
}
QImage cursorImage;
cursorImage = buffer->data().copy();
cursorImage.setDevicePixelRatio(cursorSurface->bufferScale());
cursor->updateCursor(cursorImage, tcursor->hotspot());
});
emit cursor->cursorChanged();
return tool;
}
bool tabletToolEvent(TabletEvent *event) override bool tabletToolEvent(TabletEvent *event) override
{ {
if (!workspace()) { if (!workspace()) {
@ -1603,102 +1724,12 @@ public:
qCCritical(KWIN_CORE) << "Could not find tablet manager"; qCCritical(KWIN_CORE) << "Could not find tablet manager";
return false; return false;
} }
auto tool = tabletSeat->toolByHardwareSerial(event->serialId()); auto tool = tabletSeat->toolByHardwareSerial(event->tabletId().m_serialId);
if (!tool) { if (!tool) {
using namespace KWaylandServer; tool = createTool(event->tabletId());
const QVector<InputRedirection::Capability> capabilities = event->capabilities();
const auto f = [](InputRedirection::Capability cap) {
switch (cap) {
case InputRedirection::Tilt:
return TabletToolV2Interface::Tilt;
case InputRedirection::Pressure:
return TabletToolV2Interface::Pressure;
case InputRedirection::Distance:
return TabletToolV2Interface::Distance;
case InputRedirection::Rotation:
return TabletToolV2Interface::Rotation;
case InputRedirection::Slider:
return TabletToolV2Interface::Slider;
case InputRedirection::Wheel:
return TabletToolV2Interface::Wheel;
}
return TabletToolV2Interface::Wheel;
};
QVector<TabletToolV2Interface::Capability> ifaceCapabilities;
ifaceCapabilities.resize(capabilities.size());
std::transform(capabilities.constBegin(), capabilities.constEnd(), ifaceCapabilities.begin(), f);
TabletToolV2Interface::Type toolType = TabletToolV2Interface::Type::Pen;
switch (event->toolType()) {
case InputRedirection::Pen:
toolType = TabletToolV2Interface::Type::Pen;
break;
case InputRedirection::Eraser:
toolType = TabletToolV2Interface::Type::Eraser;
break;
case InputRedirection::Brush:
toolType = TabletToolV2Interface::Type::Brush;
break;
case InputRedirection::Pencil:
toolType = TabletToolV2Interface::Type::Pencil;
break;
case InputRedirection::Airbrush:
toolType = TabletToolV2Interface::Type::Airbrush;
break;
case InputRedirection::Finger:
toolType = TabletToolV2Interface::Type::Finger;
break;
case InputRedirection::Mouse:
toolType = TabletToolV2Interface::Type::Mouse;
break;
case InputRedirection::Lens:
toolType = TabletToolV2Interface::Type::Lens;
break;
case InputRedirection::Totem:
toolType = TabletToolV2Interface::Type::Totem;
break;
}
tool = tabletSeat->addTool(toolType, event->serialId(), event->uniqueId(), ifaceCapabilities);
const auto cursor = new Cursor(tool);
Cursors::self()->addCursor(cursor);
m_cursorByTool[tool] = cursor;
connect(tool, &TabletToolV2Interface::cursorChanged, cursor, &Cursor::cursorChanged);
connect(tool, &TabletToolV2Interface::cursorChanged, cursor, [cursor] (TabletCursorV2 *tcursor) {
static const auto createDefaultCursor = [] {
WaylandCursorImage defaultCursor;
WaylandCursorImage::Image ret;
defaultCursor.loadThemeCursor(CursorShape(Qt::CrossCursor), &ret);
return ret;
};
static const auto defaultCursor = createDefaultCursor();
if (!tcursor) {
cursor->updateCursor(defaultCursor.image, defaultCursor.hotspot);
return;
}
auto cursorSurface = tcursor->surface();
if (!cursorSurface) {
cursor->updateCursor(defaultCursor.image, defaultCursor.hotspot);
return;
}
auto buffer = cursorSurface->buffer();
if (!buffer) {
cursor->updateCursor(defaultCursor.image, defaultCursor.hotspot);
return;
}
QImage cursorImage;
cursorImage = buffer->data().copy();
cursorImage.setDevicePixelRatio(cursorSurface->bufferScale());
cursor->updateCursor(cursorImage, tcursor->hotspot());
});
emit cursor->cursorChanged();
} }
KWaylandServer::TabletV2Interface *tablet = tabletSeat->tabletByName(event->tabletSysName()); KWaylandServer::TabletV2Interface *tablet = tabletSeat->tabletByName(event->tabletId().m_tabletSysName);
Toplevel *toplevel = input()->findToplevel(event->globalPos()); Toplevel *toplevel = input()->findToplevel(event->globalPos());
if (!toplevel || !toplevel->surface()) { if (!toplevel || !toplevel->surface()) {
@ -1773,6 +1804,74 @@ public:
waylandServer()->simulateUserActivity(); waylandServer()->simulateUserActivity();
return true; return true;
} }
bool tabletToolButtonEvent(uint button, bool pressed, const TabletToolId &tabletToolId) override
{
KWaylandServer::TabletSeatV2Interface *tabletSeat = findTabletSeat();
auto tool = tabletSeat->toolByHardwareSerial(tabletToolId.m_serialId);
if (!tool) {
tool = createTool(tabletToolId);
}
tool->sendButton(button, pressed);
return true;
}
KWaylandServer::TabletPadV2Interface *findPad(const QString &deviceSysName) const
{
Toplevel *toplevel = workspace()->activeClient();
auto seat = findTabletSeat();
if (!toplevel || !toplevel->surface() || !seat->isClientSupported(toplevel->surface()->client())) {
return nullptr;
}
KWaylandServer::SurfaceInterface *surface = toplevel->surface();
auto pad = seat->padByName(deviceSysName);
pad->setCurrentSurface(surface);
return pad;
}
bool tabletPadButtonEvent(uint button, bool pressed, const QString &deviceSysName) override
{
auto pad = findPad(deviceSysName);
if (!pad) {
return false;
}
pad->sendButton(QDateTime::currentMSecsSinceEpoch(), button, pressed);
return true;
}
bool tabletPadRingEvent(int number, int angle, bool isFinger, const QString &deviceSysName) override
{
auto pad = findPad(deviceSysName);
if (!pad) {
return false;
}
auto ring = pad->ring(number);
ring->sendAngle(angle);
if (isFinger) {
ring->sendSource(KWaylandServer::TabletPadRingV2Interface::SourceFinger);
}
ring->sendFrame(QDateTime::currentMSecsSinceEpoch());
return true;
}
bool tabletPadStripEvent(int number, int position, bool isFinger, const QString &deviceSysName) override
{
auto pad = findPad(deviceSysName);
if (!pad) {
return false;
}
auto strip = pad->strip(number);
strip->sendPosition(position);
if (isFinger) {
strip->sendSource(KWaylandServer::TabletPadStripV2Interface::SourceFinger);
}
strip->sendFrame(QDateTime::currentMSecsSinceEpoch());
return true;
}
QHash<KWaylandServer::TabletToolV2Interface*, Cursor*> m_cursorByTool; QHash<KWaylandServer::TabletToolV2Interface*, Cursor*> m_cursorByTool;
}; };

View file

@ -43,6 +43,7 @@ class WindowSelectorFilter;
class SwitchEvent; class SwitchEvent;
class TabletEvent; class TabletEvent;
class TabletInputFilter; class TabletInputFilter;
class TabletToolId;
namespace Decoration namespace Decoration
{ {
@ -400,10 +401,10 @@ public:
virtual bool switchEvent(SwitchEvent *event); virtual bool switchEvent(SwitchEvent *event);
virtual bool tabletToolEvent(TabletEvent *event); virtual bool tabletToolEvent(TabletEvent *event);
virtual bool tabletToolButtonEvent(const QSet<uint> &buttons); virtual bool tabletToolButtonEvent(uint button, bool pressed, const TabletToolId &tabletToolId);
virtual bool tabletPadButtonEvent(const QSet<uint> &buttons); virtual bool tabletPadButtonEvent(uint button, bool pressed, const QString &deviceSysName);
virtual bool tabletPadStripEvent(int number, int position, bool isFinger); virtual bool tabletPadStripEvent(int number, int position, bool isFinger, const QString &deviceSysName);
virtual bool tabletPadRingEvent(int number, int position, bool isFinger); virtual bool tabletPadRingEvent(int number, int position, bool isFinger, const QString &deviceSysName);
protected: protected:
void passToWaylandServer(QKeyEvent *event); void passToWaylandServer(QKeyEvent *event);

View file

@ -58,12 +58,9 @@ TabletEvent::TabletEvent(Type t, const QPointF &pos, const QPointF &globalPos,
int device, int pointerType, qreal pressure, int xTilt, int yTilt, int device, int pointerType, qreal pressure, int xTilt, int yTilt,
qreal tangentialPressure, qreal rotation, int z, qreal tangentialPressure, qreal rotation, int z,
Qt::KeyboardModifiers keyState, qint64 uniqueID, Qt::KeyboardModifiers keyState, qint64 uniqueID,
Qt::MouseButton button, Qt::MouseButtons buttons, InputRedirection::TabletToolType toolType, const QVector<InputRedirection::Capability> &capabilities, quint64 serialId, const QString &tabletSysName) Qt::MouseButton button, Qt::MouseButtons buttons, const TabletToolId &tabletId)
: QTabletEvent(t, pos, globalPos, device, pointerType, pressure, xTilt, yTilt, tangentialPressure, rotation, z, keyState, uniqueID, button, buttons) : QTabletEvent(t, pos, globalPos, device, pointerType, pressure, xTilt, yTilt, tangentialPressure, rotation, z, keyState, uniqueID, button, buttons)
, m_toolType(toolType) , m_id(tabletId)
, m_capabilities(capabilities)
, m_serialId(serialId)
, m_tabletSysName(tabletSysName)
{ {
} }

View file

@ -165,6 +165,16 @@ private:
LibInput::Device *m_device; LibInput::Device *m_device;
}; };
class TabletToolId
{
public:
const InputRedirection::TabletToolType m_toolType;
const QVector<InputRedirection::Capability> m_capabilities;
const quint64 m_serialId;
const quint64 m_uniqueId;
const QString m_tabletSysName;
};
class TabletEvent : public QTabletEvent class TabletEvent : public QTabletEvent
{ {
public: public:
@ -172,20 +182,14 @@ public:
int device, int pointerType, qreal pressure, int xTilt, int yTilt, int device, int pointerType, qreal pressure, int xTilt, int yTilt,
qreal tangentialPressure, qreal rotation, int z, qreal tangentialPressure, qreal rotation, int z,
Qt::KeyboardModifiers keyState, qint64 uniqueID, Qt::KeyboardModifiers keyState, qint64 uniqueID,
Qt::MouseButton button, Qt::MouseButtons buttons, InputRedirection::TabletToolType toolType, Qt::MouseButton button, Qt::MouseButtons buttons, const TabletToolId &tabletId);
const QVector<InputRedirection::Capability> &capabilities,
quint64 serialId, const QString &tabletSysname);
InputRedirection::TabletToolType toolType() const { return m_toolType; } const TabletToolId &tabletId() const {
QVector<InputRedirection::Capability> capabilities() const { return m_capabilities; } return m_id;
quint64 serialId() const { return m_serialId; } }
QString tabletSysName() { return m_tabletSysName; }
private: private:
const InputRedirection::TabletToolType m_toolType; const TabletToolId m_id;
const QVector<InputRedirection::Capability> m_capabilities;
const quint64 m_serialId;
const QString m_tabletSysName;
}; };
} }

View file

@ -115,27 +115,33 @@ void InputEventSpy::tabletToolEvent(TabletEvent *event)
Q_UNUSED(event) Q_UNUSED(event)
} }
void InputEventSpy::tabletToolButtonEvent(const QSet<uint> &pressedButtons) void InputEventSpy::tabletToolButtonEvent(uint button, bool pressed, const TabletToolId &tabletToolId)
{ {
Q_UNUSED(pressedButtons) Q_UNUSED(button)
Q_UNUSED(pressed)
Q_UNUSED(tabletToolId)
} }
void InputEventSpy::tabletPadButtonEvent(const QSet<uint> &pressedButtons) void InputEventSpy::tabletPadButtonEvent(uint button, bool pressed, const QString &deviceSysName)
{ {
Q_UNUSED(pressedButtons) Q_UNUSED(button)
Q_UNUSED(pressed)
Q_UNUSED(deviceSysName)
} }
void InputEventSpy::tabletPadStripEvent(int number, int position, bool isFinger) void InputEventSpy::tabletPadStripEvent(int number, int position, bool isFinger, const QString &deviceSysName)
{ {
Q_UNUSED(number) Q_UNUSED(number)
Q_UNUSED(position) Q_UNUSED(position)
Q_UNUSED(isFinger) Q_UNUSED(isFinger)
Q_UNUSED(deviceSysName)
} }
void InputEventSpy::tabletPadRingEvent(int number, int position, bool isFinger) void InputEventSpy::tabletPadRingEvent(int number, int position, bool isFinger, const QString &deviceSysName)
{ {
Q_UNUSED(number) Q_UNUSED(number)
Q_UNUSED(position) Q_UNUSED(position)
Q_UNUSED(isFinger) Q_UNUSED(isFinger)
Q_UNUSED(deviceSysName)
} }
} }

View file

@ -23,6 +23,7 @@ class MouseEvent;
class WheelEvent; class WheelEvent;
class SwitchEvent; class SwitchEvent;
class TabletEvent; class TabletEvent;
class TabletToolId;
/** /**
* Base class for spying on input events inside InputRedirection. * Base class for spying on input events inside InputRedirection.
@ -75,10 +76,10 @@ public:
virtual void switchEvent(SwitchEvent *event); virtual void switchEvent(SwitchEvent *event);
virtual void tabletToolEvent(TabletEvent *event); virtual void tabletToolEvent(TabletEvent *event);
virtual void tabletToolButtonEvent(const QSet<uint> &pressedButtons); virtual void tabletToolButtonEvent(uint button, bool pressed, const TabletToolId &tabletToolId);
virtual void tabletPadButtonEvent(const QSet<uint> &pressedButtons); virtual void tabletPadButtonEvent(uint button, bool pressed, const QString &deviceSysName);
virtual void tabletPadStripEvent(int number, int position, bool isFinger); virtual void tabletPadStripEvent(int number, int position, bool isFinger, const QString &deviceSysName);
virtual void tabletPadRingEvent(int number, int position, bool isFinger); virtual void tabletPadRingEvent(int number, int position, bool isFinger, const QString &deviceSysName);
}; };

View file

@ -19,6 +19,7 @@
#include "../screens.h" #include "../screens.h"
#endif #endif
#include "../input_event.h"
#include "../logind.h" #include "../logind.h"
#include "../udev.h" #include "../udev.h"
#include "libinput_logging.h" #include "libinput_logging.h"
@ -270,6 +271,62 @@ QPointF devicePointToGlobalPosition(const QPointF &devicePos, const AbstractWayl
} }
#endif #endif
KWin::TabletToolId createTabletId(libinput_tablet_tool *tool, const QString &sysName)
{
auto serial = libinput_tablet_tool_get_serial(tool);
auto toolId = libinput_tablet_tool_get_tool_id(tool);
auto type = libinput_tablet_tool_get_type(tool);
InputRedirection::TabletToolType toolType;
switch (type) {
case LIBINPUT_TABLET_TOOL_TYPE_PEN:
toolType = InputRedirection::Pen;
break;
case LIBINPUT_TABLET_TOOL_TYPE_ERASER:
toolType = InputRedirection::Eraser;
break;
case LIBINPUT_TABLET_TOOL_TYPE_BRUSH:
toolType = InputRedirection::Brush;
break;
case LIBINPUT_TABLET_TOOL_TYPE_PENCIL:
toolType = InputRedirection::Pencil;
break;
case LIBINPUT_TABLET_TOOL_TYPE_AIRBRUSH:
toolType = InputRedirection::Airbrush;
break;
case LIBINPUT_TABLET_TOOL_TYPE_MOUSE:
toolType = InputRedirection::Mouse;
break;
case LIBINPUT_TABLET_TOOL_TYPE_LENS:
toolType = InputRedirection::Lens;
break;
#ifdef LIBINPUT_HAS_TOTEM
case LIBINPUT_TABLET_TOOL_TYPE_TOTEM:
toolType = InputRedirection::Totem;
break;
#endif
}
QVector<InputRedirection::Capability> capabilities;
if (libinput_tablet_tool_has_pressure(tool)) {
capabilities << InputRedirection::Pressure;
}
if (libinput_tablet_tool_has_distance(tool)) {
capabilities << InputRedirection::Distance;
}
if (libinput_tablet_tool_has_rotation(tool)) {
capabilities << InputRedirection::Rotation;
}
if (libinput_tablet_tool_has_tilt(tool)) {
capabilities << InputRedirection::Tilt;
}
if (libinput_tablet_tool_has_slider(tool)) {
capabilities << InputRedirection::Slider;
}
if (libinput_tablet_tool_has_wheel(tool)) {
capabilities << InputRedirection::Wheel;
}
return {toolType, capabilities, serial, toolId, sysName};
}
void Connection::processEvents() void Connection::processEvents()
{ {
QMutexLocker locker(&m_mutex); QMutexLocker locker(&m_mutex);
@ -515,57 +572,6 @@ void Connection::processEvents()
tabletEventType = KWin::InputRedirection::Tip; tabletEventType = KWin::InputRedirection::Tip;
break; break;
} }
auto serial = libinput_tablet_tool_get_serial(tte->tool());
auto toolId = libinput_tablet_tool_get_tool_id(tte->tool());
auto type = libinput_tablet_tool_get_type(tte->tool());
InputRedirection::TabletToolType toolType;
switch (type) {
case LIBINPUT_TABLET_TOOL_TYPE_PEN:
toolType = InputRedirection::Pen;
break;
case LIBINPUT_TABLET_TOOL_TYPE_ERASER:
toolType = InputRedirection::Eraser;
break;
case LIBINPUT_TABLET_TOOL_TYPE_BRUSH:
toolType = InputRedirection::Brush;
break;
case LIBINPUT_TABLET_TOOL_TYPE_PENCIL:
toolType = InputRedirection::Pencil;
break;
case LIBINPUT_TABLET_TOOL_TYPE_AIRBRUSH:
toolType = InputRedirection::Airbrush;
break;
case LIBINPUT_TABLET_TOOL_TYPE_MOUSE:
toolType = InputRedirection::Mouse;
break;
case LIBINPUT_TABLET_TOOL_TYPE_LENS:
toolType = InputRedirection::Lens;
break;
#ifdef LIBINPUT_HAS_TOTEM
case LIBINPUT_TABLET_TOOL_TYPE_TOTEM:
toolType = InputRedirection::Totem;
break;
#endif
}
QVector<InputRedirection::Capability> capabilities;
if (libinput_tablet_tool_has_pressure(tte->tool())) {
capabilities << InputRedirection::Pressure;
}
if (libinput_tablet_tool_has_distance(tte->tool())) {
capabilities << InputRedirection::Distance;
}
if (libinput_tablet_tool_has_rotation(tte->tool())) {
capabilities << InputRedirection::Rotation;
}
if (libinput_tablet_tool_has_tilt(tte->tool())) {
capabilities << InputRedirection::Tilt;
}
if (libinput_tablet_tool_has_slider(tte->tool())) {
capabilities << InputRedirection::Slider;
}
if (libinput_tablet_tool_has_wheel(tte->tool())) {
capabilities << InputRedirection::Wheel;
}
#ifndef KWIN_BUILD_TESTING #ifndef KWIN_BUILD_TESTING
const auto *output = static_cast<AbstractWaylandOutput*>( const auto *output = static_cast<AbstractWaylandOutput*>(
@ -579,29 +585,31 @@ void Connection::processEvents()
emit tabletToolEvent(tabletEventType, emit tabletToolEvent(tabletEventType,
globalPos, tte->pressure(), globalPos, tte->pressure(),
tte->xTilt(), tte->yTilt(), tte->rotation(), tte->xTilt(), tte->yTilt(), tte->rotation(),
tte->isTipDown(), tte->isNearby(), serial, tte->isTipDown(), tte->isNearby(), createTabletId(tte->tool(), event->device()->sysName()), tte->time());
toolId, toolType, capabilities, tte->time(),
event->device());
break; break;
} }
case LIBINPUT_EVENT_TABLET_TOOL_BUTTON: { case LIBINPUT_EVENT_TABLET_TOOL_BUTTON: {
auto *tabletEvent = static_cast<TabletToolButtonEvent *>(event.data()); auto *tabletEvent = static_cast<TabletToolButtonEvent *>(event.data());
emit tabletToolButtonEvent(tabletEvent->buttonId(), emit tabletToolButtonEvent(tabletEvent->buttonId(),
tabletEvent->isButtonPressed()); tabletEvent->isButtonPressed(),
createTabletId(tabletEvent->tool(), event->device()->sysName()));
break; break;
} }
case LIBINPUT_EVENT_TABLET_PAD_BUTTON: { case LIBINPUT_EVENT_TABLET_PAD_BUTTON: {
auto *tabletEvent = static_cast<TabletPadButtonEvent *>(event.data()); auto *tabletEvent = static_cast<TabletPadButtonEvent *>(event.data());
emit tabletPadButtonEvent(tabletEvent->buttonId(), emit tabletPadButtonEvent(tabletEvent->buttonId(),
tabletEvent->isButtonPressed()); tabletEvent->isButtonPressed(),
event->device()->sysName());
break; break;
} }
case LIBINPUT_EVENT_TABLET_PAD_RING: { case LIBINPUT_EVENT_TABLET_PAD_RING: {
auto *tabletEvent = static_cast<TabletPadRingEvent *>(event.data()); auto *tabletEvent = static_cast<TabletPadRingEvent *>(event.data());
tabletEvent->position();
emit tabletPadRingEvent(tabletEvent->number(), emit tabletPadRingEvent(tabletEvent->number(),
tabletEvent->position(), tabletEvent->position(),
tabletEvent->source() == tabletEvent->source() ==
LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER); LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER,
event->device()->sysName());
break; break;
} }
case LIBINPUT_EVENT_TABLET_PAD_STRIP: { case LIBINPUT_EVENT_TABLET_PAD_STRIP: {
@ -609,7 +617,8 @@ void Connection::processEvents()
emit tabletPadStripEvent(tabletEvent->number(), emit tabletPadStripEvent(tabletEvent->number(),
tabletEvent->position(), tabletEvent->position(),
tabletEvent->source() == tabletEvent->source() ==
LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER); LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER,
event->device()->sysName());
break; break;
} }
default: default:

View file

@ -122,16 +122,12 @@ Q_SIGNALS:
void tabletToolEvent(KWin::InputRedirection::TabletEventType type, const QPointF &pos, void tabletToolEvent(KWin::InputRedirection::TabletEventType type, const QPointF &pos,
qreal pressure, int xTilt, int yTilt, qreal rotation, bool tipDown, qreal pressure, int xTilt, int yTilt, qreal rotation, bool tipDown,
bool tipNear, quint64 serialId, quint64 toolId, bool tipNear, const TabletToolId &tabletToolId, quint32 time);
InputRedirection::TabletToolType toolType, void tabletToolButtonEvent(uint button, bool isPressed, const TabletToolId &tabletToolId);
const QVector<InputRedirection::Capability> &capabilities,
quint32 time,
LibInput::Device *device);
void tabletToolButtonEvent(uint button, bool isPressed);
void tabletPadButtonEvent(uint button, bool isPressed); void tabletPadButtonEvent(uint button, bool isPressed, const QString &sysName);
void tabletPadStripEvent(int number, int position, bool isFinger); void tabletPadStripEvent(int number, int position, bool isFinger, const QString &sysName);
void tabletPadRingEvent(int number, int position, bool isFinger); void tabletPadRingEvent(int number, int position, bool isFinger, const QString &sysName);
void eventsRead(); void eventsRead();

View file

@ -296,6 +296,10 @@ public:
return state == LIBINPUT_BUTTON_STATE_PRESSED; return state == LIBINPUT_BUTTON_STATE_PRESSED;
} }
struct libinput_tablet_tool *tool() {
return libinput_event_tablet_tool_get_tool(m_tabletToolEvent);
}
private: private:
libinput_event_tablet_tool *m_tabletToolEvent; libinput_event_tablet_tool *m_tabletToolEvent;
}; };

View file

@ -45,14 +45,10 @@ void TabletInputRedirection::init()
connect(waylandServer(), &QObject::destroyed, this, [this] { setInited(false); }); connect(waylandServer(), &QObject::destroyed, this, [this] { setInited(false); });
} }
void TabletInputRedirection::tabletToolEvent(KWin::InputRedirection::TabletEventType type, void TabletInputRedirection::tabletToolEvent(KWin::InputRedirection::TabletEventType type, const QPointF &pos,
const QPointF &pos, qreal pressure, qreal pressure, int xTilt, int yTilt, qreal rotation, bool tipDown,
int xTilt, int yTilt, qreal rotation, bool tipNear, const TabletToolId &tabletToolId,
bool tipDown, bool tipNear, quint64 serialId, quint32 time)
quint64 toolId,
InputRedirection::TabletToolType toolType,
const QVector<InputRedirection::Capability> &capabilities,
quint32 time, LibInput::Device *device)
{ {
if (!inited()) { if (!inited()) {
return; return;
@ -78,7 +74,7 @@ void TabletInputRedirection::tabletToolEvent(KWin::InputRedirection::TabletEvent
0, // tangentialPressure 0, // tangentialPressure
rotation, rotation,
0, // z 0, // z
Qt::NoModifier, toolId, button, button, toolType, capabilities, serialId, device->sysName()); Qt::NoModifier, tabletToolId.m_uniqueId, button, button, tabletToolId);
ev.setTimestamp(time); ev.setTimestamp(time);
input()->processSpies(std::bind(&InputEventSpy::tabletToolEvent, std::placeholders::_1, &ev)); input()->processSpies(std::bind(&InputEventSpy::tabletToolEvent, std::placeholders::_1, &ev));
@ -89,47 +85,40 @@ void TabletInputRedirection::tabletToolEvent(KWin::InputRedirection::TabletEvent
m_tipNear = tipNear; m_tipNear = tipNear;
} }
void KWin::TabletInputRedirection::tabletToolButtonEvent(uint button, bool isPressed) void KWin::TabletInputRedirection::tabletToolButtonEvent(uint button, bool isPressed,
const TabletToolId &tabletToolId)
{ {
if (isPressed)
m_toolPressedButtons.insert(button);
else
m_toolPressedButtons.remove(button);
input()->processSpies(std::bind(&InputEventSpy::tabletToolButtonEvent, input()->processSpies(std::bind(&InputEventSpy::tabletToolButtonEvent,
std::placeholders::_1, m_toolPressedButtons)); std::placeholders::_1, button, isPressed, tabletToolId));
input()->processFilters(std::bind( &InputEventFilter::tabletToolButtonEvent, input()->processFilters(std::bind( &InputEventFilter::tabletToolButtonEvent,
std::placeholders::_1, m_toolPressedButtons)); std::placeholders::_1, button, isPressed, tabletToolId));
} }
void KWin::TabletInputRedirection::tabletPadButtonEvent(uint button, bool isPressed) void KWin::TabletInputRedirection::tabletPadButtonEvent(uint button, bool isPressed,
const QString &deviceSysName)
{ {
if (isPressed) {
m_padPressedButtons.insert(button);
} else {
m_padPressedButtons.remove(button);
}
input()->processSpies(std::bind( &InputEventSpy::tabletPadButtonEvent, input()->processSpies(std::bind( &InputEventSpy::tabletPadButtonEvent,
std::placeholders::_1, m_padPressedButtons)); std::placeholders::_1, button, isPressed, deviceSysName));
input()->processFilters(std::bind( &InputEventFilter::tabletPadButtonEvent, input()->processFilters(std::bind( &InputEventFilter::tabletPadButtonEvent,
std::placeholders::_1, m_padPressedButtons)); std::placeholders::_1, button, isPressed, deviceSysName));
} }
void KWin::TabletInputRedirection::tabletPadStripEvent(int number, int position, bool isFinger) void KWin::TabletInputRedirection::tabletPadStripEvent(int number, int position, bool isFinger,
const QString &deviceSysName)
{ {
input()->processSpies(std::bind( &InputEventSpy::tabletPadStripEvent, input()->processSpies(std::bind( &InputEventSpy::tabletPadStripEvent,
std::placeholders::_1, number, position, isFinger)); std::placeholders::_1, number, position, isFinger, deviceSysName));
input()->processFilters(std::bind( &InputEventFilter::tabletPadStripEvent, input()->processFilters(std::bind( &InputEventFilter::tabletPadStripEvent,
std::placeholders::_1, number, position, isFinger)); std::placeholders::_1, number, position, isFinger, deviceSysName));
} }
void KWin::TabletInputRedirection::tabletPadRingEvent(int number, int position, bool isFinger) void KWin::TabletInputRedirection::tabletPadRingEvent(int number, int position, bool isFinger,
const QString &deviceSysName)
{ {
input()->processSpies(std::bind( &InputEventSpy::tabletPadRingEvent, input()->processSpies(std::bind( &InputEventSpy::tabletPadRingEvent,
std::placeholders::_1, number, position, isFinger)); std::placeholders::_1, number, position, isFinger, deviceSysName));
input()->processFilters(std::bind( &InputEventFilter::tabletPadRingEvent, input()->processFilters(std::bind( &InputEventFilter::tabletPadRingEvent,
std::placeholders::_1, number, position, isFinger)); std::placeholders::_1, number, position, isFinger, deviceSysName));
} }
void TabletInputRedirection::cleanupDecoration(Decoration::DecoratedClientImpl *old, void TabletInputRedirection::cleanupDecoration(Decoration::DecoratedClientImpl *old,

View file

@ -19,6 +19,7 @@
namespace KWin namespace KWin
{ {
class Toplevel; class Toplevel;
class TabletToolId;
namespace Decoration namespace Decoration
{ {
@ -41,14 +42,13 @@ public:
void tabletToolEvent(KWin::InputRedirection::TabletEventType type, const QPointF &pos, void tabletToolEvent(KWin::InputRedirection::TabletEventType type, const QPointF &pos,
qreal pressure, int xTilt, int yTilt, qreal rotation, bool tipDown, qreal pressure, int xTilt, int yTilt, qreal rotation, bool tipDown,
bool tipNear, quint64 serialId, quint64 toolId, bool tipNear, const TabletToolId &tabletToolId,
InputRedirection::TabletToolType toolType, const QVector<InputRedirection::Capability> &capabilities, quint32 time);
quint32 time, LibInput::Device *device); void tabletToolButtonEvent(uint button, bool isPressed, const TabletToolId &tabletToolId);
void tabletToolButtonEvent(uint button, bool isPressed);
void tabletPadButtonEvent(uint button, bool isPressed); void tabletPadButtonEvent(uint button, bool isPressed, const QString &deviceSysName);
void tabletPadStripEvent(int number, int position, bool isFinger); void tabletPadStripEvent(int number, int position, bool isFinger, const QString &deviceSysName);
void tabletPadRingEvent(int number, int position, bool isFinger); void tabletPadRingEvent(int number, int position, bool isFinger, const QString &deviceSysName);
bool positionValid() const override bool positionValid() const override
{ {
@ -71,8 +71,6 @@ private:
bool m_tipNear = false; bool m_tipNear = false;
QPointF m_lastPosition; QPointF m_lastPosition;
QSet<uint> m_toolPressedButtons;
QSet<uint> m_padPressedButtons;
}; };
} }