Implement the tablet wayland protocol in kwin
Summary: Uses the tablet classes introduced in kwayland. Depends on D26858 Test Plan: Scratched my tablet with a magic stick and it did things depending on the pressure. https://youtu.be/GGx0TlNJlzs Reviewers: #kwin, #plasma, zzag, davidedmundson Reviewed By: #kwin, #plasma, zzag, davidedmundson Subscribers: davidedmundson, zzag, kwin Tags: #kwin Differential Revision: https://phabricator.kde.org/D26859
This commit is contained in:
parent
bb04ab390d
commit
e0052cedcb
21 changed files with 370 additions and 46 deletions
|
@ -654,6 +654,9 @@ set(kwinLibs
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(kwin SHARED ${kwin_SRCS})
|
add_library(kwin SHARED ${kwin_SRCS})
|
||||||
|
if (Libinput_VERSION_STRING VERSION_GREATER 1.14)
|
||||||
|
target_compile_definitions(kwin PRIVATE -DLIBINPUT_HAS_TOTEM)
|
||||||
|
endif ()
|
||||||
|
|
||||||
set_target_properties(kwin PROPERTIES
|
set_target_properties(kwin PROPERTIES
|
||||||
VERSION ${PROJECT_VERSION}
|
VERSION ${PROJECT_VERSION}
|
||||||
|
|
|
@ -916,3 +916,21 @@ libinput_event_get_tablet_tool_event(struct libinput_event *event)
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
libinput_device_tablet_pad_get_num_strips(struct libinput_device *device)
|
||||||
|
{
|
||||||
|
return device->stripCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
libinput_device_tablet_pad_get_num_rings(struct libinput_device *device)
|
||||||
|
{
|
||||||
|
return device->ringCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
libinput_device_tablet_pad_get_num_buttons(struct libinput_device *device)
|
||||||
|
{
|
||||||
|
return device->buttonCount;
|
||||||
|
}
|
||||||
|
|
|
@ -105,6 +105,9 @@ struct libinput_device {
|
||||||
enum libinput_config_click_method defaultClickMethod = LIBINPUT_CONFIG_CLICK_METHOD_NONE;
|
enum libinput_config_click_method defaultClickMethod = LIBINPUT_CONFIG_CLICK_METHOD_NONE;
|
||||||
enum libinput_config_click_method clickMethod = LIBINPUT_CONFIG_CLICK_METHOD_NONE;
|
enum libinput_config_click_method clickMethod = LIBINPUT_CONFIG_CLICK_METHOD_NONE;
|
||||||
bool setClickMethodReturnValue = 0;
|
bool setClickMethodReturnValue = 0;
|
||||||
|
uint32_t buttonCount = 0;
|
||||||
|
uint32_t stripCount = 0;
|
||||||
|
uint32_t ringCount = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct libinput_event {
|
struct libinput_event {
|
||||||
|
|
|
@ -28,6 +28,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#include "wayland_server.h"
|
#include "wayland_server.h"
|
||||||
#include "workspace.h"
|
#include "workspace.h"
|
||||||
#include "keyboard_input.h"
|
#include "keyboard_input.h"
|
||||||
|
#include "input_event.h"
|
||||||
#include "libinput/connection.h"
|
#include "libinput/connection.h"
|
||||||
#include "libinput/device.h"
|
#include "libinput/device.h"
|
||||||
#include <kwinglplatform.h>
|
#include <kwinglplatform.h>
|
||||||
|
@ -486,7 +487,7 @@ void DebugConsoleFilter::switchEvent(SwitchEvent *event)
|
||||||
m_textEdit->ensureCursorVisible();
|
m_textEdit->ensureCursorVisible();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugConsoleFilter::tabletToolEvent(QTabletEvent *event)
|
void DebugConsoleFilter::tabletToolEvent(TabletEvent *event)
|
||||||
{
|
{
|
||||||
QString typeString;
|
QString typeString;
|
||||||
{
|
{
|
||||||
|
|
|
@ -153,7 +153,7 @@ public:
|
||||||
|
|
||||||
void switchEvent(SwitchEvent *event) override;
|
void switchEvent(SwitchEvent *event) override;
|
||||||
|
|
||||||
void tabletToolEvent(QTabletEvent *event) override;
|
void tabletToolEvent(TabletEvent *event) override;
|
||||||
void tabletToolButtonEvent(const QSet<uint> &pressedButtons) override;
|
void tabletToolButtonEvent(const QSet<uint> &pressedButtons) override;
|
||||||
void tabletPadButtonEvent(const QSet<uint> &pressedButtons) override;
|
void tabletPadButtonEvent(const QSet<uint> &pressedButtons) override;
|
||||||
void tabletPadStripEvent(int number, int position, bool isFinger) override;
|
void tabletPadStripEvent(int number, int position, bool isFinger) override;
|
||||||
|
|
211
input.cpp
211
input.cpp
|
@ -36,24 +36,28 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#ifdef KWIN_BUILD_TABBOX
|
#ifdef KWIN_BUILD_TABBOX
|
||||||
#include "tabbox/tabbox.h"
|
#include "tabbox/tabbox.h"
|
||||||
#endif
|
#endif
|
||||||
#include "unmanaged.h"
|
#include "internal_client.h"
|
||||||
#include "screenedge.h"
|
|
||||||
#include "screens.h"
|
|
||||||
#include "workspace.h"
|
|
||||||
#include "libinput/connection.h"
|
#include "libinput/connection.h"
|
||||||
#include "libinput/device.h"
|
#include "libinput/device.h"
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "popup_input_filter.h"
|
#include "popup_input_filter.h"
|
||||||
|
#include "screenedge.h"
|
||||||
|
#include "screens.h"
|
||||||
|
#include "unmanaged.h"
|
||||||
#include "wayland_server.h"
|
#include "wayland_server.h"
|
||||||
|
#include "workspace.h"
|
||||||
|
#include "xdgshellclient.h"
|
||||||
#include "xwl/xwayland_interface.h"
|
#include "xwl/xwayland_interface.h"
|
||||||
#include "internal_client.h"
|
#include "cursor.h"
|
||||||
#include <KWayland/Server/display.h>
|
|
||||||
#include <KWayland/Server/fakeinput_interface.h>
|
|
||||||
#include <KWayland/Server/seat_interface.h>
|
|
||||||
#include <KWayland/Server/relativepointer_interface.h>
|
|
||||||
#include <decorations/decoratedclient.h>
|
|
||||||
#include <KDecoration2/Decoration>
|
#include <KDecoration2/Decoration>
|
||||||
#include <KGlobalAccel>
|
#include <KGlobalAccel>
|
||||||
|
#include <KWayland/Server/display.h>
|
||||||
|
#include <KWayland/Server/fakeinput_interface.h>
|
||||||
|
#include <KWayland/Server/relativepointer_interface.h>
|
||||||
|
#include <KWayland/Server/seat_interface.h>
|
||||||
|
#include <KWayland/Server/surface_interface.h>
|
||||||
|
#include <KWayland/Server/tablet_interface.h>
|
||||||
|
#include <decorations/decoratedclient.h>
|
||||||
|
|
||||||
//screenlocker
|
//screenlocker
|
||||||
#include <KScreenLocker/KsldApp>
|
#include <KScreenLocker/KsldApp>
|
||||||
|
@ -176,7 +180,7 @@ bool InputEventFilter::switchEvent(SwitchEvent *event)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InputEventFilter::tabletToolEvent(QTabletEvent *event)
|
bool InputEventFilter::tabletToolEvent(TabletEvent *event)
|
||||||
{
|
{
|
||||||
Q_UNUSED(event)
|
Q_UNUSED(event)
|
||||||
return false;
|
return false;
|
||||||
|
@ -1531,17 +1535,174 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static KWayland::Server::SeatInterface *findSeat()
|
||||||
|
{
|
||||||
|
auto server = waylandServer();
|
||||||
|
if (!server) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return server->seat();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Useful when there's no proper tablet support on the clients
|
* Useful when there's no proper tablet support on the clients
|
||||||
*/
|
*/
|
||||||
class FakeTabletInputFilter : public InputEventFilter
|
class TabletInputFilter : public QObject, public InputEventFilter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FakeTabletInputFilter()
|
TabletInputFilter()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool tabletToolEvent(QTabletEvent *event) override
|
static KWayland::Server::TabletSeatInterface *findTabletSeat()
|
||||||
|
{
|
||||||
|
auto server = waylandServer();
|
||||||
|
if (!server) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
KWayland::Server::TabletManagerInterface *manager = server->tabletManager();
|
||||||
|
return manager->seat(findSeat());
|
||||||
|
}
|
||||||
|
|
||||||
|
void integrateDevice(LibInput::Device *device)
|
||||||
|
{
|
||||||
|
if (device->isTabletTool()) {
|
||||||
|
KWayland::Server::TabletSeatInterface *tabletSeat = findTabletSeat();
|
||||||
|
struct udev_device *const udev_device = libinput_device_get_udev_device(device->device());
|
||||||
|
const char *devnode = udev_device_get_devnode(udev_device);
|
||||||
|
tabletSeat->addTablet(device->vendor(), device->product(), device->sysName(), device->name(), {QString::fromUtf8(devnode)});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void removeDevice(const QString &sysname)
|
||||||
|
{
|
||||||
|
KWayland::Server::TabletSeatInterface *tabletSeat = findTabletSeat();
|
||||||
|
tabletSeat->removeTablet(sysname);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool tabletToolEvent(TabletEvent *event) override
|
||||||
|
{
|
||||||
|
if (!workspace()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
KWayland::Server::TabletSeatInterface *tabletSeat = findTabletSeat();
|
||||||
|
auto tool = tabletSeat->toolByHardwareSerial(event->serialId());
|
||||||
|
if (!tool) {
|
||||||
|
using namespace KWayland::Server;
|
||||||
|
|
||||||
|
const QVector<InputRedirection::Capability> capabilities = event->capabilities();
|
||||||
|
const auto f = [](InputRedirection::Capability cap) {
|
||||||
|
switch (cap) {
|
||||||
|
case InputRedirection::Tilt:
|
||||||
|
return TabletToolInterface::Tilt;
|
||||||
|
case InputRedirection::Pressure:
|
||||||
|
return TabletToolInterface::Pressure;
|
||||||
|
case InputRedirection::Distance:
|
||||||
|
return TabletToolInterface::Distance;
|
||||||
|
case InputRedirection::Rotation:
|
||||||
|
return TabletToolInterface::Rotation;
|
||||||
|
case InputRedirection::Slider:
|
||||||
|
return TabletToolInterface::Slider;
|
||||||
|
case InputRedirection::Wheel:
|
||||||
|
return TabletToolInterface::Wheel;
|
||||||
|
}
|
||||||
|
return TabletToolInterface::Wheel;
|
||||||
|
};
|
||||||
|
QVector<TabletToolInterface::Capability> ifaceCapabilities;
|
||||||
|
ifaceCapabilities.resize(capabilities.size());
|
||||||
|
std::transform(capabilities.constBegin(), capabilities.constEnd(), ifaceCapabilities.begin(), f);
|
||||||
|
|
||||||
|
TabletToolInterface::Type toolType = TabletToolInterface::Type::Pen;
|
||||||
|
switch (event->toolType()) {
|
||||||
|
case InputRedirection::Pen:
|
||||||
|
toolType = TabletToolInterface::Type::Pen;
|
||||||
|
break;
|
||||||
|
case InputRedirection::Eraser:
|
||||||
|
toolType = TabletToolInterface::Type::Eraser;
|
||||||
|
break;
|
||||||
|
case InputRedirection::Brush:
|
||||||
|
toolType = TabletToolInterface::Type::Brush;
|
||||||
|
break;
|
||||||
|
case InputRedirection::Pencil:
|
||||||
|
toolType = TabletToolInterface::Type::Pencil;
|
||||||
|
break;
|
||||||
|
case InputRedirection::Airbrush:
|
||||||
|
toolType = TabletToolInterface::Type::Airbrush;
|
||||||
|
break;
|
||||||
|
case InputRedirection::Finger:
|
||||||
|
toolType = TabletToolInterface::Type::Finger;
|
||||||
|
break;
|
||||||
|
case InputRedirection::Mouse:
|
||||||
|
toolType = TabletToolInterface::Type::Mouse;
|
||||||
|
break;
|
||||||
|
case InputRedirection::Lens:
|
||||||
|
toolType = TabletToolInterface::Type::Lens;
|
||||||
|
break;
|
||||||
|
case InputRedirection::Totem:
|
||||||
|
toolType = TabletToolInterface::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->cursor(), &TabletCursor::changed, cursor, &Cursor::cursorChanged);
|
||||||
|
connect(tool->cursor(), &TabletCursor::changed, cursor, [cursor, tool] {
|
||||||
|
// cursor->setImage(tool->cursor()->image());
|
||||||
|
QPixmap redRect(20, 20);
|
||||||
|
redRect.fill(Qt::red);
|
||||||
|
cursor->setImage(redRect.toImage());
|
||||||
|
cursor->setHotspot(tool->cursor()->hotspot());
|
||||||
|
});
|
||||||
|
emit cursor->cursorChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
KWayland::Server::TabletInterface *tablet = tabletSeat->tabletByName(event->tabletSysName());
|
||||||
|
|
||||||
|
Toplevel *toplevel = input()->findToplevel(event->globalPos());
|
||||||
|
if (!toplevel || !toplevel->surface()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
KWayland::Server::SurfaceInterface *surface = toplevel->surface();
|
||||||
|
tool->setCurrentSurface(surface);
|
||||||
|
|
||||||
|
if (!tool->isClientSupported() || !tablet->isSurfaceSupported(surface)) {
|
||||||
|
return emulateTabletEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (event->type()) {
|
||||||
|
case QEvent::TabletMove: {
|
||||||
|
const auto pos = event->globalPosF() - toplevel->pos();
|
||||||
|
tool->sendMotion(pos);
|
||||||
|
m_cursorByTool[tool]->setPos(pos.toPoint());
|
||||||
|
break;
|
||||||
|
} case QEvent::TabletEnterProximity: {
|
||||||
|
tool->sendProximityIn(tablet);
|
||||||
|
break;
|
||||||
|
} case QEvent::TabletLeaveProximity:
|
||||||
|
tool->sendProximityOut();
|
||||||
|
break;
|
||||||
|
case QEvent::TabletPress:
|
||||||
|
tool->sendDown();
|
||||||
|
break;
|
||||||
|
case QEvent::TabletRelease:
|
||||||
|
tool->sendUp();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
qCWarning(KWIN_CORE) << "Unexpected tablet event type" << event;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const quint32 MAX_VAL = 65535;
|
||||||
|
tool->sendPressure(MAX_VAL * event->pressure());
|
||||||
|
tool->sendFrame(event->timestamp());
|
||||||
|
waylandServer()->simulateUserActivity();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool emulateTabletEvent(TabletEvent *event)
|
||||||
{
|
{
|
||||||
if (!workspace()) {
|
if (!workspace()) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -1569,6 +1730,7 @@ public:
|
||||||
waylandServer()->simulateUserActivity();
|
waylandServer()->simulateUserActivity();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
QHash<KWayland::Server::TabletToolInterface*, Cursor*> m_cursorByTool;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DragAndDropInputFilter : public InputEventFilter
|
class DragAndDropInputFilter : public InputEventFilter
|
||||||
|
@ -1932,7 +2094,16 @@ void InputRedirection::setupInputFilters()
|
||||||
if (waylandServer()) {
|
if (waylandServer()) {
|
||||||
installInputEventFilter(new WindowActionInputFilter);
|
installInputEventFilter(new WindowActionInputFilter);
|
||||||
installInputEventFilter(new ForwardInputFilter);
|
installInputEventFilter(new ForwardInputFilter);
|
||||||
installInputEventFilter(new FakeTabletInputFilter);
|
|
||||||
|
if (m_libInput) {
|
||||||
|
m_tabletSupport = new TabletInputFilter;
|
||||||
|
for (LibInput::Device *dev : m_libInput->devices()) {
|
||||||
|
m_tabletSupport->integrateDevice(dev);
|
||||||
|
}
|
||||||
|
connect(m_libInput, &LibInput::Connection::deviceAdded, m_tabletSupport, &TabletInputFilter::integrateDevice);
|
||||||
|
connect(m_libInput, &LibInput::Connection::deviceRemovedSysName, m_tabletSupport, &TabletInputFilter::removeDevice);
|
||||||
|
installInputEventFilter(m_tabletSupport);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1950,15 +2121,6 @@ void InputRedirection::reconfigure()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static KWayland::Server::SeatInterface *findSeat()
|
|
||||||
{
|
|
||||||
auto server = waylandServer();
|
|
||||||
if (!server) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return server->seat();
|
|
||||||
}
|
|
||||||
|
|
||||||
void InputRedirection::setupLibInput()
|
void InputRedirection::setupLibInput()
|
||||||
{
|
{
|
||||||
if (!Application::usesLibinput()) {
|
if (!Application::usesLibinput()) {
|
||||||
|
@ -2087,6 +2249,7 @@ void InputRedirection::setupLibInput()
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
setupTouchpadShortcuts();
|
setupTouchpadShortcuts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
25
input.h
25
input.h
|
@ -51,6 +51,8 @@ class TabletInputRedirection;
|
||||||
class TouchInputRedirection;
|
class TouchInputRedirection;
|
||||||
class WindowSelectorFilter;
|
class WindowSelectorFilter;
|
||||||
class SwitchEvent;
|
class SwitchEvent;
|
||||||
|
class TabletEvent;
|
||||||
|
class TabletInputFilter;
|
||||||
|
|
||||||
namespace Decoration
|
namespace Decoration
|
||||||
{
|
{
|
||||||
|
@ -100,6 +102,26 @@ public:
|
||||||
Proximity,
|
Proximity,
|
||||||
Tip
|
Tip
|
||||||
};
|
};
|
||||||
|
enum TabletToolType {
|
||||||
|
Pen,
|
||||||
|
Eraser,
|
||||||
|
Brush,
|
||||||
|
Pencil,
|
||||||
|
Airbrush,
|
||||||
|
Finger,
|
||||||
|
Mouse,
|
||||||
|
Lens,
|
||||||
|
Totem,
|
||||||
|
};
|
||||||
|
enum Capability {
|
||||||
|
Tilt,
|
||||||
|
Pressure,
|
||||||
|
Distance,
|
||||||
|
Rotation,
|
||||||
|
Slider,
|
||||||
|
Wheel,
|
||||||
|
};
|
||||||
|
|
||||||
~InputRedirection() override;
|
~InputRedirection() override;
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
|
@ -297,6 +319,7 @@ private:
|
||||||
PointerInputRedirection *m_pointer;
|
PointerInputRedirection *m_pointer;
|
||||||
TabletInputRedirection *m_tablet;
|
TabletInputRedirection *m_tablet;
|
||||||
TouchInputRedirection *m_touch;
|
TouchInputRedirection *m_touch;
|
||||||
|
TabletInputFilter *m_tabletSupport = nullptr;
|
||||||
|
|
||||||
GlobalShortcutsManager *m_shortcuts;
|
GlobalShortcutsManager *m_shortcuts;
|
||||||
|
|
||||||
|
@ -382,7 +405,7 @@ public:
|
||||||
|
|
||||||
virtual bool switchEvent(SwitchEvent *event);
|
virtual bool switchEvent(SwitchEvent *event);
|
||||||
|
|
||||||
virtual bool tabletToolEvent(QTabletEvent *event);
|
virtual bool tabletToolEvent(TabletEvent *event);
|
||||||
virtual bool tabletToolButtonEvent(const QSet<uint> &buttons);
|
virtual bool tabletToolButtonEvent(const QSet<uint> &buttons);
|
||||||
virtual bool tabletPadButtonEvent(const QSet<uint> &buttons);
|
virtual bool tabletPadButtonEvent(const QSet<uint> &buttons);
|
||||||
virtual bool tabletPadStripEvent(int number, int position, bool isFinger);
|
virtual bool tabletPadStripEvent(int number, int position, bool isFinger);
|
||||||
|
|
|
@ -65,4 +65,17 @@ SwitchEvent::SwitchEvent(State state, quint32 timestamp, quint64 timestampMicros
|
||||||
setTimestamp(timestamp);
|
setTimestamp(timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TabletEvent::TabletEvent(Type t, const QPointF &pos, const QPointF &globalPos,
|
||||||
|
int device, int pointerType, qreal pressure, int xTilt, int yTilt,
|
||||||
|
qreal tangentialPressure, qreal rotation, int z,
|
||||||
|
Qt::KeyboardModifiers keyState, qint64 uniqueID,
|
||||||
|
Qt::MouseButton button, Qt::MouseButtons buttons, InputRedirection::TabletToolType toolType, const QVector<InputRedirection::Capability> &capabilities, quint64 serialId, const QString &tabletSysName)
|
||||||
|
: QTabletEvent(t, pos, globalPos, device, pointerType, pressure, xTilt, yTilt, tangentialPressure, rotation, z, keyState, uniqueID, button, buttons)
|
||||||
|
, m_toolType(toolType)
|
||||||
|
, m_capabilities(capabilities)
|
||||||
|
, m_serialId(serialId)
|
||||||
|
, m_tabletSysName(tabletSysName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -176,6 +176,29 @@ private:
|
||||||
LibInput::Device *m_device;
|
LibInput::Device *m_device;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class TabletEvent : public QTabletEvent
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TabletEvent(Type t, const QPointF &pos, const QPointF &globalPos,
|
||||||
|
int device, int pointerType, qreal pressure, int xTilt, int yTilt,
|
||||||
|
qreal tangentialPressure, qreal rotation, int z,
|
||||||
|
Qt::KeyboardModifiers keyState, qint64 uniqueID,
|
||||||
|
Qt::MouseButton button, Qt::MouseButtons buttons, InputRedirection::TabletToolType toolType,
|
||||||
|
const QVector<InputRedirection::Capability> &capabilities,
|
||||||
|
quint64 serialId, const QString &tabletSysname);
|
||||||
|
|
||||||
|
InputRedirection::TabletToolType toolType() const { return m_toolType; }
|
||||||
|
QVector<InputRedirection::Capability> capabilities() const { return m_capabilities; }
|
||||||
|
quint64 serialId() const { return m_serialId; }
|
||||||
|
QString tabletSysName() { return m_tabletSysName; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
const InputRedirection::TabletToolType m_toolType;
|
||||||
|
const QVector<InputRedirection::Capability> m_capabilities;
|
||||||
|
const quint64 m_serialId;
|
||||||
|
const QString m_tabletSysName;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -121,7 +121,7 @@ void InputEventSpy::switchEvent(SwitchEvent *event)
|
||||||
Q_UNUSED(event)
|
Q_UNUSED(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputEventSpy::tabletToolEvent(QTabletEvent *event)
|
void InputEventSpy::tabletToolEvent(TabletEvent *event)
|
||||||
{
|
{
|
||||||
Q_UNUSED(event)
|
Q_UNUSED(event)
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ class KeyEvent;
|
||||||
class MouseEvent;
|
class MouseEvent;
|
||||||
class WheelEvent;
|
class WheelEvent;
|
||||||
class SwitchEvent;
|
class SwitchEvent;
|
||||||
|
class TabletEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for spying on input events inside InputRedirection.
|
* Base class for spying on input events inside InputRedirection.
|
||||||
|
@ -85,7 +85,7 @@ public:
|
||||||
|
|
||||||
virtual void switchEvent(SwitchEvent *event);
|
virtual void switchEvent(SwitchEvent *event);
|
||||||
|
|
||||||
virtual void tabletToolEvent(QTabletEvent *event);
|
virtual void tabletToolEvent(TabletEvent *event);
|
||||||
virtual void tabletToolButtonEvent(const QSet<uint> &pressedButtons);
|
virtual void tabletToolButtonEvent(const QSet<uint> &pressedButtons);
|
||||||
virtual void tabletPadButtonEvent(const QSet<uint> &pressedButtons);
|
virtual void tabletPadButtonEvent(const QSet<uint> &pressedButtons);
|
||||||
virtual void tabletPadStripEvent(int number, int position, bool isFinger);
|
virtual void tabletPadStripEvent(int number, int position, bool isFinger);
|
||||||
|
|
|
@ -528,12 +528,62 @@ void Connection::processEvents()
|
||||||
}
|
}
|
||||||
auto serial = libinput_tablet_tool_get_serial(tte->tool());
|
auto serial = libinput_tablet_tool_get_serial(tte->tool());
|
||||||
auto toolId = libinput_tablet_tool_get_tool_id(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;
|
||||||
|
}
|
||||||
|
|
||||||
emit tabletToolEvent(tabletEventType,
|
emit tabletToolEvent(tabletEventType,
|
||||||
tte->transformedPosition(m_size), tte->pressure(),
|
tte->transformedPosition(m_size), tte->pressure(),
|
||||||
tte->xTilt(), tte->yTilt(), tte->rotation(),
|
tte->xTilt(), tte->yTilt(), tte->rotation(),
|
||||||
tte->isTipDown(), tte->isNearby(), serial,
|
tte->isTipDown(), tte->isNearby(), serial,
|
||||||
toolId, event->device());
|
toolId, toolType, capabilities, tte->time(),
|
||||||
|
event->device());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LIBINPUT_EVENT_TABLET_TOOL_BUTTON: {
|
case LIBINPUT_EVENT_TABLET_TOOL_BUTTON: {
|
||||||
|
|
|
@ -133,7 +133,11 @@ 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, LibInput::Device *device);
|
bool tipNear, quint64 serialId, quint64 toolId,
|
||||||
|
InputRedirection::TabletToolType toolType,
|
||||||
|
const QVector<InputRedirection::Capability> &capabilities,
|
||||||
|
quint32 time,
|
||||||
|
LibInput::Device *device);
|
||||||
void tabletToolButtonEvent(uint button, bool isPressed);
|
void tabletToolButtonEvent(uint button, bool isPressed);
|
||||||
|
|
||||||
void tabletPadButtonEvent(uint button, bool isPressed);
|
void tabletPadButtonEvent(uint button, bool isPressed);
|
||||||
|
|
|
@ -158,12 +158,7 @@ Device::Device(libinput_device *device, QObject *parent)
|
||||||
, m_pointer(libinput_device_has_capability(m_device, LIBINPUT_DEVICE_CAP_POINTER))
|
, m_pointer(libinput_device_has_capability(m_device, LIBINPUT_DEVICE_CAP_POINTER))
|
||||||
, m_touch(libinput_device_has_capability(m_device, LIBINPUT_DEVICE_CAP_TOUCH))
|
, m_touch(libinput_device_has_capability(m_device, LIBINPUT_DEVICE_CAP_TOUCH))
|
||||||
, m_tabletTool(libinput_device_has_capability(m_device, LIBINPUT_DEVICE_CAP_TABLET_TOOL))
|
, m_tabletTool(libinput_device_has_capability(m_device, LIBINPUT_DEVICE_CAP_TABLET_TOOL))
|
||||||
#if 0
|
|
||||||
// next libinput version
|
|
||||||
, m_tabletPad(libinput_device_has_capability(m_device, LIBINPUT_DEVICE_CAP_TABLET_PAD))
|
, m_tabletPad(libinput_device_has_capability(m_device, LIBINPUT_DEVICE_CAP_TABLET_PAD))
|
||||||
#else
|
|
||||||
, m_tabletPad(false)
|
|
||||||
#endif
|
|
||||||
, m_supportsGesture(libinput_device_has_capability(m_device, LIBINPUT_DEVICE_CAP_GESTURE))
|
, m_supportsGesture(libinput_device_has_capability(m_device, LIBINPUT_DEVICE_CAP_GESTURE))
|
||||||
, m_switch(libinput_device_has_capability(m_device, LIBINPUT_DEVICE_CAP_SWITCH))
|
, m_switch(libinput_device_has_capability(m_device, LIBINPUT_DEVICE_CAP_SWITCH))
|
||||||
, m_lidSwitch(m_switch ? libinput_device_switch_has_switch(m_device, LIBINPUT_SWITCH_LID) : false)
|
, m_lidSwitch(m_switch ? libinput_device_switch_has_switch(m_device, LIBINPUT_SWITCH_LID) : false)
|
||||||
|
@ -427,6 +422,16 @@ void Device::setLmrTapButtonMap(bool set)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Device::stripsCount() const
|
||||||
|
{
|
||||||
|
return libinput_device_tablet_pad_get_num_strips(m_device);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Device::ringsCount() const
|
||||||
|
{
|
||||||
|
return libinput_device_tablet_pad_get_num_rings(m_device);
|
||||||
|
}
|
||||||
|
|
||||||
#define CONFIG(method, condition, function, variable, key) \
|
#define CONFIG(method, condition, function, variable, key) \
|
||||||
void Device::method(bool set) \
|
void Device::method(bool set) \
|
||||||
{ \
|
{ \
|
||||||
|
|
|
@ -472,6 +472,9 @@ public:
|
||||||
return m_tabletSwitch;
|
return m_tabletSwitch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int stripsCount() const;
|
||||||
|
int ringsCount() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All created Devices
|
* All created Devices
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -196,6 +196,10 @@ class TabletToolEvent : public Event
|
||||||
public:
|
public:
|
||||||
TabletToolEvent(libinput_event *event, libinput_event_type type);
|
TabletToolEvent(libinput_event *event, libinput_event_type type);
|
||||||
|
|
||||||
|
uint32_t time() const
|
||||||
|
{
|
||||||
|
return libinput_event_tablet_tool_get_time(m_tabletToolEvent);
|
||||||
|
}
|
||||||
bool xHasChanged() const {
|
bool xHasChanged() const {
|
||||||
return libinput_event_tablet_tool_x_has_changed(m_tabletToolEvent);
|
return libinput_event_tablet_tool_x_has_changed(m_tabletToolEvent);
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,7 @@ void ModifierOnlyShortcuts::keyEvent(KeyEvent *event)
|
||||||
m_pressedKeys.remove(event->nativeScanCode());
|
m_pressedKeys.remove(event->nativeScanCode());
|
||||||
if (m_pressedKeys.isEmpty() &&
|
if (m_pressedKeys.isEmpty() &&
|
||||||
event->modifiersRelevantForGlobalShortcuts() == Qt::NoModifier &&
|
event->modifiersRelevantForGlobalShortcuts() == Qt::NoModifier &&
|
||||||
!workspace()->globalShortcutsDisabled()) {
|
workspace() && !workspace()->globalShortcutsDisabled()) {
|
||||||
if (m_modifier != Qt::NoModifier) {
|
if (m_modifier != Qt::NoModifier) {
|
||||||
const auto list = options->modifierOnlyDBusShortcut(m_modifier);
|
const auto list = options->modifierOnlyDBusShortcut(m_modifier);
|
||||||
if (list.size() >= 4) {
|
if (list.size() >= 4) {
|
||||||
|
|
|
@ -21,6 +21,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#include "abstract_client.h"
|
#include "abstract_client.h"
|
||||||
#include "decorations/decoratedclient.h"
|
#include "decorations/decoratedclient.h"
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
|
#include "input_event.h"
|
||||||
#include "input_event_spy.h"
|
#include "input_event_spy.h"
|
||||||
#include "libinput/device.h"
|
#include "libinput/device.h"
|
||||||
#include "pointer_input.h"
|
#include "pointer_input.h"
|
||||||
|
@ -60,10 +61,11 @@ void TabletInputRedirection::tabletToolEvent(KWin::InputRedirection::TabletEvent
|
||||||
const QPointF &pos, qreal pressure,
|
const QPointF &pos, qreal pressure,
|
||||||
int xTilt, int yTilt, qreal rotation,
|
int xTilt, int yTilt, qreal rotation,
|
||||||
bool tipDown, bool tipNear, quint64 serialId,
|
bool tipDown, bool tipNear, quint64 serialId,
|
||||||
quint64 toolId, LibInput::Device *device)
|
quint64 toolId,
|
||||||
|
InputRedirection::TabletToolType toolType,
|
||||||
|
const QVector<InputRedirection::Capability> &capabilities,
|
||||||
|
quint32 time, LibInput::Device *device)
|
||||||
{
|
{
|
||||||
Q_UNUSED(device)
|
|
||||||
Q_UNUSED(toolId)
|
|
||||||
if (!inited()) {
|
if (!inited()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -83,13 +85,14 @@ void TabletInputRedirection::tabletToolEvent(KWin::InputRedirection::TabletEvent
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto button = m_tipDown ? Qt::LeftButton : Qt::NoButton;
|
const auto button = m_tipDown ? Qt::LeftButton : Qt::NoButton;
|
||||||
QTabletEvent ev(t, pos, pos, QTabletEvent::Stylus, QTabletEvent::Pen, pressure,
|
TabletEvent ev(t, pos, pos, QTabletEvent::Stylus, QTabletEvent::Pen, pressure,
|
||||||
xTilt, yTilt,
|
xTilt, yTilt,
|
||||||
0, // tangentialPressure
|
0, // tangentialPressure
|
||||||
rotation,
|
rotation,
|
||||||
0, // z
|
0, // z
|
||||||
Qt::NoModifier, serialId, button, button);
|
Qt::NoModifier, toolId, button, button, toolType, capabilities, serialId, device->sysName());
|
||||||
|
|
||||||
|
ev.setTimestamp(time);
|
||||||
input()->processSpies(std::bind(&InputEventSpy::tabletToolEvent, std::placeholders::_1, &ev));
|
input()->processSpies(std::bind(&InputEventSpy::tabletToolEvent, std::placeholders::_1, &ev));
|
||||||
input()->processFilters(
|
input()->processFilters(
|
||||||
std::bind(&InputEventFilter::tabletToolEvent, std::placeholders::_1, &ev));
|
std::bind(&InputEventFilter::tabletToolEvent, std::placeholders::_1, &ev));
|
||||||
|
|
|
@ -26,11 +26,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QPointF>
|
#include <QPointF>
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
#include <QTabletEvent>
|
|
||||||
|
|
||||||
namespace KWin
|
namespace KWin
|
||||||
{
|
{
|
||||||
class InputRedirection;
|
|
||||||
class Toplevel;
|
class Toplevel;
|
||||||
|
|
||||||
namespace Decoration
|
namespace Decoration
|
||||||
|
@ -54,7 +52,9 @@ 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, LibInput::Device *device);
|
bool tipNear, quint64 serialId, quint64 toolId,
|
||||||
|
InputRedirection::TabletToolType toolType, const QVector<InputRedirection::Capability> &capabilities,
|
||||||
|
quint32 time, LibInput::Device *device);
|
||||||
void tabletToolButtonEvent(uint button, bool isPressed);
|
void tabletToolButtonEvent(uint button, bool isPressed);
|
||||||
|
|
||||||
void tabletPadButtonEvent(uint button, bool isPressed);
|
void tabletPadButtonEvent(uint button, bool isPressed);
|
||||||
|
|
|
@ -315,6 +315,8 @@ bool WaylandServer::init(const QByteArray &socketName, InitializationFlags flags
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
m_tabletManager = m_display->createTabletManagerInterface(m_display);
|
||||||
|
|
||||||
m_xdgShell = m_display->createXdgShell(XdgShellInterfaceVersion::Stable, m_display);
|
m_xdgShell = m_display->createXdgShell(XdgShellInterfaceVersion::Stable, m_display);
|
||||||
m_xdgShell->create();
|
m_xdgShell->create();
|
||||||
connect(m_xdgShell, &XdgShellInterface::surfaceCreated, this, &WaylandServer::createSurface<XdgShellSurfaceInterface>);
|
connect(m_xdgShell, &XdgShellInterface::surfaceCreated, this, &WaylandServer::createSurface<XdgShellSurfaceInterface>);
|
||||||
|
|
|
@ -69,6 +69,7 @@ class XdgOutputManagerInterface;
|
||||||
class KeyStateInterface;
|
class KeyStateInterface;
|
||||||
class LinuxDmabufUnstableV1Interface;
|
class LinuxDmabufUnstableV1Interface;
|
||||||
class LinuxDmabufUnstableV1Buffer;
|
class LinuxDmabufUnstableV1Buffer;
|
||||||
|
class TabletManagerInterface;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,6 +106,10 @@ public:
|
||||||
KWayland::Server::SeatInterface *seat() {
|
KWayland::Server::SeatInterface *seat() {
|
||||||
return m_seat;
|
return m_seat;
|
||||||
}
|
}
|
||||||
|
KWayland::Server::TabletManagerInterface *tabletManager()
|
||||||
|
{
|
||||||
|
return m_tabletManager;
|
||||||
|
}
|
||||||
KWayland::Server::DataDeviceManagerInterface *dataDeviceManager() {
|
KWayland::Server::DataDeviceManagerInterface *dataDeviceManager() {
|
||||||
return m_dataDeviceManager;
|
return m_dataDeviceManager;
|
||||||
}
|
}
|
||||||
|
@ -246,6 +251,7 @@ private:
|
||||||
KWayland::Server::Display *m_display = nullptr;
|
KWayland::Server::Display *m_display = nullptr;
|
||||||
KWayland::Server::CompositorInterface *m_compositor = nullptr;
|
KWayland::Server::CompositorInterface *m_compositor = nullptr;
|
||||||
KWayland::Server::SeatInterface *m_seat = nullptr;
|
KWayland::Server::SeatInterface *m_seat = nullptr;
|
||||||
|
KWayland::Server::TabletManagerInterface *m_tabletManager = nullptr;
|
||||||
KWayland::Server::DataDeviceManagerInterface *m_dataDeviceManager = nullptr;
|
KWayland::Server::DataDeviceManagerInterface *m_dataDeviceManager = nullptr;
|
||||||
KWayland::Server::XdgShellInterface *m_xdgShell = nullptr;
|
KWayland::Server::XdgShellInterface *m_xdgShell = nullptr;
|
||||||
KWayland::Server::PlasmaShellInterface *m_plasmaShell = nullptr;
|
KWayland::Server::PlasmaShellInterface *m_plasmaShell = nullptr;
|
||||||
|
|
Loading…
Reference in a new issue