Chromium Code Reviews| Index: content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java |
| diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java |
| index 3493dfef590fc0fe5740ccf545029b8efa968368..20869a81bb8731eec438eec1227f0c18f1fda800 100644 |
| --- a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java |
| +++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java |
| @@ -360,6 +360,11 @@ public class ContentViewCore |
| // ResultReceiver in the InputMethodService (IME app) gets gc'ed. |
| private ShowKeyboardResultReceiver mShowKeyboardResultReceiver; |
| + // Whether this ContentViewCore has view focus. |
| + private boolean mHasViewFocus; |
| + // Whether this ContentViewCore has window focus. |
| + private boolean mHasWindowFocus; |
| + |
| // The list of observers that are notified when ContentViewCore changes its WindowAndroid. |
| private final ObserverList<WindowAndroidChangedObserver> mWindowAndroidChangedObservers; |
| @@ -552,7 +557,7 @@ public class ContentViewCore |
| InternalAccessDelegate internalDispatcher, WebContents webContents, |
| WindowAndroid windowAndroid) { |
| mViewAndroidDelegate = viewDelegate; |
| - setContainerView(viewDelegate.getContainerView()); |
| + setContainerView(viewDelegate.getContainerView(), false); |
|
aelias_OOO_until_Jul13
2017/04/03 21:57:56
Could you try just moving this to the end of the c
mthiesse
2017/04/05 14:11:23
Done.
|
| long windowNativePointer = windowAndroid.getNativePointer(); |
| assert windowNativePointer != 0; |
| @@ -580,6 +585,9 @@ public class ContentViewCore |
| mShouldRequestUnbufferedDispatch = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP |
| && ContentFeatureList.isEnabled(ContentFeatureList.REQUEST_UNBUFFERED_DISPATCH); |
| + |
| + onFocusChangedInternal(getRealWindowFocusedState(), mContainerView.hasFocus(), |
| + false /* hideKeyboardOnBlur */); |
| } |
| /** |
| @@ -639,12 +647,12 @@ public class ContentViewCore |
| } |
| /** |
| - * Sets a new container view for this {@link ContentViewCore}. |
| + * Replaces the container view for this {@link ContentViewCore}. This ContentViewCore must |
| + * already have been initialized. |
| * |
| - * <p>WARNING: This method can also be used to replace the existing container view, |
| - * but you should only do it if you have a very good reason to. Replacing the |
| - * container view has been designed to support fullscreen in the Webview so it |
| - * might not be appropriate for other use cases. |
| + * <p>WARNING: You should only use this method if you have a very good reason to. Replacing the |
| + * container view has been designed to support fullscreen in the Webview so it might not be |
| + * appropriate for other use cases. |
| * |
| * <p>This method only performs a small part of replacing the container view and |
| * embedders are responsible for: |
| @@ -656,7 +664,15 @@ public class ContentViewCore |
| * <li>etc.</li> |
| * </ul> |
| */ |
| - public void setContainerView(ViewGroup containerView) { |
| + public void replaceContainerView(ViewGroup containerView) { |
| + assert mContainerView != null; |
| + setContainerView(containerView, true); |
| + } |
| + |
| + /** |
| + * Sets the container view for this {@link ContentViewCore}. |
| + */ |
| + private void setContainerView(ViewGroup containerView, boolean initialized) { |
| try { |
| TraceEvent.begin("ContentViewCore.setContainerView"); |
| if (mContainerView != null) { |
| @@ -675,11 +691,28 @@ public class ContentViewCore |
| if (mJoystickZoomProvider != null) { |
| mJoystickZoomProvider.setContainerView(containerView); |
| } |
| + if (initialized) { |
| + onFocusChangedInternal(getRealWindowFocusedState(), mContainerView.hasFocus(), |
| + false /* hideKeyboardOnBlur */); |
| + } |
| } finally { |
| TraceEvent.end("ContentViewCore.setContainerView"); |
| } |
| } |
| + /** |
| + * Note: We don't use View#hasWindowFocus() because it returns incorrect values when the View |
| + * doesn't have View focus. |
| + * @return Whether the containerView actually has Window focus. |
| + */ |
| + private boolean getRealWindowFocusedState() { |
| + int[] states = mContainerView.getDrawableState(); |
| + for (int state : states) { |
| + if ((state & android.R.attr.state_window_focused) != 0) return true; |
| + } |
| + return false; |
| + } |
| + |
| @CalledByNative |
| private void onNativeContentViewCoreDestroyed(long nativeContentViewCore) { |
| assert nativeContentViewCore == mNativeContentViewCore; |
| @@ -1327,24 +1360,44 @@ public class ContentViewCore |
| /** |
| * @see View#onWindowFocusChanged(boolean) |
| + * |
| + * This function must only be called after this ContentViewCore has been initialized. |
| */ |
| public void onWindowFocusChanged(boolean hasWindowFocus) { |
| + if (mHasWindowFocus == hasWindowFocus) return; |
| mImeAdapter.onWindowFocusChanged(hasWindowFocus); |
| if (!hasWindowFocus) resetGestureDetection(); |
| mSelectionPopupController.onWindowFocusChanged(hasWindowFocus); |
| for (mGestureStateListenersIterator.rewind(); mGestureStateListenersIterator.hasNext();) { |
| mGestureStateListenersIterator.next().onWindowFocusChanged(hasWindowFocus); |
| } |
| + onFocusChangedInternal(hasWindowFocus, mHasViewFocus, true /* hideKeyboardOnBlur */); |
| + } |
| + |
| + /** |
| + * Called when the View focus for this ContentViewCore changes. |
| + * |
| + * This function must only be called after this ContentViewCore has been initialized. |
| + */ |
| + public void onFocusChanged(boolean hasViewFocus, boolean hideKeyboardOnBlur) { |
| + if (mHasViewFocus == hasViewFocus) return; |
| + mImeAdapter.onViewFocusChanged(hasViewFocus, hideKeyboardOnBlur); |
| + onFocusChangedInternal(mHasWindowFocus, hasViewFocus, hideKeyboardOnBlur); |
| } |
| - public void onFocusChanged(boolean gainFocus, boolean hideKeyboardOnBlur) { |
| - mImeAdapter.onViewFocusChanged(gainFocus, hideKeyboardOnBlur); |
| + private void onFocusChangedInternal( |
| + boolean hasWindowFocus, boolean hasViewFocus, boolean hideKeyboardOnBlur) { |
| + boolean hadInputFocus = mHasWindowFocus && mHasViewFocus; |
| + boolean hasInputFocus = hasWindowFocus && hasViewFocus; |
| + mHasWindowFocus = hasWindowFocus; |
| + mHasViewFocus = hasViewFocus; |
| + if (hasInputFocus == hadInputFocus) return; |
| if (mJoystickScrollProvider != null) { |
| - mJoystickScrollProvider.setEnabled(gainFocus && !isFocusedNodeEditable()); |
| + mJoystickScrollProvider.setEnabled(hasInputFocus && !isFocusedNodeEditable()); |
| } |
| - if (gainFocus) { |
| + if (hasInputFocus) { |
| restoreSelectionPopupsIfNecessary(); |
| } else { |
| cancelRequestToScrollFocusedEditableNodeIntoView(); |
| @@ -1359,7 +1412,7 @@ public class ContentViewCore |
| clearSelection(); |
| } |
| } |
| - if (mNativeContentViewCore != 0) nativeSetFocus(mNativeContentViewCore, gainFocus); |
| + if (mNativeContentViewCore != 0) nativeSetFocus(mNativeContentViewCore, hasInputFocus); |
| } |
| /** |