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

Commit 05de577c authored by Arthur Hung's avatar Arthur Hung
Browse files

Fix foldable emulator touch does not work

When foldable emulator change to minimized state and rotate screen,
the physical display would align to right-top (rotate to 90) or
left-bottom (rotate to 270), but the touch axes range still keep
the initialed values, so when cookPointerData, it would also align to
right-top or left-bottom when display rotated.

- Fix the surface range when display had offset and rotated.
- Fix the surface range checker function.

Bug: 138708005
Test: atest inputflinger_tests
Test: open foldable emulator, change to minimized state and rotate device,
      test if touch can work fine.
Change-Id: Idc97107512dd1c11e3783eb3276635f69d3b047b
parent 264a16a5
Loading
Loading
Loading
Loading
+36 −14
Original line number Diff line number Diff line
@@ -668,7 +668,7 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) {
                    naturalLogicalHeight = mViewport.logicalRight - mViewport.logicalLeft;
                    naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop;
                    naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft;
                    naturalPhysicalLeft = mViewport.deviceHeight - mViewport.physicalBottom;
                    naturalPhysicalLeft = mViewport.deviceHeight - naturalPhysicalWidth;
                    naturalPhysicalTop = mViewport.physicalLeft;
                    naturalDeviceWidth = mViewport.deviceHeight;
                    naturalDeviceHeight = mViewport.deviceWidth;
@@ -689,7 +689,7 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) {
                    naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop;
                    naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft;
                    naturalPhysicalLeft = mViewport.physicalTop;
                    naturalPhysicalTop = mViewport.deviceWidth - mViewport.physicalRight;
                    naturalPhysicalTop = mViewport.deviceWidth - naturalPhysicalHeight;
                    naturalDeviceWidth = mViewport.deviceHeight;
                    naturalDeviceHeight = mViewport.deviceWidth;
                    break;
@@ -2173,6 +2173,7 @@ void TouchInputMapper::cookPointerData() {
        // TODO: Adjust coverage coords?
        float xTransformed = in.x, yTransformed = in.y;
        mAffineTransform.applyTo(xTransformed, yTransformed);
        rotateAndScale(xTransformed, yTransformed);

        // Adjust X, Y, and coverage coords for surface orientation.
        float x, y;
@@ -2180,8 +2181,8 @@ void TouchInputMapper::cookPointerData() {

        switch (mSurfaceOrientation) {
            case DISPLAY_ORIENTATION_90:
                x = float(yTransformed - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
                y = float(mRawPointerAxes.x.maxValue - xTransformed) * mXScale + mXTranslate;
                x = yTransformed + mYTranslate;
                y = xTransformed + mXTranslate;
                left = float(rawTop - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
                right = float(rawBottom - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
                bottom = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate;
@@ -2194,8 +2195,8 @@ void TouchInputMapper::cookPointerData() {
                }
                break;
            case DISPLAY_ORIENTATION_180:
                x = float(mRawPointerAxes.x.maxValue - xTransformed) * mXScale;
                y = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale + mYTranslate;
                x = xTransformed + mXTranslate;
                y = yTransformed + mYTranslate;
                left = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale;
                right = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale;
                bottom = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate;
@@ -2208,8 +2209,8 @@ void TouchInputMapper::cookPointerData() {
                }
                break;
            case DISPLAY_ORIENTATION_270:
                x = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale;
                y = float(xTransformed - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
                x = yTransformed + mYTranslate;
                y = xTransformed + mXTranslate;
                left = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale;
                right = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale;
                bottom = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
@@ -2222,8 +2223,8 @@ void TouchInputMapper::cookPointerData() {
                }
                break;
            default:
                x = float(xTransformed - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
                y = float(yTransformed - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
                x = xTransformed + mXTranslate;
                y = yTransformed + mYTranslate;
                left = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
                right = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
                bottom = float(rawBottom - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
@@ -3617,13 +3618,34 @@ void TouchInputMapper::cancelTouch(nsecs_t when) {
    abortTouches(when, 0 /* policyFlags*/);
}

void TouchInputMapper::rotateAndScale(float& x, float& y) {
    switch (mSurfaceOrientation) {
        case DISPLAY_ORIENTATION_90:
            x = float(mRawPointerAxes.x.maxValue - x) * mXScale;
            y = float(y - mRawPointerAxes.y.minValue) * mYScale;
            break;
        case DISPLAY_ORIENTATION_180:
            x = float(mRawPointerAxes.x.maxValue - x) * mXScale;
            y = float(mRawPointerAxes.y.maxValue - y) * mYScale;
            break;
        case DISPLAY_ORIENTATION_270:
            x = float(x - mRawPointerAxes.x.minValue) * mXScale;
            y = float(mRawPointerAxes.y.maxValue - y) * mYScale;
            break;
        default:
            x = float(x - mRawPointerAxes.x.minValue) * mXScale;
            y = float(y - mRawPointerAxes.y.minValue) * mYScale;
            break;
    }
}

bool TouchInputMapper::isPointInsideSurface(int32_t x, int32_t y) {
    const float scaledX = x * mXScale;
    const float scaledY = y * mYScale;
    float xTransformed = x, yTransformed = y;
    rotateAndScale(xTransformed, yTransformed);
    return x >= mRawPointerAxes.x.minValue && x <= mRawPointerAxes.x.maxValue &&
            scaledX >= mSurfaceLeft && scaledX <= mSurfaceLeft + mSurfaceWidth &&
            xTransformed >= mSurfaceLeft && xTransformed <= mSurfaceLeft + mSurfaceWidth &&
            y >= mRawPointerAxes.y.minValue && y <= mRawPointerAxes.y.maxValue &&
            scaledY >= mSurfaceTop && scaledY <= mSurfaceTop + mSurfaceHeight;
            yTransformed >= mSurfaceTop && yTransformed <= mSurfaceTop + mSurfaceHeight;
}

const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHit(int32_t x, int32_t y) {
+1 −0
Original line number Diff line number Diff line
@@ -758,6 +758,7 @@ private:
    static void assignPointerIds(const RawState* last, RawState* current);

    const char* modeToString(DeviceMode deviceMode);
    void rotateAndScale(float& x, float& y);
};

} // namespace android
+31 −10
Original line number Diff line number Diff line
@@ -6614,20 +6614,41 @@ TEST_F(MultiTouchInputMapperTest, Viewports_SurfaceRange) {
    MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
    addConfigurationProperty("touch.deviceType", "touchScreen");
    prepareDisplay(DISPLAY_ORIENTATION_0);
    // Let surface be different from physical display.
    prepareAxes(POSITION);
    addMapperAndConfigure(mapper);

    // Touch on left-top area should work.
    int32_t rawX = DISPLAY_WIDTH / 2 - 1;
    int32_t rawY = DISPLAY_HEIGHT / 2 - 1;
    processPosition(mapper, rawX, rawY);
    processSync(mapper);

    NotifyMotionArgs args;
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));

    // Reset.
    mapper->reset(ARBITRARY_TIME);

    // Let logical display be different to physical display and rotate 90-degrees.
    std::optional<DisplayViewport> internalViewport =
            mFakePolicy->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
    internalViewport->logicalLeft = internalViewport->physicalTop + 20;
    internalViewport->logicalTop = internalViewport->physicalRight + 20;
    internalViewport->logicalRight = internalViewport->physicalRight - 20;
    internalViewport->logicalBottom = internalViewport->physicalBottom - 20;
    internalViewport->orientation = DISPLAY_ORIENTATION_90;
    internalViewport->logicalLeft = 0;
    internalViewport->logicalTop = 0;
    internalViewport->logicalRight = DISPLAY_HEIGHT;
    internalViewport->logicalBottom = DISPLAY_WIDTH / 2;

    internalViewport->physicalLeft = DISPLAY_HEIGHT;
    internalViewport->physicalTop = DISPLAY_WIDTH / 2;
    internalViewport->physicalRight = DISPLAY_HEIGHT;
    internalViewport->physicalBottom = DISPLAY_WIDTH;

    internalViewport->deviceWidth = DISPLAY_HEIGHT;
    internalViewport->deviceHeight = DISPLAY_WIDTH;
    mFakePolicy->updateViewport(internalViewport.value());
    configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);

    prepareAxes(POSITION);
    addMapperAndConfigure(mapper);

    int32_t rawX = 10;
    int32_t rawY = 10;
    // Display align to right-top after rotate 90-degrees, touch on left-top area should not work.
    processPosition(mapper, rawX, rawY);
    processSync(mapper);
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());