From 60c3b3ddfae9f39ac9a3209145ba2ac75bec94e3 Mon Sep 17 00:00:00 2001 From: David Redondo Date: Thu, 5 Aug 2021 10:31:08 +0200 Subject: [PATCH] Add support for hold gestures --- CMakeLists.txt | 2 +- src/input.cpp | 54 +++++++++++++++++++++++++++++++++++++ src/input.h | 4 +++ src/input_event_spy.cpp | 16 +++++++++++ src/input_event_spy.h | 4 +++ src/libinput/connection.cpp | 14 ++++++++++ src/libinput/connection.h | 3 +++ src/libinput/events.cpp | 10 +++++++ src/libinput/events.h | 8 ++++++ src/pointer_input.cpp | 36 +++++++++++++++++++++++++ src/pointer_input.h | 12 +++++++++ 11 files changed, 162 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 86059cb12d..fb67ddfe7b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -206,7 +206,7 @@ set_package_properties(XKB PROPERTIES find_package(Qt5XkbCommonSupport REQUIRED) -find_package(Libinput 1.14) +find_package(Libinput 1.19) set_package_properties(Libinput PROPERTIES TYPE REQUIRED PURPOSE "Required for input handling on Wayland.") find_package(UDev) diff --git a/src/input.cpp b/src/input.cpp index 945132ac6f..b4552e780f 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -184,6 +184,25 @@ bool InputEventFilter::swipeGestureCancelled(quint32 time) return false; } +bool InputEventFilter::holdGestureBegin(int fingerCount, quint32 time) +{ + Q_UNUSED(fingerCount) + Q_UNUSED(time) + return false; +} + +bool InputEventFilter::holdGestureEnd(quint32 time) +{ + Q_UNUSED(time) + return false; +} + +bool InputEventFilter::holdGestureCancelled(quint32 time) +{ + Q_UNUSED(time) + return false; +} + bool InputEventFilter::switchEvent(SwitchEvent *event) { Q_UNUSED(event) @@ -444,6 +463,17 @@ public: // no touchpad multi-finger gestures on lock screen return waylandServer()->isScreenLocked(); } + bool holdGestureBegin(int fingerCount, quint32 time) override { + Q_UNUSED(fingerCount) + Q_UNUSED(time) + // no touchpad multi-finger gestures on lock screen + return waylandServer()->isScreenLocked(); + } + bool holdGestureEnd(quint32 time) override { + Q_UNUSED(time) + // no touchpad multi-finger gestures on lock screen + return waylandServer()->isScreenLocked(); + } private: bool surfaceAllowed(KWaylandServer::SurfaceInterface *(KWaylandServer::SeatInterface::*method)() const) const { if (KWaylandServer::SurfaceInterface *s = (waylandServer()->seat()->*method)()) { @@ -1561,6 +1591,27 @@ public: seat->cancelPointerSwipeGesture(); return true; } + bool holdGestureBegin(int fingerCount, quint32 time) override + { + auto seat = waylandServer()->seat(); + seat->setTimestamp(time); + seat->startPointerHoldGesture(time); + return true; + } + bool holdGestureEnd(quint32 time) override + { + auto seat = waylandServer()->seat(); + seat->setTimestamp(time); + seat->endPointerHoldGesture(); + return true; + } + bool holdGestureCancelled(quint32 time) override + { + auto seat = waylandServer()->seat(); + seat->setTimestamp(time); + seat->cancelPointerHoldGesture(); + return true; + } }; static KWaylandServer::SeatInterface *findSeat() @@ -2414,6 +2465,9 @@ void InputRedirection::setupLibInput() connect(conn, &LibInput::Connection::swipeGestureUpdate, m_pointer, &PointerInputRedirection::processSwipeGestureUpdate); connect(conn, &LibInput::Connection::swipeGestureEnd, m_pointer, &PointerInputRedirection::processSwipeGestureEnd); connect(conn, &LibInput::Connection::swipeGestureCancelled, m_pointer, &PointerInputRedirection::processSwipeGestureCancelled); + connect(conn, &LibInput::Connection::holdGestureBegin, m_pointer, &PointerInputRedirection::processHoldGestureBegin); + connect(conn, &LibInput::Connection::holdGestureEnd, m_pointer, &PointerInputRedirection::processHoldGestureEnd); + connect(conn, &LibInput::Connection::holdGestureCancelled, m_pointer, &PointerInputRedirection::processHoldGestureCancelled); connect(conn, &LibInput::Connection::keyChanged, m_keyboard, &KeyboardInputRedirection::processKey); connect(conn, &LibInput::Connection::pointerMotion, m_pointer, &PointerInputRedirection::processMotion); connect(conn, &LibInput::Connection::pointerMotionAbsolute, m_pointer, &PointerInputRedirection::processMotionAbsolute); diff --git a/src/input.h b/src/input.h index 2ef0b841f9..8859b449a1 100644 --- a/src/input.h +++ b/src/input.h @@ -407,6 +407,10 @@ public: virtual bool swipeGestureEnd(quint32 time); virtual bool swipeGestureCancelled(quint32 time); + virtual bool holdGestureBegin(int fingerCount, quint32 time); + virtual bool holdGestureEnd(quint32 time); + virtual bool holdGestureCancelled(quint32 time); + virtual bool switchEvent(SwitchEvent *event); virtual bool tabletToolEvent(TabletEvent *event); diff --git a/src/input_event_spy.cpp b/src/input_event_spy.cpp index 9c5d7d27cc..169349cdd4 100644 --- a/src/input_event_spy.cpp +++ b/src/input_event_spy.cpp @@ -105,6 +105,22 @@ void InputEventSpy::swipeGestureCancelled(quint32 time) Q_UNUSED(time) } +void InputEventSpy::holdGestureBegin(int fingerCount, quint32 time) +{ + Q_UNUSED(fingerCount) + Q_UNUSED(time) +} + +void InputEventSpy::holdGestureEnd(quint32 time) +{ + Q_UNUSED(time) +} + +void InputEventSpy::holdGestureCancelled(quint32 time) +{ + Q_UNUSED(time) +} + void InputEventSpy::switchEvent(SwitchEvent *event) { Q_UNUSED(event) diff --git a/src/input_event_spy.h b/src/input_event_spy.h index a82fd9fdff..0d081d39af 100644 --- a/src/input_event_spy.h +++ b/src/input_event_spy.h @@ -74,6 +74,10 @@ public: virtual void swipeGestureEnd(quint32 time); virtual void swipeGestureCancelled(quint32 time); + virtual void holdGestureBegin(int fingerCount, quint32 time); + virtual void holdGestureEnd(quint32 time); + virtual void holdGestureCancelled(quint32 time); + virtual void switchEvent(SwitchEvent *event); virtual void tabletToolEvent(TabletEvent *event); diff --git a/src/libinput/connection.cpp b/src/libinput/connection.cpp index f2599b0d76..46caeb3075 100644 --- a/src/libinput/connection.cpp +++ b/src/libinput/connection.cpp @@ -516,6 +516,20 @@ void Connection::processEvents() } break; } + case LIBINPUT_EVENT_GESTURE_HOLD_BEGIN: { + HoldGestureEvent *he = static_cast(event.data()); + Q_EMIT holdGestureBegin(he->fingerCount(), he->time(), he->device()); + break; + } + case LIBINPUT_EVENT_GESTURE_HOLD_END: { + HoldGestureEvent *he = static_cast(event.data()); + if (he->isCancelled()) { + Q_EMIT holdGestureCancelled(he->time(), he->device()); + } else { + Q_EMIT holdGestureEnd(he->time(), he->device()); + } + break; + } case LIBINPUT_EVENT_SWITCH_TOGGLE: { SwitchEvent *se = static_cast(event.data()); switch (se->state()) { diff --git a/src/libinput/connection.h b/src/libinput/connection.h index bb2ed0cc5e..9fbf4b71f1 100644 --- a/src/libinput/connection.h +++ b/src/libinput/connection.h @@ -115,6 +115,9 @@ Q_SIGNALS: void pinchGestureUpdate(qreal scale, qreal angleDelta, const QSizeF &delta, quint32 time, KWin::LibInput::Device *device); void pinchGestureEnd(quint32 time, KWin::LibInput::Device *device); void pinchGestureCancelled(quint32 time, KWin::LibInput::Device *device); + void holdGestureBegin(int fingerCount, quint32 time, KWin::LibInput::Device *device); + void holdGestureEnd(quint32 time, KWin::LibInput::Device *device); + void holdGestureCancelled(quint32 time, KWin::LibInput::Device *device); void switchToggledOn(quint32 time, quint64 timeMicroseconds, KWin::LibInput::Device *device); void switchToggledOff(quint32 time, quint64 timeMicroseconds, KWin::LibInput::Device *device); diff --git a/src/libinput/events.cpp b/src/libinput/events.cpp index 6845debaf7..f995775fef 100644 --- a/src/libinput/events.cpp +++ b/src/libinput/events.cpp @@ -46,6 +46,9 @@ Event *Event::create(libinput_event *event) case LIBINPUT_EVENT_GESTURE_PINCH_UPDATE: case LIBINPUT_EVENT_GESTURE_PINCH_END: return new PinchGestureEvent(event, t); + case LIBINPUT_EVENT_GESTURE_HOLD_BEGIN: + case LIBINPUT_EVENT_GESTURE_HOLD_END: + return new HoldGestureEvent(event, t); case LIBINPUT_EVENT_TABLET_TOOL_AXIS: case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY: case LIBINPUT_EVENT_TABLET_TOOL_TIP: @@ -319,6 +322,13 @@ SwipeGestureEvent::SwipeGestureEvent(libinput_event *event, libinput_event_type SwipeGestureEvent::~SwipeGestureEvent() = default; +HoldGestureEvent::HoldGestureEvent(libinput_event *event, libinput_event_type type) + : GestureEvent(event, type) +{ +} + +HoldGestureEvent::~HoldGestureEvent() = default; + SwitchEvent::SwitchEvent(libinput_event *event, libinput_event_type type) : Event(event, type) , m_switchEvent(libinput_event_get_switch_event(event)) diff --git a/src/libinput/events.h b/src/libinput/events.h index 1e207b0573..7d01bada2e 100644 --- a/src/libinput/events.h +++ b/src/libinput/events.h @@ -161,6 +161,14 @@ public: ~SwipeGestureEvent() override; }; +class HoldGestureEvent : public GestureEvent +{ +public: + HoldGestureEvent(libinput_event *event, libinput_event_type type); + ~HoldGestureEvent() override; +}; + + class SwitchEvent : public Event { public: diff --git a/src/pointer_input.cpp b/src/pointer_input.cpp index d4b9b1df0d..c3c502dbf5 100644 --- a/src/pointer_input.cpp +++ b/src/pointer_input.cpp @@ -436,6 +436,42 @@ void PointerInputRedirection::processPinchGestureCancelled(quint32 time, KWin::L input()->processFilters(std::bind(&InputEventFilter::pinchGestureCancelled, std::placeholders::_1, time)); } +void PointerInputRedirection::processHoldGestureBegin(int fingerCount, quint32 time, KWin::LibInput::Device *device) +{ + Q_UNUSED(device) + if (!inited()) { + return; + } + update(); + + input()->processSpies(std::bind(&InputEventSpy::holdGestureBegin, std::placeholders::_1, fingerCount, time)); + input()->processFilters(std::bind(&InputEventFilter::holdGestureBegin, std::placeholders::_1, fingerCount, time)); +} + +void PointerInputRedirection::processHoldGestureEnd(quint32 time, KWin::LibInput::Device *device) +{ + Q_UNUSED(device) + if (!inited()) { + return; + } + update(); + + input()->processSpies(std::bind(&InputEventSpy::holdGestureEnd, std::placeholders::_1, time)); + input()->processFilters(std::bind(&InputEventFilter::holdGestureEnd, std::placeholders::_1, time)); +} + +void PointerInputRedirection::processHoldGestureCancelled(quint32 time, KWin::LibInput::Device *device) +{ + Q_UNUSED(device) + if (!inited()) { + return; + } + update(); + + input()->processSpies(std::bind(&InputEventSpy::holdGestureCancelled, std::placeholders::_1, time)); + input()->processFilters(std::bind(&InputEventFilter::holdGestureCancelled, std::placeholders::_1, time)); +} + bool PointerInputRedirection::areButtonsPressed() const { for (auto state : m_buttons) { diff --git a/src/pointer_input.h b/src/pointer_input.h index bd032a95b7..109846c746 100644 --- a/src/pointer_input.h +++ b/src/pointer_input.h @@ -131,6 +131,18 @@ public: * @internal */ void processPinchGestureCancelled(quint32 time, KWin::LibInput::Device *device = nullptr); + /** + * @internal + */ + void processHoldGestureBegin(int fingerCount, quint32 time, KWin::LibInput::Device *device = nullptr); + /** + * @internal + */ + void processHoldGestureEnd(quint32 time, KWin::LibInput::Device *device = nullptr); + /** + * @internal + */ + void processHoldGestureCancelled(quint32 time, KWin::LibInput::Device *device = nullptr); private: void processMotionInternal(const QPointF &pos, const QSizeF &delta, const QSizeF &deltaNonAccelerated, uint32_t time, quint64 timeUsec, LibInput::Device *device);