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

Commit 72c6990e authored by Prabir Pradhan's avatar Prabir Pradhan
Browse files

Use the cloned window's layer stack space for raw coordinates

Use the cloned window's layer stack (screen) space as the
raw coordinate space for input going to clones. This ensures the raw
coordinates are consistent between the clone and cloned windows while
mirroring.

Flag: com.android.input.flags.use_cloned_screen_coordinates_as_raw
Test: Presubmit
Bug: 377846505
Change-Id: I7370ac64585315d9c754eaa1eb0077c8555fc6a9
parent 2e5d4dd7
Loading
Loading
Loading
Loading
+45 −17
Original line number Diff line number Diff line
@@ -59,6 +59,32 @@ std::ostream& operator<<(std::ostream& out, const Region& region) {
    return out;
}

status_t writeTransform(android::Parcel* parcel, const ui::Transform& transform) {
    return parcel->writeFloat(transform.dsdx()) ?:
            parcel->writeFloat(transform.dtdx()) ?:
            parcel->writeFloat(transform.tx()) ?:
            parcel->writeFloat(transform.dtdy()) ?:
            parcel->writeFloat(transform.dsdy()) ?:
            parcel->writeFloat(transform.ty());
}

status_t readTransform(const android::Parcel* parcel, ui::Transform& transform) {
    float dsdx, dtdx, tx, dtdy, dsdy, ty;

    const status_t status = parcel->readFloat(&dsdx) ?:
            parcel->readFloat(&dtdx) ?:
            parcel->readFloat(&tx) ?:
            parcel->readFloat(&dtdy) ?:
            parcel->readFloat(&dsdy) ?:
            parcel->readFloat(&ty);
    if (status != OK) {
        return status;
    }

    transform.set({dsdx, dtdx, tx, dtdy, dsdy, ty, 0, 0, 1});
    return OK;
}

} // namespace

void WindowInfo::setInputConfig(ftl::Flags<InputConfig> config, bool value) {
@@ -135,12 +161,7 @@ status_t WindowInfo::writeToParcel(android::Parcel* parcel) const {
        parcel->writeInt32(surfaceInset) ?:
        parcel->writeFloat(globalScaleFactor) ?:
        parcel->writeFloat(alpha) ?:
        parcel->writeFloat(transform.dsdx()) ?:
        parcel->writeFloat(transform.dtdx()) ?:
        parcel->writeFloat(transform.tx()) ?:
        parcel->writeFloat(transform.dtdy()) ?:
        parcel->writeFloat(transform.dsdy()) ?:
        parcel->writeFloat(transform.ty()) ?:
        writeTransform(parcel, transform) ?:
        parcel->writeInt32(static_cast<int32_t>(touchOcclusionMode)) ?:
        parcel->writeInt32(ownerPid.val()) ?:
        parcel->writeInt32(ownerUid.val()) ?:
@@ -153,8 +174,12 @@ status_t WindowInfo::writeToParcel(android::Parcel* parcel) const {
        parcel->writeStrongBinder(touchableRegionCropHandle.promote()) ?:
        parcel->writeStrongBinder(windowToken) ?:
        parcel->writeStrongBinder(focusTransferTarget) ?:
        parcel->writeBool(canOccludePresentation);
        parcel->writeBool(canOccludePresentation) ?:
        parcel->writeBool(cloneLayerStackTransform.has_value());
    // clang-format on
    if (cloneLayerStackTransform) {
        status = status ?: writeTransform(parcel, *cloneLayerStackTransform);
    }
    return status;
}

@@ -174,10 +199,10 @@ status_t WindowInfo::readFromParcel(const android::Parcel* parcel) {
        return status;
    }

    float dsdx, dtdx, tx, dtdy, dsdy, ty;
    int32_t lpFlags, lpType, touchOcclusionModeInt, inputConfigInt, ownerPidInt, ownerUidInt,
            displayIdInt;
    sp<IBinder> touchableRegionCropHandleSp;
    bool hasCloneLayerStackTransform = false;

    // clang-format off
    status = parcel->readInt32(&lpFlags) ?:
@@ -188,12 +213,7 @@ status_t WindowInfo::readFromParcel(const android::Parcel* parcel) {
        parcel->readInt32(&surfaceInset) ?:
        parcel->readFloat(&globalScaleFactor) ?:
        parcel->readFloat(&alpha) ?:
        parcel->readFloat(&dsdx) ?:
        parcel->readFloat(&dtdx) ?:
        parcel->readFloat(&tx) ?:
        parcel->readFloat(&dtdy) ?:
        parcel->readFloat(&dsdy) ?:
        parcel->readFloat(&ty) ?:
        readTransform(parcel, /*byRef*/ transform) ?:
        parcel->readInt32(&touchOcclusionModeInt) ?:
        parcel->readInt32(&ownerPidInt) ?:
        parcel->readInt32(&ownerUidInt) ?:
@@ -206,8 +226,8 @@ status_t WindowInfo::readFromParcel(const android::Parcel* parcel) {
        parcel->readNullableStrongBinder(&touchableRegionCropHandleSp) ?:
        parcel->readNullableStrongBinder(&windowToken) ?:
        parcel->readNullableStrongBinder(&focusTransferTarget) ?:
        parcel->readBool(&canOccludePresentation);

        parcel->readBool(&canOccludePresentation)?:
        parcel->readBool(&hasCloneLayerStackTransform);
    // clang-format on

    if (status != OK) {
@@ -216,7 +236,6 @@ status_t WindowInfo::readFromParcel(const android::Parcel* parcel) {

    layoutParamsFlags = ftl::Flags<Flag>(lpFlags);
    layoutParamsType = static_cast<Type>(lpType);
    transform.set({dsdx, dtdx, tx, dtdy, dsdy, ty, 0, 0, 1});
    touchOcclusionMode = static_cast<TouchOcclusionMode>(touchOcclusionModeInt);
    inputConfig = ftl::Flags<InputConfig>(inputConfigInt);
    ownerPid = Pid{ownerPidInt};
@@ -224,6 +243,15 @@ status_t WindowInfo::readFromParcel(const android::Parcel* parcel) {
    touchableRegionCropHandle = touchableRegionCropHandleSp;
    displayId = ui::LogicalDisplayId{displayIdInt};

    cloneLayerStackTransform =
            hasCloneLayerStackTransform ? std::make_optional<ui::Transform>() : std::nullopt;
    if (cloneLayerStackTransform) {
        status = readTransform(parcel, /*byRef*/ *cloneLayerStackTransform);
        if (status != OK) {
            return status;
        }
    }

    return OK;
}

+6 −1
Original line number Diff line number Diff line
@@ -220,9 +220,14 @@ struct WindowInfo : public Parcelable {
    // An alpha of 1.0 means fully opaque and 0.0 means fully transparent.
    float alpha;

    // Transform applied to individual windows.
    // Transform applied to individual windows for input.
    // Maps display coordinates to the window's input coordinate space.
    ui::Transform transform;

    // Transform applied to get to the layer stack space of the cloned window for input.
    // Maps display coordinates of the clone window to the layer stack space of the cloned window.
    std::optional<ui::Transform> cloneLayerStackTransform;

    /*
     * This is filled in by the WM relative to the frame and then translated
     * to absolute coordinates by SurfaceFlinger once the frame is computed.
+15 −1
Original line number Diff line number Diff line
@@ -40,7 +40,18 @@ TEST(WindowInfo, ParcellingWithoutToken) {
    ASSERT_EQ(OK, i.writeToParcel(&p));
    p.setDataPosition(0);
    i2.readFromParcel(&p);
    ASSERT_TRUE(i2.token == nullptr);
    ASSERT_EQ(i2.token, nullptr);
}

TEST(WindowInfo, ParcellingWithoutCloneTransform) {
    WindowInfo i, i2;
    i.cloneLayerStackTransform.reset();

    Parcel p;
    ASSERT_EQ(OK, i.writeToParcel(&p));
    p.setDataPosition(0);
    i2.readFromParcel(&p);
    ASSERT_EQ(i2.cloneLayerStackTransform, std::nullopt);
}

TEST(WindowInfo, Parcelling) {
@@ -71,6 +82,8 @@ TEST(WindowInfo, Parcelling) {
    i.applicationInfo.token = new BBinder();
    i.applicationInfo.dispatchingTimeoutMillis = 0x12345678ABCD;
    i.focusTransferTarget = new BBinder();
    i.cloneLayerStackTransform = ui::Transform();
    i.cloneLayerStackTransform->set({5, -1, 100, 4, 0, 40, 0, 0, 1});

    Parcel p;
    i.writeToParcel(&p);
@@ -100,6 +113,7 @@ TEST(WindowInfo, Parcelling) {
    ASSERT_EQ(i.touchableRegionCropHandle, i2.touchableRegionCropHandle);
    ASSERT_EQ(i.applicationInfo, i2.applicationInfo);
    ASSERT_EQ(i.focusTransferTarget, i2.focusTransferTarget);
    ASSERT_EQ(i.cloneLayerStackTransform, i2.cloneLayerStackTransform);
}

TEST(InputApplicationInfo, Parcelling) {
+10 −0
Original line number Diff line number Diff line
@@ -224,3 +224,13 @@ flag {
  description: "Allow cursor to transition across multiple connected displays"
  bug: "362719483"
}

flag {
  name: "use_cloned_screen_coordinates_as_raw"
  namespace: "input"
  description: "Use the cloned window's layer stack (screen) space as the raw coordinate space for input going to clones"
  bug: "377846505"
  metadata {
    purpose: PURPOSE_BUGFIX
  }
}
+24 −14
Original line number Diff line number Diff line
@@ -3013,10 +3013,9 @@ void InputDispatcher::addWindowTargetLocked(const sp<WindowInfoHandle>& windowHa
                  windowHandle->getName().c_str());
            return;
        }
        inputTargets.push_back(createInputTarget(connection, windowHandle, dispatchMode,
                                                 targetFlags,
                                                 mWindowInfos.getDisplayTransform(
                                                         windowHandle->getInfo()->displayId),
        inputTargets.push_back(
                createInputTarget(connection, windowHandle, dispatchMode, targetFlags,
                                  mWindowInfos.getRawTransform(*windowHandle->getInfo()),
                                  firstDownTimeInTarget));
        it = inputTargets.end() - 1;
    }
@@ -3068,10 +3067,9 @@ void InputDispatcher::addPointerWindowTargetLocked(
                  windowHandle->getName().c_str());
            return;
        }
        inputTargets.push_back(createInputTarget(connection, windowHandle, dispatchMode,
                                                 targetFlags,
                                                 mWindowInfos.getDisplayTransform(
                                                         windowHandle->getInfo()->displayId),
        inputTargets.push_back(
                createInputTarget(connection, windowHandle, dispatchMode, targetFlags,
                                  mWindowInfos.getRawTransform(*windowHandle->getInfo()),
                                  firstDownTimeInTarget));
        it = inputTargets.end() - 1;
    }
@@ -3104,7 +3102,8 @@ void InputDispatcher::addGlobalMonitoringTargetsLocked(std::vector<InputTarget>&
    for (const Monitor& monitor : selectResponsiveMonitorsLocked(monitorsIt->second)) {
        InputTarget target{monitor.connection};
        // target.firstDownTimeInTarget is not set for global monitors. It is only required in split
        // touch and global monitoring works as intended even without setting firstDownTimeInTarget
        // touch and global monitoring works as intended even without setting firstDownTimeInTarget.
        // Since global monitors don't have windows, use the display transform as the raw transform.
        target.rawTransform = mWindowInfos.getDisplayTransform(displayId);
        target.setDefaultPointerTransform(target.rawTransform);
        inputTargets.push_back(target);
@@ -4291,6 +4290,7 @@ void InputDispatcher::synthesizeCancelationEventsForConnectionLocked(
                                                 motionEntry.downTime, targets);
                } else {
                    targets.emplace_back(fallbackTarget);
                    // Since we don't have a window, use the display transform as the raw transform.
                    const ui::Transform displayTransform =
                            mWindowInfos.getDisplayTransform(motionEntry.displayId);
                    targets.back().rawTransform = displayTransform;
@@ -4376,6 +4376,7 @@ void InputDispatcher::synthesizePointerDownEventsForConnectionLocked(
                                                 targets);
                } else {
                    targets.emplace_back(connection, targetFlags);
                    // Since we don't have a window, use the display transform as the raw transform.
                    const ui::Transform displayTransform =
                            mWindowInfos.getDisplayTransform(motionEntry.displayId);
                    targets.back().rawTransform = displayTransform;
@@ -5289,6 +5290,16 @@ ui::Transform InputDispatcher::DispatcherWindowInfo::getDisplayTransform(
                                                : kIdentityTransform;
}

ui::Transform InputDispatcher::DispatcherWindowInfo::getRawTransform(
        const android::gui::WindowInfo& windowInfo) const {
    // If the window has a cloneLayerStackTransform, always use it as the transform for the "getRaw"
    // APIs. If not, fall back to using the DisplayInfo transform of the window's display.
    return (input_flags::use_cloned_screen_coordinates_as_raw() &&
            windowInfo.cloneLayerStackTransform)
            ? *windowInfo.cloneLayerStackTransform
            : getDisplayTransform(windowInfo.displayId);
}

std::string InputDispatcher::DispatcherWindowInfo::dumpDisplayAndWindowInfo() const {
    std::string dump;
    if (!mWindowHandlesByDisplay.empty()) {
@@ -6567,9 +6578,8 @@ void InputDispatcher::doDispatchCycleFinishedCommand(nsecs_t finishTime,
                                           createInputTarget(connection, windowHandle,
                                                             InputTarget::DispatchMode::AS_IS,
                                                             dispatchEntry->targetFlags,
                                                             mWindowInfos.getDisplayTransform(
                                                                     windowHandle->getInfo()
                                                                             ->displayId),
                                                             mWindowInfos.getRawTransform(
                                                                     *windowHandle->getInfo()),
                                                             downTime));
            }
        }
Loading