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:
parent
09cad13e49
commit
4521e2ec61
75
config.tests/x11/xinput2/xinput2.cpp
Normal file
75
config.tests/x11/xinput2/xinput2.cpp
Normal 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;
|
||||
}
|
4
config.tests/x11/xinput2/xinput2.pro
Normal file
4
config.tests/x11/xinput2/xinput2.pro
Normal file
@ -0,0 +1,4 @@
|
||||
CONFIG += x11
|
||||
CONFIG -= qt
|
||||
LIBS += -lXi
|
||||
SOURCES = xinput2.cpp
|
55
configure
vendored
55
configure
vendored
@ -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"
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
294
src/plugins/platforms/xcb/qxcbconnection_maemo.cpp
Normal file
294
src/plugins/platforms/xcb/qxcbconnection_maemo.cpp
Normal 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
|
||||
|
||||
|
@ -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());
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user