8380935: TextFieldSkin caret width calculation is broken#2128
8380935: TextFieldSkin caret width calculation is broken#2128crschnick wants to merge 4 commits intoopenjdk:masterfrom
Conversation
|
👋 Welcome back crschnick! A progress list of the required criteria for merging this PR into |
|
❗ This change is not yet ready to be integrated. |
Webrevs
|
|
/reviewers 2 |
|
@andy-goryachev-oracle |
|
Looks like a number of tests is currently failing. Also, could you add a unit test specifically for this fix? |
| } else if (caretPath.getElements().size() == 4) { | ||
| // The caret is split. Ignore and keep the previous width value. | ||
| } else { | ||
| caretWidth = Math.round(caretPath.getLayoutBounds().getWidth()); |
There was a problem hiding this comment.
I'm confused, isn't this effectively dead code?
if (!4) { .. } elseif (4) { .. } else { when do we come here? }
There was a problem hiding this comment.
Yes, it was. But it shouldn't have been
There was a problem hiding this comment.
Thanks for confirming. Yeah agree, that looks wrong.
There was a problem hiding this comment.
Looking at the code review for the commit that caused this, that is a perfect example of how diffs can mislead. The fact that it introduced dead code was not visible from the diffs, only if you looked at the whole context.
There was a problem hiding this comment.
And I even made a (IMO good) suggestion to improve the if condition 🙂
-> I made this comment because I felt like the if-else condition is confusing. So turns out, it is.
I would therefore recommend to improve it now and remove the else block. It is empty anyway.
There was a problem hiding this comment.
I think it's out of scope for this PR, for several reasons.
This code relies on current, undocumented behavior of the caret shape being either a single line or two lines encoded as MoveTo-LineTo pairs. There are plans to change the caret shape for certain BIDI/RTL scenarios to indicate the direction, so the old assumptions might not hold anymore.
Also, in jfx25 we've added LayoutInfo/CaretInfo APIs in the Text and TextFlow, which should provide the caret information without relying on implementation details.
related umbrellas:
https://bugs.openjdk.org/browse/JDK-8343557
https://bugs.openjdk.org/browse/JDK-8300569
There was a problem hiding this comment.
There are plans to change the caret shape for certain BIDI/RTL scenarios to indicate the direction, so the old assumptions might not hold anymore.
When that happens, this code of course need to be adjusted. But they will probably require more code changes.
In any case, the empty else if block does not make sense
There was a problem hiding this comment.
This is an area of constant disagreement: I think it's ok to have minor cleanup like this one here, while @kevinrushforth much prefers to keep the PR focused on the fix and create a separate follow-up tickets when required, the rationale being backporting and merge conflicts. Piling up unrelated changes also delays the fix.
There was a problem hiding this comment.
I think the newest version looks very good and should still be easy to e.g. backport. And is now more clear, with variables that express the purpose (which makes comments obsolete, good!).
|
I think the tests are wrong. I looked at the logic for the caret at and if I understand it correctly, if the caret is fully to the left, the text should be shifted by caretWidth / 2. The tests assume that the text is not shifted in this case, which I don't think is accurate. If that would be the case, then the caret would be invisible |
| * The caret pos is invalid in this case, | ||
| * hence it should be updated when caret path size is not 4 */ | ||
|
|
||
| if (caretPath.getElements().size() != 0) { |
There was a problem hiding this comment.
!caretPath.getElements().isEmpty()
There was a problem hiding this comment.
I refactored it to make it easier to understand what the condition is checking now
|
Reviewers: @andy-goryachev-oracle |
andy-goryachev-oracle
left a comment
There was a problem hiding this comment.
Looks like the problem is fixed on macOS, but it should be tested on Windows at fractional scales (I suspect the fix is not exactly right for fractional scales).
Also, it would help to provide a bit more information about the fix in the PR description (explain the change).
| * hence it should be updated when caret path size is not 4 */ | ||
|
|
||
| if (caretPath.getElements().size() != 0) { | ||
| caretWidth = Math.round(caretPath.getLayoutBounds().getWidth()); |
There was a problem hiding this comment.
I wonder if this should be Region.snapSizeX() instead of Math.round():
not only Math.round() may round downward, but also produce mid-pixel results on systems with fractional scale.
Can you double check it on Windows at fractional scales (125%, 150%, 175%, 225%)?
There was a problem hiding this comment.
Since caretWidth is not directly used here, but rather in other code to calculate the translation or related, it is very likely fine here, but the target values in the other calculations may need to be snapped.
There was a problem hiding this comment.
The caretWidth value is included in various calculations, and the results of those are snapped. So I think this works correctly. This PR just restores the old behaviour before it was broken.
I will check on Windows for various scales
There was a problem hiding this comment.
Ok so Andy was right, the caret is sometimes still hidden on the right on different display scales. But even snapping the caret width does not always fix it. It requires a bigger fix for the skin in general.
However, I would argue that this is a different issue unrelated to this. I could open a follow-up to make the TextFieldSkin handle the display scale properly
There was a problem hiding this comment.
+1 for a follow up. I think not all final values that are later set in the translate etc. are snapped as of now. So we probably need to catch all locations at once.
There was a problem hiding this comment.
Do I understand you correctly - the issue is still seen with the fix at fractional scales? If so, then it would make sense to fix it in this PR.
There was a problem hiding this comment.
Yes, the issue of the missing caret still exists at some fractional scales. However, I would say that this is a separate issue, more general to the whole skin implementation.
So there are two issues here, which cause the same problem in some scenarios, but the causes and potential fixes don't really have a lot to do with each other. This one just repairs a small part that was broken during and earlier PR. To fix the caret issue on fractional scales, that would require a more investigation.
The JBS issue focuses on the broken caret width calculation, not the missing caret behavior so I think splitting this up into a separate issue makes more sense
| } else if (caretPath.getElements().size() == 4) { | ||
| // The caret is split. Ignore and keep the previous width value. | ||
| } else { | ||
| caretWidth = Math.round(caretPath.getLayoutBounds().getWidth()); |
There was a problem hiding this comment.
I think it's out of scope for this PR, for several reasons.
This code relies on current, undocumented behavior of the caret shape being either a single line or two lines encoded as MoveTo-LineTo pairs. There are plans to change the caret shape for certain BIDI/RTL scenarios to indicate the direction, so the old assumptions might not hold anymore.
Also, in jfx25 we've added LayoutInfo/CaretInfo APIs in the Text and TextFlow, which should provide the caret information without relying on implementation details.
related umbrellas:
https://bugs.openjdk.org/browse/JDK-8343557
https://bugs.openjdk.org/browse/JDK-8300569
|
How would you propose to test this, from the user perspective? |
|
The caret shows on non-fractional display scales, which is already better than before. The user can test this. In the other cases where it still doesn't show, that is not due to this fix being wrong, but due to a completely separate issue of how the skin is implemented. That can be implemented in another, more large-scale issue. There are probably more issues caused by the skin not properly snapping values than just the caret not showing if you go looking for them at fractional scales. |
This fixes a regression caused by the fix for https://bugs.openjdk.org/browse/JDK-8282290. The old if else block was broken by the other PR, which caused the calculation for the caret width to be never run.
Progress
Issue
Reviewing
Using
gitCheckout this PR locally:
$ git fetch https://git.openjdk.org/jfx.git pull/2128/head:pull/2128$ git checkout pull/2128Update a local copy of the PR:
$ git checkout pull/2128$ git pull https://git.openjdk.org/jfx.git pull/2128/headUsing Skara CLI tools
Checkout this PR locally:
$ git pr checkout 2128View PR using the GUI difftool:
$ git pr show -t 2128Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jfx/pull/2128.diff
Using Webrev
Link to Webrev Comment