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

Commit 4de04795 authored by Yohei Yukawa's avatar Yohei Yukawa
Browse files

Return the cursor position in screen coordinates

From its beginning, InputMethodService#onUpdateCursor has
provided the cursor position in local coordinates in the attached
view. However, the local coordinates is not useful for IMEs
to render a floating UI near the cursor because the IME is not
able to know the origin of the attached view.

With this CL, CURSOR_ANCHOR_MONITOR_MODE_CURSOR_RECT also means
that the IME will receive the cursor position in screen
coordinates. Because this is a new constant in the next release,
conditionally changing the coordinates never causes
compatibility issues as long as its behavior is well documented.

BUG: 14323360
Change-Id: I3acf2317ae1d763d11dae5ef73c2a1348b377c71
parent 250bb6e3
Loading
Loading
Loading
Loading
+7 −4
Original line number Diff line number Diff line
@@ -255,7 +255,8 @@ public class InputMethodService extends AbstractInputMethodService {
    public static final int CURSOR_ANCHOR_MONITOR_MODE_NONE = 0x0;

    /**
     * The IME expects that {@link #onUpdateCursor(Rect)} is called back.
     * The IME will receive {@link #onUpdateCursor(Rect)} called back with the current
     * cursor rectangle in screen coordinates.
     */
    public static final int CURSOR_ANCHOR_MONITOR_MODE_CURSOR_RECT = 0x1;

@@ -1703,9 +1704,11 @@ public class InputMethodService extends AbstractInputMethodService {
    }

    /**
     * Called when the application has reported a new location of its text
     * cursor.  This is only called if explicitly requested by the input method.
     * The default implementation does nothing.
     * Called when the application has reported a new location of its text cursor.  This is only
     * called if explicitly requested by the input method.  The default implementation does nothing.
     * @param newCursor The new cursor position, in screen coordinates if the input method calls
     * {@link #setCursorAnchorMonitorMode} with {@link #CURSOR_ANCHOR_MONITOR_MODE_CURSOR_RECT}.
     * Otherwise, this is in local coordinates.
     */
    public void onUpdateCursor(Rect newCursor) {
        // Intentionally empty
+25 −4
Original line number Diff line number Diff line
@@ -317,6 +317,10 @@ public final class InputMethodManager {
    int mCursorSelEnd;
    int mCursorCandStart;
    int mCursorCandEnd;
    /**
     * The buffer to retrieve the view location in screen coordinates in {@link #updateCursor}.
     */
    private final int[] mViewTopLeft = new int[2];

    // -----------------------------------------------------------
    
@@ -1487,9 +1491,23 @@ public final class InputMethodManager {
            return false;
        }
        synchronized (mH) {
            return mCursorAnchorMonitorMode ==
                    InputMethodService.CURSOR_ANCHOR_MONITOR_MODE_CURSOR_RECT;
            return (mCursorAnchorMonitorMode &
                    InputMethodService.CURSOR_ANCHOR_MONITOR_MODE_CURSOR_RECT) != 0;
        }
    }

    /**
     * Returns true if the current input method wants to receive the cursor rectangle in
     * screen coordinates rather than local coordinates in the attached view.
     *
     * @hide
     */
    public boolean usesScreenCoordinatesForCursorLocked() {
        // {@link InputMethodService#CURSOR_ANCHOR_MONITOR_MODE_CURSOR_RECT} also means
        // that {@link InputMethodService#onUpdateCursor} should provide the cursor rectangle
        // in screen coordinates rather than local coordinates.
        return (mCursorAnchorMonitorMode &
                InputMethodService.CURSOR_ANCHOR_MONITOR_MODE_CURSOR_RECT) != 0;
    }

    /**
@@ -1518,15 +1536,18 @@ public final class InputMethodManager {
                    || mCurrentTextBoxAttribute == null || mCurMethod == null) {
                return;
            }
            
            mTmpCursorRect.set(left, top, right, bottom);
            if (!mCursorRect.equals(mTmpCursorRect)) {
                if (DEBUG) Log.d(TAG, "updateCursor");

                try {
                    if (DEBUG) Log.v(TAG, "CURSOR CHANGE: " + mCurMethod);
                    mCurMethod.updateCursor(mTmpCursorRect);
                    mCursorRect.set(mTmpCursorRect);
                    if (usesScreenCoordinatesForCursorLocked()) {
                        view.getLocationOnScreen(mViewTopLeft);
                        mTmpCursorRect.offset(mViewTopLeft[0], mViewTopLeft[1]);
                    }
                    mCurMethod.updateCursor(mTmpCursorRect);
                } catch (RemoteException e) {
                    Log.w(TAG, "IME died: " + mCurId, e);
                }