diff --git a/dom/events/ContentEventHandler.cpp b/dom/events/ContentEventHandler.cpp index 64b8dae4374..1180e6b6319 100644 --- a/dom/events/ContentEventHandler.cpp +++ b/dom/events/ContentEventHandler.cpp @@ -58,7 +58,10 @@ using namespace widget; // 1.4. Case: [ // When start of a non-empty element is start of a range, start node is // the element and start offset is 0. -// 1.5. Case: [ +// 1.5. Case: [ +// When start of a range is 0 and there are no nodes causing text, +// start node is the root node and start offset is 0. +// 1.6. Case: [ // When start of a range is out of bounds, start node is the root node // and start offset is number of the children. // 2. End of range: @@ -1001,12 +1004,31 @@ ContentEventHandler::SetRangeFromFlatTextOffset(nsRange* aRange, } if (!startSet) { - // Rule #1.5: [ MOZ_ASSERT(!mRootContent->IsNodeOfType(nsINode::eTEXT)); - rv = aRange->SetStart(mRootContent, - static_cast(mRootContent->GetChildCount())); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; + if (!offset) { + // Rule #1.5: [ + // When there are no nodes causing text, the start of the DOM range + // should be start of the root node since clicking on such editor (e.g., + //
) sets caret to the start of + // the editor (i.e., before in the example). + rv = aRange->SetStart(mRootContent, 0); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + if (!aLength) { + rv = aRange->SetEnd(mRootContent, 0); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + return NS_OK; + } + } else { + // Rule #1.5: [ + rv = aRange->SetStart(mRootContent, + static_cast(mRootContent->GetChildCount())); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } } if (aNewOffset) { *aNewOffset = offset; diff --git a/widget/tests/window_composition_text_querycontent.xul b/widget/tests/window_composition_text_querycontent.xul index 6aa9370279f..0623446211c 100644 --- a/widget/tests/window_composition_text_querycontent.xul +++ b/widget/tests/window_composition_text_querycontent.xul @@ -3117,22 +3117,22 @@ function runSetSelectionEventTest() synthesizeSelectionSet(0, 0); is(selection.anchorNode, contenteditable, "runSetSelectionEventTest #11 (0, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node"); - todo_is(selection.anchorOffset, 0, + is(selection.anchorOffset, 0, "runSetSelectionEventTest #11 (0, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0"); is(selection.focusNode, contenteditable, "runSetSelectionEventTest #11 (0, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node"); - todo_is(selection.focusOffset, 0, + is(selection.focusOffset, 0, "runSetSelectionEventTest #11 (0, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be 0"); checkSelection(0, "", "runSetSelectionEventTest #11 (0, 0), \"" + contenteditable.innerHTML + "\""); synthesizeSelectionSet(0, 1); is(selection.anchorNode, contenteditable, "runSetSelectionEventTest #11 (0, 1), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node"); - todo_is(selection.anchorOffset, 0, + is(selection.anchorOffset, 0, "runSetSelectionEventTest #11 (0, 1), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0"); is(selection.focusNode, contenteditable, "runSetSelectionEventTest #11 (0, 1), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node"); - todo_is(selection.focusOffset, contenteditable.childNodes.length, + is(selection.focusOffset, contenteditable.childNodes.length, "runSetSelectionEventTest #11 (0, 1), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children"); checkSelection(0, "", "runSetSelectionEventTest #11 (0, 1), \"" + contenteditable.innerHTML + "\"");