diff --git a/autotests/libinput/CMakeLists.txt b/autotests/libinput/CMakeLists.txt index bd92fdf0a7..dc7a1b2901 100644 --- a/autotests/libinput/CMakeLists.txt +++ b/autotests/libinput/CMakeLists.txt @@ -51,6 +51,20 @@ target_link_libraries( testLibinputTouchEvent Qt5::Test Qt5::Widgets KF5::Config add_test(kwin-testLibinputTouchEvent testLibinputTouchEvent) ecm_mark_as_test(testLibinputTouchEvent) +######################################################## +# Test Gesture Event +######################################################## +set( testLibinputGestureEvent_SRCS + gesture_event_test.cpp + mock_libinput.cpp + ../../libinput/device.cpp + ../../libinput/events.cpp + ) +add_executable(testLibinputGestureEvent ${testLibinputGestureEvent_SRCS}) +target_link_libraries( testLibinputGestureEvent Qt5::Test Qt5::Widgets KF5::ConfigCore) +add_test(kwin-testLibinputGestureEvent testLibinputGestureEvent) +ecm_mark_as_test(testLibinputGestureEvent) + ######################################################## # Test Context ######################################################## diff --git a/autotests/libinput/gesture_event_test.cpp b/autotests/libinput/gesture_event_test.cpp new file mode 100644 index 0000000000..fe7e511537 --- /dev/null +++ b/autotests/libinput/gesture_event_test.cpp @@ -0,0 +1,214 @@ +/******************************************************************** +KWin - the KDE window manager +This file is part of the KDE project. + +Copyright (C) 2016 Martin Gräßlin + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ +#include "mock_libinput.h" +#include "../../libinput/device.h" +#include "../../libinput/events.h" + +#include + +#include + +Q_DECLARE_METATYPE(libinput_event_type) + +using namespace KWin::LibInput; + +class TestLibinputGestureEvent : public QObject +{ + Q_OBJECT +private Q_SLOTS: + void init(); + void cleanup(); + + void testType_data(); + void testType(); + + void testStart_data(); + void testStart(); + + void testSwipeUpdate(); + void testPinchUpdate(); + + void testEnd_data(); + void testEnd(); + +private: + libinput_device *m_nativeDevice = nullptr; + Device *m_device = nullptr; +}; + +void TestLibinputGestureEvent::init() +{ + m_nativeDevice = new libinput_device; + m_nativeDevice->pointer = true; + m_nativeDevice->gestureSupported = true; + m_nativeDevice->deviceSize = QSizeF(12.5, 13.8); + m_device = new Device(m_nativeDevice); +} + +void TestLibinputGestureEvent::cleanup() +{ + delete m_device; + m_device = nullptr; + + delete m_nativeDevice; + m_nativeDevice = nullptr; +} + +void TestLibinputGestureEvent::testType_data() +{ + QTest::addColumn("type"); + + QTest::newRow("pinch-start") << LIBINPUT_EVENT_GESTURE_PINCH_BEGIN; + QTest::newRow("pinch-update") << LIBINPUT_EVENT_GESTURE_PINCH_UPDATE; + QTest::newRow("pinch-end") << LIBINPUT_EVENT_GESTURE_PINCH_END; + QTest::newRow("swipe-start") << LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN; + QTest::newRow("swipe-update") << LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE; + QTest::newRow("swipe-end") << LIBINPUT_EVENT_GESTURE_SWIPE_END; +} + +void TestLibinputGestureEvent::testType() +{ + // this test verifies the initialization of a PointerEvent and the parent Event class + libinput_event_gesture *gestureEvent = new libinput_event_gesture; + QFETCH(libinput_event_type, type); + gestureEvent->type = type; + gestureEvent->device = m_nativeDevice; + + QScopedPointer event(Event::create(gestureEvent)); + // API of event + QCOMPARE(event->type(), type); + QCOMPARE(event->device(), m_device); + QCOMPARE(event->nativeDevice(), m_nativeDevice); + QCOMPARE((libinput_event*)(*event.data()), gestureEvent); + // verify it's a pointer event + QVERIFY(dynamic_cast(event.data())); + QCOMPARE((libinput_event_gesture*)(*dynamic_cast(event.data())), gestureEvent); +} + +void TestLibinputGestureEvent::testStart_data() +{ + QTest::addColumn("type"); + + QTest::newRow("pinch") << LIBINPUT_EVENT_GESTURE_PINCH_BEGIN; + QTest::newRow("swipe") << LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN; +} + +void TestLibinputGestureEvent::testStart() +{ + libinput_event_gesture *gestureEvent = new libinput_event_gesture; + gestureEvent->device = m_nativeDevice; + QFETCH(libinput_event_type, type); + gestureEvent->type = type; + gestureEvent->fingerCount = 3; + gestureEvent->time = 100u; + + QScopedPointer event(Event::create(gestureEvent)); + auto ge = dynamic_cast(event.data()); + QVERIFY(ge); + QCOMPARE(ge->fingerCount(), gestureEvent->fingerCount); + QVERIFY(!ge->isCancelled()); + QCOMPARE(ge->time(), gestureEvent->time); + QCOMPARE(ge->delta(), QSizeF(0, 0)); + if (ge->type() == LIBINPUT_EVENT_GESTURE_PINCH_BEGIN) { + auto pe = dynamic_cast(event.data()); + QCOMPARE(pe->scale(), 1.0); + QCOMPARE(pe->angleDelta(), 0.0); + } +} + +void TestLibinputGestureEvent::testSwipeUpdate() +{ + libinput_event_gesture *gestureEvent = new libinput_event_gesture; + gestureEvent->device = m_nativeDevice; + gestureEvent->type = LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE; + gestureEvent->fingerCount = 2; + gestureEvent->time = 200u; + gestureEvent->delta = QSizeF(2, 3); + + QScopedPointer event(Event::create(gestureEvent)); + auto se = dynamic_cast(event.data()); + QVERIFY(se); + QCOMPARE(se->fingerCount(), gestureEvent->fingerCount); + QVERIFY(!se->isCancelled()); + QCOMPARE(se->time(), gestureEvent->time); + QCOMPARE(se->delta(), QSizeF(2, 3)); +} + +void TestLibinputGestureEvent::testPinchUpdate() +{ + libinput_event_gesture *gestureEvent = new libinput_event_gesture; + gestureEvent->device = m_nativeDevice; + gestureEvent->type = LIBINPUT_EVENT_GESTURE_PINCH_UPDATE; + gestureEvent->fingerCount = 4; + gestureEvent->time = 600u; + gestureEvent->delta = QSizeF(5, 4); + gestureEvent->scale = 2; + gestureEvent->angleDelta = -30; + + QScopedPointer event(Event::create(gestureEvent)); + auto pe = dynamic_cast(event.data()); + QVERIFY(pe); + QCOMPARE(pe->fingerCount(), gestureEvent->fingerCount); + QVERIFY(!pe->isCancelled()); + QCOMPARE(pe->time(), gestureEvent->time); + QCOMPARE(pe->delta(), QSizeF(5, 4)); + QCOMPARE(pe->scale(), gestureEvent->scale); + QCOMPARE(pe->angleDelta(), gestureEvent->angleDelta); +} + +void TestLibinputGestureEvent::testEnd_data() +{ + QTest::addColumn("type"); + QTest::addColumn("cancelled"); + + QTest::newRow("pinch/not cancelled") << LIBINPUT_EVENT_GESTURE_PINCH_END << false; + QTest::newRow("pinch/cancelled") << LIBINPUT_EVENT_GESTURE_PINCH_END << true; + QTest::newRow("swipe/not cancelled") << LIBINPUT_EVENT_GESTURE_SWIPE_END << false; + QTest::newRow("swipe/cancelled") << LIBINPUT_EVENT_GESTURE_SWIPE_END << true; +} + +void TestLibinputGestureEvent::testEnd() +{ + libinput_event_gesture *gestureEvent = new libinput_event_gesture; + gestureEvent->device = m_nativeDevice; + QFETCH(libinput_event_type, type); + gestureEvent->type = type; + gestureEvent->fingerCount = 4; + QFETCH(bool, cancelled); + gestureEvent->cancelled = cancelled; + gestureEvent->time = 300u; + gestureEvent->scale = 3; + + QScopedPointer event(Event::create(gestureEvent)); + auto ge = dynamic_cast(event.data()); + QVERIFY(ge); + QCOMPARE(ge->fingerCount(), gestureEvent->fingerCount); + QCOMPARE(ge->isCancelled(), cancelled); + QCOMPARE(ge->time(), gestureEvent->time); + QCOMPARE(ge->delta(), QSizeF(0, 0)); + if (ge->type() == LIBINPUT_EVENT_GESTURE_PINCH_END) { + auto pe = dynamic_cast(event.data()); + QCOMPARE(pe->scale(), gestureEvent->scale); + QCOMPARE(pe->angleDelta(), 0.0); + } +} + +QTEST_GUILESS_MAIN(TestLibinputGestureEvent) +#include "gesture_event_test.moc" diff --git a/autotests/libinput/mock_libinput.cpp b/autotests/libinput/mock_libinput.cpp index 93a4870219..6ecb6342f9 100644 --- a/autotests/libinput/mock_libinput.cpp +++ b/autotests/libinput/mock_libinput.cpp @@ -267,6 +267,74 @@ struct libinput_event_touch *libinput_event_get_touch_event(struct libinput_even return nullptr; } +struct libinput_event_gesture *libinput_event_get_gesture_event(struct libinput_event *event) +{ + if (event->type == LIBINPUT_EVENT_GESTURE_PINCH_BEGIN || + event->type == LIBINPUT_EVENT_GESTURE_PINCH_UPDATE || + event->type == LIBINPUT_EVENT_GESTURE_PINCH_END || + event->type == LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN || + event->type == LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE || + event->type == LIBINPUT_EVENT_GESTURE_SWIPE_END) { + return reinterpret_cast(event); + } + return nullptr; +} + +int libinput_event_gesture_get_cancelled(struct libinput_event_gesture *event) +{ + if (event->type == LIBINPUT_EVENT_GESTURE_PINCH_END || event->type == LIBINPUT_EVENT_GESTURE_SWIPE_END) { + return event->cancelled; + } + return 0; +} + +uint32_t libinput_event_gesture_get_time(struct libinput_event_gesture *event) +{ + return event->time; +} + +int libinput_event_gesture_get_finger_count(struct libinput_event_gesture *event) +{ + return event->fingerCount; +} + +double libinput_event_gesture_get_dx(struct libinput_event_gesture *event) +{ + if (event->type == LIBINPUT_EVENT_GESTURE_PINCH_UPDATE || event->type == LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE) { + return event->delta.width(); + } + return 0.0; +} + +double libinput_event_gesture_get_dy(struct libinput_event_gesture *event) +{ + if (event->type == LIBINPUT_EVENT_GESTURE_PINCH_UPDATE || event->type == LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE) { + return event->delta.height(); + } + return 0.0; +} + +double libinput_event_gesture_get_scale(struct libinput_event_gesture *event) +{ + switch (event->type) { + case LIBINPUT_EVENT_GESTURE_PINCH_BEGIN: + return 1.0; + case LIBINPUT_EVENT_GESTURE_PINCH_UPDATE: + case LIBINPUT_EVENT_GESTURE_PINCH_END: + return event->scale; + default: + return 0.0; + } +} + +double libinput_event_gesture_get_angle_delta(struct libinput_event_gesture *event) +{ + if (event->type == LIBINPUT_EVENT_GESTURE_PINCH_UPDATE) { + return event->angleDelta; + } + return 0.0; +} + uint32_t libinput_event_keyboard_get_key(struct libinput_event_keyboard *event) { return event->key; diff --git a/autotests/libinput/mock_libinput.h b/autotests/libinput/mock_libinput.h index 6779dc535f..e57082fb27 100644 --- a/autotests/libinput/mock_libinput.h +++ b/autotests/libinput/mock_libinput.h @@ -87,6 +87,14 @@ struct libinput_event_touch : libinput_event { QPointF absolutePos; }; +struct libinput_event_gesture : libinput_event { + int fingerCount = 0; + bool cancelled = false; + QSizeF delta = QSizeF(0, 0); + qreal scale = 0.0; + qreal angleDelta = 0.0; +}; + struct libinput { int refCount = 1; QByteArray seat; diff --git a/debug_console.cpp b/debug_console.cpp index 53d90c45bb..5d00cf003d 100644 --- a/debug_console.cpp +++ b/debug_console.cpp @@ -334,6 +334,118 @@ bool DebugConsoleFilter::touchUp(quint32 id, quint32 time) return false; } +bool DebugConsoleFilter::pinchGestureBegin(int fingerCount, quint32 time) +{ + QString text = s_hr; + text.append(s_tableStart); + text.append(tableHeaderRow(i18nc("A pinch gesture is started", "Pinch start"))); + text.append(timestampRow(time)); + text.append(tableRow(i18nc("Number of fingers in this pinch gesture", "Finger count"), fingerCount)); + text.append(s_tableEnd); + + m_textEdit->insertHtml(text); + m_textEdit->ensureCursorVisible(); + return false; +} + +bool DebugConsoleFilter::pinchGestureUpdate(qreal scale, qreal angleDelta, const QSizeF &delta, quint32 time) +{ + QString text = s_hr; + text.append(s_tableStart); + text.append(tableHeaderRow(i18nc("A pinch gesture is updated", "Pinch update"))); + text.append(timestampRow(time)); + text.append(tableRow(i18nc("Current scale in pinch gesture", "Scale"), scale)); + text.append(tableRow(i18nc("Current angle in pinch gesture", "Angle delta"), angleDelta)); + text.append(tableRow(i18nc("Current delta in pinch gesture", "Delta x"), delta.width())); + text.append(tableRow(i18nc("Current delta in pinch gesture", "Delta y"), delta.height())); + text.append(s_tableEnd); + + m_textEdit->insertHtml(text); + m_textEdit->ensureCursorVisible(); + return false; +} + +bool DebugConsoleFilter::pinchGestureEnd(quint32 time) +{ + QString text = s_hr; + text.append(s_tableStart); + text.append(tableHeaderRow(i18nc("A pinch gesture ended", "Pinch end"))); + text.append(timestampRow(time)); + text.append(s_tableEnd); + + m_textEdit->insertHtml(text); + m_textEdit->ensureCursorVisible(); + return false; +} + +bool DebugConsoleFilter::pinchGestureCancelled(quint32 time) +{ + QString text = s_hr; + text.append(s_tableStart); + text.append(tableHeaderRow(i18nc("A pinch gesture got cancelled", "Pinch cancelled"))); + text.append(timestampRow(time)); + text.append(s_tableEnd); + + m_textEdit->insertHtml(text); + m_textEdit->ensureCursorVisible(); + return false; +} + +bool DebugConsoleFilter::swipeGestureBegin(int fingerCount, quint32 time) +{ + QString text = s_hr; + text.append(s_tableStart); + text.append(tableHeaderRow(i18nc("A swipe gesture is started", "Swipe start"))); + text.append(timestampRow(time)); + text.append(tableRow(i18nc("Number of fingers in this swipe gesture", "Finger count"), fingerCount)); + text.append(s_tableEnd); + + m_textEdit->insertHtml(text); + m_textEdit->ensureCursorVisible(); + return false; +} + +bool DebugConsoleFilter::swipeGestureUpdate(const QSizeF &delta, quint32 time) +{ + QString text = s_hr; + text.append(s_tableStart); + text.append(tableHeaderRow(i18nc("A swipe gesture is updated", "Swipe update"))); + text.append(timestampRow(time)); + text.append(tableRow(i18nc("Current delta in swipe gesture", "Delta x"), delta.width())); + text.append(tableRow(i18nc("Current delta in swipe gesture", "Delta y"), delta.height())); + text.append(s_tableEnd); + + m_textEdit->insertHtml(text); + m_textEdit->ensureCursorVisible(); + return false; +} + +bool DebugConsoleFilter::swipeGestureEnd(quint32 time) +{ + QString text = s_hr; + text.append(s_tableStart); + text.append(tableHeaderRow(i18nc("A swipe gesture ended", "Swipe end"))); + text.append(timestampRow(time)); + text.append(s_tableEnd); + + m_textEdit->insertHtml(text); + m_textEdit->ensureCursorVisible(); + return false; +} + +bool DebugConsoleFilter::swipeGestureCancelled(quint32 time) +{ + QString text = s_hr; + text.append(s_tableStart); + text.append(tableHeaderRow(i18nc("A swipe gesture got cancelled", "Swipe cancelled"))); + text.append(timestampRow(time)); + text.append(s_tableEnd); + + m_textEdit->insertHtml(text); + m_textEdit->ensureCursorVisible(); + return false; +} + DebugConsole::DebugConsole() : QWidget() , m_ui(new Ui::DebugConsole) diff --git a/debug_console.h b/debug_console.h index f76699a215..1cf9910c3e 100644 --- a/debug_console.h +++ b/debug_console.h @@ -133,6 +133,16 @@ public: bool touchMotion(quint32 id, const QPointF &pos, quint32 time) override; bool touchUp(quint32 id, quint32 time) override; + bool pinchGestureBegin(int fingerCount, quint32 time) override; + bool pinchGestureUpdate(qreal scale, qreal angleDelta, const QSizeF &delta, quint32 time) override; + bool pinchGestureEnd(quint32 time) override; + bool pinchGestureCancelled(quint32 time) override; + + bool swipeGestureBegin(int fingerCount, quint32 time) override; + bool swipeGestureUpdate(const QSizeF &delta, quint32 time) override; + bool swipeGestureEnd(quint32 time) override; + bool swipeGestureCancelled(quint32 time) override; + private: QTextEdit *m_textEdit; }; diff --git a/input.cpp b/input.cpp index 17312c595a..37ab081145 100644 --- a/input.cpp +++ b/input.cpp @@ -106,6 +106,60 @@ bool InputEventFilter::touchUp(quint32 id, quint32 time) return false; } +bool InputEventFilter::pinchGestureBegin(int fingerCount, quint32 time) +{ + Q_UNUSED(fingerCount) + Q_UNUSED(time) + return false; +} + +bool InputEventFilter::pinchGestureUpdate(qreal scale, qreal angleDelta, const QSizeF &delta, quint32 time) +{ + Q_UNUSED(scale) + Q_UNUSED(angleDelta) + Q_UNUSED(delta) + Q_UNUSED(time) + return false; +} + +bool InputEventFilter::pinchGestureEnd(quint32 time) +{ + Q_UNUSED(time) + return false; +} + +bool InputEventFilter::pinchGestureCancelled(quint32 time) +{ + Q_UNUSED(time) + return false; +} + +bool InputEventFilter::swipeGestureBegin(int fingerCount, quint32 time) +{ + Q_UNUSED(fingerCount) + Q_UNUSED(time) + return false; +} + +bool InputEventFilter::swipeGestureUpdate(const QSizeF &delta, quint32 time) +{ + Q_UNUSED(delta) + Q_UNUSED(time) + return false; +} + +bool InputEventFilter::swipeGestureEnd(quint32 time) +{ + Q_UNUSED(time) + return false; +} + +bool InputEventFilter::swipeGestureCancelled(quint32 time) +{ + Q_UNUSED(time) + return false; +} + #if HAVE_INPUT class VirtualTerminalFilter : public InputEventFilter { public: @@ -1134,6 +1188,14 @@ void InputRedirection::setupLibInput() ); connect(conn, &LibInput::Connection::pointerButtonChanged, m_pointer, &PointerInputRedirection::processButton); connect(conn, &LibInput::Connection::pointerAxisChanged, m_pointer, &PointerInputRedirection::processAxis); + connect(conn, &LibInput::Connection::pinchGestureBegin, m_pointer, &PointerInputRedirection::processPinchGestureBegin); + connect(conn, &LibInput::Connection::pinchGestureUpdate, m_pointer, &PointerInputRedirection::processPinchGestureUpdate); + connect(conn, &LibInput::Connection::pinchGestureEnd, m_pointer, &PointerInputRedirection::processPinchGestureEnd); + connect(conn, &LibInput::Connection::pinchGestureCancelled, m_pointer, &PointerInputRedirection::processPinchGestureCancelled); + connect(conn, &LibInput::Connection::swipeGestureBegin, m_pointer, &PointerInputRedirection::processSwipeGestureBegin); + 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::keyChanged, m_keyboard, &KeyboardInputRedirection::processKey); connect(conn, &LibInput::Connection::pointerMotion, this, [this] (QPointF delta, uint32_t time, LibInput::Device *device) { diff --git a/input.h b/input.h index 2829344a12..f8863a65dd 100644 --- a/input.h +++ b/input.h @@ -288,6 +288,16 @@ public: virtual bool touchDown(quint32 id, const QPointF &pos, quint32 time); virtual bool touchMotion(quint32 id, const QPointF &pos, quint32 time); virtual bool touchUp(quint32 id, quint32 time); + + virtual bool pinchGestureBegin(int fingerCount, quint32 time); + virtual bool pinchGestureUpdate(qreal scale, qreal angleDelta, const QSizeF &delta, quint32 time); + virtual bool pinchGestureEnd(quint32 time); + virtual bool pinchGestureCancelled(quint32 time); + + virtual bool swipeGestureBegin(int fingerCount, quint32 time); + virtual bool swipeGestureUpdate(const QSizeF &delta, quint32 time); + virtual bool swipeGestureEnd(quint32 time); + virtual bool swipeGestureCancelled(quint32 time); }; class InputDeviceHandler : public QObject diff --git a/libinput/connection.cpp b/libinput/connection.cpp index c14b4066ee..08e39aa2b4 100644 --- a/libinput/connection.cpp +++ b/libinput/connection.cpp @@ -369,6 +369,44 @@ void Connection::processEvents() emit touchFrame(event->device()); break; } + case LIBINPUT_EVENT_GESTURE_PINCH_BEGIN: { + PinchGestureEvent *pe = static_cast(event.data()); + emit pinchGestureBegin(pe->fingerCount(), pe->time(), pe->device()); + break; + } + case LIBINPUT_EVENT_GESTURE_PINCH_UPDATE: { + PinchGestureEvent *pe = static_cast(event.data()); + emit pinchGestureUpdate(pe->scale(), pe->angleDelta(), pe->delta(), pe->time(), pe->device()); + break; + } + case LIBINPUT_EVENT_GESTURE_PINCH_END: { + PinchGestureEvent *pe = static_cast(event.data()); + if (pe->isCancelled()) { + emit pinchGestureCancelled(pe->time(), pe->device()); + } else { + emit pinchGestureEnd(pe->time(), pe->device()); + } + break; + } + case LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN: { + SwipeGestureEvent *se = static_cast(event.data()); + emit swipeGestureBegin(se->fingerCount(), se->time(), se->device()); + break; + } + case LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE: { + SwipeGestureEvent *se = static_cast(event.data()); + emit swipeGestureUpdate(se->delta(), se->time(), se->device()); + break; + } + case LIBINPUT_EVENT_GESTURE_SWIPE_END: { + SwipeGestureEvent *se = static_cast(event.data()); + if (se->isCancelled()) { + emit swipeGestureCancelled(se->time(), se->device()); + } else { + emit swipeGestureEnd(se->time(), se->device()); + } + break; + } default: // nothing break; diff --git a/libinput/connection.h b/libinput/connection.h index f6b3676da8..03996d3fbf 100644 --- a/libinput/connection.h +++ b/libinput/connection.h @@ -99,6 +99,14 @@ Q_SIGNALS: void hasTouchChanged(bool); void deviceAdded(KWin::LibInput::Device *); void deviceRemoved(KWin::LibInput::Device *); + void swipeGestureBegin(int fingerCount, quint32 time, KWin::LibInput::Device *device); + void swipeGestureUpdate(const QSizeF &delta, quint32 time, KWin::LibInput::Device *device); + void swipeGestureEnd(quint32 time, KWin::LibInput::Device *device); + void swipeGestureCancelled(quint32 time, KWin::LibInput::Device *device); + void pinchGestureBegin(int fingerCount, quint32 time, KWin::LibInput::Device *device); + 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 eventsRead(); diff --git a/libinput/events.cpp b/libinput/events.cpp index a9dff4814e..1ebb20359e 100644 --- a/libinput/events.cpp +++ b/libinput/events.cpp @@ -49,6 +49,14 @@ Event *Event::create(libinput_event *event) case LIBINPUT_EVENT_TOUCH_CANCEL: case LIBINPUT_EVENT_TOUCH_FRAME: return new TouchEvent(event, t); + case LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN: + case LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE: + case LIBINPUT_EVENT_GESTURE_SWIPE_END: + return new SwipeGestureEvent(event, t); + case LIBINPUT_EVENT_GESTURE_PINCH_BEGIN: + case LIBINPUT_EVENT_GESTURE_PINCH_UPDATE: + case LIBINPUT_EVENT_GESTURE_PINCH_END: + return new PinchGestureEvent(event, t); default: return new Event(event, t); } @@ -209,5 +217,58 @@ qint32 TouchEvent::id() const return libinput_event_touch_get_slot(m_touchEvent); } +GestureEvent::GestureEvent(libinput_event *event, libinput_event_type type) + : Event(event, type) + , m_gestureEvent(libinput_event_get_gesture_event(event)) +{ +} + +GestureEvent::~GestureEvent() = default; + +quint32 GestureEvent::time() const +{ + return libinput_event_gesture_get_time(m_gestureEvent); +} + +int GestureEvent::fingerCount() const +{ + return libinput_event_gesture_get_finger_count(m_gestureEvent); +} + +QSizeF GestureEvent::delta() const +{ + return QSizeF(libinput_event_gesture_get_dx(m_gestureEvent), + libinput_event_gesture_get_dy(m_gestureEvent)); +} + +bool GestureEvent::isCancelled() const +{ + return libinput_event_gesture_get_cancelled(m_gestureEvent) != 0; +} + +PinchGestureEvent::PinchGestureEvent(libinput_event *event, libinput_event_type type) + : GestureEvent(event, type) +{ +} + +PinchGestureEvent::~PinchGestureEvent() = default; + +qreal PinchGestureEvent::scale() const +{ + return libinput_event_gesture_get_scale(m_gestureEvent); +} + +qreal PinchGestureEvent::angleDelta() const +{ + return libinput_event_gesture_get_angle_delta(m_gestureEvent); +} + +SwipeGestureEvent::SwipeGestureEvent(libinput_event *event, libinput_event_type type) + : GestureEvent(event, type) +{ +} + +SwipeGestureEvent::~SwipeGestureEvent() = default; + } } diff --git a/libinput/events.h b/libinput/events.h index a20b11da64..bc8baaa7a1 100644 --- a/libinput/events.h +++ b/libinput/events.h @@ -129,6 +129,47 @@ private: libinput_event_touch *m_touchEvent; }; +class GestureEvent : public Event +{ +public: + virtual ~GestureEvent(); + + quint32 time() const; + int fingerCount() const; + + QSizeF delta() const; + + bool isCancelled() const; + + operator libinput_event_gesture*() { + return m_gestureEvent; + } + operator libinput_event_gesture*() const { + return m_gestureEvent; + } + +protected: + GestureEvent(libinput_event *event, libinput_event_type type); + libinput_event_gesture *m_gestureEvent; +}; + +class PinchGestureEvent : public GestureEvent +{ +public: + PinchGestureEvent(libinput_event *event, libinput_event_type type); + virtual ~PinchGestureEvent(); + + qreal scale() const; + qreal angleDelta() const; +}; + +class SwipeGestureEvent : public GestureEvent +{ +public: + SwipeGestureEvent(libinput_event *event, libinput_event_type type); + virtual ~SwipeGestureEvent(); +}; + inline libinput_event_type Event::type() const { diff --git a/pointer_input.cpp b/pointer_input.cpp index ee33624130..3b5df18aee 100644 --- a/pointer_input.cpp +++ b/pointer_input.cpp @@ -231,6 +231,126 @@ void PointerInputRedirection::processAxis(InputRedirection::PointerAxis axis, qr } } +void PointerInputRedirection::processSwipeGestureBegin(int fingerCount, quint32 time, KWin::LibInput::Device *device) +{ + Q_UNUSED(device) + if (!m_inited) { + return; + } + + const auto &filters = m_input->filters(); + for (auto it = filters.begin(), end = filters.end(); it != end; it++) { + if ((*it)->swipeGestureBegin(fingerCount, time)) { + return; + } + } +} + +void PointerInputRedirection::processSwipeGestureUpdate(const QSizeF &delta, quint32 time, KWin::LibInput::Device *device) +{ + Q_UNUSED(device) + if (!m_inited) { + return; + } + + const auto &filters = m_input->filters(); + for (auto it = filters.begin(), end = filters.end(); it != end; it++) { + if ((*it)->swipeGestureUpdate(delta, time)) { + return; + } + } +} + +void PointerInputRedirection::processSwipeGestureEnd(quint32 time, KWin::LibInput::Device *device) +{ + Q_UNUSED(device) + if (!m_inited) { + return; + } + + const auto &filters = m_input->filters(); + for (auto it = filters.begin(), end = filters.end(); it != end; it++) { + if ((*it)->swipeGestureEnd(time)) { + return; + } + } +} + +void PointerInputRedirection::processSwipeGestureCancelled(quint32 time, KWin::LibInput::Device *device) +{ + Q_UNUSED(device) + if (!m_inited) { + return; + } + + const auto &filters = m_input->filters(); + for (auto it = filters.begin(), end = filters.end(); it != end; it++) { + if ((*it)->swipeGestureCancelled(time)) { + return; + } + } +} + +void PointerInputRedirection::processPinchGestureBegin(int fingerCount, quint32 time, KWin::LibInput::Device *device) +{ + Q_UNUSED(device) + if (!m_inited) { + return; + } + + const auto &filters = m_input->filters(); + for (auto it = filters.begin(), end = filters.end(); it != end; it++) { + if ((*it)->pinchGestureBegin(fingerCount, time)) { + return; + } + } +} + +void PointerInputRedirection::processPinchGestureUpdate(qreal scale, qreal angleDelta, const QSizeF &delta, quint32 time, KWin::LibInput::Device *device) +{ + Q_UNUSED(device) + if (!m_inited) { + return; + } + + const auto &filters = m_input->filters(); + for (auto it = filters.begin(), end = filters.end(); it != end; it++) { + if ((*it)->pinchGestureUpdate(scale, angleDelta, delta, time)) { + return; + } + } +} + +void PointerInputRedirection::processPinchGestureEnd(quint32 time, KWin::LibInput::Device *device) +{ + Q_UNUSED(device) + if (!m_inited) { + return; + } + + const auto &filters = m_input->filters(); + for (auto it = filters.begin(), end = filters.end(); it != end; it++) { + if ((*it)->pinchGestureEnd(time)) { + return; + } + } +} + +void PointerInputRedirection::processPinchGestureCancelled(quint32 time, KWin::LibInput::Device *device) +{ + Q_UNUSED(device) + if (!m_inited) { + return; + } + + const auto &filters = m_input->filters(); + for (auto it = filters.begin(), end = filters.end(); it != end; it++) { + if ((*it)->pinchGestureCancelled(time)) { + return; + } + } +} + void PointerInputRedirection::update() { if (!m_inited) { diff --git a/pointer_input.h b/pointer_input.h index fa16c3fb93..e018d56522 100644 --- a/pointer_input.h +++ b/pointer_input.h @@ -86,6 +86,38 @@ public: * @internal */ void processAxis(InputRedirection::PointerAxis axis, qreal delta, uint32_t time, LibInput::Device *device = nullptr); + /** + * @internal + */ + void processSwipeGestureBegin(int fingerCount, quint32 time, KWin::LibInput::Device *device = nullptr); + /** + * @internal + */ + void processSwipeGestureUpdate(const QSizeF &delta, quint32 time, KWin::LibInput::Device *device = nullptr); + /** + * @internal + */ + void processSwipeGestureEnd(quint32 time, KWin::LibInput::Device *device = nullptr); + /** + * @internal + */ + void processSwipeGestureCancelled(quint32 time, KWin::LibInput::Device *device = nullptr); + /** + * @internal + */ + void processPinchGestureBegin(int fingerCount, quint32 time, KWin::LibInput::Device *device = nullptr); + /** + * @internal + */ + void processPinchGestureUpdate(qreal scale, qreal angleDelta, const QSizeF &delta, quint32 time, KWin::LibInput::Device *device = nullptr); + /** + * @internal + */ + void processPinchGestureEnd(quint32 time, KWin::LibInput::Device *device = nullptr); + /** + * @internal + */ + void processPinchGestureCancelled(quint32 time, KWin::LibInput::Device *device = nullptr); private: void updatePosition(const QPointF &pos);