| 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 6cae0306e6b02cee2884e9b011fe82d609bb6d30..a96b77de2873c5f90dc7099bd7d9387aeeb20632 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
|
| @@ -17,8 +17,6 @@ import android.graphics.Bitmap;
|
| import android.graphics.Rect;
|
| import android.os.Build;
|
| import android.os.Bundle;
|
| -import android.os.Handler;
|
| -import android.os.ResultReceiver;
|
| import android.os.SystemClock;
|
| import android.util.Pair;
|
| import android.view.ActionMode;
|
| @@ -37,7 +35,6 @@ import android.view.accessibility.AccessibilityManager.AccessibilityStateChangeL
|
| import android.view.accessibility.AccessibilityNodeProvider;
|
| import android.view.inputmethod.EditorInfo;
|
| import android.view.inputmethod.InputConnection;
|
| -import android.view.inputmethod.InputMethodManager;
|
|
|
| import org.chromium.base.ObserverList;
|
| import org.chromium.base.ObserverList.RewindableIterator;
|
| @@ -61,6 +58,7 @@ import org.chromium.content_public.browser.AccessibilitySnapshotCallback;
|
| import org.chromium.content_public.browser.AccessibilitySnapshotNode;
|
| import org.chromium.content_public.browser.ActionModeCallbackHelper;
|
| import org.chromium.content_public.browser.GestureStateListener;
|
| +import org.chromium.content_public.browser.ImeEventObserver;
|
| import org.chromium.content_public.browser.WebContents;
|
| import org.chromium.content_public.browser.WebContentsObserver;
|
| import org.chromium.device.gamepad.GamepadList;
|
| @@ -68,7 +66,6 @@ import org.chromium.ui.base.DeviceFormFactor;
|
| import org.chromium.ui.base.EventForwarder;
|
| import org.chromium.ui.base.ViewAndroidDelegate;
|
| import org.chromium.ui.base.WindowAndroid;
|
| -import org.chromium.ui.base.ime.TextInputType;
|
| import org.chromium.ui.display.DisplayAndroid;
|
| import org.chromium.ui.display.DisplayAndroid.DisplayAndroidObserver;
|
|
|
| @@ -92,7 +89,7 @@ import java.util.Map;
|
| public class ContentViewCore
|
| implements AccessibilityStateChangeListener, DisplayAndroidObserver,
|
| SystemCaptioningBridge.SystemCaptioningBridgeListener, WindowAndroidProvider,
|
| - JoystickZoomProvider.PinchZoomHandler {
|
| + JoystickZoomProvider.PinchZoomHandler, ImeEventObserver {
|
| private static final String TAG = "cr_ContentViewCore";
|
|
|
| // Used to avoid enabling zooming in / out if resulting zooming will
|
| @@ -174,32 +171,6 @@ public class ContentViewCore
|
| }
|
|
|
| /**
|
| - * {@ResultReceiver} passed in InputMethodManager#showSoftInput}. We need this to scroll to the
|
| - * editable node at the right timing, which is after input method window shows up.
|
| - */
|
| - // TODO(crbug.com/635567): Fix this properly.
|
| - @SuppressLint("ParcelCreator")
|
| - private static class ShowKeyboardResultReceiver extends ResultReceiver {
|
| -
|
| - // Unfortunately, the memory life cycle of ResultReceiver object, once passed in
|
| - // showSoftInput(), is in the control of Android's input method framework and IME app,
|
| - // so we use a weakref to avoid tying CVC's lifetime to that of ResultReceiver object.
|
| - private final WeakReference<ContentViewCore> mContentViewCore;
|
| -
|
| - public ShowKeyboardResultReceiver(ContentViewCore contentViewCore, Handler handler) {
|
| - super(handler);
|
| - mContentViewCore = new WeakReference<>(contentViewCore);
|
| - }
|
| -
|
| - @Override
|
| - public void onReceiveResult(int resultCode, Bundle resultData) {
|
| - ContentViewCore contentViewCore = mContentViewCore.get();
|
| - if (contentViewCore == null) return;
|
| - contentViewCore.onShowKeyboardReceiveResult(resultCode);
|
| - }
|
| - }
|
| -
|
| - /**
|
| * Interface that consumers of {@link ContentViewCore} must implement to allow the proper
|
| * dispatching of view methods through the containing view.
|
| *
|
| @@ -322,10 +293,6 @@ public class ContentViewCore
|
| // WebView.
|
| private boolean mShouldSetAccessibilityFocusOnPageLoad;
|
|
|
| - // Temporary notification to tell onSizeChanged to focus a form element,
|
| - // because the OSK was just brought up.
|
| - private final Rect mFocusPreOSKViewportRect = new Rect();
|
| -
|
| // Whether a touch scroll sequence is active, used to hide text selection
|
| // handles. Note that a scroll sequence will *always* bound a pinch
|
| // sequence, so this will also be true for the duration of a pinch gesture.
|
| @@ -356,10 +323,6 @@ public class ContentViewCore
|
| // A ViewAndroidDelegate that delegates to the current container view.
|
| private ViewAndroidDelegate mViewAndroidDelegate;
|
|
|
| - // NOTE: This object will not be released by Android framework until the matching
|
| - // ResultReceiver in the InputMethodService (IME app) gets gc'ed.
|
| - private ShowKeyboardResultReceiver mShowKeyboardResultReceiver;
|
| -
|
| private Boolean mHasViewFocus;
|
|
|
| // The list of observers that are notified when ContentViewCore changes its WindowAndroid.
|
| @@ -474,6 +437,10 @@ public class ContentViewCore
|
| if (mNativeContentViewCore != 0) nativeWasResized(mNativeContentViewCore);
|
| }
|
|
|
| + public void addImeEventObserver(ImeEventObserver imeEventObserver) {
|
| + mImeAdapter.addEventObserver(imeEventObserver);
|
| + }
|
| +
|
| @VisibleForTesting
|
| public void setImeAdapterForTest(ImeAdapter imeAdapter) {
|
| mImeAdapter = imeAdapter;
|
| @@ -484,55 +451,6 @@ public class ContentViewCore
|
| return mImeAdapter;
|
| }
|
|
|
| - private ImeAdapter createImeAdapter() {
|
| - return new ImeAdapter(mWebContents, new InputMethodManagerWrapper(mContext),
|
| - new ImeAdapter.ImeAdapterDelegate() {
|
| - @Override
|
| - public void onImeEvent() {
|
| - mPopupZoomer.hide(true);
|
| - getContentViewClient().onImeEvent();
|
| - if (isFocusedNodeEditable()) mWebContents.dismissTextHandles();
|
| - }
|
| -
|
| - @Override
|
| - public void onKeyboardBoundsUnchanged() {
|
| - assert mWebContents != null;
|
| - mWebContents.scrollFocusedEditableNodeIntoView();
|
| - }
|
| -
|
| - @Override
|
| - public boolean performContextMenuAction(int id) {
|
| - assert mWebContents != null;
|
| - switch (id) {
|
| - case android.R.id.selectAll:
|
| - mWebContents.selectAll();
|
| - return true;
|
| - case android.R.id.cut:
|
| - mWebContents.cut();
|
| - return true;
|
| - case android.R.id.copy:
|
| - mWebContents.copy();
|
| - return true;
|
| - case android.R.id.paste:
|
| - mWebContents.paste();
|
| - return true;
|
| - default:
|
| - return false;
|
| - }
|
| - }
|
| -
|
| - @Override
|
| - public View getAttachedView() {
|
| - return mContainerView;
|
| - }
|
| -
|
| - @Override
|
| - public ResultReceiver getNewShowKeyboardReceiver() {
|
| - return ContentViewCore.this.getNewShowKeyboardReceiver();
|
| - }
|
| - });
|
| - }
|
| -
|
| /**
|
| *
|
| * @param viewDelegate Delegate to add/remove anchor views.
|
| @@ -570,12 +488,14 @@ public class ContentViewCore
|
| setContainerViewInternals(internalDispatcher);
|
|
|
| initPopupZoomer(mContext);
|
| - mImeAdapter = createImeAdapter();
|
| + mImeAdapter = new ImeAdapter(
|
| + mWebContents, mContainerView, new InputMethodManagerWrapper(mContext));
|
| + mImeAdapter.addEventObserver(this);
|
|
|
| - mSelectionPopupController = new SelectionPopupController(mContext, windowAndroid,
|
| - webContents, viewDelegate.getContainerView(), mRenderCoordinates);
|
| + mSelectionPopupController = new SelectionPopupController(
|
| + mContext, windowAndroid, webContents, mContainerView, mRenderCoordinates);
|
| mSelectionPopupController.setCallback(ActionModeCallbackHelper.EMPTY_CALLBACK);
|
| - mSelectionPopupController.setContainerView(getContainerView());
|
| + mSelectionPopupController.setContainerView(mContainerView);
|
|
|
| mWebContentsObserver = new ContentViewWebContentsObserver(this);
|
|
|
| @@ -663,6 +583,7 @@ public class ContentViewCore
|
| if (mContainerView != null) {
|
| hideSelectPopupWithCancelMessage();
|
| mPopupZoomer.hide(false);
|
| + mImeAdapter.setContainerView(containerView);
|
| }
|
|
|
| mContainerView = containerView;
|
| @@ -1295,12 +1216,13 @@ public class ContentViewCore
|
|
|
| // Execute a delayed form focus operation because the OSK was brought
|
| // up earlier.
|
| - if (!mFocusPreOSKViewportRect.isEmpty()) {
|
| + Rect focusPreOSKViewportRect = mImeAdapter.getFocusPreOSKViewportRect();
|
| + if (!focusPreOSKViewportRect.isEmpty()) {
|
| Rect rect = new Rect();
|
| getContainerView().getWindowVisibleDisplayFrame(rect);
|
| - if (!rect.equals(mFocusPreOSKViewportRect)) {
|
| + if (!rect.equals(focusPreOSKViewportRect)) {
|
| // Only assume the OSK triggered the onSizeChanged if width was preserved.
|
| - if (rect.width() == mFocusPreOSKViewportRect.width()) {
|
| + if (rect.width() == focusPreOSKViewportRect.width()) {
|
| assert mWebContents != null;
|
| mWebContents.scrollFocusedEditableNodeIntoView();
|
| }
|
| @@ -1312,7 +1234,7 @@ public class ContentViewCore
|
| private void cancelRequestToScrollFocusedEditableNodeIntoView() {
|
| // Zero-ing the rect will prevent |updateAfterSizeChanged()| from
|
| // issuing the delayed form focus event.
|
| - mFocusPreOSKViewportRect.setEmpty();
|
| + mImeAdapter.getFocusPreOSKViewportRect().setEmpty();
|
| }
|
|
|
| /**
|
| @@ -1791,31 +1713,17 @@ public class ContentViewCore
|
| TraceEvent.end("ContentViewCore:updateFrameInfo");
|
| }
|
|
|
| - @CalledByNative
|
| - private void updateImeAdapter(int textInputType, int textInputFlags, int textInputMode,
|
| - String text, int selectionStart, int selectionEnd, int compositionStart,
|
| - int compositionEnd, boolean showImeIfNeeded, boolean replyToRequest) {
|
| - try {
|
| - TraceEvent.begin("ContentViewCore.updateImeAdapter");
|
| - boolean focusedNodeEditable = (textInputType != TextInputType.NONE);
|
| - boolean focusedNodeIsPassword = (textInputType == TextInputType.PASSWORD);
|
| -
|
| - mImeAdapter.updateState(textInputType, textInputFlags, textInputMode, showImeIfNeeded,
|
| - text, selectionStart, selectionEnd, compositionStart, compositionEnd,
|
| - replyToRequest);
|
| -
|
| - boolean editableToggled = (focusedNodeEditable != isFocusedNodeEditable());
|
| - mSelectionPopupController.updateSelectionState(focusedNodeEditable,
|
| - focusedNodeIsPassword);
|
| - if (editableToggled) {
|
| - if (mJoystickScrollProvider != null) {
|
| - mJoystickScrollProvider.setEnabled(!focusedNodeEditable);
|
| - }
|
| - getContentViewClient().onFocusedNodeEditabilityChanged(focusedNodeEditable);
|
| - }
|
| - } finally {
|
| - TraceEvent.end("ContentViewCore.updateImeAdapter");
|
| - }
|
| + // ImeEventObserver
|
| +
|
| + @Override
|
| + public void onImeEvent() {
|
| + mPopupZoomer.hide(true);
|
| + }
|
| +
|
| + @Override
|
| + public void onNodeAttributeUpdated(boolean editable, boolean password) {
|
| + if (mJoystickScrollProvider != null) mJoystickScrollProvider.setEnabled(!editable);
|
| + mSelectionPopupController.updateSelectionState(editable, password);
|
| }
|
|
|
| /**
|
| @@ -1937,10 +1845,7 @@ public class ContentViewCore
|
| */
|
| @CalledByNative
|
| private boolean hasFocus() {
|
| - // If the container view is not focusable, we consider it always focused from
|
| - // Chromium's point of view.
|
| - if (!mContainerView.isFocusable()) return true;
|
| - return mContainerView.hasFocus();
|
| + return ViewUtils.hasFocus(mContainerView);
|
| }
|
|
|
| /**
|
| @@ -2564,35 +2469,6 @@ public class ContentViewCore
|
| mSelectionPopupController.setSelectionClient(selectionClient);
|
| }
|
|
|
| - /**
|
| - * Call this when we get result from ResultReceiver passed in calling showSoftInput().
|
| - * @param resultCode The result of showSoftInput() as defined in InputMethodManager.
|
| - */
|
| - public void onShowKeyboardReceiveResult(int resultCode) {
|
| - if (resultCode == InputMethodManager.RESULT_SHOWN) {
|
| - // If OSK is newly shown, delay the form focus until
|
| - // the onSizeChanged (in order to adjust relative to the
|
| - // new size).
|
| - // TODO(jdduke): We should not assume that onSizeChanged will
|
| - // always be called, crbug.com/294908.
|
| - getContainerView().getWindowVisibleDisplayFrame(mFocusPreOSKViewportRect);
|
| - } else if (hasFocus() && resultCode == InputMethodManager.RESULT_UNCHANGED_SHOWN) {
|
| - // If the OSK was already there, focus the form immediately.
|
| - if (mWebContents != null) {
|
| - mWebContents.scrollFocusedEditableNodeIntoView();
|
| - }
|
| - }
|
| - }
|
| -
|
| - @VisibleForTesting
|
| - public ResultReceiver getNewShowKeyboardReceiver() {
|
| - if (mShowKeyboardResultReceiver == null) {
|
| - // Note: the returned object will get leaked by Android framework.
|
| - mShowKeyboardResultReceiver = new ShowKeyboardResultReceiver(this, new Handler());
|
| - }
|
| - return mShowKeyboardResultReceiver;
|
| - }
|
| -
|
| private native long nativeInit(WebContents webContents, ViewAndroidDelegate viewAndroidDelegate,
|
| long windowAndroidPtr, float dipScale, HashSet<Object> retainedObjectSet);
|
| private static native ContentViewCore nativeFromWebContentsAndroid(WebContents webContents);
|
|
|