/**************************************************************************** ** ** 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 sales@trolltech.com. ** ** 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_LINUXTP
|