| 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.ClipData; | 10 import android.content.ClipData; |
| (...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 261 if (!isActionModeValid()) clearSelection(); | 261 if (!isActionModeValid()) clearSelection(); |
| 262 } | 262 } |
| 263 | 263 |
| 264 @TargetApi(Build.VERSION_CODES.M) | 264 @TargetApi(Build.VERSION_CODES.M) |
| 265 private ActionMode startFloatingActionMode() { | 265 private ActionMode startFloatingActionMode() { |
| 266 ActionMode actionMode = mView.startActionMode( | 266 ActionMode actionMode = mView.startActionMode( |
| 267 new FloatingActionModeCallback(this, mCallback), ActionMode.TYPE
_FLOATING); | 267 new FloatingActionModeCallback(this, mCallback), ActionMode.TYPE
_FLOATING); |
| 268 return actionMode; | 268 return actionMode; |
| 269 } | 269 } |
| 270 | 270 |
| 271 void createAndShowPastePopup(int x, int y, boolean canSelectAll, boolean can
EditRichly) { | 271 void createAndShowPastePopup( |
| 272 int left, int top, int right, int bottom, boolean canSelectAll, bool
ean canEditRichly) { |
| 272 if (mView.getParent() == null || mView.getVisibility() != View.VISIBLE)
{ | 273 if (mView.getParent() == null || mView.getVisibility() != View.VISIBLE)
{ |
| 273 return; | 274 return; |
| 274 } | 275 } |
| 275 | 276 |
| 276 if (!supportsFloatingActionMode() && !canPaste()) return; | 277 if (!supportsFloatingActionMode() && !canPaste()) return; |
| 277 destroyPastePopup(); | 278 destroyPastePopup(); |
| 279 mSelectionRect.set(left, top, right, bottom); |
| 278 mCanSelectAllForPastePopup = canSelectAll; | 280 mCanSelectAllForPastePopup = canSelectAll; |
| 279 mCanEditRichlyForPastePopup = canEditRichly; | 281 mCanEditRichlyForPastePopup = canEditRichly; |
| 280 PastePopupMenuDelegate delegate = new PastePopupMenuDelegate() { | 282 PastePopupMenuDelegate delegate = new PastePopupMenuDelegate() { |
| 281 @Override | 283 @Override |
| 282 public void paste() { | 284 public void paste() { |
| 283 mWebContents.paste(); | 285 mWebContents.paste(); |
| 284 mWebContents.dismissTextHandles(); | 286 mWebContents.dismissTextHandles(); |
| 285 } | 287 } |
| 286 | 288 |
| 287 @Override | 289 @Override |
| (...skipping 22 matching lines...) Expand all Loading... |
| 310 return SelectionPopupController.this.canPasteAsPlainText(); | 312 return SelectionPopupController.this.canPasteAsPlainText(); |
| 311 } | 313 } |
| 312 }; | 314 }; |
| 313 Context windowContext = mWindowAndroid.getContext().get(); | 315 Context windowContext = mWindowAndroid.getContext().get(); |
| 314 if (windowContext == null) return; | 316 if (windowContext == null) return; |
| 315 if (supportsFloatingActionMode()) { | 317 if (supportsFloatingActionMode()) { |
| 316 mPastePopupMenu = new FloatingPastePopupMenu(windowContext, mView, d
elegate); | 318 mPastePopupMenu = new FloatingPastePopupMenu(windowContext, mView, d
elegate); |
| 317 } else { | 319 } else { |
| 318 mPastePopupMenu = new LegacyPastePopupMenu(windowContext, mView, del
egate); | 320 mPastePopupMenu = new LegacyPastePopupMenu(windowContext, mView, del
egate); |
| 319 } | 321 } |
| 320 showPastePopup(x, y); | 322 showPastePopup(); |
| 321 } | 323 } |
| 322 | 324 |
| 323 private void showPastePopup(int x, int y) { | 325 private void showPastePopup() { |
| 324 // Coordinates are in DIP. | |
| 325 final float deviceScale = mRenderCoordinates.getDeviceScaleFactor(); | |
| 326 final int xPix = (int) (x * deviceScale); | |
| 327 final int yPix = (int) (y * deviceScale); | |
| 328 final float browserControlsShownPix = mRenderCoordinates.getContentOffse
tYPix(); | |
| 329 try { | 326 try { |
| 330 mPastePopupMenu.show(xPix, (int) (yPix + browserControlsShownPix)); | 327 mPastePopupMenu.show(getSelectionRectRelativeToContainingView()); |
| 331 } catch (WindowManager.BadTokenException e) { | 328 } catch (WindowManager.BadTokenException e) { |
| 332 } | 329 } |
| 333 } | 330 } |
| 334 | 331 |
| 335 @Override | 332 @Override |
| 336 public boolean supportsFloatingActionMode() { | 333 public boolean supportsFloatingActionMode() { |
| 337 return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M; | 334 return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M; |
| 338 } | 335 } |
| 339 | 336 |
| 340 void destroyPastePopup() { | 337 void destroyPastePopup() { |
| (...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 679 * Called when an ActionMode needs to be positioned on screen, potentially o
ccluding view | 676 * Called when an ActionMode needs to be positioned on screen, potentially o
ccluding view |
| 680 * content. Note this may be called on a per-frame basis. | 677 * content. Note this may be called on a per-frame basis. |
| 681 * | 678 * |
| 682 * @param mode The ActionMode that requires positioning. | 679 * @param mode The ActionMode that requires positioning. |
| 683 * @param view The View that originated the ActionMode, in whose coordinates
the Rect should | 680 * @param view The View that originated the ActionMode, in whose coordinates
the Rect should |
| 684 * be provided. | 681 * be provided. |
| 685 * @param outRect The Rect to be populated with the content position. | 682 * @param outRect The Rect to be populated with the content position. |
| 686 */ | 683 */ |
| 687 @Override | 684 @Override |
| 688 public void onGetContentRect(ActionMode mode, View view, Rect outRect) { | 685 public void onGetContentRect(ActionMode mode, View view, Rect outRect) { |
| 686 outRect.set(getSelectionRectRelativeToContainingView()); |
| 687 } |
| 688 |
| 689 private Rect getSelectionRectRelativeToContainingView() { |
| 689 float deviceScale = mRenderCoordinates.getDeviceScaleFactor(); | 690 float deviceScale = mRenderCoordinates.getDeviceScaleFactor(); |
| 690 outRect.set((int) (mSelectionRect.left * deviceScale), | 691 Rect viewSelectionRect = new Rect((int) (mSelectionRect.left * deviceSca
le), |
| 691 (int) (mSelectionRect.top * deviceScale), | 692 (int) (mSelectionRect.top * deviceScale), |
| 692 (int) (mSelectionRect.right * deviceScale), | 693 (int) (mSelectionRect.right * deviceScale), |
| 693 (int) (mSelectionRect.bottom * deviceScale)); | 694 (int) (mSelectionRect.bottom * deviceScale)); |
| 694 | 695 |
| 695 // The selection coordinates are relative to the content viewport, but w
e need | 696 // The selection coordinates are relative to the content viewport, but w
e need |
| 696 // coordinates relative to the containing View. | 697 // coordinates relative to the containing View. |
| 697 outRect.offset(0, (int) mRenderCoordinates.getContentOffsetYPix()); | 698 viewSelectionRect.offset(0, (int) mRenderCoordinates.getContentOffsetYPi
x()); |
| 699 return viewSelectionRect; |
| 698 } | 700 } |
| 699 | 701 |
| 700 /** | 702 /** |
| 701 * Perform an action that depends on the semantics of the selected text. | 703 * Perform an action that depends on the semantics of the selected text. |
| 702 */ | 704 */ |
| 703 @VisibleForTesting | 705 @VisibleForTesting |
| 704 void doAssistAction() { | 706 void doAssistAction() { |
| 705 if (mClassificationResult == null || !mClassificationResult.hasNamedActi
on()) return; | 707 if (mClassificationResult == null || !mClassificationResult.hasNamedActi
on()) return; |
| 706 | 708 |
| 707 assert mClassificationResult.onClickListener != null | 709 assert mClassificationResult.onClickListener != null |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 917 } | 919 } |
| 918 | 920 |
| 919 void restoreSelectionPopupsIfNecessary() { | 921 void restoreSelectionPopupsIfNecessary() { |
| 920 if (mHasSelection && !isActionModeValid()) { | 922 if (mHasSelection && !isActionModeValid()) { |
| 921 showActionModeOrClearOnFailure(); | 923 showActionModeOrClearOnFailure(); |
| 922 } | 924 } |
| 923 } | 925 } |
| 924 | 926 |
| 925 // All coordinates are in DIP. | 927 // All coordinates are in DIP. |
| 926 @CalledByNative | 928 @CalledByNative |
| 927 private void onSelectionEvent( | 929 private void onSelectionEvent(int eventType, int left, int top, int right, i
nt bottom) { |
| 928 int eventType, int xAnchor, int yAnchor, int left, int top, int righ
t, int bottom) { | |
| 929 // Ensure the provided selection coordinates form a non-empty rect, as r
equired by | 930 // Ensure the provided selection coordinates form a non-empty rect, as r
equired by |
| 930 // the selection action mode. | 931 // the selection action mode. |
| 931 if (left == right) ++right; | 932 if (left == right) ++right; |
| 932 if (top == bottom) ++bottom; | 933 if (top == bottom) ++bottom; |
| 933 switch (eventType) { | 934 switch (eventType) { |
| 934 case SelectionEventType.SELECTION_HANDLES_SHOWN: | 935 case SelectionEventType.SELECTION_HANDLES_SHOWN: |
| 935 mSelectionRect.set(left, top, right, bottom); | 936 mSelectionRect.set(left, top, right, bottom); |
| 936 mHasSelection = true; | 937 mHasSelection = true; |
| 937 mUnselectAllOnDismiss = true; | 938 mUnselectAllOnDismiss = true; |
| 938 if (mSelectionClient != null | 939 if (mSelectionClient != null |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 977 break; | 978 break; |
| 978 | 979 |
| 979 case SelectionEventType.INSERTION_HANDLE_SHOWN: | 980 case SelectionEventType.INSERTION_HANDLE_SHOWN: |
| 980 mSelectionRect.set(left, top, right, bottom); | 981 mSelectionRect.set(left, top, right, bottom); |
| 981 mIsInsertion = true; | 982 mIsInsertion = true; |
| 982 break; | 983 break; |
| 983 | 984 |
| 984 case SelectionEventType.INSERTION_HANDLE_MOVED: | 985 case SelectionEventType.INSERTION_HANDLE_MOVED: |
| 985 mSelectionRect.set(left, top, right, bottom); | 986 mSelectionRect.set(left, top, right, bottom); |
| 986 if (!mScrollInProgress && isPastePopupShowing()) { | 987 if (!mScrollInProgress && isPastePopupShowing()) { |
| 987 showPastePopup(xAnchor, yAnchor); | 988 showPastePopup(); |
| 988 } else { | 989 } else { |
| 989 destroyPastePopup(); | 990 destroyPastePopup(); |
| 990 } | 991 } |
| 991 break; | 992 break; |
| 992 | 993 |
| 993 case SelectionEventType.INSERTION_HANDLE_TAPPED: | 994 case SelectionEventType.INSERTION_HANDLE_TAPPED: |
| 994 if (mWasPastePopupShowingOnInsertionDragStart) { | 995 if (mWasPastePopupShowingOnInsertionDragStart) { |
| 995 destroyPastePopup(); | 996 destroyPastePopup(); |
| 996 } else { | 997 } else { |
| 997 mWebContents.showContextMenuAtPoint(xAnchor, yAnchor); | 998 mWebContents.showContextMenuAtPoint(mSelectionRect.left, mSe
lectionRect.bottom); |
| 998 } | 999 } |
| 999 mWasPastePopupShowingOnInsertionDragStart = false; | 1000 mWasPastePopupShowingOnInsertionDragStart = false; |
| 1000 break; | 1001 break; |
| 1001 | 1002 |
| 1002 case SelectionEventType.INSERTION_HANDLE_CLEARED: | 1003 case SelectionEventType.INSERTION_HANDLE_CLEARED: |
| 1003 destroyPastePopup(); | 1004 destroyPastePopup(); |
| 1004 mIsInsertion = false; | 1005 mIsInsertion = false; |
| 1005 mSelectionRect.setEmpty(); | 1006 mSelectionRect.setEmpty(); |
| 1006 break; | 1007 break; |
| 1007 | 1008 |
| 1008 case SelectionEventType.INSERTION_HANDLE_DRAG_STARTED: | 1009 case SelectionEventType.INSERTION_HANDLE_DRAG_STARTED: |
| 1009 mWasPastePopupShowingOnInsertionDragStart = isPastePopupShowing(
); | 1010 mWasPastePopupShowingOnInsertionDragStart = isPastePopupShowing(
); |
| 1010 destroyPastePopup(); | 1011 destroyPastePopup(); |
| 1011 break; | 1012 break; |
| 1012 | 1013 |
| 1013 case SelectionEventType.INSERTION_HANDLE_DRAG_STOPPED: | 1014 case SelectionEventType.INSERTION_HANDLE_DRAG_STOPPED: |
| 1014 if (mWasPastePopupShowingOnInsertionDragStart) { | 1015 if (mWasPastePopupShowingOnInsertionDragStart) { |
| 1015 mWebContents.showContextMenuAtPoint(xAnchor, yAnchor); | 1016 mWebContents.showContextMenuAtPoint(mSelectionRect.left, mSe
lectionRect.bottom); |
| 1016 } | 1017 } |
| 1017 mWasPastePopupShowingOnInsertionDragStart = false; | 1018 mWasPastePopupShowingOnInsertionDragStart = false; |
| 1018 break; | 1019 break; |
| 1019 | 1020 |
| 1020 default: | 1021 default: |
| 1021 assert false : "Invalid selection event type."; | 1022 assert false : "Invalid selection event type."; |
| 1022 } | 1023 } |
| 1023 | 1024 |
| 1024 if (mSelectionClient != null) { | 1025 if (mSelectionClient != null) { |
| 1025 final float deviceScale = mRenderCoordinates.getDeviceScaleFactor(); | 1026 final float deviceScale = mRenderCoordinates.getDeviceScaleFactor(); |
| 1026 int xAnchorPix = (int) (xAnchor * deviceScale); | 1027 int xAnchorPix = (int) (mSelectionRect.left * deviceScale); |
| 1027 int yAnchorPix = (int) (yAnchor * deviceScale); | 1028 int yAnchorPix = (int) (mSelectionRect.bottom * deviceScale); |
| 1028 mSelectionClient.onSelectionEvent(eventType, xAnchorPix, yAnchorPix)
; | 1029 mSelectionClient.onSelectionEvent(eventType, xAnchorPix, yAnchorPix)
; |
| 1029 } | 1030 } |
| 1030 } | 1031 } |
| 1031 | 1032 |
| 1032 /** | 1033 /** |
| 1033 * Clears the current text selection. Note that we will try to move cursor t
o selection | 1034 * Clears the current text selection. Note that we will try to move cursor t
o selection |
| 1034 * end if applicable. | 1035 * end if applicable. |
| 1035 */ | 1036 */ |
| 1036 void clearSelection() { | 1037 void clearSelection() { |
| 1037 if (mWebContents == null || !isActionModeSupported()) return; | 1038 if (mWebContents == null || !isActionModeSupported()) return; |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1146 if (mPendingShowActionMode) return; | 1147 if (mPendingShowActionMode) return; |
| 1147 } | 1148 } |
| 1148 | 1149 |
| 1149 // Rely on this method to clear |mHidden| and unhide the action mode
. | 1150 // Rely on this method to clear |mHidden| and unhide the action mode
. |
| 1150 showActionModeOrClearOnFailure(); | 1151 showActionModeOrClearOnFailure(); |
| 1151 } | 1152 } |
| 1152 }; | 1153 }; |
| 1153 | 1154 |
| 1154 private native void nativeInit(WebContents webContents); | 1155 private native void nativeInit(WebContents webContents); |
| 1155 } | 1156 } |
| OLD | NEW |