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

Commit 9afe784f authored by Prabir Pradhan's avatar Prabir Pradhan
Browse files

Undo rotation by physical orientation in WindowInfo transforms

Some devices have a their display panels installed in a different
orientation than the expected default orientation. This can be
configured through the build prop
ro.surface_flinger.primary_display_orientation, or through other means.

Input, framework, and other services are not concerned with the display
panel orientation. In this CL, we rotate the transforms sent in
WindowInfo by the inverse of the physical orientation, making the window
transforms relative to WM's ROTATION_0 instead of the display panel
orientation.

Bug: 179274888
Bug: 195617582
Bug: 195586068
Test: manual with device that has a non-standard display panel
installation
Test: atest com.android.launcher3.ui.TaplTestsLauncher3

Merged-In: I727b22c004014355f337da2b753b61c5946667d0
Change-Id: I727b22c004014355f337da2b753b61c5946667d0
parent 214040a7
Loading
Loading
Loading
Loading
+34 −20
Original line number Original line Diff line number Diff line
@@ -2164,7 +2164,7 @@ Rect Layer::getInputBounds() const {
    return getCroppedBufferSize(getDrawingState());
    return getCroppedBufferSize(getDrawingState());
}
}


void Layer::fillInputFrameInfo(WindowInfo& info, const ui::Transform& toPhysicalDisplay) {
void Layer::fillInputFrameInfo(WindowInfo& info, const ui::Transform& toNonRotatedDisplay) {
    // Transform layer size to screen space and inset it by surface insets.
    // Transform layer size to screen space and inset it by surface insets.
    // If this is a portal window, set the touchableRegion to the layerBounds.
    // If this is a portal window, set the touchableRegion to the layerBounds.
    Rect layerBounds = info.portalToDisplayId == ADISPLAY_ID_NONE
    Rect layerBounds = info.portalToDisplayId == ADISPLAY_ID_NONE
@@ -2185,12 +2185,12 @@ void Layer::fillInputFrameInfo(WindowInfo& info, const ui::Transform& toPhysical
    }
    }


    ui::Transform layerToDisplay = getInputTransform();
    ui::Transform layerToDisplay = getInputTransform();
    // Transform that takes window coordinates to unrotated display coordinates
    // Transform that takes window coordinates to non-rotated display coordinates
    ui::Transform t = toPhysicalDisplay * layerToDisplay;
    ui::Transform t = toNonRotatedDisplay * layerToDisplay;
    int32_t xSurfaceInset = info.surfaceInset;
    int32_t xSurfaceInset = info.surfaceInset;
    int32_t ySurfaceInset = info.surfaceInset;
    int32_t ySurfaceInset = info.surfaceInset;
    // Bring screenBounds into unrotated space
    // Bring screenBounds into non-rotated space
    Rect screenBounds = toPhysicalDisplay.transform(Rect{mScreenBounds});
    Rect screenBounds = toNonRotatedDisplay.transform(Rect{mScreenBounds});


    const float xScale = t.getScaleX();
    const float xScale = t.getScaleX();
    const float yScale = t.getScaleY();
    const float yScale = t.getScaleY();
@@ -2283,19 +2283,33 @@ WindowInfo Layer::fillInputInfo(const sp<DisplayDevice>& display) {
    info.id = sequence;
    info.id = sequence;
    info.displayId = getLayerStack();
    info.displayId = getLayerStack();


    // Transform that goes from "logical(rotated)" display to physical/unrotated display.
    // Transform that goes from "logical(rotated)" display to the non-rotated display.
    // This is for when inputflinger operates in physical display-space.
    ui::Transform toNonRotatedDisplay;
    ui::Transform toPhysicalDisplay;
    if (display) {
    if (display) {
        toPhysicalDisplay = display->getTransform();
        // The physical orientation is set when the orientation of the display panel is different
        // getOrientation() without masking can contain more-significant bits (eg. ROT_INVALID).
        // than the default orientation of the device. We do not need to expose the physical
        static constexpr uint32_t ALL_ROTATIONS_MASK =
        // orientation of the panel outside of SurfaceFlinger.
                ui::Transform::ROT_90 | ui::Transform::ROT_180 | ui::Transform::ROT_270;
        const ui::Rotation inversePhysicalOrientation =
        info.displayOrientation = toPhysicalDisplay.getOrientation() & ALL_ROTATIONS_MASK;
                ui::ROTATION_0 - display->getPhysicalOrientation();
        info.displayWidth = display->getWidth();
        auto width = display->getWidth();
        info.displayHeight = display->getHeight();
        auto height = display->getHeight();
    }
        if (inversePhysicalOrientation == ui::ROTATION_90 ||
    fillInputFrameInfo(info, toPhysicalDisplay);
            inversePhysicalOrientation == ui::ROTATION_270) {
            std::swap(width, height);
        }
        const auto rotationFlags = ui::Transform::toRotationFlags(inversePhysicalOrientation);
        const ui::Transform undoPhysicalOrientation(rotationFlags, width, height);
        toNonRotatedDisplay = undoPhysicalOrientation * display->getTransform();

        // Send the inverse of the display orientation so that input can transform points back to
        // the rotated display space.
        const ui::Rotation inverseOrientation = ui::ROTATION_0 - display->getOrientation();
        info.displayOrientation = ui::Transform::toRotationFlags(inverseOrientation);

        info.displayWidth = width;
        info.displayHeight = height;
    }
    fillInputFrameInfo(info, toNonRotatedDisplay);


    // For compatibility reasons we let layers which can receive input
    // For compatibility reasons we let layers which can receive input
    // receive input before they have actually submitted a buffer. Because
    // receive input before they have actually submitted a buffer. Because
@@ -2312,14 +2326,14 @@ WindowInfo Layer::fillInputInfo(const sp<DisplayDevice>& display) {
    auto cropLayer = mDrawingState.touchableRegionCrop.promote();
    auto cropLayer = mDrawingState.touchableRegionCrop.promote();
    if (info.replaceTouchableRegionWithCrop) {
    if (info.replaceTouchableRegionWithCrop) {
        if (cropLayer == nullptr) {
        if (cropLayer == nullptr) {
            info.touchableRegion = Region(toPhysicalDisplay.transform(Rect{mScreenBounds}));
            info.touchableRegion = Region(toNonRotatedDisplay.transform(Rect{mScreenBounds}));
        } else {
        } else {
            info.touchableRegion =
            info.touchableRegion =
                    Region(toPhysicalDisplay.transform(Rect{cropLayer->mScreenBounds}));
                    Region(toNonRotatedDisplay.transform(Rect{cropLayer->mScreenBounds}));
        }
        }
    } else if (cropLayer != nullptr) {
    } else if (cropLayer != nullptr) {
        info.touchableRegion = info.touchableRegion.intersect(
        info.touchableRegion = info.touchableRegion.intersect(
                toPhysicalDisplay.transform(Rect{cropLayer->mScreenBounds}));
                toNonRotatedDisplay.transform(Rect{cropLayer->mScreenBounds}));
    }
    }


    // Inherit the trusted state from the parent hierarchy, but don't clobber the trusted state
    // Inherit the trusted state from the parent hierarchy, but don't clobber the trusted state
@@ -2332,7 +2346,7 @@ WindowInfo Layer::fillInputInfo(const sp<DisplayDevice>& display) {
    if (isClone()) {
    if (isClone()) {
        sp<Layer> clonedRoot = getClonedRoot();
        sp<Layer> clonedRoot = getClonedRoot();
        if (clonedRoot != nullptr) {
        if (clonedRoot != nullptr) {
            Rect rect = toPhysicalDisplay.transform(Rect{clonedRoot->mScreenBounds});
            Rect rect = toNonRotatedDisplay.transform(Rect{clonedRoot->mScreenBounds});
            info.touchableRegion = info.touchableRegion.intersect(rect);
            info.touchableRegion = info.touchableRegion.intersect(rect);
        }
        }
    }
    }
+1 −1
Original line number Original line Diff line number Diff line
@@ -1073,7 +1073,7 @@ private:
    void fillTouchOcclusionMode(gui::WindowInfo& info);
    void fillTouchOcclusionMode(gui::WindowInfo& info);


    // Fills in the frame and transform info for the gui::WindowInfo
    // Fills in the frame and transform info for the gui::WindowInfo
    void fillInputFrameInfo(gui::WindowInfo& info, const ui::Transform& toPhysicalDisplay);
    void fillInputFrameInfo(gui::WindowInfo& info, const ui::Transform& toNonRotatedDisplay);


    // Cached properties computed from drawing state
    // Cached properties computed from drawing state
    // Effective transform taking into account parent transforms and any parent scaling, which is
    // Effective transform taking into account parent transforms and any parent scaling, which is