/****************************************************************************
**
** 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_LINUXT
|