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

Commit 1976760e authored by Prabir Pradhan's avatar Prabir Pradhan
Browse files

Address internal comments: Pointer icon refactor for mouse

Bug: 293587049
Test: atest inputflinger_tests
Change-Id: I9609e186ec92f283c25d2c9734ea2c3465445d5c
parent da10dd34
Loading
Loading
Loading
Loading
+33 −18
Original line number Diff line number Diff line
@@ -77,20 +77,17 @@ NotifyMotionArgs PointerChoreographer::processMotion(const NotifyMotionArgs& arg

NotifyMotionArgs PointerChoreographer::processMouseEventLocked(const NotifyMotionArgs& args) {
    if (args.getPointerCount() != 1) {
        LOG(FATAL) << "Wrong number of pointers " << args.dump();
        LOG(FATAL) << "Only mouse events with a single pointer are currently supported: "
                   << args.dump();
    }

    const int32_t displayId = getTargetMouseDisplayLocked(args.displayId);
    auto it = mMousePointersByDisplay.find(displayId);
    if (it == mMousePointersByDisplay.end()) {
        it = mMousePointersByDisplay
                     .insert({displayId,
                              mPolicy.createPointerController(
                                      PointerControllerInterface::ControllerType::MOUSE)})
                     .first;
        if (const auto viewport = findViewportByIdLocked(displayId); viewport) {
            it->second->setDisplayViewport(*viewport);
        }

    // Get the mouse pointer controller for the display, or create one if it doesn't exist.
    auto [it, emplaced] =
            mMousePointersByDisplay.try_emplace(displayId,
                                                getMouseControllerConstructor(displayId));
    if (emplaced) {
        notifyPointerDisplayIdChangedLocked();
    }

@@ -194,9 +191,10 @@ void PointerChoreographer::updatePointerControllersLocked() {

    // Remove PointerControllers no longer needed.
    // This has the side-effect of fading pointers or clearing spots before removal.
    std::erase_if(mMousePointersByDisplay, [&mouseDisplaysToKeep](const auto& item) {
        if (mouseDisplaysToKeep.find(item.first) == mouseDisplaysToKeep.end()) {
            item.second->fade(PointerControllerInterface::Transition::IMMEDIATE);
    std::erase_if(mMousePointersByDisplay, [&mouseDisplaysToKeep](const auto& pair) {
        auto& [displayId, controller] = pair;
        if (mouseDisplaysToKeep.find(displayId) == mouseDisplaysToKeep.end()) {
            controller->fade(PointerControllerInterface::Transition::IMMEDIATE);
            return true;
        }
        return false;
@@ -211,8 +209,12 @@ void PointerChoreographer::notifyPointerDisplayIdChangedLocked() {
    FloatPoint cursorPosition = {0, 0};
    if (const auto it = mMousePointersByDisplay.find(mDefaultMouseDisplayId);
        it != mMousePointersByDisplay.end()) {
        displayIdToNotify = it->second->getDisplayId();
        cursorPosition = it->second->getPosition();
        const auto& pointerController = it->second;
        // Use the displayId from the pointerController, because it accurately reflects whether
        // the viewport has been added for that display. Otherwise, we would have to check if
        // the viewport exists separately.
        displayIdToNotify = pointerController->getDisplayId();
        cursorPosition = pointerController->getPosition();
    }

    if (mNotifiedPointerDisplayId == displayIdToNotify) {
@@ -232,8 +234,7 @@ void PointerChoreographer::setDefaultMouseDisplayId(int32_t displayId) {
void PointerChoreographer::setDisplayViewports(const std::vector<DisplayViewport>& viewports) {
    std::scoped_lock _l(mLock);
    for (const auto& viewport : viewports) {
        int32_t displayId = viewport.displayId;
        if (const auto it = mMousePointersByDisplay.find(displayId);
        if (const auto it = mMousePointersByDisplay.find(viewport.displayId);
            it != mMousePointersByDisplay.end()) {
            it->second->setDisplayViewport(viewport);
        }
@@ -262,4 +263,18 @@ FloatPoint PointerChoreographer::getMouseCursorPosition(int32_t displayId) {
    return {AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION};
}

PointerChoreographer::ControllerConstructor PointerChoreographer::getMouseControllerConstructor(
        int32_t displayId) {
    std::function<std::shared_ptr<PointerControllerInterface>()> ctor =
            [this, displayId]() REQUIRES(mLock) {
                auto pc = mPolicy.createPointerController(
                        PointerControllerInterface::ControllerType::MOUSE);
                if (const auto viewport = findViewportByIdLocked(displayId); viewport) {
                    pc->setDisplayViewport(*viewport);
                }
                return pc;
            };
    return ConstructorDelegate(std::move(ctor));
}

} // namespace android
+19 −0
Original line number Diff line number Diff line
@@ -21,9 +21,24 @@
#include "PointerChoreographerPolicyInterface.h"

#include <android-base/thread_annotations.h>
#include <type_traits>

namespace android {

/**
 * A helper class that wraps a factory method that acts as a constructor for the type returned
 * by the factory method.
 */
template <typename Factory>
struct ConstructorDelegate {
    constexpr ConstructorDelegate(Factory&& factory) : mFactory(std::move(factory)) {}

    using ConstructedType = std::invoke_result_t<const Factory&>;
    constexpr operator ConstructedType() const { return mFactory(); }

    Factory mFactory;
};

/**
 * PointerChoreographer manages the icons shown by the system for input interactions.
 * This includes showing the mouse cursor, stylus hover icons, and touch spots.
@@ -81,6 +96,10 @@ private:
    NotifyMotionArgs processMouseEventLocked(const NotifyMotionArgs& args) REQUIRES(mLock);
    NotifyMotionArgs processTouchscreenEventLocked(const NotifyMotionArgs& args) REQUIRES(mLock);

    using ControllerConstructor =
            ConstructorDelegate<std::function<std::shared_ptr<PointerControllerInterface>()>>;
    ControllerConstructor getMouseControllerConstructor(int32_t displayId) REQUIRES(mLock);

    std::mutex mLock;

    InputListenerInterface& mNextListener;
+7 −4
Original line number Diff line number Diff line
@@ -452,11 +452,14 @@ public:
    /* Returns true if any InputConnection is currently active. */
    virtual bool isInputMethodConnectionActive() = 0;

    /* Gets the viewport of a particular display. The logical bounds of the viewport should be used
     * as the range of possible values for pointing devices, like mice and touchpads.
    /* Gets the viewport of a particular display that the pointer device is associated with. If
     * the pointer device is not associated with any display, it should ADISPLAY_IS_NONE to get
     * the viewport that should be used. The device should get a new viewport using this method
     * every time there is a display configuration change. The logical bounds of the viewport should
     * be used as the range of possible values for pointing devices, like mice and touchpads.
     */
    virtual std::optional<DisplayViewport> getViewportForPointerDevice(
            int32_t associatedDisplayId) = 0;
    virtual std::optional<DisplayViewport> getPointerViewportForAssociatedDisplay(
            int32_t associatedDisplayId = ADISPLAY_ID_NONE) = 0;
};

} // namespace android
+6 −0
Original line number Diff line number Diff line
@@ -41,6 +41,12 @@ public:
    virtual std::shared_ptr<PointerControllerInterface> createPointerController(
            PointerControllerInterface::ControllerType type) = 0;

    /**
     * Notifies the policy that the default pointer displayId has changed. PointerChoreographer is
     * the single source of truth for all pointers on screen.
     * @param displayId The updated display on which the mouse cursor is shown
     * @param position The new position of the mouse cursor on the logical display
     */
    virtual void notifyPointerDisplayIdChanged(int32_t displayId, const FloatPoint& position) = 0;
};

+16 −15
Original line number Diff line number Diff line
@@ -37,8 +37,6 @@ namespace android {
// The default velocity control parameters that has no effect.
static const VelocityControlParameters FLAT_VELOCITY_CONTROL_PARAMS{};

static const DisplayViewport INVALID_VIEWPORT{};

// --- CursorMotionAccumulator ---

CursorMotionAccumulator::CursorMotionAccumulator() {
@@ -76,7 +74,8 @@ void CursorMotionAccumulator::finishSync() {
CursorInputMapper::CursorInputMapper(InputDeviceContext& deviceContext,
                                     const InputReaderConfiguration& readerConfig)
      : InputMapper(deviceContext, readerConfig),
        mLastEventTime(std::numeric_limits<nsecs_t>::min()) {}
        mLastEventTime(std::numeric_limits<nsecs_t>::min()),
        mEnablePointerChoreographer(input_flags::enable_pointer_choreographer()) {}

CursorInputMapper::~CursorInputMapper() {
    if (mPointerController != nullptr) {
@@ -288,7 +287,7 @@ std::list<NotifyArgs> CursorInputMapper::sync(nsecs_t when, nsecs_t readTime) {
    float xCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
    float yCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
    if (mSource == AINPUT_SOURCE_MOUSE) {
        if (!input_flags::enable_pointer_choreographer()) {
        if (!mEnablePointerChoreographer) {
            if (moved || scrolled || buttonsChanged) {
                mPointerController->setPresentation(
                        PointerControllerInterface::Presentation::POINTER);
@@ -507,14 +506,14 @@ void CursorInputMapper::configureOnChangeDisplayInfo(const InputReaderConfigurat
    const bool isPointer = mParameters.mode == Parameters::Mode::POINTER;

    mDisplayId = ADISPLAY_ID_NONE;
    DisplayViewport resolvedViewport = INVALID_VIEWPORT;
    std::optional<DisplayViewport> resolvedViewport;
    bool isBoundsSet = false;
    if (auto assocViewport = mDeviceContext.getAssociatedViewport(); assocViewport) {
        // This InputDevice is associated with a viewport.
        // Only generate events for the associated display.
        mDisplayId = assocViewport->displayId;
        resolvedViewport = *assocViewport;
        if (!input_flags::enable_pointer_choreographer()) {
        if (!mEnablePointerChoreographer) {
            const bool mismatchedPointerDisplay =
                    isPointer && (assocViewport->displayId != mPointerController->getDisplayId());
            if (mismatchedPointerDisplay) {
@@ -525,13 +524,13 @@ void CursorInputMapper::configureOnChangeDisplayInfo(const InputReaderConfigurat
        }
    } else if (isPointer) {
        // The InputDevice is not associated with a viewport, but it controls the mouse pointer.
        if (input_flags::enable_pointer_choreographer()) {
        if (mEnablePointerChoreographer) {
            // Always use DISPLAY_ID_NONE for mouse events.
            // PointerChoreographer will make it target the correct the displayId later.
            const auto pointerViewport =
                    getContext()->getPolicy()->getViewportForPointerDevice(ADISPLAY_ID_NONE);
                    getContext()->getPolicy()->getPointerViewportForAssociatedDisplay();
            mDisplayId = pointerViewport ? std::make_optional(ADISPLAY_ID_NONE) : std::nullopt;
            resolvedViewport = pointerViewport.value_or(INVALID_VIEWPORT);
            resolvedViewport = pointerViewport;
        } else {
            mDisplayId = mPointerController->getDisplayId();
            if (auto v = config.getDisplayViewportById(*mDisplayId); v) {
@@ -545,15 +544,17 @@ void CursorInputMapper::configureOnChangeDisplayInfo(const InputReaderConfigurat
    }

    mOrientation = (mParameters.orientationAware && mParameters.hasAssociatedDisplay) ||
                    mParameters.mode == Parameters::Mode::POINTER_RELATIVE
                    mParameters.mode == Parameters::Mode::POINTER_RELATIVE || !resolvedViewport
            ? ui::ROTATION_0
            : getInverseRotation(resolvedViewport.orientation);
            : getInverseRotation(resolvedViewport->orientation);

    if (!isBoundsSet) {
        mBoundsInLogicalDisplay = {static_cast<float>(resolvedViewport.logicalLeft),
                                   static_cast<float>(resolvedViewport.logicalTop),
                                   static_cast<float>(resolvedViewport.logicalRight - 1),
                                   static_cast<float>(resolvedViewport.logicalBottom - 1)};
        mBoundsInLogicalDisplay = resolvedViewport
                ? FloatRect{static_cast<float>(resolvedViewport->logicalLeft),
                            static_cast<float>(resolvedViewport->logicalTop),
                            static_cast<float>(resolvedViewport->logicalRight - 1),
                            static_cast<float>(resolvedViewport->logicalBottom - 1)}
                : FloatRect{0, 0, 0, 0};
    }

    bumpGeneration();
Loading