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

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

Merge "Refactor QuickStepController into Gestures"

parents 252c7c43 86a436ef
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -36,7 +36,7 @@ public interface NavGesture extends Plugin {

        public boolean onInterceptTouchEvent(MotionEvent event);

        public void setBarState(boolean vertical, boolean isRtl);
        public void setBarState(boolean isRtl, int navBarPosition);

        public void onDraw(Canvas canvas);

+15 −0
Original line number Diff line number Diff line
@@ -263,6 +263,16 @@ public class ButtonDispatcher {
        }
    }

    public void setTranslation(int x, int y, int z) {
        final int N = mViews.size();
        for (int i = 0; i < N; i++) {
            final View view = mViews.get(i);
            view.setTranslationX(x);
            view.setTranslationY(y);
            view.setTranslationZ(z);
        }
    }

    public ArrayList<View> getViews() {
        return mViews;
    }
@@ -276,6 +286,11 @@ public class ButtonDispatcher {
        if (mImageDrawable != null) {
            mImageDrawable.setCallback(mCurrentView);
        }
        if (mCurrentView != null) {
            mCurrentView.setTranslationX(0);
            mCurrentView.setTranslationY(0);
            mCurrentView.setTranslationZ(0);
        }
    }

    public void setVertical(boolean vertical) {
+131 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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.
 */

package com.android.systemui.statusbar.phone;

import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_HOME;

import android.annotation.NonNull;
import android.hardware.input.InputManager;
import android.os.Handler;
import android.os.SystemClock;
import android.view.HapticFeedbackConstants;
import android.view.InputDevice;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.MotionEvent;

import com.android.systemui.recents.OverviewProxyService;

/**
 * A back action when triggered will execute a back command
 */
public class NavigationBackAction extends NavigationGestureAction {

    private static final String PULL_HOME_GO_BACK_PROP = "quickstepcontroller_homegoesback";
    private static final String BACK_AFTER_END_PROP =
            "quickstepcontroller_homegoesbackwhenend";
    private static final String NAVBAR_EXPERIMENTS_DISABLED = "navbarexperiments_disabled";
    private static final long BACK_BUTTON_FADE_OUT_ALPHA = 60;
    private static final long BACK_GESTURE_POLL_TIMEOUT = 1000;

    private final Handler mHandler = new Handler();

    private final Runnable mExecuteBackRunnable = new Runnable() {
        @Override
        public void run() {
            if (isEnabled() && canPerformAction()) {
                performBack();
                mHandler.postDelayed(this, BACK_GESTURE_POLL_TIMEOUT);
            }
        }
    };

    public NavigationBackAction(@NonNull NavigationBarView navigationBarView,
            @NonNull OverviewProxyService service) {
        super(navigationBarView, service);
    }

    @Override
    public int requiresTouchDownHitTarget() {
        return HIT_TARGET_HOME;
    }

    @Override
    public boolean requiresDragWithHitTarget() {
        return true;
    }

    @Override
    public boolean canPerformAction() {
        return mProxySender.getBackButtonAlpha() > 0;
    }

    @Override
    public boolean isEnabled() {
        return swipeHomeGoBackGestureEnabled();
    }

    @Override
    protected void onGestureStart(MotionEvent event) {
        if (!QuickStepController.shouldhideBackButton(getContext())) {
            mNavigationBarView.getBackButton().setAlpha(0 /* alpha */, true /* animate */,
                    BACK_BUTTON_FADE_OUT_ALPHA);
        }
        mHandler.removeCallbacks(mExecuteBackRunnable);
        if (!shouldExecuteBackOnUp()) {
            performBack();
            mHandler.postDelayed(mExecuteBackRunnable, BACK_GESTURE_POLL_TIMEOUT);
        }
    }

    @Override
    protected void onGestureEnd() {
        mHandler.removeCallbacks(mExecuteBackRunnable);
        if (!QuickStepController.shouldhideBackButton(getContext())) {
            mNavigationBarView.getBackButton().setAlpha(
                    mProxySender.getBackButtonAlpha(), true /* animate */);
        }
        if (shouldExecuteBackOnUp()) {
            performBack();
        }
    }

    private void performBack() {
        sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK);
        sendEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK);
        mNavigationBarView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
    }

    private boolean swipeHomeGoBackGestureEnabled() {
        return !getGlobalBoolean(NAVBAR_EXPERIMENTS_DISABLED)
                && getGlobalBoolean(PULL_HOME_GO_BACK_PROP);
    }

    private boolean shouldExecuteBackOnUp() {
        return !getGlobalBoolean(NAVBAR_EXPERIMENTS_DISABLED)
                && getGlobalBoolean(BACK_AFTER_END_PROP);
    }

    private void sendEvent(int action, int code) {
        long when = SystemClock.uptimeMillis();
        final KeyEvent ev = new KeyEvent(when, when, action, code, 0 /* repeat */,
                0 /* metaState */, KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /* scancode */,
                KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY,
                InputDevice.SOURCE_KEYBOARD);
        InputManager.getInstance().injectInputEvent(ev, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
    }
}
+28 −19
Original line number Diff line number Diff line
@@ -38,9 +38,11 @@ import android.graphics.Rect;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
import android.view.Display;
import android.view.MotionEvent;
@@ -49,6 +51,7 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
import android.view.inputmethod.InputMethodManager;
@@ -143,6 +146,10 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
    private RecentsOnboarding mRecentsOnboarding;
    private NotificationPanelView mPanelView;

    private QuickScrubAction mQuickScrubAction;
    private QuickStepAction mQuickStepAction;
    private NavigationBackAction mBackAction;

    /**
     * Helper that is responsible for showing the right toast when a disallowed activity operation
     * occurred. In pinned mode, we show instructions on how to break out of this mode, whilst in
@@ -299,6 +306,10 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
        mButtonDispatchers.put(R.id.rotate_suggestion, rotateSuggestionButton);
        mButtonDispatchers.put(R.id.menu_container, mContextualButtonGroup);
        mDeadZone = new DeadZone(this);

        mQuickScrubAction = new QuickScrubAction(this, mOverviewProxyService);
        mQuickStepAction = new QuickStepAction(this, mOverviewProxyService);
        mBackAction = new NavigationBackAction(this, mOverviewProxyService);
    }

    public BarTransitions getBarTransitions() {
@@ -313,6 +324,8 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
        mPanelView = panel;
        if (mGestureHelper instanceof QuickStepController) {
            ((QuickStepController) mGestureHelper).setComponents(this);
            ((QuickStepController) mGestureHelper).setGestureActions(mQuickStepAction,
                    null /* swipeDownAction*/, mBackAction, mQuickScrubAction);
        }
    }

@@ -756,24 +769,6 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
        mRecentsOnboarding.hide(true);
    }

    /**
     * @return the button at the given {@param x} and {@param y}.
     */
    ButtonDispatcher getButtonAtPosition(int x, int y) {
        for (int i = 0; i < mButtonDispatchers.size(); i++) {
            ButtonDispatcher button = mButtonDispatchers.valueAt(i);
            View buttonView = button.getCurrentView();
            if (buttonView != null) {
                buttonView.getHitRect(mTmpRect);
                offsetDescendantRectToMyCoords(buttonView, mTmpRect);
                if (mTmpRect.contains(x, y)) {
                    return button;
                }
            }
        }
        return null;
    }

    @Override
    public void onFinishInflate() {
        mNavigationInflaterView = findViewById(R.id.navigation_inflater);
@@ -908,7 +903,13 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
    private void updateTaskSwitchHelper() {
        if (mGestureHelper == null) return;
        boolean isRtl = (getLayoutDirection() == View.LAYOUT_DIRECTION_RTL);
        mGestureHelper.setBarState(mVertical, isRtl);
        int navBarPos = 0;
        try {
            navBarPos = WindowManagerGlobal.getWindowManagerService().getNavBarPosition();
        } catch (RemoteException e) {
            Slog.e(TAG, "Failed to get nav bar position.", e);
        }
        mGestureHelper.setBarState(isRtl, navBarPos);
    }

    @Override
@@ -1112,6 +1113,14 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav

        mContextualButtonGroup.dump(pw);
        if (mGestureHelper != null) {
            pw.println("Navigation Gesture Actions {");
            pw.print("    "); pw.println("QuickScrub Enabled=" + mQuickScrubAction.isEnabled());
            pw.print("    "); pw.println("QuickScrub Active=" + mQuickScrubAction.isActive());
            pw.print("    "); pw.println("QuickStep Enabled=" + mQuickStepAction.isEnabled());
            pw.print("    "); pw.println("QuickStep Active=" + mQuickStepAction.isActive());
            pw.print("    "); pw.println("Back Gesture Enabled=" + mBackAction.isEnabled());
            pw.print("    "); pw.println("Back Gesture Active=" + mBackAction.isActive());
            pw.println("}");
            mGestureHelper.dump(pw);
        }
        mRecentsOnboarding.dump(pw);
+181 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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.
 */

package com.android.systemui.statusbar.phone;

import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_RIGHT;

import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_NONE;

import android.annotation.NonNull;
import android.content.Context;
import android.graphics.Canvas;
import android.view.MotionEvent;

import android.view.WindowManagerPolicyConstants;
import com.android.systemui.recents.OverviewProxyService;

/**
 * A gesture action that would be triggered and reassigned by {@link QuickStepController}
 */
public abstract class NavigationGestureAction {

    protected final NavigationBarView mNavigationBarView;
    protected final OverviewProxyService mProxySender;

    protected int mNavigationBarPosition;
    protected boolean mDragHorizontalPositive;
    protected boolean mDragVerticalPositive;
    private boolean mIsActive;

    public NavigationGestureAction(@NonNull NavigationBarView navigationBarView,
            @NonNull OverviewProxyService service) {
        mNavigationBarView = navigationBarView;
        mProxySender = service;
    }

    /**
     * Pass event that the state of the bar (such as rotation) has changed
     * @param changed if rotation or drag positive direction (such as ltr) has changed
     * @param navBarPos position of navigation bar
     * @param dragHorPositive direction of positive horizontal drag, could change with ltr changes
     * @param dragVerPositive direction of positive vertical drag, could change with ltr changes
     */
    public void setBarState(boolean changed, int navBarPos, boolean dragHorPositive,
            boolean dragVerPositive) {
        mNavigationBarPosition = navBarPos;
        mDragHorizontalPositive = dragHorPositive;
        mDragVerticalPositive = dragVerPositive;
    }

    /**
     * Resets the state of the action. Called when touch down occurs over the Navigation Bar.
     */
    public void reset() {
        mIsActive = false;
    }

    /**
     * Start the gesture and the action will be active
     * @param event the event that caused the gesture
     */
    public void startGesture(MotionEvent event) {
        mIsActive = true;
        onGestureStart(event);
    }

    /**
     * Gesture has ended with action cancel or up and this action will not be active
     */
    public void endGesture() {
        mIsActive = false;
        onGestureEnd();
    }

    /**
     * If the action is currently active based on the gesture that triggered it. Only one action
     * can occur at a time
     * @return whether or not if this action has been triggered
     */
    public boolean isActive() {
        return mIsActive;
    }

    /**
     * @return whether or not this action can run if notification shade is shown
     */
    public boolean canRunWhenNotificationsShowing() {
        return true;
    }

    /**
     * @return whether or not this action triggers when starting a gesture from a certain hit target
     * If {@link HIT_TARGET_NONE} is specified then action does not need to be triggered by button
     */
    public int requiresTouchDownHitTarget() {
        return HIT_TARGET_NONE;
    }

    /**
     * @return whether or not to move the button that started gesture over with user input drag
     */
    public boolean requiresDragWithHitTarget() {
        return false;
    }

    /**
     * Tell if the action is able to execute. Note that {@link #isEnabled()} must be true for this
     * to be checked. The difference between this and {@link #isEnabled()} is that this dependent
     * on the state of the navigation bar
     * @return true if action can execute after gesture activates based on current states
     */
    public boolean canPerformAction() {
        return true;
    }

    /**
     * Tell if action is enabled. Compared to {@link #canPerformAction()} this is based on settings
     * if the action is disabled for a particular gesture. For example a back action can be enabled
     * however if there is nothing to back to then {@link #canPerformAction()} should return false.
     * In this way if the action requires {@link #requiresDragWithHitTarget()} then if enabled, the
     * button can be dragged with a large dampening factor during the gesture but will not activate
     * the action.
     * @return true if this action is enabled and can run
     */
    public abstract boolean isEnabled();

    protected void onDarkIntensityChange(float intensity) {
    }

    protected void onDraw(Canvas canvas) {
    }

    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    }

    /**
     * When gesture starts, this will run to execute the action
     * @param event the event that triggered the gesture
     */
    protected abstract void onGestureStart(MotionEvent event);

    /**
     * Channels motion move events to the action to track the user inputs
     * @param x the x position
     * @param y the y position
     */
    public void onGestureMove(int x, int y) {
    }

    /**
     * When gesture ends, this will run from action up or cancel
     */
    protected void onGestureEnd() {
    }

    protected Context getContext() {
        return mNavigationBarView.getContext();
    }

    protected boolean isNavBarVertical() {
        return mNavigationBarPosition == NAV_BAR_LEFT || mNavigationBarPosition == NAV_BAR_RIGHT;
    }

    protected boolean getGlobalBoolean(@NonNull String key) {
        return QuickStepController.getBoolGlobalSetting(getContext(), key);
    }
}
Loading