Merge "Clear IMM#mCurRootView when needed" into udc-dev

This commit is contained in:
Adrian Roos
2023-04-26 08:25:15 +00:00
committed by Android (Google) Code Review
3 changed files with 67 additions and 7 deletions

View File

@@ -3783,6 +3783,7 @@ package android.view.inputmethod {
method @NonNull @RequiresPermission(value=android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, conditional=true) public java.util.List<android.view.inputmethod.InputMethodInfo> getInputMethodListAsUser(int); method @NonNull @RequiresPermission(value=android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, conditional=true) public java.util.List<android.view.inputmethod.InputMethodInfo> getInputMethodListAsUser(int);
method public boolean hasActiveInputConnection(@Nullable android.view.View); method public boolean hasActiveInputConnection(@Nullable android.view.View);
method @RequiresPermission(android.Manifest.permission.TEST_INPUT_METHOD) public boolean hasPendingImeVisibilityRequests(); method @RequiresPermission(android.Manifest.permission.TEST_INPUT_METHOD) public boolean hasPendingImeVisibilityRequests();
method @RequiresPermission(android.Manifest.permission.TEST_INPUT_METHOD) public boolean isCurrentRootView(@NonNull android.view.View);
method @RequiresPermission(android.Manifest.permission.TEST_INPUT_METHOD) public boolean isInputMethodPickerShown(); method @RequiresPermission(android.Manifest.permission.TEST_INPUT_METHOD) public boolean isInputMethodPickerShown();
method @RequiresPermission(android.Manifest.permission.TEST_INPUT_METHOD) public void setStylusWindowIdleTimeoutForTest(long); method @RequiresPermission(android.Manifest.permission.TEST_INPUT_METHOD) public void setStylusWindowIdleTimeoutForTest(long);
field public static final long CLEAR_SHOW_FORCED_FLAG_WHEN_LEAVING = 214016041L; // 0xcc1a029L field public static final long CLEAR_SHOW_FORCED_FLAG_WHEN_LEAVING = 214016041L; // 0xcc1a029L

View File

@@ -86,10 +86,13 @@ public final class ImeFocusController {
void onPreWindowFocus(boolean hasWindowFocus, WindowManager.LayoutParams windowAttribute) { void onPreWindowFocus(boolean hasWindowFocus, WindowManager.LayoutParams windowAttribute) {
mHasImeFocus = WindowManager.LayoutParams.mayUseInputMethod(windowAttribute.flags); mHasImeFocus = WindowManager.LayoutParams.mayUseInputMethod(windowAttribute.flags);
if (!hasWindowFocus || !mHasImeFocus || isInLocalFocusMode(windowAttribute)) { if (!hasWindowFocus || !mHasImeFocus || isInLocalFocusMode(windowAttribute)) {
return; if (!hasWindowFocus) {
getImmDelegate().onWindowLostFocus(mViewRootImpl);
} }
} else {
getImmDelegate().onPreWindowGainedFocus(mViewRootImpl); getImmDelegate().onPreWindowGainedFocus(mViewRootImpl);
} }
}
@UiThread @UiThread
void onPostWindowFocus(View focusedView, boolean hasWindowFocus, void onPostWindowFocus(View focusedView, boolean hasWindowFocus,
@@ -163,6 +166,7 @@ public final class ImeFocusController {
void onPreWindowGainedFocus(ViewRootImpl viewRootImpl); void onPreWindowGainedFocus(ViewRootImpl viewRootImpl);
void onPostWindowGainedFocus(View viewForWindowFocus, void onPostWindowGainedFocus(View viewForWindowFocus,
@NonNull WindowManager.LayoutParams windowAttribute); @NonNull WindowManager.LayoutParams windowAttribute);
void onWindowLostFocus(@NonNull ViewRootImpl viewRootImpl);
void onViewFocusChanged(@NonNull View view, boolean hasFocus); void onViewFocusChanged(@NonNull View view, boolean hasFocus);
void onScheduledCheckFocus(@NonNull ViewRootImpl viewRootImpl); void onScheduledCheckFocus(@NonNull ViewRootImpl viewRootImpl);
void onViewDetachedFromWindow(View view, ViewRootImpl viewRootImpl); void onViewDetachedFromWindow(View view, ViewRootImpl viewRootImpl);

View File

@@ -482,12 +482,20 @@ public final class InputMethodManager {
private View mNextServedView; private View mNextServedView;
/** /**
* This is the root view of the overall window that currently has input * The latest {@link ViewRootImpl} that has, or most recently had, input method focus.
* method focus. *
* <p>This value will be cleared when it becomes inactive and no longer has window focus.
*/ */
@Nullable
@GuardedBy("mH") @GuardedBy("mH")
ViewRootImpl mCurRootView; ViewRootImpl mCurRootView;
/**
* Whether the {@link #mCurRootView} currently has window focus.
*/
@GuardedBy("mH")
boolean mCurRootViewWindowFocused;
/** /**
* This is set when we are in the process of connecting, to determine * This is set when we are in the process of connecting, to determine
* when we have actually finished. * when we have actually finished.
@@ -745,6 +753,7 @@ public final class InputMethodManager {
public void onPreWindowGainedFocus(ViewRootImpl viewRootImpl) { public void onPreWindowGainedFocus(ViewRootImpl viewRootImpl) {
synchronized (mH) { synchronized (mH) {
setCurrentRootViewLocked(viewRootImpl); setCurrentRootViewLocked(viewRootImpl);
mCurRootViewWindowFocused = true;
} }
} }
@@ -821,6 +830,17 @@ public final class InputMethodManager {
} }
} }
@Override
public void onWindowLostFocus(@NonNull ViewRootImpl viewRootImpl) {
synchronized (mH) {
if (mCurRootView == viewRootImpl) {
mCurRootViewWindowFocused = false;
clearCurRootViewIfNeeded();
}
}
}
@Override @Override
public void onViewFocusChanged(@Nullable View view, boolean hasFocus) { public void onViewFocusChanged(@Nullable View view, boolean hasFocus) {
onViewFocusChangedInternal(view, hasFocus); onViewFocusChangedInternal(view, hasFocus);
@@ -1114,6 +1134,10 @@ public final class InputMethodManager {
// Note that finishComposingText() is allowed to run // Note that finishComposingText() is allowed to run
// even when we are not active. // even when we are not active.
mFallbackInputConnection.finishComposingTextFromImm(); mFallbackInputConnection.finishComposingTextFromImm();
if (clearCurRootViewIfNeeded()) {
return;
}
} }
// Check focus again in case that "onWindowFocus" is called before // Check focus again in case that "onWindowFocus" is called before
// handling this message. // handling this message.
@@ -1756,8 +1780,7 @@ public final class InputMethodManager {
} }
/** /**
* Return true if the given view is the currently active view for the * Return {@code true} if the given view is the currently active view for the input method.
* input method.
*/ */
public boolean isActive(View view) { public boolean isActive(View view) {
// Re-dispatch if there is a context mismatch. // Re-dispatch if there is a context mismatch.
@@ -1773,7 +1796,7 @@ public final class InputMethodManager {
} }
/** /**
* Return true if any view is currently active in the input method. * Return {@code true} if any view is currently active for the input method.
*/ */
public boolean isActive() { public boolean isActive() {
checkFocus(); checkFocus();
@@ -1782,6 +1805,20 @@ public final class InputMethodManager {
} }
} }
/**
* Returns {@code true} if the given view's {@link ViewRootImpl} is the currently active one
* for the {@code InputMethodManager}.
*
* @hide
*/
@TestApi
@RequiresPermission(Manifest.permission.TEST_INPUT_METHOD)
public boolean isCurrentRootView(@NonNull View attachedView) {
synchronized (mH) {
return mCurRootView == attachedView.getViewRootImpl();
}
}
/** /**
* Return {@code true} if the currently served view is accepting full text edits. * Return {@code true} if the currently served view is accepting full text edits.
* If {@code false}, it has no input connection, so it can only handle raw key events. * If {@code false}, it has no input connection, so it can only handle raw key events.
@@ -1908,6 +1945,24 @@ public final class InputMethodManager {
mImeDispatcher.clear(); mImeDispatcher.clear();
} }
/**
* Clears the {@link #mCurRootView} if it's no longer window focused and the connection is
* no longer active.
*
* @return {@code} true iff it was cleared.
*/
@GuardedBy("mH")
private boolean clearCurRootViewIfNeeded() {
if (!mActive && !mCurRootViewWindowFocused) {
finishInputLocked();
mDelegate.setCurrentRootViewLocked(null);
return true;
}
return false;
}
public void displayCompletions(View view, CompletionInfo[] completions) { public void displayCompletions(View view, CompletionInfo[] completions) {
// Re-dispatch if there is a context mismatch. // Re-dispatch if there is a context mismatch.
final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view); final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);