6#include <QSocketNotifier>
9#include <QGuiApplication>
11#include <QLoggingCategory>
12#include <qpa/qwindowsysteminterface.h>
14#include <qplatformdefs.h>
15#include <private/qcore_unix_p.h>
16#include <private/qhighdpiscaling_p.h>
21#include <dev/evdev/input.h>
24#include <linux/input.h>
27#define TEST_BIT(array, bit) (array[bit/8] & (1<<(bit%8)))
37 qCDebug(qLcEvdevMouse) <<
"create mouse handler for" <<
device << specification;
39 bool compression =
true;
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)
59 ::ioctl(
fd, EVIOCGRAB, grab);
67QEvdevMouseHandler::QEvdevMouseHandler(
const QString &
device,
int fd,
bool abs,
bool compression,
int jitterLimit)
68 : m_device(
device), m_fd(
fd), m_abs(abs), m_compression(compression)
72 m_jitterLimitSquared = jitterLimit * jitterLimit;
80 m_abs = getHardwareMaximum();
82 detectHiResWheelSupport();
96void QEvdevMouseHandler::detectHiResWheelSupport()
98#if defined(REL_WHEEL_HI_RES) || defined(REL_HWHEEL_HI_RES)
102 unsigned char relFeatures[(REL_MAX / 8) + 1]{};
103 if (ioctl(m_fd, EVIOCGBIT(EV_REL,
sizeof (relFeatures)), relFeatures) == -1)
106#if defined(REL_WHEEL_HI_RES)
107 m_hiResWheel =
TEST_BIT(relFeatures, REL_WHEEL_HI_RES);
109#if defined(REL_HWHEEL_HI_RES)
110 m_hiResHWheel =
TEST_BIT(relFeatures, REL_HWHEEL_HI_RES);
117bool QEvdevMouseHandler::getHardwareMaximum()
119 unsigned char absFeatures[(ABS_MAX / 8) + 1];
120 memset(absFeatures,
'\0',
sizeof (absFeatures));
123 if (ioctl(m_fd, EVIOCGBIT(EV_ABS,
sizeof (absFeatures)), absFeatures) == -1)
130 struct input_absinfo absInfo;
131 if (ioctl(m_fd, EVIOCGABS(ABS_X), &absInfo) == -1)
134 m_hardwareWidth = absInfo.maximum - absInfo.minimum;
136 if (ioctl(m_fd, EVIOCGABS(ABS_Y), &absInfo) == -1)
139 m_hardwareHeight = absInfo.maximum - absInfo.minimum;
143 m_hardwareScalerX =
static_cast<qreal>(m_hardwareWidth) / (
g.right() -
g.left());
144 m_hardwareScalerY =
static_cast<qreal>(m_hardwareHeight) / (
g.bottom() -
g.top());
146 qCDebug(qLcEvdevMouse) <<
"Absolute pointing device"
147 <<
"hardware max x" << m_hardwareWidth
148 <<
"hardware max y" << m_hardwareHeight
149 <<
"hardware scalers x" << m_hardwareScalerX <<
'y' << m_hardwareScalerY;
154void QEvdevMouseHandler::sendMouseEvent()
164 x = m_x / m_hardwareScalerX;
165 y = m_y / m_hardwareScalerY;
170 m_prevInvalid =
false;
184 struct ::input_event
buffer[32];
186 bool posChanged =
false, btnChanged =
false;
187 bool pendingMouseEvent =
false;
192 qWarning(
"evdevmouse: Got EOF from the input device");
195 if (errno != EINTR && errno != EAGAIN) {
196 qErrnoWarning(errno,
"evdevmouse: Could not read from input device");
199 if (errno == ENODEV) {
209 if (
n %
sizeof(
buffer[0]) == 0)
216 for (
int i = 0;
i <
n; ++
i) {
218 if (
data->type == EV_ABS) {
220 if (
data->code == ABS_X && m_x !=
data->value) {
223 }
else if (
data->code == ABS_Y && m_y !=
data->value) {
227 }
else if (
data->type == EV_REL) {
229 if (
data->code == REL_X) {
232 }
else if (
data->code == REL_Y) {
235 }
else if (!m_hiResWheel &&
data->code == REL_WHEEL) {
239#ifdef REL_WHEEL_HI_RES
240 }
else if (
data->code == REL_WHEEL_HI_RES) {
244 }
else if (!m_hiResHWheel &&
data->code == REL_HWHEEL) {
248#ifdef REL_HWHEEL_HI_RES
249 }
else if (
data->code == REL_HWHEEL_HI_RES) {
254 }
else if (
data->type == EV_KEY &&
data->code == BTN_TOUCH) {
257 m_prevInvalid =
true;
258 }
else if (
data->type == EV_KEY &&
data->code >= BTN_LEFT &&
data->code <= BTN_JOYSTICK) {
262 switch (
data->code) {
284 }
else if (
data->type == EV_SYN &&
data->code == SYN_REPORT) {
286 btnChanged = posChanged =
false;
288 pendingMouseEvent =
false;
289 }
else if (posChanged) {
293 pendingMouseEvent =
true;
298 }
else if (
data->type == EV_MSC &&
data->code == MSC_SCAN) {
303 if (m_compression && pendingMouseEvent) {
304 int distanceSquared = (m_x - m_prevx)*(m_x - m_prevx) + (m_y - m_prevy)*(m_y - m_prevy);
305 if (distanceSquared > m_jitterLimitSquared)
312#include "moc_qevdevmousehandler_p.cpp"
IOBluetoothDevice * device
void handleMouseEvent(int x, int y, bool abs, Qt::MouseButtons buttons, Qt::MouseButton button, QEvent::Type type)
void handleWheelEvent(QPoint delta)
QScreen * primaryScreen
the primary (or default) screen of the application.
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Q_WEAK_OVERLOAD void setObjectName(const QString &name)
Sets the object's name to name.
\inmodule QtCore\reentrant
constexpr void setY(int y) noexcept
Sets the y coordinate of this point to the given y coordinate.
constexpr void setX(int x) noexcept
Sets the x coordinate of this point to the given x coordinate.
\inmodule QtCore\reentrant
The QScreen class is used to query screen properties. \inmodule QtGui.
QRect virtualGeometry
the pixel geometry of the virtual desktop to which this screen belongs
void activated(QSocketDescriptor socket, QSocketNotifier::Type activationEvent, QPrivateSignal)
Q_CORE_EXPORT QList< QStringView > split(QStringView sep, Qt::SplitBehavior behavior=Qt::KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Splits the view into substring views wherever sep occurs, and returns the list of those string views.
\macro QT_RESTRICTED_CAST_FROM_ASCII
void qErrnoWarning(const char *msg,...)
T toNativePixels(const T &value, const C *context)
Combined button and popup list for selecting options.
static int qt_safe_open(const char *pathname, int flags, mode_t mode=0777)
static int qt_safe_close(int fd)
#define TEST_BIT(array, bit)
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
Qt::MouseButtons m_buttons
GLint GLint GLint GLint GLint x
[0]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
#define qPrintable(string)