|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the QtGui module of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 #include "qmousetslib_qws.h" |
|
43 |
|
44 #if !defined(QT_NO_QWS_MOUSE_TSLIB) || defined(QT_PLUGIN) |
|
45 |
|
46 #include <QtCore/qregexp.h> |
|
47 #include <QtCore/qstringlist.h> |
|
48 #include "qsocketnotifier.h" |
|
49 #include "qscreen_qws.h" |
|
50 |
|
51 #include <tslib.h> |
|
52 #include <errno.h> |
|
53 |
|
54 QT_BEGIN_NAMESPACE |
|
55 |
|
56 #ifdef TSLIBMOUSEHANDLER_DEBUG |
|
57 # include <QtCore/QDebug> |
|
58 #endif |
|
59 |
|
60 /*! |
|
61 \internal |
|
62 |
|
63 \class QWSTslibMouseHandler |
|
64 \ingroup qws |
|
65 |
|
66 \brief The QWSTslibMouseHandler class implements a mouse driver |
|
67 for the Universal Touch Screen Library, tslib. |
|
68 |
|
69 QWSTslibMouseHandler inherits the QWSCalibratedMouseHandler class, |
|
70 providing calibration and noise reduction functionality in |
|
71 addition to generating mouse events, for devices using the |
|
72 Universal Touch Screen Library. |
|
73 |
|
74 To be able to compile this mouse handler, \l{Qt for Embedded Linux} |
|
75 must be configured with the \c -qt-mouse-tslib option, see the |
|
76 \l{Pointer Handling} documentation for details. In addition, the tslib |
|
77 headers and library must be present in the build environment. The |
|
78 tslib sources can be downloaded from \l |
|
79 {http://tslib.berlios.de/}. Use the \c -L and \c -I options |
|
80 with \c configure to explicitly specify the location of the |
|
81 library and its headers: |
|
82 |
|
83 \snippet doc/src/snippets/code/src_gui_embedded_qmousetslib_qws.cpp 0 |
|
84 |
|
85 In order to use this mouse handler, tslib must also be correctly |
|
86 installed on the target machine. This includes providing a \c |
|
87 ts.conf configuration file and setting the necessary environment |
|
88 variables, see the README file provided with tslib for details. |
|
89 |
|
90 The ts.conf file will usually contain the following two lines |
|
91 |
|
92 \snippet doc/src/snippets/code/src_gui_embedded_qmousetslib_qws.cpp 1 |
|
93 |
|
94 To make \l{Qt for Embedded Linux} explicitly choose the tslib mouse |
|
95 handler, set the QWS_MOUSE_PROTO environment variable. |
|
96 |
|
97 \sa {Pointer Handling}, {Qt for Embedded Linux} |
|
98 */ |
|
99 |
|
100 class QWSTslibMouseHandlerPrivate : public QObject |
|
101 { |
|
102 Q_OBJECT |
|
103 public: |
|
104 QWSTslibMouseHandlerPrivate(QWSTslibMouseHandler *h, |
|
105 const QString &device); |
|
106 ~QWSTslibMouseHandlerPrivate(); |
|
107 |
|
108 void suspend(); |
|
109 void resume(); |
|
110 |
|
111 void calibrate(const QWSPointerCalibrationData *data); |
|
112 void clearCalibration(); |
|
113 |
|
114 private: |
|
115 QWSTslibMouseHandler *handler; |
|
116 struct tsdev *dev; |
|
117 QSocketNotifier *mouseNotifier; |
|
118 int jitter_limit; |
|
119 |
|
120 struct ts_sample lastSample; |
|
121 bool wasPressed; |
|
122 int lastdx; |
|
123 int lastdy; |
|
124 |
|
125 bool calibrated; |
|
126 QString devName; |
|
127 |
|
128 bool open(); |
|
129 void close(); |
|
130 inline bool get_sample(struct ts_sample *sample); |
|
131 |
|
132 private slots: |
|
133 void readMouseData(); |
|
134 }; |
|
135 |
|
136 QWSTslibMouseHandlerPrivate::QWSTslibMouseHandlerPrivate(QWSTslibMouseHandler *h, |
|
137 const QString &device) |
|
138 : handler(h), dev(0), mouseNotifier(0), jitter_limit(3) |
|
139 { |
|
140 QStringList args = device.split(QLatin1Char(':'), QString::SkipEmptyParts); |
|
141 QRegExp jitterRegex(QLatin1String("^jitter_limit=(\\d+)$")); |
|
142 int index = args.indexOf(jitterRegex); |
|
143 if (index >= 0) { |
|
144 jitter_limit = jitterRegex.cap(1).toInt(); |
|
145 args.removeAt(index); |
|
146 } |
|
147 |
|
148 devName = args.join(QString()); |
|
149 |
|
150 if (devName.isNull()) { |
|
151 const char *str = getenv("TSLIB_TSDEVICE"); |
|
152 if (str) |
|
153 devName = QString::fromLocal8Bit(str); |
|
154 } |
|
155 |
|
156 if (devName.isNull()) |
|
157 devName = QLatin1String("/dev/ts"); |
|
158 |
|
159 if (!open()) |
|
160 return; |
|
161 |
|
162 calibrated = true; |
|
163 |
|
164 int fd = ts_fd(dev); |
|
165 mouseNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, this); |
|
166 connect(mouseNotifier, SIGNAL(activated(int)),this, SLOT(readMouseData())); |
|
167 resume(); |
|
168 } |
|
169 |
|
170 QWSTslibMouseHandlerPrivate::~QWSTslibMouseHandlerPrivate() |
|
171 { |
|
172 close(); |
|
173 } |
|
174 |
|
175 bool QWSTslibMouseHandlerPrivate::open() |
|
176 { |
|
177 dev = ts_open(devName.toLocal8Bit().constData(), 1); |
|
178 if (!dev) { |
|
179 qCritical("QWSTslibMouseHandlerPrivate: ts_open() failed" |
|
180 " with error: '%s'", strerror(errno)); |
|
181 qCritical("Please check your tslib installation!"); |
|
182 return false; |
|
183 } |
|
184 |
|
185 if (ts_config(dev)) { |
|
186 qCritical("QWSTslibMouseHandlerPrivate: ts_config() failed" |
|
187 " with error: '%s'", strerror(errno)); |
|
188 qCritical("Please check your tslib installation!"); |
|
189 close(); |
|
190 return false; |
|
191 } |
|
192 |
|
193 return true; |
|
194 } |
|
195 |
|
196 void QWSTslibMouseHandlerPrivate::close() |
|
197 { |
|
198 if (dev) |
|
199 ts_close(dev); |
|
200 } |
|
201 |
|
202 void QWSTslibMouseHandlerPrivate::suspend() |
|
203 { |
|
204 if (mouseNotifier) |
|
205 mouseNotifier->setEnabled(false); |
|
206 } |
|
207 |
|
208 void QWSTslibMouseHandlerPrivate::resume() |
|
209 { |
|
210 memset(&lastSample, 0, sizeof(lastSample)); |
|
211 wasPressed = false; |
|
212 lastdx = 0; |
|
213 lastdy = 0; |
|
214 if (mouseNotifier) |
|
215 mouseNotifier->setEnabled(true); |
|
216 } |
|
217 |
|
218 bool QWSTslibMouseHandlerPrivate::get_sample(struct ts_sample *sample) |
|
219 { |
|
220 if (!calibrated) |
|
221 return (ts_read_raw(dev, sample, 1) == 1); |
|
222 |
|
223 return (ts_read(dev, sample, 1) == 1); |
|
224 } |
|
225 |
|
226 void QWSTslibMouseHandlerPrivate::readMouseData() |
|
227 { |
|
228 if (!qt_screen) |
|
229 return; |
|
230 |
|
231 for(;;) { |
|
232 struct ts_sample sample = lastSample; |
|
233 bool pressed = wasPressed; |
|
234 |
|
235 // Fast return if there's no events. |
|
236 if (!get_sample(&sample)) |
|
237 return; |
|
238 pressed = (sample.pressure > 0); |
|
239 |
|
240 // Only return last sample unless there's a press/release event. |
|
241 while (pressed == wasPressed) { |
|
242 if (!get_sample(&sample)) |
|
243 break; |
|
244 pressed = (sample.pressure > 0); |
|
245 } |
|
246 |
|
247 // work around missing coordinates on mouse release in raw mode |
|
248 if (!calibrated && !pressed && sample.x == 0 && sample.y == 0) { |
|
249 sample.x = lastSample.x; |
|
250 sample.y = lastSample.y; |
|
251 } |
|
252 |
|
253 int dx = sample.x - lastSample.x; |
|
254 int dy = sample.y - lastSample.y; |
|
255 |
|
256 // Remove small movements in oppsite direction |
|
257 if (dx * lastdx < 0 && qAbs(dx) < jitter_limit) { |
|
258 sample.x = lastSample.x; |
|
259 dx = 0; |
|
260 } |
|
261 if (dy * lastdy < 0 && qAbs(dy) < jitter_limit) { |
|
262 sample.y = lastSample.y; |
|
263 dy = 0; |
|
264 } |
|
265 |
|
266 if (wasPressed == pressed && dx == 0 && dy == 0) |
|
267 return; |
|
268 |
|
269 #ifdef TSLIBMOUSEHANDLER_DEBUG |
|
270 qDebug() << "last" << QPoint(lastSample.x, lastSample.y) |
|
271 << "curr" << QPoint(sample.x, sample.y) |
|
272 << "dx,dy" << QPoint(dx, dy) |
|
273 << "ddx,ddy" << QPoint(dx*lastdx, dy*lastdy) |
|
274 << "pressed" << wasPressed << pressed; |
|
275 #endif |
|
276 |
|
277 lastSample = sample; |
|
278 wasPressed = pressed; |
|
279 if (dx != 0) |
|
280 lastdx = dx; |
|
281 if (dy != 0) |
|
282 lastdy = dy; |
|
283 |
|
284 const QPoint p(sample.x, sample.y); |
|
285 if (calibrated) { |
|
286 // tslib should do all the translation and filtering, so we send a |
|
287 // "raw" mouse event |
|
288 handler->QWSMouseHandler::mouseChanged(p, pressed); |
|
289 } else { |
|
290 handler->sendFiltered(p, pressed); |
|
291 } |
|
292 } |
|
293 } |
|
294 |
|
295 void QWSTslibMouseHandlerPrivate::clearCalibration() |
|
296 { |
|
297 suspend(); |
|
298 close(); |
|
299 handler->QWSCalibratedMouseHandler::clearCalibration(); |
|
300 calibrated = false; |
|
301 open(); |
|
302 resume(); |
|
303 } |
|
304 |
|
305 void QWSTslibMouseHandlerPrivate::calibrate(const QWSPointerCalibrationData *data) |
|
306 { |
|
307 suspend(); |
|
308 close(); |
|
309 // default implementation writes to /etc/pointercal |
|
310 // using the same format as the tslib linear module. |
|
311 handler->QWSCalibratedMouseHandler::calibrate(data); |
|
312 calibrated = true; |
|
313 open(); |
|
314 resume(); |
|
315 } |
|
316 |
|
317 /*! |
|
318 \internal |
|
319 */ |
|
320 QWSTslibMouseHandler::QWSTslibMouseHandler(const QString &driver, |
|
321 const QString &device) |
|
322 : QWSCalibratedMouseHandler(driver, device) |
|
323 { |
|
324 d = new QWSTslibMouseHandlerPrivate(this, device); |
|
325 } |
|
326 |
|
327 /*! |
|
328 \internal |
|
329 */ |
|
330 QWSTslibMouseHandler::~QWSTslibMouseHandler() |
|
331 { |
|
332 delete d; |
|
333 } |
|
334 |
|
335 /*! |
|
336 \reimp |
|
337 */ |
|
338 void QWSTslibMouseHandler::suspend() |
|
339 { |
|
340 d->suspend(); |
|
341 } |
|
342 |
|
343 /*! |
|
344 \reimp |
|
345 */ |
|
346 void QWSTslibMouseHandler::resume() |
|
347 { |
|
348 d->resume(); |
|
349 } |
|
350 |
|
351 /*! |
|
352 \reimp |
|
353 */ |
|
354 void QWSTslibMouseHandler::clearCalibration() |
|
355 { |
|
356 d->clearCalibration(); |
|
357 } |
|
358 |
|
359 /*! |
|
360 \reimp |
|
361 */ |
|
362 void QWSTslibMouseHandler::calibrate(const QWSPointerCalibrationData *data) |
|
363 { |
|
364 d->calibrate(data); |
|
365 } |
|
366 |
|
367 QT_END_NAMESPACE |
|
368 |
|
369 #include "qmousetslib_qws.moc" |
|
370 |
|
371 #endif //QT_NO_QWS_MOUSE_TSLIB |