diff --git a/autotests/libinput/input_event_test.cpp b/autotests/libinput/input_event_test.cpp --- a/autotests/libinput/input_event_test.cpp +++ b/autotests/libinput/input_event_test.cpp @@ -58,7 +58,7 @@ QFETCH(QEvent::Type, type); // now create our own event MouseEvent event(type, QPointF(100, 200), Qt::LeftButton, Qt::LeftButton | Qt::RightButton, - Qt::ShiftModifier | Qt::ControlModifier, 300, &d); + Qt::ShiftModifier | Qt::ControlModifier, 300, QSizeF(1, 2), QSizeF(3, 4), quint64(-1), &d); // and verify the contract of QMouseEvent QCOMPARE(event.type(), type); QCOMPARE(event.globalPos(), QPoint(100, 200)); @@ -70,6 +70,9 @@ QCOMPARE(event.timestamp(), 300ul); // and our custom argument QCOMPARE(event.device(), &d); + QCOMPARE(event.delta(), QSizeF(1, 2)); + QCOMPARE(event.deltaUnaccelerated(), QSizeF(3, 4)); + QCOMPARE(event.timestampMicroseconds(), quint64(-1)); } void InputEventsTest::testInitKeyEvent_data() diff --git a/autotests/libinput/mock_libinput.cpp b/autotests/libinput/mock_libinput.cpp --- a/autotests/libinput/mock_libinput.cpp +++ b/autotests/libinput/mock_libinput.cpp @@ -450,11 +450,26 @@ return event->delta.height(); } +double libinput_event_pointer_get_dx_unaccelerated(struct libinput_event_pointer *event) +{ + return event->delta.width(); +} + +double libinput_event_pointer_get_dy_unaccelerated(struct libinput_event_pointer *event) +{ + return event->delta.height(); +} + uint32_t libinput_event_pointer_get_time(struct libinput_event_pointer *event) { return event->time; } +uint64_t libinput_event_pointer_get_time_usec(struct libinput_event_pointer *event) +{ + return quint64(event->time * 1000); +} + uint32_t libinput_event_pointer_get_button(struct libinput_event_pointer *event) { return event->button; diff --git a/autotests/libinput/pointer_event_test.cpp b/autotests/libinput/pointer_event_test.cpp --- a/autotests/libinput/pointer_event_test.cpp +++ b/autotests/libinput/pointer_event_test.cpp @@ -128,6 +128,7 @@ QTEST(pe->buttonState(), "expectedButtonState"); QCOMPARE(pe->button(), button); QCOMPARE(pe->time(), time); + QCOMPARE(pe->timeMicroseconds(), quint64(time * 1000)); } void TestLibinputPointerEvent::testAxis_data() @@ -183,7 +184,7 @@ QVERIFY(pe); QCOMPARE(pe->type(), LIBINPUT_EVENT_POINTER_MOTION); QCOMPARE(pe->time(), 500u); - QCOMPARE(pe->delta(), QPointF(2.1, 4.5)); + QCOMPARE(pe->delta(), QSizeF(2.1, 4.5)); } void TestLibinputPointerEvent::testAbsoluteMotion() diff --git a/debug_console.cpp b/debug_console.cpp --- a/debug_console.cpp +++ b/debug_console.cpp @@ -68,6 +68,11 @@ return tableRow(i18n("Timestamp"), timestamp); } +static QString timestampRowUsec(quint64 timestamp) +{ + return tableRow(i18n("Timestamp (µsec)"), timestamp); +} + static QString buttonToString(Qt::MouseButton button) { switch (button) { @@ -171,14 +176,27 @@ text.append(s_tableStart); switch (event->type()) { - case QEvent::MouseMove: + case QEvent::MouseMove: { text.append(tableHeaderRow(i18nc("A mouse pointer motion event", "Pointer Motion"))); + auto e = static_cast(event); #if HAVE_INPUT - text.append(deviceRow(static_cast(event)->device())); + text.append(deviceRow(e->device())); #endif text.append(timestamp); + if (e->timestampMicroseconds() != 0) { + text.append(timestampRowUsec(e->timestampMicroseconds())); + } + if (e->delta() != QSizeF()) { + text.append(tableRow(i18nc("The relative mouse movement", "Delta"), + QStringLiteral("%1/%2").arg(e->delta().width()).arg(e->delta().height()))); + } + if (e->deltaUnaccelerated() != QSizeF()) { + text.append(tableRow(i18nc("The relative mouse movement", "Delta (not accelerated)"), + QStringLiteral("%1/%2").arg(e->deltaUnaccelerated().width()).arg(e->deltaUnaccelerated().height()))); + } text.append(tableRow(i18nc("The global mouse pointer position", "Global Position"), QStringLiteral("%1/%2").arg(event->pos().x()).arg(event->pos().y()))); break; + } case QEvent::MouseButtonPress: text.append(tableHeaderRow(i18nc("A mouse pointer button press event", "Pointer Button Press"))); #if HAVE_INPUT diff --git a/input.cpp b/input.cpp --- a/input.cpp +++ b/input.cpp @@ -18,6 +18,7 @@ along with this program. If not, see . *********************************************************************/ #include "input.h" +#include "input_event.h" #include "keyboard_input.h" #include "pointer_input.h" #include "touch_input.h" @@ -43,6 +44,7 @@ #include #include #include +#include #include #include //screenlocker @@ -892,13 +894,18 @@ auto seat = waylandServer()->seat(); seat->setTimestamp(event->timestamp()); switch (event->type()) { - case QEvent::MouseMove: + case QEvent::MouseMove: { if (event->buttons() == Qt::NoButton) { // update pointer window only if no button is pressed input()->pointer()->update(); } seat->setPointerPos(event->globalPos()); + MouseEvent *e = static_cast(event); + if (e->delta() != QSizeF()) { + seat->relativePointerMotion(e->delta(), e->deltaUnaccelerated(), e->timestampMicroseconds()); + } break; + } case QEvent::MouseButtonPress: seat->pointerButtonPressed(nativeButton); break; @@ -1232,6 +1239,12 @@ LibInput::Connection *conn = LibInput::Connection::create(this); m_libInput = conn; if (conn) { + + if (waylandServer()) { + // create relative pointer manager + waylandServer()->display()->createRelativePointerManager(KWayland::Server::RelativePointerInterfaceVersion::UnstableV1, waylandServer()->display())->create(); + } + conn->setInputConfig(m_inputConfig); conn->setup(); connect(conn, &LibInput::Connection::eventsRead, this, @@ -1251,8 +1264,8 @@ 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) { - m_pointer->processMotion(m_pointer->pos() + delta, time, device); + [this] (const QSizeF &delta, const QSizeF &deltaNonAccel, uint32_t time, quint64 timeMicroseconds, LibInput::Device *device) { + m_pointer->processMotion(m_pointer->pos() + QPointF(delta.width(), delta.height()), delta, deltaNonAccel, time, timeMicroseconds, device); } ); connect(conn, &LibInput::Connection::pointerMotionAbsolute, this, diff --git a/input_event.h b/input_event.h --- a/input_event.h +++ b/input_event.h @@ -33,13 +33,30 @@ { public: explicit MouseEvent(QEvent::Type type, const QPointF &pos, Qt::MouseButton button, Qt::MouseButtons buttons, - Qt::KeyboardModifiers modifiers, quint32 timestamp, LibInput::Device *device); + Qt::KeyboardModifiers modifiers, quint32 timestamp, + const QSizeF &delta, const QSizeF &deltaNonAccelerated, quint64 timestampMicroseconds, + LibInput::Device *device); + + QSizeF delta() const { + return m_delta; + } + + QSizeF deltaUnaccelerated() const { + return m_deltaUnccelerated; + } + + quint64 timestampMicroseconds() const { + return m_timestampMicroseconds; + } LibInput::Device *device() const { return m_device; } private: + QSizeF m_delta; + QSizeF m_deltaUnccelerated; + quint64 m_timestampMicroseconds; LibInput::Device *m_device; }; diff --git a/input_event.cpp b/input_event.cpp --- a/input_event.cpp +++ b/input_event.cpp @@ -24,8 +24,12 @@ MouseEvent::MouseEvent(QEvent::Type type, const QPointF &pos, Qt::MouseButton button, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, - quint32 timestamp, LibInput::Device *device) + quint32 timestamp, const QSizeF &delta, const QSizeF &deltaNonAccelerated, + quint64 timestampMicroseconds, LibInput::Device *device) : QMouseEvent(type, pos, pos, button, buttons, modifiers) + , m_delta(delta) + , m_deltaUnccelerated(deltaNonAccelerated) + , m_timestampMicroseconds(timestampMicroseconds) , m_device(device) { setTimestamp(timestamp); diff --git a/libinput/connection.h b/libinput/connection.h --- a/libinput/connection.h +++ b/libinput/connection.h @@ -86,7 +86,7 @@ void keyChanged(quint32 key, KWin::InputRedirection::KeyboardKeyState, quint32 time, KWin::LibInput::Device *device); void pointerButtonChanged(quint32 button, KWin::InputRedirection::PointerButtonState state, quint32 time, KWin::LibInput::Device *device); void pointerMotionAbsolute(QPointF orig, QPointF screen, quint32 time, KWin::LibInput::Device *device); - void pointerMotion(QPointF delta, quint32 time, KWin::LibInput::Device *device); + void pointerMotion(const QSizeF &delta, const QSizeF &deltaNonAccelerated, quint32 time, quint64 timeMicroseconds, KWin::LibInput::Device *device); void pointerAxisChanged(KWin::InputRedirection::PointerAxis axis, qreal delta, quint32 time, KWin::LibInput::Device *device); void touchFrame(KWin::LibInput::Device *device); void touchCanceled(KWin::LibInput::Device *device); diff --git a/libinput/connection.cpp b/libinput/connection.cpp --- a/libinput/connection.cpp +++ b/libinput/connection.cpp @@ -328,20 +328,24 @@ } case LIBINPUT_EVENT_POINTER_MOTION: { PointerEvent *pe = static_cast(event.data()); - QPointF delta = pe->delta(); + auto delta = pe->delta(); + auto deltaNonAccel = pe->deltaUnaccelerated(); quint32 latestTime = pe->time(); + quint64 latestTimeUsec = pe->timeMicroseconds(); auto it = m_eventQueue.begin(); while (it != m_eventQueue.end()) { if ((*it)->type() == LIBINPUT_EVENT_POINTER_MOTION) { QScopedPointer p(static_cast(*it)); delta += p->delta(); + deltaNonAccel += p->deltaUnaccelerated(); latestTime = p->time(); + latestTimeUsec = p->timeMicroseconds(); it = m_eventQueue.erase(it); } else { break; } } - emit pointerMotion(delta, latestTime, pe->device()); + emit pointerMotion(delta, deltaNonAccel, latestTime, latestTimeUsec, pe->device()); break; } case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE: { diff --git a/libinput/events.h b/libinput/events.h --- a/libinput/events.h +++ b/libinput/events.h @@ -89,10 +89,12 @@ QPointF absolutePos() const; QPointF absolutePos(const QSize &size) const; - QPointF delta() const; + QSizeF delta() const; + QSizeF deltaUnaccelerated() const; uint32_t button() const; InputRedirection::PointerButtonState buttonState() const; uint32_t time() const; + quint64 timeMicroseconds() const; QVector axis() const; qreal axisValue(InputRedirection::PointerAxis a) const; diff --git a/libinput/events.cpp b/libinput/events.cpp --- a/libinput/events.cpp +++ b/libinput/events.cpp @@ -133,17 +133,28 @@ libinput_event_pointer_get_absolute_y_transformed(m_pointerEvent, size.height())); } -QPointF PointerEvent::delta() const +QSizeF PointerEvent::delta() const { Q_ASSERT(type() == LIBINPUT_EVENT_POINTER_MOTION); - return QPointF(libinput_event_pointer_get_dx(m_pointerEvent), libinput_event_pointer_get_dy(m_pointerEvent)); + return QSizeF(libinput_event_pointer_get_dx(m_pointerEvent), libinput_event_pointer_get_dy(m_pointerEvent)); +} + +QSizeF PointerEvent::deltaUnaccelerated() const +{ + Q_ASSERT(type() == LIBINPUT_EVENT_POINTER_MOTION); + return QSizeF(libinput_event_pointer_get_dx_unaccelerated(m_pointerEvent), libinput_event_pointer_get_dy_unaccelerated(m_pointerEvent)); } uint32_t PointerEvent::time() const { return libinput_event_pointer_get_time(m_pointerEvent); } +quint64 PointerEvent::timeMicroseconds() const +{ + return libinput_event_pointer_get_time_usec(m_pointerEvent); +} + uint32_t PointerEvent::button() const { Q_ASSERT(type() == LIBINPUT_EVENT_POINTER_BUTTON); diff --git a/pointer_input.h b/pointer_input.h --- a/pointer_input.h +++ b/pointer_input.h @@ -88,6 +88,10 @@ void processMotion(const QPointF &pos, uint32_t time, LibInput::Device *device = nullptr); /** * @internal + **/ + void processMotion(const QPointF &pos, const QSizeF &delta, const QSizeF &deltaNonAccelerated, uint32_t time, quint64 timeUsec, LibInput::Device *device); + /** + * @internal */ void processButton(uint32_t button, InputRedirection::PointerButtonState state, uint32_t time, LibInput::Device *device = nullptr); /** diff --git a/pointer_input.cpp b/pointer_input.cpp --- a/pointer_input.cpp +++ b/pointer_input.cpp @@ -162,12 +162,18 @@ void PointerInputRedirection::processMotion(const QPointF &pos, uint32_t time, LibInput::Device *device) { + processMotion(pos, QSizeF(), QSizeF(), time, 0, device); +} + +void PointerInputRedirection::processMotion(const QPointF &pos, const QSizeF &delta, const QSizeF &deltaNonAccelerated, uint32_t time, quint64 timeUsec, LibInput::Device *device) +{ if (!m_inited) { return; } updatePosition(pos); MouseEvent event(QEvent::MouseMove, m_pos, Qt::NoButton, m_qtButtons, - m_input->keyboardModifiers(), time, device); + m_input->keyboardModifiers(), time, + delta, deltaNonAccelerated, timeUsec, device); const auto &filters = m_input->filters(); for (auto it = filters.begin(), end = filters.end(); it != end; it++) { @@ -199,7 +205,7 @@ } MouseEvent event(type, m_pos, buttonToQtMouseButton(button), m_qtButtons, - m_input->keyboardModifiers(), time, device); + m_input->keyboardModifiers(), time, QSizeF(), QSizeF(), 0, device); const auto &filters = m_input->filters(); for (auto it = filters.begin(), end = filters.end(); it != end; it++) { diff --git a/tests/libinputtest.cpp b/tests/libinputtest.cpp --- a/tests/libinputtest.cpp +++ b/tests/libinputtest.cpp @@ -75,8 +75,8 @@ } ); QObject::connect(conn, &Connection::pointerMotion, - [](QPointF delta) { - std::cout << "Got pointer motion: " << delta.x() << "/" << delta.y() << std::endl; + [](const QSizeF &delta) { + std::cout << "Got pointer motion: " << delta.width() << "/" << delta.height() << std::endl; } ); QObject::connect(conn, &Connection::pointerAxisChanged,