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

Commit 2b9fc253 authored by [1;3C's avatar [1;3C Committed by Evan Rosky
Browse files

Unrotate inputwindows into rotation display grew-up in

This way inputflinger internally works within one coordinate
space at all times and only transforms coordinates for dispatch
to targets

This is behind a flag:
   adb shell setprop persist.debug.per_window_input_rotation 1

Bug: 179274888
Test: phone should work as before
Change-Id: I503f9beea9863193801aa6422a416382374e48c8
parent 021885b0
Loading
Loading
Loading
Loading
+22 −10
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@

#include "Layer.h"

#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android/native_window.h>
#include <binder/IPCThreadState.h>
@@ -2480,7 +2481,7 @@ void Layer::writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet
    if (traceFlags & SurfaceTracing::TRACE_INPUT) {
        InputWindowInfo info;
        if (useDrawing) {
            info = fillInputInfo();
            info = fillInputInfo({nullptr});
        } else {
            info = state.inputInfo;
        }
@@ -2501,7 +2502,7 @@ bool Layer::isRemovedFromCurrentState() const {
    return mRemovedFromCurrentState;
}

void Layer::fillInputFrameInfo(InputWindowInfo& info) {
void Layer::fillInputFrameInfo(InputWindowInfo& info, const ui::Transform& toPhysicalDisplay) {
    // Transform layer size to screen space and inset it by surface insets.
    // If this is a portal window, set the touchableRegion to the layerBounds.
    Rect layerBounds = info.portalToDisplayId == ADISPLAY_ID_NONE
@@ -2521,9 +2522,13 @@ void Layer::fillInputFrameInfo(InputWindowInfo& info) {
        return;
    }

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

    const float xScale = t.getScaleX();
    const float yScale = t.getScaleY();
@@ -2581,7 +2586,6 @@ void Layer::fillInputFrameInfo(InputWindowInfo& info) {
    // We need to send the layer bounds cropped to the screenbounds since the layer can be cropped.
    // The frame should be the area the user sees on screen since it's used for occlusion
    // detection.
    Rect screenBounds = Rect{mScreenBounds};
    transformedLayerBounds.intersect(screenBounds, &transformedLayerBounds);
    info.frameLeft = transformedLayerBounds.left;
    info.frameTop = transformedLayerBounds.top;
@@ -2593,7 +2597,7 @@ void Layer::fillInputFrameInfo(InputWindowInfo& info) {
    info.touchableRegion = inputTransform.transform(info.touchableRegion);
}

InputWindowInfo Layer::fillInputInfo() {
InputWindowInfo Layer::fillInputInfo(const sp<DisplayDevice>& display) {
    if (!hasInputInfo()) {
        mDrawingState.inputInfo.name = getName();
        mDrawingState.inputInfo.ownerUid = mOwnerUid;
@@ -2610,7 +2614,13 @@ InputWindowInfo Layer::fillInputInfo() {
        info.displayId = getLayerStack();
    }

    fillInputFrameInfo(info);
    // Transform that goes from "logical(rotated)" display to physical/unrotated display.
    // This is for when inputflinger operates in physical display-space.
    ui::Transform toPhysicalDisplay;
    if (display) {
        toPhysicalDisplay = display->getTransform();
    }
    fillInputFrameInfo(info, toPhysicalDisplay);

    // For compatibility reasons we let layers which can receive input
    // receive input before they have actually submitted a buffer. Because
@@ -2626,12 +2636,14 @@ InputWindowInfo Layer::fillInputInfo() {
    auto cropLayer = mDrawingState.touchableRegionCrop.promote();
    if (info.replaceTouchableRegionWithCrop) {
        if (cropLayer == nullptr) {
            info.touchableRegion = Region(Rect{mScreenBounds});
            info.touchableRegion = Region(toPhysicalDisplay.transform(Rect{mScreenBounds}));
        } else {
            info.touchableRegion = Region(Rect{cropLayer->mScreenBounds});
            info.touchableRegion =
                    Region(toPhysicalDisplay.transform(Rect{cropLayer->mScreenBounds}));
        }
    } else if (cropLayer != nullptr) {
        info.touchableRegion = info.touchableRegion.intersect(Rect{cropLayer->mScreenBounds});
        info.touchableRegion = info.touchableRegion.intersect(
                toPhysicalDisplay.transform(Rect{cropLayer->mScreenBounds}));
    }

    // If the layer is a clone, we need to crop the input region to cloned root to prevent
@@ -2639,7 +2651,7 @@ InputWindowInfo Layer::fillInputInfo() {
    if (isClone()) {
        sp<Layer> clonedRoot = getClonedRoot();
        if (clonedRoot != nullptr) {
            Rect rect(clonedRoot->mScreenBounds);
            Rect rect = toPhysicalDisplay.transform(Rect{clonedRoot->mScreenBounds});
            info.touchableRegion = info.touchableRegion.intersect(rect);
        }
    }
+2 −2
Original line number Diff line number Diff line
@@ -913,7 +913,7 @@ public:
    bool getPremultipledAlpha() const;
    void setInputInfo(const InputWindowInfo& info);

    InputWindowInfo fillInputInfo();
    InputWindowInfo fillInputInfo(const sp<DisplayDevice>& display);
    /**
     * Returns whether this layer has an explicitly set input-info.
     */
@@ -1193,7 +1193,7 @@ private:
    sp<Layer> getRootLayer();

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

    // Cached properties computed from drawing state
    // Effective transform taking into account parent transforms and any parent scaling, which is
+21 −4
Original line number Diff line number Diff line
@@ -2906,15 +2906,32 @@ void SurfaceFlinger::updateInputFlinger() {
    mInputWindowCommands.clear();
}

bool enablePerWindowInputRotation() {
    static bool value =
            android::base::GetBoolProperty("persist.debug.per_window_input_rotation", false);
    return value;
}

void SurfaceFlinger::updateInputWindowInfo() {
    std::vector<InputWindowInfo> inputInfos;

    mDrawingState.traverseInReverseZOrder([&](Layer* layer) {
        if (layer->needsInputInfo()) {
        if (!layer->needsInputInfo()) return;
        sp<DisplayDevice> display;
        if (enablePerWindowInputRotation()) {
            for (const auto& pair : ON_MAIN_THREAD(mDisplays)) {
                const auto& displayDevice = pair.second;
                if (!displayDevice->getCompositionDisplay()
                             ->belongsInOutput(layer->getLayerStack(),
                                               layer->getPrimaryDisplayOnly())) {
                    continue;
                }
                display = displayDevice;
            }
        }
        // When calculating the screen bounds we ignore the transparent region since it may
        // result in an unwanted offset.
            inputInfos.push_back(layer->fillInputInfo());
        }
        inputInfos.push_back(layer->fillInputInfo(display));
    });

    mInputFlinger->setInputWindows(inputInfos,