Add multipoint touch support for Harmattan to the xcb platform plugin.

Proper multipoint touch support was only introduced in XInput2.1, but Harmattan uses
a tweaked version of XInput2.0 that transfers touch data through mouse events.

This patch applies on the xcb plugin a subset of the changes that were applied on the
Qt 4.7 that was shipped to Harmattan to get similar multipoint touch support.

Change-Id: Ifda7ad40de29d7ded1443d4f78b3ec3807303a9f
Reviewed-by: Simon Hausmann <simon.hausmann@nokia.com>
This commit is contained in:
Jocelyn Turcotte 2011-10-14 15:55:35 +02:00 committed by Qt by Nokia
parent 09cad13e49
commit 4521e2ec61
8 changed files with 517 additions and 1 deletions

View File

@ -0,0 +1,75 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the config.tests of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <X11/Xlib.h>
#include <X11/extensions/XInput2.h>
#include <X11/extensions/Xge.h>
#ifndef XInput_2_0
# error "Missing XInput_2_0 #define"
#endif
int main(int, char **)
{
// need XGenericEventCookie for XInput2 to work
Display *dpy = 0;
XEvent xevent;
if (XGetEventData(dpy, &xevent.xcookie)) {
XFreeEventData(dpy, &xevent.xcookie);
}
XIEvent *xievent;
xievent = 0;
XIDeviceEvent *xideviceevent;
xideviceevent = 0;
XIHierarchyEvent *xihierarchyevent;
xihierarchyevent = 0;
int deviceid = 0;
int len = 0;
Atom *atoms = XIListProperties(dpy, deviceid, &len);
if (atoms)
XFree(atoms);
return 0;
}

View File

@ -0,0 +1,4 @@
CONFIG += x11
CONFIG -= qt
LIBS += -lXi
SOURCES = xinput2.cpp

55
configure vendored
View File

@ -748,6 +748,7 @@ CFG_DECORATION_AVAILABLE="styled windows default"
CFG_DECORATION_ON="${CFG_DECORATION_AVAILABLE}" # all on by default
CFG_DECORATION_PLUGIN_AVAILABLE=
CFG_DECORATION_PLUGIN=
CFG_XINPUT2=auto
CFG_XINPUT=runtime
CFG_XKB=auto
CFG_XCB=auto
@ -819,6 +820,7 @@ XPLATFORM= # This seems to be the QMAKESPEC, like "linux-g++" or "s
XPLATFORM_MINGW=no # Whether target platform is MinGW (win32-g++*)
XPLATFORM_SYMBIAN=no # Whether target platform is SYMBIAN (*symbian*)
XPLATFORM_SYMBIAN_SBSV2=no # Whether target platform is SYMBIAN_SBSV2 (symbian-sbsv2)
XPLATFORM_MAEMO=no
PLATFORM=$QMAKESPEC
QT_CROSS_COMPILE=no
OPT_CONFIRM_LICENSE=no
@ -1042,7 +1044,7 @@ while [ "$#" -gt 0 ]; do
VAL=no
;;
#Qt style yes options
-incremental|-qvfb|-profile|-shared|-static|-sm|-xinerama|-xshape|-xsync|-xinput|-egl|-reduce-exports|-pch|-separate-debug-info|-stl|-freetype|-xcursor|-xfixes|-xrandr|-xrender|-mitshm|-fontconfig|-xkb|-xcb|-wayland|-nis|-qdbus|-dbus|-dbus-linked|-glib|-gstreamer|-gtkstyle|-cups|-iconv|-largefile|-h|-help|-v|-verbose|-debug|-release|-fast|-accessibility|-confirm-license|-gnumake|-framework|-qt3support|-debug-and-release|-exceptions|-cocoa|-carbon|-universal|-harfbuzz|-prefix-install|-silent|-armfpa|-optimized-qmake|-dwarf2|-reduce-relocations|-sse|-openssl|-openssl-linked|-ptmalloc|-xmlpatterns|-phonon|-phonon-backend|-multimedia|-audio-backend|-svg|-v8|-declarative|-declarative-debug|-javascript-jit|-script|-scripttools|-rpath|-force-pkg-config|-s60|-usedeffiles|-icu)
-incremental|-qvfb|-profile|-shared|-static|-sm|-xinerama|-xshape|-xsync|-xinput|-xinput2|-egl|-reduce-exports|-pch|-separate-debug-info|-stl|-freetype|-xcursor|-xfixes|-xrandr|-xrender|-mitshm|-fontconfig|-xkb|-xcb|-wayland|-nis|-qdbus|-dbus|-dbus-linked|-glib|-gstreamer|-gtkstyle|-cups|-iconv|-largefile|-h|-help|-v|-verbose|-debug|-release|-fast|-accessibility|-confirm-license|-gnumake|-framework|-qt3support|-debug-and-release|-exceptions|-cocoa|-carbon|-universal|-harfbuzz|-prefix-install|-silent|-armfpa|-optimized-qmake|-dwarf2|-reduce-relocations|-sse|-openssl|-openssl-linked|-ptmalloc|-xmlpatterns|-phonon|-phonon-backend|-multimedia|-audio-backend|-svg|-v8|-declarative|-declarative-debug|-javascript-jit|-script|-scripttools|-rpath|-force-pkg-config|-s60|-usedeffiles|-icu)
VAR=`echo $1 | sed "s,^-\(.*\),\1,"`
VAL=yes
;;
@ -1592,6 +1594,7 @@ while [ "$#" -gt 0 ]; do
case `basename "$XPLATFORM"` in win32-g++*) XPLATFORM_MINGW=yes;; esac
case "$XPLATFORM" in *symbian*) XPLATFORM_SYMBIAN=yes;; esac
case "$XPLATFORM" in symbian-sbsv2) XPLATFORM_SYMBIAN_SBSV2=yes;; esac
case "$XPLATFORM" in linux-g++-maemo) XPLATFORM_MAEMO=yes;; esac
;;
debug-and-release)
if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then
@ -1712,6 +1715,13 @@ while [ "$#" -gt 0 ]; do
UNKNOWN_OPT=yes
fi
;;
xinput2)
if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then
CFG_XINPUT2="$VAL"
else
UNKNOWN_OPT=yes
fi
;;
xinput)
if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ] || [ "$VAL" = "runtime" ]; then
CFG_XINPUT="$VAL"
@ -2913,6 +2923,7 @@ fi
case `basename "$XPLATFORM"` in win32-g++*) XPLATFORM_MINGW=yes;; esac
case "$XPLATFORM" in *symbian*) XPLATFORM_SYMBIAN=yes;; esac
case "$XPLATFORM" in symbian-sbsv2) XPLATFORM_SYMBIAN_SBSV2=yes;; esac
case "$XPLATFORM" in linux-g++-maemo) XPLATFORM_MAEMO=yes;; esac
if [ -d "$PLATFORM" ]; then
QMAKESPEC="$PLATFORM"
@ -3732,6 +3743,13 @@ if [ "$OPT_HELP" = "yes" ]; then
XWY="*"
XWN=" "
fi
if [ "$CFG_XINPUT2" = "no" ]; then
X2Y=" "
X2N="*"
else
X2Y="*"
X2N=" "
fi
cat <<EOF
Usage: $relconf [-h] [-prefix <dir>] [-prefix-install] [-bindir <dir>] [-libdir <dir>]
@ -4088,6 +4106,17 @@ EOF
fi # X11/QWS
if [ "$XPLATFORM_MAEMO" = "yes" ]; then
cat << EOF
$X2N -no-xinput2......... Do not compile XInput2 support.
$X2Y -xinput2............ Compile XInput2 support.
EOF
fi
if [ "$PLATFORM_X11" = "yes" ]; then
if [ "$CFG_SM" = "no" ]; then
SMY=" "
@ -6301,6 +6330,26 @@ if [ "$PLATFORM_QPA" = "yes" ]; then
if "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" config.tests/qpa/xcb-xlib "xcb-xlib" $L_FLAGS $I_FLAGS $l_FLAGS; then
QT_CONFIG="$QT_CONFIG xcb-xlib"
fi
if [ "$XPLATFORM_MAEMO" = "yes" ]; then
# auto-detect XInput2/Xinput support
if [ "$CFG_XINPUT2" != "no" ]; then
if "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" config.tests/x11/xinput2 "XInput2" $L_FLAGS $I_FLAGS $l_FLAGS $X11TESTS_FLAGS; then
CFG_XINPUT2=yes
CFG_XINPUT=no
else
if [ "$CFG_XINPUT2" = "yes" ] && [ "$CFG_CONFIGURE_EXIT_ON_ERROR" = "yes" ]; then
echo "XInput2 support cannot be enabled due to functionality tests!"
echo " Turn on verbose messaging (-v) to $0 to see the final report."
echo " If you believe this message is in error you may use the continue"
echo " switch (-continue) to $0 to continue."
exit 101
else
CFG_XINPUT2=no
fi
fi
fi
fi
else
if [ "$CFG_XCB" = "yes" ]; then
echo "The XCB test failed!"
@ -7271,6 +7320,7 @@ fi
[ "$CFG_OPENSSL" = "linked" ] && QT_CONFIG="$QT_CONFIG openssl-linked"
[ "$CFG_MAC_HARFBUZZ" = "yes" ] && QT_CONFIG="$QT_CONFIG harfbuzz"
[ "$CFG_XCB" = "yes" ] && QT_CONFIG="$QT_CONFIG xcb"
[ "$CFG_XINPUT2" = "yes" ] && QT_CONFIG="$QT_CONFIG xinput2"
if [ "$PLATFORM_X11" = "yes" ]; then
[ "$CFG_SM" = "yes" ] && QT_CONFIG="$QT_CONFIG x11sm"
@ -8633,6 +8683,9 @@ if [ "$CFG_XCB_LIMITED" = "yes" ] && [ "$CFG_XCB" = "yes" ]; then
else
echo "Xcb support ............ $CFG_XCB"
fi
if [ "$XPLATFORM_MAEMO" = "yes" ] && [ "$CFG_XCB" = "yes" ]; then
echo "XInput2 support ........ $CFG_XINPUT2"
fi
echo
[ "$CFG_PTMALLOC" != "no" ] && echo "Use ptmalloc ........... $CFG_PTMALLOC"

View File

@ -88,6 +88,9 @@ QT_BEGIN_NAMESPACE
QXcbConnection::QXcbConnection(const char *displayName)
: m_displayName(displayName ? QByteArray(displayName) : qgetenv("DISPLAY"))
#ifdef XCB_USE_XINPUT2_MAEMO
, m_xinputData(0)
#endif
#ifdef XCB_USE_DRI2
, m_dri2_major(0)
, m_dri2_minor(0)
@ -155,6 +158,9 @@ QXcbConnection::QXcbConnection(const char *displayName)
initializeXFixes();
initializeXRender();
#ifdef XCB_USE_XINPUT2_MAEMO
initializeXInput2();
#endif
m_wmSupport = new QXcbWMSupport(this);
m_keyboard = new QXcbKeyboard(this);
@ -173,6 +179,10 @@ QXcbConnection::~QXcbConnection()
qDeleteAll(m_screens);
#ifdef XCB_USE_XINPUT2_MAEMO
finalizeXInput2();
#endif
#ifdef XCB_POLL_FOR_QUEUED_EVENT
sendConnectionEvent(QXcbAtom::_QT_CLOSE_CONNECTION);
m_reader->wait();
@ -530,6 +540,11 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
case XCB_PROPERTY_NOTIFY:
HANDLE_PLATFORM_WINDOW_EVENT(xcb_property_notify_event_t, window, handlePropertyNotifyEvent);
break;
#ifdef XCB_USE_XINPUT2_MAEMO
case GenericEvent:
handleGenericEvent((xcb_ge_event_t*)event);
break;
#endif
default:
handled = false;
break;
@ -862,6 +877,22 @@ static const char * xcb_atomnames = {
// Tablet
"STYLUS\0"
"ERASER\0"
// XInput2
"Button Left\0"
"Button Middle\0"
"Button Right\0"
"Button Wheel Up\0"
"Button Wheel Down\0"
"Button Horiz Wheel Left\0"
"Button Horiz Wheel Right\0"
"Abs MT Position X\0"
"Abs MT Position Y\0"
"Abs MT Touch Major\0"
"Abs MT Touch Minor\0"
"Abs MT Pressure\0"
"Abs MT Tracking ID\0"
"Max Contacts\0"
};
xcb_atom_t QXcbConnection::atom(QXcbAtom::Atom atom)

View File

@ -51,6 +51,10 @@
#include <QThread>
#include <QVector>
#ifdef XCB_USE_XINPUT2_MAEMO
struct XInput2Data;
#endif
#define Q_XCB_DEBUG
QT_BEGIN_NAMESPACE
@ -222,6 +226,22 @@ namespace QXcbAtom {
XTabletStylus,
XTabletEraser,
// XInput2
ButtonLeft,
ButtonMiddle,
ButtonRight,
ButtonWheelUp,
ButtonWheelDown,
ButtonHorizWheelLeft,
ButtonHorizWheelRight,
AbsMTPositionX,
AbsMTPositionY,
AbsMTTouchMajor,
AbsMTTouchMinor,
AbsMTPressure,
AbsMTTrackingID,
MaxContacts,
NPredefinedAtoms,
_QT_SETTINGS_TIMESTAMP = NPredefinedAtoms,
@ -301,6 +321,9 @@ public:
#if defined(XCB_USE_EGL) || defined(XCB_USE_DRI2)
void *egl_display() const { return m_egl_display; }
#endif
#ifdef XCB_USE_XINPUT2_MAEMO
bool isUsingXInput2();
#endif
void sync();
void flush() { xcb_flush(m_connection); }
@ -334,6 +357,11 @@ private:
void initializeXRender();
#ifdef XCB_USE_DRI2
void initializeDri2();
#endif
#ifdef XCB_USE_XINPUT2_MAEMO
void initializeXInput2();
void finalizeXInput2();
void handleGenericEvent(xcb_ge_event_t *event);
#endif
void handleClientMessageEvent(const xcb_client_message_event_t *event);
@ -360,6 +388,9 @@ private:
void *m_xlib_display;
#endif
QXcbEventReader *m_reader;
#ifdef XCB_USE_XINPUT2_MAEMO
XInput2Data *m_xinputData;
#endif
#ifdef XCB_USE_DRI2
uint32_t m_dri2_major;
uint32_t m_dri2_minor;

View File

@ -0,0 +1,294 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qxcbconnection.h"
#ifdef XCB_USE_XINPUT2_MAEMO
#include "qxcbwindow.h"
#include <QtGui/QWindowSystemInterface>
#include <X11/extensions/XInput2.h>
#include <X11/extensions/XI2proto.h>
#include <X11/Xatom.h>
// Define it here to work around XLib defining Bool and stuff.
// We can't declare those variables in the header without facing include order headaches.
struct XInput2Data {
XInput2Data()
: use_xinput(false)
, xinput_opcode(0)
, xinput_eventbase(0)
, xinput_errorbase(0)
, xideviceinfo(0)
, xibuttonclassinfo(0)
, xiMaxContacts(0)
{
}
// true if Qt is compiled w/ XInput2 or Tablet support and we have a tablet.
bool use_xinput;
int xinput_opcode;
int xinput_eventbase;
int xinput_errorbase;
// device info for the master pointer Qt is using
XIDeviceInfo *xideviceinfo;
XIButtonClassInfo *xibuttonclassinfo;
int xiMaxContacts;
QList<QWindowSystemInterface::TouchPoint> allTouchPoints;
};
bool QXcbConnection::isUsingXInput2()
{
return m_xinputData && m_xinputData->use_xinput && m_xinputData->xiMaxContacts != 0;
}
void QXcbConnection::initializeXInput2()
{
Q_ASSERT(!m_xinputData);
m_xinputData = new XInput2Data;
m_xinputData->use_xinput = XQueryExtension((Display *)m_xlib_display, "XInputExtension", &m_xinputData->xinput_opcode,
&m_xinputData->xinput_eventbase, &m_xinputData->xinput_errorbase);
if (m_xinputData->use_xinput) {
// we want XInput2
int ximajor = 2, ximinor = 0;
if (XIQueryVersion((Display *)m_xlib_display, &ximajor, &ximinor) == BadRequest) {
// XInput2 not available
m_xinputData->use_xinput = false;
} else {
// find the first master pointer and use this throughout Qt
// when making XI2 calls that need a device id (rationale is that
// for the time being, most setups will only have one master
// pointer (despite having multiple slaves)
int deviceCount = 0;
XIDeviceInfo *devices = XIQueryDevice((Display *)m_xlib_display, XIAllMasterDevices, &deviceCount);
if (devices) {
for (int i = 0; i < deviceCount; ++i) {
if (devices[i].use == XIMasterPointer) {
int unused = 0;
m_xinputData->xideviceinfo = XIQueryDevice((Display *)m_xlib_display, devices[i].deviceid, &unused);
break;
}
}
XIFreeDeviceInfo(devices);
}
if (!m_xinputData->xideviceinfo)
qFatal("Qt: Internal error, no XI2 master pointer found.");
// find the button info
m_xinputData->xibuttonclassinfo = 0;
for (int i = 0; i < m_xinputData->xideviceinfo->num_classes; ++i) {
if (m_xinputData->xideviceinfo->classes[i]->type == XIButtonClass) {
m_xinputData->xibuttonclassinfo = (XIButtonClassInfo *) m_xinputData->xideviceinfo->classes[i];
break;
}
}
// find the "Max Contacts" property on the device
Atom typeReturn;
int formatReturn;
ulong countReturn, bytesReturn;
uchar *data = 0;
if (XIGetProperty((Display *)m_xlib_display,
m_xinputData->xibuttonclassinfo->sourceid,
atom(QXcbAtom::MaxContacts),
0, 1,
False,
XA_INTEGER,
&typeReturn,
&formatReturn,
&countReturn,
&bytesReturn,
&data) == Success
&& data != 0
&& typeReturn == XA_INTEGER
&& formatReturn == 8
&& countReturn == 1) {
// touch driver reported the max number of touch-points
m_xinputData->xiMaxContacts = data[0];
} else {
m_xinputData->xiMaxContacts = 0;
}
if (data)
XFree(data);
XFlush((Display *)m_xlib_display);
}
}
}
void QXcbConnection::finalizeXInput2()
{
if (m_xinputData && m_xinputData->xideviceinfo) {
XIFreeDeviceInfo(m_xinputData->xideviceinfo);
}
delete m_xinputData;
}
// Borrowed from libXi.
static int count_bits(unsigned char* ptr, int len)
{
int bits = 0;
int i;
unsigned char x;
for (i = 0; i < len; i++)
{
x = ptr[i];
while (x > 0)
{
bits += (x & 0x1);
x >>= 1;
}
}
return bits;
}
static bool getValuatorValueIfSet(xXIDeviceEvent *xideviceevent, int valuatorNum, double *value)
{
unsigned char *buttonsMaskAddr = (unsigned char*)&xideviceevent[1];
unsigned char *valuatorsMaskAddr = buttonsMaskAddr + xideviceevent->buttons_len * 4;
FP3232 *valuatorsValuesAddr = (FP3232*)(valuatorsMaskAddr + xideviceevent->valuators_len * 4);
int numValuatorValues = count_bits(valuatorsMaskAddr, xideviceevent->valuators_len * 4);
// This relies on all bit being set until a certain number i.e. it doesn't support only bit 0 and 5 being set in the mask.
// Just like the original code, works for now.
if (valuatorNum >= numValuatorValues)
return false;
*value = valuatorsValuesAddr[valuatorNum].integral;
*value += ((double)valuatorsValuesAddr[valuatorNum].frac / (1 << 16) / (1 << 16));
return true;
}
void QXcbConnection::handleGenericEvent(xcb_ge_event_t *event)
{
// xGenericEvent has "extension" on the second byte, xcb_ge_event_t has "pad0".
if (m_xinputData->use_xinput && event->pad0 == m_xinputData->xinput_opcode) {
// xcb event structs contain stuff that wasn't on the wire, the full_sequence field
// adds an extra 4 bytes and generic events cookie data is on the wire right after the standard 32 bytes.
// Move this data back to have the same layout in memory as it was on the wire
// and allow casting, overwritting the full_sequence field.
memmove((char*)event + 32, (char*)event + 36, event->length * 4);
xXIGenericDeviceEvent* xievent = (xXIGenericDeviceEvent*)event;
// On Harmattan XInput2 is hacked to give touch points updates into standard mouse button press/motion events.
if (m_xinputData->xiMaxContacts != 0
&& (xievent->evtype == XI_ButtonPress
|| xievent->evtype == XI_ButtonRelease
|| xievent->evtype == XI_Motion)) {
xXIDeviceEvent *xideviceevent = (xXIDeviceEvent *)xievent;
QList<QWindowSystemInterface::TouchPoint> touchPoints = m_xinputData->allTouchPoints;
if (touchPoints.count() != m_xinputData->xiMaxContacts) {
// initial event, allocate space for all (potential) touch points
touchPoints.reserve(m_xinputData->xiMaxContacts);
for (int i = 0; i < m_xinputData->xiMaxContacts; ++i) {
QWindowSystemInterface::TouchPoint tp;
tp.id = i;
tp.isPrimary = (i == 0);
tp.state = Qt::TouchPointReleased;
touchPoints << tp;
}
}
qreal x, y, nx, ny, w = 0.0, h = 0.0, p = -1.0;
int id;
uint active = 0;
for (int i = 0; i < m_xinputData->xideviceinfo->num_classes; ++i) {
XIAnyClassInfo *classinfo = m_xinputData->xideviceinfo->classes[i];
if (classinfo->type == XIValuatorClass) {
XIValuatorClassInfo *valuatorclassinfo = reinterpret_cast<XIValuatorClassInfo *>(classinfo);
int n = valuatorclassinfo->number;
double value;
if (!getValuatorValueIfSet(xideviceevent, n, &value))
continue;
if (valuatorclassinfo->label == atom(QXcbAtom::AbsMTPositionX)) {
x = value;
nx = (x - valuatorclassinfo->min) / (valuatorclassinfo->max - valuatorclassinfo->min);
} else if (valuatorclassinfo->label == atom(QXcbAtom::AbsMTPositionY)) {
y = value;
ny = (y - valuatorclassinfo->min) / (valuatorclassinfo->max - valuatorclassinfo->min);
} else if (valuatorclassinfo->label == atom(QXcbAtom::AbsMTTouchMajor)) {
w = value;
} else if (valuatorclassinfo->label == atom(QXcbAtom::AbsMTTouchMinor)) {
h = value;
} else if (valuatorclassinfo->label == atom(QXcbAtom::AbsMTPressure)) {
p = (value - valuatorclassinfo->min) / (valuatorclassinfo->max - valuatorclassinfo->min);
} else if (valuatorclassinfo->label == atom(QXcbAtom::AbsMTTrackingID)) {
id = value;
active |= 1 << id;
QWindowSystemInterface::TouchPoint &touchPoint = touchPoints[id];
Qt::TouchPointState newstate;
if (touchPoint.state == Qt::TouchPointReleased) {
newstate = Qt::TouchPointPressed;
} else {
if (touchPoint.area.center() != QPoint(x, y))
newstate = Qt::TouchPointMoved;
else
newstate = Qt::TouchPointStationary;
}
touchPoint.state = newstate;
touchPoint.area = QRectF(x - w/2, y - h/2, w, h);
touchPoint.normalPosition = QPointF(nx, ny);
touchPoint.pressure = p;
}
}
}
// mark previously-active-but-now-inactive touch points as released
for (int i = 0; i < touchPoints.count(); ++i)
if (!(active & (1 << i)) && touchPoints.at(i).state != Qt::TouchPointReleased)
touchPoints[i].state = Qt::TouchPointReleased;
if (xideviceevent->evtype == XI_ButtonRelease) {
// final event, forget touch state
m_xinputData->allTouchPoints.clear();
} else {
// save current state so that we have something to reuse later
m_xinputData->allTouchPoints = touchPoints;
}
if (QXcbWindow *platformWindow = platformWindowFromId(xideviceevent->event))
QWindowSystemInterface::handleTouchEvent(platformWindow->window(), xideviceevent->time, (QEvent::Type)0 /*None*/, QTouchEvent::TouchScreen, m_xinputData->allTouchPoints);
}
}
}
#endif // XCB_USE_XINPUT2_MAEMO

View File

@ -93,6 +93,10 @@
#include <X11/Xutil.h>
#endif
#ifdef XCB_USE_XINPUT2_MAEMO
#include <X11/extensions/XInput2.h>
#endif
#if defined(XCB_USE_GLX)
#include "qglxintegration.h"
#include <QtPlatformSupport/private/qglxconvenience_p.h>
@ -322,6 +326,23 @@ void QXcbWindow::create()
atom(QXcbAtom::WM_CLIENT_LEADER), XCB_ATOM_WINDOW, 32,
1, &leader));
#ifdef XCB_USE_XINPUT2_MAEMO
if (connection()->isUsingXInput2()) {
XIEventMask xieventmask;
uchar bitmask[2] = { 0, 0 };
xieventmask.deviceid = XIAllMasterDevices;
xieventmask.mask = bitmask;
xieventmask.mask_len = sizeof(bitmask);
XISetMask(bitmask, XI_ButtonPress);
XISetMask(bitmask, XI_ButtonRelease);
XISetMask(bitmask, XI_Motion);
XISelectEvents(DISPLAY_FROM_XCB(this), m_window, &xieventmask, 1);
}
#endif
setWindowFlags(window()->windowFlags());
setWindowTitle(window()->windowTitle());
setWindowState(window()->windowState());

View File

@ -45,6 +45,13 @@ contains(QT_CONFIG, xcb-poll-for-queued-event) {
contains(QT_CONFIG, xcb-xlib) {
DEFINES += XCB_USE_XLIB
LIBS += -lX11 -lX11-xcb
linux-g++-maemo:contains(QT_CONFIG, xinput2) {
# XInput2 support for Harmattan.
DEFINES += XCB_USE_XINPUT2_MAEMO
SOURCES += qxcbconnection_maemo.cpp
LIBS += -lXi
}
}
# to support custom cursors with depth > 1