--- /dev/null
+/****************************************************************************
+**
+** 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;
+}
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
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
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
;;
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
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"
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"
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>]
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=" "
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!"
[ "$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"
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"
--- /dev/null
+/****************************************************************************
+**
+** 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
+
+