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

Commit f12f9f18 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Add NO_FOCUS_CHANGE flag to pointer gestures to disallow focus changes"...

Merge "Add NO_FOCUS_CHANGE flag to pointer gestures to disallow focus changes" into sc-dev am: 88fceed4

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/native/+/13838214

Change-Id: Iee432afafe70019e154af5194cf8a81ccc2f3dfc
parents e66802bb 88fceed4
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -70,6 +70,14 @@ enum {
     */
    AMOTION_EVENT_FLAG_IS_GENERATED_GESTURE = 0x8,

    /**
     * This flag indicates that the event will not cause a focus change if it is directed to an
     * unfocused window, even if it an ACTION_DOWN. This is typically used with pointer
     * gestures to allow the user to direct gestures to an unfocused window without bringing it
     * into focus.
     */
    AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE = 0x40,

    /* Motion event is inconsistent with previously sent motion events. */
    AMOTION_EVENT_FLAG_TAINTED = 0x80000000,
};
+6 −0
Original line number Diff line number Diff line
@@ -2886,6 +2886,12 @@ void InputDispatcher::enqueueDispatchEntryLocked(const sp<Connection>& connectio
                ATRACE_NAME(message.c_str());
            }

            if ((motionEntry.flags & AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE) &&
                (motionEntry.policyFlags & POLICY_FLAG_TRUSTED)) {
                // Skip reporting pointer down outside focus to the policy.
                break;
            }

            dispatchPointerDownOutsideFocus(motionEntry.source, dispatchEntry->resolvedAction,
                                            inputTarget.inputChannel->getConnectionToken());

+14 −8
Original line number Diff line number Diff line
@@ -2456,6 +2456,12 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, nsecs_t readTime, u
    int32_t metaState = getContext()->getGlobalMetaState();
    int32_t buttonState = mCurrentCookedState.buttonState;

    uint32_t flags = 0;

    if (!PointerGesture::canGestureAffectWindowFocus(mPointerGesture.currentGestureMode)) {
        flags |= AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE;
    }

    // Update last coordinates of pointers that have moved so that we observe the new
    // pointer positions at the same time as other pointers that have just gone up.
    bool down = mPointerGesture.currentGestureMode == PointerGesture::Mode::TAP ||
@@ -2485,8 +2491,8 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, nsecs_t readTime, u
    BitSet32 dispatchedGestureIdBits(mPointerGesture.lastGestureIdBits);
    if (!dispatchedGestureIdBits.isEmpty()) {
        if (cancelPreviousGesture) {
            dispatchMotion(when, readTime, policyFlags, mSource, AMOTION_EVENT_ACTION_CANCEL, 0, 0,
                           metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
            dispatchMotion(when, readTime, policyFlags, mSource, AMOTION_EVENT_ACTION_CANCEL, 0,
                           flags, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
                           mPointerGesture.lastGestureProperties, mPointerGesture.lastGestureCoords,
                           mPointerGesture.lastGestureIdToIndex, dispatchedGestureIdBits, -1, 0, 0,
                           mPointerGesture.downTime);
@@ -2504,7 +2510,7 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, nsecs_t readTime, u
                uint32_t id = upGestureIdBits.clearFirstMarkedBit();

                dispatchMotion(when, readTime, policyFlags, mSource,
                               AMOTION_EVENT_ACTION_POINTER_UP, 0, 0, metaState, buttonState,
                               AMOTION_EVENT_ACTION_POINTER_UP, 0, flags, metaState, buttonState,
                               AMOTION_EVENT_EDGE_FLAG_NONE, mPointerGesture.lastGestureProperties,
                               mPointerGesture.lastGestureCoords,
                               mPointerGesture.lastGestureIdToIndex, dispatchedGestureIdBits, id, 0,
@@ -2517,7 +2523,7 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, nsecs_t readTime, u

    // Send motion events for all pointers that moved.
    if (moveNeeded) {
        dispatchMotion(when, readTime, policyFlags, mSource, AMOTION_EVENT_ACTION_MOVE, 0, 0,
        dispatchMotion(when, readTime, policyFlags, mSource, AMOTION_EVENT_ACTION_MOVE, 0, flags,
                       metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
                       mPointerGesture.currentGestureProperties,
                       mPointerGesture.currentGestureCoords,
@@ -2538,7 +2544,7 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, nsecs_t readTime, u
            }

            dispatchMotion(when, readTime, policyFlags, mSource, AMOTION_EVENT_ACTION_POINTER_DOWN,
                           0, 0, metaState, buttonState, 0,
                           0, flags, metaState, buttonState, 0,
                           mPointerGesture.currentGestureProperties,
                           mPointerGesture.currentGestureCoords,
                           mPointerGesture.currentGestureIdToIndex, dispatchedGestureIdBits, id, 0,
@@ -2548,8 +2554,8 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, nsecs_t readTime, u

    // Send motion events for hover.
    if (mPointerGesture.currentGestureMode == PointerGesture::Mode::HOVER) {
        dispatchMotion(when, readTime, policyFlags, mSource, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
                       metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
        dispatchMotion(when, readTime, policyFlags, mSource, AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
                       flags, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
                       mPointerGesture.currentGestureProperties,
                       mPointerGesture.currentGestureCoords,
                       mPointerGesture.currentGestureIdToIndex,
@@ -2573,7 +2579,7 @@ void TouchInputMapper::dispatchPointerGestures(nsecs_t when, nsecs_t readTime, u

        const int32_t displayId = mPointerController->getDisplayId();
        NotifyMotionArgs args(getContext()->getNextId(), when, readTime, getDeviceId(), mSource,
                              displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
                              displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, flags,
                              metaState, buttonState, MotionClassification::NONE,
                              AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties, &pointerCoords,
                              0, 0, x, y, mPointerGesture.downTime, /* videoFrames */ {});
+21 −0
Original line number Diff line number Diff line
@@ -590,6 +590,27 @@ private:
            QUIET,
        };

        // When a gesture is sent to an unfocused window, return true if it can bring that window
        // into focus, false otherwise.
        static bool canGestureAffectWindowFocus(Mode mode) {
            switch (mode) {
                case Mode::TAP:
                case Mode::TAP_DRAG:
                case Mode::BUTTON_CLICK_OR_DRAG:
                    // Taps can affect window focus.
                    return true;
                case Mode::FREEFORM:
                case Mode::HOVER:
                case Mode::NEUTRAL:
                case Mode::PRESS:
                case Mode::QUIET:
                case Mode::SWIPE:
                    // Most gestures can be performed on an unfocused window, so they should not
                    // not affect window focus.
                    return false;
            }
        }

        // Time the first finger went down.
        nsecs_t firstTouchTime;

+26 −1
Original line number Diff line number Diff line
@@ -1225,6 +1225,11 @@ public:
        return *this;
    }

    MotionEventBuilder& addFlag(uint32_t flags) {
        mFlags |= flags;
        return *this;
    }

    MotionEvent build() {
        std::vector<PointerProperties> pointerProperties;
        std::vector<PointerCoords> pointerCoords;
@@ -1244,7 +1249,7 @@ public:
        MotionEvent event;
        ui::Transform identityTransform;
        event.initialize(InputEvent::nextId(), DEVICE_ID, mSource, mDisplayId, INVALID_HMAC,
                         mAction, mActionButton, /* flags */ 0, /* edgeFlags */ 0, AMETA_NONE,
                         mAction, mActionButton, mFlags, /* edgeFlags */ 0, AMETA_NONE,
                         mButtonState, MotionClassification::NONE, identityTransform,
                         /* xPrecision */ 0, /* yPrecision */ 0, mRawXCursorPosition,
                         mRawYCursorPosition, mDisplayWidth, mDisplayHeight, mEventTime, mEventTime,
@@ -1260,6 +1265,7 @@ private:
    int32_t mDisplayId{ADISPLAY_ID_DEFAULT};
    int32_t mActionButton{0};
    int32_t mButtonState{0};
    int32_t mFlags{0};
    float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
    float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
    int32_t mDisplayWidth{AMOTION_EVENT_INVALID_DISPLAY_SIZE};
@@ -3105,6 +3111,25 @@ TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlr
    mFakePolicy->assertOnPointerDownWasNotCalled();
}

// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
    const MotionEvent event =
            MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
                    .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
                    .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(20).y(20))
                    .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
                    .build();
    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(mDispatcher, event))
            << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
    mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);

    ASSERT_TRUE(mDispatcher->waitForIdle());
    mFakePolicy->assertOnPointerDownWasNotCalled();
    // Ensure that the unfocused window did not receive any FOCUS events.
    mUnfocusedWindow->assertNoEvents();
}

// These tests ensures we can send touch events to a single client when there are multiple input
// windows that point to the same client token.
class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {