Merge lp:~oif-team/ubuntu/natty/qt4-x11/xi2.1 into lp:ubuntu/natty/qt4-x11

Proposed by Chase Douglas
Status: Needs review
Proposed branch: lp:~oif-team/ubuntu/natty/qt4-x11/xi2.1
Merge into: lp:ubuntu/natty/qt4-x11
Diff against target: 941 lines (+909/-1)
4 files modified
debian/changelog (+8/-0)
debian/control (+1/-1)
debian/patches/200_xi2.1.patch (+897/-0)
debian/patches/series (+3/-0)
To merge this branch: bzr merge lp:~oif-team/ubuntu/natty/qt4-x11/xi2.1
Reviewer Review Type Date Requested Status
Jonathan Riddell Pending
Review via email: mp+50952@code.launchpad.net

Description of the change

Add in multitouch support. The patch's origin is from Denis Dzyubenko from Nokia. I have refined it some more. Hopefully this will serve as the base for multitouch support in upstream Qt when XInput 2.1 is finalized and available.

To post a comment you must log in.

Unmerged revisions

142. By Chase Douglas

* Add multitouch support through preliminary XInput 2.1
  - Add debian/patches/200_xi2.1.patch
  - Add build dependency on new libxi-dev with XInput 2.1 support

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/changelog'
2--- debian/changelog 2011-02-07 12:11:02 +0000
3+++ debian/changelog 2011-02-23 16:43:58 +0000
4@@ -1,3 +1,11 @@
5+qt4-x11 (4:4.7.1-0ubuntu10) UNRELEASED; urgency=low
6+
7+ * Add multitouch support through preliminary XInput 2.1
8+ - Add debian/patches/200_xi2.1.patch
9+ - Add build dependency on new libxi-dev with XInput 2.1 support
10+
11+ -- Chase Douglas <chase.douglas@ubuntu.com> Wed, 23 Feb 2011 10:59:05 -0500
12+
13 qt4-x11 (4:4.7.1-0ubuntu9) natty; urgency=high
14
15 * Force Qt4 on ARM to build against gcc-4.4 due to compiler regression in
16
17=== modified file 'debian/control'
18--- debian/control 2011-02-07 12:11:02 +0000
19+++ debian/control 2011-02-23 16:43:58 +0000
20@@ -13,7 +13,7 @@
21 # libopenvg1-mesa-dev,
22 libpam0g-dev, libpng12-dev, libpq-dev, libreadline-dev, libsm-dev,
23 libsqlite0-dev, libsqlite3-dev, libtiff4-dev, libx11-dev, libxcursor-dev,
24- libxext-dev, libxft-dev, libxi-dev, libxinerama-dev, libxmu-dev,
25+ libxext-dev, libxft-dev, libxi-dev (>= 2:1.4.1-1ubuntu1), libxinerama-dev, libxmu-dev,
26 libxrandr-dev, libxrender-dev, libxslt1-dev, libxt-dev, libxtst-dev,
27 libxv-dev, zlib1g-dev, freetds-dev, g++-4.4 [armel]
28 Standards-Version: 3.9.1
29
30=== added file 'debian/patches/200_xi2.1.patch'
31--- debian/patches/200_xi2.1.patch 1970-01-01 00:00:00 +0000
32+++ debian/patches/200_xi2.1.patch 2011-02-23 16:43:58 +0000
33@@ -0,0 +1,897 @@
34+--- /dev/null
35++++ b/config.tests/x11/xinput2/xinput2.cpp
36+@@ -0,0 +1,75 @@
37++/****************************************************************************
38++**
39++** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
40++** All rights reserved.
41++** Contact: Nokia Corporation (qt-info@nokia.com)
42++**
43++** This file is part of the config.tests of the Qt Toolkit.
44++**
45++** $QT_BEGIN_LICENSE:LGPL$
46++** No Commercial Usage
47++** This file contains pre-release code and may not be distributed.
48++** You may use this file in accordance with the terms and conditions
49++** contained in the Technology Preview License Agreement accompanying
50++** this package.
51++**
52++** GNU Lesser General Public License Usage
53++** Alternatively, this file may be used under the terms of the GNU Lesser
54++** General Public License version 2.1 as published by the Free Software
55++** Foundation and appearing in the file LICENSE.LGPL included in the
56++** packaging of this file. Please review the following information to
57++** ensure the GNU Lesser General Public License version 2.1 requirements
58++** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
59++**
60++** In addition, as a special exception, Nokia gives you certain additional
61++** rights. These rights are described in the Nokia Qt LGPL Exception
62++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
63++**
64++** If you have questions regarding the use of this file, please contact
65++** Nokia at qt-info@nokia.com.
66++**
67++**
68++**
69++**
70++**
71++**
72++**
73++**
74++** $QT_END_LICENSE$
75++**
76++****************************************************************************/
77++
78++#include <X11/Xlib.h>
79++#include <X11/extensions/XInput2.h>
80++#include <X11/extensions/Xge.h>
81++
82++#ifndef XInput_2_1
83++# error "Missing XInput_2_1 #define"
84++#endif
85++
86++int main(int, char **)
87++{
88++ // need XGenericEventCookie for XInput2 to work
89++ Display *dpy = 0;
90++ XEvent xevent;
91++ if (XGetEventData(dpy, &xevent.xcookie)) {
92++ XFreeEventData(dpy, &xevent.xcookie);
93++ }
94++
95++ XIEvent *xievent;
96++ xievent = 0;
97++
98++ XIDeviceEvent *xideviceevent;
99++ xideviceevent = 0;
100++
101++ XIHierarchyEvent *xihierarchyevent;
102++ xihierarchyevent = 0;
103++
104++ int deviceid = 0;
105++ int len = 0;
106++ Atom *atoms = XIListProperties(dpy, deviceid, &len);
107++ if (atoms)
108++ XFree(atoms);
109++
110++ return 0;
111++}
112+--- /dev/null
113++++ b/config.tests/x11/xinput2/xinput2.pro
114+@@ -0,0 +1,4 @@
115++CONFIG += x11
116++CONFIG -= qt
117++LIBS += -lXi
118++SOURCES = xinput2.cpp
119+--- a/configure
120++++ b/configure
121+@@ -765,6 +765,7 @@ CFG_DECORATION_AVAILABLE="styled windows
122+ CFG_DECORATION_ON="${CFG_DECORATION_AVAILABLE}" # all on by default
123+ CFG_DECORATION_PLUGIN_AVAILABLE=
124+ CFG_DECORATION_PLUGIN=
125++CFG_XINPUT2=auto
126+ CFG_XINPUT=runtime
127+ CFG_XKB=auto
128+ CFG_NIS=auto
129+@@ -991,7 +992,7 @@ while [ "$#" -gt 0 ]; do
130+ VAL=no
131+ ;;
132+ #Qt style yes options
133+- -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|-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|-prefix-install|-silent|-armfpa|-optimized-qmake|-dwarf2|-reduce-relocations|-sse|-openssl|-openssl-linked|-ptmalloc|-xmlpatterns|-phonon|-phonon-backend|-multimedia|-audio-backend|-svg|-declarative|-webkit|-javascript-jit|-script|-scripttools|-rpath|-force-pkg-config|-s60|-usedeffiles)
134++ -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|-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|-prefix-install|-silent|-armfpa|-optimized-qmake|-dwarf2|-reduce-relocations|-sse|-openssl|-openssl-linked|-ptmalloc|-xmlpatterns|-phonon|-phonon-backend|-multimedia|-audio-backend|-svg|-declarative|-webkit|-javascript-jit|-script|-scripttools|-rpath|-force-pkg-config|-s60|-usedeffiles)
135+ VAR=`echo $1 | sed "s,^-\(.*\),\1,"`
136+ VAL=yes
137+ ;;
138+@@ -1637,6 +1638,13 @@ while [ "$#" -gt 0 ]; do
139+ UNKNOWN_OPT=yes
140+ fi
141+ ;;
142++ xinput2)
143++ if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then
144++ CFG_XINPUT2="$VAL"
145++ else
146++ UNKNOWN_OPT=yes
147++ fi
148++ ;;
149+ xinput)
150+ if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ] || [ "$VAL" = "runtime" ]; then
151+ CFG_XINPUT="$VAL"
152+@@ -3982,6 +3990,13 @@ if [ "$PLATFORM_X11" = "yes" ]; then
153+ XMY="*"
154+ XMN=" "
155+ fi
156++ if [ "$CFG_XINPUT2" = "no" ]; then
157++ X2Y=" "
158++ X2N="*"
159++ else
160++ X2Y="*"
161++ X2N=" "
162++ fi
163+ if [ "$CFG_XINPUT" = "no" ]; then
164+ XIY=" "
165+ XIN="*"
166+@@ -4086,7 +4101,10 @@ Qt/X11 only:
167+ Requires fontconfig/fontconfig.h, libfontconfig,
168+ freetype.h and libfreetype.
169+
170+- $XIN -no-xinput ......... Do not compile Xinput support.
171++ $X2N -no-xinput2......... Do not compile XInput2 support.
172++ $X2Y -xinput2............ Compile XInput2 support.
173++
174++ $XIN -no-xinput.......... Do not compile Xinput support.
175+ $XIY -xinput ............ Compile Xinput support. This also enabled tablet support
176+ which requires IRIX with wacom.h and libXi or
177+ XFree86 with X11/extensions/XInput.h and libXi.
178+@@ -5910,7 +5928,23 @@ if [ "$PLATFORM_X11" = "yes" ]; then
179+ fi
180+ fi
181+
182+- # auto-detect Xinput support
183++ # auto-detect XInput2/Xinput support
184++ if [ "$CFG_XINPUT2" != "no" ]; then
185++ 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
186++ CFG_XINPUT2=yes
187++ CFG_XINPUT=no
188++ else
189++ if [ "$CFG_XINPUT2" = "yes" ] && [ "$CFG_CONFIGURE_EXIT_ON_ERROR" = "yes" ]; then
190++ echo "XInput2 support cannot be enabled due to functionality tests!"
191++ echo " Turn on verbose messaging (-v) to $0 to see the final report."
192++ echo " If you believe this message is in error you may use the continue"
193++ echo " switch (-continue) to $0 to continue."
194++ exit 101
195++ else
196++ CFG_XINPUT2=no
197++ fi
198++ fi
199++ fi
200+ if [ "$CFG_XINPUT" != "no" ]; then
201+ if "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" config.tests/x11/xinput "XInput" $L_FLAGS $I_FLAGS $l_FLAGS $X11TESTS_FLAGS; then
202+ if [ "$CFG_XINPUT" != "runtime" ]; then
203+@@ -6971,9 +7005,12 @@ if [ "$PLATFORM_X11" = "yes" ]; then
204+ if [ "$CFG_FONTCONFIG" = "yes" ]; then
205+ QT_CONFIG="$QT_CONFIG fontconfig"
206+ fi
207+- if [ "$CFG_XINPUT" = "yes" ]; then
208++ if [ "$CFG_XINPUT2" = "yes" -o "$CFG_XINPUT" = "yes" ]; then
209+ QMakeVar set QMAKE_LIBS_X11 '-lXi $$QMAKE_LIBS_X11'
210+ fi
211++ if [ "$CFG_XINPUT2" = "yes" ]; then
212++ QT_CONFIG="$QT_CONFIG xinput2"
213++ fi
214+ if [ "$CFG_XINPUT" = "yes" ]; then
215+ QT_CONFIG="$QT_CONFIG xinput tablet"
216+ fi
217+@@ -7846,6 +7883,7 @@ fi
218+ [ "$CFG_XSHAPE" = "no" ] && QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_SHAPE"
219+ [ "$CFG_XVIDEO" = "no" ] && QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_XVIDEO"
220+ [ "$CFG_XSYNC" = "no" ] && QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_XSYNC"
221++[ "$CFG_XINPUT2" = "no" ] && QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_XINPUT2"
222+ [ "$CFG_XINPUT" = "no" ] && QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_XINPUT QT_NO_TABLET"
223+
224+ [ "$CFG_XCURSOR" = "runtime" ] && QCONFIG_FLAGS="$QCONFIG_FLAGS QT_RUNTIME_XCURSOR"
225+@@ -8376,6 +8414,7 @@ if [ "$PLATFORM_X11" = "yes" ]; then
226+ echo "Xfixes support ......... $CFG_XFIXES"
227+ echo "Xrandr support ......... $CFG_XRANDR"
228+ echo "Xrender support ........ $CFG_XRENDER"
229++ echo "XInput2 support ........ $CFG_XINPUT2"
230+ echo "Xi support ............. $CFG_XINPUT"
231+ echo "MIT-SHM support ........ $CFG_MITSHM"
232+ echo "FontConfig support ..... $CFG_FONTCONFIG"
233+--- a/examples/touch/fingerpaint/scribblearea.cpp
234++++ b/examples/touch/fingerpaint/scribblearea.cpp
235+@@ -186,7 +186,9 @@ bool ScribbleArea::event(QEvent *event)
236+ QRectF rect = touchPoint.rect();
237+ if (rect.isEmpty()) {
238+ qreal diameter = qreal(50) * touchPoint.pressure();
239++ QPointF center = rect.center();
240+ rect.setSize(QSizeF(diameter, diameter));
241++ rect.moveCenter(center);
242+ }
243+
244+ QPainter painter(&image);
245+--- a/src/gui/kernel/kernel.pri
246++++ b/src/gui/kernel/kernel.pri
247+@@ -141,6 +141,7 @@ symbian {
248+ unix:x11 {
249+ INCLUDEPATH += ../3rdparty/xorg
250+ HEADERS += \
251++ kernel/qt_x11_p.h \
252+ kernel/qx11embed_x11.h \
253+ kernel/qx11info_x11.h \
254+ kernel/qkde_p.h
255+--- a/src/gui/kernel/qapplication_p.h
256++++ b/src/gui/kernel/qapplication_p.h
257+@@ -601,6 +601,35 @@ public:
258+ QList<QTouchEvent::TouchPoint> appAllTouchPoints;
259+ #endif
260+
261++#if defined(Q_WS_X11) && !defined(QT_NO_XINPUT2)
262++ struct TouchDeviceInfo {
263++ int deviceid;
264++ int maxTouches;
265++ bool directTouch;
266++ int numValuators;
267++ struct Valuator {
268++ int number;
269++ unsigned long label; // Atom
270++ qreal min;
271++ qreal max;
272++ quint32 resolution;
273++ };
274++ Valuator xivPosX;
275++ Valuator xivPosY;
276++ Valuator xivTouchMajor;
277++ Valuator xivTouchMinor;
278++ Valuator xivOrientation;
279++ };
280++ QHash<int, TouchDeviceInfo> touchDevices;
281++ QList<QTouchEvent::TouchPoint> appTouchPoints;
282++ QTouchEvent::DeviceType activeDeviceType;
283++ QMap<int, QPointF> touchedPos; // initial value of X and Y valuators for indirect touch
284++ QMap<int, QSizeF> touchedSize; // major => height, minor => width
285++ QMap<int, qreal> touchedOrientation; // -1 => point to left, 0 => point up, 1 => point to right
286++ QTouchEvent::TouchPoint unsentAppTouchPoint; // sequence that was not delivered to a widget yet
287++ void x11GetTouchDeviceInfo();
288++#endif
289++
290+ private:
291+ #ifdef Q_WS_QWS
292+ QMap<const QScreen*, QRect> maxWindowRects;
293+--- a/src/gui/kernel/qapplication_x11.cpp
294++++ b/src/gui/kernel/qapplication_x11.cpp
295+@@ -87,6 +87,7 @@
296+ #include <private/qgraphicssystemfactory_p.h>
297+ #include "qguiplatformplugin_p.h"
298+ #include "qkde_p.h"
299++#include "qmath.h"
300+
301+ #if !defined (QT_NO_TABLET)
302+ extern "C" {
303+@@ -126,9 +127,6 @@ extern "C" {
304+
305+ #define XK_MISCELLANY
306+ #include <X11/keysymdef.h>
307+-#if !defined(QT_NO_XINPUT)
308+-#include <X11/extensions/XI.h>
309+-#endif
310+
311+ #include <stdlib.h>
312+ #include <string.h>
313+@@ -327,6 +325,13 @@ static const char * x11_atomnames = {
314+ // Tablet
315+ "STYLUS\0"
316+ "ERASER\0"
317++
318++ // XInput 2.1 touch
319++ "Abs MT Touch Major\0"
320++ "Abs MT Touch Minor\0"
321++ "Abs MT Orientation\0"
322++ "Abs MT Position X\0"
323++ "Abs MT Position Y\0"
324+ };
325+
326+ Q_GUI_EXPORT QX11Data *qt_x11Data = 0;
327+@@ -578,6 +583,10 @@ public:
328+ #endif
329+ bool translatePropertyEvent(const XEvent *);
330+
331++#if !defined(QT_NO_XINPUT2)
332++ bool translateXI2Event(const XIEvent *);
333++#endif
334++
335+ void doDeferredMap()
336+ {
337+ Q_ASSERT(testAttribute(Qt::WA_WState_Created));
338+@@ -699,7 +708,7 @@ static int qt_x_errhandler(Display *dpy,
339+
340+ default:
341+ #if !defined(QT_NO_XINPUT)
342+- if (err->request_code == X11->xinput_major
343++ if (err->request_code == X11->xinput_opcode
344+ && err->error_code == (X11->xinput_errorbase + XI_BadDevice)
345+ && err->minor_code == 3 /* X_OpenDevice */) {
346+ return 0;
347+@@ -730,7 +739,7 @@ static int qt_x_errhandler(Display *dpy,
348+ extensionName = "RENDER";
349+ else if (err->request_code == X11->xrandr_major)
350+ extensionName = "RANDR";
351+- else if (err->request_code == X11->xinput_major)
352++ else if (err->request_code == X11->xinput_opcode)
353+ extensionName = "XInputExtension";
354+ else if (err->request_code == X11->mitshm_major)
355+ extensionName = "MIT-SHM";
356+@@ -1628,6 +1637,16 @@ static void getXDefault(const char *grou
357+ }
358+ #endif
359+
360++inline void copy(QApplicationPrivate::TouchDeviceInfo::Valuator &dst,
361++ const XITouchValuatorClassInfo &src)
362++{
363++ dst.number = src.number;
364++ dst.label = src.label;
365++ dst.min = src.min;
366++ dst.max = src.max;
367++ dst.resolution = src.resolution;
368++}
369++
370+ // ### This should be static but it isn't because of the friend declaration
371+ // ### in qpaintdevice.h which then should have a static too but can't have
372+ // ### it because "storage class specifiers invalid in friend function
373+@@ -1660,9 +1679,13 @@ void qt_init(QApplicationPrivate *priv,
374+
375+ // XInputExtension
376+ X11->use_xinput = false;
377+- X11->xinput_major = 0;
378++ X11->xinput_opcode = 0;
379+ X11->xinput_eventbase = 0;
380+ X11->xinput_errorbase = 0;
381++#if !defined(QT_NO_XINPUT2)
382++ X11->xideviceinfo = 0;
383++ X11->xitouchclassinfo = 0;
384++#endif
385+
386+ X11->use_xkb = false;
387+ X11->xkb_major = 0;
388+@@ -2124,14 +2147,25 @@ void qt_init(QApplicationPrivate *priv,
389+ #endif // QT_RUNTIME_XINERAMA
390+ #endif // QT_NO_XINERAMA
391+
392+-#ifndef QT_NO_XINPUT
393++#if !defined(QT_NO_XINPUT2)
394++ X11->use_xinput = XQueryExtension(X11->display, "XInputExtension", &X11->xinput_opcode,
395++ &X11->xinput_eventbase, &X11->xinput_errorbase);
396++ if (X11->use_xinput) {
397++ // we want XInput2
398++ int ximajor = 2, ximinor = 1;
399++ if (XIQueryVersion(X11->display, &ximajor, &ximinor) == BadRequest) {
400++ // XInput2 not available
401++ X11->use_xinput = false;
402++ }
403++ }
404++#elif !defined(QT_NO_XINPUT)
405+ // See if Xinput is supported on the connected display
406+ X11->ptrXCloseDevice = 0;
407+ X11->ptrXListInputDevices = 0;
408+ X11->ptrXOpenDevice = 0;
409+ X11->ptrXFreeDeviceList = 0;
410+ X11->ptrXSelectExtensionEvent = 0;
411+- X11->use_xinput = XQueryExtension(X11->display, "XInputExtension", &X11->xinput_major,
412++ X11->use_xinput = XQueryExtension(X11->display, "XInputExtension", &X11->xinput_opcode,
413+ &X11->xinput_eventbase, &X11->xinput_errorbase);
414+ if (X11->use_xinput) {
415+ X11->ptrXCloseDevice = XINPUT_LOAD(XCloseDevice);
416+@@ -3149,6 +3183,8 @@ int QApplication::x11ProcessEvent(XEvent
417+ Q_D(QApplication);
418+ QScopedLoopLevelCounter loopLevelCounter(d->threadData);
419+
420++ bool isXI2Event = false;
421++
422+ #ifdef ALIEN_DEBUG
423+ //qDebug() << "QApplication::x11ProcessEvent:" << event->type;
424+ #endif
425+@@ -3179,6 +3215,16 @@ int QApplication::x11ProcessEvent(XEvent
426+ case SelectionClear:
427+ X11->time = event->xselectionclear.time;
428+ break;
429++#if !defined(QT_NO_XINPUT2)
430++ case GenericEvent:
431++ if (X11->use_xinput
432++ && XGetEventData(X11->display, &event->xcookie)
433++ && event->xcookie.extension == X11->xinput_opcode) {
434++ // remember for later
435++ isXI2Event = true;
436++ }
437++ break;
438++#endif
439+ default:
440+ break;
441+ }
442+@@ -3190,7 +3236,43 @@ int QApplication::x11ProcessEvent(XEvent
443+ }
444+ #endif
445+
446+- QETWidget *widget = (QETWidget*)QWidget::find((WId)event->xany.window);
447++ QETWidget *widget = 0;
448++#if !defined(QT_NO_XINPUT2)
449++ if (isXI2Event) {
450++ // event->xany.window is not usable for these events
451++ // look up widget based on the type of event we received
452++ switch (event->xcookie.evtype) {
453++ case XI_TouchBegin:
454++ case XI_TouchEnd:
455++ case XI_TouchUpdate:
456++ // all of these events send XIDeviceEvents
457++ widget = (QETWidget *) QWidget::find(((XIDeviceEvent *) event->xcookie.data)->event);
458++ break;
459++ default:
460++ break;
461++ }
462++ } else
463++#endif // !defined(QT_NO_XINPUT2)
464++ {
465++ widget = (QETWidget*)QWidget::find((WId)event->xany.window);
466++ }
467++
468++#if !defined(QT_NO_XINPUT2)
469++ // make sure XFreeEventData() is called at every return point
470++ class CallXFreeEventData
471++ {
472++ Display *display;
473++ XGenericEventCookie *cookie;
474++ public:
475++ CallXFreeEventData(Display *display, XGenericEventCookie *cookie)
476++ : display(display), cookie(cookie)
477++ { }
478++ ~CallXFreeEventData()
479++ {
480++ XFreeEventData(display, cookie);
481++ }
482++ } instance(X11->display, &event->xcookie);
483++#endif
484+
485+ if (wPRmapper) { // just did a widget reparent?
486+ if (widget == 0) { // not in std widget mapper
487+@@ -3202,6 +3284,15 @@ int QApplication::x11ProcessEvent(XEvent
488+ case XKeyRelease:
489+ widget = qPRFindWidget(event->xany.window);
490+ break;
491++#if !defined(QT_NO_XINPUT2)
492++ case GenericEvent:
493++ // as above, event->xany.window is unusable for these events
494++ if (isXI2Event) {
495++ widget = qPRFindWidget(((XIDeviceEvent *) event->xcookie.data)->event);
496++ break;
497++ }
498++ break;
499++#endif
500+ }
501+ }
502+ else if (widget->testAttribute(Qt::WA_WState_Reparented))
503+@@ -3836,6 +3927,10 @@ int QApplication::x11ProcessEvent(XEvent
504+ }
505+ break;
506+
507++ case GenericEvent:
508++ if (isXI2Event)
509++ widget->translateXI2Event((XIEvent *)event->xcookie.data);
510++ break;
511+ default:
512+ break;
513+ }
514+@@ -5058,6 +5153,184 @@ bool QETWidget::translatePropertyEvent(c
515+ return true;
516+ }
517+
518++#if !defined(QT_NO_XINPUT2)
519++bool QETWidget::translateXI2Event(const XIEvent *event)
520++{
521++ const XIDeviceEvent *dev = (const XIDeviceEvent *)event;
522++ QApplicationPrivate *qAppPriv = QApplicationPrivate::instance();
523++ const QApplicationPrivate::TouchDeviceInfo &tdi = qAppPriv->touchDevices[dev->sourceid];
524++ const int trackingId = dev->detail;
525++ QTouchEvent::TouchPoint *tp = 0;
526++ Qt::TouchPointStates primary = Qt::TouchPointPrimary;
527++
528++ if (!(dev->flags & XIPointerEmulated))
529++ primary = (Qt::TouchPointStates)0;
530++
531++ switch (event->evtype) {
532++ case XI_TouchBegin: {
533++ Q_ASSERT(qAppPriv->touchDevices.contains(dev->sourceid));
534++
535++ QWidget *w = childAt(QPoint(dev->event_x, dev->event_y));
536++ if (!w)
537++ break;
538++
539++ if (tdi.directTouch) {
540++ qAppPriv->appTouchPoints.append(QTouchEvent::TouchPoint(trackingId));
541++ tp = &qAppPriv->appTouchPoints.last();
542++ } else {
543++ // touch pad
544++ if (qAppPriv->appTouchPoints.isEmpty()) {
545++ if (!w->testAttribute(Qt::WA_TouchPadAcceptSingleTouchEvents)) {
546++ if (qAppPriv->unsentAppTouchPoint.id() == -1) {
547++ // do not send first TouchBegin from touchpad to a widget
548++ qAppPriv->unsentAppTouchPoint = QTouchEvent::TouchPoint(trackingId);
549++ tp = &qAppPriv->unsentAppTouchPoint;
550++ } else {
551++ // second touch on a touchpad
552++ qAppPriv->unsentAppTouchPoint.setState(Qt::TouchPointPressed | primary);
553++ qAppPriv->appTouchPoints.append(qAppPriv->unsentAppTouchPoint);
554++ qAppPriv->unsentAppTouchPoint = QTouchEvent::TouchPoint();
555++ }
556++ }
557++ }
558++ }
559++ if (!tp) {
560++ qAppPriv->appTouchPoints.append(QTouchEvent::TouchPoint(trackingId));
561++ tp = &qAppPriv->appTouchPoints.last();
562++ }
563++ break;
564++ }
565++
566++ case XI_TouchEnd:
567++ case XI_TouchUpdate: {
568++ Q_ASSERT(qAppPriv->touchDevices.contains(dev->sourceid));
569++
570++ // find the touchpoint
571++ for (int i = 0; i < qAppPriv->appTouchPoints.size(); ++i) {
572++ QTouchEvent::TouchPoint &touchPoint = qAppPriv->appTouchPoints[i];
573++ if (touchPoint.id() == trackingId)
574++ tp = &touchPoint;
575++ else
576++ touchPoint.setState(Qt::TouchPointStationary | primary);
577++ }
578++ if (!tp && qAppPriv->unsentAppTouchPoint.id() == trackingId)
579++ tp = &qAppPriv->unsentAppTouchPoint;
580++ if (!tp) {
581++ qWarning("Got touch without getting TouchBegin for id %d", trackingId);
582++ return false;
583++ }
584++ break;
585++ }
586++ default:
587++ qWarning() << "translateXI2Event: unknown XI2 event:" << event->evtype;
588++ return false;
589++ }
590++
591++ qreal *values = dev->valuators.values;
592++ for (int i = 0; i < qMin(dev->valuators.mask_len * 8, tdi.numValuators); ++i) {
593++ if (XIMaskIsSet(dev->valuators.mask, i)) {
594++ if (tdi.xivPosX.number == i) {
595++ qreal value = (*values++ - tdi.xivPosX.min) / (tdi.xivPosX.max - tdi.xivPosX.min);
596++ qreal screenValue;
597++ if (tdi.directTouch) {
598++ screenValue = dev->root_x;
599++ } else {
600++ if (qAppPriv->appTouchPoints.size() > 1) {
601++ // non-first touch point, make it relative to the first one
602++ const int firstId = qAppPriv->appTouchPoints.first().id();
603++ screenValue = dev->root_x + (value - qAppPriv->touchedPos[firstId].x()) * 300;
604++ if (event->evtype == XI_TouchBegin)
605++ qAppPriv->touchedPos[trackingId].rx() = qAppPriv->touchedPos[firstId].x();
606++ } else {
607++ screenValue = dev->root_x;
608++ if (event->evtype == XI_TouchBegin)
609++ qAppPriv->touchedPos[trackingId].rx() = value;
610++ }
611++ }
612++ tp->d->screenRect.moveCenter(QPointF(screenValue, tp->d->screenRect.center().y()));
613++ tp->d->normalizedPos.setX(value);
614++ } else if (tdi.xivPosY.number == i) {
615++ qreal value = (*values++ - tdi.xivPosY.min) / (tdi.xivPosY.max - tdi.xivPosY.min);
616++ qreal screenValue;
617++ if (tdi.directTouch) {
618++ screenValue = dev->root_y;
619++ } else {
620++ if (qAppPriv->appTouchPoints.size() > 1) {
621++ // non-first touch point, make it relative to the first one
622++ const int firstId = qAppPriv->appTouchPoints.first().id();
623++ screenValue = dev->root_y + (value - qAppPriv->touchedPos[firstId].y()) * 300;
624++ if (event->evtype == XI_TouchBegin)
625++ qAppPriv->touchedPos[trackingId].ry() = qAppPriv->touchedPos[firstId].y();
626++ } else {
627++ screenValue = dev->root_y;
628++ if (event->evtype == XI_TouchBegin)
629++ qAppPriv->touchedPos[trackingId].ry() = value;
630++ }
631++ }
632++ tp->d->screenRect.moveCenter(QPointF(tp->d->screenRect.center().x(), screenValue));
633++ tp->d->normalizedPos.setY(value);
634++ } else if (tdi.xivTouchMajor.number == i) {
635++ qreal value = (*values++ - tdi.xivTouchMajor.min) / (tdi.xivTouchMajor.max - tdi.xivTouchMajor.min);
636++ qAppPriv->touchedSize[trackingId].rheight() = value;
637++ } else if (tdi.xivTouchMinor.number == i) {
638++ qreal value = (*values++ - tdi.xivTouchMinor.min) / (tdi.xivTouchMinor.max - tdi.xivTouchMinor.min);
639++ qAppPriv->touchedSize[trackingId].rwidth() = value;
640++ } else if (tdi.xivOrientation.number == i) {
641++ qreal value = (*values++ - tdi.xivOrientation.min) / (tdi.xivOrientation.max - tdi.xivOrientation.min);
642++ qAppPriv->touchedOrientation[trackingId] = value * M_PI_2;
643++ } else
644++ ++values;
645++ }
646++ }
647++
648++ qreal angle = qAppPriv->touchedOrientation[trackingId];
649++ qreal width = qAppPriv->touchedSize[trackingId].height() * qFabs(qFastSin(angle)) +
650++ qAppPriv->touchedSize[trackingId].width() * qFabs(qFastCos(angle));
651++ qreal height = qAppPriv->touchedSize[trackingId].width() * qFabs(qFastSin(angle)) +
652++ qAppPriv->touchedSize[trackingId].height() * qFabs(qFastCos(angle));
653++ width *= tdi.directTouch ? 500 : 25;
654++ height *= tdi.directTouch ? 500 : 25;
655++ QPointF center = tp->d->screenRect.center();
656++ tp->d->screenRect = QRectF(center.x() - width/2, center.y() - height/2, width, height);
657++
658++ bool send = true;
659++ if (event->evtype == XI_TouchBegin) {
660++ tp->setState(Qt::TouchPointPressed | primary);
661++ if (qAppPriv->appTouchPoints.isEmpty())
662++ send = false;
663++ } else if (event->evtype == XI_TouchUpdate) {
664++ tp->setState(Qt::TouchPointMoved | primary);
665++ QWidget *w = childAt(QPoint(dev->event_x, dev->event_y));
666++ if (!w || (!tdi.directTouch && qAppPriv->appTouchPoints.size() == 1 && !w->testAttribute(Qt::WA_TouchPadAcceptSingleTouchEvents)))
667++ send = false;
668++ } else if (event->evtype == XI_TouchEnd) {
669++ tp->setState(Qt::TouchPointReleased | primary);
670++ if (qAppPriv->appTouchPoints.isEmpty())
671++ send = false;
672++
673++ for (int i = 0; i < qAppPriv->appTouchPoints.size(); ++i) {
674++ if (qAppPriv->appTouchPoints[i].id() == trackingId) {
675++ qAppPriv->appTouchPoints.removeAt(i);
676++ break;
677++ }
678++ }
679++ if (qAppPriv->unsentAppTouchPoint.id() == trackingId)
680++ qAppPriv->unsentAppTouchPoint = QTouchEvent::TouchPoint();
681++ if (qAppPriv->appTouchPoints.isEmpty()) {
682++ qAppPriv->touchedPos.clear();
683++ qAppPriv->touchedSize.clear();
684++ qAppPriv->touchedOrientation.clear();
685++ }
686++ }
687++
688++ if (send) {
689++ qAppPriv->activeDeviceType = tdi.directTouch ? QTouchEvent::TouchScreen : QTouchEvent::TouchPad;
690++ QApplicationPrivate::translateRawTouchEvent(0, qAppPriv->activeDeviceType, qAppPriv->appTouchPoints);
691++ }
692++
693++ return true;
694++}
695++#endif
696+
697+ //
698+ // Paint event translation
699+@@ -6177,11 +6450,61 @@ void QApplicationPrivate::_q_readRX71Mul
700+
701+ #else // !QT_RX71_MULTITOUCH
702+
703++#if !defined(QT_NO_XINPUT2)
704++void QApplicationPrivate::x11GetTouchDeviceInfo()
705++{
706++ int count = 0;
707++ XIDeviceInfo *devices = XIQueryDevice(X11->display, XIAllDevices, &count);
708++ if (devices) {
709++ for (int i = 0; i < count; ++i) {
710++ if (!devices[i].enabled)
711++ continue;
712++ for (int k = 0; k < devices[i].num_classes; ++k) {
713++ XIAnyClassInfo *xiclassinfo = devices[i].classes[k];
714++ if (xiclassinfo->type == XITouchClass) {
715++ XITouchClassInfo *t = (XITouchClassInfo *)xiclassinfo;
716++ QApplicationPrivate::TouchDeviceInfo& tdi = touchDevices[devices[i].deviceid];
717++ tdi.deviceid = devices[i].deviceid;
718++ tdi.directTouch = t->mode == XIDirectTouch;
719++ tdi.maxTouches = t->num_touches;
720++ } else if (xiclassinfo->type == XITouchValuatorClass) {
721++ XITouchValuatorClassInfo *v = (XITouchValuatorClassInfo *)xiclassinfo;
722++ QApplicationPrivate::TouchDeviceInfo &tdi = touchDevices[devices[i].deviceid];
723++ tdi.numValuators++;
724++ if (v->label == ATOM(XAbsMTTouchMajor))
725++ copy(tdi.xivTouchMajor, *v);
726++ else if (v->label == ATOM(XAbsMTTouchMinor))
727++ copy(tdi.xivTouchMinor, *v);
728++ else if (v->label == ATOM(XAbsMTOrientation))
729++ copy(tdi.xivOrientation, *v);
730++ else if (v->label == ATOM(XAbsMTPositionX))
731++ copy(tdi.xivPosX, *v);
732++ else if (v->label == ATOM(XAbsMTPositionY))
733++ copy(tdi.xivPosY, *v);
734++ }
735++ }
736++ }
737++ XIFreeDeviceInfo(devices);
738++ }
739++}
740++
741++void QApplicationPrivate::initializeMultitouch_sys()
742++{
743++ x11GetTouchDeviceInfo();
744++}
745++void QApplicationPrivate::cleanupMultitouch_sys()
746++{
747++}
748++
749++#else
750++
751+ void QApplicationPrivate::initializeMultitouch_sys()
752+ { }
753+ void QApplicationPrivate::cleanupMultitouch_sys()
754+ { }
755+
756++#endif
757++
758+ #endif // QT_RX71_MULTITOUCH
759+
760+ QT_END_NAMESPACE
761+--- a/src/gui/kernel/qevent.h
762++++ b/src/gui/kernel/qevent.h
763+@@ -791,6 +791,7 @@ public:
764+ QTouchEventTouchPointPrivate *d;
765+ friend class QApplication;
766+ friend class QApplicationPrivate;
767++ friend class QETWidget;
768+ };
769+
770+ enum DeviceType {
771+--- a/src/gui/kernel/qt_x11_p.h
772++++ b/src/gui/kernel/qt_x11_p.h
773+@@ -97,13 +97,14 @@
774+ # include <X11/extensions/shape.h>
775+ #endif // QT_NO_SHAPE
776+
777+-
778+-#if !defined (QT_NO_TABLET)
779++#if !defined(QT_NO_XINPUT2)
780++# include <X11/extensions/XInput2.h>
781++#elif !defined (QT_NO_TABLET)
782+ # include <X11/extensions/XInput.h>
783+-#if defined (Q_OS_IRIX)
784+-# include <X11/extensions/SGIMisc.h>
785+-# include <wacom.h>
786+-#endif
787++# if defined (Q_OS_IRIX)
788++# include <X11/extensions/SGIMisc.h>
789++# include <wacom.h>
790++# endif
791+ #endif // QT_NO_TABLET
792+
793+
794+@@ -433,11 +434,15 @@ struct QX11Data
795+ bool use_mitshm_pixmaps;
796+ int mitshm_major;
797+
798+- // true if Qt is compiled w/ Tablet support and we have a tablet.
799++ // true if Qt is compiled w/ XInput2 or Tablet support and we have a tablet.
800+ bool use_xinput;
801+- int xinput_major;
802++ int xinput_opcode;
803+ int xinput_eventbase;
804+ int xinput_errorbase;
805++#if !defined(QT_NO_XINPUT2)
806++ XIDeviceInfo *xideviceinfo;
807++ XITouchClassInfo *xitouchclassinfo;
808++#endif
809+
810+ // for XKEYBOARD support
811+ bool use_xkb;
812+@@ -683,6 +688,12 @@ struct QX11Data
813+ XTabletStylus,
814+ XTabletEraser,
815+
816++ XAbsMTTouchMajor,
817++ XAbsMTTouchMinor,
818++ XAbsMTOrientation,
819++ XAbsMTPositionX,
820++ XAbsMTPositionY,
821++
822+ NPredefinedAtoms,
823+
824+ _QT_SETTINGS_TIMESTAMP = NPredefinedAtoms,
825+--- a/src/gui/kernel/qwidget.cpp
826++++ b/src/gui/kernel/qwidget.cpp
827+@@ -10737,7 +10737,7 @@ void QWidget::setAttribute(Qt::WidgetAtt
828+
829+ break;
830+ case Qt::WA_AcceptTouchEvents:
831+-#if defined(Q_WS_WIN) || defined(Q_WS_MAC) || defined(Q_OS_SYMBIAN)
832++#if defined(Q_WS_WIN) || defined(Q_WS_MAC) || defined(Q_OS_SYMBIAN) || defined(Q_WS_X11)
833+ if (on)
834+ d->registerTouchWindow();
835+ #endif
836+--- a/src/gui/kernel/qwidget_p.h
837++++ b/src/gui/kernel/qwidget_p.h
838+@@ -667,6 +667,8 @@ public:
839+
840+ inline QRect mapFromWS(const QRect &r) const
841+ { QRect rr(r); rr.translate(data.wrect.topLeft()); return rr; }
842++
843++ void registerTouchWindow();
844+ #endif
845+
846+ // Variables.
847+@@ -776,7 +778,6 @@ public:
848+ void unregisterOleDnd(QWidget *widget, QOleDropTarget *target);
849+ #endif
850+ void grabMouseWhileInWindow();
851+- void registerTouchWindow();
852+ void winSetupGestures();
853+ #elif defined(Q_WS_MAC) // <--------------------------------------------------------- MAC
854+ // This is new stuff
855+@@ -852,7 +853,6 @@ public:
856+ static OSStatus qt_window_event(EventHandlerCallRef er, EventRef event, void *);
857+ static OSStatus qt_widget_event(EventHandlerCallRef er, EventRef event, void *);
858+ static bool qt_widget_rgn(QWidget *, short, RgnHandle, bool);
859+- void registerTouchWindow();
860+ #elif defined(Q_WS_QWS) // <--------------------------------------------------------- QWS
861+ void setMaxWindowState_helper();
862+ void setFullScreenSize_helper();
863+@@ -872,7 +872,6 @@ public:
864+ static QWidget *keyboardGrabber;
865+ void s60UpdateIsOpaque();
866+ void reparentChildren();
867+- void registerTouchWindow();
868+ #endif
869+
870+ };
871+--- a/src/gui/kernel/qwidget_x11.cpp
872++++ b/src/gui/kernel/qwidget_x11.cpp
873+@@ -871,7 +871,13 @@ void QWidgetPrivate::create_sys(WId wind
874+ // else
875+ XSelectInput(dpy, id, stdDesktopEventMask);
876+ } else if (q->internalWinId()) {
877+- XSelectInput(dpy, id, stdWidgetEventMask);
878++ uint eventmask = stdWidgetEventMask;
879++
880++ if (q->testAttribute(Qt::WA_AcceptTouchEvents))
881++ registerTouchWindow();
882++
883++ XSelectInput(dpy, id, eventmask);
884++
885+ #if !defined (QT_NO_TABLET)
886+ QTabletDeviceDataList *tablet_list = qt_tablet_devices();
887+ if (X11->ptrXSelectExtensionEvent) {
888+@@ -938,6 +944,9 @@ void QWidgetPrivate::create_sys(WId wind
889+ surface->flush(q, q->rect(), q->mapTo(surface->window(), QPoint()));
890+ }
891+
892++ if (q->testAttribute(Qt::WA_AcceptTouchEvents))
893++ registerTouchWindow();
894++
895+ #ifdef ALIEN_DEBUG
896+ qDebug() << "QWidgetPrivate::create_sys END:" << q;
897+ #endif
898+@@ -3099,4 +3108,32 @@ void QWidgetPrivate::updateX11AcceptFocu
899+ XFree((char *)h);
900+ }
901+
902++void QWidgetPrivate::registerTouchWindow()
903++{
904++#if !defined(QT_NO_XINPUT2)
905++ Q_Q(QWidget);
906++
907++ if (!q->testAttribute(Qt::WA_WState_Created) || q->windowType() == Qt::Desktop)
908++ return;
909++
910++ if (X11->use_xinput) {
911++ XIEventMask xieventmask;
912++
913++ const int mask_len = XIMaskLen(XI_LASTEVENT);
914++ QVector<uchar> mask_vector(mask_len, 0);
915++ uchar *bitmask = mask_vector.data();
916++
917++ xieventmask.deviceid = XIAllDevices;
918++ xieventmask.mask = bitmask;
919++ xieventmask.mask_len = mask_len;
920++
921++ XISetMask(bitmask, XI_TouchBegin);
922++ XISetMask(bitmask, XI_TouchEnd);
923++ XISetMask(bitmask, XI_TouchUpdate);
924++
925++ XISelectEvents(X11->display, q->effectiveWinId(), &xieventmask, 1);
926++ }
927++#endif
928++}
929++
930+ QT_END_NAMESPACE
931
932=== modified file 'debian/patches/series'
933--- debian/patches/series 2011-01-18 20:37:32 +0000
934+++ debian/patches/series 2011-02-23 16:43:58 +0000
935@@ -48,3 +48,6 @@
936 kubuntu_25_qsortfilterproxymodel.diff
937 kubuntu_26_dbusconnection_pointer.diff
938 kubuntu_27_dbus_signal_filter_passes_not_handled.diff
939+
940+# XI 2.1 multitouch support
941+200_xi2.1.patch

Subscribers

People subscribed via source and target branches