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 4f54ff25e4455c47fa5d73073115f644e5a12b0f..6766dca7757baeadf386d2a3945f00f0447faaf0 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 |
| @@ -112,8 +112,7 @@ public class ContentViewCore implements AccessibilityStateChangeListener, Displa |
| // and remove from it in removeJavaScriptInterface(). The annotation class is stored for |
| // the purpose of migrating injected objects from one instance of CVC to another, which |
| // is used by Android WebView to support WebChromeClient.onCreateWindow scenario. |
| - private final Map<String, Pair<Object, Class>> mJavaScriptInterfaces = |
| - new HashMap<String, Pair<Object, Class>>(); |
| + private final Map<String, Pair<Object, Class>> mJavaScriptInterfaces = new HashMap<>(); |
|
aelias_OOO_until_Jul13
2017/03/30 02:06:55
I assume you made these changes because of a presu
mthiesse
2017/03/30 14:51:51
My editor automatically makes these changes, and I
|
| // Additionally, we keep track of all Java bound JS objects that are in use on the |
| // current page to ensure that they are not garbage collected until the page is |
| @@ -121,7 +120,7 @@ public class ContentViewCore implements AccessibilityStateChangeListener, Displa |
| // via the removeJavaScriptInterface API and transient objects returned from methods |
| // on the interface object. Note we use HashSet rather than Set as the native side |
| // expects HashSet (no bindings for interfaces). |
| - private final HashSet<Object> mRetainedJavaScriptObjects = new HashSet<Object>(); |
| + private final HashSet<Object> mRetainedJavaScriptObjects = new HashSet<>(); |
| /** |
| * A {@link WebContentsObserver} that listens to frame navigation events. |
| @@ -132,7 +131,7 @@ public class ContentViewCore implements AccessibilityStateChangeListener, Displa |
| ContentViewWebContentsObserver(ContentViewCore contentViewCore) { |
| super(contentViewCore.getWebContents()); |
| - mWeakContentViewCore = new WeakReference<ContentViewCore>(contentViewCore); |
| + mWeakContentViewCore = new WeakReference<>(contentViewCore); |
| } |
| @Override |
| @@ -371,6 +370,11 @@ public class ContentViewCore implements AccessibilityStateChangeListener, Displa |
| // 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; |
| @@ -396,10 +400,10 @@ public class ContentViewCore implements AccessibilityStateChangeListener, Displa |
| mAccessibilityManager = (AccessibilityManager) |
| getContext().getSystemService(Context.ACCESSIBILITY_SERVICE); |
| mSystemCaptioningBridge = CaptioningBridgeFactory.getSystemCaptioningBridge(mContext); |
| - mGestureStateListeners = new ObserverList<GestureStateListener>(); |
| + mGestureStateListeners = new ObserverList<>(); |
| mGestureStateListenersIterator = mGestureStateListeners.rewindableIterator(); |
| - mWindowAndroidChangedObservers = new ObserverList<WindowAndroidChangedObserver>(); |
| + mWindowAndroidChangedObservers = new ObserverList<>(); |
| } |
| /** |
| @@ -676,6 +680,8 @@ public class ContentViewCore implements AccessibilityStateChangeListener, Displa |
| } |
| mContainerView = containerView; |
| + onFocusChangedInternal(getRealWindowFocusedState(), containerView.hasFocus(), |
| + false /* hideKeyboardOnBlur */); |
| mContainerView.setClickable(true); |
| if (mSelectionPopupController != null) { |
| mSelectionPopupController.setContainerView(containerView); |
| @@ -685,6 +691,20 @@ public class ContentViewCore implements AccessibilityStateChangeListener, Displa |
| } |
| } |
| + /** |
| + * 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() { |
| + boolean hasWindowFocus = false; |
| + int[] states = mContainerView.getDrawableState(); |
| + for (int state : states) { |
| + if ((state & android.R.attr.state_window_focused) != 0) hasWindowFocus = true; |
| + } |
| + return hasWindowFocus; |
| + } |
| + |
| @CalledByNative |
| private void onNativeContentViewCoreDestroyed(long nativeContentViewCore) { |
| assert nativeContentViewCore == mNativeContentViewCore; |
| @@ -1334,23 +1354,37 @@ public class ContentViewCore implements AccessibilityStateChangeListener, Displa |
| * @see View#onWindowFocusChanged(boolean) |
| */ |
| 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 */); |
| } |
| public void onFocusChanged(boolean gainFocus, boolean hideKeyboardOnBlur) { |
|
aelias_OOO_until_Jul13
2017/03/30 02:06:55
Please rename "gainFocus" to "hasViewFocus"
mthiesse
2017/03/30 14:51:51
Done.
|
| - mImeAdapter.onViewFocusChanged(gainFocus, hideKeyboardOnBlur); |
| + if (mHasViewFocus == gainFocus) return; |
| + onFocusChangedInternal(mHasWindowFocus, gainFocus, hideKeyboardOnBlur); |
| + } |
| + |
| + @VisibleForTesting |
| + public void onFocusChangedInternal( |
| + boolean hasWindowFocus, boolean hasViewFocus, boolean hideKeyboardOnBlur) { |
| + boolean hadInputFocus = mHasWindowFocus && mHasViewFocus; |
| + boolean hasInputFocus = hasWindowFocus && hasViewFocus; |
| + mHasWindowFocus = hasWindowFocus; |
| + mHasViewFocus = hasViewFocus; |
| + if (hasInputFocus == hadInputFocus) return; |
|
aelias_OOO_until_Jul13
2017/03/30 02:06:55
This early-return seems to do nothing given the ot
mthiesse
2017/03/30 14:51:51
It doesn't do nothing - it stops us from doing wor
|
| + mImeAdapter.onViewFocusChanged(hasInputFocus, hideKeyboardOnBlur); |
| // Used in test that bypasses initialize(). |
| if (mJoystickScrollProvider != null) { |
| - mJoystickScrollProvider.setEnabled(gainFocus && !isFocusedNodeEditable()); |
| + mJoystickScrollProvider.setEnabled(hasInputFocus && !isFocusedNodeEditable()); |
| } |
| - if (gainFocus) { |
| + if (hasInputFocus) { |
| restoreSelectionPopupsIfNecessary(); |
| } else { |
| cancelRequestToScrollFocusedEditableNodeIntoView(); |
| @@ -1365,7 +1399,7 @@ public class ContentViewCore implements AccessibilityStateChangeListener, Displa |
| clearSelection(); |
| } |
| } |
| - if (mNativeContentViewCore != 0) nativeSetFocus(mNativeContentViewCore, gainFocus); |
| + if (mNativeContentViewCore != 0) nativeSetFocus(mNativeContentViewCore, hasInputFocus); |
| } |
| /** |
| @@ -1822,7 +1856,7 @@ public class ContentViewCore implements AccessibilityStateChangeListener, Displa |
| assert mNativeSelectPopupSourceFrame == 0 : "Zombie popup did not clear the frame source"; |
| assert items.length == enabled.length; |
| - List<SelectPopupItem> popupItems = new ArrayList<SelectPopupItem>(); |
| + List<SelectPopupItem> popupItems = new ArrayList<>(); |
| for (int i = 0; i < items.length; i++) { |
| popupItems.add(new SelectPopupItem(items[i], enabled[i])); |
| } |