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

Commit 51c5a1d0 authored by Tiger Huang's avatar Tiger Huang
Browse files

Make per-display focus optional (1/2)

In general cases, we don't have multiple input methods simultaneously.
So that it may not make sense to have multiple focused window in the
system. Especially when there are multiple blinking cursors of input
boxes on different displays, the user may not be able to know which
input box can receive key events. In these cases, we let the system
has only one focused window.

In some cases, there can be multiple input methods simultaneously (one
for each display). To enable multiple users to interact with the
corresponding displays at the same time, we should let the system have
per-display focused window in these cases.

This CL makes per-display focus optional, and also reverts ag/5312657

Fix: 120241480
Fix: 120790099
Test: atest ActivityManagerMultiDisplayTests \
            CtsWindowManagerDeviceTestCases \
            WmTests

Change-Id: Ie030eed523599b217060887171710692d050e5d8
parent 3c2a2034
Loading
Loading
Loading
Loading
+6 −29
Original line number Diff line number Diff line
@@ -71,33 +71,10 @@ oneway interface IWindow {
    void dispatchGetNewSurface();

    /**
     * Tell the window that it is either gaining or losing focus.
     *
     * @param hasFocus       {@code true} if window has focus, {@code false} otherwise.
     * @param inTouchMode    {@code true} if screen is in touch mode, {@code false} otherwise.
     * @param reportToClient {@code true} when need to report to child view with
     *                       {@link View#onWindowFocusChanged(boolean)}, {@code false} otherwise.
     * <p>
     * Note: In the previous design, there is only one window focus state tracked by
     * WindowManagerService.
     * For multi-display, the window focus state is tracked by each display independently.
     * <p>
     * It will introduce a problem if the window was already focused on one display and then
     * switched to another display, since the window focus state on each display is independent,
     * there is no global window focus state in WindowManagerService, so the window focus state of
     * the former display remains unchanged.
     * <p>
     * When switched back to former display, some flows that rely on the global window focus state
     * in view root will be missed due to the window focus state remaining unchanged.
     * (i.e: Showing single IME window when switching between displays.)
     * <p>
     * To solve the problem, WindowManagerService tracks the top focused display change and then
     * callbacks to the client via this method to make sure that the client side will request the
     * IME on the top focused display, and then set {@param reportToClient} as {@code false} to
     * ignore reporting to the application, since its focus remains unchanged on its display.
     *
     * Tell the window that it is either gaining or losing focus.  Keep it up
     * to date on the current state showing navigational focus (touch mode) too.
     */
    void windowFocusChanged(boolean hasFocus, boolean inTouchMode, boolean reportToClient);
    void windowFocusChanged(boolean hasFocus, boolean inTouchMode);

    void closeSystemDialogs(String reason);

+9 −24
Original line number Diff line number Diff line
@@ -2741,7 +2741,7 @@ public final class ViewRootImpl implements ViewParent,
        }
    }

    private void handleWindowFocusChanged(boolean reportToClient) {
    private void handleWindowFocusChanged() {
        final boolean hasWindowFocus;
        final boolean inTouchMode;
        synchronized (this) {
@@ -2776,9 +2776,8 @@ public final class ViewRootImpl implements ViewParent,
                        } catch (RemoteException ex) {
                        }
                        // Retry in a bit.
                        final Message msg = mHandler.obtainMessage(MSG_WINDOW_FOCUS_CHANGED);
                        msg.arg1 = reportToClient ? 1 : 0;
                        mHandler.sendMessageDelayed(msg, 500);
                        mHandler.sendMessageDelayed(mHandler.obtainMessage(
                                MSG_WINDOW_FOCUS_CHANGED), 500);
                        return;
                    }
                }
@@ -2795,15 +2794,8 @@ public final class ViewRootImpl implements ViewParent,
            }
            if (mView != null) {
                mAttachInfo.mKeyDispatchState.reset();
                // We dispatch onWindowFocusChanged to child view only when window is gaining /
                // losing focus.
                // If the focus is updated from top display change but window focus on the display
                // remains unchanged, will not callback onWindowFocusChanged again since it may
                // be redundant & can affect the state when it callbacks.
                if (reportToClient) {
                mView.dispatchWindowFocusChanged(hasWindowFocus);
                mAttachInfo.mTreeObserver.dispatchOnWindowFocusChange(hasWindowFocus);
                }
                if (mAttachInfo.mTooltipHost != null) {
                    mAttachInfo.mTooltipHost.hideTooltip();
                }
@@ -4404,7 +4396,7 @@ public final class ViewRootImpl implements ViewParent,
                    }
                    break;
                case MSG_WINDOW_FOCUS_CHANGED: {
                    handleWindowFocusChanged(msg.arg1 != 0 /* reportToClient */);
                    handleWindowFocusChanged();
                } break;
                case MSG_DIE:
                    doDie();
@@ -7348,7 +7340,7 @@ public final class ViewRootImpl implements ViewParent,
        }

        if (stage != null) {
            handleWindowFocusChanged(true /* reportToClient */);
            handleWindowFocusChanged();
            stage.deliver(q);
        } else {
            finishInputEvent(q);
@@ -7665,11 +7657,6 @@ public final class ViewRootImpl implements ViewParent,
    }

    public void windowFocusChanged(boolean hasFocus, boolean inTouchMode) {
        windowFocusChanged(hasFocus, inTouchMode, true /* reportToClient */);
    }

    public void windowFocusChanged(boolean hasFocus, boolean inTouchMode,
            boolean reportToClient) {
        synchronized (this) {
            mWindowFocusChanged = true;
            mUpcomingWindowFocus = hasFocus;
@@ -7677,7 +7664,6 @@ public final class ViewRootImpl implements ViewParent,
        }
        Message msg = Message.obtain();
        msg.what = MSG_WINDOW_FOCUS_CHANGED;
        msg.arg1 = reportToClient ? 1 : 0;
        mHandler.sendMessage(msg);
    }

@@ -8239,11 +8225,10 @@ public final class ViewRootImpl implements ViewParent,
        }

        @Override
        public void windowFocusChanged(boolean hasFocus, boolean inTouchMode,
                boolean reportToClient) {
        public void windowFocusChanged(boolean hasFocus, boolean inTouchMode) {
            final ViewRootImpl viewAncestor = mViewAncestor.get();
            if (viewAncestor != null) {
                viewAncestor.windowFocusChanged(hasFocus, inTouchMode, reportToClient);
                viewAncestor.windowFocusChanged(hasFocus, inTouchMode);
            }
        }

+2 −2
Original line number Diff line number Diff line
@@ -26,9 +26,9 @@ import android.view.DisplayCutout;
import android.view.DragEvent;
import android.view.IWindow;
import android.view.IWindowSession;
import android.view.PointerIcon;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
import android.view.PointerIcon;

import com.android.internal.os.IResultReceiver;

@@ -76,7 +76,7 @@ public class BaseIWindow extends IWindow.Stub {
    }

    @Override
    public void windowFocusChanged(boolean hasFocus, boolean touchEnabled, boolean reportToClient) {
    public void windowFocusChanged(boolean hasFocus, boolean touchEnabled) {
    }

    @Override
+4 −0
Original line number Diff line number Diff line
@@ -2014,6 +2014,10 @@
         This is intended to allow packaging drivers or tools for installation on a PC. -->
    <string translatable="false" name="config_isoImagePath"></string>

    <!-- Whether the system enables per-display focus. If the system has the input method for each
         display, this value should be true. -->
    <bool name="config_perDisplayFocusEnabled">false</bool>

    <!-- Whether a software navigation bar should be shown. NOTE: in the future this may be
         autodetected from the Configuration. -->
    <bool name="config_showNavigationBar">false</bool>
+1 −0
Original line number Diff line number Diff line
@@ -1668,6 +1668,7 @@
  <java-symbol type="bool" name="config_lockDayNightMode" />
  <java-symbol type="bool" name="config_lockUiMode" />
  <java-symbol type="bool" name="config_reverseDefaultRotation" />
  <java-symbol type="bool" name="config_perDisplayFocusEnabled" />
  <java-symbol type="bool" name="config_showNavigationBar" />
  <java-symbol type="bool" name="config_supportAutoRotation" />
  <java-symbol type="bool" name="target_honeycomb_needs_options_menu" />
Loading