|
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 "qmouse_qws.h" |
|
43 #include "qwindowsystem_qws.h" |
|
44 #include "qscreen_qws.h" |
|
45 #include "qapplication.h" |
|
46 #include "qtextstream.h" |
|
47 #include "qfile.h" |
|
48 #include "qdebug.h" |
|
49 #include "qscreen_qws.h" |
|
50 |
|
51 QT_BEGIN_NAMESPACE |
|
52 |
|
53 /*! |
|
54 \class QWSPointerCalibrationData |
|
55 \ingroup qws |
|
56 |
|
57 \brief The QWSPointerCalibrationData class is a container for |
|
58 mouse calibration data in Qt for Embedded Linux. |
|
59 |
|
60 Note that this class is only available in \l{Qt for Embedded Linux}. |
|
61 |
|
62 QWSPointerCalibrationData stores device and screen coordinates in |
|
63 the devPoints and screenPoints variables, respectively. |
|
64 |
|
65 A calibration program should create a QWSPointerCalibrationData |
|
66 object, fill the devPoints and screenPoints variables with its |
|
67 device and screen coordinates, and pass the object to the mouse |
|
68 driver using the QWSMouseHandler::calibrate() function. |
|
69 |
|
70 \sa QWSCalibratedMouseHandler, {Mouse Calibration Example} |
|
71 */ |
|
72 |
|
73 /*! |
|
74 \variable QWSPointerCalibrationData::devPoints |
|
75 \brief the raw device coordinates for each value of the Location enum. |
|
76 */ |
|
77 |
|
78 /*! |
|
79 \variable QWSPointerCalibrationData::screenPoints |
|
80 \brief the logical screen coordinates for each value of the Location enum. |
|
81 */ |
|
82 |
|
83 /*! |
|
84 \enum QWSPointerCalibrationData::Location |
|
85 |
|
86 This enum describes the various logical positions that can be |
|
87 specified by the devPoints and screenPoints variables. |
|
88 |
|
89 \value TopLeft Index of the top left corner of the screen. |
|
90 \value BottomLeft Index of the bottom left corner of the screen. |
|
91 \value BottomRight Index of the bottom right corner of the screen. |
|
92 \value TopRight Index of the top right corner of the screen. |
|
93 \value Center Index of the center of the screen. |
|
94 \value LastLocation Last index in the pointer arrays. |
|
95 */ |
|
96 |
|
97 class QWSMouseHandlerPrivate |
|
98 { |
|
99 public: |
|
100 QWSMouseHandlerPrivate() : screen(qt_screen) {} |
|
101 |
|
102 const QScreen *screen; |
|
103 }; |
|
104 |
|
105 /*! |
|
106 \class QWSMouseHandler |
|
107 \ingroup qws |
|
108 |
|
109 \brief The QWSMouseHandler class is a base class for mouse drivers in |
|
110 Qt for Embedded Linux. |
|
111 |
|
112 Note that this class is only available in \l{Qt for Embedded Linux}. |
|
113 |
|
114 \l{Qt for Embedded Linux} provides ready-made drivers for several mouse |
|
115 protocols, see the \l{Qt for Embedded Linux Pointer Handling}{pointer |
|
116 handling} documentation for details. Custom mouse drivers can be |
|
117 implemented by subclassing the QWSMouseHandler class and creating |
|
118 a mouse driver plugin (derived from QMouseDriverPlugin). |
|
119 The default implementation of the QMouseDriverFactory class |
|
120 will automatically detect the plugin, and load the driver into the |
|
121 server application at run-time using Qt's \l {How to Create Qt |
|
122 Plugins}{plugin system}. |
|
123 |
|
124 The mouse driver receives mouse events from the system device and |
|
125 encapsulates each event with an instance of the QWSEvent class |
|
126 which it then passes to the server application (the server is |
|
127 responsible for propagating the event to the appropriate |
|
128 client). To receive mouse events, a QWSMouseHandler object will |
|
129 usually create a QSocketNotifier object for the given device. The |
|
130 QSocketNotifier class provides support for monitoring activity on |
|
131 a file descriptor. When the socket notifier receives data, it will |
|
132 call the mouse driver's mouseChanged() function to send the event |
|
133 to the \l{Qt for Embedded Linux} server application for relaying to |
|
134 clients. |
|
135 |
|
136 If you are creating a driver for a device that needs calibration |
|
137 or noise reduction, such as a touchscreen, use the |
|
138 QWSCalibratedMouseHandler subclass instead to take advantage of |
|
139 the calibrate() and clearCalibration() functions. The \l |
|
140 {qws/mousecalibration}{Mouse Calibration} |
|
141 demonstrates how to write a simple program using the mechanisms |
|
142 provided by the QWSMouseHandler class to calibrate a mouse driver. |
|
143 |
|
144 Note that when deriving from the QWSMouseHandler class, the |
|
145 resume() and suspend() functions must be reimplemented to control |
|
146 the flow of mouse input, i.e., the default implementation does |
|
147 nothing. Reimplementations of these functions typically call the |
|
148 QSocketNotifier::setEnabled() function to enable or disable the |
|
149 socket notifier, respectively. |
|
150 |
|
151 In addition, QWSMouseHandler provides the setScreen() function |
|
152 that allows you to specify a screen for your mouse driver and the |
|
153 limitToScreen() function that ensures that a given position is |
|
154 within this screen's boundaries (changing the position if |
|
155 necessary). Finally, QWSMouseHandler provides the pos() function |
|
156 returning the current mouse position. |
|
157 |
|
158 \sa QMouseDriverPlugin, QMouseDriverFactory, {Qt for Embedded Linux Pointer |
|
159 Handling} |
|
160 */ |
|
161 |
|
162 |
|
163 /*! |
|
164 \fn void QWSMouseHandler::suspend() |
|
165 |
|
166 Implement this function to suspend reading and handling of mouse |
|
167 events, e.g., call the QSocketNotifier::setEnabled() function to |
|
168 disable the socket notifier. |
|
169 |
|
170 \sa resume() |
|
171 */ |
|
172 |
|
173 /*! |
|
174 \fn void QWSMouseHandler::resume() |
|
175 |
|
176 Implement this function to resume reading and handling mouse |
|
177 events, e.g., call the QSocketNotifier::setEnabled() function to |
|
178 enable the socket notifier. |
|
179 |
|
180 \sa suspend() |
|
181 */ |
|
182 |
|
183 /*! |
|
184 \fn const QPoint &QWSMouseHandler::pos() const |
|
185 |
|
186 Returns the current mouse position. |
|
187 |
|
188 \sa mouseChanged(), limitToScreen() |
|
189 */ |
|
190 |
|
191 /*! |
|
192 Constructs a mouse driver. The \a driver and \a device arguments |
|
193 are passed by the QWS_MOUSE_PROTO environment variable. |
|
194 |
|
195 Call the QWSServer::setMouseHandler() function to make the newly |
|
196 created mouse driver, the primary driver. Note that the primary |
|
197 driver is controlled by the system, i.e., the system will delete |
|
198 it upon exit. |
|
199 */ |
|
200 QWSMouseHandler::QWSMouseHandler(const QString &, const QString &) |
|
201 : mousePos(QWSServer::mousePosition), d_ptr(new QWSMouseHandlerPrivate) |
|
202 { |
|
203 } |
|
204 |
|
205 /*! |
|
206 Destroys this mouse driver. |
|
207 |
|
208 Do not call this function if this driver is the primary mouse |
|
209 driver, i.e., if QWSServer::setMouseHandler() function has been |
|
210 called passing this driver as argument. The primary mouse |
|
211 driver is deleted by the system. |
|
212 */ |
|
213 QWSMouseHandler::~QWSMouseHandler() |
|
214 { |
|
215 delete d_ptr; |
|
216 } |
|
217 |
|
218 /*! |
|
219 Ensures that the given \a position is within the screen's |
|
220 boundaries, changing the \a position if necessary. |
|
221 |
|
222 \sa pos(), setScreen() |
|
223 */ |
|
224 |
|
225 void QWSMouseHandler::limitToScreen(QPoint &position) |
|
226 { |
|
227 position.setX(qMin(d_ptr->screen->deviceWidth() - 1, qMax(0, position.x()))); |
|
228 position.setY(qMin(d_ptr->screen->deviceHeight() - 1, qMax(0, position.y()))); |
|
229 } |
|
230 |
|
231 /*! |
|
232 \since 4.2 |
|
233 |
|
234 Sets the screen for this mouse driver to be the given \a screen. |
|
235 |
|
236 \sa limitToScreen() |
|
237 */ |
|
238 void QWSMouseHandler::setScreen(const QScreen *screen) |
|
239 { |
|
240 d_ptr->screen = (screen ? screen : qt_screen); |
|
241 } |
|
242 |
|
243 /*! |
|
244 Notifies the system of a new mouse event. |
|
245 |
|
246 This function updates the current mouse position and sends the |
|
247 event to the \l{Qt for Embedded Linux} server application for |
|
248 delivery to the correct widget. Note that a custom mouse driver must call |
|
249 this function whenever it wants to deliver a new mouse event. |
|
250 |
|
251 The given \a position is the global position of the mouse cursor. |
|
252 The \a state parameter is a bitmask of the Qt::MouseButton enum's |
|
253 values, indicating which mouse buttons are pressed. The \a wheel |
|
254 parameter is the delta value of the mouse wheel as returned by |
|
255 QWheelEvent::delta(). |
|
256 |
|
257 \sa pos() |
|
258 */ |
|
259 void QWSMouseHandler::mouseChanged(const QPoint &position, int state, int wheel) |
|
260 { |
|
261 mousePos = position + d_ptr->screen->offset(); |
|
262 QWSServer::sendMouseEvent(mousePos, state, wheel); |
|
263 } |
|
264 |
|
265 /*! |
|
266 \fn QWSMouseHandler::clearCalibration() |
|
267 |
|
268 This virtual function allows subclasses of QWSMouseHandler to |
|
269 clear the calibration information. Note that the default |
|
270 implementation does nothing. |
|
271 |
|
272 \sa QWSCalibratedMouseHandler::clearCalibration(), calibrate() |
|
273 */ |
|
274 |
|
275 /*! |
|
276 \fn QWSMouseHandler::calibrate(const QWSPointerCalibrationData *data) |
|
277 |
|
278 This virtual function allows subclasses of QWSMouseHandler to set |
|
279 the calibration information passed in the given \a data. Note that |
|
280 the default implementation does nothing. |
|
281 |
|
282 \sa QWSCalibratedMouseHandler::calibrate(), clearCalibration() |
|
283 */ |
|
284 |
|
285 /*! \fn QWSMouseHandler::getCalibration(QWSPointerCalibrationData *data) const |
|
286 This virtual function allows subclasses of QWSMouseHandler |
|
287 to fill in the device coordinates in \a data with values |
|
288 that correspond to screen coordinates that are already in |
|
289 \a data. Note that the default implementation does nothing. |
|
290 */ |
|
291 |
|
292 /*! |
|
293 \class QWSCalibratedMouseHandler |
|
294 \ingroup qws |
|
295 |
|
296 \brief The QWSCalibratedMouseHandler class provides mouse |
|
297 calibration and noise reduction in Qt for Embedded Linux. |
|
298 |
|
299 Note that this class is only available in \l{Qt for Embedded Linux}. |
|
300 |
|
301 \l{Qt for Embedded Linux} provides ready-made drivers for several mouse |
|
302 protocols, see the \l{Qt for Embedded Linux Pointer Handling}{pointer |
|
303 handling} documentation for details. In general, custom mouse |
|
304 drivers can be implemented by subclassing the QWSMouseHandler |
|
305 class. But when the system device does not have a fixed mapping |
|
306 between device and screen coordinates and/or produces noisy events |
|
307 (e.g., a touchscreen), you should derive from the |
|
308 QWSCalibratedMouseHandler class instead to take advantage of its |
|
309 calibration functionality. As always, you must also create a mouse |
|
310 driver plugin (derived from QMouseDriverPlugin); |
|
311 the implementation of the QMouseDriverFactory class will then |
|
312 automatically detect the plugin, and load the driver into the |
|
313 server application at run-time using Qt's |
|
314 \l{How to Create Qt Plugins}{plugin system}. |
|
315 |
|
316 QWSCalibratedMouseHandler provides an implementation of the |
|
317 calibrate() function to update the calibration parameters based on |
|
318 coordinate mapping of the given calibration data. The calibration |
|
319 data is represented by an QWSPointerCalibrationData object. The |
|
320 linear transformation between device coordinates and screen |
|
321 coordinates is performed by calling the transform() function |
|
322 explicitly on the points passed to the |
|
323 QWSMouseHandler::mouseChanged() function. Use the |
|
324 clearCalibration() function to make the mouse driver return mouse |
|
325 events in raw device coordinates and not in screen coordinates. |
|
326 |
|
327 The calibration parameters are recalculated whenever calibrate() |
|
328 is called, and they can be stored using the writeCalibration() |
|
329 function. Previously written parameters can be retrieved at any |
|
330 time using the readCalibration() function (calibration parameters |
|
331 are always read when the class is instantiated). Note that the |
|
332 calibration parameters is written to and read from the file |
|
333 currently specified by the POINTERCAL_FILE environment variable; |
|
334 the default file is \c /etc/pointercal. |
|
335 |
|
336 To achieve noise reduction, QWSCalibratedMouseHandler provides the |
|
337 sendFiltered() function. Use this function instead of |
|
338 mouseChanged() whenever a mouse event occurs. The filter's size |
|
339 can be manipulated using the setFilterSize() function. |
|
340 |
|
341 \sa QWSMouseHandler, QWSPointerCalibrationData, |
|
342 {Mouse Calibration Example} |
|
343 */ |
|
344 |
|
345 |
|
346 /*! |
|
347 \internal |
|
348 */ |
|
349 |
|
350 QWSCalibratedMouseHandler::QWSCalibratedMouseHandler(const QString &, const QString &) |
|
351 : samples(5), currSample(0), numSamples(0) |
|
352 { |
|
353 clearCalibration(); |
|
354 readCalibration(); |
|
355 } |
|
356 |
|
357 /*! |
|
358 Fills \a cd with the device coordinates corresponding to the given |
|
359 screen coordinates. |
|
360 |
|
361 \internal |
|
362 */ |
|
363 void QWSCalibratedMouseHandler::getCalibration(QWSPointerCalibrationData *cd) const |
|
364 { |
|
365 const qint64 scale = qint64(a) * qint64(e) - qint64(b) * qint64(d); |
|
366 const qint64 xOff = qint64(b) * qint64(f) - qint64(c) * qint64(e); |
|
367 const qint64 yOff = qint64(c) * qint64(d) - qint64(a) * qint64(f); |
|
368 for (int i = 0; i <= QWSPointerCalibrationData::LastLocation; ++i) { |
|
369 const qint64 sX = cd->screenPoints[i].x(); |
|
370 const qint64 sY = cd->screenPoints[i].y(); |
|
371 const qint64 dX = (s*(e*sX - b*sY) + xOff) / scale; |
|
372 const qint64 dY = (s*(a*sY - d*sX) + yOff) / scale; |
|
373 cd->devPoints[i] = QPoint(dX, dY); |
|
374 } |
|
375 } |
|
376 |
|
377 /*! |
|
378 Clears the current calibration, i.e., makes the mouse |
|
379 driver return mouse events in raw device coordinates instead of |
|
380 screen coordinates. |
|
381 |
|
382 \sa calibrate() |
|
383 */ |
|
384 void QWSCalibratedMouseHandler::clearCalibration() |
|
385 { |
|
386 a = 1; |
|
387 b = 0; |
|
388 c = 0; |
|
389 d = 0; |
|
390 e = 1; |
|
391 f = 0; |
|
392 s = 1; |
|
393 } |
|
394 |
|
395 |
|
396 /*! |
|
397 Saves the current calibration parameters in \c /etc/pointercal |
|
398 (separated by whitespace and in alphabetical order). |
|
399 |
|
400 You can override the default \c /etc/pointercal by specifying |
|
401 another file using the POINTERCAL_FILE environment variable. |
|
402 |
|
403 \sa readCalibration() |
|
404 */ |
|
405 void QWSCalibratedMouseHandler::writeCalibration() |
|
406 { |
|
407 QString calFile; |
|
408 calFile = QString::fromLocal8Bit(qgetenv("POINTERCAL_FILE")); |
|
409 if (calFile.isEmpty()) |
|
410 calFile = QLatin1String("/etc/pointercal"); |
|
411 |
|
412 #ifndef QT_NO_TEXTSTREAM |
|
413 QFile file(calFile); |
|
414 if (file.open(QIODevice::WriteOnly)) { |
|
415 QTextStream t(&file); |
|
416 t << a << ' ' << b << ' ' << c << ' '; |
|
417 t << d << ' ' << e << ' ' << f << ' ' << s << endl; |
|
418 } else |
|
419 #endif |
|
420 { |
|
421 qCritical("QWSCalibratedMouseHandler::writeCalibration: " |
|
422 "Could not save calibration into %s", qPrintable(calFile)); |
|
423 } |
|
424 } |
|
425 |
|
426 /*! |
|
427 Reads previously written calibration parameters which are stored |
|
428 in \c /etc/pointercal (separated by whitespace and in alphabetical |
|
429 order). |
|
430 |
|
431 You can override the default \c /etc/pointercal by specifying |
|
432 another file using the POINTERCAL_FILE environment variable. |
|
433 |
|
434 |
|
435 \sa writeCalibration() |
|
436 */ |
|
437 void QWSCalibratedMouseHandler::readCalibration() |
|
438 { |
|
439 QString calFile = QString::fromLocal8Bit(qgetenv("POINTERCAL_FILE")); |
|
440 if (calFile.isEmpty()) |
|
441 calFile = QLatin1String("/etc/pointercal"); |
|
442 |
|
443 #ifndef QT_NO_TEXTSTREAM |
|
444 QFile file(calFile); |
|
445 if (file.open(QIODevice::ReadOnly)) { |
|
446 QTextStream t(&file); |
|
447 t >> a >> b >> c >> d >> e >> f >> s; |
|
448 if (s == 0 || t.status() != QTextStream::Ok) { |
|
449 qCritical("Corrupt calibration data"); |
|
450 clearCalibration(); |
|
451 } |
|
452 } else |
|
453 #endif |
|
454 { |
|
455 qDebug() << "Could not read calibration:" <<calFile; |
|
456 } |
|
457 } |
|
458 |
|
459 static int ilog2(quint32 n) |
|
460 { |
|
461 int result = 0; |
|
462 |
|
463 if (n & 0xffff0000) { |
|
464 n >>= 16; |
|
465 result += 16; |
|
466 } |
|
467 if (n & 0xff00) { |
|
468 n >>= 8; |
|
469 result += 8;} |
|
470 if (n & 0xf0) { |
|
471 n >>= 4; |
|
472 result += 4; |
|
473 } |
|
474 if (n & 0xc) { |
|
475 n >>= 2; |
|
476 result += 2; |
|
477 } |
|
478 if (n & 0x2) |
|
479 result += 1; |
|
480 |
|
481 return result; |
|
482 } |
|
483 |
|
484 /*! |
|
485 Updates the calibration parameters based on coordinate mapping of |
|
486 the given \a data. |
|
487 |
|
488 Create an instance of the QWSPointerCalibrationData class, fill in |
|
489 the device and screen coordinates and pass that object to the mouse |
|
490 driver using this function. |
|
491 |
|
492 \sa clearCalibration(), transform() |
|
493 */ |
|
494 void QWSCalibratedMouseHandler::calibrate(const QWSPointerCalibrationData *data) |
|
495 { |
|
496 // Algorithm derived from |
|
497 // "How To Calibrate Touch Screens" by Carlos E. Vidales, |
|
498 // printed in Embedded Systems Programming, Vol. 15 no 6, June 2002 |
|
499 // URL: http://www.embedded.com/showArticle.jhtml?articleID=9900629 |
|
500 |
|
501 const QPoint pd0 = data->devPoints[QWSPointerCalibrationData::TopLeft]; |
|
502 const QPoint pd1 = data->devPoints[QWSPointerCalibrationData::TopRight]; |
|
503 const QPoint pd2 = data->devPoints[QWSPointerCalibrationData::BottomRight]; |
|
504 const QPoint p0 = data->screenPoints[QWSPointerCalibrationData::TopLeft]; |
|
505 const QPoint p1 = data->screenPoints[QWSPointerCalibrationData::TopRight]; |
|
506 const QPoint p2 = data->screenPoints[QWSPointerCalibrationData::BottomRight]; |
|
507 |
|
508 const qint64 xd0 = pd0.x(); |
|
509 const qint64 xd1 = pd1.x(); |
|
510 const qint64 xd2 = pd2.x(); |
|
511 const qint64 yd0 = pd0.y(); |
|
512 const qint64 yd1 = pd1.y(); |
|
513 const qint64 yd2 = pd2.y(); |
|
514 const qint64 x0 = p0.x(); |
|
515 const qint64 x1 = p1.x(); |
|
516 const qint64 x2 = p2.x(); |
|
517 const qint64 y0 = p0.y(); |
|
518 const qint64 y1 = p1.y(); |
|
519 const qint64 y2 = p2.y(); |
|
520 |
|
521 qint64 scale = ((xd0 - xd2)*(yd1 - yd2) - (xd1 - xd2)*(yd0 - yd2)); |
|
522 int shift = 0; |
|
523 qint64 absScale = qAbs(scale); |
|
524 // use maximum 16 bit precision to reduce risk of integer overflow |
|
525 if (absScale > (1 << 16)) { |
|
526 shift = ilog2(absScale >> 16) + 1; |
|
527 scale >>= shift; |
|
528 } |
|
529 |
|
530 s = scale; |
|
531 a = ((x0 - x2)*(yd1 - yd2) - (x1 - x2)*(yd0 - yd2)) >> shift; |
|
532 b = ((xd0 - xd2)*(x1 - x2) - (x0 - x2)*(xd1 - xd2)) >> shift; |
|
533 c = (yd0*(xd2*x1 - xd1*x2) + yd1*(xd0*x2 - xd2*x0) + yd2*(xd1*x0 - xd0*x1)) >> shift; |
|
534 d = ((y0 - y2)*(yd1 - yd2) - (y1 - y2)*(yd0 - yd2)) >> shift; |
|
535 e = ((xd0 - xd2)*(y1 - y2) - (y0 - y2)*(xd1 - xd2)) >> shift; |
|
536 f = (yd0*(xd2*y1 - xd1*y2) + yd1*(xd0*y2 - xd2*y0) + yd2*(xd1*y0 - xd0*y1)) >> shift; |
|
537 |
|
538 writeCalibration(); |
|
539 } |
|
540 |
|
541 /*! |
|
542 Transforms the given \a position from device coordinates to screen |
|
543 coordinates, and returns the transformed position. |
|
544 |
|
545 This function is typically called explicitly on the points passed |
|
546 to the QWSMouseHandler::mouseChanged() function. |
|
547 |
|
548 This implementation is a linear transformation using 7 parameters |
|
549 (\c a, \c b, \c c, \c d, \c e, \c f and \c s) to transform the |
|
550 device coordinates (\c Xd, \c Yd) into screen coordinates (\c Xs, |
|
551 \c Ys) using the following equations: |
|
552 |
|
553 \snippet doc/src/snippets/code/src_gui_embedded_qmouse_qws.cpp 0 |
|
554 |
|
555 \sa mouseChanged() |
|
556 */ |
|
557 QPoint QWSCalibratedMouseHandler::transform(const QPoint &position) |
|
558 { |
|
559 QPoint tp; |
|
560 |
|
561 tp.setX((a * position.x() + b * position.y() + c) / s); |
|
562 tp.setY((d * position.x() + e * position.y() + f) / s); |
|
563 |
|
564 return tp; |
|
565 } |
|
566 |
|
567 /*! |
|
568 Sets the size of the filter used in noise reduction to the given |
|
569 \a size. |
|
570 |
|
571 The sendFiltered() function reduces noice by calculating an |
|
572 average position from a collection of mouse event positions. The |
|
573 filter size determines the number of positions that forms the |
|
574 basis for these calculations. |
|
575 |
|
576 \sa sendFiltered() |
|
577 */ |
|
578 void QWSCalibratedMouseHandler::setFilterSize(int size) |
|
579 { |
|
580 samples.resize(qMax(1, size)); |
|
581 numSamples = 0; |
|
582 currSample = 0; |
|
583 } |
|
584 |
|
585 /*! |
|
586 \fn bool QWSCalibratedMouseHandler::sendFiltered(const QPoint &position, int state) |
|
587 |
|
588 Notifies the system of a new mouse event \e after applying a noise |
|
589 reduction filter. Returns true if the filtering process is |
|
590 successful; otherwise returns false. Note that if the filtering |
|
591 process failes, the system is not notified about the event. |
|
592 |
|
593 The given \a position is the global position of the mouse. The \a |
|
594 state parameter is a bitmask of the Qt::MouseButton enum's values |
|
595 indicating which mouse buttons are pressed. |
|
596 |
|
597 The noice is reduced by calculating an average position from a |
|
598 collection of mouse event positions and then calling the |
|
599 mouseChanged() function with the new position. The number of |
|
600 positions that is used is determined by the filter size. |
|
601 |
|
602 \sa mouseChanged(), setFilterSize() |
|
603 */ |
|
604 bool QWSCalibratedMouseHandler::sendFiltered(const QPoint &position, int button) |
|
605 { |
|
606 if (!button) { |
|
607 if (numSamples >= samples.count()) |
|
608 mouseChanged(transform(position), 0); |
|
609 currSample = 0; |
|
610 numSamples = 0; |
|
611 return true; |
|
612 } |
|
613 |
|
614 bool sent = false; |
|
615 samples[currSample] = position; |
|
616 numSamples++; |
|
617 if (numSamples >= samples.count()) { |
|
618 |
|
619 int ignore = -1; |
|
620 if (samples.count() > 2) { // throw away the "worst" sample |
|
621 int maxd = 0; |
|
622 for (int i = 0; i < samples.count(); i++) { |
|
623 int d = (mousePos - samples[i]).manhattanLength(); |
|
624 if (d > maxd) { |
|
625 maxd = d; |
|
626 ignore = i; |
|
627 } |
|
628 } |
|
629 } |
|
630 |
|
631 // average the rest |
|
632 QPoint pos(0, 0); |
|
633 int numAveraged = 0; |
|
634 for (int i = 0; i < samples.count(); i++) { |
|
635 if (ignore == i) |
|
636 continue; |
|
637 pos += samples[i]; |
|
638 ++numAveraged; |
|
639 } |
|
640 if (numAveraged) |
|
641 pos /= numAveraged; |
|
642 |
|
643 mouseChanged(transform(pos), button); |
|
644 sent = true; |
|
645 } |
|
646 currSample++; |
|
647 if (currSample >= samples.count()) |
|
648 currSample = 0; |
|
649 |
|
650 return sent; |
|
651 } |
|
652 |
|
653 QT_END_NAMESPACE |