Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.content.browser; | 5 package org.chromium.content.browser; |
| 6 | 6 |
| 7 import android.annotation.TargetApi; | 7 import android.annotation.TargetApi; |
| 8 import android.app.Activity; | 8 import android.app.Activity; |
| 9 import android.app.SearchManager; | 9 import android.app.SearchManager; |
| 10 import android.content.ClipboardManager; | 10 import android.content.ClipboardManager; |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 21 import android.view.Menu; | 21 import android.view.Menu; |
| 22 import android.view.MenuInflater; | 22 import android.view.MenuInflater; |
| 23 import android.view.MenuItem; | 23 import android.view.MenuItem; |
| 24 import android.view.View; | 24 import android.view.View; |
| 25 import android.view.ViewConfiguration; | 25 import android.view.ViewConfiguration; |
| 26 import android.view.WindowManager; | 26 import android.view.WindowManager; |
| 27 | 27 |
| 28 import org.chromium.base.BuildInfo; | 28 import org.chromium.base.BuildInfo; |
| 29 import org.chromium.base.Log; | 29 import org.chromium.base.Log; |
| 30 import org.chromium.base.VisibleForTesting; | 30 import org.chromium.base.VisibleForTesting; |
| 31 import org.chromium.base.annotations.CalledByNative; | |
| 32 import org.chromium.base.annotations.JNINamespace; | |
| 31 import org.chromium.base.metrics.RecordUserAction; | 33 import org.chromium.base.metrics.RecordUserAction; |
| 32 import org.chromium.content.R; | 34 import org.chromium.content.R; |
| 33 import org.chromium.content.browser.input.FloatingPastePopupMenu; | 35 import org.chromium.content.browser.input.FloatingPastePopupMenu; |
| 34 import org.chromium.content.browser.input.LGEmailActionModeWorkaround; | 36 import org.chromium.content.browser.input.LGEmailActionModeWorkaround; |
| 35 import org.chromium.content.browser.input.LegacyPastePopupMenu; | 37 import org.chromium.content.browser.input.LegacyPastePopupMenu; |
| 36 import org.chromium.content.browser.input.PastePopupMenu; | 38 import org.chromium.content.browser.input.PastePopupMenu; |
| 37 import org.chromium.content.browser.input.PastePopupMenu.PastePopupMenuDelegate; | 39 import org.chromium.content.browser.input.PastePopupMenu.PastePopupMenuDelegate; |
| 38 import org.chromium.content_public.browser.ActionModeCallbackHelper; | 40 import org.chromium.content_public.browser.ActionModeCallbackHelper; |
| 39 import org.chromium.content_public.browser.WebContents; | 41 import org.chromium.content_public.browser.WebContents; |
| 40 import org.chromium.ui.base.DeviceFormFactor; | 42 import org.chromium.ui.base.DeviceFormFactor; |
| 41 import org.chromium.ui.base.WindowAndroid; | 43 import org.chromium.ui.base.WindowAndroid; |
| 42 import org.chromium.ui.touch_selection.SelectionEventType; | 44 import org.chromium.ui.touch_selection.SelectionEventType; |
| 43 | 45 |
| 44 import java.util.List; | 46 import java.util.List; |
| 45 | 47 |
| 46 /** | 48 /** |
| 47 * A class that handles input-related web content selection UI like action mode | 49 * A class that handles input-related web content selection UI like action mode |
| 48 * and paste popup view. It wraps an {@link ActionMode} created by the associate d view, | 50 * and paste popup view. It wraps an {@link ActionMode} created by the associate d view, |
| 49 * providing modified interaction with it. | 51 * providing modified interaction with it. |
| 50 * | 52 * |
| 51 * Embedders can use {@link ActionModeCallbackHelper} implemented by this class | 53 * Embedders can use {@link ActionModeCallbackHelper} implemented by this class |
| 52 * to create {@link ActionMode.Callback} instance and configure the selection ac tion | 54 * to create {@link ActionMode.Callback} instance and configure the selection ac tion |
| 53 * mode tasks to their requirements. | 55 * mode tasks to their requirements. |
| 54 */ | 56 */ |
| 57 @JNINamespace("content") | |
| 55 @TargetApi(Build.VERSION_CODES.M) | 58 @TargetApi(Build.VERSION_CODES.M) |
| 56 public class SelectionPopupController extends ActionModeCallbackHelper { | 59 public class SelectionPopupController extends ActionModeCallbackHelper { |
| 57 private static final String TAG = "SelectionPopupCtlr"; // 20 char limit | 60 private static final String TAG = "SelectionPopupCtlr"; // 20 char limit |
| 58 | 61 |
| 59 /** | 62 /** |
| 60 * Android Intent size limitations prevent sending over a megabyte of data. Limit | 63 * Android Intent size limitations prevent sending over a megabyte of data. Limit |
| 61 * query lengths to 100kB because other things may be added to the Intent. | 64 * query lengths to 100kB because other things may be added to the Intent. |
| 62 */ | 65 */ |
| 63 private static final int MAX_SHARE_QUERY_LENGTH = 100000; | 66 private static final int MAX_SHARE_QUERY_LENGTH = 100000; |
| 64 | 67 |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 124 // ContextSelectionProvider was able to classify it, otherwise null. | 127 // ContextSelectionProvider was able to classify it, otherwise null. |
| 125 private ContextSelectionProvider.Result mClassificationResult; | 128 private ContextSelectionProvider.Result mClassificationResult; |
| 126 | 129 |
| 127 // The resource ID for Assist menu item. | 130 // The resource ID for Assist menu item. |
| 128 private int mAssistMenuItemId; | 131 private int mAssistMenuItemId; |
| 129 | 132 |
| 130 // This variable is set to true when showActionMode() is postponed till clas sification result | 133 // This variable is set to true when showActionMode() is postponed till clas sification result |
| 131 // arrives or till the selection is adjusted based on the classification res ult. | 134 // arrives or till the selection is adjusted based on the classification res ult. |
| 132 private boolean mPendingShowActionMode; | 135 private boolean mPendingShowActionMode; |
| 133 | 136 |
| 137 // Whether a scroll is in progress. | |
| 138 private boolean mScrollInProgress; | |
| 139 | |
| 134 /** | 140 /** |
| 135 * Create {@link SelectionPopupController} instance. | 141 * Create {@link SelectionPopupController} instance. |
| 136 * @param context Context for action mode. | 142 * @param context Context for action mode. |
| 137 * @param window WindowAndroid instance. | 143 * @param window WindowAndroid instance. |
| 138 * @param webContents WebContents instance. | 144 * @param webContents WebContents instance. |
| 139 * @param view Container view. | 145 * @param view Container view. |
| 140 * @param renderCoordinates Coordinates info used to position elements. | 146 * @param renderCoordinates Coordinates info used to position elements. |
| 141 */ | 147 */ |
| 142 public SelectionPopupController(Context context, WindowAndroid window, WebCo ntents webContents, | 148 public SelectionPopupController(Context context, WindowAndroid window, WebCo ntents webContents, |
| 143 View view, RenderCoordinates renderCoordinates) { | 149 View view, RenderCoordinates renderCoordinates) { |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 162 | 168 |
| 163 mSelectionClient = | 169 mSelectionClient = |
| 164 ContextSelectionClient.create(new ContextSelectionCallback(), wi ndow, webContents); | 170 ContextSelectionClient.create(new ContextSelectionCallback(), wi ndow, webContents); |
| 165 | 171 |
| 166 // TODO(timav): Use android.R.id.textAssist for the Assist item id once we switch to | 172 // TODO(timav): Use android.R.id.textAssist for the Assist item id once we switch to |
| 167 // Android O SDK and remove |mAssistMenuItemId|. | 173 // Android O SDK and remove |mAssistMenuItemId|. |
| 168 if (BuildInfo.isAtLeastO()) { | 174 if (BuildInfo.isAtLeastO()) { |
| 169 mAssistMenuItemId = | 175 mAssistMenuItemId = |
| 170 mContext.getResources().getIdentifier("textAssist", "id", "a ndroid"); | 176 mContext.getResources().getIdentifier("textAssist", "id", "a ndroid"); |
| 171 } | 177 } |
| 178 | |
| 179 nativeInit(webContents); | |
| 172 } | 180 } |
| 173 | 181 |
| 174 /** | 182 /** |
| 175 * Update the container view. | 183 * Update the container view. |
| 176 */ | 184 */ |
| 177 void setContainerView(View view) { | 185 void setContainerView(View view) { |
| 178 assert view != null; | 186 assert view != null; |
| 179 | 187 |
| 180 // Cleans up action mode before switching to a new container view. | 188 // Cleans up action mode before switching to a new container view. |
| 181 if (isActionModeValid()) finishActionMode(); | 189 if (isActionModeValid()) finishActionMode(); |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 353 | 361 |
| 354 /** | 362 /** |
| 355 * @see ActionMode#onWindowFocusChanged() | 363 * @see ActionMode#onWindowFocusChanged() |
| 356 */ | 364 */ |
| 357 void onWindowFocusChanged(boolean hasWindowFocus) { | 365 void onWindowFocusChanged(boolean hasWindowFocus) { |
| 358 if (supportsFloatingActionMode() && isActionModeValid()) { | 366 if (supportsFloatingActionMode() && isActionModeValid()) { |
| 359 mActionMode.onWindowFocusChanged(hasWindowFocus); | 367 mActionMode.onWindowFocusChanged(hasWindowFocus); |
| 360 } | 368 } |
| 361 } | 369 } |
| 362 | 370 |
| 371 void setScrollInProgress(boolean inProgress) { | |
| 372 mScrollInProgress = inProgress; | |
| 373 } | |
| 374 | |
| 363 /** | 375 /** |
| 364 * Hide or reveal the ActionMode. Note that this only has visible | 376 * Hide or reveal the ActionMode. Note that this only has visible |
| 365 * side-effects if the underlying ActionMode supports hiding. | 377 * side-effects if the underlying ActionMode supports hiding. |
| 366 * @param hide whether to hide or show the ActionMode. | 378 * @param hide whether to hide or show the ActionMode. |
| 367 */ | 379 */ |
| 368 void hideActionMode(boolean hide) { | 380 void hideActionMode(boolean hide) { |
|
boliu
2017/04/20 23:16:49
hmm, did we use to unhide the action mode when tou
Jinsuk Kim
2017/04/20 23:49:06
Done.
| |
| 369 if (!canHideActionMode()) return; | 381 if (!canHideActionMode()) return; |
| 370 if (mHidden == hide) return; | 382 if (mHidden == hide) return; |
| 371 mHidden = hide; | 383 mHidden = hide; |
| 372 if (mHidden) { | 384 if (mHidden) { |
| 373 mRepeatingHideRunnable.run(); | 385 mRepeatingHideRunnable.run(); |
| 374 } else { | 386 } else { |
| 375 mView.removeCallbacks(mRepeatingHideRunnable); | 387 mView.removeCallbacks(mRepeatingHideRunnable); |
| 376 // To show the action mode that is being hidden call hide() again wi th a short delay. | 388 // To show the action mode that is being hidden call hide() again wi th a short delay. |
| 377 hideActionModeTemporarily(SHOW_DELAY_MS); | 389 hideActionModeTemporarily(SHOW_DELAY_MS); |
| 378 } | 390 } |
| (...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 825 } | 837 } |
| 826 } | 838 } |
| 827 | 839 |
| 828 void restoreSelectionPopupsIfNecessary() { | 840 void restoreSelectionPopupsIfNecessary() { |
| 829 if (mHasSelection && !isActionModeValid()) { | 841 if (mHasSelection && !isActionModeValid()) { |
| 830 showActionModeOrClearOnFailure(); | 842 showActionModeOrClearOnFailure(); |
| 831 } | 843 } |
| 832 } | 844 } |
| 833 | 845 |
| 834 // All coordinates are in DIP. | 846 // All coordinates are in DIP. |
| 835 void onSelectionEvent(int eventType, int xAnchor, int yAnchor, | 847 @CalledByNative |
| 836 int left, int top, int right, int bottom, boolean isScrollInProgress , | 848 private void onSelectionEvent( |
| 837 boolean touchScrollInProgress) { | 849 int eventType, int xAnchor, int yAnchor, int left, int top, int righ t, int bottom) { |
| 838 // Ensure the provided selection coordinates form a non-empty rect, as r equired by | 850 // Ensure the provided selection coordinates form a non-empty rect, as r equired by |
| 839 // the selection action mode. | 851 // the selection action mode. |
| 840 if (left == right) ++right; | 852 if (left == right) ++right; |
| 841 if (top == bottom) ++bottom; | 853 if (top == bottom) ++bottom; |
| 842 switch (eventType) { | 854 switch (eventType) { |
| 843 case SelectionEventType.SELECTION_HANDLES_SHOWN: | 855 case SelectionEventType.SELECTION_HANDLES_SHOWN: |
| 844 mSelectionRect.set(left, top, right, bottom); | 856 mSelectionRect.set(left, top, right, bottom); |
| 845 mHasSelection = true; | 857 mHasSelection = true; |
| 846 mUnselectAllOnDismiss = true; | 858 mUnselectAllOnDismiss = true; |
| 847 if (mSelectionClient == null || !mSelectionClient.sendsSelection PopupUpdates()) { | 859 if (mSelectionClient == null || !mSelectionClient.sendsSelection PopupUpdates()) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 881 // request always calling onClassified() callback. | 893 // request always calling onClassified() callback. |
| 882 break; | 894 break; |
| 883 | 895 |
| 884 case SelectionEventType.INSERTION_HANDLE_SHOWN: | 896 case SelectionEventType.INSERTION_HANDLE_SHOWN: |
| 885 mSelectionRect.set(left, top, right, bottom); | 897 mSelectionRect.set(left, top, right, bottom); |
| 886 mIsInsertion = true; | 898 mIsInsertion = true; |
| 887 break; | 899 break; |
| 888 | 900 |
| 889 case SelectionEventType.INSERTION_HANDLE_MOVED: | 901 case SelectionEventType.INSERTION_HANDLE_MOVED: |
| 890 mSelectionRect.set(left, top, right, bottom); | 902 mSelectionRect.set(left, top, right, bottom); |
| 891 if (!isScrollInProgress && isPastePopupShowing()) { | 903 if (!mScrollInProgress && isPastePopupShowing()) { |
| 892 showPastePopup(xAnchor, yAnchor); | 904 showPastePopup(xAnchor, yAnchor); |
| 893 } else { | 905 } else { |
| 894 destroyPastePopup(); | 906 destroyPastePopup(); |
| 895 } | 907 } |
| 896 break; | 908 break; |
| 897 | 909 |
| 898 case SelectionEventType.INSERTION_HANDLE_TAPPED: | 910 case SelectionEventType.INSERTION_HANDLE_TAPPED: |
| 899 if (mWasPastePopupShowingOnInsertionDragStart) { | 911 if (mWasPastePopupShowingOnInsertionDragStart) { |
| 900 destroyPastePopup(); | 912 destroyPastePopup(); |
| 901 } else { | 913 } else { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 937 /** | 949 /** |
| 938 * Clears the current text selection. Note that we will try to move cursor t o selection | 950 * Clears the current text selection. Note that we will try to move cursor t o selection |
| 939 * end if applicable. | 951 * end if applicable. |
| 940 */ | 952 */ |
| 941 void clearSelection() { | 953 void clearSelection() { |
| 942 if (mWebContents == null || !isActionModeSupported()) return; | 954 if (mWebContents == null || !isActionModeSupported()) return; |
| 943 mWebContents.collapseSelection(); | 955 mWebContents.collapseSelection(); |
| 944 mClassificationResult = null; | 956 mClassificationResult = null; |
| 945 } | 957 } |
| 946 | 958 |
| 947 void onSelectionChanged(String text) { | 959 @CalledByNative |
| 960 private void onSelectionChanged(String text) { | |
| 948 mLastSelectedText = text; | 961 mLastSelectedText = text; |
| 949 if (mSelectionClient != null) { | 962 if (mSelectionClient != null) { |
| 950 mSelectionClient.onSelectionChanged(text); | 963 mSelectionClient.onSelectionChanged(text); |
| 951 } | 964 } |
| 952 } | 965 } |
| 953 | 966 |
| 954 // The client that implements selection augmenting functionality, or null if none exists. | 967 // The client that implements selection augmenting functionality, or null if none exists. |
| 955 void setSelectionClient(SelectionClient selectionClient) { | 968 void setSelectionClient(SelectionClient selectionClient) { |
| 956 mSelectionClient = selectionClient; | 969 mSelectionClient = selectionClient; |
| 957 | 970 |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1035 mWebContents.adjustSelectionByCharacterOffset(result.startAdjust , result.endAdjust); | 1048 mWebContents.adjustSelectionByCharacterOffset(result.startAdjust , result.endAdjust); |
| 1036 | 1049 |
| 1037 // Remain pending until SELECTION_HANDLES_MOVED arrives. | 1050 // Remain pending until SELECTION_HANDLES_MOVED arrives. |
| 1038 if (mPendingShowActionMode) return; | 1051 if (mPendingShowActionMode) return; |
| 1039 } | 1052 } |
| 1040 | 1053 |
| 1041 // Rely on this method to clear |mHidden| and unhide the action mode . | 1054 // Rely on this method to clear |mHidden| and unhide the action mode . |
| 1042 showActionModeOrClearOnFailure(); | 1055 showActionModeOrClearOnFailure(); |
| 1043 } | 1056 } |
| 1044 }; | 1057 }; |
| 1058 | |
| 1059 private native void nativeInit(WebContents webContents); | |
| 1045 } | 1060 } |
| OLD | NEW |