wayland: Add support for high resolution scrolling

In libinput 1.19, three new pointer axis events were added in order to
provide support for high-resolution scrolling.

LIBINPUT_EVENT_POINTER_AXIS is de-facto deprecated and new users of
libinput should use instead SCROLL_WHEEL, SCROLL_FINGER, and
SCROLL_CONTINUOUS.

Discrete deltas were replaced with v120 delta values. 120 corresponds to
a single discrete delta. Smaller values correspond to "partial" wheel
ticks.

https://gitlab.freedesktop.org/wayland/wayland/-/merge_requests/72
This commit is contained in:
Vlad Zahorodnii 2022-10-11 13:33:04 +03:00
parent 22e6b944b2
commit c147340878
21 changed files with 225 additions and 118 deletions

View file

@ -204,7 +204,7 @@ if (Wayland_Egl_FOUND)
set(HAVE_WAYLAND_EGL TRUE)
endif()
find_package(Wayland 1.20 REQUIRED COMPONENTS
find_package(Wayland 1.21 REQUIRED COMPONENTS
Server
)

View file

@ -111,7 +111,7 @@ void InputEventsTest::testInitWheelEvent_data()
{
QTest::addColumn<Qt::Orientation>("orientation");
QTest::addColumn<qreal>("delta");
QTest::addColumn<qint32>("discreteDelta");
QTest::addColumn<qint32>("deltaV120");
QTest::addColumn<QPoint>("expectedAngleDelta");
QTest::newRow("horiz") << Qt::Horizontal << 3.3 << 1 << QPoint(3, 0);
@ -129,8 +129,8 @@ void InputEventsTest::testInitWheelEvent()
// setup event
QFETCH(Qt::Orientation, orientation);
QFETCH(qreal, delta);
QFETCH(qint32, discreteDelta);
WheelEvent event(QPointF(100, 200), delta, discreteDelta, orientation, Qt::LeftButton | Qt::RightButton,
QFETCH(qint32, deltaV120);
WheelEvent event(QPointF(100, 200), delta, deltaV120, orientation, Qt::LeftButton | Qt::RightButton,
Qt::ShiftModifier | Qt::ControlModifier, InputRedirection::PointerAxisSourceWheel, 300, &d);
// compare QWheelEvent contract
QCOMPARE(event.type(), QEvent::Wheel);
@ -142,7 +142,7 @@ void InputEventsTest::testInitWheelEvent()
QTEST(event.angleDelta(), "expectedAngleDelta");
QTEST(event.orientation(), "orientation");
QTEST(event.delta(), "delta");
QTEST(event.discreteDelta(), "discreteDelta");
QTEST(event.deltaV120(), "deltaV120");
QCOMPARE(event.axisSource(), InputRedirection::PointerAxisSourceWheel);
// and our custom argument
QCOMPARE(event.device(), &d);

View file

@ -414,7 +414,9 @@ struct libinput_event_pointer *libinput_event_get_pointer_event(struct libinput_
case LIBINPUT_EVENT_POINTER_MOTION:
case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
case LIBINPUT_EVENT_POINTER_BUTTON:
case LIBINPUT_EVENT_POINTER_AXIS:
case LIBINPUT_EVENT_POINTER_SCROLL_WHEEL:
case LIBINPUT_EVENT_POINTER_SCROLL_FINGER:
case LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS:
return reinterpret_cast<libinput_event_pointer *>(event);
default:
return nullptr;
@ -595,29 +597,24 @@ int libinput_event_pointer_has_axis(struct libinput_event_pointer *event, enum l
}
}
double libinput_event_pointer_get_axis_value(struct libinput_event_pointer *event, enum libinput_pointer_axis axis)
double libinput_event_pointer_get_scroll_value(struct libinput_event_pointer *event, enum libinput_pointer_axis axis)
{
if (axis == LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL) {
return event->verticalAxisValue;
return event->verticalScrollValue;
} else {
return event->horizontalAxisValue;
return event->horizontalScrollValue;
}
}
double libinput_event_pointer_get_axis_value_discrete(struct libinput_event_pointer *event, enum libinput_pointer_axis axis)
double libinput_event_pointer_get_scroll_value_v120(struct libinput_event_pointer *event, enum libinput_pointer_axis axis)
{
if (axis == LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL) {
return event->verticalDiscreteAxisValue;
return event->verticalScrollValueV120;
} else {
return event->horizontalDiscreteAxisValue;
return event->horizontalScrollValueV120;
}
}
enum libinput_pointer_axis_source libinput_event_pointer_get_axis_source(struct libinput_event_pointer *event)
{
return event->axisSource;
}
uint32_t libinput_event_touch_get_time(struct libinput_event_touch *event)
{
return event->time;

View file

@ -128,11 +128,10 @@ struct libinput_event_pointer : libinput_event
quint32 button = 0;
bool verticalAxis = false;
bool horizontalAxis = false;
qreal horizontalAxisValue = 0.0;
qreal verticalAxisValue = 0.0;
qreal horizontalDiscreteAxisValue = 0.0;
qreal verticalDiscreteAxisValue = 0.0;
libinput_pointer_axis_source axisSource = {};
qreal horizontalScrollValue = 0.0;
qreal verticalScrollValue = 0.0;
qreal horizontalScrollValueV120 = 0.0;
qreal verticalScrollValueV120 = 0.0;
QSizeF delta;
QPointF absolutePos;
};

View file

@ -17,7 +17,6 @@
Q_DECLARE_METATYPE(libinput_event_type)
Q_DECLARE_METATYPE(libinput_button_state)
Q_DECLARE_METATYPE(libinput_pointer_axis_source)
using namespace KWin::LibInput;
@ -32,8 +31,12 @@ private Q_SLOTS:
void testType();
void testButton_data();
void testButton();
void testAxis_data();
void testAxis();
void testScrollWheel_data();
void testScrollWheel();
void testScrollFinger_data();
void testScrollFinger();
void testScrollContinuous_data();
void testScrollContinuous();
void testMotion();
void testAbsoluteMotion();
@ -66,7 +69,9 @@ void TestLibinputPointerEvent::testType_data()
QTest::newRow("motion") << LIBINPUT_EVENT_POINTER_MOTION;
QTest::newRow("absolute motion") << LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE;
QTest::newRow("button") << LIBINPUT_EVENT_POINTER_BUTTON;
QTest::newRow("axis") << LIBINPUT_EVENT_POINTER_AXIS;
QTest::newRow("scroll wheel") << LIBINPUT_EVENT_POINTER_SCROLL_WHEEL;
QTest::newRow("scroll finger") << LIBINPUT_EVENT_POINTER_SCROLL_FINGER;
QTest::newRow("scroll continuous") << LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS;
}
void TestLibinputPointerEvent::testType()
@ -122,64 +127,129 @@ void TestLibinputPointerEvent::testButton()
QCOMPARE(pe->timeMicroseconds(), quint64(time * 1000));
}
void TestLibinputPointerEvent::testAxis_data()
void TestLibinputPointerEvent::testScrollWheel_data()
{
QTest::addColumn<bool>("horizontal");
QTest::addColumn<bool>("vertical");
QTest::addColumn<QPointF>("value");
QTest::addColumn<QPoint>("discreteValue");
QTest::addColumn<libinput_pointer_axis_source>("axisSource");
QTest::addColumn<KWin::InputRedirection::PointerAxisSource>("expectedAxisSource");
QTest::addColumn<QPoint>("valueV120");
QTest::addColumn<quint32>("time");
QTest::newRow("wheel/horizontal") << true << false << QPointF(3.0, 0.0) << QPoint(1, 0) << LIBINPUT_POINTER_AXIS_SOURCE_WHEEL << KWin::InputRedirection::PointerAxisSourceWheel << 100u;
QTest::newRow("wheel/vertical") << false << true << QPointF(0.0, 2.5) << QPoint(0, 1) << LIBINPUT_POINTER_AXIS_SOURCE_WHEEL << KWin::InputRedirection::PointerAxisSourceWheel << 200u;
QTest::newRow("wheel/both") << true << true << QPointF(1.1, 4.2) << QPoint(1, 1) << LIBINPUT_POINTER_AXIS_SOURCE_WHEEL << KWin::InputRedirection::PointerAxisSourceWheel << 300u;
QTest::newRow("finger/horizontal") << true << false << QPointF(3.0, 0.0) << QPoint(0, 0) << LIBINPUT_POINTER_AXIS_SOURCE_FINGER << KWin::InputRedirection::PointerAxisSourceFinger << 400u;
QTest::newRow("stop finger/horizontal") << true << false << QPointF(0.0, 0.0) << QPoint(0, 0) << LIBINPUT_POINTER_AXIS_SOURCE_FINGER << KWin::InputRedirection::PointerAxisSourceFinger << 500u;
QTest::newRow("finger/vertical") << false << true << QPointF(0.0, 2.5) << QPoint(0, 0) << LIBINPUT_POINTER_AXIS_SOURCE_FINGER << KWin::InputRedirection::PointerAxisSourceFinger << 600u;
QTest::newRow("stop finger/vertical") << false << true << QPointF(0.0, 0.0) << QPoint(0, 0) << LIBINPUT_POINTER_AXIS_SOURCE_FINGER << KWin::InputRedirection::PointerAxisSourceFinger << 700u;
QTest::newRow("finger/both") << true << true << QPointF(1.1, 4.2) << QPoint(0, 0) << LIBINPUT_POINTER_AXIS_SOURCE_FINGER << KWin::InputRedirection::PointerAxisSourceFinger << 800u;
QTest::newRow("stop finger/both") << true << true << QPointF(0.0, 0.0) << QPoint(0, 0) << LIBINPUT_POINTER_AXIS_SOURCE_FINGER << KWin::InputRedirection::PointerAxisSourceFinger << 900u;
QTest::newRow("continuous/horizontal") << true << false << QPointF(3.0, 0.0) << QPoint(0, 0) << LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS << KWin::InputRedirection::PointerAxisSourceContinuous << 1000u;
QTest::newRow("continuous/vertical") << false << true << QPointF(0.0, 2.5) << QPoint(0, 0) << LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS << KWin::InputRedirection::PointerAxisSourceContinuous << 1100u;
QTest::newRow("continuous/both") << true << true << QPointF(1.1, 4.2) << QPoint(0, 0) << LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS << KWin::InputRedirection::PointerAxisSourceContinuous << 1200u;
QTest::newRow("wheel/horizontal") << true << false << QPointF(3.0, 0.0) << QPoint(120, 0) << 100u;
QTest::newRow("wheel/vertical") << false << true << QPointF(0.0, 2.5) << QPoint(0, 120) << 200u;
QTest::newRow("wheel/both") << true << true << QPointF(1.1, 4.2) << QPoint(120, 120) << 300u;
}
void TestLibinputPointerEvent::testAxis()
void TestLibinputPointerEvent::testScrollWheel()
{
// this test verifies pointer axis functionality
libinput_event_pointer *pointerEvent = new libinput_event_pointer;
pointerEvent->device = m_nativeDevice;
pointerEvent->type = LIBINPUT_EVENT_POINTER_AXIS;
pointerEvent->type = LIBINPUT_EVENT_POINTER_SCROLL_WHEEL;
QFETCH(bool, horizontal);
QFETCH(bool, vertical);
QFETCH(QPointF, value);
QFETCH(QPoint, discreteValue);
QFETCH(libinput_pointer_axis_source, axisSource);
QFETCH(QPoint, valueV120);
QFETCH(quint32, time);
pointerEvent->horizontalAxis = horizontal;
pointerEvent->verticalAxis = vertical;
pointerEvent->horizontalAxisValue = value.x();
pointerEvent->verticalAxisValue = value.y();
pointerEvent->horizontalDiscreteAxisValue = discreteValue.x();
pointerEvent->verticalDiscreteAxisValue = discreteValue.y();
pointerEvent->axisSource = axisSource;
pointerEvent->horizontalScrollValue = value.x();
pointerEvent->verticalScrollValue = value.y();
pointerEvent->horizontalScrollValueV120 = valueV120.x();
pointerEvent->verticalScrollValueV120 = valueV120.y();
pointerEvent->time = time;
std::unique_ptr<Event> event(Event::create(pointerEvent));
auto pe = dynamic_cast<PointerEvent *>(event.get());
QVERIFY(pe);
QCOMPARE(pe->type(), LIBINPUT_EVENT_POINTER_AXIS);
QCOMPARE(pe->type(), LIBINPUT_EVENT_POINTER_SCROLL_WHEEL);
QCOMPARE(pe->axis().contains(KWin::InputRedirection::PointerAxisHorizontal), horizontal);
QCOMPARE(pe->axis().contains(KWin::InputRedirection::PointerAxisVertical), vertical);
QCOMPARE(pe->axisValue(KWin::InputRedirection::PointerAxisHorizontal), value.x());
QCOMPARE(pe->axisValue(KWin::InputRedirection::PointerAxisVertical), value.y());
QCOMPARE(pe->discreteAxisValue(KWin::InputRedirection::PointerAxisHorizontal), discreteValue.x());
QCOMPARE(pe->discreteAxisValue(KWin::InputRedirection::PointerAxisVertical), discreteValue.y());
QTEST(pe->axisSource(), "expectedAxisSource");
QCOMPARE(pe->scrollValue(KWin::InputRedirection::PointerAxisHorizontal), value.x());
QCOMPARE(pe->scrollValue(KWin::InputRedirection::PointerAxisVertical), value.y());
QCOMPARE(pe->scrollValueV120(KWin::InputRedirection::PointerAxisHorizontal), valueV120.x());
QCOMPARE(pe->scrollValueV120(KWin::InputRedirection::PointerAxisVertical), valueV120.y());
QCOMPARE(pe->time(), time);
}
void TestLibinputPointerEvent::testScrollFinger_data()
{
QTest::addColumn<bool>("horizontal");
QTest::addColumn<bool>("vertical");
QTest::addColumn<QPointF>("value");
QTest::addColumn<quint32>("time");
QTest::newRow("finger/horizontal") << true << false << QPointF(3.0, 0.0) << 400u;
QTest::newRow("stop finger/horizontal") << true << false << QPointF(0.0, 0.0) << 500u;
QTest::newRow("finger/vertical") << false << true << QPointF(0.0, 2.5) << 600u;
QTest::newRow("stop finger/vertical") << false << true << QPointF(0.0, 0.0) << 700u;
QTest::newRow("finger/both") << true << true << QPointF(1.1, 4.2) << 800u;
QTest::newRow("stop finger/both") << true << true << QPointF(0.0, 0.0) << 900u;
}
void TestLibinputPointerEvent::testScrollFinger()
{
// this test verifies pointer axis functionality
libinput_event_pointer *pointerEvent = new libinput_event_pointer;
pointerEvent->device = m_nativeDevice;
pointerEvent->type = LIBINPUT_EVENT_POINTER_SCROLL_FINGER;
QFETCH(bool, horizontal);
QFETCH(bool, vertical);
QFETCH(QPointF, value);
QFETCH(quint32, time);
pointerEvent->horizontalAxis = horizontal;
pointerEvent->verticalAxis = vertical;
pointerEvent->horizontalScrollValue = value.x();
pointerEvent->verticalScrollValue = value.y();
pointerEvent->time = time;
std::unique_ptr<Event> event(Event::create(pointerEvent));
auto pe = dynamic_cast<PointerEvent *>(event.get());
QVERIFY(pe);
QCOMPARE(pe->type(), LIBINPUT_EVENT_POINTER_SCROLL_FINGER);
QCOMPARE(pe->axis().contains(KWin::InputRedirection::PointerAxisHorizontal), horizontal);
QCOMPARE(pe->axis().contains(KWin::InputRedirection::PointerAxisVertical), vertical);
QCOMPARE(pe->scrollValue(KWin::InputRedirection::PointerAxisHorizontal), value.x());
QCOMPARE(pe->scrollValue(KWin::InputRedirection::PointerAxisVertical), value.y());
QCOMPARE(pe->time(), time);
}
void TestLibinputPointerEvent::testScrollContinuous_data()
{
QTest::addColumn<bool>("horizontal");
QTest::addColumn<bool>("vertical");
QTest::addColumn<QPointF>("value");
QTest::addColumn<quint32>("time");
QTest::newRow("continuous/horizontal") << true << false << QPointF(3.0, 0.0) << 1000u;
QTest::newRow("continuous/vertical") << false << true << QPointF(0.0, 2.5) << 1100u;
QTest::newRow("continuous/both") << true << true << QPointF(1.1, 4.2) << 1200u;
}
void TestLibinputPointerEvent::testScrollContinuous()
{
// this test verifies pointer axis functionality
libinput_event_pointer *pointerEvent = new libinput_event_pointer;
pointerEvent->device = m_nativeDevice;
pointerEvent->type = LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS;
QFETCH(bool, horizontal);
QFETCH(bool, vertical);
QFETCH(QPointF, value);
QFETCH(quint32, time);
pointerEvent->horizontalAxis = horizontal;
pointerEvent->verticalAxis = vertical;
pointerEvent->horizontalScrollValue = value.x();
pointerEvent->verticalScrollValue = value.y();
pointerEvent->time = time;
std::unique_ptr<Event> event(Event::create(pointerEvent));
auto pe = dynamic_cast<PointerEvent *>(event.get());
QVERIFY(pe);
QCOMPARE(pe->type(), LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS);
QCOMPARE(pe->axis().contains(KWin::InputRedirection::PointerAxisHorizontal), horizontal);
QCOMPARE(pe->axis().contains(KWin::InputRedirection::PointerAxisVertical), vertical);
QCOMPARE(pe->scrollValue(KWin::InputRedirection::PointerAxisHorizontal), value.x());
QCOMPARE(pe->scrollValue(KWin::InputRedirection::PointerAxisVertical), value.y());
QCOMPARE(pe->time(), time);
}

View file

@ -300,12 +300,42 @@ void Connection::processEvents()
Q_EMIT ke->device()->keyChanged(ke->key(), ke->state(), ke->time(), ke->device());
break;
}
case LIBINPUT_EVENT_POINTER_AXIS: {
PointerEvent *pe = static_cast<PointerEvent *>(event.get());
const auto axes = pe->axis();
case LIBINPUT_EVENT_POINTER_SCROLL_WHEEL: {
const PointerEvent *pointerEvent = static_cast<PointerEvent *>(event.get());
const auto axes = pointerEvent->axis();
for (const InputRedirection::PointerAxis &axis : axes) {
Q_EMIT pe->device()->pointerAxisChanged(axis, pe->axisValue(axis), pe->discreteAxisValue(axis),
pe->axisSource(), pe->time(), pe->device());
Q_EMIT pointerEvent->device()->pointerAxisChanged(axis,
pointerEvent->scrollValue(axis),
pointerEvent->scrollValueV120(axis),
InputRedirection::PointerAxisSourceWheel,
pointerEvent->time(),
pointerEvent->device());
}
break;
}
case LIBINPUT_EVENT_POINTER_SCROLL_FINGER: {
const PointerEvent *pointerEvent = static_cast<PointerEvent *>(event.get());
const auto axes = pointerEvent->axis();
for (const InputRedirection::PointerAxis &axis : axes) {
Q_EMIT pointerEvent->device()->pointerAxisChanged(axis,
pointerEvent->scrollValue(axis),
0,
InputRedirection::PointerAxisSourceFinger,
pointerEvent->time(),
pointerEvent->device());
}
break;
}
case LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS: {
const PointerEvent *pointerEvent = static_cast<PointerEvent *>(event.get());
const auto axes = pointerEvent->axis();
for (const InputRedirection::PointerAxis &axis : axes) {
Q_EMIT pointerEvent->device()->pointerAxisChanged(axis,
pointerEvent->scrollValue(axis),
0,
InputRedirection::PointerAxisSourceContinuous,
pointerEvent->time(),
pointerEvent->device());
}
break;
}

View file

@ -27,7 +27,9 @@ std::unique_ptr<Event> Event::create(libinput_event *event)
switch (t) {
case LIBINPUT_EVENT_KEYBOARD_KEY:
return std::make_unique<KeyEvent>(event);
case LIBINPUT_EVENT_POINTER_AXIS:
case LIBINPUT_EVENT_POINTER_SCROLL_WHEEL:
case LIBINPUT_EVENT_POINTER_SCROLL_FINGER:
case LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS:
case LIBINPUT_EVENT_POINTER_BUTTON:
case LIBINPUT_EVENT_POINTER_MOTION:
case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
@ -191,7 +193,6 @@ InputRedirection::PointerButtonState PointerEvent::buttonState() const
QVector<InputRedirection::PointerAxis> PointerEvent::axis() const
{
Q_ASSERT(type() == LIBINPUT_EVENT_POINTER_AXIS);
QVector<InputRedirection::PointerAxis> a;
if (libinput_event_pointer_has_axis(m_pointerEvent, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL)) {
a << InputRedirection::PointerAxisHorizontal;
@ -202,39 +203,20 @@ QVector<InputRedirection::PointerAxis> PointerEvent::axis() const
return a;
}
qreal PointerEvent::axisValue(InputRedirection::PointerAxis axis) const
qreal PointerEvent::scrollValue(InputRedirection::PointerAxis axis) const
{
Q_ASSERT(type() == LIBINPUT_EVENT_POINTER_AXIS);
const libinput_pointer_axis a = axis == InputRedirection::PointerAxisHorizontal
? LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL
: LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL;
return libinput_event_pointer_get_axis_value(m_pointerEvent, a) * device()->scrollFactor();
return libinput_event_pointer_get_scroll_value(m_pointerEvent, a) * device()->scrollFactor();
}
qint32 PointerEvent::discreteAxisValue(InputRedirection::PointerAxis axis) const
qint32 PointerEvent::scrollValueV120(InputRedirection::PointerAxis axis) const
{
Q_ASSERT(type() == LIBINPUT_EVENT_POINTER_AXIS);
const libinput_pointer_axis a = (axis == InputRedirection::PointerAxisHorizontal)
? LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL
: LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL;
return libinput_event_pointer_get_axis_value_discrete(m_pointerEvent, a) * device()->scrollFactor();
}
InputRedirection::PointerAxisSource PointerEvent::axisSource() const
{
Q_ASSERT(type() == LIBINPUT_EVENT_POINTER_AXIS);
switch (libinput_event_pointer_get_axis_source(m_pointerEvent)) {
case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL:
return InputRedirection::PointerAxisSourceWheel;
case LIBINPUT_POINTER_AXIS_SOURCE_FINGER:
return InputRedirection::PointerAxisSourceFinger;
case LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS:
return InputRedirection::PointerAxisSourceContinuous;
case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL_TILT:
return InputRedirection::PointerAxisSourceWheelTilt;
default:
return InputRedirection::PointerAxisSourceUnknown;
}
return libinput_event_pointer_get_scroll_value_v120(m_pointerEvent, a) * device()->scrollFactor();
}
TouchEvent::TouchEvent(libinput_event *event, libinput_event_type type)

View file

@ -87,9 +87,8 @@ public:
uint32_t time() const;
quint64 timeMicroseconds() const;
QVector<InputRedirection::PointerAxis> axis() const;
qreal axisValue(InputRedirection::PointerAxis a) const;
qint32 discreteAxisValue(InputRedirection::PointerAxis axis) const;
InputRedirection::PointerAxisSource axisSource() const;
qreal scrollValue(InputRedirection::PointerAxis a) const;
qint32 scrollValueV120(InputRedirection::PointerAxis axis) const;
operator libinput_event_pointer *()
{

View file

@ -511,7 +511,7 @@ void X11WindowedBackend::handleButtonPress(xcb_button_press_event_t *event)
if (!pressed) {
return;
}
const int delta = (event->detail == XCB_BUTTON_INDEX_4 || event->detail == 6) ? -1 : 1;
const int delta = (event->detail == XCB_BUTTON_INDEX_4 || event->detail == 6) ? -120 : 120;
static const qreal s_defaultAxisStepDistance = 10.0;
InputRedirection::PointerAxis axis;
if (event->detail > 5) {

View file

@ -49,7 +49,7 @@ Q_SIGNALS:
void pointerButtonChanged(quint32 button, InputRedirection::PointerButtonState state, quint32 time, InputDevice *device);
void pointerMotionAbsolute(const QPointF &position, quint32 time, InputDevice *device);
void pointerMotion(const QSizeF &delta, const QSizeF &deltaNonAccelerated, quint32 time, quint64 timeMicroseconds, InputDevice *device);
void pointerAxisChanged(InputRedirection::PointerAxis axis, qreal delta, qint32 discreteDelta,
void pointerAxisChanged(InputRedirection::PointerAxis axis, qreal delta, qint32 deltaV120,
InputRedirection::PointerAxisSource source, quint32 time, InputDevice *device);
void touchFrame(InputDevice *device);
void touchCanceled(InputDevice *device);

View file

@ -392,7 +392,7 @@ public:
const WheelEvent *wheelEvent = static_cast<WheelEvent *>(event);
seat->setTimestamp(wheelEvent->timestamp());
seat->notifyPointerAxis(wheelEvent->orientation(), wheelEvent->delta(),
wheelEvent->discreteDelta(),
wheelEvent->deltaV120(),
kwinAxisSourceToKWaylandAxisSource(wheelEvent->axisSource()));
seat->notifyPointerFrame();
}
@ -1866,7 +1866,7 @@ public:
auto seat = waylandServer()->seat();
seat->setTimestamp(event->timestamp());
auto _event = static_cast<WheelEvent *>(event);
seat->notifyPointerAxis(_event->orientation(), _event->delta(), _event->discreteDelta(),
seat->notifyPointerAxis(_event->orientation(), _event->delta(), _event->deltaV120(),
kwinAxisSourceToKWaylandAxisSource(_event->axisSource()));
seat->notifyPointerFrame();
return true;

View file

@ -24,14 +24,14 @@ MouseEvent::MouseEvent(QEvent::Type type, const QPointF &pos, Qt::MouseButton bu
setTimestamp(timestamp);
}
WheelEvent::WheelEvent(const QPointF &pos, qreal delta, qint32 discreteDelta, Qt::Orientation orientation,
WheelEvent::WheelEvent(const QPointF &pos, qreal delta, qint32 deltaV120, Qt::Orientation orientation,
Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, InputRedirection::PointerAxisSource source,
quint32 timestamp, InputDevice *device)
: QWheelEvent(pos, pos, QPoint(), (orientation == Qt::Horizontal) ? QPoint(delta, 0) : QPoint(0, delta), buttons, modifiers, Qt::NoScrollPhase, false)
, m_device(device)
, m_orientation(orientation)
, m_delta(delta)
, m_discreteDelta(discreteDelta)
, m_deltaV120(deltaV120)
, m_source(source)
{
setTimestamp(timestamp);

View file

@ -79,7 +79,7 @@ private:
class WheelEvent : public QWheelEvent
{
public:
explicit WheelEvent(const QPointF &pos, qreal delta, qint32 discreteDelta, Qt::Orientation orientation,
explicit WheelEvent(const QPointF &pos, qreal delta, qint32 deltaV120, Qt::Orientation orientation,
Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, InputRedirection::PointerAxisSource source,
quint32 timestamp, InputDevice *device);
@ -93,9 +93,9 @@ public:
return m_delta;
}
qint32 discreteDelta() const
qint32 deltaV120() const
{
return m_discreteDelta;
return m_deltaV120;
}
InputRedirection::PointerAxisSource axisSource() const
@ -122,7 +122,7 @@ private:
InputDevice *m_device;
Qt::Orientation m_orientation;
qreal m_delta;
qint32 m_discreteDelta;
qint32 m_deltaV120;
InputRedirection::PointerAxisSource m_source;
Qt::KeyboardModifiers m_modifiersRelevantForShortcuts = Qt::KeyboardModifiers();
};

View file

@ -290,7 +290,7 @@ void PointerInputRedirection::processButton(uint32_t button, InputRedirection::P
}
}
void PointerInputRedirection::processAxis(InputRedirection::PointerAxis axis, qreal delta, qint32 discreteDelta,
void PointerInputRedirection::processAxis(InputRedirection::PointerAxis axis, qreal delta, qint32 deltaV120,
InputRedirection::PointerAxisSource source, uint32_t time, InputDevice *device)
{
input()->setLastInputHandler(this);
@ -298,7 +298,7 @@ void PointerInputRedirection::processAxis(InputRedirection::PointerAxis axis, qr
Q_EMIT input()->pointerAxisChanged(axis, delta);
WheelEvent wheelEvent(m_pos, delta, discreteDelta,
WheelEvent wheelEvent(m_pos, delta, deltaV120,
(axis == InputRedirection::PointerAxisHorizontal) ? Qt::Horizontal : Qt::Vertical,
m_qtButtons, input()->keyboardModifiers(), source, time, device);
wheelEvent.setModifiersRelevantForGlobalShortcuts(input()->modifiersRelevantForGlobalShortcuts());

View file

@ -96,7 +96,7 @@ public:
/**
* @internal
*/
void processAxis(InputRedirection::PointerAxis axis, qreal delta, qint32 discreteDelta, InputRedirection::PointerAxisSource source, uint32_t time, InputDevice *device = nullptr);
void processAxis(InputRedirection::PointerAxis axis, qreal delta, qint32 deltaV120, InputRedirection::PointerAxisSource source, uint32_t time, InputDevice *device = nullptr);
/**
* @internal
*/

View file

@ -407,12 +407,12 @@ void TestWaylandSeat::testPointer()
// test axis
m_seatInterface->setTimestamp(2);
m_seatInterface->notifyPointerAxis(Qt::Horizontal, 10, 1, PointerAxisSource::Wheel);
m_seatInterface->notifyPointerAxis(Qt::Horizontal, 10, 120, PointerAxisSource::Wheel);
m_seatInterface->notifyPointerFrame();
QVERIFY(axisSpy.wait());
QCOMPARE(frameSpy.count(), 6);
m_seatInterface->setTimestamp(3);
m_seatInterface->notifyPointerAxis(Qt::Vertical, 20, 2, PointerAxisSource::Wheel);
m_seatInterface->notifyPointerAxis(Qt::Vertical, 20, 240, PointerAxisSource::Wheel);
m_seatInterface->notifyPointerFrame();
QVERIFY(axisSpy.wait());
QCOMPARE(frameSpy.count(), 7);
@ -1196,7 +1196,7 @@ void TestWaylandSeat::testPointerAxis()
quint32 timestamp = 1;
m_seatInterface->setTimestamp(timestamp++);
m_seatInterface->notifyPointerAxis(Qt::Vertical, 10, 1, PointerAxisSource::Wheel);
m_seatInterface->notifyPointerAxis(Qt::Vertical, 10, 120, PointerAxisSource::Wheel);
m_seatInterface->notifyPointerFrame();
QVERIFY(frameSpy.wait());
QCOMPARE(frameSpy.count(), 2);
@ -1242,7 +1242,7 @@ void TestWaylandSeat::testPointerAxis()
// if the device is unknown, no axis_source event should be sent
m_seatInterface->setTimestamp(timestamp++);
m_seatInterface->notifyPointerAxis(Qt::Horizontal, 42, 1, PointerAxisSource::Unknown);
m_seatInterface->notifyPointerAxis(Qt::Horizontal, 42, 120, PointerAxisSource::Unknown);
m_seatInterface->notifyPointerFrame();
QVERIFY(frameSpy.wait());
QCOMPARE(frameSpy.count(), 5);

View file

@ -208,12 +208,35 @@ void PointerInterface::sendButton(quint32 button, PointerButtonState state, quin
}
}
void PointerInterface::sendAxis(Qt::Orientation orientation, qreal delta, qint32 discreteDelta, PointerAxisSource source)
static bool shouldResetAccumulator(int accumulator, int delta)
{
// Reset the accumulator if the delta has opposite sign.
return accumulator && (accumulator < 0 != delta < 0);
}
void PointerInterface::sendAxis(Qt::Orientation orientation, qreal delta, qint32 deltaV120, PointerAxisSource source)
{
if (!d->focusedSurface) {
return;
}
qint32 deltaDiscrete;
if (orientation == Qt::Horizontal) {
if (shouldResetAccumulator(d->accumulatorV120.x(), deltaV120)) {
d->accumulatorV120.setX(0);
}
d->accumulatorV120.rx() += deltaV120;
deltaDiscrete = d->accumulatorV120.x() / 120;
d->accumulatorV120.rx() -= deltaDiscrete * 120;
} else {
if (shouldResetAccumulator(d->accumulatorV120.y(), deltaV120)) {
d->accumulatorV120.setY(0);
}
d->accumulatorV120.ry() += deltaV120;
deltaDiscrete = d->accumulatorV120.y() / 120;
d->accumulatorV120.ry() -= deltaDiscrete * 120;
}
const auto pointerResources = d->pointersForClient(d->focusedSurface->client());
for (PointerInterfacePrivate::Resource *resource : pointerResources) {
const quint32 version = resource->version();
@ -244,8 +267,14 @@ void PointerInterface::sendAxis(Qt::Orientation orientation, qreal delta, qint32
}
if (delta != 0.0) {
if (discreteDelta && version >= WL_POINTER_AXIS_DISCRETE_SINCE_VERSION) {
d->send_axis_discrete(resource->handle, wlOrientation, discreteDelta);
if (version >= WL_POINTER_AXIS_VALUE120_SINCE_VERSION) {
if (deltaV120) {
d->send_axis_value120(resource->handle, wlOrientation, deltaV120);
}
} else if (version >= WL_POINTER_AXIS_DISCRETE_SINCE_VERSION) {
if (deltaDiscrete) {
d->send_axis_discrete(resource->handle, wlOrientation, deltaDiscrete);
}
}
d->send_axis(resource->handle, d->seat->timestamp(), wlOrientation, wl_fixed_from_double(delta));
} else if (version >= WL_POINTER_AXIS_STOP_SINCE_VERSION) {

View file

@ -58,7 +58,7 @@ public:
void sendEnter(SurfaceInterface *surface, const QPointF &position, quint32 serial);
void sendLeave(quint32 serial);
void sendButton(quint32 button, PointerButtonState state, quint32 serial);
void sendAxis(Qt::Orientation orientation, qreal delta, qint32 discreteDelta, PointerAxisSource source);
void sendAxis(Qt::Orientation orientation, qreal delta, qint32 deltaV120, PointerAxisSource source);
void sendMotion(const QPointF &position);
void sendFrame();

View file

@ -43,6 +43,7 @@ public:
std::unique_ptr<PointerPinchGestureV1Interface> pinchGesturesV1;
std::unique_ptr<PointerHoldGestureV1Interface> holdGesturesV1;
QPointF lastPosition;
QPoint accumulatorV120;
void sendLeave(quint32 serial);
void sendEnter(const QPointF &parentSurfacePosition, quint32 serial);

View file

@ -37,7 +37,7 @@
namespace KWaylandServer
{
static const int s_version = 7;
static const int s_version = 8;
SeatInterfacePrivate *SeatInterfacePrivate::get(SeatInterface *seat)
{
@ -690,7 +690,7 @@ bool SeatInterface::isPointerButtonPressed(quint32 button) const
return it.value() == SeatInterfacePrivate::Pointer::State::Pressed;
}
void SeatInterface::notifyPointerAxis(Qt::Orientation orientation, qreal delta, qint32 discreteDelta, PointerAxisSource source)
void SeatInterface::notifyPointerAxis(Qt::Orientation orientation, qreal delta, qint32 deltaV120, PointerAxisSource source)
{
if (!d->pointer) {
return;
@ -699,7 +699,7 @@ void SeatInterface::notifyPointerAxis(Qt::Orientation orientation, qreal delta,
// ignore
return;
}
d->pointer->sendAxis(orientation, delta, discreteDelta, source);
d->pointer->sendAxis(orientation, delta, deltaV120, source);
}
void SeatInterface::notifyPointerButton(Qt::MouseButton button, PointerButtonState state)

View file

@ -374,10 +374,10 @@ public:
*
* @param orientation The scroll axis.
* @param delta The length of a vector along the specified axis @p orientation.
* @param discreteDelta The number of discrete steps, e.g. mouse wheel clicks.
* @param deltaV120 The high-resolution scrolling axis value.
* @param source Describes how the axis event was physically generated.
*/
void notifyPointerAxis(Qt::Orientation orientation, qreal delta, qint32 discreteDelta, PointerAxisSource source);
void notifyPointerAxis(Qt::Orientation orientation, qreal delta, qint32 deltaV120, PointerAxisSource source);
/**
* @returns true if there is a pressed button with the given @p serial
*/