Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure "text boxes" preserve cursor location #15099

Merged
merged 21 commits into from
Jul 6, 2023
Merged

Ensure "text boxes" preserve cursor location #15099

merged 21 commits into from
Jul 6, 2023

Conversation

mattleibow
Copy link
Member

@mattleibow mattleibow commented May 16, 2023

Description of Change

This PR adds some tests to make sure all the platforms are consistent with regards to how the cursor position changes (or not) when text is changed.

It is just 2 small changes:

  • make sure the cursor is not updated for the same text
  • moved the duplicate tests from editor/entry into a single base test for all things - editor, entry and searchbar

There is a code change for iOS and Windows to only update selection start/length if the text has changed:

  • if nothing has changed, don't move the cursor
  • if the text is the same, then we may still be initializing a binding process
  • doing less is always better for performance

@ghost ghost added the legacy-area-controls Label, Button, CheckBox, Slider, Stepper, Switch, Picker, Entry, Editor label May 16, 2023
@mattleibow mattleibow changed the title Ensure iOS "text boxes" preserve cursor location Ensure "text boxes" preserve cursor location May 16, 2023
Comment on lines 95 to 131
[Theory]
[InlineData(2)]
public async Task CursorPositionInitializesCorrectlyWithUpdateCursorPositionLast(int initialPosition)
{
var entry = new TView
{
Text = "This is TEXT!",
CursorPosition = initialPosition
};

var value = await GetValueAsync<int, THandler>(entry, handler =>
{
handler.UpdateValue(nameof(ITextInput.CursorPosition));
return GetPlatformCursorPosition(handler);
});

Assert.Equal(initialPosition, value);
}

[Theory]
[InlineData(2)]
public async Task CursorPositionInitializesCorrectlyWithUpdateTextLast(int initialPosition)
{
var entry = new TView
{
Text = "This is TEXT!",
CursorPosition = initialPosition
};

var value = await GetValueAsync<int, THandler>(entry, handler =>
{
handler.UpdateValue(nameof(ITextInput.Text));
return GetPlatformCursorPosition(handler);
});

Assert.Equal(initialPosition, value);
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These 2 tests cause failures depending on the order of properties in the mapper table. Currently if Text is first, then it is passing, but if it happens to have Text after the CursorPosition (which will be the case in my other PRs because I am fixing the mappers) then it fails.


platformControl.Select(cursorPosition, 0);
platformControl.Select(cursorPosition, 0);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the change for Windows.

textView.Text = newText;

textView.SetTextRange(cursorPosition, 0);
textView.SetTextRange(cursorPosition, 0);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the change for iOS.

@mattleibow mattleibow requested a review from PureWeen May 17, 2023 06:34
@rmarinho
Copy link
Member

@mattleibow can you see if it helps with this issue. #11512 ?

@mattleibow
Copy link
Member Author

@rmarinho this does not seem to make any difference. I think your conclusions on the other issue are correct, so maybe we need to do less of something so the code that runs in the events actually stick.

@rmarinho
Copy link
Member

/rebase

@rachelkang rachelkang self-requested a review June 8, 2023 15:02
Copy link
Member

@rachelkang rachelkang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UPDATE: After some offline discussion, we learned this PR isn't exactly meant to modify the behavior I annotated below, although it is still useful context to have.


I tested some of the different scenarios on Windows and Android via keyboard tab / shift+tab navigation. Here's what I'm seeing on this PR branch at this point in time:

Scenario Behavior
1. Entry/Editor blank with text updated after Cursor position remains wherever it was left last. The platform "remembers" wherever it is, even if the cursor is in the middle of a word.
2a. Entry/Editor with pre-filled text Cursor position remains at the beginning of the input field.
2b. 2a with text updated after Same as 1
3a. Entry/Editor with pre-filled text via binding Same as 2a
3b. 3a with text updated after Same as 1

Interestingly, the behavior on Windows and Android was exactly the same for all of the scenarios. Shift+Tab didn't appear to work on Android emulator for me though (unclear why, as I do think it was working before and/or on device, but anyhow, that's a separate issue).

This behavior is also exactly the same on main, so it doesn't seem that keyboard focus was affected by the work you've done so far on this PR.

Based on what I'm seeing here, my thinking is that we should update so that for scenarios 2a and 3a, cursor position is at the END of the text in input field.

Copy link
Member

@rachelkang rachelkang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM on Windows!

need to test on iOS still, and left a couple comments

Copy link
Contributor

@hartez hartez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, couple of minor change requests.

@rachelkang
Copy link
Member

rachelkang commented Jul 6, 2023

UPDATE: After some offline discussion, we learned this PR isn't exactly meant to modify the behavior I annotated below, although it is still useful context to have.

I tested some of the different scenarios on Windows and Android via keyboard tab / shift+tab navigation. Here's what I'm seeing on this PR branch at this point in time:

Scenario Behavior

  1. Entry/Editor blank with text updated after Cursor position remains wherever it was left last. The platform "remembers" wherever it is, even if the cursor is in the middle of a word.
    2a. Entry/Editor with pre-filled text Cursor position remains at the beginning of the input field.
    2b. 2a with text updated after Same as 1
    3a. Entry/Editor with pre-filled text via binding Same as 2a
    3b. 3a with text updated after Same as 1
    Interestingly, the behavior on Windows and Android was exactly the same for all of the scenarios. Shift+Tab didn't appear to work on Android emulator for me though (unclear why, as I do think it was working before and/or on device, but anyhow, that's a separate issue).

This behavior is also exactly the same on main, so it doesn't seem that keyboard focus was affected by the work you've done so far on this PR.

Based on what I'm seeing here, my thinking is that we should update so that for scenarios 2a and 3a, cursor position is at the END of the text in input field.

Updating table to record my findings on macios:

Scenario WinUI/Android Mac iOS
1. Entry/Editor blank with text updated after Cursor position remains wherever it was left last. The platform "remembers" wherever it is, even if the cursor is in the middle of a word. same as WinUI/Android, but Keyboard tab nav doesn't work unless VO is on or keyboard navigation setting is enabled, and tabbing away from an Editor doesn't seem feasible? (creates a tab space in the actual input) With VO+double tap, cursor always jumps to the end? Double tapping toggles between cursor beginning and end position. With keyboard, position is always at the end and doesn't remember changes for Entry, but position starts at the beginning and then remembers changes for Editor
2a. Entry/Editor with pre-filled text Cursor position remains at the beginning of the input field. same as WinUI/Android same as 1
2b. 2a with text updated after Same as 1 Same as 1 Same as 1
3a. Entry/Editor with pre-filled text via binding Same as 2a not tested not tested
3b. 3a with text updated after Same as 1 not tested not tested

Copy link
Member

@rachelkang rachelkang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested on mac, iOS as well and LGTM!

(There are some behavior quirks, but no new quirks. We should definitely investigate more in the future, but that's outside the scope of what this PR aims to do).

Left a nitpick comment on a var name, but approving as all else LGTM!

textField.Text = newText;
{
// Re-calculate the cursor offset position if the text was modified by a Converter.
// but if the text is being set by code, let's just move the cursor to the end.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should reevaluate this behavior in the future as it's inconsistent with Windows and Android. And we should check to see if it's consistent with iOS platform behavior, as it seems like it might not be. Could you log an issue to capture this, or update existing related issue?

where TType : IView, new()
where THandler : class, IPlatformViewHandler, IElementHandler, new()
{
Func<THandler, Task> boop = (handler) =>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: can we rename boop to be more descriptive :p

@hartez hartez enabled auto-merge (squash) July 6, 2023 18:30
@hartez hartez merged commit 0504ca2 into main Jul 6, 2023
@hartez hartez deleted the dev/ios-text branch July 6, 2023 18:30
@github-actions github-actions bot locked and limited conversation to collaborators Dec 10, 2023
@Eilon Eilon removed the legacy-area-controls Label, Button, CheckBox, Slider, Stepper, Switch, Picker, Entry, Editor label May 10, 2024
@samhouts samhouts added the fixed-in-8.0.0-preview.7.8842 Look for this fix in 8.0.0-preview.7.8842! label Aug 2, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-controls-entry Entry fixed-in-8.0.0-preview.7.8842 Look for this fix in 8.0.0-preview.7.8842!
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants