wayland: Fix high-res scroll events with low-res clients
Sending an axis event for every high-res scroll wheel movement was causing excessive scrolling on clients that expect low-res (discrete) scroll events. Signed-off-by: John Brooks <john@fastquake.com>
This commit is contained in:
parent
a873830a86
commit
a276e6dc10
3 changed files with 68 additions and 25 deletions
|
@ -477,7 +477,7 @@ void TestDragAndDrop::testPointerEventsIgnored()
|
||||||
m_seatInterface->setTimestamp(timestamp++);
|
m_seatInterface->setTimestamp(timestamp++);
|
||||||
m_seatInterface->notifyPointerMotion(QPointF(10, 10));
|
m_seatInterface->notifyPointerMotion(QPointF(10, 10));
|
||||||
m_seatInterface->setTimestamp(timestamp++);
|
m_seatInterface->setTimestamp(timestamp++);
|
||||||
m_seatInterface->notifyPointerAxis(Qt::Vertical, 5, 1, PointerAxisSource::Wheel);
|
m_seatInterface->notifyPointerAxis(Qt::Vertical, 5, 120, PointerAxisSource::Wheel);
|
||||||
m_seatInterface->notifyPointerFrame();
|
m_seatInterface->notifyPointerFrame();
|
||||||
// verify that we have those
|
// verify that we have those
|
||||||
QVERIFY(axisSpy.wait());
|
QVERIFY(axisSpy.wait());
|
||||||
|
|
|
@ -214,35 +214,63 @@ static bool shouldResetAccumulator(int accumulator, int delta)
|
||||||
return accumulator && (accumulator < 0 != delta < 0);
|
return accumulator && (accumulator < 0 != delta < 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void updateAccumulators(Qt::Orientation orientation, qreal delta, qint32 deltaV120, PointerInterfacePrivate *d, qint32 &valueAxisLowRes, qint32 &valueDiscrete)
|
||||||
|
{
|
||||||
|
qint32 *accumulatorV120;
|
||||||
|
qreal *accumulatorAxis;
|
||||||
|
|
||||||
|
if (orientation == Qt::Horizontal) {
|
||||||
|
accumulatorV120 = &d->accumulatorV120.rx();
|
||||||
|
accumulatorAxis = &d->accumulatorAxis.rx();
|
||||||
|
} else {
|
||||||
|
accumulatorV120 = &d->accumulatorV120.ry();
|
||||||
|
accumulatorAxis = &d->accumulatorAxis.ry();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldResetAccumulator(*accumulatorV120, deltaV120)) {
|
||||||
|
*accumulatorV120 = 0;
|
||||||
|
*accumulatorAxis = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*accumulatorAxis += delta;
|
||||||
|
*accumulatorV120 += deltaV120;
|
||||||
|
|
||||||
|
// ±120 is a "wheel click"
|
||||||
|
valueDiscrete = *accumulatorV120 / 120;
|
||||||
|
*accumulatorV120 -= valueDiscrete * 120;
|
||||||
|
|
||||||
|
if (valueDiscrete) {
|
||||||
|
// Accumulate the axis values to send to low-res clients
|
||||||
|
valueAxisLowRes = *accumulatorAxis;
|
||||||
|
*accumulatorAxis = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PointerInterface::sendAxis(Qt::Orientation orientation, qreal delta, qint32 deltaV120, PointerAxisSource source)
|
void PointerInterface::sendAxis(Qt::Orientation orientation, qreal delta, qint32 deltaV120, PointerAxisSource source)
|
||||||
{
|
{
|
||||||
if (!d->focusedSurface) {
|
if (!d->focusedSurface) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
qint32 deltaDiscrete;
|
qint32 valueAxisLowRes = 0;
|
||||||
if (orientation == Qt::Horizontal) {
|
qint32 valueDiscrete = 0;
|
||||||
if (shouldResetAccumulator(d->accumulatorV120.x(), deltaV120)) {
|
|
||||||
d->accumulatorV120.setX(0);
|
if (deltaV120) {
|
||||||
}
|
updateAccumulators(orientation, delta, deltaV120, d.get(),
|
||||||
d->accumulatorV120.rx() += deltaV120;
|
valueAxisLowRes, valueDiscrete);
|
||||||
deltaDiscrete = d->accumulatorV120.x() / 120;
|
|
||||||
d->accumulatorV120.rx() -= deltaDiscrete * 120;
|
|
||||||
} else {
|
} else {
|
||||||
if (shouldResetAccumulator(d->accumulatorV120.y(), deltaV120)) {
|
valueAxisLowRes = delta;
|
||||||
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());
|
const auto pointerResources = d->pointersForClient(d->focusedSurface->client());
|
||||||
for (PointerInterfacePrivate::Resource *resource : pointerResources) {
|
for (PointerInterfacePrivate::Resource *resource : pointerResources) {
|
||||||
const quint32 version = resource->version();
|
const quint32 version = resource->version();
|
||||||
|
|
||||||
const auto wlOrientation =
|
// Don't send anything if the client doesn't support high-res scrolling and
|
||||||
(orientation == Qt::Vertical) ? PointerInterfacePrivate::axis_vertical_scroll : PointerInterfacePrivate::axis_horizontal_scroll;
|
// we haven't accumulated a wheel click's worth of events.
|
||||||
|
if (version < WL_POINTER_AXIS_VALUE120_SINCE_VERSION && deltaV120 && !valueDiscrete) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (source != PointerAxisSource::Unknown && version >= WL_POINTER_AXIS_SOURCE_SINCE_VERSION) {
|
if (source != PointerAxisSource::Unknown && version >= WL_POINTER_AXIS_SOURCE_SINCE_VERSION) {
|
||||||
PointerInterfacePrivate::axis_source wlSource;
|
PointerInterfacePrivate::axis_source wlSource;
|
||||||
|
@ -266,17 +294,31 @@ void PointerInterface::sendAxis(Qt::Orientation orientation, qreal delta, qint32
|
||||||
d->send_axis_source(resource->handle, wlSource);
|
d->send_axis_source(resource->handle, wlSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (delta != 0.0) {
|
const auto wlOrientation =
|
||||||
if (version >= WL_POINTER_AXIS_VALUE120_SINCE_VERSION) {
|
(orientation == Qt::Vertical) ? PointerInterfacePrivate::axis_vertical_scroll : PointerInterfacePrivate::axis_horizontal_scroll;
|
||||||
if (deltaV120) {
|
|
||||||
|
if (delta) {
|
||||||
|
if (deltaV120) {
|
||||||
|
if (version >= WL_POINTER_AXIS_VALUE120_SINCE_VERSION) {
|
||||||
|
// Send high resolution scroll events if client supports them
|
||||||
d->send_axis_value120(resource->handle, wlOrientation, deltaV120);
|
d->send_axis_value120(resource->handle, wlOrientation, deltaV120);
|
||||||
|
d->send_axis(resource->handle, d->seat->timestamp().count(), wlOrientation,
|
||||||
|
wl_fixed_from_double(delta));
|
||||||
|
} else {
|
||||||
|
if (version >= WL_POINTER_AXIS_DISCRETE_SINCE_VERSION && valueDiscrete) {
|
||||||
|
// Send discrete scroll events if client supports them.
|
||||||
|
d->send_axis_discrete(resource->handle, wlOrientation,
|
||||||
|
valueDiscrete);
|
||||||
|
}
|
||||||
|
// Send accumulated axis values
|
||||||
|
d->send_axis(resource->handle, d->seat->timestamp().count(), wlOrientation,
|
||||||
|
wl_fixed_from_double(valueAxisLowRes));
|
||||||
}
|
}
|
||||||
} else if (version >= WL_POINTER_AXIS_DISCRETE_SINCE_VERSION) {
|
} else {
|
||||||
if (deltaDiscrete) {
|
// Finger or continuous scroll
|
||||||
d->send_axis_discrete(resource->handle, wlOrientation, deltaDiscrete);
|
d->send_axis(resource->handle, d->seat->timestamp().count(), wlOrientation,
|
||||||
}
|
wl_fixed_from_double(delta));
|
||||||
}
|
}
|
||||||
d->send_axis(resource->handle, d->seat->timestamp().count(), wlOrientation, wl_fixed_from_double(delta));
|
|
||||||
} else if (version >= WL_POINTER_AXIS_STOP_SINCE_VERSION) {
|
} else if (version >= WL_POINTER_AXIS_STOP_SINCE_VERSION) {
|
||||||
d->send_axis_stop(resource->handle, d->seat->timestamp().count(), wlOrientation);
|
d->send_axis_stop(resource->handle, d->seat->timestamp().count(), wlOrientation);
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,7 @@ public:
|
||||||
std::unique_ptr<PointerPinchGestureV1Interface> pinchGesturesV1;
|
std::unique_ptr<PointerPinchGestureV1Interface> pinchGesturesV1;
|
||||||
std::unique_ptr<PointerHoldGestureV1Interface> holdGesturesV1;
|
std::unique_ptr<PointerHoldGestureV1Interface> holdGesturesV1;
|
||||||
QPointF lastPosition;
|
QPointF lastPosition;
|
||||||
|
QPointF accumulatorAxis;
|
||||||
QPoint accumulatorV120;
|
QPoint accumulatorV120;
|
||||||
|
|
||||||
void sendLeave(quint32 serial);
|
void sendLeave(quint32 serial);
|
||||||
|
|
Loading…
Reference in a new issue