QTabBar: Improve scrolling with high resolution mouse wheels
The current behavior for handling the angle delta of a wheel event changes index the instant there is a change in angle delta. This works fine for mouse wheels that send events with 120 angle delta units and there is also already behavior defined for devices with pixel deltas, but there is nothing good for handling events from high resolution mouse wheels that don't have pixel deltas. This patch makes it so that the current index doesn't change until the accumulated angle delta for the X or Y axis reaches 120. [ChangeLog][QtWidgets][QTabBar] Scrolling with a high resolution mouse wheel changes the current index at a rate more like a normal mouse wheel. Task-number: QTBUG-97844 Pick-to: 6.3 Change-Id: I2e7fd88984a253f6ef8a0008deb7233e4cb4d84a Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
This commit is contained in:
parent
9ac323f7cd
commit
f0371487ce
@ -1718,6 +1718,9 @@ bool QTabBar::event(QEvent *event)
|
|||||||
update(d->hoverRect);
|
update(d->hoverRect);
|
||||||
d->hoverIndex = -1;
|
d->hoverIndex = -1;
|
||||||
d->hoverRect = QRect();
|
d->hoverRect = QRect();
|
||||||
|
#if QT_CONFIG(wheelevent)
|
||||||
|
d->accumulatedAngleDelta = QPoint();
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#if QT_CONFIG(tooltip)
|
#if QT_CONFIG(tooltip)
|
||||||
@ -2421,8 +2424,17 @@ void QTabBar::wheelEvent(QWheelEvent *event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const int delta = wheelVertical ? event->angleDelta().y() : event->angleDelta().x();
|
d->accumulatedAngleDelta += event->angleDelta();
|
||||||
const int offset = delta > 0 ? -1 : 1;
|
const int xSteps = d->accumulatedAngleDelta.x() / QWheelEvent::DefaultDeltasPerStep;
|
||||||
|
const int ySteps = d->accumulatedAngleDelta.y() / QWheelEvent::DefaultDeltasPerStep;
|
||||||
|
int offset = 0;
|
||||||
|
if (xSteps > 0 || ySteps > 0) {
|
||||||
|
offset = -1;
|
||||||
|
d->accumulatedAngleDelta = QPoint();
|
||||||
|
} else if (xSteps < 0 || ySteps < 0) {
|
||||||
|
offset = 1;
|
||||||
|
d->accumulatedAngleDelta = QPoint();
|
||||||
|
}
|
||||||
const int oldCurrentIndex = d->currentIndex;
|
const int oldCurrentIndex = d->currentIndex;
|
||||||
d->setCurrentNextEnabledIndex(offset);
|
d->setCurrentNextEnabledIndex(offset);
|
||||||
if (oldCurrentIndex != d->currentIndex) {
|
if (oldCurrentIndex != d->currentIndex) {
|
||||||
|
@ -102,6 +102,9 @@ public:
|
|||||||
QRect hoverRect;
|
QRect hoverRect;
|
||||||
QPoint dragStartPosition;
|
QPoint dragStartPosition;
|
||||||
QPoint mousePosition = {-1, -1};
|
QPoint mousePosition = {-1, -1};
|
||||||
|
#if QT_CONFIG(wheelevent)
|
||||||
|
QPoint accumulatedAngleDelta;
|
||||||
|
#endif
|
||||||
QSize iconSize;
|
QSize iconSize;
|
||||||
QToolButton* rightB = nullptr; // right or bottom
|
QToolButton* rightB = nullptr; // right or bottom
|
||||||
QToolButton* leftB = nullptr; // left or top
|
QToolButton* leftB = nullptr; // left or top
|
||||||
|
@ -103,6 +103,8 @@ private slots:
|
|||||||
void mouseWheel();
|
void mouseWheel();
|
||||||
void kineticWheel_data();
|
void kineticWheel_data();
|
||||||
void kineticWheel();
|
void kineticWheel();
|
||||||
|
void highResolutionWheel_data();
|
||||||
|
void highResolutionWheel();
|
||||||
|
|
||||||
void scrollButtons_data();
|
void scrollButtons_data();
|
||||||
void scrollButtons();
|
void scrollButtons();
|
||||||
@ -1106,6 +1108,49 @@ void tst_QTabBar::kineticWheel()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_QTabBar::highResolutionWheel_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<int>("angleDelta");
|
||||||
|
// Smallest angleDelta for a Logitech MX Master 3 with Linux/X11/Libinput
|
||||||
|
QTest::addRow("increment index") << -16;
|
||||||
|
QTest::addRow("decrement index") << 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QTabBar::highResolutionWheel()
|
||||||
|
{
|
||||||
|
TabBar tabbar;
|
||||||
|
TabBarScrollingProxyStyle proxyStyle;
|
||||||
|
tabbar.setStyle(&proxyStyle);
|
||||||
|
|
||||||
|
tabbar.addTab("tab1");
|
||||||
|
tabbar.addTab("tab2");
|
||||||
|
QFETCH(int, angleDelta);
|
||||||
|
// Negative values increment, positive values decrement
|
||||||
|
int startIndex = angleDelta < 0 ? 0 : 1;
|
||||||
|
tabbar.setCurrentIndex(startIndex);
|
||||||
|
|
||||||
|
const auto systemId = QPointingDevice::primaryPointingDevice()->systemId() + 1;
|
||||||
|
QPointingDevice hiResWheel(
|
||||||
|
"test high resolution wheel", systemId, QInputDevice::DeviceType::Mouse,
|
||||||
|
QPointingDevice::PointerType::Generic,
|
||||||
|
QInputDevice::Capability::Position | QInputDevice::Capability::Scroll, 1, 3);
|
||||||
|
|
||||||
|
const QPoint wheelPoint = tabbar.rect().bottomRight();
|
||||||
|
QWheelEvent event(wheelPoint, tabbar.mapToGlobal(wheelPoint), QPoint(),
|
||||||
|
QPoint(angleDelta, angleDelta), Qt::NoButton, Qt::NoModifier,
|
||||||
|
Qt::NoScrollPhase, false, Qt::MouseEventSynthesizedByApplication,
|
||||||
|
&hiResWheel);
|
||||||
|
|
||||||
|
proxyStyle.scrolling = true;
|
||||||
|
for (int accumulated = 0; accumulated < QWheelEvent::DefaultDeltasPerStep;
|
||||||
|
accumulated += qAbs(angleDelta)) {
|
||||||
|
// verify that nothing has changed until the threshold has been reached
|
||||||
|
QVERIFY(tabbar.currentIndex() == startIndex);
|
||||||
|
QVERIFY(QApplication::sendEvent(&tabbar, &event));
|
||||||
|
}
|
||||||
|
QVERIFY(tabbar.currentIndex() != startIndex);
|
||||||
|
}
|
||||||
|
|
||||||
#endif // QT_CONFIG(wheelevent)
|
#endif // QT_CONFIG(wheelevent)
|
||||||
|
|
||||||
void tst_QTabBar::scrollButtons_data()
|
void tst_QTabBar::scrollButtons_data()
|
||||||
|
Loading…
Reference in New Issue
Block a user