src/gui/embedded/qmousetslib_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 "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