qt5: initial support for multi-touch input

The initial support reports TouchPointPressed, TouchPointMoved, and
TouchPointReleased for multiple touch points, but is currently only
tested with widgets not leveraging multi-touch events. In other words, I
made sure synthetic mouse events are generated properly when using touch
screens.
This commit is contained in:
Christian Helmuth 2016-08-04 16:51:49 +02:00
parent b0f7717711
commit 7038825522
2 changed files with 78 additions and 7 deletions

View File

@ -13,10 +13,10 @@
/* Genode includes */
#include <base/log.h>
#include <nitpicker_session/client.h>
/* Qt includes */
#include <qpa/qwindowsysteminterface.h>
#include <qpa/qplatformscreen.h>
#include <QGuiApplication>
#include <QDebug>
@ -27,15 +27,70 @@ QT_BEGIN_NAMESPACE
static const bool qnpw_verbose = false/*true*/;
QTouchDevice * QNitpickerPlatformWindow::_init_touch_device()
{
QVector<QWindowSystemInterface::TouchPoint>::iterator i = _touch_points.begin();
for (unsigned n = 0; i != _touch_points.end(); ++i, ++n) {
i->id = n;
i->state = Qt::TouchPointReleased;
}
QTouchDevice *dev = new QTouchDevice;
dev->setName("Genode multi-touch device");
dev->setType(QTouchDevice::TouchScreen);
dev->setCapabilities(QTouchDevice::Position);
QWindowSystemInterface::registerTouchDevice(dev);
return dev;
}
void QNitpickerPlatformWindow::_process_touch_events(QList<Input::Event> const &events)
{
if (events.empty()) return;
QList<QWindowSystemInterface::TouchPoint> touch_points;
for (QList<Input::Event>::const_iterator i = events.begin(); i != events.end(); ++i) {
/*
* Coordinates must be normalized to positions of the platform window.
* We lack information about the value ranges (min and max) of touch
* coordinates to normalize ourselves.
*/
QPointF const pos((qreal)i->ax(), (qreal)i->ay() );
QWindowSystemInterface::TouchPoint &otp = _touch_points[i->code()];
QWindowSystemInterface::TouchPoint tp;
tp.id = i->code();
tp.area = QRectF(QPointF(0, 0), QSize(1, 1));
/* report 1x1 rectangular area centered at screen coordinates */
tp.area.moveCenter(QPointF(i->ax(), i->ay()));
if (i->rx() == -1 && i->ry() == -1) {
tp.state = Qt::TouchPointReleased;
tp.pressure = 0;
} else {
tp.state = otp.state == Qt::TouchPointReleased
? Qt::TouchPointPressed : Qt::TouchPointMoved;
tp.pressure = 1;
}
otp = tp;
touch_points.push_back(tp);
}
QWindowSystemInterface::handleTouchEvent(0, _touch_device, touch_points);
}
void QNitpickerPlatformWindow::_process_mouse_event(Input::Event *ev)
{
QPoint global_position(ev->ax(), ev->ay());
QPoint local_position(global_position.x() - geometry().x(),
global_position.y() - geometry().y());
//qDebug() << "local_position =" << local_position;
//qDebug() << "global_position =" << global_position;
switch (ev->type()) {
case Input::Event::PRESS:
@ -136,6 +191,7 @@ void QNitpickerPlatformWindow::_key_repeat()
void QNitpickerPlatformWindow::_handle_input(unsigned int)
{
QList<Input::Event> touch_events;
for (int i = 0, num_ev = _input_session.flush(); i < num_ev; i++) {
Input::Event *ev = &_ev_buf[i];
@ -145,8 +201,8 @@ void QNitpickerPlatformWindow::_handle_input(unsigned int)
bool const is_mouse_button_event =
is_key_event && (ev->code() == Input::BTN_LEFT ||
ev->code() == Input::BTN_MIDDLE ||
ev->code() == Input::BTN_RIGHT);
ev->code() == Input::BTN_MIDDLE ||
ev->code() == Input::BTN_RIGHT);
if (ev->type() == Input::Event::MOTION ||
ev->type() == Input::Event::WHEEL ||
@ -154,12 +210,19 @@ void QNitpickerPlatformWindow::_handle_input(unsigned int)
_process_mouse_event(ev);
} else if (ev->type() == Input::Event::TOUCH) {
touch_events.push_back(*ev);
} else if (is_key_event && (ev->code() < 128)) {
_process_key_event(ev);
}
}
/* process all gathered touch events */
_process_touch_events(touch_events);
}
@ -265,7 +328,8 @@ QNitpickerPlatformWindow::QNitpickerPlatformWindow(QWindow *window,
_input_signal_dispatcher(_signal_receiver, *this,
&QNitpickerPlatformWindow::_input),
_mode_changed_signal_dispatcher(_signal_receiver, *this,
&QNitpickerPlatformWindow::_mode_changed)
&QNitpickerPlatformWindow::_mode_changed),
_touch_device(_init_touch_device())
{
if (qnpw_verbose)
if (window->transientParent())

View File

@ -24,7 +24,9 @@
/* Qt includes */
#include <qpa/qplatformwindow.h>
#include <qpa/qwindowsysteminterface.h>
#include <qevdevkeyboardhandler_p.h>
#include <qtouchdevice.h>
/* Qoost includes */
#include <qoost/qmember.h>
@ -64,8 +66,13 @@ class QNitpickerPlatformWindow : public QObject, public QPlatformWindow
Genode::Signal_dispatcher<QNitpickerPlatformWindow> _input_signal_dispatcher;
Genode::Signal_dispatcher<QNitpickerPlatformWindow> _mode_changed_signal_dispatcher;
QVector<QWindowSystemInterface::TouchPoint> _touch_points { 16 };
QTouchDevice *_touch_device;
QTouchDevice * _init_touch_device();
void _process_mouse_event(Input::Event *ev);
void _process_key_event(Input::Event *ev);
void _process_touch_events(QList<Input::Event> const &events);
Nitpicker::Session::View_handle _create_view();
void _adjust_and_set_geometry(const QRect &rect);