Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Conversation

@justinmc
Copy link
Contributor

@justinmc justinmc commented Mar 31, 2020

I noticed a similar PR (#8956) that got backspace to work with grapheme clusters, and I thought we could take the same approach to fix dpad movement through grapheme clusters.

Before After

Probably just a partial solution for: flutter/flutter#13404
Potentially solves: flutter/flutter#52167

@justinmc
Copy link
Contributor Author

This needs a test of its own, but it's breaking a bunch of existing tests. I think this PR is fine but the tests can't handle calls to Selection.extendRight etc.

@justinmc
Copy link
Contributor Author

My workstation is offline and I'm having a hard time running these tests without it. I'll follow up once I get that powered on.

@justinmc
Copy link
Contributor Author

@GaryQian Any idea how I can fix these tests? The Selection.extend... and Selection.move... methods seem to do totally crazy stuff in tests, but not in an actual app. I think the code in this PR is correct, but the tests can't verify that it's correct.

I encountered the same problem in #15560 and worked around it, but I'm not seeing a way to work around it here. I tried all kinds of different ways to check that any telling method was called using mocks or spies, but I couldn't get anything that worked. Let me know if something jumps out at you.

@GaryQian
Copy link
Contributor

Strange test behavior of the extend methods were also reported when working on #17393. I am not sure what is causing this.

There may be some value in looking at using the TextKeyListener as used in the above PR? This listener seems to perform many of the operations we are trying to do here and also multiplexes out to different sub-class listeners for handling of different keyboard types.

@DeMonkeyCoder
Copy link
Contributor

DeMonkeyCoder commented Apr 21, 2020

@GaryQian Actually I couldn't run tests even on a clean engine build without my PR. The problem was caused by extendLeft and extendRight because they were setting the cursor position at the most left or right position in test files. I don't know why but I guess not using actual layouts was causing the problem

Using extendRight and extendLeft is not a good idea because they have bugs with RTL as mentioned in #17393. @justinmc

@justinmc
Copy link
Contributor Author

I tried using TextKeyListener like in the PR by @alimahdiyar, but it seems it can't handle dpad events. onKeyDown just returns false for dpad events.

If it's not possible to use Selection's move/extends/Left/Right because it's buggy, then is there any other way to do this? Maybe manually detect grapheme clusters. I'm going to close this PR if no one has any other ideas.

@DeMonkeyCoder
Copy link
Contributor

DeMonkeyCoder commented Apr 23, 2020

Give me a day or two. I'm currently busy with fixing my system.
But I have some ideas for handling this.

@justinmc
Copy link
Contributor Author

Sounds good, thanks and let me know.

@DeMonkeyCoder
Copy link
Contributor

DeMonkeyCoder commented Apr 24, 2020

Implementation for DPAD movement is not in TextKeyListener subclasses and I think this is why you get false.
https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/text/method/TextKeyListener.java#222
This one is the one I think should handle DPAD movement which is using extendLeft
https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/text/method/ArrowKeyMovementMethod.java#69
I'm currently reading source code for handling last glyph and working on a clean PR.

@DeMonkeyCoder
Copy link
Contributor

DeMonkeyCoder commented Apr 26, 2020

I wrote a funciton to get left offset in #17960
However, I wasn't able to use it here.

if (selStart == selEnd && !event.isShiftPressed()) {
    int newSel = getOffsetBefore(selStart);
    setSelection(newSel, newSel);
}

this code snippet was setting the newSel correctly but setSelection was still setting the selection point to selStart - 1. I don't know why

@justinmc
Copy link
Contributor Author

justinmc commented Apr 28, 2020

Seems like I can't use things like Selection.extendLeft based on the conversation above, but getOffsetBefore would solve this problem for me. I'll keep my eye on #17960 and hope to use it here when it's merged.

Edit: I missed your point about it not working when you tried it, hmm. Anyway, I'll give it a shot if that PR moves forward.

@DeMonkeyCoder
Copy link
Contributor

The PR I was working on is merged. textUtils.getOffsetBefore is what we need here.

@justinmc
Copy link
Contributor Author

@alimahdiyar It seems to work! Sorry it took me awhile to get back to this. The left key is working as of e2c2e86 but now I've got to write something like getOffsetAfter for the right key.

@DeMonkeyCoder
Copy link
Contributor

DeMonkeyCoder commented Jun 12, 2020

I figured out that moving forward is handled differently in the android source code. I don't know whether text painting stuff can help in implementing getOffsetAfter here in flutter or not
https://android.googlesource.com/platform/frameworks/base/+/android10-c2f2-release/core/java/android/text/method/BaseKeyListener.java#306

@justinmc
Copy link
Contributor Author

I think it's not going to be possible to use Android's current approach for getOffsetAfter. The inner workings like getTextRunCursor were only added in API 29. I looked into reimplementing that, but ran into lots of private stuff that's not going to be easy to just copy over.

I'm going to try to implementing getOffsetAfter in a similar way to getOffsetBefore instead.

@justinmc justinmc force-pushed the dpad-grapheme branch 2 times, most recently from 532b7d9 to f873780 Compare July 1, 2020 21:49
@justinmc
Copy link
Contributor Author

justinmc commented Jul 1, 2020

@GaryQian @alimahdiyar Ready for re-review.

I managed to port over getOffsetBefore to a new getOffsetAfter method. It appears to work with my manual testing and it passes the existing test cases, but I'm missing a lot of the context on these niche unicode characters. I mostly wrote this by basing it on the tests, so let me know if you see anything I've missed or any opportunities to clean up and deduplicate the code.

@nturgut
Copy link
Contributor

nturgut commented Jul 6, 2020

Hi, if the PR fails on Mac Web Engine, can you please rebase to the head? The reference in this file should be up to date: https://github.com/flutter/engine/blob/master/lib/web_ui/pubspec.yaml#L30

@justinmc
Copy link
Contributor Author

justinmc commented Jul 6, 2020

@nturgut Thanks for the heads up! It did fail, so I've updated to master.

@DeMonkeyCoder
Copy link
Contributor

DeMonkeyCoder commented Jul 7, 2020

@justinmc Yes, I was using physical keyboard for the emulator. But I added some logs there and it seems that function was triggered even on physical keyboard's keypress.

assertEquals(Selection.getSelectionStart(editable), 4);
didConsume = adaptor.sendKeyEvent(downKeyDown);
assertTrue(didConsume);
assertEquals(Selection.getSelectionStart(editable), 8);
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it's good to add another situation for this test such that if we are in offset 6, then the right key should bring us to offset 8.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good call. Added in 1c5df01.

@justinmc
Copy link
Contributor Author

justinmc commented Jul 8, 2020

@alimahdiyar I tried adding log statements and using the physical keyboard arrow keys as well, and I also saw that the logs were called. However, the behavior appears different. It might be affected by some code in the framework, which I think I remember seeing at some point.

I'm going to merge this PR if it passes and plan to follow up in another PR if there are smaller bugs. Let me know if you see anything specific.

@justinmc
Copy link
Contributor Author

justinmc commented Jul 8, 2020

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants