This document aims to illustrate why we need to take care when converting between the discrete and continuous coordinate spaces, especially when performing rotations.
The Linux evdev protocol works over discrete integral values. The same is true for displays, which output discrete pixels. WindowManager also tracks window bounds in pixels in the rotated logical display.
However, our MotionEvent
APIs report floating point axis values in a continuous space. This disparity is important to note when working in InputFlinger, which has to make sure the discrete raw coordinates are converted to the continuous space correctly in all scenarios.
Let's consider an example of device that has a 3 x 4 screen.
If the user interacts with the highlighted pixel, the touchscreen would report the discreet coordinates (0, 2).
┌─────┬─────┬─────┐ │ 0,0 │ 1,0 │ 2,0 │ ├─────┼─────┼─────┤ │ 0,1 │ 1,1 │ 2,1 │ ├─────┼─────┼─────┤ │█0,2█│ 1,2 │ 2,2 │ ├─────┼─────┼─────┤ │ 0,3 │ 1,3 │ 2,3 │ └─────┴─────┴─────┘
When converted to the continuous space, the point (0, 2) corresponds to the location shown below.
0 1 2 3 0 ┌─────┬─────┬─────┐ │ │ │ │ 1 ├─────┼─────┼─────┤ │ │ │ │ 2 █─────┼─────┼─────┤ │ │ │ │ 3 ├─────┼─────┼─────┤ │ │ │ │ 4 └─────┴─────┴─────┘
When the device is rotated and the same place on the touchscreen is touched, the input device will still report the same coordinates of (0, 2).
In the rotated display, that now corresponds to the pixel (2, 2).
┌─────┬─────┬─────┬─────┐ │ 0,0 │ 1,0 │ 2,0 │ 3,0 │ ├─────┼─────┼─────┼─────┤ │ 0,1 │ 1,1 │ 2,1 │ 3,1 │ ├─────┼─────┼─────┼─────┤ │ 0,2 │ 1,2 │█2,2█│ 3,2 │ └─────┴─────┴─────┴─────┘
It is important to note that rotating the device 90 degrees is NOT equivalent to rotating the continuous coordinate space by 90 degrees.
The point (2, 2) now corresponds to a different location in the continuous space than before, even though the user was interacting at the same place on the touchscreen.
0 1 2 3 4 0 ┌─────┬─────┬─────┬─────┐ │ │ │ │ │ 1 ├─────┼─────┼─────┼─────┤ │ │ │ │ │ 2 ├─────┼─────█─────┼─────┤ │ │ │ │ │ 3 └─────┴─────┴─────┴─────┘
If we were to simply (incorrectly) rotate the continuous space from before by 90 degrees, the touched point would correspond to the location (2, 3), shown below. This new point is outside the bounds of the display, since it does not correspond to any pixel at that location.
It should be impossible for a touchscreen to generate points outside the bounds of the display, because we assume that the area of the touchscreen maps directly to the area of the display. Therefore, that point is an invalid coordinate that cannot be generated by an input device.
0 1 2 3 4 0 ┌─────┬─────┬─────┬─────┐ │ │ │ │ ╏ 1 ├─────┼─────┼─────┼─────┤ │ │ │ │ ╏ 2 ├─────┼─────┼─────┼─────┤ │ │ │ │ ╏ 3 └-----┴-----█-----┴-----┘
The same logic applies to windows as well. When performing hit tests to determine if a point in the continuous space falls inside a window's bounds, hit test must be performed in the correct orientation, since points on the right and bottom edges of the window do not fall within the window bounds.