Android多点触摸.docx

上传人:b****6 文档编号:5949325 上传时间:2023-01-02 格式:DOCX 页数:13 大小:20.10KB
下载 相关 举报
Android多点触摸.docx_第1页
第1页 / 共13页
Android多点触摸.docx_第2页
第2页 / 共13页
Android多点触摸.docx_第3页
第3页 / 共13页
Android多点触摸.docx_第4页
第4页 / 共13页
Android多点触摸.docx_第5页
第5页 / 共13页
点击查看更多>>
下载资源
资源描述

Android多点触摸.docx

《Android多点触摸.docx》由会员分享,可在线阅读,更多相关《Android多点触摸.docx(13页珍藏版)》请在冰豆网上搜索。

Android多点触摸.docx

Android多点触摸

第一章摘要在Linux内核支持的基础上,Android在其2.0源码中加入多点触摸功能。

由此触摸屏在Android的frameworks被完全分为2种实现途径:

单点触摸屏的单点方式,多点触摸屏的单点和多点方式。

第二章软件位在Linux的input.h中,多点触摸功能依赖于以下几个主要的软件位:

………………………..

#defineSYN_REPORT0

#defineSYN_CONFIG1

#defineSYN_MT_REPORT2

………………………...

#defineABS_MT_TOUCH_MAJOR0x30/*Majoraxisoftouchingellipse*/

#defineABS_MT_TOUCH_MINOR0x31/*Minoraxis(omitifcircular)*/

#defineABS_MT_WIDTH_MAJOR0x32/*Majoraxisofapproachingellipse*/

#defineABS_MT_WIDTH_MINOR0x33/*Minoraxis(omitifcircular)*/

#defineABS_MT_ORIENTATION0x34/*Ellipseorientation*/

#defineABS_MT_POSITION_X0x35/*CenterXellipseposition*/

#defineABS_MT_POSITION_Y0x36/*CenterYellipseposition*/

#defineABS_MT_TOOL_TYPE0x37/*Typeoftouchingdevice*/

#defineABS_MT_BLOB_ID0x38/*Groupasetofpacketsasablob*/

…………………………

在Android中对应的软件位定义在RawInputEvent.java中:

…………………..

publicclassRawInputEvent{

……………….

publicstaticfinalintCLASS_TOUCHSCREEN_MT=0x00000010;

………………..

publicstaticfinalintABS_MT_TOUCH_MAJOR=0x30;

publicstaticfinalintABS_MT_TOUCH_MINOR=0x31;

publicstaticfinalintABS_MT_WIDTH_MAJOR=0x32;

publicstaticfinalintABS_MT_WIDTH_MINOR=0x33;

publicstaticfinalintABS_MT_ORIENTATION=0x34;

publicstaticfinalintABS_MT_POSITION_X=0x35;

publicstaticfinalintABS_MT_POSITION_Y=0x36;

publicstaticfinalintABS_MT_TOOL_TYPE=0x37;

publicstaticfinalintABS_MT_BLOB_ID=0x38;

………………….

publicstaticfinalintSYN_REPORT=0;

publicstaticfinalintSYN_CONFIG=1;

publicstaticfinalintSYN_MT_REPORT=2;

………………..

在Android中,多点触摸的实现方法在具体的代码实现中和单点是完全区分开的。

在Android代码的EventHub.cpp中,单点屏和多点屏由如下代码段来判定:

intEventHub:

:

open_device(constchar*deviceName)

{

………………………

if(test_bit(ABS_MT_TOUCH_MAJOR,abs_bitmask)

&&test_bit(ABS_MT_POSITION_X,abs_bitmask)

&&test_bit(ABS_MT_POSITION_Y,abs_bitmask)){

device->classes|=CLASS_TOUCHSCREEN|CLASS_TOUCHSCREEN_MT;

//LOGI("Itisamulti-touchscreen!

");

}

//single-touch?

elseif(test_bit(BTN_TOUCH,key_bitmask)

&&test_bit(ABS_X,abs_bitmask)

&&test_bit(ABS_Y,abs_bitmask)){

device->classes|=CLASS_TOUCHSCREEN;

//LOGI("Itisasingle-touchscreen!

");

}

………………..

}

我们知道,在触摸屏驱动中,通常在probe函数中会调用input_set_abs_params给设备的input_dev结构体初始化,这些input_dev的参数会在Android的EventHub.cpp中被读取。

如上可知,如果我们的触摸屏想被当成多点屏被处理,只需要在驱动中给input_dev额外增加以下几个参数即可:

input_set_abs_params(mcs_data.input,ABS_MT_POSITION_X,pdata->abs_x_min,pdata->abs_x_max,0,0);

input_set_abs_params(mcs_data.input,ABS_MT_POSITION_Y,pdata->abs_y_min,pdata->abs_y_max,0,0);

input_set_abs_params(mcs_data.input,ABS_MT_TOUCH_MAJOR,0,15,0,0);

//相当于单点屏的ABX_PRESSURE

input_set_abs_params(mcs_data.input,ABS_MT_WIDTH_MAJOR,0,15,0,0);

//相当于单点屏的ABS_TOOL_WIDTH

注:

为了让我们的驱动代码支持所有的Android版本,无论是多点屏还是单点屏,一般都会保留单点屏的事件,如ABS_TOUCH,ABS_PRESSURE,ABS_X,ABS_Y等。

另外,由于在Android2.0前支持多点的frameworks大多是用HAT0X,HAT0Y来实现的,所以一般也会上报这2个事件。

第三章同步方式由于多点触摸技术需要采集到多个点,然后再一起处理这些点,所以在软件实现中需要保证每一波点的准确性和完整性。

因此,Linux内核提供了input_mt_sync(structinput_dev*input)函数。

在每波的每个点上报后需要紧跟一句input_mt_sync(),当这波所有点上报后再使用input_sync()进行同步。

例如一波要上报3个点:

/*上报点1*/

……………..

input_mt_sync(input);

/*上报点2*/

……………..

input_mt_sync(input);

/*上报点3*/

……………..

input_mt_sync(input);

input_sync(input);

注:

即使是仅上报一个点的单点事件,也需要一次input_my_sync。

文章出处:

飞诺网():

在Android的KeyInputQueue.java中,系统创建了一个线程,然后把所有的Input事件放入一个队列:

publicabstractclassKeyInputQueue{

……………………

ThreadmThread=newThread("InputDeviceReader"){

publicvoidrun(){

android.os.Process.setThreadPriority(

android.os.Process.THREAD_PRIORITY_URGENT_DISPLAY);

try{

RawInputEventev=newRawInputEvent();

while(true){

InputDevicedi;

//block,doesn'treleasethemonitor

readEvent(ev);

if(ev.type==RawInputEvent.EV_DEVICE_ADDED){

synchronized(mFirst){

di=newInputDevice(ev.deviceId);

mDevices.put(ev.deviceId,di);

configChanged=true;

}

}elseif(ev.type==RawInputEvent.EV_DEVICE_REMOVED){

synchronized(mFirst){

Log.i(TAG,"Deviceremoved:

id=0x"

+Integer.toHexString(ev.deviceId));

di=mDevices.get(ev.deviceId);

if(di!

=null){

mDevices.delete(ev.deviceId);

configChanged=true;

}else{

Log.w(TAG,"Baddeviceid:

"+ev.deviceId);

}

}

}else{

di=getInputDevice(ev.deviceId);

//firstcrackatit

send=preprocessEvent(di,ev);

if(ev.type==RawInputEvent.EV_KEY){

di.mMetaKeysState=makeMetaState(ev.keycode,

ev.value!

=0,di.mMetaKeysState);

mHaveGlobalMetaState=false;

}

}

if(di==null){

continue;

}

if(configChanged){

synchronized(mFirst){

addLocked(di,SystemClock.uptimeMillis(),0,

RawInputEvent.CLASS_CONFIGURATION_CHANGED,

null);

}

}

if(!

send){

continue;

}

synchronized(mFirst){

……………………….

if(type==RawInputEvent.EV_KEY&&

(classes&RawInputEvent.CLASS_KEYBOARD)!

=0&&

(scancode

scancode>RawInputEvent.BTN_LAST)){

/*键盘按键事件*/

…………………….

}elseif(ev.type==RawInputEvent.EV_KEY){

/*下面是EV_KEY事件分支,只支持单点的触摸屏有按键事件,

*而支持多点的触摸屏没有按键事件,只有绝对坐标事件

*/

if(ev.scancode==RawInputEvent.BTN_TOUCH&&

(classes&(RawInputEvent.CLASS_TOUCHSCREEN

|RawInputEvent.CLASS_TOUCHSCREEN_MT))

==RawInputEvent.CLASS_TOUCHSCREEN){

/*只支持单点的触摸屏的按键事件*/

…………………………………

}elseif(ev.scancode==RawInputEvent.BTN_MOUSE&&

(classes&RawInputEvent.CLASS_TRACKBALL)!

=0){

/*鼠标和轨迹球*/

……………………….

}elseif(ev.type==RawInputEvent.EV_ABS&&

(classes&RawInputEvent.CLASS_TOUCHSCREEN_MT)!

=0){

/*下面才是多点触摸屏上报的事件*/

if(ev.scancode==RawInputEvent.ABS_MT_TOUCH_MAJOR){

di.mAbs.changed=true;

di.mAbs.mNextData[di.mAbs.mAddingPointerOffset

+MotionEvent.SAMPLE_PRESSURE]=ev.value;

}elseif(ev.scancode==RawInputEvent.ABS_MT_POSITION_X){

di.mAbs.changed=true;

di.mAbs.mNextData[di.mAbs.mAddingPointerOffset

+MotionEvent.SAMPLE_X]=ev.value;

}elseif(ev.scancode==RawInputEvent.ABS_MT_POSITION_Y){

di.mAbs.changed=true;

di.mAbs.mNextData[di.mAbs.mAddingPointerOffset

+MotionEvent.SAMPLE_Y]=ev.value;

}elseif(ev.scancode==RawInputEvent.ABS_MT_WIDTH_MAJOR){

di.mAbs.changed=true;

di.mAbs.mNextData[di.mAbs.mAddingPointerOffset

+MotionEvent.SAMPLE_SIZE]=ev.value;

}

/*上面这段就是多点触摸屏要用到的事件上报部分;

*使用一个数组mNextData来保存,其中di.mAbs.mAddingPointerOffset

*是当前点的偏移量,在每个点中还在MotionEvent中定义了X,Y,PRESSURE

*SIZE等偏移量,多点触摸屏的压力值由绝对坐标事件ABS_MT_TOUCH_MAJOR确定。

*/

}elseif(ev.type==RawInputEvent.EV_ABS&&

(classes&RawInputEvent.CLASS_TOUCHSCREEN)!

=0){

/*这里是对单点触摸屏上报坐标事件的新的处理方法,同样使用了数组来保存*/

if(ev.scancode==RawInputEvent.ABS_X){

di.mAbs.changed=true;

di.curTouchVals[MotionEvent.SAMPLE_X]=ev.value;

}elseif(ev.scancode==RawInputEvent.ABS_Y){

di.mAbs.changed=true;

di.curTouchVals[MotionEvent.SAMPLE_Y]=ev.value;

}elseif(ev.scancode==RawInputEvent.ABS_PRESSURE){

di.mAbs.changed=true;

di.curTouchVals[MotionEvent.SAMPLE_PRESSURE]=ev.value;

di.curTouchVals[MotionEvent.NUM_SAMPLE_DATA

+MotionEvent.SAMPLE_PRESSURE]=ev.value;

}elseif(ev.scancode==RawInputEvent.ABS_TOOL_WIDTH){

di.mAbs.changed=true;

di.curTouchVals[MotionEvent.SAMPLE_SIZE]=ev.value;

di.curTouchVals[MotionEvent.NUM_SAMPLE_DATA

+MotionEvent.SAMPLE_SIZE]=ev.value;

}

…………………………………………….}

/*下面是关键的同步处理方法*/

if(ev.type==RawInputEvent.EV_SYN

&&ev.scancode==RawInputEvent.SYN_MT_REPORT

&&di.mAbs!

=null){

/*在这里实现了对SYN_MT_REPORT事件的处理,

*改变了di.mAbs.mAddingPointerOffset的值,从而将

*新增的点的参数保存到下一组偏移量的位置。

*/

…………………….

finalintnewOffset=(num<=InputDevice.MAX_POINTERS)

?

(num*MotionEvent.NUM_SAMPLE_DATA)

:

(InputDevice.MAX_POINTERS*

MotionEvent.NUM_SAMPLE_DATA);

di.mAbs.mAddingPointerOffset=newOffset;

di.mAbs.mNextData[newOffset

+MotionEvent.SAMPLE_PRESSURE]=0;

}

……………….

}elseif(send||(ev.type==RawInputEvent.EV_SYN

&&ev.scancode==RawInputEvent.SYN_REPORT)){

/*这里实现了对SYN_REPORT事件的处理

*如果是单点触摸屏,即使用di.curTouchVals数组保存的点

*转化为多点触摸屏的mNextData数组保存

*最后是调用InputDevice中的generateAbsMotion处理这个数组。

这个函数

*的具体实现方法将在后面补充

*/

…………………………..

ms.finish();//重置所有点和偏移量

……………………..

}

由于上层的代码仍然使用ABS_X,ABS_Y这些事件,为了使多点触摸屏代码有良好的兼容性,在KeyInputQueue.java的最后,我们将多点事件类型转化为单点事件类型,返回一个新的InputDevice:

privateInputDevicenewInputDevice(intdeviceId){

intclasses=getDeviceClasses(deviceId);

Stringname=getDeviceName(deviceId);

InputDevice.AbsoluteInfoabsX;

InputDevice.AbsoluteInfoabsY;

InputDevice.AbsoluteInfoabsPressure;

InputDevice.AbsoluteInfoabsSize;

if((classes&RawInputEvent.CLASS_TOUCHSCREEN_MT)!

=0){

absX=loadAbsoluteInfo(deviceId,

RawInputEvent.ABS_MT_POSITION_X,"X");

absY=loadAbsoluteInfo(deviceId,

RawInputEvent.ABS_MT_POSITION_Y,"Y");

absPressure=loadAbsoluteInfo(deviceId,

RawInputEvent.ABS_MT_TOUCH_MAJOR,"Pressure");

absSize=loadAbsoluteInfo(deviceId,

RawInputEvent.ABS_MT_WIDTH_MAJOR,"Size");

}elseif((classes&RawInputEvent.CLASS_TOUCHSCREEN)!

=0){

absX=loadAbsoluteInfo(deviceId,

RawInputEvent.ABS_X,"X");

absY=loadAbsoluteInfo(deviceId,

RawInputEvent.ABS_Y,"Y");

absPressure=loadAbsoluteInfo(deviceId,

RawInputEvent.ABS_PRESSURE,"Pressure");

absSize=loadAbsoluteInfo(deviceId,

RawInputEvent.ABS_TOOL_WIDTH,"Size");

}else{

absX=null;

absY=null;

absPressure=null;

absSize=null;

}

returnnewInputDevice(deviceId,classes,name,absX,absY,absPressure,absSize);

}

文章出处:

飞诺网():

第四章触摸事件数组的处理上面我们曾说到generateAbsMotion这个方法,它们在InputDevice类的内部类MotionState中实现,该类被定义为InputDevice类的静态成员类(staticclass),调用它们可以直接使用:

InputDeviceClass.MotionStateClass.generateAbsMotion()。

publicclassIn

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 自然科学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1