Closed Bug 1699417 Opened 3 years ago Closed 3 years ago

Range.getBoundingClientRect() returns wrong top/y if caret set to first char in multiline contentEditable

Categories

(Core :: DOM: Selection, defect, P3)

Firefox 87
defect

Tracking

()

RESOLVED WONTFIX
Tracking Status
firefox88 --- wontfix
firefox89 --- wontfix

People

(Reporter: mail, Unassigned)

References

(Blocks 1 open bug)

Details

(Keywords: parity-chrome)

Attachments

(2 files)

Attached file index.html

User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36

Steps to reproduce:

  1. Open attached file index.html
  2. Resize window so that the text wraps into multiple lines
  3. Open dev console by pressing F12 and switch to console
  4. Click before the first char in the first line of text
  5. top/y position logged in console is correct :)
  6. Click the before the first char in the second line
  7. top/y position is logged in console incorrect :(

Notes:

  • The problem only appears on the first character in each line. For all other characters inside the text, the positions are reported correctly.
  • The problem also appears on todays beta and nightly builds of Firefox.
  • The problem does NOT appear in latest Google Chrome or Internet Explorer 11.

Actual results:

top/y position is the same for the first char in the second line as is for the first char in the first line.

Expected results:

top/y for first char of second line should be different from first line.

It seems if setting caret to first char in second line, the position of the last char of the first line is reported. This includes x/left/y/top.

Hi,
I was able to reproduce this issue on my machine win 10x64 on the latest Nightly 88.0a1: top/y position is the same for the first char in the second line as is for the first char in the first line. I can confirm that this issue doesn't occurs on Chrome.

Status: UNCONFIRMED → NEW
Component: Untriaged → SVG
Ever confirmed: true
Product: Firefox → Core
Component: SVG → DOM: Selection

Looks like that nsRange::CollectClientRectsAndText() does not take the result of Selection::GetInterlinePosition() and always use end of line's character.
https://searchfox.org/mozilla-central/rev/4e87b5392eafe1f1d49017e76f7317b06ec0b1d8/dom/base/nsRange.cpp#2713

Kagami, could you take a look?

Severity: -- → S3
Flags: needinfo?(krosylight)
Keywords: parity-chrome
Priority: -- → P3

Sounds a bit tricky since the method should work independent from the current selection (because the range can be cloned). I guess we should add an internal caret association state for ranges to make this work. Does this sound good to you?

Flags: needinfo?(krosylight) → needinfo?(masayuki)

(In reply to Kagami :saschanaz from comment #4)

Sounds a bit tricky since the method should work independent from the current selection (because the range can be cloned). I guess we should add an internal caret association state for ranges to make this work. Does this sound good to you?

I think that it should depend on how Chrome behave. I guess that in the most cases, it's required only with nsRange::mSelection is set to non-null. But if Chrome keeps the interline position after cloning a selection range, we should follow it.

Flags: needinfo?(masayuki)

AFAICT Blink does not have a notion of "interline position". Gecko can put the selection at the end of line + next to the whitespace but Blink cannot, it only puts the caret before the whitespace. So I think we can't follow them unless we want to remove such behavior.

What this means is that each offset on Blink corresponds to a single visual position but not on Gecko.

And I think we don't want to remove that behavior since at least one word processor (MS Word) also behaves same. (The caret can be after the whitespace at the end of the line.)

Storing the caret state makes sense to me for now, since it prevents unexpected change after cloning and thus aligns better with Chrome. Does this make sense to you?

Flags: needinfo?(masayuki)

(In reply to Kagami :saschanaz from comment #6)

AFAICT Blink does not have a notion of "interline position". Gecko can put the selection at the end of line + next to the whitespace but Blink cannot, it only puts the caret before the whitespace. So I think we can't follow them unless we want to remove such behavior.

Indeed. If a line break occurs at middle of a word, the behavior is exactly same as Gecko:
https://jsfiddle.net/d_toybox/q6uy4bon/3/

So, the remaining web-compat issue is, whether after a white-space which caused a line break should be included in the previous line or next line. But your comment 7 is reasonable to keep our current behavior.

Therefore, I think that this can be closed as WONTFIX for now.

Status: NEW → RESOLVED
Closed: 3 years ago
Flags: needinfo?(masayuki)
Resolution: --- → WONTFIX

Interesting, I'm seeing slightly different behavior where the end of lines are considered as next lines (on Android right now). Maybe a good chance to file a spec issue? 🤔

Hmm, I'm really confused.

Firefox for Desktop:

  • When selection is collapsed at end of line which ends with a white-space, the position is end of the line.
  • When selection is collapsed at start of line whose previous line ends with a white-space, the position is end of the previous line.
  • When selection is collapsed at end of line which ends with a non-white-space, the position is end of the line.
  • When selection is collapsed at start of line whose previous line ends with a non-white-space, the position is end of the previous line.

Chrome for Desktop:

  • When selection is collapsed at end of line which ends with a white-space, the position is start of the next line.
  • When selection is collapsed at start of line whose previous line ends with a white-space, the position is start of the line.
  • When selection is collapsed at end of line which ends with a non-white-space, the position is end of the line.
  • When selection is collapsed at start of line whose previous line ends with a non-white-space, the position is end of the previous line.

So, the difference is, white-space which caused a line break is positioned end of the previous line or start of next line.

You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: