LibWeb: Do not modify selection if editing host is already selected
If an editing host receives focus, we would always set a new selection range. However, we only need to do that if we're not already part of the active range. This corresponds to behavior shown by Chrome and Firefox.
This commit is contained in:
parent
8537f0fa82
commit
c9d4913bb4
3 changed files with 39 additions and 0 deletions
|
|
@ -18,6 +18,7 @@
|
|||
#include <LibWeb/DOM/IDLEventListener.h>
|
||||
#include <LibWeb/DOM/LiveNodeList.h>
|
||||
#include <LibWeb/DOM/Position.h>
|
||||
#include <LibWeb/DOM/Range.h>
|
||||
#include <LibWeb/DOM/ShadowRoot.h>
|
||||
#include <LibWeb/HTML/BrowsingContext.h>
|
||||
#include <LibWeb/HTML/CloseWatcher.h>
|
||||
|
|
@ -41,6 +42,7 @@
|
|||
#include <LibWeb/Layout/TextNode.h>
|
||||
#include <LibWeb/Namespace.h>
|
||||
#include <LibWeb/Painting/PaintableBox.h>
|
||||
#include <LibWeb/Selection/Selection.h>
|
||||
#include <LibWeb/UIEvents/EventNames.h>
|
||||
#include <LibWeb/UIEvents/PointerEvent.h>
|
||||
#include <LibWeb/WebIDL/DOMException.h>
|
||||
|
|
@ -2039,6 +2041,12 @@ void HTMLElement::did_receive_focus()
|
|||
auto editing_host = document().editing_host_manager();
|
||||
editing_host->set_active_contenteditable_element(this);
|
||||
|
||||
// Don't update the selection if we're already part of the active range.
|
||||
if (auto range = document().get_selection()->range()) {
|
||||
if (is_inclusive_ancestor_of(range->start_container()) || is_inclusive_ancestor_of(range->end_container()))
|
||||
return;
|
||||
}
|
||||
|
||||
DOM::Text* text = nullptr;
|
||||
for_each_in_inclusive_subtree_of_type<DOM::Text>([&](auto& node) {
|
||||
text = &node;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
Range: [object Text] 1 [object Text] 2
|
||||
document.activeElement: [object HTMLDivElement]
|
||||
Selection must be the same as above:
|
||||
Range: [object Text] 1 [object Text] 2
|
||||
document.activeElement: [object HTMLDivElement]
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
<!DOCTYPE html>
|
||||
<div contenteditable>foo</div>
|
||||
<script src="include.js"></script>
|
||||
<script>
|
||||
test(() => {
|
||||
const divElm = document.querySelector('div[contenteditable]');
|
||||
|
||||
// Select the middle 'o'
|
||||
let range = document.createRange();
|
||||
range.setStart(divElm.childNodes[0], 1);
|
||||
range.setEnd(divElm.childNodes[0], 2);
|
||||
getSelection().addRange(range);
|
||||
|
||||
println(`Range: ${range.startContainer} ${range.startOffset} ${range.endContainer} ${range.endOffset}`);
|
||||
println(`document.activeElement: ${document.activeElement}`);
|
||||
|
||||
// Refocus on the editing host
|
||||
document.body.focus();
|
||||
divElm.focus();
|
||||
|
||||
println('Selection must be the same as above:');
|
||||
range = getSelection().getRangeAt(0);
|
||||
println(`Range: ${range.startContainer} ${range.startOffset} ${range.endContainer} ${range.endOffset}`);
|
||||
println(`document.activeElement: ${document.activeElement}`);
|
||||
});
|
||||
</script>
|
||||
Loading…
Reference in a new issue