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

[SuperEditor][Mobile] Fix caret position after rotation (Resolves #2056) #2057

Merged
merged 11 commits into from
Jun 7, 2024

Conversation

angelosilvestre
Copy link
Collaborator

[SuperEditor][Mobile] Fix caret position after rotation. Resolves #2056

On mobile, rotating the phone is causing the caret to be displayed at the wrong position:

cursor_position.mov

This was caused by #1967

We are accessing the layer's RenderBox to get the size, to be able to adjust the caret for situations where the caret is pushed off-screen.

The issue is that, at the point in the pipeline, the layer hasn't been laid out yet for the current frame.

To fix the issue, I changed it to get the width from the content's RenderBox instead of the layer's RenderBox. Since both should always be the same size, this shouldn't be an issue.

We have tests for caret position after phone rotation, but I'm not sure yet why these tests didn't catch this issue. Maybe it's related to the text used in those tests...

Also, it seems that when rotating from landscape to portrait, this issue doesn't happen. It only seems to happen when rotating from portrait to landscape.

@angelosilvestre
Copy link
Collaborator Author

@matthew-carroll I had to set the golden tests to be ignored for Android, it seems a failure caused by some anti-aliasing. I already filed #1996 to see what we can do.

@angelosilvestre
Copy link
Collaborator Author

@knopp Could you please try this PR?

@knopp
Copy link
Contributor

knopp commented May 29, 2024

I tested it and it fixes the issue.

@@ -353,6 +361,12 @@ class AndroidControlsDocumentLayerState
}
}

@override
DocumentSelectionLayout? computeLayoutDataWithDocumentLayout(BuildContext context, DocumentLayout documentLayout) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a reason that this method now needs to be implemented when it wasn't before?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Previously, all the implementation was already in the computeLayoutDataWithDocumentLayout method. But now that we need to access the content's RenderBox I switched to use computeLayoutData directly.

Now we don't need computeLayoutDataWithDocumentLayout, but since it doesn't have a default implementation in the superclass, we need to implement it...

@@ -321,13 +327,15 @@ class AndroidControlsDocumentLayerState
// Default caret width used by the Android caret.
const caretWidth = 2;

final layerBox = context.findRenderObject() as RenderBox?;
if (layerBox != null && layerBox.hasSize && caretRect.left + caretWidth >= layerBox.size.width) {
// Use the content's RenderBox instead of the layer's RenderBox, because at this point, the layer
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you explain this? I'm not sure I understand what this is saying, or why it's the case...

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Updated the comment.

@@ -192,3 +292,22 @@ Future<void> _pumpCaretTestApp(WidgetTester tester) async {
],
).pump();
}

Future<TestDocumentContext> _pumpPhoneRotationTestApp(WidgetTester tester) async {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you add a comment for when/how this is meant to be used? Typically pumping is a thing that happens initially, so the idea of pumping for rotation isn't immediately obvious without further instructions.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I changed the name to make it simpler. This method has just the initial pump, I added the phoneRotation just to clarify in which kind of test this is used.

import 'package:golden_toolkit/golden_toolkit.dart';
import 'package:super_editor/super_editor.dart';
import 'package:super_editor/super_editor_test.dart';

import '../../test/super_editor/supereditor_test_tools.dart';
import '../test_tools_goldens.dart';

void main() {
Future<void> main() async {
await loadAppFonts();
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this loadAppFonts() going to impact tests that are run in other files after this one?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It shouldn't. If we don't specify a style rule with the font family we will still use Ahem.

Copy link
Contributor

Choose a reason for hiding this comment

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

Can you verify that? I was just doing some golden work in swift_ui and if I call loadAppFonts() from the test config, I get regular fonts in the goldens. The only difference between calling loadAppFonts() from the test config vs calling it from a specific test file is that some tests might run before the test file and won't be impacted. But I'm worried about any tests that run after the given test file.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It can impact if other files specify the font family. Once we load the fonts, it seems we cannot unload them.

Copy link
Contributor

Choose a reason for hiding this comment

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

Then should we move this into the global test config to avoid burying it in a single file?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It seems our global test config already has that, so we don't need to add it in this file. Removed.

Copy link
Contributor

@matthew-carroll matthew-carroll left a comment

Choose a reason for hiding this comment

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

LGTM

@matthew-carroll matthew-carroll merged commit a212a35 into main Jun 7, 2024
11 checks passed
@matthew-carroll matthew-carroll deleted the 2056_mobile-caret-rotation branch June 7, 2024 02:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Cursor at wrong position after portrait to landscape rotation
3 participants