Add support for high resolution wheel events from Linux 5.0+

They come in as a different relative axis, and we need to ignore the old
axis to not scroll double.

Change-Id: I808cce95417ec9f8058dee26d0a2694dda27944d
Reviewed-by: Gatis Paeglis <gatis.paeglis@qt.io>
This commit is contained in:
Allan Sandfeld Jensen 2020-02-14 14:20:02 +01:00
parent cc106ce565
commit 13873c6bc6
2 changed files with 36 additions and 2 deletions

View File

@ -113,6 +113,8 @@ QEvdevMouseHandler::QEvdevMouseHandler(const QString &device, int fd, bool abs,
if (m_abs)
m_abs = getHardwareMaximum();
detectHiResWheelSupport();
// socket notifier for events on the mouse device
m_notify = new QSocketNotifier(m_fd, QSocketNotifier::Read, this);
connect(m_notify, &QSocketNotifier::activated,
@ -125,6 +127,25 @@ QEvdevMouseHandler::~QEvdevMouseHandler()
qt_safe_close(m_fd);
}
void QEvdevMouseHandler::detectHiResWheelSupport()
{
#if defined(REL_WHEEL_HI_RES) || defined(REL_HWHEEL_HI_RES)
// Check if we can expect hires events as we will get both
// legacy and hires event and needs to know if we should
// ignore the legacy events.
unsigned char relFeatures[(REL_MAX / 8) + 1]{};
if (ioctl(m_fd, EVIOCGBIT(EV_REL, sizeof (relFeatures)), relFeatures) == -1)
return;
#if defined(REL_WHEEL_HI_RES)
m_hiResWheel = TEST_BIT(relFeatures, REL_WHEEL_HI_RES);
#endif
#if defined(REL_HWHEEL_HI_RES)
m_hiResHWheel = TEST_BIT(relFeatures, REL_HWHEEL_HI_RES);
#endif
#endif
}
// Ask touch screen hardware for information on coordinate maximums
// If any ioctls fail, revert to non abs mode
bool QEvdevMouseHandler::getHardwareMaximum()
@ -243,14 +264,24 @@ void QEvdevMouseHandler::readMouseData()
} else if (data->code == REL_Y) {
m_y += data->value;
posChanged = true;
} else if (data->code == ABS_WHEEL) { // vertical scroll
} else if (!m_hiResWheel && data->code == REL_WHEEL) {
// data->value: positive == up, negative == down
delta.setY(120 * data->value);
emit handleWheelEvent(delta);
} else if (data->code == ABS_THROTTLE) { // horizontal scroll
#ifdef REL_WHEEL_HI_RES
} else if (data->code == REL_WHEEL_HI_RES) {
delta.setY(data->value);
emit handleWheelEvent(delta);
#endif
} else if (!m_hiResHWheel && data->code == REL_HWHEEL) {
// data->value: positive == right, negative == left
delta.setX(-120 * data->value);
emit handleWheelEvent(delta);
#ifdef REL_HWHEEL_HI_RES
} else if (data->code == REL_HWHEEL_HI_RES) {
delta.setX(-data->value);
emit handleWheelEvent(delta);
#endif
}
} else if (data->type == EV_KEY && data->code == BTN_TOUCH) {
// We care about touchpads only, not touchscreens -> don't map to button press.

View File

@ -81,6 +81,7 @@ private:
void sendMouseEvent();
bool getHardwareMaximum();
void detectHiResWheelSupport();
QString m_device;
int m_fd;
@ -89,6 +90,8 @@ private:
int m_prevx = 0, m_prevy = 0;
bool m_abs;
bool m_compression;
bool m_hiResWheel = false;
bool m_hiResHWheel = false;
Qt::MouseButtons m_buttons;
Qt::MouseButton m_button;
QEvent::Type m_eventType;