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

Commit 6c202d41 authored by Tiger Huang's avatar Tiger Huang Committed by Android (Google) Code Review
Browse files

Merge "Let view focus move across adjacent task fragments" into main

parents 9067ebe3 75f3b1b8
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -370,4 +370,14 @@ interface IWindowSession {
    boolean transferEmbeddedTouchFocusToHost(IWindow embeddedWindow);

    boolean transferHostTouchGestureToEmbedded(IWindow hostWindow, IBinder transferTouchToken);

    /**
     * Moves the focus to the adjacent window if there is one in the given direction. This can only
     * move the focus to the window in the same leaf task.
     *
     * @param fromWindow The calling window that the focus is moved from.
     * @param direction The {@link android.view.View.FocusDirection} that the new focus should go.
     * @return {@code true} if the focus changes. Otherwise, {@code false}.
     */
    boolean moveFocusToAdjacentWindow(IWindow fromWindow, int direction);
}
+18 −1
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
package android.view;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.content.pm.ActivityInfo.OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS;
import static android.graphics.HardwareRenderer.SYNC_CONTEXT_IS_STOPPED;
import static android.graphics.HardwareRenderer.SYNC_LOST_SURFACE_REWARD_IF_FOUND;
@@ -7236,7 +7237,7 @@ public final class ViewRootImpl implements ViewParent,
        }
        private boolean performFocusNavigation(KeyEvent event) {
            int direction = 0;
            @FocusDirection int direction = 0;
            switch (event.getKeyCode()) {
                case KeyEvent.KEYCODE_DPAD_LEFT:
                    if (event.hasNoModifiers()) {
@@ -7288,6 +7289,8 @@ public final class ViewRootImpl implements ViewParent,
                                            isFastScrolling));
                            return true;
                        }
                    } else if (moveFocusToAdjacentWindow(direction)) {
                        return true;
                    }
                    // Give the focused view a last chance to handle the dpad key.
@@ -7297,11 +7300,25 @@ public final class ViewRootImpl implements ViewParent,
                } else {
                    if (mView.restoreDefaultFocus()) {
                        return true;
                    } else if (moveFocusToAdjacentWindow(direction)) {
                        return true;
                    }
                }
            }
            return false;
        }
        private boolean moveFocusToAdjacentWindow(@FocusDirection int direction) {
            if (getConfiguration().windowConfiguration.getWindowingMode()
                    != WINDOWING_MODE_MULTI_WINDOW) {
                return false;
            }
            try {
                return mWindowSession.moveFocusToAdjacentWindow(mWindow, direction);
            } catch (RemoteException e) {
                return false;
            }
        }
        private boolean performKeyboardGroupNavigation(int direction) {
            final View focused = mView.findFocus();
+8 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import android.os.RemoteCallback;
import android.os.RemoteException;
import android.util.Log;
import android.util.MergedConfiguration;
import android.view.View.FocusDirection;
import android.view.WindowInsets.Type.InsetsType;
import android.window.ClientWindowFrames;
import android.window.OnBackInvokedCallbackInfo;
@@ -665,6 +666,13 @@ public class WindowlessWindowManager implements IWindowSession {
        return false;
    }

    @Override
    public boolean moveFocusToAdjacentWindow(IWindow fromWindow, @FocusDirection int direction) {
        Log.e(TAG, "Received request to moveFocusToAdjacentWindow on"
                + " WindowlessWindowManager. We shouldn't get here!");
        return false;
    }

    void setParentInterface(@Nullable ISurfaceControlViewHostParent parentInterface) {
        IBinder oldInterface = mParentInterface == null ? null : mParentInterface.asBinder();
        IBinder newInterface = parentInterface == null ? null : parentInterface.asBinder();
+12 −0
Original line number Diff line number Diff line
@@ -75,6 +75,7 @@ import android.view.InsetsState;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
import android.view.View;
import android.view.View.FocusDirection;
import android.view.WindowInsets;
import android.view.WindowInsets.Type.InsetsType;
import android.view.WindowManager;
@@ -1000,6 +1001,17 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
        }
        return didTransfer;
    }

    @Override
    public boolean moveFocusToAdjacentWindow(IWindow fromWindow, @FocusDirection int direction) {
        final long identity = Binder.clearCallingIdentity();
        try {
            return mService.moveFocusToAdjacentWindow(this, fromWindow, direction);
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    @Override
    public void generateDisplayHash(IWindow window, Rect boundsInWindow, String hashAlgorithm,
            RemoteCallback callback) {
+61 −0
Original line number Diff line number Diff line
@@ -287,6 +287,7 @@ import android.view.SurfaceControlViewHost;
import android.view.SurfaceSession;
import android.view.TaskTransitionSpec;
import android.view.View;
import android.view.View.FocusDirection;
import android.view.ViewDebug;
import android.view.WindowContentFrameStats;
import android.view.WindowInsets;
@@ -9104,6 +9105,66 @@ public class WindowManagerService extends IWindowManager.Stub
                win.mClient);
    }

    boolean moveFocusToAdjacentWindow(Session session, IWindow fromWindow,
            @FocusDirection int direction) {
        synchronized (mGlobalLock) {
            final WindowState fromWin = windowForClientLocked(session, fromWindow, false);
            if (fromWin == null || !fromWin.isFocused()) {
                return false;
            }
            final TaskFragment fromFragment = fromWin.getTaskFragment();
            if (fromFragment == null) {
                return false;
            }
            final TaskFragment adjacentFragment = fromFragment.getAdjacentTaskFragment();
            if (adjacentFragment == null || adjacentFragment.asTask() != null) {
                // Don't move the focus to another task.
                return false;
            }
            final Rect fromBounds = fromFragment.getBounds();
            final Rect adjacentBounds = adjacentFragment.getBounds();
            switch (direction) {
                case View.FOCUS_LEFT:
                    if (adjacentBounds.left >= fromBounds.left) {
                        return false;
                    }
                    break;
                case View.FOCUS_UP:
                    if (adjacentBounds.top >= fromBounds.top) {
                        return false;
                    }
                    break;
                case View.FOCUS_RIGHT:
                    if (adjacentBounds.right <= fromBounds.right) {
                        return false;
                    }
                    break;
                case View.FOCUS_DOWN:
                    if (adjacentBounds.bottom <= fromBounds.bottom) {
                        return false;
                    }
                    break;
                case View.FOCUS_BACKWARD:
                case View.FOCUS_FORWARD:
                    // These are not absolute directions. Skip checking the bounds.
                    break;
                default:
                    return false;
            }
            final ActivityRecord topRunningActivity = adjacentFragment.topRunningActivity(
                    true /* focusableOnly */);
            if (topRunningActivity == null) {
                return false;
            }
            moveDisplayToTopInternal(topRunningActivity.getDisplayId());
            handleTaskFocusChange(topRunningActivity.getTask(), topRunningActivity);
            if (fromWin.isFocused()) {
                return false;
            }
        }
        return true;
    }

    /** Return whether layer tracing is enabled */
    public boolean isLayerTracing() {
        if (!checkCallingPermission(
Loading