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
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index b9dfb2e..e7ab826 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -68,6 +68,7 @@
import android.text.Selection;
import android.text.TextUtils;
import android.util.AttributeSet;
+import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.Log;
import android.view.Display;
@@ -111,6 +112,8 @@
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.OverScroller;
+import android.widget.PopupWindow;
+import android.widget.TextView;
import android.widget.Toast;
import junit.framework.Assert;
@@ -122,7 +125,6 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
@@ -423,6 +425,23 @@
setSelection(selectionStart, selectionEnd);
}
+ public void replaceSelection(CharSequence text) {
+ Editable editable = getEditable();
+ int selectionStart = Selection.getSelectionStart(editable);
+ int selectionEnd = Selection.getSelectionEnd(editable);
+ setNewText(selectionStart, selectionEnd, text);
+ editable.replace(selectionStart, selectionEnd, text);
+ InputMethodManager imm = InputMethodManager.peekInstance();
+ if (imm != null) {
+ // Since the text has changed, do not allow the IME to replace the
+ // existing text as though it were a completion.
+ imm.restartInput(WebView.this);
+ }
+ // Move caret to the end of the new text
+ int newCaret = selectionStart + text.length();
+ setSelection(newCaret, newCaret);
+ }
+
@Override
public boolean setComposingText(CharSequence text, int newCursorPosition) {
Editable editable = getEditable();
@@ -609,6 +628,78 @@
}
}
+ private class PastePopupWindow extends PopupWindow implements OnClickListener {
+ private ViewGroup mContentView;
+ private TextView mPasteTextView;
+
+ public PastePopupWindow() {
+ super(WebView.this.mContext, null,
+ com.android.internal.R.attr.textSelectHandleWindowStyle);
+ setClippingEnabled(true);
+ LinearLayout linearLayout = new LinearLayout(WebView.this.getContext());
+ linearLayout.setOrientation(LinearLayout.HORIZONTAL);
+ mContentView = linearLayout;
+ mContentView.setBackgroundResource(
+ com.android.internal.R.drawable.text_edit_paste_window);
+
+ LayoutInflater inflater = (LayoutInflater)WebView.this.mContext.
+ getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+ ViewGroup.LayoutParams wrapContent = new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+
+ mPasteTextView = (TextView) inflater.inflate(
+ com.android.internal.R.layout.text_edit_action_popup_text, null);
+ mPasteTextView.setLayoutParams(wrapContent);
+ mContentView.addView(mPasteTextView);
+ mPasteTextView.setText(com.android.internal.R.string.paste);
+ mPasteTextView.setOnClickListener(this);
+ this.setContentView(mContentView);
+ }
+
+ public void show(Rect cursorRect, int windowLeft, int windowTop) {
+ measureContent();
+
+ int width = mContentView.getMeasuredWidth();
+ int height = mContentView.getMeasuredHeight();
+ int y = cursorRect.top - height;
+ if (y < windowTop) {
+ // There's not enough room vertically, move it below the
+ // handle.
+ // The selection handle is vertically offset by 1/4 of the
+ // line height.
+ y = cursorRect.bottom - (cursorRect.height() / 4) +
+ mSelectHandleCenter.getIntrinsicHeight();
+ }
+ int x = cursorRect.centerX() - (width / 2);
+ if (x < windowLeft) {
+ x = windowLeft;
+ }
+ if (!isShowing()) {
+ showAtLocation(WebView.this, Gravity.NO_GRAVITY, x, y);
+ }
+ update(x, y, width, height);
+ }
+
+ public void hide() {
+ dismiss();
+ }
+
+ @Override
+ public void onClick(View view) {
+ pasteFromClipboard();
+ selectionDone();
+ }
+
+ protected void measureContent() {
+ final DisplayMetrics displayMetrics = mContext.getResources().getDisplayMetrics();
+ mContentView.measure(
+ View.MeasureSpec.makeMeasureSpec(displayMetrics.widthPixels,
+ View.MeasureSpec.AT_MOST),
+ View.MeasureSpec.makeMeasureSpec(displayMetrics.heightPixels,
+ View.MeasureSpec.AT_MOST));
+ }
+ }
// The listener to capture global layout change event.
private InnerGlobalLayoutListener mGlobalLayoutListener = null;
@@ -636,6 +727,7 @@
private boolean mGLViewportEmpty = false;
WebViewInputConnection mInputConnection = null;
private int mFieldPointer;
+ private PastePopupWindow mPasteWindow;
/**
* Transportation object for returning WebView across thread boundaries.
@@ -5910,6 +6002,27 @@
return true;
}
+ private void showPasteWindow() {
+ ClipboardManager cm = (ClipboardManager)(mContext
+ .getSystemService(Context.CLIPBOARD_SERVICE));
+ if (cm.hasPrimaryClip()) {
+ Rect cursorRect = contentToViewRect(mSelectCursorBase);
+ int[] location = new int[2];
+ getLocationInWindow(location);
+ cursorRect.offset(location[0] - mScrollX, location[1] - mScrollY);
+ if (mPasteWindow == null) {
+ mPasteWindow = new PastePopupWindow();
+ }
+ mPasteWindow.show(cursorRect, location[0], location[1]);
+ }
+ }
+
+ private void hidePasteButton() {
+ if (mPasteWindow != null) {
+ mPasteWindow.hide();
+ }
+ }
+
private void syncSelectionCursors() {
mSelectCursorBaseLayerId =
nativeGetHandleLayerId(mNativeClass, HANDLE_ID_BASE, mSelectCursorBase);
@@ -5919,13 +6032,11 @@
private boolean setupWebkitSelect() {
syncSelectionCursors();
- ClipboardManager cm = (ClipboardManager)(mContext
- .getSystemService(Context.CLIPBOARD_SERVICE));
- if (!mIsCaretSelection || cm.hasPrimaryClip()) {
- if (!startSelectActionMode()) {
- selectionDone();
- return false;
- }
+ if (mIsCaretSelection) {
+ showPasteWindow();
+ } else if (!startSelectActionMode()) {
+ selectionDone();
+ return false;
}
mSelectingText = true;
mTouchMode = TOUCH_DRAG_MODE;
@@ -5982,6 +6093,7 @@
*/
void selectionDone() {
if (mSelectingText) {
+ hidePasteButton();
mSelectingText = false;
// finish is idempotent, so this is fine even if selectionDone was
// called by mSelectCallback.onDestroyActionMode
@@ -6051,12 +6163,8 @@
if (clipData != null) {
ClipData.Item clipItem = clipData.getItemAt(0);
CharSequence pasteText = clipItem.getText();
- if (pasteText != null) {
- int[] handles = new int[4];
- getSelectionHandles(handles);
- mWebViewCore.sendMessage(EventHub.DELETE_TEXT, handles);
- mWebViewCore.sendMessage(EventHub.INSERT_TEXT,
- pasteText.toString());
+ if (mInputConnection != null) {
+ mInputConnection.replaceSelection(pasteText);
}
}
}
@@ -6614,6 +6722,7 @@
mSelectionStarted = true;
mSelectDraggingCursor = mSelectCursorBase;
mPrivateHandler.removeMessages(CLEAR_CARET_HANDLE);
+ hidePasteButton();
} else if (mSelectHandleLeft != null
&& mSelectHandleLeft.getBounds()
.contains(shiftedX, shiftedY)) {
@@ -7276,10 +7385,11 @@
if (mSelectingText) {
mSelectionStarted = false;
+ syncSelectionCursors();
if (mIsCaretSelection) {
resetCaretTimer();
+ showPasteWindow();
}
- syncSelectionCursors();
invalidate();
}
}