Implement todos in touchscreen generic plug-in.
The patch implements periodic clearing of the point states when no activity occurs (i.e. no ev_syn is coming at all, meaning that most probably all the fingers are already up) and also moves the entire functionality into a separate thread even when used as a plug-in. Change-Id: Ib1daa738085b61af9b07eb8a284416e5a3fcabe8 Reviewed-on: http://codereview.qt.nokia.com/1744 Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com> Reviewed-by: Jørgen Lind <jorgen.lind@nokia.com>
This commit is contained in:
parent
9581c90395
commit
ba1b6f16ae
@ -14,9 +14,9 @@ LinuxTouchScreen:/dev/input/eventN to explicitly set the device file
|
||||
name.
|
||||
|
||||
By default the surface of the touch device is mapped to the entire
|
||||
screen. If this is not desired, define FORCE_TO_ACTIVE_WINDOW in
|
||||
qtoucheventsenderqpa.cpp. This will map the touch surface to the
|
||||
active window instead.
|
||||
screen. If this is not desired, pass force_window in the plugin
|
||||
specification. This will cause mapping the touch surface to the active
|
||||
window instead.
|
||||
|
||||
Only touch events are generated (via
|
||||
QWindowSystemInterface::handleTouchEvent), mouse events are not. This
|
||||
|
@ -67,8 +67,8 @@ QObject* QTouchScreenPlugin::create(const QString &key,
|
||||
const QString &spec)
|
||||
{
|
||||
if (!key.compare(QLatin1String("LinuxTouchScreen"), Qt::CaseInsensitive)) {
|
||||
QTouchScreenHandler *h = new QTouchScreenHandler(spec);
|
||||
h->addObserver(new QTouchEventSenderQPA);
|
||||
QTouchScreenObserver *obs = new QTouchEventSenderQPA(spec);
|
||||
QTouchScreenHandlerThread *h = new QTouchScreenHandlerThread(spec, obs);
|
||||
return h;
|
||||
}
|
||||
|
||||
|
@ -47,7 +47,11 @@
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
//#define POINT_DEBUG
|
||||
//#define FORCE_TO_ACTIVE_WINDOW
|
||||
|
||||
QTouchEventSenderQPA::QTouchEventSenderQPA(const QString &spec)
|
||||
{
|
||||
m_forceToActiveWindow = spec.split(QLatin1Char(':')).contains(QLatin1String("force_window"));
|
||||
}
|
||||
|
||||
void QTouchEventSenderQPA::touch_configure(int x_min, int x_max, int y_min, int y_max)
|
||||
{
|
||||
@ -60,21 +64,18 @@ void QTouchEventSenderQPA::touch_configure(int x_min, int x_max, int y_min, int
|
||||
void QTouchEventSenderQPA::touch_point(QEvent::Type state,
|
||||
const QList<QWindowSystemInterface::TouchPoint> &points)
|
||||
{
|
||||
#ifdef FORCE_TO_ACTIVE_WINDOW
|
||||
QWidget *win = QApplication::activeWindow(); // ### migrate to QWindow later on
|
||||
if (!win) {
|
||||
#ifdef POINT_DEBUG
|
||||
qDebug("sendTouchEvent: No active window");
|
||||
#endif
|
||||
return;
|
||||
QRect winRect;
|
||||
if (m_forceToActiveWindow) {
|
||||
QWidget *win = QApplication::activeWindow(); // ### migrate to QWindow later on
|
||||
if (!win)
|
||||
return;
|
||||
winRect = win->geometry();
|
||||
} else {
|
||||
winRect = QApplication::desktop()->screenGeometry();
|
||||
}
|
||||
const QRect winRect = win->geometry();
|
||||
#else
|
||||
const QRect winRect = QApplication::desktop()->screenGeometry();
|
||||
#endif
|
||||
|
||||
#ifdef POINT_DEBUG
|
||||
qDebug() << points.size() << "points" << winRect << state;
|
||||
qDebug() << "QPA: Mapping" << points.size() << "points to" << winRect << state;
|
||||
#endif
|
||||
|
||||
QList<QWindowSystemInterface::TouchPoint> touchPoints = points;
|
||||
|
@ -51,10 +51,12 @@ QT_BEGIN_NAMESPACE
|
||||
class QTouchEventSenderQPA : public QTouchScreenObserver
|
||||
{
|
||||
public:
|
||||
QTouchEventSenderQPA(const QString &spec = QString());
|
||||
void touch_configure(int x_min, int x_max, int y_min, int y_max);
|
||||
void touch_point(QEvent::Type state, const QList<QWindowSystemInterface::TouchPoint> &points);
|
||||
|
||||
private:
|
||||
bool m_forceToActiveWindow;
|
||||
int hw_range_x_min;
|
||||
int hw_range_x_max;
|
||||
int hw_range_y_min;
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include <QStringList>
|
||||
#include <QSocketNotifier>
|
||||
#include <QtCore/private/qcore_unix_p.h>
|
||||
#include <QTimer>
|
||||
#include <QDebug>
|
||||
|
||||
#include <libudev.h>
|
||||
@ -58,9 +59,9 @@ QT_BEGIN_NAMESPACE
|
||||
class QTouchScreenData
|
||||
{
|
||||
public:
|
||||
QTouchScreenData(QTouchScreenHandler *q_ptr);
|
||||
QTouchScreenData(QTouchScreenHandler *q_ptr, const QStringList &args);
|
||||
|
||||
void handle(input_event *data);
|
||||
void processInputEvent(input_event *data);
|
||||
|
||||
QTouchScreenHandler *q;
|
||||
QEvent::Type m_state;
|
||||
@ -78,6 +79,8 @@ public:
|
||||
QMap<int, Slot> m_slots;
|
||||
QMap<int, QPoint> m_lastReport;
|
||||
int m_currentSlot;
|
||||
QTimer m_clearTimer;
|
||||
bool m_clearTimerEnabled;
|
||||
|
||||
int hw_range_x_min;
|
||||
int hw_range_x_max;
|
||||
@ -88,7 +91,7 @@ public:
|
||||
QList<QTouchScreenObserver *> m_observers;
|
||||
};
|
||||
|
||||
QTouchScreenData::QTouchScreenData(QTouchScreenHandler *q_ptr)
|
||||
QTouchScreenData::QTouchScreenData(QTouchScreenHandler *q_ptr, const QStringList &args)
|
||||
: q(q_ptr),
|
||||
m_state(QEvent::TouchBegin),
|
||||
m_prevState(m_state),
|
||||
@ -96,6 +99,15 @@ QTouchScreenData::QTouchScreenData(QTouchScreenHandler *q_ptr)
|
||||
hw_range_x_min(0), hw_range_x_max(0),
|
||||
hw_range_y_min(0), hw_range_y_max(0)
|
||||
{
|
||||
m_clearTimerEnabled = !args.contains(QLatin1String("no_timeout"));
|
||||
if (m_clearTimerEnabled) {
|
||||
QObject::connect(&m_clearTimer, SIGNAL(timeout()), q, SLOT(onTimeout()));
|
||||
m_clearTimer.setSingleShot(true);
|
||||
m_clearTimer.setInterval(2000); // default timeout is 2 seconds
|
||||
for (int i = 0; i < args.count(); ++i)
|
||||
if (args.at(i).startsWith(QLatin1String("timeout=")))
|
||||
m_clearTimer.setInterval(args.at(i).mid(8).toInt());
|
||||
}
|
||||
}
|
||||
|
||||
QTouchScreenHandler::QTouchScreenHandler(const QString &spec)
|
||||
@ -130,7 +142,7 @@ QTouchScreenHandler::QTouchScreenHandler(const QString &spec)
|
||||
return;
|
||||
}
|
||||
|
||||
d = new QTouchScreenData(this);
|
||||
d = new QTouchScreenData(this, args);
|
||||
|
||||
input_absinfo absInfo;
|
||||
memset(&absInfo, 0, sizeof(input_absinfo));
|
||||
@ -203,12 +215,25 @@ void QTouchScreenHandler::readData()
|
||||
} else if (n > 0) {
|
||||
for (int i = 0; i < n; ++i) {
|
||||
input_event *data = &buffer[i];
|
||||
d->handle(data);
|
||||
d->processInputEvent(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QTouchScreenData::handle(input_event *data)
|
||||
void QTouchScreenHandler::onTimeout()
|
||||
{
|
||||
#ifdef POINT_DEBUG
|
||||
qDebug("TIMEOUT (%d slots)", d->m_slots.count());
|
||||
#endif
|
||||
d->m_slots.clear();
|
||||
if (d->m_state != QEvent::TouchEnd)
|
||||
for (int i = 0; i < d->m_observers.count(); ++i)
|
||||
d->m_observers.at(i)->touch_point(QEvent::TouchEnd,
|
||||
QList<QWindowSystemInterface::TouchPoint>());
|
||||
d->m_state = QEvent::TouchBegin;
|
||||
}
|
||||
|
||||
void QTouchScreenData::processInputEvent(input_event *data)
|
||||
{
|
||||
if (data->type == EV_ABS) {
|
||||
if (data->code == ABS_MT_POSITION_X) {
|
||||
@ -233,6 +258,8 @@ void QTouchScreenData::handle(input_event *data)
|
||||
m_slots[m_currentSlot].state = Qt::TouchPointReleased;
|
||||
}
|
||||
} else if (data->type == EV_SYN && data->code == SYN_REPORT) {
|
||||
if (m_clearTimerEnabled)
|
||||
m_clearTimer.stop();
|
||||
m_touchPoints.clear();
|
||||
QList<int> keys = m_slots.keys();
|
||||
int ignoredSlotCount = 0;
|
||||
@ -270,10 +297,6 @@ void QTouchScreenData::handle(input_event *data)
|
||||
}
|
||||
}
|
||||
|
||||
// ### TODO Add timestamps and remove points that stay unchanged for too long.
|
||||
// The user's finger may fall off the touchscreen, which means there will be
|
||||
// no released event sent ever for that particular point.
|
||||
|
||||
#ifdef POINT_DEBUG
|
||||
qDebug() << m_touchPoints.count() << "touchpoints, event type" << m_state;
|
||||
for (int i = 0; i < m_touchPoints.count(); ++i)
|
||||
@ -294,6 +317,13 @@ void QTouchScreenData::handle(input_event *data)
|
||||
m_state = QEvent::TouchUpdate;
|
||||
else if (m_state == QEvent::TouchEnd)
|
||||
m_state = QEvent::TouchBegin;
|
||||
|
||||
// The user's finger may fall off the touchscreen which in some rare
|
||||
// cases may mean there will be no released event ever received for that
|
||||
// particular point. Use a timer to clear all points when no activity
|
||||
// occurs for a certain period of time.
|
||||
if (m_clearTimerEnabled && m_state != QEvent::TouchBegin)
|
||||
m_clearTimer.start();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,6 +75,7 @@ public:
|
||||
|
||||
private slots:
|
||||
void readData();
|
||||
void onTimeout();
|
||||
|
||||
private:
|
||||
void try_udev(QString *path);
|
||||
|
Loading…
Reference in New Issue
Block a user