/**************************************************************************** ** ** Copyright (C) 1992-2007 Trolltech ASA. All rights reserved. ** ** This file is part of the QtGui module of the Qt Toolkit. ** ** This file may be used under the terms of the GNU General Public ** License version 2.0 as published by the Free Software Foundation ** and appearing in the file LICENSE.GPL included in the packaging of ** this file. Please review the following information to ensure GNU ** General Public Licensing requirements will be met: ** http://trolltech.com/products/qt/licenses/licensing/opensource/ ** ** If you are unsure which license is appropriate for your use, please ** review the following information: ** http://trolltech.com/products/qt/licenses/licensing/licensingoverview ** or contact the sales department at [email protected]. ** ** In addition, as a special exception, Trolltech gives you certain ** additional rights. These rights are described in the Trolltech GPL ** Exception version 1.0, which can be found at ** http://www.trolltech.com/products/qt/gplexception/ and in the file ** GPL_EXCEPTION.txt in this package. ** ** In addition, as a special exception, Trolltech, as the sole copyright ** holder for Qt Designer, grants users of the Qt/Eclipse Integration ** plug-in the right for the Qt/Eclipse Integration to link to ** functionality provided by Qt Designer and its related libraries. ** ** Trolltech reserves all rights not expressly granted herein. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ****************************************************************************/ # include "qmouselinuxtp_qws.h" # ifndef QT_NO_QWS_MOUSE_LINUXTP # include "qwindowsystem_qws.h" # include "qsocketnotifier.h" # include "qtimer.h" # include "qapplication.h" # include "qscreen_qws.h" # include < unistd. h> # include < stdlib. h> # include < stdio. h> # include < sys/ ioctl. h> # include < sys/ types. h> # include < sys/ stat. h> # include < fcntl. h> # include < errno . h> # include < termios. h> # if defined( QT_QWS_IPAQ) # ifndef QT_QWS_IPAQ_RAW # define QT_QWS_IPAQ_RAW # endif # define QT_QWS_SCREEN_COORDINATES typedef struct { unsigned short pressure; unsigned short x; unsigned short y; unsigned short pad; } TS_EVENT; # elif defined( QT_QWS_EBX) # define QT_QWS_EBX_RAW # define QT_QWS_SCREEN_COORDINATES # ifndef QT_QWS_SHARP typedef struct { unsigned short pressure; unsigned short x; unsigned short y; unsigned short pad; } TS_EVENT; # else typedef struct { long y; long x; long pressure; long long millisecs; } TS_EVENT; # define QT_QWS_TP_SAMPLE_SIZE 10 # define QT_QWS_TP_MINIMUM_SAMPLES 4 # define QT_QWS_TP_PRESSURE_THRESHOLD 500 # define QT_QWS_TP_MOVE_LIMIT 50 # define QT_QWS_TP_JITTER_LIMIT 2 # endif # else // not IPAQ, not SHARP typedef struct { unsigned short pressure; unsigned short x; unsigned short y; unsigned short pad; } TS_EVENT; # endif # ifndef QT_QWS_TP_SAMPLE_SIZE # define QT_QWS_TP_SAMPLE_SIZE 5 # endif # ifndef QT_QWS_TP_MINIMUM_SAMPLES //确定每个点的有效样本数 # define QT_QWS_TP_MINIMUM_SAMPLES 5 # endif # ifndef QT_QWS_TP_PRESSURE_THRESHOLD //压力筏值 # define QT_QWS_TP_PRESSURE_THRESHOLD 1 # endif # ifndef QT_QWS_TP_MOVE_LIMIT //鼠标移动位置的上限(这里用词不是太准) # define QT_QWS_TP_MOVE_LIMIT 100 # endif # ifndef QT_QWS_TP_JITTER_LIMIT //鼠标移动位置的下限(这里用词不是太准) # define QT_QWS_TP_JITTER_LIMIT 2 # endif class QWSLinuxTPMouseHandlerPrivate : public QObject { Q_OBJECT public : QWSLinuxTPMouseHandlerPrivate( QWSLinuxTPMouseHandler * h, const QString & ) ; ~ QWSLinuxTPMouseHandlerPrivate( ) ; void suspend( ) ; void resume( ) ; private : static const int mouseBufSize = 2048; int mouseFD; //打开触摸屏设备后的文件描述符 QPoint oldmouse; //先前的鼠标位置 QPoint oldTotalMousePos; //先前的鼠标位置累加和 bool waspressed; //先前是否有点击事件发生 QPolygon samples; int currSample; //当前样本 int lastSample; int numSamples; //当前有效样本数 int skipCount; //没有处理的鼠标位置的次数 int mouseIdx; //索引 uchar mouseBuf[ mouseBufSize] ; //用作从mouseFD中读到的数据的缓冲区 QWSLinuxTPMouseHandler * handler; QSocketNotifier * mouseNotifier; private slots: void readMouseData( ) ; } ; QWSLinuxTPMouseHandler: : QWSLinuxTPMouseHandler( const QString & driver, const QString & device) : QWSCalibratedMouseHandler( driver, device) { d = new QWSLinuxTPMouseHandlerPrivate( this , device) ; } QWSLinuxTPMouseHandler: : ~ QWSLinuxTPMouseHandler( ) { delete d; } void QWSLinuxTPMouseHandler: : suspend( ) { d- > suspend( ) ; } void QWSLinuxTPMouseHandler: : resume( ) { d- > resume( ) ; } QWSLinuxTPMouseHandlerPrivate: : QWSLinuxTPMouseHandlerPrivate( QWSLinuxTPMouseHandler * h, const QString & device) : samples( QT_QWS_TP_SAMPLE_SIZE) , currSample( 0) , lastSample( 0) , numSamples( 0) , skipCount( 0) , handler( h) { QString mousedev; //确定触摸屏的设备文件 if ( device. isEmpty( ) ) { # if defined( QT_QWS_IPAQ) # ifdef QT_QWS_IPAQ_RAW mousedev = QLatin1String( "/dev/h3600_tsraw" ) ; # else mousedev = QLatin1String( "/dev/h3600_ts" ) ; # endif # else mousedev = QLatin1String( "/dev/ts" ) ; # endif } else { mousedev = device; } if ( ( mouseFD = open ( mousedev. toLatin1( ) . constData( ) , O_RDONLY | O_NDELAY) ) < 0) { qWarning( "Cannot open %s (%s)" , qPrintable( mousedev) , strerror ( errno ) ) ; return ; } //创建一个QScketNotifier对象mouseNotifier, 其属性为QSocketNotifier::Read, 用来监听mouseFD, //当mouseFD有新的数据可以读的时候,发射activated()信号给slot mouseNotifier = new QSocketNotifier( mouseFD, QSocketNotifier: : Read , this ) ; connect ( mouseNotifier, SIGNAL ( activated( int ) ) , this , SLOT( readMouseData( ) ) ) ; waspressed= false ; mouseIdx = 0; } QWSLinuxTPMouseHandlerPrivate: : ~ QWSLinuxTPMouseHandlerPrivate( ) { if ( mouseFD > = 0) close ( mouseFD) ; } //notifier默认是使能的 //当notfier使能的时候,它会发射activated信号只要监听的相应事件发生. void QWSLinuxTPMouseHandlerPrivate: : suspend( ) { if ( mouseNotifier) mouseNotifier- > setEnabled( false ) ; } void QWSLinuxTPMouseHandlerPrivate: : resume( ) { mouseIdx= 0; currSample= 0; lastSample= 0; numSamples= 0; skipCount= 0; if ( mouseNotifier) mouseNotifier- > setEnabled( true ) ; } void QWSLinuxTPMouseHandlerPrivate: : readMouseData( ) { if ( ! qt_screen) return ; //从mouseFD读数据到mouseBuf中,一次采2048个样,每QT_QWS_TP_MINIMUM_SAMPLES个样本确定一次 鼠标位置 int n; do { n = read ( mouseFD, mouseBuf+ mouseIdx, mouseBufSize- mouseIdx) ; if ( n > 0) mouseIdx + = n; } while ( n > 0 & & mouseIdx < mouseBufSize) ; //qDebug("readMouseData()"); TS_EVENT * data; int idx = 0; // perhaps we shouldn't be reading EVERY SAMPLE. while ( mouseIdx- idx > = ( int ) sizeof ( TS_EVENT) ) { uchar * mb = mouseBuf+ idx; data = ( TS_EVENT * ) mb; //触摸屏点击压力不小于筏值,获取一个样本位置,表示一次有效点击 //如是小于筏值,将所有变量清零,表示没有点击,也可以理解为没有东西接触屏 if ( data- > pressure > = QT_QWS_TP_PRESSURE_THRESHOLD) { # ifdef QT_QWS_SHARP samples[ currSample] = QPoint( 1000 - data- > x, data- > y) ; # else samples[ currSample] = QPoint( data- > x, data- > y) ; # endif //增加样本计数 //样本数达到采样最小值时,求平均数计算出当前鼠标的位置 numSamples+ + ; if ( numSamples > = QT_QWS_TP_MINIMUM_SAMPLES) { int sampleCount = qMin( numSamples + 1, samples. count ( ) ) ; // average the rest QPoint mousePos = QPoint( 0, 0) ; QPoint totalMousePos = oldTotalMousePos; totalMousePos + = samples[ currSample] ; if ( numSamples > = samples. count ( ) ) totalMousePos - = samples[ lastSample] ; mousePos = totalMousePos / ( sampleCount - 1) ; # if defined( QT_QWS_SCREEN_COORDINATES) mousePos = handler- > transform ( mousePos) ; # endif if ( ! waspressed) oldmouse = mousePos; //如果当前鼠标位置与先前鼠标位置距离太远,则将此样本作无效处理 //如果当前鼠标位置与先前鼠标位置距离太近,则无需更新鼠标位置 //除此两种情况,或者因太近而有两次没有更新过鼠标位置了,则更新鼠标位置,以免误差累计 QPoint dp = mousePos - oldmouse; int dxSqr = dp. x( ) * dp. x( ) ; int dySqr = dp. y( ) * dp. y( ) ; if ( dxSqr + dySqr < ( QT_QWS_TP_MOVE_LIMIT * QT_QWS_TP_MOVE_LIMIT) ) { if ( waspressed) { if ( ( dxSqr + dySqr > ( QT_QWS_TP_JITTER_LIMIT * QT_QWS_TP_JITTER_LIMIT) ) | | skipCount > 2) { handler- > mouseChanged( mousePos, Qt: : LeftButton) ; oldmouse = mousePos; skipCount = 0; } else { skipCount+ + ; } } else { handler- > mouseChanged( mousePos, Qt: : LeftButton) ; oldmouse= mousePos; waspressed= true ; } // save recuring information currSample+ + ; if ( numSamples > = samples. count ( ) ) lastSample+ + ; oldTotalMousePos = totalMousePos; } else { numSamples- - ; // don't use this sample, it was bad. } } else { // build up the average oldTotalMousePos + = samples[ currSample] ; currSample+ + ; } if ( currSample > = samples. count ( ) ) currSample = 0; if ( lastSample > = samples. count ( ) ) lastSample = 0; } else { //检测到没有点击,则所有变量做清零处理 currSample = 0; lastSample = 0; numSamples = 0; skipCount = 0; oldTotalMousePos = QPoint( 0, 0) ; if ( waspressed) { handler- > mouseChanged( oldmouse, 0) ; oldmouse = QPoint( - 100, - 100) ; waspressed= false ; } } idx + = sizeof ( TS_EVENT) ; } int surplus = mouseIdx - idx; for ( int i = 0; i < surplus; i+ + ) mouseBuf[ i] = mouseBuf[ idx+ i] ; mouseIdx = surplus; } # include "qmouselinuxtp_qws.moc" # endif //QT_NO_QWS_MOUSE_LINUXT |