Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting the cursor at the start of inserted text with InputConnection.commitText

The documentation for InputConnection.commitText(CharSequence text, int newCursorPosition) says that newCursorPosition means:

int: The new cursor position around the text, in Java characters. If > 0, this is relative to the end of the text - 1; if <= 0, this is relative to the start of the text. So a value of 1 will always advance the cursor to the position after the full text being inserted. Note that this means you can't position the cursor within the text, because the editor can make modifications to the text you are providing so it is not possible to correctly specify locations there.

In this example, if I enter two characters, then position the cursor between them like this

enter image description here

and then enter another character, it doesn't matter if I set newCursorPosition to 0 or 1. The cursor is always at the end of the insertion. For example calling

inputConnection.commitText("aaa", 0);

or

inputConnection.commitText("aaa", 1);

Both show the cursor like this:

enter image description here

If I do -1 with

inputConnection.commitText("aaa", -1);

I get this

enter image description here

The 1 and -1 results are expected as per the documentation. Why doesn't 0 put the cursor at the beginning of the insertion? I would expect 0 should be like this

inputConnection.commitText("aaa", 0);

enter image description here

but it isn't. Why not?

like image 446
Suragch Avatar asked Oct 17 '22 09:10

Suragch


1 Answers

This looks like a defect in the code, but you be the judge.

Take a look at replaceText() in BaseInputConnection. I believe that this is the code that places the cursor after insertion. (replaceText() is called from commitText()).

In the referenced code, a is the selection start. b is the selection end. Since there is no selection in the example and the cursor is at index 1 then a == b == 1. Also, the new text (aaa) is not inserted (replacing a selection [a,b]) until after the cursor is moved to the new selection.

Selection.setSelection(content, newCursorPosition) sets the cursor position, so for 0 and 1 to produce identical positioning in your example, I would expect the derived value of newCursorPosition to be the same for both inputs.

With the cursor positioned between the two 8's at position 1, let's think through the following code:

if (newCursorPosition > 0) {
    newCursorPosition += b - 1;
} else {
    newCursorPosition += a;
}

For your input of 1, newCursorPosition > 0, so newCursorPosition = newCursorPosition + 1 - 1 or 1.

For your input of 0, newCursorPosition is not = 0, so newCursorPosition = newCursorPosition + a (0 + 1) or 1.

Since both inputs produce the same value, I would expect Selection.setSelection(content, newCursorPosition) to produce the results you see.

I have not followed the code exactly to this location, but I believe that this is the problem. I have followed the execution paths in BaseInputConnection for newCursorPosition = 0 and newCursorPosition = 1 on a Pixel emulator with API 21 and what is outlined above does hold.

like image 122
Cheticamp Avatar answered Oct 21 '22 07:10

Cheticamp