9#include <QSocketNotifier>
10#include <QGuiApplication>
11#include <QLoggingCategory>
12#include <QtCore/private/qcore_unix_p.h>
13#include <QtGui/qpointingdevice.h>
14#include <QtGui/private/qhighdpiscaling_p.h>
15#include <QtGui/private/qguiapplication_p.h>
16#include <QtGui/private/qpointingdevice_p.h>
21#include <dev/evdev/input.h>
23#include <linux/input.h>
26#ifndef input_event_sec
27#define input_event_sec time.tv_sec
30#ifndef input_event_usec
31#define input_event_usec time.tv_usec
52#ifndef ABS_MT_TOUCH_MAJOR
53#define ABS_MT_TOUCH_MAJOR 0x30
55#ifndef ABS_MT_POSITION_X
56#define ABS_MT_POSITION_X 0x35
58#ifndef ABS_MT_POSITION_Y
59#define ABS_MT_POSITION_Y 0x36
62#define ABS_MT_SLOT 0x2f
65#define ABS_CNT (ABS_MAX+1)
67#ifndef ABS_MT_TRACKING_ID
68#define ABS_MT_TRACKING_ID 0x39
70#ifndef ABS_MT_PRESSURE
71#define ABS_MT_PRESSURE 0x3a
74#define SYN_MT_REPORT 2
145 m_timeStamp(0), m_lastTimeStamp(0),
146 hw_range_x_min(0), hw_range_x_max(0),
147 hw_range_y_min(0), hw_range_y_max(0),
148 hw_pressure_min(0), hw_pressure_max(0),
150 m_filtered(
false), m_prediction(0)
162#define LONG_BITS (sizeof(long) << 3)
163#define NUM_LONGS(bits) (((bits) + LONG_BITS - 1) / LONG_BITS)
181 int rotationAngle = 0;
182 bool invertx =
false;
183 bool inverty =
false;
185 if (
args.
at(
i).startsWith(
"rotate"_L1)) {
194 rotationAngle = argValue;
199 }
else if (
args.
at(
i) ==
"invertx"_L1) {
201 }
else if (
args.
at(
i) ==
"inverty"_L1) {
208 m_fd =
QT_OPEN(
device.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0);
219 m_mtdev =
static_cast<mtdev *
>(calloc(1,
sizeof(mtdev)));
220 int mtdeverr = mtdev_open(m_mtdev, m_fd);
222 qWarning(
"evdevtouch: mtdev_open failed: %d", mtdeverr);
232 const char *mtdevStr =
"(mtdev)";
235 const char *mtdevStr =
"";
237 if (ioctl(m_fd, EVIOCGBIT(EV_ABS,
sizeof(absbits)), absbits) >= 0) {
245 "evdevtouch: %ls: Protocol type %c %s (%s), filtered=%s",
247 d->
m_typeB ?
'B' :
'A', mtdevStr,
253 input_absinfo absInfo;
254 memset(&absInfo, 0,
sizeof(input_absinfo));
255 bool has_x_range =
false, has_y_range =
false;
259 absInfo.minimum, absInfo.maximum);
267 absInfo.minimum, absInfo.maximum);
273 if (!has_x_range || !has_y_range)
276 if (ioctl(m_fd, EVIOCGABS(ABS_PRESSURE), &absInfo) >= 0) {
278 absInfo.minimum, absInfo.maximum);
279 if (absInfo.maximum > absInfo.minimum) {
286 if (ioctl(m_fd, EVIOCGNAME(
sizeof(
name) - 1),
name) >= 0) {
292 if (d->
hw_name ==
"ti-tsc"_L1) {
301 qCDebug(qLcEvdevTouch,
"evdevtouch: found ti-tsc, overriding: min X: %d max X: %d min Y: %d max Y: %d",
305 bool grabSuccess = !ioctl(m_fd, EVIOCGRAB, (
void *) 1);
307 ioctl(m_fd, EVIOCGRAB, (
void *) 0);
309 qWarning(
"evdevtouch: The device is grabbed by another process. No events will be read.");
324 qCDebug(qLcEvdevTouch,
"evdevtouch: Mapping device %ls to screen %ls",
328 registerPointingDevice();
335 mtdev_close(m_mtdev);
345 unregisterPointingDevice();
366 events = mtdev_get(m_mtdev, m_fd,
buffer,
sizeof(
buffer) /
sizeof(::input_event));
370 }
while (events == -1 && errno == EINTR);
377 for (
int i = 0;
i < events; ++
i)
389 if (
n %
sizeof(::input_event) == 0)
393 n /=
sizeof(::input_event);
395 for (
int i = 0;
i <
n; ++
i)
402 qWarning(
"evdevtouch: Got EOF from input device");
404 }
else if (events < 0) {
405 if (errno != EINTR && errno != EAGAIN) {
406 qErrnoWarning(
"evdevtouch: Could not read from input device");
407 if (errno == ENODEV) {
414 unregisterPointingDevice();
421void QEvdevTouchScreenHandler::registerPointingDevice()
472void QEvdevTouchScreenHandler::unregisterPointingDevice()
491 *combinedStates |= tp.
state;
512 if (
data->type == EV_ABS) {
544 if (
data->value == 0)
550 qCDebug(qLcEvents,
"EV_ABS code 0x%x: pressure %d; bounding to [%d,%d]",
560 if (
data->code == BTN_TOUCH &&
data->value == 0)
573 }
else if (
data->type == EV_SYN &&
data->code == SYN_REPORT) {
579 std::unique_lock<QMutex> locker;
581 locker = std::unique_lock<QMutex>{
m_mutex};
589 QEventPoint::States combinedStates;
590 bool hasPressure =
false;
595 if (!contact.
state) {
609 contact.
state = (prev.
x == contact.
x && prev.
y == contact.
y)
649 if (!contact.
state) {
681 int minDist = -1,
id = -1;
685 int dx =
x - contact.
x;
686 int dy =
y - contact.
y;
687 int dist = dx * dx + dy * dy;
688 if (minDist == -1 ||
dist < minDist) {
704 int bestDist = -1, bestId = 0;
708 if (
id >= 0 && (bestDist == -1 ||
dist < bestDist)) {
715 bestMatch->trackingId = bestId;
716 newContacts.insert(bestId, *bestMatch);
717 candidates.
remove(bestId);
725 it->trackingId = ++maxId;
778 for (
int i = 0;
i < pointCount; ++
i) {
800 qCDebug(qLcEvents) <<
"reporting" << tp;
805 emit q->touchPointsUpdated();
812 , m_touchUpdatePending(
false)
843 return m_touchDeviceRegistered;
846void QEvdevTouchScreenHandlerThread::notifyTouchDeviceRegistered()
848 m_touchDeviceRegistered =
true;
855 if (
window != m_filterWindow) {
862 if (m_filterWindow) {
863 m_touchUpdatePending =
true;
864 m_filterWindow->requestUpdate();
871 m_touchUpdatePending =
false;
872 filterAndSendTouchPoints();
877void QEvdevTouchScreenHandlerThread::filterAndSendTouchPoints()
891 double touchDelta =
time - lastTime;
892 if (m_touchRate < 0 || touchDelta > vsyncDelta) {
906 const double ratio = 0.9;
907 m_touchRate = sqrt(m_touchRate * m_touchRate * ratio + touchDelta * touchDelta * (1.0 - ratio));
918 FilteredTouchPoint
f;
922 for (
int j=0;
j<lastPoints.
size(); ++
j) {
923 if (lastPoints.
at(
j).id == tp.
id) {
924 ltp = lastPoints.
at(
j);
930 if (lastTime != 0 && ltp.
id >= 0)
933 f = m_filteredPoints.
take(tp.
id);
934 f.x.update(
pos.x(), velocity.
x(), vsyncDelta);
935 f.y.update(
pos.y(), velocity.
y(), vsyncDelta);
938 f.x.initialize(
pos.x(), velocity.
x());
939 f.y.initialize(
pos.y(), velocity.
y());
948 qreal filteredNormalizedX =
f.x.position() +
f.x.velocity() * m_handler->d->
m_prediction / 1000.0;
949 qreal filteredNormalizedY =
f.y.position() +
f.y.velocity() * m_handler->d->
m_prediction / 1000.0;
953 qBound<qreal>(0, filteredNormalizedY, 1));
966 filteredPoints[tp.
id] =
f;
970 const FilteredTouchPoint &
f =
it.value();
977 m_filteredPoints = filteredPoints;
987#include "moc_qevdevtouchhandler_p.cpp"
IOBluetoothDevice * device
static QCoreApplication * instance() noexcept
Returns a pointer to the application's QCoreApplication (or QGuiApplication/QApplication) instance.
QEvdevTouchScreenHandler * q
int findClosestContact(const QHash< int, Contact > &contacts, int x, int y, int *dist)
QHash< int, Contact > m_lastContacts
QEvdevTouchScreenData(QEvdevTouchScreenHandler *q_ptr, const QStringList &args)
QList< QWindowSystemInterface::TouchPoint > m_lastTouchPoints
bool m_forceToActiveWindow
QHash< int, Contact > m_contacts
void loadMultiScreenMappings()
QRect screenGeometry() const
void addTouchPoint(const Contact &contact, QEventPoint::States *combinedStates)
QPointer< QScreen > m_screen
QList< QWindowSystemInterface::TouchPoint > m_touchPoints
void processInputEvent(input_event *data)
bool eventFilter(QObject *object, QEvent *event) override
QEvdevTouchScreenHandlerThread(const QString &device, const QString &spec, QObject *parent=nullptr)
void scheduleTouchPointUpdate()
bool isPointingDeviceRegistered() const
~QEvdevTouchScreenHandlerThread()
void touchDeviceRegistered()
QPointingDevice * touchDevice() const
void touchPointsUpdated()
~QEvdevTouchScreenHandler()
friend class QEvdevTouchScreenData
QEvdevTouchScreenHandler(const QString &device, const QString &spec=QString(), QObject *parent=nullptr)
State
Specifies the state of this event point.
QScreen * primaryScreen
the primary (or default) screen of the application.
static QWindow * focusWindow()
Returns the QWindow that receives events tied to focus, such as key events.
static QList< QScreen * > screens()
Returns a list of all the screens associated with the windowing system the application is connected t...
bool remove(const Key &key)
Removes the item that has the key from the hash.
const_iterator constEnd() const noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the ...
const_iterator constBegin() const noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item in the hash.
T take(const Key &key)
Removes the item with the key from the hash and returns the value associated with it.
bool contains(const Key &key) const noexcept
Returns true if the hash contains an item with the key; otherwise returns false.
bool isEmpty() const noexcept
Returns true if the hash contains no items; otherwise returns false.
qsizetype size() const noexcept
bool isEmpty() const noexcept
const_reference at(qsizetype i) const noexcept
void append(parameter_type t)
void unlock() noexcept
Unlocks the mutex.
void lock() noexcept
Locks the mutex.
void installEventFilter(QObject *filterObj)
Installs an event filter filterObj on this object.
void moveToThread(QThread *thread)
Changes the thread affinity for this object and its children.
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
void removeEventFilter(QObject *obj)
Removes an event filter object obj from this object.
QThread * thread() const
Returns the thread in which the object lives.
Q_WEAK_OVERLOAD void setObjectName(const QString &name)
Sets the object's name to name.
void deleteLater()
\threadsafe
static QOutputMapping * get()
\inmodule QtCore\reentrant
constexpr qreal x() const noexcept
Returns the x coordinate of this point.
constexpr qreal y() const noexcept
Returns the y coordinate of this point.
\inmodule QtCore\reentrant
static QPointingDevicePrivate * get(QPointingDevice *q)
The QPointingDevice class describes a device from which mouse, touch or tablet events originate.
\inmodule QtCore\reentrant
constexpr void moveCenter(const QPointF &p) noexcept
Moves the rectangle, leaving the center point at the given position.
constexpr qreal height() const noexcept
Returns the height of the rectangle.
constexpr qreal width() const noexcept
Returns the width of the rectangle.
\inmodule QtCore\reentrant
constexpr int height() const noexcept
Returns the height of the rectangle.
constexpr bool isNull() const noexcept
Returns true if the rectangle is a null rectangle, otherwise returns false.
constexpr int top() const noexcept
Returns the y-coordinate of the rectangle's top edge.
constexpr int left() const noexcept
Returns the x-coordinate of the rectangle's left edge.
constexpr int x() const noexcept
Returns the x-coordinate of the rectangle's left edge.
constexpr int width() const noexcept
Returns the width of the rectangle.
constexpr int y() const noexcept
Returns the y-coordinate of the rectangle's top edge.
The QScreen class is used to query screen properties. \inmodule QtGui.
QRect geometry
the screen's geometry in pixels
qreal refreshRate
the approximate vertical refresh rate of the screen in Hz
iterator insert(const T &value)
void activated(QSocketDescriptor socket, QSocketNotifier::Type activationEvent, QPrivateSignal)
\macro QT_RESTRICTED_CAST_FROM_ASCII
QStringList split(const QString &sep, Qt::SplitBehavior behavior=Qt::KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Splits the string into substrings wherever sep occurs, and returns the list of those strings.
static QString fromLocal8Bit(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
uint toUInt(bool *ok=nullptr, int base=10) const
Returns the string converted to an {unsigned int} using base base, which is 10 by default and must be...
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
The QVector2D class represents a vector or vertex in 2D space.
static bool handleTouchEvent(QWindow *window, const QPointingDevice *device, const QList< struct TouchPoint > &points, Qt::KeyboardModifiers mods=Qt::NoModifier)
static void registerInputDevice(const QInputDevice *device)
QSet< QString >::iterator it
void qErrnoWarning(const char *msg,...)
T toNativePixels(const T &value, const C *context)
T toNativeWindowGeometry(const T &value, const C *context)
Combined button and popup list for selecting options.
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage return DBusPendingCall * pending
#define ABS_MT_POSITION_X
static bool testBit(long bit, const long *field)
#define ABS_MT_POSITION_Y
#define ABS_MT_POSITION_X
static bool testBit(long bit, const long *array)
#define ABS_MT_TRACKING_ID
#define ABS_MT_TOUCH_MAJOR
#define ABS_MT_POSITION_Y
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
constexpr const T & qBound(const T &min, const T &val, const T &max)
GLint GLint GLint GLint GLint x
[0]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLfixed GLfixed GLint GLint GLfixed points
GLdouble GLdouble GLdouble GLdouble q
GLenum GLenum GLenum GLenum mapping
GLenum GLenum GLenum input
#define qUtf16Printable(string)
#define QStringLiteral(str)
#define QT_CONFIG(feature)
if(qFloatDistance(a, b)<(1<< 7))
[0]
std::uniform_real_distribution dist(1, 2.5)
[2]
connect(quitButton, &QPushButton::clicked, &app, &QCoreApplication::quit, Qt::QueuedConnection)
QList< QPointF > rawPositions
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent