Add touch event support to wayland plugin.

Change-Id: If4be4965ae4e9898f5afb756632aa0349bd9b149
Reviewed-on: http://codereview.qt.nokia.com/935
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Jørgen Lind <jorgen.lind@nokia.com>
This commit is contained in:
Laszlo Agocs 2011-06-29 17:03:19 +03:00 committed by Qt by Nokia
parent c70869abc1
commit 06d85c51fe
4 changed files with 196 additions and 8 deletions

View File

@ -309,7 +309,7 @@ void QWaylandDisplay::displayHandleGlobal(uint32_t id,
wl_shell_add_listener(mShell, &shellListener, this);
} else if (interface == "wl_input_device") {
QWaylandInputDevice *inputDevice =
new QWaylandInputDevice(mDisplay, id);
new QWaylandInputDevice(this, id);
mInputDevices.append(inputDevice);
} else if (interface == "wl_selection_offer") {
QWaylandClipboard::instance(display)->createSelectionOffer(id);

View File

@ -45,10 +45,9 @@
#include "qwaylandwindow.h"
#include "qwaylandbuffer.h"
#include <QWindowSystemInterface>
#include <QtGui/private/qpixmap_raster_p.h>
#include <QtGui/QPlatformWindow>
#include <QDebug>
#include <unistd.h>
#include <fcntl.h>
@ -58,13 +57,17 @@
#include <X11/keysym.h>
#endif
QWaylandInputDevice::QWaylandInputDevice(struct wl_display *display,
//#define POINT_DEBUG
QWaylandInputDevice::QWaylandInputDevice(QWaylandDisplay *display,
uint32_t id)
: mDisplay(display)
, mInputDevice(wl_input_device_create(display, id, 1))
: mQDisplay(display)
, mDisplay(display->wl_display())
, mInputDevice(wl_input_device_create(mDisplay, id, 1))
, mPointerFocus(NULL)
, mKeyboardFocus(NULL)
, mButtons(0)
, mTouchState(QEvent::TouchBegin)
{
wl_input_device_add_listener(mInputDevice,
&inputDeviceListener,
@ -338,12 +341,168 @@ void QWaylandInputDevice::inputHandleKeyboardFocus(void *data,
#endif
}
void QWaylandInputDevice::inputHandleTouchDown(void *data,
struct wl_input_device *wl_input_device,
uint32_t time,
int id,
int x,
int y)
{
QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
inputDevice->handleTouchPoint(id, x, y, Qt::TouchPointPressed);
}
void QWaylandInputDevice::inputHandleTouchUp(void *data,
struct wl_input_device *wl_input_device,
uint32_t time,
int id)
{
QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
inputDevice->handleTouchPoint(id, 0, 0, Qt::TouchPointReleased);
}
void QWaylandInputDevice::inputHandleTouchMotion(void *data,
struct wl_input_device *wl_input_device,
uint32_t time,
int id,
int x,
int y)
{
QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
inputDevice->handleTouchPoint(id, x, y, Qt::TouchPointMoved);
}
void QWaylandInputDevice::handleTouchPoint(int id, int x, int y, Qt::TouchPointState state)
{
QWindowSystemInterface::TouchPoint tp;
// Find out the coordinates for Released events.
bool coordsOk = false;
if (state == Qt::TouchPointReleased)
for (int i = 0; i < mPrevTouchPoints.count(); ++i)
if (mPrevTouchPoints.at(i).id == id) {
tp.area = mPrevTouchPoints.at(i).area;
coordsOk = true;
break;
}
if (!coordsOk) {
// x and y are surface relative.
// We need a global (screen) position.
QWaylandWindow *win = mPointerFocus;
if (!win)
win = mKeyboardFocus;
#ifdef POINT_DEBUG
qDebug() << "surface relative coords" << x << y << "using window" << win;
#endif
if (!win)
return;
QRect winRect = win->geometry();
// Get a normalized position (0..1).
const qreal nx = x / qreal(winRect.width());
const qreal ny = y / qreal(winRect.height());
tp.normalPosition = QPointF(nx, ny);
// Map to screen.
QPlatformScreen *screen = mQDisplay->screens().at(0);
QRect screenRect = screen->geometry();
x = int(nx * screenRect.width());
y = int(ny * screenRect.height());
#ifdef POINT_DEBUG
qDebug() << "normalized position" << nx << ny
<< "win rect" << winRect << "screen rect" << screenRect;
qDebug() << "mapped to screen position" << x << y;
#endif
tp.area = QRectF(x, y, 1, 1);
}
tp.state = state;
tp.id = id;
tp.isPrimary = mTouchPoints.isEmpty();
tp.pressure = tp.state == Qt::TouchPointReleased ? 0 : 1;
mTouchPoints.append(tp);
}
void QWaylandInputDevice::inputHandleTouchFrame(void *data, struct wl_input_device *wl_input_device)
{
QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
inputDevice->handleTouchFrame();
}
void QWaylandInputDevice::handleTouchFrame()
{
// Copy all points, that are in the previous but not in the current list, as stationary.
for (int i = 0; i < mPrevTouchPoints.count(); ++i) {
const QWindowSystemInterface::TouchPoint &prevPoint(mPrevTouchPoints.at(i));
if (prevPoint.state == Qt::TouchPointReleased)
continue;
bool found = false;
for (int j = 0; j < mTouchPoints.count(); ++j)
if (mTouchPoints.at(j).id == prevPoint.id) {
found = true;
break;
}
if (!found) {
QWindowSystemInterface::TouchPoint p = prevPoint;
p.state = Qt::TouchPointStationary;
mTouchPoints.append(p);
}
}
if (mTouchPoints.isEmpty()) {
mPrevTouchPoints.clear();
return;
}
#ifdef POINT_DEBUG
qDebug() << mTouchPoints.count() << "touchpoints, event type" << mTouchState;
for (int i = 0; i < mTouchPoints.count(); ++i)
qDebug() << " " << mTouchPoints[i].id << mTouchPoints[i].state << mTouchPoints[i].area;
#endif
QWindowSystemInterface::handleTouchEvent(0, mTouchState, QTouchEvent::TouchScreen, mTouchPoints);
bool allReleased = true;
for (int i = 0; i < mTouchPoints.count(); ++i)
if (mTouchPoints.at(i).state != Qt::TouchPointReleased) {
allReleased = false;
break;
}
mPrevTouchPoints = mTouchPoints;
mTouchPoints.clear();
if (allReleased) {
#ifdef POINT_DEBUG
qDebug() << mTouchPoints.count() << "touchpoints, event type" << QEvent::TouchEnd;
#endif
QWindowSystemInterface::handleTouchEvent(0, QEvent::TouchEnd, QTouchEvent::TouchScreen, mTouchPoints);
mTouchState = QEvent::TouchBegin;
mPrevTouchPoints.clear();
} else if (mTouchState == QEvent::TouchBegin)
mTouchState = QEvent::TouchUpdate;
}
void QWaylandInputDevice::inputHandleTouchCancel(void *data, struct wl_input_device *wl_input_device)
{
}
const struct wl_input_device_listener QWaylandInputDevice::inputDeviceListener = {
QWaylandInputDevice::inputHandleMotion,
QWaylandInputDevice::inputHandleButton,
QWaylandInputDevice::inputHandleKey,
QWaylandInputDevice::inputHandlePointerFocus,
QWaylandInputDevice::inputHandleKeyboardFocus,
QWaylandInputDevice::inputHandleTouchDown,
QWaylandInputDevice::inputHandleTouchUp,
QWaylandInputDevice::inputHandleTouchMotion,
QWaylandInputDevice::inputHandleTouchFrame,
QWaylandInputDevice::inputHandleTouchCancel
};
void QWaylandInputDevice::attach(QWaylandBuffer *buffer, int x, int y)

View File

@ -48,21 +48,24 @@
#include <QObject>
#include <QtGui/QPlatformIntegration>
#include <QtGui/QPlatformScreen>
#include <QWindowSystemInterface>
#include <wayland-client.h>
QT_BEGIN_NAMESPACE
class QWaylandWindow;
class QWaylandDisplay;
class QWaylandInputDevice {
public:
QWaylandInputDevice(struct wl_display *display, uint32_t id);
QWaylandInputDevice(QWaylandDisplay *display, uint32_t id);
void attach(QWaylandBuffer *buffer, int x, int y);
void handleWindowDestroyed(QWaylandWindow *window);
struct wl_input_device *wl_input_device() const { return mInputDevice; }
private:
QWaylandDisplay *mQDisplay;
struct wl_display *mDisplay;
struct wl_input_device *mInputDevice;
QWaylandWindow *mPointerFocus;
@ -95,6 +98,32 @@ private:
uint32_t time,
struct wl_surface *surface,
struct wl_array *keys);
static void inputHandleTouchDown(void *data,
struct wl_input_device *wl_input_device,
uint32_t time,
int id,
int x,
int y);
static void inputHandleTouchUp(void *data,
struct wl_input_device *wl_input_device,
uint32_t time,
int id);
static void inputHandleTouchMotion(void *data,
struct wl_input_device *wl_input_device,
uint32_t time,
int id,
int x,
int y);
static void inputHandleTouchFrame(void *data,
struct wl_input_device *wl_input_device);
static void inputHandleTouchCancel(void *data,
struct wl_input_device *wl_input_device);
void handleTouchPoint(int id, int x, int y, Qt::TouchPointState state);
void handleTouchFrame();
QList<QWindowSystemInterface::TouchPoint> mTouchPoints;
QList<QWindowSystemInterface::TouchPoint> mPrevTouchPoints;
QEvent::Type mTouchState;
};
QT_END_NAMESPACE

View File

@ -1,3 +1,3 @@
This version of the Qt Wayland plugin is checked against the following sha1
from the Wayland repository:
bfea3d6befdb688d5354e6f15a9400ea637febf9
aa7bbb210b7121b9314993228960240358e9b123