Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(437)

Side by Side Diff: content/public/android/java/src/org/chromium/content/browser/SelectionPopupController.java

Issue 2855353002: Make Paste Popup use selection rect for positioning (Closed)
Patch Set: Calculate selection rect better Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698