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

Commit ee12e4d5 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Move drag event to InputDispatcher (7/n)" into sc-dev

parents ab1098bf 6d4bed94
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@ filegroup {
        "InputTarget.cpp",
        "Monitor.cpp",
        "TouchState.cpp",
        "DragState.cpp",
    ],
}

+38 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "DragState.h"
#include <android-base/stringprintf.h>
#include <input/InputWindow.h>

using android::InputWindowHandle;
using android::base::StringPrintf;

namespace android::inputdispatcher {

void DragState::dump(std::string& dump, const char* prefix) {
    dump += prefix + StringPrintf("Drag Window: %s\n", dragWindow->getName().c_str());
    if (dragHoverWindowHandle) {
        dump += prefix +
                StringPrintf("Drag Hover Window: %s\n", dragHoverWindowHandle->getName().c_str());
    }
    dump += prefix + StringPrintf("isStartDrag: %s\n", isStartDrag ? "true" : "false");
    dump += prefix +
            StringPrintf("isStylusButtonDownAtStart: %s\n",
                         isStylusButtonDownAtStart ? "true" : "false");
}

} // namespace android::inputdispatcher
 No newline at end of file
+45 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef _UI_INPUT_INPUTDISPATCHER_DRAGSTATE_H
#define _UI_INPUT_INPUTDISPATCHER_DRAGSTATE_H

#include <utils/RefBase.h>
#include <string>

namespace android {

class InputWindowHandle;

namespace inputdispatcher {
struct DragState {
    DragState(const sp<android::InputWindowHandle>& windowHandle) : dragWindow(windowHandle) {}
    void dump(std::string& dump, const char* prefix = "");

    // The window being dragged.
    const sp<InputWindowHandle> dragWindow;
    // The last drag hover window which could receive the drag event.
    sp<InputWindowHandle> dragHoverWindowHandle;
    // Indicates the if received first event to check for button state.
    bool isStartDrag = false;
    // Indicate if the stylus button is down at the start of the drag.
    bool isStylusButtonDownAtStart = false;
};

} // namespace inputdispatcher
} // namespace android

#endif // _UI_INPUT_INPUTDISPATCHER_DRAGSTATE_H
 No newline at end of file
+50 −24
Original line number Diff line number Diff line
@@ -961,7 +961,7 @@ sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t display
    // Traverse windows from front to back to find touched window.
    const std::vector<sp<InputWindowHandle>>& windowHandles = getWindowHandlesLocked(displayId);
    for (const sp<InputWindowHandle>& windowHandle : windowHandles) {
        if (ignoreDragWindow && haveSameToken(windowHandle, touchState->dragWindow)) {
        if (ignoreDragWindow && haveSameToken(windowHandle, mDragState->dragWindow)) {
            continue;
        }
        const InputWindowInfo* windowInfo = windowHandle->getInfo();
@@ -2061,7 +2061,7 @@ InputEventInjectionResult InputDispatcher::findTouchedWindowTargetsLocked(
            goto Failed;
        }

        addDragEventLocked(entry, tempTouchState);
        addDragEventLocked(entry);

        // Check whether touches should slip outside of the current foreground window.
        if (maskedAction == AMOTION_EVENT_ACTION_MOVE && entry.pointerCount == 1 &&
@@ -2318,39 +2318,61 @@ Failed:
    return injectionResult;
}

void InputDispatcher::addDragEventLocked(const MotionEntry& entry, TouchState& state) {
    if (entry.pointerCount != 1 || !state.dragWindow) {
void InputDispatcher::finishDragAndDrop(int32_t displayId, float x, float y) {
    const sp<InputWindowHandle> dropWindow =
            findTouchedWindowAtLocked(displayId, x, y, nullptr /*touchState*/,
                                      false /*addOutsideTargets*/, false /*addPortalWindows*/,
                                      true /*ignoreDragWindow*/);
    if (dropWindow) {
        vec2 local = dropWindow->getInfo()->transform.transform(x, y);
        notifyDropWindowLocked(dropWindow->getToken(), local.x, local.y);
    }
    mDragState.reset();
}

void InputDispatcher::addDragEventLocked(const MotionEntry& entry) {
    if (entry.pointerCount != 1 || !mDragState) {
        return;
    }

    if (!mDragState->isStartDrag) {
        mDragState->isStartDrag = true;
        mDragState->isStylusButtonDownAtStart =
                (entry.buttonState & AMOTION_EVENT_BUTTON_STYLUS_PRIMARY) != 0;
    }

    int32_t maskedAction = entry.action & AMOTION_EVENT_ACTION_MASK;
    int32_t x = static_cast<int32_t>(entry.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X));
    int32_t y = static_cast<int32_t>(entry.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y));
    if (maskedAction == AMOTION_EVENT_ACTION_MOVE) {
        // Handle the special case : stylus button no longer pressed.
        bool isStylusButtonDown = (entry.buttonState & AMOTION_EVENT_BUTTON_STYLUS_PRIMARY) != 0;
        if (mDragState->isStylusButtonDownAtStart && !isStylusButtonDown) {
            finishDragAndDrop(entry.displayId, x, y);
            return;
        }

        const sp<InputWindowHandle> hoverWindowHandle =
                findTouchedWindowAtLocked(entry.displayId, x, y, &state,
                findTouchedWindowAtLocked(entry.displayId, x, y, nullptr /*touchState*/,
                                          false /*addOutsideTargets*/, false /*addPortalWindows*/,
                                          true /*ignoreDragWindow*/);
        // enqueue drag exit if needed.
        if (hoverWindowHandle != state.dragHoverWindowHandle &&
            !haveSameToken(hoverWindowHandle, state.dragHoverWindowHandle)) {
            if (state.dragHoverWindowHandle != nullptr) {
                enqueueDragEventLocked(state.dragHoverWindowHandle, true /*isExiting*/, entry);
        if (hoverWindowHandle != mDragState->dragHoverWindowHandle &&
            !haveSameToken(hoverWindowHandle, mDragState->dragHoverWindowHandle)) {
            if (mDragState->dragHoverWindowHandle != nullptr) {
                enqueueDragEventLocked(mDragState->dragHoverWindowHandle, true /*isExiting*/,
                                       entry);
            }
            state.dragHoverWindowHandle = hoverWindowHandle;
            mDragState->dragHoverWindowHandle = hoverWindowHandle;
        }
        // enqueue drag location if needed.
        if (hoverWindowHandle != nullptr) {
            enqueueDragEventLocked(hoverWindowHandle, false /*isExiting*/, entry);
        }
    } else if (maskedAction == AMOTION_EVENT_ACTION_UP ||
               maskedAction == AMOTION_EVENT_ACTION_CANCEL) {
        if (state.dragHoverWindowHandle && maskedAction == AMOTION_EVENT_ACTION_UP) {
            vec2 local = state.dragHoverWindowHandle->getInfo()->transform.transform(x, y);
            notifyDropWindowLocked(state.dragHoverWindowHandle->getToken(), local.x, local.y);
        }
        state.dragWindow = nullptr;
        state.dragHoverWindowHandle = nullptr;
    } else if (maskedAction == AMOTION_EVENT_ACTION_UP) {
        finishDragAndDrop(entry.displayId, x, y);
    } else if (maskedAction == AMOTION_EVENT_ACTION_CANCEL) {
        mDragState.reset();
    }
}

@@ -4445,13 +4467,12 @@ void InputDispatcher::setInputWindowsLocked(
            }
        }

        // If drag window is gone, it would receive a cancel event and broadcast the DRAG_END. we
        // If drag window is gone, it would receive a cancel event and broadcast the DRAG_END. We
        // could just clear the state here.
        if (state.dragWindow &&
            std::find(windowHandles.begin(), windowHandles.end(), state.dragWindow) ==
        if (mDragState &&
            std::find(windowHandles.begin(), windowHandles.end(), mDragState->dragWindow) ==
                    windowHandles.end()) {
            state.dragWindow = nullptr;
            state.dragHoverWindowHandle = nullptr;
            mDragState.reset();
        }
    }

@@ -4690,7 +4711,7 @@ bool InputDispatcher::transferTouchFocus(const sp<IBinder>& fromToken, const sp<

                    // Store the dragging window.
                    if (isDragDrop) {
                        state.dragWindow = toWindowHandle;
                        mDragState = std::make_unique<DragState>(toWindowHandle);
                    }

                    found = true;
@@ -4833,6 +4854,11 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) {
        dump += INDENT "TouchStates: <no displays touched>\n";
    }

    if (mDragState) {
        dump += StringPrintf(INDENT "DragState:\n");
        mDragState->dump(dump, INDENT2);
    }

    if (!mWindowHandlesByDisplay.empty()) {
        for (auto& it : mWindowHandlesByDisplay) {
            const std::vector<sp<InputWindowHandle>> windowHandles = it.second;
+4 −1
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@

#include "AnrTracker.h"
#include "CancelationOptions.h"
#include "DragState.h"
#include "Entry.h"
#include "FocusResolver.h"
#include "InjectionState.h"
@@ -340,6 +341,7 @@ private:
            REQUIRES(mLock);

    std::unordered_map<int32_t, TouchState> mTouchStatesByDisplay GUARDED_BY(mLock);
    std::unique_ptr<DragState> mDragState GUARDED_BY(mLock);

    // Focused applications.
    std::unordered_map<int32_t, std::shared_ptr<InputApplicationHandle>>
@@ -499,7 +501,8 @@ private:
                                  const InjectionState* injectionState);
    // Enqueue a drag event if needed, and update the touch state.
    // Uses findTouchedWindowTargetsLocked to make the decision
    void addDragEventLocked(const MotionEntry& entry, TouchState& state) REQUIRES(mLock);
    void addDragEventLocked(const MotionEntry& entry) REQUIRES(mLock);
    void finishDragAndDrop(int32_t displayId, float x, float y) REQUIRES(mLock);

    struct TouchOcclusionInfo {
        bool hasBlockingOcclusion;
Loading