【转】Android-Input 触摸设备
https://source.android.com/devices/input/touch-devices
触摸设备
Android 支持各种触摸屏和触摸板,包括基于触控笔的数字化板。
触摸屏是与显示屏相关联的触摸设备,使用户能够在屏幕上直接操纵内容。
触摸板是不与显示屏相关联的触摸设备(如数字化板)。触摸板通常用于指控或绝对间接定位或基于手势的界面控制。
触摸设备可能具有功能与鼠标按钮类似的按钮。
有时可以使用各种不同的工具(如手指或触控笔)操作触摸设备,具体取决于底层的触摸传感器技术。
触摸设备有时用于实现虚拟按键。例如,在某些 Android 设备上,触摸屏传感器区域延伸超出显示屏的边缘,作为触摸式键盘的一部分发挥双重作用。
由于触摸设备种类繁多,Android 依赖于大量配置属性来描述每个设备的特征和期望的行为。
触摸设备分类
如果同时满足以下两个条件,则输入设备属于多点触控设备:
输入设备报告存在
ABS_MT_POSITION_X
和ABS_MT_POSITION_Y
绝对轴。输入设备没有任何游戏手柄按钮。某些游戏手柄会使用与 MT 轴的代码重叠的代码来报告轴,而这一条件则消除了这种歧义。
如果同时满足以下两个条件,则输入设备属于单点触控设备:
输入设备不属于多点触控设备。输入设备要么属于单点触控设备,要么属于多点触控设备,而不会同时属于这两种类别。
输入设备报告存在
ABS_X
和ABS_Y
绝对轴以及BTN_TOUCH
按键代码。
一旦输入设备属于触摸设备,则通过尝试加载设备的虚拟按键映射文件来确定是否存在虚拟按键。如果存在虚拟按键映射,则还会加载设备的按键布局文件。
有关虚拟按键映射文件的位置和格式,请参阅下面的部分。
接下来,系统会加载触摸设备的输入设备配置文件。
所有内置触摸设备都应具有输入设备配置文件。如果没有输入设备配置文件,则系统将选择适用于典型通用触摸外设(如外部 USB 或蓝牙 HID 触摸屏或触摸板)的默认配置。这些默认配置不适用于内置触摸屏,很可能会导致错误的行为。
加载输入设备配置后,系统会将输入设备分类为触摸屏、触摸板或指控设备。
触摸屏设备用于直接操纵屏幕上的对象。由于用户直接触摸屏幕,因此系统不需要任何额外的感知性来指示被操纵的对象。
触摸板设备用于向应用提供关于在给定传感器区域上进行触摸时的绝对定位信息。它可能对数字化板有用。
指控设备用于使用光标间接操纵屏幕上的对象。手指被解释为多点触控指控手势。其他工具(如触控笔)则通过绝对位置来解释。
有关详情,请参阅间接多点触控指控手势。
以下规则用于将输入设备分类为触摸屏、触摸板或指控设备。
如果设置了
touch.deviceType
属性,则将按照指示设置设备类型。如果输入设备报告存在
INPUT_PROP_DIRECT
输入属性(通过EVIOCGPROP
ioctl),则设备类型将设置为触摸屏。该条件假设直接输入触摸设备已连接到同样处于连接状态的显示屏。如果输入设备报告存在
INPUT_PROP_POINTER
输入属性(通过EVIOCGPROP
ioctl),则设备类型将设置为指控设备。如果输入设备报告存在
REL_X
或REL_Y
相对轴,则设备类型将设置为触摸板。该条件消除了由鼠标和触摸板组成的输入设备存在的歧义。在这种情况下,触摸板不会用于控制指针,因为鼠标已经在控制它。否则,设备类型将被设置为指控设备。该默认设置确保没有指定任何其他特殊用途的触摸板将用于控制指针。
按钮
按钮是可供应用用来执行其他功能的“可选”控件。触摸设备上的按钮与鼠标按钮类似,主要与“指针式”触摸设备或者触控笔配合使用。
支持以下按钮:
BTN_LEFT
:映射到MotionEvent.BUTTON_PRIMARY
。BTN_RIGHT
:映射到MotionEvent.BUTTON_SECONDARY
。BTN_MIDDLE
:映射到MotionEvent.BUTTON_MIDDLE
。BTN_BACK
和BTN_SIDE
:映射到MotionEvent.BUTTON_BACK
。按此按钮还可以合成按键(使用按键代码KeyEvent.KEYCODE_BACK
)。BTN_FORWARD
和BTN_EXTRA
:映射到MotionEvent.BUTTON_FORWARD
。按此按钮还可以合成按键(使用按键代码KeyEvent.KEYCODE_FORWARD
)。BTN_STYLUS
:映射到MotionEvent.BUTTON_SECONDARY
。BTN_STYLUS2
:映射到MotionEvent.BUTTON_TERTIARY
。
工具和工具类型
“工具”是指用于和触摸设备进行交互的手指、触控笔或其他装置。有些触摸设备可以区分不同类型的工具。
在 Android 的其他位置(和在 MotionEvent
API 中一样),“工具”通常称为“指针”。
支持以下工具类型:
BTN_TOOL_FINGER
和MT_TOOL_FINGER
:映射到MotionEvent.TOOL_TYPE_FINGER
。BTN_TOOL_PEN
和MT_TOOL_PEN
:映射到MotionEvent.TOOL_TYPE_STYLUS
。BTN_TOOL_RUBBER
:映射到MotionEvent.TOOL_TYPE_ERASER
。BTN_TOOL_BRUSH
:映射到MotionEvent.TOOL_TYPE_STYLUS
。BTN_TOOL_PENCIL
:映射到MotionEvent.TOOL_TYPE_STYLUS
。BTN_TOOL_AIRBRUSH
:映射到MotionEvent.TOOL_TYPE_STYLUS
。BTN_TOOL_MOUSE
:映射到MotionEvent.TOOL_TYPE_MOUSE
。BTN_TOOL_LENS
:映射到MotionEvent.TOOL_TYPE_MOUSE
。BTN_TOOL_DOUBLETAP
、BTN_TOOL_TRIPLETAP
和BTN_TOOL_QUADTAP
:映射到MotionEvent.TOOL_TYPE_FINGER
。
悬停与触摸工具
工具可以与触摸设备接触,也可以在触摸设备的感应范围内悬停在设备的上方。并非所有触摸设备都能够感应到悬停在其上方的工具。那些可实现感应的触摸设备(如基于射频的触控笔数字化仪)通常能在工具进入其有限的感应范围后检测到该工具。
InputReader
组件会谨慎区分触摸工具和悬停工具。同样,触摸工具和悬停工具也会以不同的方式报告给应用。
触摸工具将通过以下组件作为触摸事件报告给应用:MotionEvent.ACTION_DOWN
、MotionEvent.ACTION_MOVE
、MotionEvent.ACTION_DOWN
、MotionEvent.ACTION_POINTER_DOWN
和 MotionEvent.ACTION_POINTER_UP
。
悬停工具将通过以下组件作为通用动作事件报告给应用:MotionEvent.ACTION_HOVER_ENTER
、MotionEvent.ACTION_HOVER_MOVE
和 MotionEvent.ACTION_HOVER_EXIT
。
触摸设备驱动程序要求
触摸设备驱动程序应该仅注册它们实际支持的轴/按钮的轴/按键代码。如果注册多余的轴/按键代码,则可能会混淆设备分类算法或导致系统错误地检测设备的功能。
例如,如果设备报告
BTN_TOUCH
按键代码,系统会假设BTN_TOUCH
将始终用于指示该工具是否实际触摸屏幕。因此,不应使用BTN_TOUCH
来指示该工具只是在感应范围内悬停。单点触控设备使用以下 Linux 输入事件:
ABS_X
:(必需)报告工具的 X 坐标。ABS_Y
:(必需)报告工具的 Y 坐标。ABS_PRESSURE
:(可选)报告应用于工具尖端的物理压力或触摸区域的信号强度。ABS_TOOL_WIDTH
:(可选)报告触摸区域或工具本身的横截面积或宽度。ABS_DISTANCE
:(可选)报告工具与触摸设备表面之间的距离。ABS_TILT_X
:(可选)报告工具沿触摸设备表面 X 轴方向的倾斜度。ABS_TILT_Y
:(可选)报告工具沿触摸设备表面 Y 轴方向的倾斜度。BTN_TOUCH
:(必需)指示工具是否触摸到设备。BTN_LEFT
、BTN_RIGHT
、BTN_MIDDLE
、BTN_BACK
、BTN_SIDE
、BTN_FORWARD
、BTN_EXTRA
、BTN_STYLUS
、BTN_STYLUS2
:(可选)报告按钮状态。BTN_TOOL_FINGER
、BTN_TOOL_PEN
、BTN_TOOL_RUBBER
、BTN_TOOL_BRUSH
、BTN_TOOL_PENCIL
、BTN_TOOL_AIRBRUSH
、BTN_TOOL_MOUSE
、BTN_TOOL_LENS
、BTN_TOOL_DOUBLETAP
、BTN_TOOL_TRIPLETAP
、BTN_TOOL_QUADTAP
:(可选)报告工具类型。
多点触控设备使用以下 Linux 输入事件:
ABS_MT_POSITION_X
:(必需)报告工具的 X 坐标。ABS_MT_POSITION_Y
:(必需)报告工具的 Y 坐标。ABS_MT_PRESSURE
:(可选)报告应用于工具尖端的物理压力或触摸区域的信号强度。ABS_MT_TOUCH_MAJOR
:(可选)报告触摸区域的横截面积或触摸区域较长尺寸的长度。ABS_MT_TOUCH_MINOR
:(可选)报告触摸区域较短尺寸的长度。如果ABS_MT_TOUCH_MAJOR
报告区域测量,则不应使用此轴。ABS_MT_WIDTH_MAJOR
:(可选)报告工具本身的横截面积或工具本身较长尺寸的长度。如果工具本身的尺寸未知,则不应使用此轴。ABS_MT_WIDTH_MINOR
:(可选)报告工具本身较短尺寸的长度。如果ABS_MT_WIDTH_MAJOR
报告区域测量或者工具本身的尺寸未知,则不应使用此轴。ABS_MT_ORIENTATION
:(可选)报告工具的方向。ABS_MT_DISTANCE
:(可选)报告工具与触摸设备表面之间的距离。ABS_MT_TOOL_TYPE
:(可选)将工具类型报告为MT_TOOL_FINGER
或MT_TOOL_PEN
。ABS_MT_TRACKING_ID
:(可选)报告工具的跟踪 ID。跟踪 ID 是一个任意的非负整数。当多个工具同时处于活动状态时,该 ID 用于独立地识别和跟踪各个工具。例如,当多个手指同时触摸设备时,会为每个手指分配一个不同的跟踪 ID,用于在手指保持接触期间识别手指。跟踪 ID 可在其关联的工具移出感应范围后重复使用。ABS_MT_SLOT
:(可选)在使用 Linux 多点触控协议“B”时,报告工具的槽位 ID。有关详情,请参阅 Linux 多点触控协议文档。BTN_TOUCH
:(必需)指示工具是否触摸到设备。BTN_LEFT
、BTN_RIGHT
、BTN_MIDDLE
、BTN_BACK
、BTN_SIDE
、BTN_FORWARD
、BTN_EXTRA
、BTN_STYLUS
、BTN_STYLUS2
:(可选)报告按钮状态。BTN_TOOL_FINGER
、BTN_TOOL_PEN
、BTN_TOOL_RUBBER
、BTN_TOOL_BRUSH
、BTN_TOOL_PENCIL
、BTN_TOOL_AIRBRUSH
、BTN_TOOL_MOUSE
、BTN_TOOL_LENS
、BTN_TOOL_DOUBLETAP
、BTN_TOOL_TRIPLETAP
、BTN_TOOL_QUADTAP
:(可选)报告工具类型。
如果同时定义了单点触控协议轴和多点触控协议轴,则仅使用多点触控轴,并忽略单点触控轴。
ABS_X
、ABS_Y
、ABS_MT_POSITION_X
和ABS_MT_POSITION_Y
轴的最小值和最大值用于在特定于设备的 Surface 单元内指定设备有效区域的范围。如果是触摸屏,有效区域是指触摸设备实际覆盖显示屏的部分。对于触摸屏,系统会自动插入报告的触摸位置(在 Surface 单元内),以通过以下公式计算得出采用显示像素表示的触摸位置:
displayX = (x - minX) * displayWidth / (maxX - minX + 1)
displayY = (y - minY) * displayHeight / (maxY - minY + 1)触摸屏可能会报告在报告的有效区域之外发起的触摸。
在有效区域之外发起的触摸不会传递给应用,但可用于虚拟按键。
在有效区域内发起的触摸或进入和退出显示区域的触摸会传递给应用。因此,如果触摸是在应用的范围内开始,然后移动到有效区域之外,则应用可能会收到显示坐标为负或超出显示范围的触摸事件。这属于正常现象。
触摸设备不得限制有效区域的触摸坐标边界。如果触摸退出有效区域,则应将其报告为超出有效区域范围,或者根本不应报告。
例如,如果用户的手指在触摸屏左上角附近触摸,则可能会报告 (minX, minY) 坐标。如果手指继续移动到有效区域之外,触摸屏应该开始报告分量小于 minX 和 minY 的坐标(如 (minX - 2, minY - 3)),或者完全停止报告触摸。换句话说,当用户的手指确实触摸到有效区域之外时,触摸屏不应该报告 (minX, minY)。
如果将触摸坐标限制到显示屏边缘,则会在屏幕边缘周围产生人为硬边界,阻止系统顺畅地跟踪进入或退出显示区域边界的运动。
ABS_PRESSURE
或ABS_MT_PRESSURE
报告的值(如果有报告)在工具触摸设备时必须为非零值;否则就为零,表示该工具处于悬停状态。报告压力信息为可选项,但强烈建议报告该信息。应用可以使用压力信息来实现压敏绘图等效果。
ABS_TOOL_WIDTH
、ABS_MT_TOUCH_MAJOR
、ABS_MT_TOUCH_MINOR
、ABS_MT_WIDTH_MAJOR
或ABS_MT_WIDTH_MINOR
报告的值在工具触摸设备时应为非零值;否则就为零,但这不是必需的。例如,触摸设备可能能够测量手指触摸点的尺寸,但不能测量触控笔触摸点的尺寸。报告大小信息为可选项,但强烈建议报告。应用可以使用压力信息来实现尺寸敏感绘图等效果。
ABS_DISTANCE
或ABS_MT_DISTANCE
报告的值在工具触摸设备时应接近零。即使当工具处于直接接触时,距离仍可能为非零。报告的确切值取决于硬件测量距离的方式。报告距离信息为可选项,但建议用于触控笔设备。
当工具垂直于设备时,
ABS_TILT_X
和ABS_TILT_Y
报告的值应为零。将非零倾斜作为工具保持在倾斜处的标志。假定沿 X 轴和 Y 轴的倾斜角度以与垂直方向的夹角计。中心点(完全垂直)由每个轴的
(max + min) / 2
指定。小于中心点的值表示向上或向左倾斜,大于中心点的值表示向下或向右倾斜。InputReader
将 X 和 Y 倾斜分量转换成从 0 到PI / 2
弧度的垂直倾斜角以及从-PI
到PI
弧度的平面定向角。该表示法将产生与描述手指触摸所用方向相符的方向的描述。报告倾斜信息为可选项,但建议用于触控笔设备。
如果工具类型是由
ABS_MT_TOOL_TYPE
报告的,则会取代BTN_TOOL_*
报告的任何工具类型信息。如果根本没有任何工具类型信息,则工具类型将默认为MotionEvent.TOOL_TYPE_FINGER
。根据以下条件确定工具的活动状态:
当使用单点触控协议时,如果
BTN_TOUCH
或BTN_TOOL_*
为 1,则表示工具处于活动状态。这个条件意味着
InputReader
至少需要获得一些关于工具性质的信息:工具是否正在触摸,或者至少知道工具的类型。如果没有可用的信息,则假定工具处于非活动状态(超出范围)。当使用多点触控协议“A”时,只要工具出现在最近的同步报告中,则表示其处于活动状态。当工具不再出现在同步报告中时,则表示工具不再存在。
当使用多点触控协议“B”时,只要工具具有活动插槽,则表示其处于活动状态。当插槽被清除时,则表示工具不再存在。
根据以下条件确定工具悬停:
如果工具为
BTN_TOOL_MOUSE
或BTN_TOOL_LENS
,则该工具不会悬停,即使以下任一条件为真也不例外。如果工具处于活动状态,并且驱动程序报告的压力为零,则表示工具处于悬停状态。
如果工具处于活动状态,而且驱动程序支持
BTN_TOUCH
按键代码,并且BTN_TOUCH
的值为零,则表示工具处于悬停状态。
InputReader
支持多点触控协议“A”和“B”。新驱动程序应该使用“B”协议,但是使用任一协议均可正常运作。根据 Android Ice Cream Sandwich 4.0,可能需要更改触摸屏驱动程序,以符合 Linux 输入协议规范。
可能需要进行以下更改:
当一个工具变为非活动状态(“抬起”一根手指)时,它应该停止显示在后续的多点触控同步报告中。当所有工具变为非活动状态(“抬起”所有手指)时,驱动程序应发送一个空的同步报告数据包,如
SYN_MT_REPORT
后跟SYN_REPORT
。以前版本的 Android 通过发送压力值 0 来报告“抬起”事件。该旧行为与 Linux 输入协议规范不兼容,因此不再受支持。
物理压力或信号强度信息应使用
ABS_MT_PRESSURE
进行报告。以前版本的 Android 从
ABS_MT_TOUCH_MAJOR
检索压力信息。该旧行为与 Linux 输入协议规范不兼容,因此不再受支持。触摸尺寸信息应使用
ABS_MT_TOUCH_MAJOR
进行报告。以前版本的 Android 从
ABS_MT_TOOL_MAJOR
检索尺寸信息。该旧行为与 Linux 输入协议规范不兼容,因此不再受支持。
触摸设备驱动程序不再需要 Android 系统专用的自定义设置。通过依靠标准的 Linux 输入协议,Android 可以使用未经修改的驱动程序来支持更多种类的触摸外设,如外部 HID 多点触控触摸屏。
触摸设备操作
下面简要汇总了 Android 上的触摸设备操作。
EventHub
从evdev
驱动程序读取原始事件。InputReader
消耗原始事件,并更新关于每个工具的位置和其他特征的内部状态。它还会跟踪按钮状态。如果按下或释放“后退”或“前进”按钮,
InputReader
会向InputDispatcher
发出按键事件通知。InputReader
确定是否发生了虚拟按键的按压操作。如果是,它会向InputDispatcher
发出按键事件通知。InputReader
确定触摸行为是否在显示范围内发起的。如果是,它会向InputDispatcher
发出触摸事件通知。如果没有触摸工具,但至少有一个悬停工具,则
InputReader
会向InputDispatcher
发出悬停事件通知。如果触摸设备类型是指控设备,则
InputReader
会执行指针手势检测,相应地移动指针和相关点,并通知InputDispatcher
指针事件。InputDispatcher
使用WindowManagerPolicy
来确定是否应该调度这些事件,以及它们是否应该唤醒设备。然后,InputDispatcher
将事件传递给相应的应用。
触摸设备配置
触摸设备行为由设备的坐标轴、按钮、输入属性、输入设备配置、虚拟按键映射和按键布局确定。
要详细了解参与键盘配置的文件,请参阅以下部分:
属性
系统依赖于许多输入设备配置属性来配置和校准触摸设备行为。
原因之一是触摸设备的设备驱动程序通常使用特定于设备的单元来报告触摸特性。
例如,许多触摸设备使用内部特定于设备的比例(例如由触摸触发的传感器节点的总数)来测量触摸接触面积。此原始尺寸值对应用来说没有意义,因为它们需要了解触摸设备传感器节点的物理尺寸和其他特性。
系统使用在输入设备配置文件中编码的校准参数,将触摸设备报告的值解码、转换和标准化为应用可以理解的更简单的标准表示。
文档规范
对本文档而言,我们将使用以下规范来描述系统在校准过程中使用的值。
原始轴值
以下表达式表示触摸设备驱动程序作为 EV_ABS
事件报告的原始值。
raw.x
ABS_X
或ABS_MT_POSITION_X
轴的值。raw.y
ABS_Y
或ABS_MT_POSITION_Y
轴的值。raw.pressure
ABS_PRESSURE
或ABS_MT_PRESSURE
轴的值,如果未提供,则为 0。raw.touchMajor
ABS_MT_TOUCH_MAJOR
轴的值,如果未提供,则为 0。raw.touchMinor
ABS_MT_TOUCH_MINOR
轴的值,如果未提供,则为raw.touchMajor
。raw.toolMajor
ABS_TOOL_WIDTH
或ABS_MT_WIDTH_MAJOR
轴的值,如果未提供,则为 0。raw.toolMinor
ABS_MT_WIDTH_MINOR
轴的值,如果未提供,则为raw.toolMajor
。raw.orientation
ABS_MT_ORIENTATION
轴的值,如果未提供,则为 0。raw.distance
ABS_DISTANCE
或ABS_MT_DISTANCE
轴的值,如果未提供,则为 0。raw.tiltX
ABS_TILT_X
轴的值,如果未提供,则为 0。raw.tiltY
ABS_TILT_Y
轴的值,如果未提供,则为 0。
原始轴范围
以下表达式表示原始值的范围。通过为每个轴调用 EVIOCGABS
ioctl 获得它们。
raw.*.min
- 原始轴的最小值(含)。
raw.*.max
- 原始轴的最大值(含)。
raw.*.range
- 相当于
raw.*.max - raw.*.min
。 raw.*.fuzz
- 原始轴的精度。例如,fuzz = 1 表示值精确到 +/- 1 个单位。
raw.width
- 触摸区域的宽度(含),相当于
raw.x.range + 1
。 raw.height
- 触摸区域的高度(含),相当于
raw.y.range + 1
。
输出范围
以下表达式表示输出坐标系的特性。系统使用线性插值将触摸设备使用的 Surface 单元的触摸位置信息转换成将报告给应用的输出单元(如显示像素)。
output.width
- 输出宽度。对于触摸屏(与显示屏相关联),输出宽度是显示屏宽度(以像素为单位)。对于触摸板(不与显示屏相关联),输出宽度等于
raw.width
,表示不会插入值。 output.height
- 输出高度。对于触摸屏(与显示屏相关联),输出高度是显示屏高度(以像素为单位)。对于触摸板(不与显示屏相关联),输出高度等于
raw.height
,表示不会插入值。 output.diag
- 输出坐标系的对角线长度,相当于
sqrt(output.width ^2 + output.height ^2)
。
基础配置
触摸输入映射器在输入设备配置文件中使用许多配置属性来指定校准值。下表介绍了一些通用配置属性。在下面的部分中介绍了所有其他属性及其进行校准所用的字段。
touch.deviceType
定义:touch.deviceType
= touchScreen
| touchPad
| pointer
| default
指定触摸设备类型。
如果值为
touchScreen
,则触摸设备是与显示屏相关联的触摸屏。如果值为
touchPad
,则触摸设备是不与显示屏相关联的触摸板。如果值为
pointer
,则触摸设备是不与显示屏相关联的触摸板,并且其动作用于间接多点触控指控手势。如果值为
default
,则系统将根据分类算法自动检测设备类型。
有关设备类型如何影响触摸设备的行为的详细信息,请参阅分类部分。
在 Honeycomb 之前,所有触摸设备都被视为触摸屏。
touch.orientationAware
定义:touch.orientationAware
= 0
| 1
指定触摸设备是否应对显示屏的方向更改做出响应。
如果值为
1
,则只要显示屏的方向更改了,触摸设备报告的触摸位置就会旋转。如果值为
0
,则触摸设备报告的触摸位置将不受显示屏方向更改的影响。
如果设备是触摸屏,则默认值为 1
,否则为 0
。
系统会区分内部和外部触摸屏与显示部分。方向感知型内部触摸屏基于内部显示部分的方向进行旋转。方向感知型外部触摸屏基于外部显示部分的方向进行旋转。
方向感知功能用于支持 Nexus One 等设备上的触摸屏旋转。例如,当设备从其自然方向顺时针旋转 90 度时,触摸的绝对位置将被重新映射,使得在触摸屏绝对坐标系左上角的触摸行为被报告为在显示屏旋转坐标系左上角的触摸行为。这样做是为了使用应用绘制其可见元素时所用的同一坐标系报告触摸行为。
在 Honeycomb 之前,所有触摸设备都被视为具有方向感知功能。
touch.gestureMode
定义:touch.gestureMode
= pointer
| spots
| default
指定指控手势的表示模式。仅在触摸设备为指控类型时,该配置属性才具有相关性。
如果值为
pointer
,则触摸板手势将通过与鼠标指针相似的光标来表示。如果值为
spots
,则触摸板手势由代表手势形心的锚点和代表各个手指位置的一组圆形斑点来表示。
如果设置了 INPUT_PROP_SEMI_MT
输入属性,则默认值为 pointer
,否则为 spots
。
X
和 Y
字段
X 和 Y 字段给出了接触区域中心的位置信息。
计算
计算非常简单:来自触摸驱动程序的位置信息被线性插入输出坐标系。
xScale = output.width / raw.width
yScale = output.height / raw.height If not orientation aware or screen rotation is 0 degrees:
output.x = (raw.x - raw.x.min) * xScale
output.y = (raw.y - raw.y.min) * yScale
Else If rotation is 90 degrees:
output.x = (raw.y - raw.y.min) * yScale
output.y = (raw.x.max - raw.x) * xScale
Else If rotation is 180 degrees:
output.x = (raw.x.max - raw.x) * xScale
output.y = (raw.y.max - raw.y) * yScale
Else If rotation is 270 degrees:
output.x = (raw.y.max - raw.y) * yScale
output.y = (raw.x - raw.x.min) * xScale
End If
TouchMajor
、TouchMinor
、ToolMajor
、ToolMinor
、Size
字段
TouchMajor
和 TouchMinor
字段描述了在输出单元中接触区域的大致维度(单位为像素)。
ToolMajor
和 ToolMinor
字段描述了在输出单元中工具本身的大致维度(单位为像素)。
Size
字段描述了相对于触摸设备可以感知的最大可能触摸区域的标准化触摸区域尺寸。可能的最小标准化尺寸为 0.0(无接触或不可测量),可能的最大标准化尺寸为 1.0(传感器区域已经完全覆盖)。
如果可以同时测量近似长度和宽度,则 TouchMajor
字段会指定接触区域的较长维度,TouchMinor
字段会指定接触区域的较短维度。如果只能测量接触区域的大致直径,则 TouchMajor
和 TouchMinor
字段将相等。
同样,ToolMajor
字段会指定工具截断面的较长维度,ToolMinor
字段会指定工具截断面的较短维度。
如果触摸尺寸不可测量,但工具尺寸可测量,则工具尺寸将设为等于触摸尺寸。相反,如果工具尺寸不可测量,但触摸尺寸可测量,则触摸尺寸将设为等于工具尺寸。
触摸设备以各种方式测量或报告触摸尺寸和工具尺寸。目前的实现支持三种不同的测量方式:Surface 单元内的直径、面积和几何边界区域。
touch.size.calibration
定义:touch.size.calibration
= none
| geometric
| diameter
| area
| default
指定触摸驱动程序报告触摸尺寸和工具尺寸时所用的测量类型。
如果值为
none
,则尺寸设为零。如果值为
geometric
,则假定以与位置相同的 Surface 单元指定尺寸,从而以相同的方式对尺寸进行缩放。如果值为
diameter
,则假定尺寸与触摸或工具直径(宽度)成比例。如果值为
area
,则假定尺寸与触摸或工具面积成比例。如果值为
default
,那么在raw.touchMajor
或raw.toolMajor
轴提供值的情况下,系统将使用geometric
校准,否则将使用none
校准。
touch.size.scale
定义:touch.size.scale
= <非负浮点数>
指定校准中使用的恒定比例因子。
默认值为 1.0
。
touch.size.bias
定义:touch.size.bias
= <非负浮点数>
指定校准中使用的恒定偏差值。
默认值为 0.0
。
touch.size.isSummed
定义:touch.size.isSummed
= 0
| 1
指定尺寸是报告为所有有效接触区域的尺寸总和,还是针对每个接触区域单独报告尺寸。
如果值为
1
,则报告的尺寸需除以接触数量,然后才能使用。如果值为
0
,则报告的尺寸将按原样使用。
默认值为 0
。
一些触摸设备(尤其是“Semi-MT”设备)无法区分多个接触点的单个维度,因此它们会报告表示其总面积或宽度的尺寸测量结果。对于此类设备,此属性只能设为 1
。如果有疑问,请将此值设为 0
。
计算
TouchMajor
、TouchMinor
、ToolMajor
、ToolMinor
和 Size
字段的计算方法取决于指定的校准参数。
If raw.touchMajor and raw.toolMajor are available:
touchMajor = raw.touchMajor
touchMinor = raw.touchMinor
toolMajor = raw.toolMajor
toolMinor = raw.toolMinor
Else If raw.touchMajor is available:
toolMajor = touchMajor = raw.touchMajor
toolMinor = touchMinor = raw.touchMinor
Else If raw.toolMajor is available:
touchMajor = toolMajor = raw.toolMajor
touchMinor = toolMinor = raw.toolMinor
Else
touchMajor = toolMajor = 0
touchMinor = toolMinor = 0
size = 0
End If size = avg(touchMajor, touchMinor) If touch.size.isSummed == 1:
touchMajor = touchMajor / numberOfActiveContacts
touchMinor = touchMinor / numberOfActiveContacts
toolMajor = toolMajor / numberOfActiveContacts
toolMinor = toolMinor / numberOfActiveContacts
size = size / numberOfActiveContacts
End If If touch.size.calibration == "none":
touchMajor = toolMajor = 0
touchMinor = toolMinor = 0
size = 0
Else If touch.size.calibration == "geometric":
outputScale = average(output.width / raw.width, output.height / raw.height)
touchMajor = touchMajor * outputScale
touchMinor = touchMinor * outputScale
toolMajor = toolMajor * outputScale
toolMinor = toolMinor * outputScale
Else If touch.size.calibration == "area":
touchMajor = sqrt(touchMajor)
touchMinor = touchMajor
toolMajor = sqrt(toolMajor)
toolMinor = toolMajor
Else If touch.size.calibration == "diameter":
touchMinor = touchMajor
toolMinor = toolMajor
End If If touchMajor != 0:
output.touchMajor = touchMajor * touch.size.scale + touch.size.bias
Else
output.touchMajor = 0
End If If touchMinor != 0:
output.touchMinor = touchMinor * touch.size.scale + touch.size.bias
Else
output.touchMinor = 0
End If If toolMajor != 0:
output.toolMajor = toolMajor * touch.size.scale + touch.size.bias
Else
output.toolMajor = 0
End If If toolMinor != 0:
output.toolMinor = toolMinor * touch.size.scale + touch.size.bias
Else
output.toolMinor = 0
End If output.size = size
Pressure
字段
Pressure
字段描述了以介于 0.0(无接触)和 1.0(全力)之间的标准化值形式施加到触摸设备的近似物理压力。
零压力表示工具处于悬停状态。
touch.pressure.calibration
定义:touch.pressure.calibration
= none
| physical
| amplitude
| default
指定触摸驱动程序报告压力所用的测量类型。
如果值为
none
,压力未知,因此触摸时设置为 1.0,悬停时为 0.0。如果值为
physical
,则认为压力轴测量的是施加到触摸板的压力的实际物理强度。如果值为
amplitude
,则认为压力轴测量的是信号幅度(与接触的尺寸和施加的压力有关)。如果值为
default
,在压力轴可用的情况下,系统将使用physical
校准,否则使用none
。
touch.pressure.scale
定义:touch.pressure.scale
= <非负浮点数>
指定校准中使用的恒定比例因子。
默认值为 1.0 / raw.pressure.max
。
计算
Pressure
字段的计算方法取决于指定的校准参数。
If touch.pressure.calibration == "physical" or "amplitude":
output.pressure = raw.pressure * touch.pressure.scale
Else
If hovering:
output.pressure = 0
Else
output.pressure = 1
End If
End If
Orientation
和 Tilt
字段
Orientation
字段以角度测量的形式描述了触摸和工具的方向。值 0
表示长轴垂直取向,-PI/2
表示长轴朝向左侧,PI/2
表示长轴朝向右侧。当存在触控笔工具时,方向范围可以是从 -PI
到 PI
的整个圆环范围。
Tilt
字段通过测量角度描述了工具的倾斜度。倾斜度为 0
表示工具垂直于表面。倾斜度为 PI/2
表示工具与表面平行。
touch.orientation.calibration
定义:touch.orientation.calibration
= none
| interpolated
| vector
| default
指定触摸驱动程序报告方向时所用的测量类型。
如果值为
none
,则方向未知,因此设为 0。如果值为
interpolated
,则方向被线性插入,使得raw.orientation.min
的原始值映射到-PI/2
,raw.orientation.max
的原始值映射到PI/2
。(raw.orientation.min + raw.orientation.max) / 2
的中心值映射到0
。如果值为
vector
,则方向表示为包含两个带符号的 4 位字段的压缩向量。该表示用于 Atmel 基于对象的协议部分。当解码时,向量生成定向角和置信度。置信度用于缩放尺寸信息,除非它是几何图形。如果值为
default
,那么在方向轴可用的情况下,系统将使用interpolated
校准,否则使用none
。
计算
Orientation
和 Tilt
字段的计算方法取决于指定的校准参数和可用输入。
If touch.tiltX and touch.tiltY are available:
tiltXCenter = average(raw.tiltX.min, raw.tiltX.max)
tiltYCenter = average(raw.tiltY.min, raw.tiltY.max)
tiltXAngle = (raw.tiltX - tiltXCenter) * PI / 180
tiltYAngle = (raw.tiltY - tiltYCenter) * PI / 180
output.orientation = atan2(-sin(tiltXAngle), sinf(tiltYAngle))
output.tilt = acos(cos(tiltXAngle) * cos(tiltYAngle))
Else If touch.orientation.calibration == "interpolated":
center = average(raw.orientation.min, raw.orientation.max)
output.orientation = PI / (raw.orientation.max - raw.orientation.min)
output.tilt = 0
Else If touch.orientation.calibration == "vector":
c1 = (raw.orientation & 0xF0) >> 4
c2 = raw.orientation & 0x0F If c1 != 0 or c2 != 0:
If c1 >= 8 Then c1 = c1 - 16
If c2 >= 8 Then c2 = c2 - 16
angle = atan2(c1, c2) / 2
confidence = sqrt(c1*c1 + c2*c2) output.orientation = angle If touch.size.calibration == "diameter" or "area":
scale = 1.0 + confidence / 16
output.touchMajor *= scale
output.touchMinor /= scale
output.toolMajor *= scale
output.toolMinor /= scale
End If
Else
output.orientation = 0
End If
output.tilt = 0
Else
output.orientation = 0
output.tilt = 0
End If If orientation aware:
If screen rotation is 90 degrees:
output.orientation = output.orientation - PI / 2
Else If screen rotation is 270 degrees:
output.orientation = output.orientation + PI / 2
End If
End If
Distance
字段
Distance
字段描述了工具和触摸设备表面之间的距离。值 0.0 表示直接接触,值越大,表示与表面之间的距离越远。
touch.distance.calibration
定义:touch.distance.calibration
= none
| scaled
| default
指定触摸驱动程序报告距离时所用的测量类型。
如果值为
none
,则距离未知,因此设为 0。如果值为
scaled
,则报告的距离将乘以恒定比例因子。如果值为
default
,则在距离轴可用的情况下,系统将使用scaled
校准,否则使用none
。
touch.distance.scale
定义:touch.distance.scale
= <非负浮点数>
指定校准中使用的恒定比例因子。
默认值为 1.0
。
计算
Distance
字段的计算方法取决于指定的校准参数。
If touch.distance.calibration == "scaled":
output.distance = raw.distance * touch.distance.scale
Else
output.distance = 0
End If
示例
# Input device configuration file for a touch screen that supports pressure,
# size and orientation. The pressure and size scale factors were obtained
# by measuring the characteristics of the device itself and deriving
# useful approximations based on the resolution of the touch sensor and the
# display.
#
# Note that these parameters are specific to a particular device model.
# Different parameters will need to be used for other devices. # Basic Parameters
touch.deviceType = touchScreen
touch.orientationAware = 1 # Size
# Based on empirical measurements, we estimate the size of the contact
# using size = sqrt(area) * 28 + 0.
touch.size.calibration = area
touch.size.scale = 28
touch.size.bias = 0
touch.size.isSummed = 0 # Pressure
# Driver reports signal strength as pressure.
#
# A normal index finger touch typically registers about 80 signal strength
# units although we don't expect these values to be accurate.
touch.pressure.calibration = amplitude
touch.pressure.scale = 0.0125 # Orientation
touch.orientation.calibration = vector
兼容性说明
触摸设备的配置属性在 Android Ice Cream Sandwich 4.0 中发生了重大变化。必须更新触摸设备的所有输入设备配置文件,才能使用新配置属性。
更旧的触摸设备驱动程序可能也需要更新。
虚拟按键映射文件
触摸设备经常用于实现虚拟按键。
有几种方法可以做到这一点,具体取决于触摸控制器的功能。一些触摸控制器可以直接配置为通过设置固件寄存器来实现软键。其他时候,最好在软件中执行从触摸坐标到按键代码的映射。
在软件中实现虚拟按键时,内核必须将名为 virtualkeys.<devicename>
的虚拟按键映射文件作为本机已加载属性导出。例如,如果触摸屏设备驱动程序将其名称报告为“touchyfeely”,则虚拟按键映射文件的路径必须为 /sys/board_properties/virtualkeys.touchyfeely
。
虚拟按键映射文件描述了触摸屏上虚拟按键的坐标和 Linux 按键代码。
除了虚拟按键映射文件外,还必须有一个对应的按键布局文件和按键字符映射文件,以将 Linux 按键代码映射到 Android 按键代码,并指定键盘设备的类型(通常为 SPECIAL_FUNCTION
)。
语法
虚拟按键映射文件是一个纯文本文件,由一系列用换行符或冒号分隔的虚拟按键布局描述组成。
注释行以“#”开头,并持续到这一行的结束位置。
每个虚拟按键用由 6 个冒号分隔的组件进行描述:
0x01
:版本代码。必须始终为0x01
。- <Linux key code>:虚拟按键的 Linux 按键代码。
- <centerX>:虚拟按键中心的 X 轴坐标(以像素为单位)。
- <centerY>:虚拟按键中心的 Y 轴坐标(以像素为单位)。
- <width>:虚拟按键的宽度(以像素为单位)。
- <height>:虚拟按键的高度(以像素为单位)。
所有的坐标和尺寸都是根据显示坐标系指定的。
下面是一个虚拟按键映射文件,全部写在一行上。
# All on one line
0x01:158:55:835:90:55:0x01:139:172:835:125:55:0x01:102:298:835:115:55:0x01:217:412:835:95:55
相同的虚拟按键映射文件也可以写在多行上。
# One key per line
0x01:158:55:835:90:55
0x01:139:172:835:125:55
0x01:102:298:835:115:55
0x01:217:412:835:95:55
在上述示例中,触摸屏具有 480×800 的分辨率。因此,所有虚拟按键的 <centerY> 坐标为 835,位于略低于触摸屏可见区域的位置。
第一个按键的 Linux 扫描代码为 158
(KEY_BACK
),centerX 为 55
,centerY 为 835
,width 为 90
,height 为 55
。
示例
虚拟按键映射文件:/sys/board_properties/virtualkeys.touchyfeely
。
0x01:158:55:835:90:55
0x01:139:172:835:125:55
0x01:102:298:835:115:55
0x01:217:412:835:95:55
按键布局文件:/system/usr/keylayout/touchyfeely.kl
。
key 158 BACK
key 139 MENU
key 172 HOME
key 217 SEARCH
按键字符映射文件:/system/usr/keychars/touchyfeely.kcm
。
type SPECIAL_FUNCTION
间接多点触控指控手势
在指控模式下,系统会解释以下手势:
单指点按:点击。
单指移动:移动指针。
单指移动加按下按钮:拖动指针。
两个手指移动(两个手指沿相同的方向移动):沿着该方向拖动指针下方的区域。指针本身不动。
两个手指移动(两个手指朝着彼此移动或者移向不同方向):平移/缩放/旋转指针周围的区域。指针本身不动。
多个手指移动:自由手势。
延伸阅读
【转】Android-Input 触摸设备的更多相关文章
- Linux Android 多点触摸协议 原文出自【比特网】,转载请保留原文链接:http://soft.chinabyte.com/os/71/12306571.shtml
为了使用功能强大的多点触控设备,就需要一种方案去上报用户层所需的详细的手指触摸数据.这个文档所描述的多点触控协议可以让内核驱动程序向用户层上报任意多指的数据信息. 使用说明 单点触摸信息是以ABS承载 ...
- Linux与Android 多点触摸协议【转】
本文转载自:http://blog.csdn.net/xubin341719/article/details/7833277 一.Linux与Android 多点触摸协议 为了使用功能强大的多点触控设 ...
- Linux & Android 多点触摸协议
Linux & Android 多点触摸协议 Android4.0多点触摸入门 1 KERNEL 对于触摸屏的驱动我们简单的划分为两个主要的部分,一个是注册,另一个是上报. 1.1 注册 单点 ...
- Linux/Android——Input系统之InputMapper 处理 (八)【转】
本文转载自:http://blog.csdn.net/jscese/article/details/43561773 前文Linux/Android——Input系统之InputReader (七)介 ...
- Linux/Android——Input系统之InputReader (七)【转】
本文转载自:http://blog.csdn.net/jscese/article/details/42739197 在前文Linux/Android——Input系统之frameworks层Inpu ...
- Linux/Android——input系统之 kernel层 与 frameworks层交互 (五)【转】
本文转载自:http://blog.csdn.net/jscese/article/details/42291149 之前的四篇博文记录的都是linux中的input体系相关的东西,最底层以我调试的u ...
- Linux/Android——input子系统核心 (三)【转】
本文转载自:http://blog.csdn.net/jscese/article/details/42123673 之前的博客有涉及到linux的input子系统,这里学习记录一下input模块. ...
- WPF 插拔触摸设备触摸失效
原文:WPF 插拔触摸设备触摸失效 最近使用 WPF 程序,在不停插拔触摸设备会让 WPF 程序触摸失效.通过分析 WPF 源代码可以找到 WPF 触摸失效的原因. 在 Windows 会将所有的 H ...
- 2018-8-15-WPF-插拔触摸设备触摸失效
title author date CreateTime categories WPF 插拔触摸设备触摸失效 lindexi 2018-08-15 08:12:47 +0800 2018-08-09 ...
随机推荐
- Java程序设计的第二次作业
本次作业包含两个部分:一是以下4个题目的程序源码和运行结果截图:二是本次作业的小结(谈谈你在做作业的过程中遇到了哪些问题,如何解决,有哪些收获). 1.编写“人”类及其测试类.1.1 “人”类: 类 ...
- OO-第一单元总结
经过了前三次作业和两次实验的引导,我的编程思路在逐步从面向过程转向面向对象.也对面向对象有了初步的理解.虽然第一次实验由于自己没有及时完成导致没有提交过有些遗憾,但是第二次实验还是提交了几次的(虽然由 ...
- RePr: Improved Training of Convolutional Filters
关键点: 1.关于filter正交 将一层中的一个$k \times k \times c$的卷积核展开为$k * k * c$的向量,表示为$f$.一层中有$J_{\ell}$个卷积核,$\bold ...
- SpringBoot之profile详解
SpringBoot中使用配置文件application.properties&application.yml两种方式,在这两种方式下分别对应各自的profile配置方式,同时还存在命令行.虚 ...
- Sublime Text3安装evernote插件
关键字 Markdown编辑器.Evernote.Sublime Text3 正文 Sublime Text3安装evernote插件方法如下: 1.使用Package Control安装ever ...
- VSCode 启动 Vue 项目 npm install 报错
1. 报错后,查看了版本. 查看node版本:node -v 查看npm版本:npm -v 查看Augular版本:ng --version 2. 感觉 Augular CLI版本太低,使用以下方 ...
- rem 转 px
(function (doc, win) { var docEl = doc.documentElement, resizeEvt = 'orientationchange' in window ? ...
- Redhat 6.3上安装CMake
在编译libssh时,要用到CMake,而且要依赖3.3以上的版本. 尝试了从CMake官网下载源码,编译安装.结果发现各种依赖,比如要升级GCC,升级Python等等,麻烦要死.搞了半天还是一堆问题 ...
- FastCGI 进程意外退出造成500错误
在一台新服务器上,安装新网站,之前只放至了一个网站.是服务器商配置好的,非集成环境. 添加了一个新站,路径都制定好了,但是在访问时出现了500错误.提示貌似是php的问题,但是之前的网站,运行的是di ...
- failed call to cuInit: CUDA_ERROR_NO_DEVICE: no CUDA-capable device is detected 排坑指南
训练maskrcnn时,出现了 failed call to cuInit: CUDA_ERROR_NO_DEVICE: no CUDA-capable device is detected 一开始以 ...