Skip to content

Commit 1023aa4

Browse files
author
George Mount
committed
Paste window instead of action bar when cursor shown.
Use the paste window shown with TextView when the cursor is shown rather than use the action bar. Change-Id: I47d0bc2d5cba066399532a9e75171a75628ac7ed
1 parent 3cd9c12 commit 1023aa4

File tree

1 file changed

+125
-15
lines changed

1 file changed

+125
-15
lines changed

core/java/android/webkit/WebView.java

Lines changed: 125 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
import android.text.Selection;
6969
import android.text.TextUtils;
7070
import android.util.AttributeSet;
71+
import android.util.DisplayMetrics;
7172
import android.util.EventLog;
7273
import android.util.Log;
7374
import android.view.Display;
@@ -111,6 +112,8 @@
111112
import android.widget.LinearLayout;
112113
import android.widget.ListView;
113114
import android.widget.OverScroller;
115+
import android.widget.PopupWindow;
116+
import android.widget.TextView;
114117
import android.widget.Toast;
115118

116119
import junit.framework.Assert;
@@ -122,7 +125,6 @@
122125
import java.io.IOException;
123126
import java.io.InputStream;
124127
import java.io.OutputStream;
125-
import java.io.UnsupportedEncodingException;
126128
import java.net.URLDecoder;
127129
import java.util.ArrayList;
128130
import java.util.HashMap;
@@ -423,6 +425,23 @@ public void setTextAndKeepSelection(CharSequence text) {
423425
setSelection(selectionStart, selectionEnd);
424426
}
425427

428+
public void replaceSelection(CharSequence text) {
429+
Editable editable = getEditable();
430+
int selectionStart = Selection.getSelectionStart(editable);
431+
int selectionEnd = Selection.getSelectionEnd(editable);
432+
setNewText(selectionStart, selectionEnd, text);
433+
editable.replace(selectionStart, selectionEnd, text);
434+
InputMethodManager imm = InputMethodManager.peekInstance();
435+
if (imm != null) {
436+
// Since the text has changed, do not allow the IME to replace the
437+
// existing text as though it were a completion.
438+
imm.restartInput(WebView.this);
439+
}
440+
// Move caret to the end of the new text
441+
int newCaret = selectionStart + text.length();
442+
setSelection(newCaret, newCaret);
443+
}
444+
426445
@Override
427446
public boolean setComposingText(CharSequence text, int newCursorPosition) {
428447
Editable editable = getEditable();
@@ -609,6 +628,78 @@ private void sendDeleteKey() {
609628
}
610629
}
611630

631+
private class PastePopupWindow extends PopupWindow implements OnClickListener {
632+
private ViewGroup mContentView;
633+
private TextView mPasteTextView;
634+
635+
public PastePopupWindow() {
636+
super(WebView.this.mContext, null,
637+
com.android.internal.R.attr.textSelectHandleWindowStyle);
638+
setClippingEnabled(true);
639+
LinearLayout linearLayout = new LinearLayout(WebView.this.getContext());
640+
linearLayout.setOrientation(LinearLayout.HORIZONTAL);
641+
mContentView = linearLayout;
642+
mContentView.setBackgroundResource(
643+
com.android.internal.R.drawable.text_edit_paste_window);
644+
645+
LayoutInflater inflater = (LayoutInflater)WebView.this.mContext.
646+
getSystemService(Context.LAYOUT_INFLATER_SERVICE);
647+
648+
ViewGroup.LayoutParams wrapContent = new ViewGroup.LayoutParams(
649+
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
650+
651+
mPasteTextView = (TextView) inflater.inflate(
652+
com.android.internal.R.layout.text_edit_action_popup_text, null);
653+
mPasteTextView.setLayoutParams(wrapContent);
654+
mContentView.addView(mPasteTextView);
655+
mPasteTextView.setText(com.android.internal.R.string.paste);
656+
mPasteTextView.setOnClickListener(this);
657+
this.setContentView(mContentView);
658+
}
659+
660+
public void show(Rect cursorRect, int windowLeft, int windowTop) {
661+
measureContent();
662+
663+
int width = mContentView.getMeasuredWidth();
664+
int height = mContentView.getMeasuredHeight();
665+
int y = cursorRect.top - height;
666+
if (y < windowTop) {
667+
// There's not enough room vertically, move it below the
668+
// handle.
669+
// The selection handle is vertically offset by 1/4 of the
670+
// line height.
671+
y = cursorRect.bottom - (cursorRect.height() / 4) +
672+
mSelectHandleCenter.getIntrinsicHeight();
673+
}
674+
int x = cursorRect.centerX() - (width / 2);
675+
if (x < windowLeft) {
676+
x = windowLeft;
677+
}
678+
if (!isShowing()) {
679+
showAtLocation(WebView.this, Gravity.NO_GRAVITY, x, y);
680+
}
681+
update(x, y, width, height);
682+
}
683+
684+
public void hide() {
685+
dismiss();
686+
}
687+
688+
@Override
689+
public void onClick(View view) {
690+
pasteFromClipboard();
691+
selectionDone();
692+
}
693+
694+
protected void measureContent() {
695+
final DisplayMetrics displayMetrics = mContext.getResources().getDisplayMetrics();
696+
mContentView.measure(
697+
View.MeasureSpec.makeMeasureSpec(displayMetrics.widthPixels,
698+
View.MeasureSpec.AT_MOST),
699+
View.MeasureSpec.makeMeasureSpec(displayMetrics.heightPixels,
700+
View.MeasureSpec.AT_MOST));
701+
}
702+
}
612703

613704
// The listener to capture global layout change event.
614705
private InnerGlobalLayoutListener mGlobalLayoutListener = null;
@@ -636,6 +727,7 @@ private void sendDeleteKey() {
636727
private boolean mGLViewportEmpty = false;
637728
WebViewInputConnection mInputConnection = null;
638729
private int mFieldPointer;
730+
private PastePopupWindow mPasteWindow;
639731

640732
/**
641733
* Transportation object for returning WebView across thread boundaries.
@@ -5910,6 +6002,27 @@ private boolean startSelectActionMode() {
59106002
return true;
59116003
}
59126004

6005+
private void showPasteWindow() {
6006+
ClipboardManager cm = (ClipboardManager)(mContext
6007+
.getSystemService(Context.CLIPBOARD_SERVICE));
6008+
if (cm.hasPrimaryClip()) {
6009+
Rect cursorRect = contentToViewRect(mSelectCursorBase);
6010+
int[] location = new int[2];
6011+
getLocationInWindow(location);
6012+
cursorRect.offset(location[0] - mScrollX, location[1] - mScrollY);
6013+
if (mPasteWindow == null) {
6014+
mPasteWindow = new PastePopupWindow();
6015+
}
6016+
mPasteWindow.show(cursorRect, location[0], location[1]);
6017+
}
6018+
}
6019+
6020+
private void hidePasteButton() {
6021+
if (mPasteWindow != null) {
6022+
mPasteWindow.hide();
6023+
}
6024+
}
6025+
59136026
private void syncSelectionCursors() {
59146027
mSelectCursorBaseLayerId =
59156028
nativeGetHandleLayerId(mNativeClass, HANDLE_ID_BASE, mSelectCursorBase);
@@ -5919,13 +6032,11 @@ private void syncSelectionCursors() {
59196032

59206033
private boolean setupWebkitSelect() {
59216034
syncSelectionCursors();
5922-
ClipboardManager cm = (ClipboardManager)(mContext
5923-
.getSystemService(Context.CLIPBOARD_SERVICE));
5924-
if (!mIsCaretSelection || cm.hasPrimaryClip()) {
5925-
if (!startSelectActionMode()) {
5926-
selectionDone();
5927-
return false;
5928-
}
6035+
if (mIsCaretSelection) {
6036+
showPasteWindow();
6037+
} else if (!startSelectActionMode()) {
6038+
selectionDone();
6039+
return false;
59296040
}
59306041
mSelectingText = true;
59316042
mTouchMode = TOUCH_DRAG_MODE;
@@ -5982,6 +6093,7 @@ public void selectAll() {
59826093
*/
59836094
void selectionDone() {
59846095
if (mSelectingText) {
6096+
hidePasteButton();
59856097
mSelectingText = false;
59866098
// finish is idempotent, so this is fine even if selectionDone was
59876099
// called by mSelectCallback.onDestroyActionMode
@@ -6051,12 +6163,8 @@ public void pasteFromClipboard() {
60516163
if (clipData != null) {
60526164
ClipData.Item clipItem = clipData.getItemAt(0);
60536165
CharSequence pasteText = clipItem.getText();
6054-
if (pasteText != null) {
6055-
int[] handles = new int[4];
6056-
getSelectionHandles(handles);
6057-
mWebViewCore.sendMessage(EventHub.DELETE_TEXT, handles);
6058-
mWebViewCore.sendMessage(EventHub.INSERT_TEXT,
6059-
pasteText.toString());
6166+
if (mInputConnection != null) {
6167+
mInputConnection.replaceSelection(pasteText);
60606168
}
60616169
}
60626170
}
@@ -6614,6 +6722,7 @@ public void run() {
66146722
mSelectionStarted = true;
66156723
mSelectDraggingCursor = mSelectCursorBase;
66166724
mPrivateHandler.removeMessages(CLEAR_CARET_HANDLE);
6725+
hidePasteButton();
66176726
} else if (mSelectHandleLeft != null
66186727
&& mSelectHandleLeft.getBounds()
66196728
.contains(shiftedX, shiftedY)) {
@@ -7276,10 +7385,11 @@ private void stopTouch() {
72767385

72777386
if (mSelectingText) {
72787387
mSelectionStarted = false;
7388+
syncSelectionCursors();
72797389
if (mIsCaretSelection) {
72807390
resetCaretTimer();
7391+
showPasteWindow();
72817392
}
7282-
syncSelectionCursors();
72837393
invalidate();
72847394
}
72857395
}

0 commit comments

Comments
 (0)