| <!-- |
| Copyright 2011 The Android Open Source Project |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --> |
| |
| # Touch Devices # |
| |
| Android supports a variety of touch screens and touch pads, including |
| stylus-based digitizer tablets. |
| |
| Touch screens are touch devices that are associated with a display such that |
| the user has the impression of directly manipulating items on screen. |
| |
| Touch pads are touch devices that are not associated with a display such as a |
| digitizer tablet. Touch pads are typically used for pointing or for |
| absolute indirect positioning or gesture-based control of a user interface. |
| |
| Touch devices may have buttons whose functions are similar to mouse buttons. |
| |
| Touch devices can sometimes be manipulated using a variety of different tools |
| such as fingers or a stylus depending on the underlying touch sensor technology. |
| |
| Touch devices are sometimes used to implement virtual keys. For example, on |
| some Android devices, the touch screen sensor area extends beyond the edge of |
| the display and serves dual purpose as part of a touch sensitive key pad. |
| |
| Due to the great variety of touch devices, Android relies on a large number of |
| configuration properties to describe the characteristics and desired behavior |
| of each device. |
| |
| ## Touch Device Classification ## |
| |
| An input device is classified as a *multi-touch* device if both of |
| the following conditions hold: |
| |
| * The input device reports the presence of the `ABS_MT_POSITION_X` and |
| `ABS_MT_POSITION_Y` absolute axes. |
| |
| * The input device does not have any gamepad buttons. This condition |
| resolves an ambiguity with certain gamepads that report axes with codes |
| that overlaps those of the MT axes. |
| |
| An input device is classified as a *single-touch* device if both of the |
| following conditions hold: |
| |
| * The input device is not classified as a multi-touch device. An input device |
| is either classified as a single-touch device or as a multi-touch device, |
| never both. |
| |
| * The input device reports the presence of the `ABS_X` and `ABS_Y` absolute |
| axes, and the presence of the `BTN_TOUCH` key code. |
| |
| Once an input device has been classified as a touch device, the presence |
| of virtual keys is determined by attempting to load the virtual key map file |
| for the device. If a virtual key map is available, then the key layout |
| file for the device is also loaded. |
| |
| Refer to the section below about the location and format of virtual key map |
| files. |
| |
| Next, the system loads the input device configuration file for the touch device. |
| |
| **All built-in touch devices should have input device configuration files.** |
| If no input device configuration file is present, the system will |
| choose a default configuration that is appropriate for typical general-purpose |
| touch peripherals such as external USB or Bluetooth HID touch screens |
| or touch pads. These defaults are not designed for built-in touch screens and |
| will most likely result in incorrect behavior. |
| |
| After the input device configuration loaded, the system will classify the |
| input device as a *touch screen*, *touch pad* or *pointer* device. |
| |
| * A *touch screen* device is used for direct manipulation of objects on the |
| screen. Since the user is directly touching the screen, the system does |
| not require any additional affordances to indicate the objects being |
| manipulated. |
| |
| * A *touch pad* device is used to provide absolute positioning information |
| to an application about touches on a given sensor area. It may be useful |
| for digitizer tablets. |
| |
| * A *pointer* device is used for indirect manipulation of objects on the |
| screen using a cursor. Fingers are interpreted as multi-touch pointer |
| gestures. Other tools, such as styluses, are interpreted using |
| absolute positions. |
| |
| See [Indirect Multi-touch Pointer Gestures](#indirect-multi-touch-pointer-gestures) |
| for more information. |
| |
| The following rules are used to classify the input device as a *touch screen*, |
| *touch pad* or *pointer* device. |
| |
| * If the `touch.deviceType` property is set, then the device type will be |
| set as indicated. |
| |
| * If the input device reports the presence of the `INPUT_PROP_DIRECT` |
| input property (via the `EVIOCGPROP` ioctl), then the device type will |
| be set to *touch screen*. This condition assumes that direct input touch |
| devices are attached to a display that is also connected. |
| |
| * If the input device reports the presence of the `INPUT_PROP_POINTER` |
| input property (via the `EVIOCGPROP` ioctl), then the device type will |
| be set to *pointer*. |
| |
| * If the input device reports the presence of the `REL_X` or `REL_Y` relative |
| axes, then the device type will be set to *touch pad*. This condition |
| resolves an ambiguity for input devices that consist of both a mouse and |
| a touch pad. In this case, the touch pad will not be used to control |
| the pointer because the mouse already controls it. |
| |
| * Otherwise, the device type will be set to *pointer*. This default ensures |
| that touch pads that have not been designated any other special purpose |
| will serve to control the pointer. |
| |
| ## Buttons ## |
| |
| Buttons are *optional* controls that may be used by applications to perform |
| additional functions. Buttons on touch devices behave similarly to mouse |
| buttons and are mainly of use with *pointer* type touch devices or with a |
| stylus. |
| |
| The following buttons are supported: |
| |
| * `BTN_LEFT`: mapped to `MotionEvent.BUTTON_PRIMARY`. |
| |
| * `BTN_RIGHT`: mapped to `MotionEvent.BUTTON_SECONDARY`. |
| |
| * `BTN_MIDDLE`: mapped to `MotionEvent.BUTTON_MIDDLE`. |
| |
| * `BTN_BACK` and `BTN_SIDE`: mapped to `MotionEvent.BUTTON_BACK`. |
| Pressing this button also synthesizes a key press with the key code |
| `KeyEvent.KEYCODE_BACK`. |
| |
| * `BTN_FORWARD` and `BTN_EXTRA`: mapped to `MotionEvent.BUTTON_FORWARD`. |
| Pressing this button also synthesizes a key press with the key code |
| `KeyEvent.KEYCODE_FORWARD`. |
| |
| * `BTN_STYLUS`: mapped to `MotionEvent.BUTTON_SECONDARY`. |
| |
| * `BTN_STYLUS2`: mapped to `MotionEvent.BUTTON_TERTIARY`. |
| |
| ## Tools and Tool Types ## |
| |
| A *tool* is a finger, stylus or other apparatus that is used to interact with |
| the touch device. Some touch devices can distinguish between different |
| types of tools. |
| |
| Elsewhere in Android, as in the `MotionEvent` API, a *tool* is often referred |
| to as a *pointer*. |
| |
| The following tool types are supported: |
| |
| * `BTN_TOOL_FINGER` and `MT_TOOL_FINGER`: mapped to `MotionEvent.TOOL_TYPE_FINGER`. |
| |
| * `BTN_TOOL_PEN` and `MT_TOOL_PEN`: mapped to `MotionEvent.TOOL_TYPE_STYLUS`. |
| |
| * `BTN_TOOL_RUBBER`: mapped to `MotionEvent.TOOL_TYPE_ERASER`. |
| |
| * `BTN_TOOL_BRUSH`: mapped to `MotionEvent.TOOL_TYPE_STYLUS`. |
| |
| * `BTN_TOOL_PENCIL`: mapped to `MotionEvent.TOOL_TYPE_STYLUS`. |
| |
| * `BTN_TOOL_AIRBRUSH`: mapped to `MotionEvent.TOOL_TYPE_STYLUS`. |
| |
| * `BTN_TOOL_MOUSE`: mapped to `MotionEvent.TOOL_TYPE_MOUSE`. |
| |
| * `BTN_TOOL_LENS`: mapped to `MotionEvent.TOOL_TYPE_MOUSE`. |
| |
| * `BTN_TOOL_DOUBLETAP`, `BTN_TOOL_TRIPLETAP`, and `BTN_TOOL_QUADTAP`: |
| mapped to `MotionEvent.TOOL_TYPE_FINGER`. |
| |
| ## Hovering vs. Touching Tools ## |
| |
| Tools can either be in contact with the touch device or in range and hovering |
| above it. Not all touch devices are able to sense the presence of a tool |
| hovering above the touch device. Those that do, such as RF-based stylus digitizers, |
| can often detect when the tool is within a limited range of the digitizer. |
| |
| The `InputReader` component takes care to distinguish touching tools from hovering |
| tools. Likewise, touching tools and hovering tools are reported to applications |
| in different ways. |
| |
| Touching tools are reported to applications as touch events |
| using `MotionEvent.ACTION_DOWN`, `MotionEvent.ACTION_MOVE`, `MotionEvent.ACTION_DOWN`, |
| `MotionEvent.ACTION_POINTER_DOWN` and `MotionEvent.ACTION_POINTER_UP`. |
| |
| Hovering tools are reported to applications as generic motion events using |
| `MotionEvent.ACTION_HOVER_ENTER`, `MotionEvent.ACTION_HOVER_MOVE` |
| and `MotionEvent.ACTION_HOVER_EXIT`. |
| |
| ## Touch Device Driver Requirements ## |
| |
| 1. Touch device drivers should only register axes and key codes for the axes |
| and buttons that they actually support. Registering excess axes or key codes |
| may confuse the device classification algorithm or cause the system to incorrectly |
| detect the capabilities of the device. |
| |
| For example, if the device reports the `BTN_TOUCH` key code, the system will |
| assume that `BTN_TOUCH` will always be used to indicate whether the tool is |
| actually touching the screen or is merely in range and hovering. |
| |
| 2. Single-touch devices use the following Linux input events: |
| |
| * `ABS_X`: *(REQUIRED)* Reports the X coordinate of the tool. |
| |
| * `ABS_Y`: *(REQUIRED)* Reports the Y coordinate of the tool. |
| |
| * `ABS_PRESSURE`: *(optional)* Reports the physical pressure applied to the tip |
| of the tool or the signal strength of the touch contact. |
| |
| * `ABS_TOOL_WIDTH`: *(optional)* Reports the cross-sectional area or width of the |
| touch contact or of the tool itself. |
| |
| * `ABS_DISTANCE`: *(optional)* Reports the distance of the tool from the surface of |
| the touch device. |
| |
| * `ABS_TILT_X`: *(optional)* Reports the tilt of the tool from the surface of the |
| touch device along the X axis. |
| |
| * `ABS_TILT_Y`: *(optional)* Reports the tilt of the tool from the surface of the |
| touch device along the Y axis. |
| |
| * `BTN_TOUCH`: *(REQUIRED)* Indicates whether the tool is touching the device. |
| |
| * `BTN_LEFT`, `BTN_RIGHT`, `BTN_MIDDLE`, `BTN_BACK`, `BTN_SIDE`, `BTN_FORWARD`, |
| `BTN_EXTRA`, `BTN_STYLUS`, `BTN_STYLUS2`: |
| *(optional)* Reports [button](#buttons) states. |
| |
| * `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`: |
| *(optional)* Reports the [tool type](#tools-and-tool-types). |
| |
| 3. Multi-touch devices use the following Linux input events: |
| |
| * `ABS_MT_POSITION_X`: *(REQUIRED)* Reports the X coordinate of the tool. |
| |
| * `ABS_MT_POSITION_Y`: *(REQUIRED)* Reports the Y coordinate of the tool. |
| |
| * `ABS_MT_PRESSURE`: *(optional)* Reports the physical pressure applied to the |
| tip of the tool or the signal strength of the touch contact. |
| |
| * `ABS_MT_TOUCH_MAJOR`: *(optional)* Reports the cross-sectional area of the |
| touch contact, or the length of the longer dimension of the touch contact. |
| |
| * `ABS_MT_TOUCH_MINOR`: *(optional)* Reports the length of the shorter dimension of the |
| touch contact. This axis should not be used if `ABS_MT_TOUCH_MAJOR` is reporting an |
| area measurement. |
| |
| * `ABS_MT_WIDTH_MAJOR`: *(optional)* Reports the cross-sectional area of the tool itself, |
| or the length of the longer dimension of the tool itself. |
| This axis should not be used if the dimensions of the tool itself are unknown. |
| |
| * `ABS_MT_WIDTH_MINOR`: *(optional)* Reports the length of the shorter dimension of |
| the tool itself. This axis should not be used if `ABS_MT_WIDTH_MAJOR` is reporting |
| an area measurement or if the dimensions of the tool itself are unknown. |
| |
| * `ABS_MT_ORIENTATION`: *(optional)* Reports the orientation of the tool. |
| |
| * `ABS_MT_DISTANCE`: *(optional)* Reports the distance of the tool from the |
| surface of the touch device. |
| |
| * `ABS_MT_TOOL_TYPE`: *(optional)* Reports the [tool type](#tools-and-tool-types) as |
| `MT_TOOL_FINGER` or `MT_TOOL_PEN`. |
| |
| * `ABS_MT_TRACKING_ID`: *(optional)* Reports the tracking id of the tool. |
| The tracking id is an arbitrary non-negative integer that is used to identify |
| and track each tool independently when multiple tools are active. For example, |
| when multiple fingers are touching the device, each finger should be assigned a distinct |
| tracking id that is used as long as the finger remains in contact. Tracking ids |
| may be reused when their associated tools move out of range. |
| |
| * `ABS_MT_SLOT`: *(optional)* Reports the slot id of the tool, when using the Linux |
| multi-touch protocol 'B'. Refer to the Linux multi-touch protocol documentation |
| for more details. |
| |
| * `BTN_TOUCH`: *(REQUIRED)* Indicates whether the tool is touching the device. |
| |
| * `BTN_LEFT`, `BTN_RIGHT`, `BTN_MIDDLE`, `BTN_BACK`, `BTN_SIDE`, `BTN_FORWARD`, |
| `BTN_EXTRA`, `BTN_STYLUS`, `BTN_STYLUS2`: |
| *(optional)* Reports [button](#buttons) states. |
| |
| * `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`: |
| *(optional)* Reports the [tool type](#tools-and-tool-types). |
| |
| 4. If axes for both the single-touch and multi-touch protocol are defined, then |
| only the multi-touch axes will be used and the single-touch axes will be ignored. |
| |
| 5. The minimum and maximum values of the `ABS_X`, `ABS_Y`, `ABS_MT_POSITION_X` |
| and `ABS_MT_POSITION_Y` axes define the bounds of the active area of the device |
| in device-specific surface units. In the case of a touch screen, the active area |
| describes the part of the touch device that actually covers the display. |
| |
| For a touch screen, the system automatically interpolates the reported touch |
| positions in surface units to obtain touch positions in display pixels according |
| to the following calculation: |
| |
| displayX = (x - minX) * displayWidth / (maxX - minX + 1) |
| displayY = (y - minY) * displayHeight / (maxY - minY + 1) |
| |
| A touch screen may report touches outside of the reported active area. |
| |
| Touches that are initiated outside the active area are not delivered to applications |
| but may be used for virtual keys. |
| |
| Touches that are initiated inside the active area, or that enter and exit the display |
| area are delivered to applications. Consequently, if a touch starts within the |
| bounds of an application and then moves outside of the active area, the application |
| may receive touch events with display coordinates that are negative or beyond the |
| bounds of the display. This is expected behavior. |
| |
| A touch device should never clamp touch coordinates to the bounds of the active |
| area. If a touch exits the active area, it should be reported as being outside of |
| the active area, or it should not be reported at all. |
| |
| For example, if the user's finger is touching near the top-left corner of the |
| touch screen, it may report a coordinate of (minX, minY). If the finger continues |
| to move further outside of the active area, the touch screen should either start |
| reporting coordinates with components less than minX and minY, such as |
| (minX - 2, minY - 3), or it should stop reporting the touch altogether. |
| In other words, the touch screen should *not* be reporting (minX, minY) |
| when the user's finger is really touching outside of the active area. |
| |
| Clamping touch coordinates to the display edge creates an artificial |
| hard boundary around the edge of the screen which prevents the system from |
| smoothly tracking motions that enter or exit the bounds of the display area. |
| |
| 6. The values reported by `ABS_PRESSURE` or `ABS_MT_PRESSURE`, if they |
| are reported at all, must be non-zero when the tool is touching the device |
| and zero otherwise to indicate that the tool is hovering. |
| |
| Reporting pressure information is *optional* but strongly recommended. |
| Applications can use pressure information to implement pressure-sensitive drawing |
| and other effects. |
| |
| 7. The values reported by `ABS_TOOL_WIDTH`, `ABS_MT_TOUCH_MAJOR`, `ABS_MT_TOUCH_MINOR`, |
| `ABS_MT_WIDTH_MAJOR`, or `ABS_MT_WIDTH_MINOR` should be non-zero when the tool |
| is touching the device and zero otherwise, but this is not required. |
| For example, the touch device may be able to measure the size of finger touch |
| contacts but not stylus touch contacts. |
| |
| Reporting size information is *optional* but strongly recommended. |
| Applications can use pressure information to implement size-sensitive drawing |
| and other effects. |
| |
| 8. The values reported by `ABS_DISTANCE` or `ABS_MT_DISTANCE` should approach |
| zero when the tool is touching the device. The distance may remain non-zero |
| even when the tool is in direct contact. The exact values reported depend |
| on the manner in which the hardware measures distance. |
| |
| Reporting distance information is *optional* but recommended for |
| stylus devices. |
| |
| 9. The values reported by `ABS_TILT_X` and `ABS_TILT_Y` should be zero when the |
| tool is perpendicular to the device. A non-zero tilt is taken as an indication |
| that the tool is held at an incline. |
| |
| The tilt angles along the X and Y axes are assumed to be specified in degrees |
| from perpendicular. The center point (perfectly perpendicular) is given |
| by `(max + min) / 2` for each axis. Values smaller than the center point |
| represent a tilt up or to the left, values larger than the center point |
| represent a tilt down or to the right. |
| |
| The `InputReader` converts the X and Y tilt components into a perpendicular |
| tilt angle ranging from 0 to `PI / 2` radians and a planar orientation angle |
| ranging from `-PI` to `PI` radians. This representation results in a |
| description of orientation that is compatible with what is used to describe |
| finger touches. |
| |
| Reporting tilt information is *optional* but recommended for stylus devices. |
| |
| 10. If the tool type is reported by `ABS_MT_TOOL_TYPE`, it will supercede any tool |
| type information reported by `BTN_TOOL_*`. |
| If no tool type information is available at all, the tool type defaults to |
| `MotionEvent.TOOL_TYPE_FINGER`. |
| |
| 11. A tool is determined to be active based on the following conditions: |
| |
| * When using the single-touch protocol, the tool is active if `BTN_TOUCH`, |
| or `BTN_TOOL_*` is 1. |
| |
| This condition implies that the `InputReader` needs to have at least some |
| information about the nature of the tool, either whether it is touching, |
| or at least its tool type. If no information is available, |
| then the tool is assumed to be inactive (out of range). |
| |
| * When using the multi-touch protocol 'A', the tool is active whenever it |
| appears in the most recent sync report. When the tool stops appearing in |
| sync reports, it ceases to exist. |
| |
| * When using the multi-touch protocol 'B', the tool is active as long as |
| it has an active slot. When the slot it cleared, the tool ceases to exist. |
| |
| 12. A tool is determined to be hovering based on the following conditions: |
| |
| * If the tool is `BTN_TOOL_MOUSE` or `BTN_TOOL_LENS`, then the tool |
| is not hovering, even if either of the following conditions are true. |
| |
| * If the tool is active and the driver reports pressure information, |
| and the reported pressure is zero, then the tool is hovering. |
| |
| * If the tool is active and the driver supports the `BTN_TOUCH` key code and |
| `BTN_TOUCH` has a value of zero, then the tool is hovering. |
| |
| 13. The `InputReader` supports both multi-touch protocol 'A' and 'B'. New drivers |
| should use the 'B' protocol but either will work. |
| |
| 14. **As of Android Ice Cream Sandwich 4.0, touch screen drivers may need to be changed |
| to comply with the Linux input protocol specification.** |
| |
| The following changes may be required: |
| |
| * When a tool becomes inactive (finger goes "up"), it should stop appearing |
| in subsequent multi-touch sync reports. When all tools become inactive |
| (all fingers go "up"), the driver should send an empty sync report packet, |
| such as `SYN_MT_REPORT` followed by `SYN_REPORT`. |
| |
| Previous versions of Android expected "up" events to be reported by sending |
| a pressure value of 0. The old behavior was incompatible with the |
| Linux input protocol specification and is no longer supported. |
| |
| * Physical pressure or signal strength information should be reported using |
| `ABS_MT_PRESSURE`. |
| |
| Previous versions of Android retrieved pressure information from |
| `ABS_MT_TOUCH_MAJOR`. The old behavior was incompatible with the |
| Linux input protocol specification and is no longer supported. |
| |
| * Touch size information should be reported using `ABS_MT_TOUCH_MAJOR`. |
| |
| Previous versions of Android retrieved size information from |
| `ABS_MT_TOOL_MAJOR`. The old behavior was incompatible with the |
| Linux input protocol specification and is no longer supported. |
| |
| Touch device drivers no longer need Android-specific customizations. |
| By relying on the standard Linux input protocol, Android can support a |
| wider variety of touch peripherals, such as external HID multi-touch |
| touch screens, using unmodified drivers. |
| |
| ## Touch Device Operation ## |
| |
| The following is a brief summary of the touch device operation on Android. |
| |
| 1. The `EventHub` reads raw events from the `evdev` driver. |
| |
| 2. The `InputReader` consumes the raw events and updates internal state about |
| the position and other characteristics of each tool. It also tracks |
| button states. |
| |
| 3. If the BACK or FORWARD buttons were pressed or released, the `InputReader` |
| notifies the `InputDispatcher` about the key event. |
| |
| 4. The `InputReader` determines whether a virtual key press occurred. If so, |
| it notifies the `InputDispatcher` about the key event. |
| |
| 5. The `InputReader` determines whether the touch was initiated within the |
| bounds of the display. If so, it notifies the `InputDispatcher` about |
| the touch event. |
| |
| 6. If there are no touching tools but there is at least one hovering tool, |
| the `InputReader` notifies the `InputDispatcher` about the hover event. |
| |
| 7. If the touch device type is *pointer*, the `InputReader` performs pointer |
| gesture detection, moves the pointer and spots accordingly and notifies |
| the `InputDispatcher` about the pointer event. |
| |
| 8. The `InputDispatcher` uses the `WindowManagerPolicy` to determine whether |
| the events should be dispatched and whether they should wake the device. |
| Then, the `InputDispatcher` delivers the events to the appropriate applications. |
| |
| ## Touch Device Configuration ## |
| |
| Touch device behavior is determined by the device's axes, buttons, input properties, |
| input device configuration, virtual key map and key layout. |
| |
| Refer to the following sections for more details about the files that |
| participate in keyboard configuration: |
| |
| * [Input Device Configuration Files](/tech/input/input-device-configuration-files.html) |
| * [Virtual Key Map Files](#virtual-key-map-files) |
| |
| ### Properties ### |
| |
| The system relies on many input device configuration properties to configure |
| and calibrate touch device behavior. |
| |
| One reason for this is that the device drivers for touch devices often report |
| the characteristics of touches using device-specific units. |
| |
| For example, many touch devices measure the touch contact area |
| using an internal device-specific scale, such as the total number of |
| sensor nodes that were triggered by the touch. This raw size value would |
| not be meaningful applications because they would need to know about the |
| physical size and other characteristics of the touch device sensor nodes. |
| |
| The system uses calibration parameters encoded in input device configuration |
| files to decode, transform, and normalize the values reported by the touch |
| device into a simpler standard representation that applications can understand. |
| |
| ### Documentation Conventions ### |
| |
| For documentation purposes, we will use the following conventions to describe |
| the values used by the system during the calibration process. |
| |
| #### Raw Axis Values #### |
| |
| The following expressions denote the raw values reported by the touch |
| device driver as `EV_ABS` events. |
| |
| `raw.x` |
| : The value of the `ABS_X` or `ABS_MT_POSITION_X` axis. |
| |
| `raw.y` |
| : The value of the `ABS_Y` or `ABS_MT_POSITION_Y` axis. |
| |
| `raw.pressure` |
| : The value of the `ABS_PRESSURE` or `ABS_MT_PRESSURE` axis, or 0 if not available. |
| |
| `raw.touchMajor` |
| : The value of the `ABS_MT_TOUCH_MAJOR` axis, or 0 if not available. |
| |
| `raw.touchMinor` |
| : The value of the `ABS_MT_TOUCH_MINOR` axis, or `raw.touchMajor` if not available. |
| |
| `raw.toolMajor` |
| : The value of the `ABS_TOOL_WIDTH` or `ABS_MT_WIDTH_MAJOR` axis, or 0 if not available. |
| |
| `raw.toolMinor` |
| : The value of the `ABS_MT_WIDTH_MINOR` axis, or `raw.toolMajor` if not available. |
| |
| `raw.orientation` |
| : The value of the `ABS_MT_ORIENTATION` axis, or 0 if not available. |
| |
| `raw.distance` |
| : The value of the `ABS_DISTANCE` or `ABS_MT_DISTANCE` axis, or 0 if not available. |
| |
| `raw.tiltX` |
| : The value of the `ABS_TILT_X` axis, or 0 if not available. |
| |
| `raw.tiltY` |
| : The value of the `ABS_TILT_Y` axis, or 0 if not available. |
| |
| #### Raw Axis Ranges #### |
| |
| The following expressions denote the bounds of raw values. They are obtained |
| by calling `EVIOCGABS` ioctl for each axis. |
| |
| `raw.*.min` |
| : The inclusive minimum value of the raw axis. |
| |
| `raw.*.max` |
| : The inclusive maximum value of the raw axis. |
| |
| `raw.*.range` |
| : Equivalent to `raw.*.max - raw.*.min`. |
| |
| `raw.*.fuzz` |
| : The accuracy of the raw axis. eg. fuzz = 1 implies values are accurate to +/- 1 unit. |
| |
| `raw.width` |
| : The inclusive width of the touch area, equivalent to `raw.x.range + 1`. |
| |
| `raw.height` |
| : The inclusive height of the touch area, equivalent to `raw.y.range + 1`. |
| |
| #### Output Ranges #### |
| |
| The following expressions denote the characteristics of the output coordinate system. |
| The system uses linear interpolation to translate touch position information from |
| the surface units used by the touch device into the output units that will |
| be reported to applications such as display pixels. |
| |
| `output.width` |
| : The output width. For touch screens (associated with a display), this |
| is the display width in pixels. For touch pads (not associated with a display), |
| the output width equals `raw.width`, indicating that no interpolation will |
| be performed. |
| |
| `output.height` |
| : The output height. For touch screens (associated with a display), this |
| is the display height in pixels. For touch pads (not associated with a display), |
| the output height equals `raw.height`, indicating that no interpolation will |
| be performed. |
| |
| `output.diag` |
| : The diagonal length of the output coordinate system, equivalent to |
| `sqrt(output.width ^2 + output.height ^2)`. |
| |
| ### Basic Configuration ### |
| |
| The touch input mapper uses many configuration properties in the input device |
| configuration file to specify calibration values. The following table describes |
| some general purpose configuration properties. All other properties are described |
| in the following sections along with the fields they are used to calibrate. |
| |
| #### `touch.deviceType` #### |
| |
| *Definition:* `touch.deviceType` = `touchScreen` | `touchPad` | `pointer` | `default` |
| |
| Specifies the touch device type. |
| |
| * If the value is `touchScreen`, the touch device is a touch screen associated |
| with a display. |
| |
| * If the value is `touchPad`, the touch device is a touch pad not associated |
| with a display. |
| |
| * If the value is `pointer`, the touch device is a touch pad not associated |
| with a display, and its motions are used for |
| [indirect multi-touch pointer gestures](#indirect-multi-touch-pointer-gestures). |
| |
| * If the value is `default`, the system automatically detects the device type |
| according to the classification algorithm. |
| |
| Refer to the [Classification](#touch-device-classification) section for more details |
| about how the device type influences the behavior of the touch device. |
| |
| Prior to Honeycomb, all touch devices were assumed to be touch screens. |
| |
| #### `touch.orientationAware` #### |
| |
| *Definition:* `touch.orientationAware` = `0` | `1` |
| |
| Specifies whether the touch device should react to display orientation changes. |
| |
| * If the value is `1`, touch positions reported by the touch device are rotated |
| whenever the display orientation changes. |
| |
| * If the value is `0`, touch positions reported by the touch device are immune |
| to display orientation changes. |
| |
| The default value is `1` if the device is a touch screen, `0` otherwise. |
| |
| The system distinguishes between internal and external touch screens and displays. |
| An orientation aware internal touch screen is rotated based on the orientation |
| of the internal display. An orientation aware external touch screen is rotated |
| based on the orientation of the external display. |
| |
| Orientation awareness is used to support rotation of touch screens on devices |
| like the Nexus One. For example, when the device is rotated clockwise 90 degrees |
| from its natural orientation, the absolute positions of touches are remapped such |
| that a touch in the top-left corner of the touch screen's absolute coordinate system |
| is reported as a touch in the top-left corner of the display's rotated coordinate system. |
| This is done so that touches are reported with the same coordinate system that |
| applications use to draw their visual elements. |
| |
| Prior to Honeycomb, all touch devices were assumed to be orientation aware. |
| |
| #### `touch.gestureMode` #### |
| |
| *Definition:* `touch.gestureMode` = `pointer` | `spots` | `default` |
| |
| Specifies the presentation mode for pointer gestures. This configuration property |
| is only relevant when the touch device is of type *pointer*. |
| |
| * If the value is `pointer`, the touch pad gestures are presented by way of a cursor |
| similar to a mouse pointer. |
| |
| * If the value is `spots`, the touch pad gestures are presented by an anchor |
| that represents the centroid of the gesture and a set of circular spots |
| that represent the position of individual fingers. |
| |
| The default value is `pointer` when the `INPUT_PROP_SEMI_MT` input property |
| is set, or `spots` otherwise. |
| |
| ### `X` and `Y` Fields ### |
| |
| The X and Y fields provide positional information for the center of the contact area. |
| |
| #### Calculation #### |
| |
| The calculation is straightforward: positional information from the touch driver is |
| linearly interpolated to the output coordinate system. |
| |
| 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` Fields ### |
| |
| The `TouchMajor` and `TouchMinor` fields describe the approximate dimensions |
| of the contact area in output units (pixels). |
| |
| The `ToolMajor` and `ToolMinor` fields describe the approximate dimensions |
| of the [tool](#tools-and-tool-types) itself in output units (pixels). |
| |
| The `Size` field describes the normalized size of the touch relative to |
| the largest possible touch that the touch device can sense. The smallest |
| possible normalized size is 0.0 (no contact, or it is unmeasurable), and the largest |
| possible normalized size is 1.0 (sensor area is saturated). |
| |
| When both the approximate length and breadth can be measured, then the `TouchMajor` field |
| specifies the longer dimension and the `TouchMinor` field specifies the shorter dimension |
| of the contact area. When only the approximate diameter of the contact area can be measured, |
| then the `TouchMajor` and `TouchMinor` fields will be equal. |
| |
| Likewise, the `ToolMajor` field specifies the longer dimension and the `ToolMinor` |
| field specifies the shorter dimension of the tool's cross-sectional area. |
| |
| If the touch size is unavailable but the tool size is available, then the tool size |
| will be set equal to the touch size. Conversely, if the tool size is unavailable |
| but the touch size is available, then the touch size will be set equal to the tool size. |
| |
| Touch devices measure or report the touch size and tool size in various ways. |
| The current implementation supports three different kinds of measurements: |
| diameter, area, and geometric bounding box in surface units. |
| |
| #### `touch.size.calibration` #### |
| |
| *Definition:* `touch.size.calibration` = `none` | `geometric` | `diameter` |
| | `area` | `default` |
| |
| Specifies the kind of measurement used by the touch driver to report the |
| touch size and tool size. |
| |
| * If the value is `none`, the size is set to zero. |
| |
| * If the value is `geometric`, the size is assumed to be specified in the same |
| surface units as the position, so it is scaled in the same manner. |
| |
| * If the value is `diameter`, the size is assumed to be proportional to |
| the diameter (width) of the touch or tool. |
| |
| * If the value is `area`, the size is assumed to be proportional to the |
| area of the touch or tool. |
| |
| * If the value is `default`, the system uses the `geometric` calibration if the |
| `raw.touchMajor` or `raw.toolMajor` axis is available, otherwise it uses |
| the `none` calibration. |
| |
| #### `touch.size.scale` #### |
| |
| *Definition:* `touch.size.scale` = <a non-negative floating point number> |
| |
| Specifies a constant scale factor used in the calibration. |
| |
| The default value is `1.0`. |
| |
| #### `touch.size.bias` #### |
| |
| *Definition:* `touch.size.bias` = <a non-negative floating point number> |
| |
| Specifies a constant bias value used in the calibration. |
| |
| The default value is `0.0`. |
| |
| #### `touch.size.isSummed` #### |
| |
| *Definition:* `touch.size.isSummed` = `0` | `1` |
| |
| Specifies whether the size is reported as the sum of the sizes of all |
| active contacts, or is reported individually for each contact. |
| |
| * If the value is `1`, the reported size will be divided by the number |
| of contacts prior to use. |
| |
| * If the value is `0`, the reported size will be used as is. |
| |
| The default value is `0`. |
| |
| Some touch devices, particularly "Semi-MT" devices cannot distinguish the |
| individual dimensions of multiple contacts so they report a size measurement |
| that represents their total area or width. This property should only be set to |
| `1` for such devices. If in doubt, set this value to `0`. |
| |
| #### Calculation #### |
| |
| The calculation of the `TouchMajor`, `TouchMinor`, `ToolMajor`, `ToolMinor` |
| and `Size` fields depends on the specified calibration parameters. |
| |
| 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` Field ### |
| |
| The `Pressure` field describes the approximate physical pressure applied to the |
| touch device as a normalized value between 0.0 (no touch) and 1.0 (full force). |
| |
| A zero pressure indicates that the tool is hovering. |
| |
| #### `touch.pressure.calibration` #### |
| |
| *Definition:* `touch.pressure.calibration` = `none` | `physical` | `amplitude` | `default` |
| |
| Specifies the kind of measurement used by the touch driver to report the pressure. |
| |
| * If the value is `none`, the pressure is unknown so it is set to 1.0 when |
| touching and 0.0 when hovering. |
| |
| * If the value is `physical`, the pressure axis is assumed to measure the actual |
| physical intensity of pressure applied to the touch pad. |
| |
| * If the value is `amplitude`, the pressure axis is assumed to measure the signal |
| amplitude, which is related to the size of the contact and the pressure applied. |
| |
| * If the value is `default`, the system uses the `physical` calibration if the |
| pressure axis available, otherwise uses `none`. |
| |
| #### `touch.pressure.scale` #### |
| |
| *Definition:* `touch.pressure.scale` = <a non-negative floating point number> |
| |
| Specifies a constant scale factor used in the calibration. |
| |
| The default value is `1.0 / raw.pressure.max`. |
| |
| #### Calculation #### |
| |
| The calculation of the `Pressure` field depends on the specified calibration parameters. |
| |
| 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` and `Tilt` Fields ### |
| |
| The `Orientation` field describes the orientation of the touch and tool as an |
| angular measurement. An orientation of `0` indicates that the major axis is |
| oriented vertically, `-PI/2` indicates that the major axis is oriented to the left, |
| `PI/2` indicates that the major axis is oriented to the right. When a stylus |
| tool is present, the orientation range may be described in a full circle range |
| from `-PI` or `PI`. |
| |
| The `Tilt` field describes the inclination of the tool as an angular measurement. |
| A tilt of `0` indicates that the tool is perpendicular to the surface. |
| A tilt of `PI/2` indicates that the tool is flat on the surface. |
| |
| #### `touch.orientation.calibration` #### |
| |
| *Definition:* `touch.orientation.calibration` = `none` | `interpolated` | `vector` | `default` |
| |
| Specifies the kind of measurement used by the touch driver to report the orientation. |
| |
| * If the value is `none`, the orientation is unknown so it is set to 0. |
| |
| * If the value is `interpolated`, the orientation is linearly interpolated such that a |
| raw value of `raw.orientation.min` maps to `-PI/2` and a raw value of |
| `raw.orientation.max` maps to `PI/2`. The center value of |
| `(raw.orientation.min + raw.orientation.max) / 2` maps to `0`. |
| |
| * If the value is `vector`, the orientation is interpreted as a packed vector consisiting |
| of two signed 4-bit fields. This representation is used on Atmel Object Based Protocol |
| parts. When decoded, the vector yields an orientation angle and confidence |
| magnitude. The confidence magnitude is used to scale the size information, |
| unless it is geometric. |
| |
| * If the value is `default`, the system uses the `interpolated` calibration if the |
| orientation axis available, otherwise uses `none`. |
| |
| #### Calculation #### |
| |
| The calculation of the `Orientation` and `Tilt` fields depends on the specified |
| calibration parameters and available input. |
| |
| 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` Field ### |
| |
| The `Distance` field describes the distance between the tool and the touch device |
| surface. A value of 0.0 indicates direct contact and larger values indicate |
| increasing distance from the surface. |
| |
| #### `touch.distance.calibration` #### |
| |
| *Definition:* `touch.distance.calibration` = `none` | `scaled` | `default` |
| |
| Specifies the kind of measurement used by the touch driver to report the distance. |
| |
| * If the value is `none`, the distance is unknown so it is set to 0. |
| |
| * If the value is `scaled`, the reported distance is multiplied by a |
| constant scale factor. |
| |
| * If the value is `default`, the system uses the `scaled` calibration if the |
| distance axis available, otherwise uses `none`. |
| |
| #### `touch.distance.scale` #### |
| |
| *Definition:* `touch.distance.scale` = <a non-negative floating point number> |
| |
| Specifies a constant scale factor used in the calibration. |
| |
| The default value is `1.0`. |
| |
| #### Calculation #### |
| |
| The calculation of the `Distance` field depends on the specified calibration parameters. |
| |
| If touch.distance.calibration == "scaled": |
| output.distance = raw.distance * touch.distance.scale |
| Else |
| output.distance = 0 |
| End If |
| |
| ### Example ### |
| |
| # 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 |
| |
| ### Compatibility Notes ### |
| |
| The configuration properties for touch devices changed significantly in |
| Android Ice Cream Sandwich 4.0. **All input device configuration files for touch |
| devices must be updated to use the new configuration properties.** |
| |
| Older touch device [drivers](#touch-device-driver-requirements) may also need to be |
| updated. |
| |
| ## Virtual Key Map Files ## |
| |
| Touch devices are often used to implement virtual keys. |
| |
| There are several ways of doing this, depending on the capabilities of the |
| touch controller. Some touch controllers can be directly configured to implement |
| soft keys by setting firmware registers. Other times it is desirable to perform |
| the mapping from touch coordinates to key codes in software. |
| |
| When virtual keys are implemented in software, the kernel must export a virtual key map |
| file called `virtualkeys.<devicename>` as a board property. For example, |
| if the touch screen device drivers reports its name as "touchyfeely" then |
| the virtual key map file must have the path `/sys/board_properties/virtualkeys.touchyfeely`. |
| |
| A virtual key map file describes the coordinates and Linux key codes of virtual keys |
| on the touch screen. |
| |
| In addition to the virtual key map file, there must be a corresponding key layout |
| file and key character map file to map the Linux key codes to Android key codes and |
| to specify the type of the keyboard device (usually `SPECIAL_FUNCTION`). |
| |
| ### Syntax ### |
| |
| A virtual key map file is a plain text file consisting of a sequence of virtual key |
| layout descriptions either separated by newlines or by colons. |
| |
| Comment lines begin with '#' and continue to the end of the line. |
| |
| Each virtual key is described by 6 colon-delimited components: |
| |
| * `0x01`: A version code. Must always be `0x01`. |
| * <Linux key code>: The Linux key code of the virtual key. |
| * <centerX>: The X pixel coordinate of the center of the virtual key. |
| * <centerY>: The Y pixel coordinate of the center of the virtual key. |
| * <width>: The width of the virtual key in pixels. |
| * <height>: The height of the virtual key in pixels. |
| |
| All coordinates and sizes are specified in terms of the display coordinate system. |
| |
| Here is a virtual key map file all written on one line. |
| |
| # 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 |
| |
| The same virtual key map file can also be written on multiple lines. |
| |
| # 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 |
| |
| In the above example, the touch screen has a resolution of 480x800. Accordingly, all of |
| the virtual keys have a <centerY> coordinate of 835, which is a little bit below |
| the visible area of the touch screen. |
| |
| The first key has a Linux scan code of `158` (`KEY_BACK`), centerX of `55`, |
| centerY of `835`, width of `90` and height of `55`. |
| |
| ### Example ### |
| |
| Virtual key map file: `/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 |
| |
| Key layout file: `/system/usr/keylayout/touchyfeely.kl`. |
| |
| key 158 BACK |
| key 139 MENU |
| key 102 HOME |
| key 217 SEARCH |
| |
| Key character map file: `/system/usr/keychars/touchyfeely.kcm`. |
| |
| type SPECIAL_FUNCTION |
| |
| ## Indirect Multi-touch Pointer Gestures ## |
| |
| In pointer mode, the system interprets the following gestures: |
| |
| 1. Single finger tap: click. |
| |
| 2. Single finger motion: move the pointer. |
| |
| 3. Single finger motion plus button presses: drag the pointer. |
| |
| 4. Two finger motion both fingers moving in the same direction: drag the area under the pointer |
| in that direction. The pointer itself does not move. |
| |
| 5. Two finger motion both fingers moving towards each other or apart in |
| different directions: pan/scale/rotate the area surrounding the pointer. |
| The pointer itself does not move. |
| |
| 6. Multiple finger motion: freeform gesture. |
| |
| ## Further Reading ## |
| |
| 1. [Linux multi-touch protocol](http://www.kernel.org/doc/Documentation/input/multi-touch-protocol.txt) |
| 2. [ENAC list of available multitouch devices on Linux](http://lii-enac.fr/en/architecture/linux-input/multitouch-devices.html) |