35std::unique_ptr<QEvdevMouseHandler>
QEvdevMouseHandler::create(
const QString &device,
const QString &specification)
37 qCDebug(qLcEvdevMouse) <<
"create mouse handler for" << device << specification;
39 bool compression =
true;
44 const auto args = QStringView{specification}.split(u':');
45 for (
const auto &arg : args) {
46 if (arg ==
"nocompress"_L1)
48 else if (arg.startsWith(
"dejitter="_L1))
49 jitterLimit = arg.mid(9).toInt();
50 else if (arg.startsWith(
"grab="_L1))
51 grab = arg.mid(5).toInt();
52 else if (arg ==
"abs"_L1)
57 fd = qt_safe_open(device.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0);
59 ::ioctl(fd, EVIOCGRAB, grab);
60 return std::unique_ptr<QEvdevMouseHandler>(
new QEvdevMouseHandler(device, fd, abs, compression, jitterLimit));
62 qErrnoWarning(errno,
"Cannot open mouse input device %s", qPrintable(device));
68 : m_device(device), m_fd(fd), m_abs(abs), m_compression(compression)
103 if (ioctl(m_fd, EVIOCGBIT(EV_REL,
sizeof (relFeatures)), relFeatures) == -1)
172 emit handleMouseEvent(x, y, m_abs, m_buttons, Qt::NoButton, m_eventType);
174 emit handleMouseEvent(x, y, m_abs, m_buttons, m_button, m_eventType);
182 struct ::input_event buffer[32];
184 bool posChanged =
false, btnChanged =
false;
185 bool pendingMouseEvent =
false;
187 int result = QT_READ(m_fd,
reinterpret_cast<
char *>(buffer) + n,
sizeof(buffer) - n);
190 qWarning(
"evdevmouse: Got EOF from the input device");
192 }
else if (result < 0) {
193 if (errno != EINTR && errno != EAGAIN) {
194 qErrnoWarning(errno,
"evdevmouse: Could not read from input device");
197 if (errno == ENODEV) {
207 if (n %
sizeof(buffer[0]) == 0)
212 n /=
sizeof(buffer[0]);
214 for (
int i = 0; i < n; ++i) {
215 struct ::input_event *data = &buffer[i];
216 if (data->type ==
EV_ABS) {
218 if (data->code ==
ABS_X && m_x != data->value) {
221 }
else if (data->code ==
ABS_Y && m_y != data->value) {
225 }
else if (data->type == EV_REL) {
227 if (data->code == REL_X) {
230 }
else if (data->code == REL_Y) {
233 }
else if (!m_hiResWheel && data->code == REL_WHEEL) {
235 delta.setY(120 * data->value);
236 emit handleWheelEvent(delta);
237#ifdef REL_WHEEL_HI_RES
238 }
else if (data->code == REL_WHEEL_HI_RES) {
239 delta.setY(data->value);
240 emit handleWheelEvent(delta);
242 }
else if (!m_hiResHWheel && data->code == REL_HWHEEL) {
244 delta.setX(-120 * data->value);
245 emit handleWheelEvent(delta);
246#ifdef REL_HWHEEL_HI_RES
247 }
else if (data->code == REL_HWHEEL_HI_RES) {
248 delta.setX(-data->value);
249 emit handleWheelEvent(delta);
255 m_prevInvalid =
true;
256 }
else if (data->type ==
EV_KEY && data->code >= BTN_LEFT && data->code <= BTN_JOYSTICK) {
257 Qt::MouseButton button = Qt::NoButton;
260 switch (data->code) {
261 case 0x110: button = Qt::LeftButton;
break;
262 case 0x111: button = Qt::RightButton;
break;
263 case 0x112: button = Qt::MiddleButton;
break;
264 case 0x113: button = Qt::ExtraButton1;
break;
265 case 0x114: button = Qt::ExtraButton2;
break;
266 case 0x115: button = Qt::ExtraButton3;
break;
267 case 0x116: button = Qt::ExtraButton4;
break;
268 case 0x117: button = Qt::ExtraButton5;
break;
269 case 0x118: button = Qt::ExtraButton6;
break;
270 case 0x119: button = Qt::ExtraButton7;
break;
271 case 0x11a: button = Qt::ExtraButton8;
break;
272 case 0x11b: button = Qt::ExtraButton9;
break;
273 case 0x11c: button = Qt::ExtraButton10;
break;
274 case 0x11d: button = Qt::ExtraButton11;
break;
275 case 0x11e: button = Qt::ExtraButton12;
break;
276 case 0x11f: button = Qt::ExtraButton13;
break;
278 m_buttons.setFlag(button, data->value);
280 m_eventType = data->value == 0 ? QEvent::MouseButtonRelease : QEvent::MouseButtonPress;
284 btnChanged = posChanged =
false;
286 pendingMouseEvent =
false;
287 }
else if (posChanged) {
288 m_eventType = QEvent::MouseMove;
291 pendingMouseEvent =
true;
296 }
else if (data->type == EV_MSC && data->code == MSC_SCAN) {
301 if (m_compression && pendingMouseEvent) {
302 int distanceSquared = (m_x - m_prevx)*(m_x - m_prevx) + (m_y - m_prevy)*(m_y - m_prevy);
303 if (distanceSquared > m_jitterLimitSquared)