Closed
Bug 344423
Opened 18 years ago
Closed 18 years ago
[Will|Did]DeleteSelection startOffset off by 1 for backspace in plain text editing
Categories
(Core :: DOM: Editor, defect)
Tracking
()
RESOLVED
FIXED
People
(Reporter: aaronlev, Assigned: aaronlev)
References
Details
(Keywords: access)
Attachments
(2 files, 8 obsolete files)
7.54 KB,
patch
|
uriber
:
review+
ginnchen+exoracle
:
review+
roc
:
superreview+
|
Details | Diff | Splinter Review |
861 bytes,
patch
|
aaronlev
:
review+
jag+mozilla
:
superreview+
|
Details | Diff | Splinter Review |
WillDeleteText(nsISelection *aSelection) is our notification for html input and XUL textbox for text deletions.
Two problems:
When backspace or delete is pressed the startOffset and endOffset are the same, when the endOffset should show that a char is being deleted. We can work around that problem.
The bigger problem is that the startOffset is too high, off by 1.
Assignee | ||
Updated•18 years ago
|
Summary: WillDeleteSelection provides incorrect info for backspace → WillDeleteSelection startOffset off by 1 for backspace
Assignee | ||
Updated•18 years ago
|
Summary: WillDeleteSelection startOffset off by 1 for backspace → [Will|Did]DeleteSelection startOffset off by 1 for backspace
Assignee | ||
Comment 1•18 years ago
|
||
The problem is StartBatchChanges
(http://lxr.mozilla.org/seamonkey/source/layout/generic/nsSelection.cpp#2826)
When EndBatchChanges() is finally called, the selection is updated. However, [Will|Did]DeleteSelection both get called before that, and it still thinks the selection is to the right of the character to be deleted.
Assignee | ||
Comment 2•18 years ago
|
||
Mats, do you have any ideas?
Assignee | ||
Comment 3•18 years ago
|
||
I'm not sure, but I think this means we can remove some ePrevious handling for the collapsed action in nsTextEditRules::WillDeleteSelection.
Incidentally, the bug only occurs for plain text editing, not for HTML.
Assignee | ||
Updated•18 years ago
|
Summary: [Will|Did]DeleteSelection startOffset off by 1 for backspace → [Will|Did]DeleteSelection startOffset off by 1 for backspace in plain text editing
Assignee | ||
Comment 4•18 years ago
|
||
This fixes bug 260921
Assignee | ||
Comment 5•18 years ago
|
||
Attachment #232065 -
Attachment is obsolete: true
Assignee | ||
Comment 6•18 years ago
|
||
Attachment #232068 -
Attachment is obsolete: true
Assignee | ||
Comment 7•18 years ago
|
||
Assignee: nobody → aaronleventhal
Attachment #232077 -
Attachment is obsolete: true
Status: NEW → ASSIGNED
Attachment #232123 -
Flags: review?(uriber)
Assignee | ||
Comment 8•18 years ago
|
||
Attachment #232137 -
Flags: review?(mats.palmgren)
Assignee | ||
Updated•18 years ago
|
Attachment #232137 -
Flags: review?(mats.palmgren) → review?(uriber)
Comment 9•18 years ago
|
||
(In reply to comment #8)
> Created an attachment (id=232137) [edit]
> Alternative patch
I think you attached the same patch again.
I'll only be able to have a good look at this sometime next week, but at a first glance, I'm not sure this is the right way to go. In fact, when I touched the word-delete code, I commented somewhere that I think it should not go through nsSelection::MoveCaret, but instead be implemented more like single-character deletion. The reason is that "delete" is a pure logical operation, whereas much of the code in PeekOffset (used by CaretMove) is there to enable various visual quirks associated with caret movement.
As an example, I suspect that with this patch, placing the caret at the beginning of a wrapped line and hitting "backspace" once won't actually delete anything, but just move the caret to the end of the previous line. This is the (apparently intended) behavior for pressing left-arrow, and while it's (arguably) correct in that case, it's certainly wrong for backspace.
I'll take a closer look (and perhaps be able to come up with a suggestion for an alternative fix) sometime early next week.
Assignee | ||
Updated•18 years ago
|
Attachment #232137 -
Attachment is obsolete: true
Attachment #232137 -
Flags: review?(uriber)
Assignee | ||
Comment 10•18 years ago
|
||
Attachment #232140 -
Flags: review?(uriber)
Assignee | ||
Comment 11•18 years ago
|
||
(In reply to comment #9)
> As an example, I suspect that with this patch, placing the caret at the
> beginning of a wrapped line and hitting "backspace" once won't actually delete
> anything, but just move the caret to the end of the previous line.e.
You're right.
That extra "smart" behavior with wrapped text is not necessary for left/right arrow. None of the applications I test with do that:
Notepad, MS Word, IE, Opera
Honestly that's just weird. We don't even do that in rich text editing (Midas, thunderbird etc.). We should be consistent with ourselves and other apps, and remove the extra complicated code. That would allow this patch to work. A big benefit of the alternative patch which does this for Delete as well is the removal of lots of code -- that's not a bad thing :)
> I'll take a closer look (and perhaps be able to come up with a suggestion for
> an alternative fix) sometime early next week.
Thanks!
Assignee | ||
Comment 12•18 years ago
|
||
> This is the (apparently intended) behavior for pressing left-arrow, and while
> it's (arguably) correct in that case, it's certainly wrong for backspace.
I found another reason that it's a bad idea. When your press shift+right or shift+left to select by character, it pauses and does nothing once when you move pas the line boundary. That's weird. A screen reader user would certainly be confused by that.
So we have 5 reasons to remove that special case:
1) Inconsistent with our rich text editor
2) Inconsistent with other apps
3) Can remove lots of code via the alternative patch, fixing this bug at the same time
4) No confusing visual pause for shift+left and shift+right
5) Won't consuse screen reader users arrowing through the text. I just noticed that they get a beep when they arrow through the end of the line where there is no character.
Comment 13•18 years ago
|
||
(In reply to comment #12)
> So we have 5 reasons to remove that special case:
The more I think of it, the more I agree with you on this. My current thinking is that this was probably not even done on purpose in the first place. The flip side is that removing it (without breaking other cases) might not be straightforward. I'm amazed that in 6 years or so, no bug (AFAIK) was filed on this behavior.
That said, I brought this specific case just as an example. While I can't think of other examples where delete should behave differently than caret movement off the top of my head, I'd like to think about this a bit more.
I definitely agree that if we're going to do this, we should do it for both directions (backspace and delete), so I'll concentrate on your second alternative when reviewing.
Assignee | ||
Comment 14•18 years ago
|
||
One exception I see in Notepad/Opera/IE/Word is that pressing end or shift+end leaves you at the end of the current line. However, the next right arrow then goes to the 2nd character in the next line. In other words, there is *never* an invisible or extra stop allowed.
In Composer/Midas an end/shift+end press puts you before the space at the end of the line. The next right arrow puts you at the beginning of the next line.
Assignee | ||
Updated•18 years ago
|
Attachment #232123 -
Attachment is obsolete: true
Attachment #232123 -
Flags: review?(uriber)
Comment 15•18 years ago
|
||
Doing some archeology, I found that the current caret behavior at end of line (or at least the "forward" half of it) was requested in bug 9433, which says:
"[Pressing the right arrow when after the space at end of a wrapped line] should move [the caret] to the beginning of the [next] line (just before the first
character.) This is tricky since technically, this is not a change in location,
but it is what should happen in any word processor."
This was implemented as part of bug 9195.
So this was, apparently, done intentionally. Still, whether 1999-era word processors really behaved this way or not, I agree it's not desirable behavior now. I'll probably file a bug on it sometime tomorrow when I have time.
Assignee | ||
Comment 16•18 years ago
|
||
Uri, I like the idea of a separate bug to fix PeekOffset.
This patch tries but has problems at the end of a line which is so long as to fill the textarea width, and isn't deleting when you hit Delete after an End key press. I did have that working, and it has to do with the logic in nsFrame::GetFrameFromDirection that I was messing with. Hard to make that work right without a new member variable in aPos, like aPos->mKeepGoingAfterLineEdge or somthing. I was trying to use mVisible for it.
Attachment #232140 -
Attachment is obsolete: true
Attachment #232196 -
Flags: review?(uriber)
Attachment #232140 -
Flags: review?(uriber)
Assignee | ||
Comment 17•18 years ago
|
||
The problem with long lines in the text area was really bug 335560.
Attachment #232196 -
Attachment is obsolete: true
Attachment #232268 -
Flags: review?(uriber)
Attachment #232196 -
Flags: review?(uriber)
Comment 18•18 years ago
|
||
(In reply to comment #16)
> Uri, I like the idea of a separate bug to fix PeekOffset.
Done - see bug 347494. Aaron - with your permission, I'd like to take a stab at that bug myself (although I might end up using parts of your proposed fix).
Any fix to that bug will have to be tested in a wide range of plaintext and HTML situations, including bidi.
Let's concentrate the discussion here on the original bug and your proposed fix for it (i.e., attachment 232140 [details] [diff] [review]). I hope to be able to test it and give some more comments later today, or perhaps tomorrow.
Assignee | ||
Comment 19•18 years ago
|
||
Sounds great! Thank you.
Comment 20•18 years ago
|
||
Some more random comments and questions, in no particular order:
One thing I noticed about the patch is that it removes the calls to CheckBidiLevelForDeletion(), and thereby kills the bidi "don't delete if caret is not next to deleted character" feature. This should be restored.
Another question is whether you could remove the "if (bCollapsed)" block from nsHTMLEditRules::WillDeleteSelection, like you did in nsTextEdit rules.
It also seems like you might be able to get rid of nsEditor::CreateTxnForDeleteInsertionPoint() and nsEditor::CreateTxnForDeleteCharacter().
>- case eToEndOfLine:
>- result = selCont->IntraLineMove(PR_TRUE, PR_TRUE);
>- aAction = eNext;
>- break;
Notice that it says "eNext", not "eNone" in this branch. Initially I though this might have been a typo, but apparently it's not. So you're probably changing behavior in this case by always setting to eNone.
Finally, note that this patch makes deletion susceptible to any other existing caret-movement bugs, such as bug 346445, and perhaps other bugs I'm not aware of.
I'll continue looking at the patch later this week. The problem is that I don't really know the editor code that well (as opposed to the selection code), so I'm somewhat nervous about reviewing this. Perhaps someone more familiar with the editor module should give this a look as well?
Assignee | ||
Comment 21•18 years ago
|
||
Wow, I did not even realize that nsPlaintextEditor::DeleteSelection() is called for rich text deletes. Bad assumption on my part, based on the class name.
Okay, so on the plus side this means we can eliminate even more code. That's great. On the minus side, as you said, we'll have to deal with all the caret navigation bugs, which I do not want to do. Someone should do this so we can remove all the unnecessary code, but probably not me.
> One thing I noticed about the patch is that it removes the calls to
> CheckBidiLevelForDeletion(), and thereby kills the bidi "don't delete if caret
> is not next to deleted character" feature. This should be restored.
If we decide to still go with this approach I'll remove that.
> Another question is whether you could remove the "if (bCollapsed)" block from
> nsHTMLEditRules::WillDeleteSelection, like you did in nsTextEdit rules.
> Notice that it says "eNext", not "eNone" in this branch. Initially I though
> this might have been a typo, but apparently it's not. So you're probably
> changing behavior in this case by always setting to eNone.
I wasn't able to duplicate bug 67847 even without that line. They fixed that bug by setting it to eNext. But now that I test with rich text, I see not that bug but we're not deleting the entire selection when I hit delete. That's probably because I am shifting selection without even checking to see if it's collapsed.
I'd like to find a way to fix that without requiring setting it to eNext, because that means we'd still need the if (bCollapsed) sections.
Assignee | ||
Comment 22•18 years ago
|
||
> I'm somewhat nervous about reviewing this. Perhaps someone more familiar with
> the editor module should give this a look as well?
I'm nervous about fixing it. I'm not sure who the current module owner is but I don't think anyone is active. Editor is orphaned as far as I know.
If there is a simpler fix I think we should go for it.
Assignee | ||
Comment 23•18 years ago
|
||
Uri, given the problems with doing this for rich text -- there will be regressions, how about we only do this for plain text?
After all this is only a bug for the plaintext editor anyway.
Comment 24•18 years ago
|
||
(In reply to comment #23)
> After all this is only a bug for the plaintext editor anyway.
Is that because something is preventing the bug from happening in HTML, or just because we don't care about HTML in this case?
Comment 25•18 years ago
|
||
(In reply to comment #22)
>
> If there is a simpler fix I think we should go for it.
>
Perhaps you can pass on the action into [Will|Did]DeleteSelection (as it is passed to nsTextEditRules::WillDeleteSelection), and then use it (if it's not eNone) to "compensate" for the wrong offset?
Assignee | ||
Comment 26•18 years ago
|
||
Hi Uri, it's a bug in plaintext only because for HTML we are getting 100% accurate WillDeleteText calls. WillDeleteSelection isn't used for the collapsed case there.
> Perhaps you can pass on the action into [Will|Did]DeleteSelection (as it is
> passed to nsTextEditRules::WillDeleteSelection), and then use it (if it's not
> eNone) to "compensate" for the wrong offset?
You're saying [Will|Did]DeleteSelection would get a new aCollapsedAction parameter? I didn't want to have to change nsIEditActionListener, because I don't know who all the consumers of that are outside of Mozilla. What do you think?
Maybe we should make it use [Will|Did]DeleteText for the collapsed case, as HTML does?
Comment 27•18 years ago
|
||
(In reply to comment #26)
> You're saying [Will|Did]DeleteSelection would get a new aCollapsedAction
> parameter? I didn't want to have to change nsIEditActionListener, because I
> don't know who all the consumers of that are outside of Mozilla. What do you
> think?
>
I guess that's what I was saying. As I said before, I don't really know this code well - I was just throwing an idea up in the air. But I think your suggestion below is a better idea.
> Maybe we should make it use [Will|Did]DeleteText for the collapsed case, as
> HTML does?
This sounds like a very good idea to me. After all, in this case we're not really deleting a selection. Assuming this is not too difficult to do, I suggest going this way.
Assignee | ||
Comment 28•18 years ago
|
||
Attachment #232268 -
Attachment is obsolete: true
Attachment #234955 -
Flags: review?(uriber)
Attachment #232268 -
Flags: review?(uriber)
Comment 29•18 years ago
|
||
Comment on attachment 234955 [details] [diff] [review]
1) Call [Will|Did]Delete[Text|Node] correctly instead of assuming [Will|Did]DeleteSelection, 2) Invalidate accessible children from dom node edit changes 3) Correct offset/length for WillDeleteNode
The new code in nsEditor::DeleteSelectionImpl will only work for the plaintext editor. Fortunately, it will never actually be reached in the HTMLEditor case, but we need to make sure of that. So I suggest ASSERTing that this is, in fact, a plaintext editor, and also adding a comment explaining why this code will not be reached by the HTML editor.
Additionally, the only non-text node that we might encounter in the plaintext editor is a nsHTMLBRElement, so it might be worth asserting that this is indeed the case, if deleteCharData is null. Also, add a comment saying that the handling of non-text nodes could be removed altogether once bug 240933 is fixed.
I'm not sure how the changes to nsHyperTextAccessible are relevant, and in any case, I'm not in the position to review them - but I assume you know what you're doing there.
Other than that, looks good. r=me with those asserts and comments.
Attachment #234955 -
Flags: review?(uriber) → review+
Assignee | ||
Comment 30•18 years ago
|
||
Comment on attachment 234955 [details] [diff] [review]
1) Call [Will|Did]Delete[Text|Node] correctly instead of assuming [Will|Did]DeleteSelection, 2) Invalidate accessible children from dom node edit changes 3) Correct offset/length for WillDeleteNode
I will add the asserts and comments as recommended.
Ginn, could you r+ the mozilla/accessible changes?
Attachment #234955 -
Flags: superreview?(roc)
Attachment #234955 -
Flags: review?(ginn.chen)
Assignee | ||
Comment 31•18 years ago
|
||
BTW, the InvalidateChildren() calls in nsHyperTextAccessible were necessary so that the accessibility cache is updated after a <br> is inserted or deleted. Otherwise bad things happen, such as events not being fired, or incorrect information in events.
The other change in mozilla/accessible was because we weren't passing the correct information to DOMPointToOffset when a node was deleted.
Comment 32•18 years ago
|
||
Comment on attachment 234955 [details] [diff] [review]
1) Call [Will|Did]Delete[Text|Node] correctly instead of assuming [Will|Did]DeleteSelection, 2) Invalidate accessible children from dom node edit changes 3) Correct offset/length for WillDeleteNode
r=me for accessibility part
Attachment #234955 -
Flags: review?(ginn.chen) → review+
Attachment #234955 -
Flags: superreview?(roc) → superreview+
Assignee | ||
Updated•18 years ago
|
Status: ASSIGNED → RESOLVED
Closed: 18 years ago
Resolution: --- → FIXED
Comment 33•18 years ago
|
||
I think you got your )s mixed up...
Attachment #237710 -
Flags: review?(aaronleventhal)
Assignee | ||
Updated•18 years ago
|
Attachment #237710 -
Flags: review?(aaronleventhal) → review+
Updated•18 years ago
|
Attachment #237710 -
Flags: superreview+
Comment 34•18 years ago
|
||
aaron, it looks like the code added to nsEditor.cpp has introduced a crash.
see bug #353515. additionally, is there a typo in this comment:
// XXX After bug 240933 is fixed we will never be deleting a node
// a node, there will always be a char data
At least, I don't get the "a node a node" part.
Assignee | ||
Comment 35•18 years ago
|
||
s/a node a node/a node
Assignee | ||
Comment 36•18 years ago
|
||
Basically after that bug is fixed (if it is fixed) there will no longer be <br>'s, so plain text will be plain text.
You need to log in
before you can comment on or make changes to this bug.
Description
•