Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c0c3025c authored by George Mount's avatar George Mount
Browse files

Fix delete key with ContentEditable fields.

 Bug 5806859
 Bug 5795341
 Add a custom InputConnection to capture the deleteSurroundingText
 command and use it to send delete key codes to the WebView for
 single deletes or calling into WebViewCore to delete contents for
 more complex changes.
 Also makes the IME options "normal text" for webkit-based text
 entry.
 Webkit change: Ic938d6fa

Change-Id: I18606014a034194928a61981dc3e2400a7db5fac
parent 7a939077
Loading
Loading
Loading
Loading
+50 −3
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@ import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.StrictMode;
import android.os.SystemClock;
import android.provider.Settings;
import android.speech.tts.TextToSpeech;
import android.util.AttributeSet;
@@ -82,6 +83,7 @@ import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.inputmethod.BaseInputConnection;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
@@ -349,6 +351,43 @@ public class WebView extends AbsoluteLayout
        }
    }

    /**
     * InputConnection used for ContentEditable. This captures the 'delete'
     * commands and sends delete key presses.
     */
    private class WebViewInputConnection extends BaseInputConnection {
        public WebViewInputConnection() {
            super(WebView.this, false);
        }

        private void sendKeyPress(int keyCode) {
            long eventTime = SystemClock.uptimeMillis();
            sendKeyEvent(new KeyEvent(eventTime, eventTime,
                    KeyEvent.ACTION_DOWN, keyCode, 0, 0,
                    KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
                    KeyEvent.FLAG_SOFT_KEYBOARD));
            sendKeyEvent(new KeyEvent(SystemClock.uptimeMillis(), eventTime,
                    KeyEvent.ACTION_UP, keyCode, 0, 0,
                    KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
                    KeyEvent.FLAG_SOFT_KEYBOARD));
        }

        @Override
        public boolean deleteSurroundingText(int leftLength, int rightLength) {
            // Look for one-character delete and send it as a key press.
            if (leftLength == 1 && rightLength == 0) {
                sendKeyPress(KeyEvent.KEYCODE_DEL);
            } else if (leftLength == 0 && rightLength == 1){
                sendKeyPress(KeyEvent.KEYCODE_FORWARD_DEL);
            } else if (mWebViewCore != null) {
                mWebViewCore.sendMessage(EventHub.DELETE_SURROUNDING_TEXT,
                        leftLength, rightLength);
            }
            return super.deleteSurroundingText(leftLength, rightLength);
        }
    }


    // The listener to capture global layout change event.
    private InnerGlobalLayoutListener mGlobalLayoutListener = null;

@@ -373,6 +412,8 @@ public class WebView extends AbsoluteLayout
    private final Rect mViewRectViewport = new Rect();
    private final RectF mVisibleContentRect = new RectF();
    private boolean mGLViewportEmpty = false;
    WebViewInputConnection mInputConnection = new WebViewInputConnection();


    /**
     *  Transportation object for returning WebView across thread boundaries.
@@ -4864,11 +4905,17 @@ public class WebView extends AbsoluteLayout
        }
    }

    @Override
    public boolean onCheckIsTextEditor() {
        return true;
    }

    @Override
    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
      InputConnection connection = super.onCreateInputConnection(outAttrs);
      outAttrs.imeOptions |= EditorInfo.IME_FLAG_NO_FULLSCREEN;
      return connection;
        outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_FULLSCREEN
                | EditorInfo.TYPE_CLASS_TEXT
                | EditorInfo.TYPE_TEXT_VARIATION_NORMAL;
        return mInputConnection;
    }

    /**
+19 −0
Original line number Diff line number Diff line
@@ -629,6 +629,18 @@ public final class WebViewCore {
    private native void nativeDeleteSelection(int nativeClass, int start,
            int end, int textGeneration);

    /**
     * Delete text near the cursor.
     * @param nativeClass The pointer to the native class (mNativeClass)
     * @param leftLength The number of characters to the left of the cursor to
     * delete
     * @param rightLength The number of characters to the right of the cursor
     * to delete.
     */
    private native void nativeDeleteSurroundingText(int nativeClass,
            int leftLength,
            int rightLength);

    /**
     *  Set the selection to (start, end) in the focused textfield. If start and
     *  end are out of order, swap them.
@@ -981,6 +993,8 @@ public final class WebViewCore {
        static final int SET_BACKGROUND_COLOR = 126;
        static final int SET_MOVE_FOCUS = 127;
        static final int SAVE_DOCUMENT_STATE = 128;
        static final int DELETE_SURROUNDING_TEXT = 129;


        static final int WEBKIT_DRAW = 130;
        static final int POST_URL = 132;
@@ -1512,6 +1526,11 @@ public final class WebViewCore {
                                    deleteSelectionData.mStart, deleteSelectionData.mEnd, msg.arg1);
                            break;

                        case DELETE_SURROUNDING_TEXT:
                            nativeDeleteSurroundingText(mNativeClass,
                                    msg.arg1, msg.arg2);
                            break;

                        case SET_SELECTION:
                            nativeSetSelection(mNativeClass, msg.arg1, msg.arg2);
                            break;