Caret shows inside character after push key space




2 years ago
a year ago


(Reporter: piotrazsko, Unassigned)


(Blocks: 1 bug, {testcase})

50 Branch

Firefox Tracking Flags

(Not tracked)




(1 attachment)



2 years ago
Created attachment 8818496 [details]
1. FF space.mp4

User Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0
Build ID: 20161213004019

Steps to reproduce:

1.create contenteditable node
2.add 2 childnodes
3.set styles to node:display:inline-block
4.set caret to end first node
5.push space key

Actual results:

Caret  shows inside character.

Expected results:

Caret shows inside first node


2 years ago
Component: Untriaged → Editor
Product: Firefox → Core

Comment 1

2 years ago
Could you provide the Codepen testcase, please.
Flags: needinfo?(piotrazsko)
Keywords: testcase-wanted

Comment 2

2 years ago
(In reply to Loic from comment #1)
> Could you provide the Codepen testcase, please.
(set caret between words and push space)

Comment 3

2 years ago
(In reply to Loic from comment #1)
> Could you provide the Codepen testcase, please.



2 years ago
Keywords: testcase-wanted → testcase
Ever confirmed: true
Flags: needinfo?(piotrazsko)
Priority: -- → P3
Blocks: 1341152
Simple test-case:

data:text/html,<!doctype html>
<div contenteditable>
<span style="display:inline-block">a</span
><span style="display:inline-block">b</span>

Position the cursor before the letter "a", then hit right arrow, then space.  No space visibly appears, and the cursor winds up floating inside the letter "b".

What's happening here is that we do insert the space inside the first <span> as expected.  This is a trailing space in a block, so it should collapse per CSS rules:

data:text/html,<!doctype html>
<span style="display:inline-block">a </span
><span style="display:inline-block">b</span>

No space in Firefox or Chrome.  But in Firefox, contenteditable has special magic handling of trailing whitespace, which makes the space appear so that you can see you typed something.  But that magic seems not to expand the inline-block's width, so the cursor appears one space to the right of the "a", but the "b" doesn't get pushed over correspondingly.

In Chrome, according to their developer tools, it looks like it just inserts nbsp instead of a space.  If you insert multiple spaces in a row, it becomes a sequence of nbsp and regular space, like

  &nbsp; &nbsp;
  &nbsp; &nbsp;&nbsp;
  &nbsp; &nbsp; &nbsp;

etc.  We also insert actual &nbsp;'s in some cases -- for instance, if you hit space twice here, the first one becomes an &nbsp;, so it stretches the block as expected (but by one space instead of two).  This entire situation is pretty terrible, as explained in detail in the note here:

And the comment here (click "View comments" at the right to expand):

The least bad solution is probably just to insert an nbsp instead of a space, like Chrome.  The problem is my notes say they have magic for nbsp handling in contenteditable, which we probably don't.  In particular, if the cursor is near the end of the line, hitting space should go to the beginning of the next line, and if we insert an nbsp we'll bring the last letter along with us, like:
  a b c d e|
  a b c d  
  e |
instead of
  a b c d e
where | is the cursor.

Chrome cheats here because they just wrap at &nbsp; in contenteditable:

data:text/html,<!doctype html>
<div contenteditable style="width:20px;border:1px solid black">a&nbsp;&nbsp;b</div>

(Remove "contenteditable" and it matches us.)  So they don't have this problem, or rather it's not evident until the page ceases to be editable, at which point it's not so noticeable.

Masayuki, what do you think we should do here?  If we want to match Chrome exactly, we're going to need to start breaking lines at nbsp in contenteditable, which is pretty sad, but I really don't know of any better solution.  I guess the alternative is to fix our own magic space handling in contenteditable so it properly expands the block width here.  I don't know how to do either of these things.
Flags: needinfo?(masayuki)
Honestly, I have no idea. However, I don't like the &nbsp; hack of Chromium because it really can cause unexpected results like you mentioned.

I believe that the ideal solution is, ASCII whitespaces should be treated as characters like usual text editors. So, they should be neither collapsed nor omitted at end of lines. However, this also could cause different result than non-contenteditable rendering result. E.g., if a richtext editor can be modified with a button which toggles contenteditable attribute. Then, removing contenteditable attribute by pressing the button may cause changing the layout. But I guess that this is the least unexpected behavior of approaches.

So, perhaps, nsTextFrame should treat whitespaces as preformated when the content is editable. Although, I don't know how layout module people think about this issue.

Or, just for now, the invisible whitespace width shouldn't be added to decide the caret position.
Flags: needinfo?(masayuki)
We already do emit &nbsp; in many cases, just not in this one.  I think it would be a bad regression to stop doing this, because then the editor wouldn't be WYSIWYG anymore.  You'd see many spaces in a row when editing, then they would disappear when you saved.
I didn't mention about the case of preceding whitespaces since the conversion is actually required for making same visual result between editable contents and static contents.
You need to log in before you can comment on or make changes to this bug.