src/gui/embedded/qmouse_qws.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     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