diff --git a/quickstep/src/com/android/quickstep/FocusState.kt b/quickstep/src/com/android/quickstep/FocusState.kt new file mode 100644 index 0000000000..ba3991fdff --- /dev/null +++ b/quickstep/src/com/android/quickstep/FocusState.kt @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2024 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.quickstep + +import android.os.RemoteException +import android.util.Log +import android.view.Display.DEFAULT_DISPLAY +import com.android.launcher3.util.Executors +import com.android.wm.shell.shared.IFocusTransitionListener.Stub +import com.android.wm.shell.shared.IShellTransitions + +/** Class to track focus state of displays and windows */ +class FocusState { + + var focusedDisplayId = DEFAULT_DISPLAY + private set + + private var listeners = mutableSetOf() + + fun addListener(l: FocusChangeListener) = listeners.add(l) + + fun removeListener(l: FocusChangeListener) = listeners.remove(l) + + fun init(transitions: IShellTransitions?) { + try { + transitions?.setFocusTransitionListener( + object : Stub() { + override fun onFocusedDisplayChanged(displayId: Int) { + Executors.MAIN_EXECUTOR.execute { + listeners.forEach { it.onFocusedDisplayChanged(displayId) } + } + } + } + ) + } catch (e: RemoteException) { + Log.w(TAG, "Failed call setFocusTransitionListener", e) + } + } + + interface FocusChangeListener { + fun onFocusedDisplayChanged(displayId: Int) + } + + override fun toString() = "{FocusState focusedDisplayId=$focusedDisplayId}" + + companion object { + private const val TAG = "FocusState" + } +} diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java index 34435d52c1..a55cf186ea 100644 --- a/quickstep/src/com/android/quickstep/SystemUiProxy.java +++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java @@ -161,6 +161,7 @@ public class SystemUiProxy implements ISystemUiProxy, NavHandle, SafeCloseable { private IRemoteAnimationRunner mBackToLauncherRunner; private IDragAndDrop mDragAndDrop; private final HomeVisibilityState mHomeVisibilityState = new HomeVisibilityState(); + private final FocusState mFocusState = new FocusState(); // Used to dedupe calls to SystemUI private int mLastShelfHeight; @@ -300,6 +301,7 @@ public class SystemUiProxy implements ISystemUiProxy, NavHandle, SafeCloseable { registerSplitScreenListener(mSplitScreenListener); registerSplitSelectListener(mSplitSelectListener); mHomeVisibilityState.init(mShellTransitions); + mFocusState.init(mShellTransitions); setStartingWindowListener(mStartingWindowListener); setLauncherUnlockAnimationController( mLauncherActivityClass, mLauncherUnlockAnimationController); @@ -1144,6 +1146,10 @@ public class SystemUiProxy implements ISystemUiProxy, NavHandle, SafeCloseable { return mHomeVisibilityState; } + public FocusState getFocusState() { + return mFocusState; + } + /** * Returns a surface which can be used to attach overlays to home task or null if * the task doesn't exist or sysui is not connected @@ -1592,6 +1598,7 @@ public class SystemUiProxy implements ISystemUiProxy, NavHandle, SafeCloseable { pw.println("\tmOneHanded=" + mOneHanded); pw.println("\tmShellTransitions=" + mShellTransitions); pw.println("\tmHomeVisibilityState=" + mHomeVisibilityState); + pw.println("\tmFocusState=" + mFocusState); pw.println("\tmStartingWindow=" + mStartingWindow); pw.println("\tmStartingWindowListener=" + mStartingWindowListener); pw.println("\tmSysuiUnlockAnimationController=" + mSysuiUnlockAnimationController);