Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 46211fbf authored by Prabir Pradhan's avatar Prabir Pradhan
Browse files

TouchInputMapper: Use ui::Transform to calulate MotionRanges

The MotionRange API can be queried by apps from the InputDevice class.
The API is unaware of the window context from which the app is calling
it, which means we cannot return values in the window's coordinate
space. Therefore we use the rotated display space (a.k.a. logical
display space) for the MotionRange API.

After this CL, the MotionRanges are now in the same coordinate space as
MotionEvent#getRawX and MotionEvent#getRawY, which should make them more
useful to apps. Previously, they were always in the display space,
which meant they were not updated when the display rotated.

In this CL, the x and y axis range is calcualted from the input device's
raw range. This means the range is finally accurate to what the device
can actually produce, rather than the range being completly determined
from the display size.

Bug: 257118693
Test: atest inputflinger_tests
Change-Id: Ib336707c6401a366c759548ed7784fc430176c6a
parent 33e3baa3
Loading
Loading
Loading
Loading
+33 −34
Original line number Diff line number Diff line
@@ -805,40 +805,39 @@ void TouchInputMapper::initializeOrientedRanges() {
        };
    }

    // Compute oriented precision, scales and ranges.
    // Note that the maximum value reported is an inclusive maximum value so it is one
    // unit less than the total width or height of the display.
    // TODO(b/20508709): Calculate the oriented ranges using the input device's raw frame.
    switch (mInputDeviceOrientation) {
        case ui::ROTATION_90:
        case ui::ROTATION_270:
            mOrientedRanges.x.min = 0;
            mOrientedRanges.x.max = mDisplayBounds.height - 1;
            mOrientedRanges.x.flat = 0;
            mOrientedRanges.x.fuzz = 0;
            mOrientedRanges.x.resolution = mRawPointerAxes.y.resolution * mRawToDisplay.getScaleY();

            mOrientedRanges.y.min = 0;
            mOrientedRanges.y.max = mDisplayBounds.width - 1;
            mOrientedRanges.y.flat = 0;
            mOrientedRanges.y.fuzz = 0;
            mOrientedRanges.y.resolution = mRawPointerAxes.x.resolution * mRawToDisplay.getScaleX();
            break;

        default:
            mOrientedRanges.x.min = 0;
            mOrientedRanges.x.max = mDisplayBounds.width - 1;
            mOrientedRanges.x.flat = 0;
            mOrientedRanges.x.fuzz = 0;
            mOrientedRanges.x.resolution = mRawPointerAxes.x.resolution * mRawToDisplay.getScaleX();

            mOrientedRanges.y.min = 0;
            mOrientedRanges.y.max = mDisplayBounds.height - 1;
            mOrientedRanges.y.flat = 0;
            mOrientedRanges.y.fuzz = 0;
            mOrientedRanges.y.resolution = mRawPointerAxes.y.resolution * mRawToDisplay.getScaleY();
            break;
    }
    // Oriented X/Y range (in the rotated display's orientation)
    const FloatRect rawFrame = Rect{mRawPointerAxes.x.minValue, mRawPointerAxes.y.minValue,
                                    mRawPointerAxes.x.maxValue, mRawPointerAxes.y.maxValue}
                                       .toFloatRect();
    const auto orientedRangeRect = mRawToRotatedDisplay.transform(rawFrame);
    mOrientedRanges.x.min = orientedRangeRect.left;
    mOrientedRanges.y.min = orientedRangeRect.top;
    mOrientedRanges.x.max = orientedRangeRect.right;
    mOrientedRanges.y.max = orientedRangeRect.bottom;

    // Oriented flat (in the rotated display's orientation)
    const auto orientedFlat =
            transformWithoutTranslation(mRawToRotatedDisplay,
                                        {static_cast<float>(mRawPointerAxes.x.flat),
                                         static_cast<float>(mRawPointerAxes.y.flat)});
    mOrientedRanges.x.flat = std::abs(orientedFlat.x);
    mOrientedRanges.y.flat = std::abs(orientedFlat.y);

    // Oriented fuzz (in the rotated display's orientation)
    const auto orientedFuzz =
            transformWithoutTranslation(mRawToRotatedDisplay,
                                        {static_cast<float>(mRawPointerAxes.x.fuzz),
                                         static_cast<float>(mRawPointerAxes.y.fuzz)});
    mOrientedRanges.x.fuzz = std::abs(orientedFuzz.x);
    mOrientedRanges.y.fuzz = std::abs(orientedFuzz.y);

    // Oriented resolution (in the rotated display's orientation)
    const auto orientedRes =
            transformWithoutTranslation(mRawToRotatedDisplay,
                                        {static_cast<float>(mRawPointerAxes.x.resolution),
                                         static_cast<float>(mRawPointerAxes.y.resolution)});
    mOrientedRanges.x.resolution = std::abs(orientedRes.x);
    mOrientedRanges.y.resolution = std::abs(orientedRes.y);
}

void TouchInputMapper::computeInputTransforms() {
+48 −2
Original line number Diff line number Diff line
@@ -6927,9 +6927,11 @@ public:
        // four times the resolution of the display in the Y axis.
        prepareButtons();
        mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_X, PRECISION_RAW_X_MIN, PRECISION_RAW_X_MAX,
                                       0, 0);
                                       PRECISION_RAW_X_FLAT, PRECISION_RAW_X_FUZZ,
                                       PRECISION_RAW_X_RES);
        mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Y, PRECISION_RAW_Y_MIN, PRECISION_RAW_Y_MAX,
                                       0, 0);
                                       PRECISION_RAW_Y_FLAT, PRECISION_RAW_Y_FUZZ,
                                       PRECISION_RAW_Y_RES);
    }
    static const int32_t PRECISION_RAW_X_MIN = TouchInputMapperTest::RAW_X_MIN;
@@ -6937,6 +6939,15 @@ public:
    static const int32_t PRECISION_RAW_Y_MIN = TouchInputMapperTest::RAW_Y_MIN;
    static const int32_t PRECISION_RAW_Y_MAX = PRECISION_RAW_Y_MIN + DISPLAY_HEIGHT * 4 - 1;
    static const int32_t PRECISION_RAW_X_RES = 50;  // units per millimeter
    static const int32_t PRECISION_RAW_Y_RES = 100; // units per millimeter
    static const int32_t PRECISION_RAW_X_FLAT = 16;
    static const int32_t PRECISION_RAW_Y_FLAT = 32;
    static const int32_t PRECISION_RAW_X_FUZZ = 4;
    static const int32_t PRECISION_RAW_Y_FUZZ = 8;
    static const std::array<Point, 4> kRawCorners;
};
@@ -7094,6 +7105,41 @@ TEST_P(TouchscreenPrecisionTestsFixture, RotationPrecisionOrientationAwareInOri2
    }
}
TEST_P(TouchscreenPrecisionTestsFixture, MotionRangesAreOrientedInRotatedDisplay) {
    const ui::Rotation displayRotation = GetParam();
    addConfigurationProperty("touch.deviceType", "touchScreen");
    prepareDisplay(displayRotation);
    __attribute__((unused)) SingleTouchInputMapper& mapper =
            addMapperAndConfigure<SingleTouchInputMapper>();
    const InputDeviceInfo deviceInfo = mDevice->getDeviceInfo();
    // MotionRanges use display pixels as their units
    const auto* xRange = deviceInfo.getMotionRange(AMOTION_EVENT_AXIS_X, AINPUT_SOURCE_TOUCHSCREEN);
    const auto* yRange = deviceInfo.getMotionRange(AMOTION_EVENT_AXIS_Y, AINPUT_SOURCE_TOUCHSCREEN);
    // The MotionRanges should be oriented in the rotated display's coordinate space
    const bool displayRotated =
            displayRotation == ui::ROTATION_90 || displayRotation == ui::ROTATION_270;
    constexpr float MAX_X = 479.5;
    constexpr float MAX_Y = 799.75;
    EXPECT_EQ(xRange->min, 0.f);
    EXPECT_EQ(yRange->min, 0.f);
    EXPECT_EQ(xRange->max, displayRotated ? MAX_Y : MAX_X);
    EXPECT_EQ(yRange->max, displayRotated ? MAX_X : MAX_Y);
    EXPECT_EQ(xRange->flat, 8.f);
    EXPECT_EQ(yRange->flat, 8.f);
    EXPECT_EQ(xRange->fuzz, 2.f);
    EXPECT_EQ(yRange->fuzz, 2.f);
    EXPECT_EQ(xRange->resolution, 25.f); // pixels per millimeter
    EXPECT_EQ(yRange->resolution, 25.f); // pixels per millimeter
}
// Run the precision tests for all rotations.
INSTANTIATE_TEST_SUITE_P(TouchscreenPrecisionTests, TouchscreenPrecisionTestsFixture,
                         ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,