mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-28 13:18:19 +00:00
LibWeb: Selecting an editing host should focus it
Unspecced but common behavior in the major browsers: if the selection moves to an editing host, the editing host itself should become focused.
This commit is contained in:
parent
c9d4913bb4
commit
0ce1571e71
Notes:
github-actions[bot]
2025-08-01 08:10:36 +00:00
Author: https://github.com/gmta
Commit: 0ce1571e71
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/5666
3 changed files with 35 additions and 7 deletions
|
@ -525,26 +525,37 @@ GC::Ptr<DOM::Range> Selection::range() const
|
|||
|
||||
void Selection::set_range(GC::Ptr<DOM::Range> range)
|
||||
{
|
||||
if (m_range == range)
|
||||
auto old_range = m_range;
|
||||
if (old_range == range)
|
||||
return;
|
||||
|
||||
if (m_range)
|
||||
m_range->set_associated_selection({}, nullptr);
|
||||
if (old_range)
|
||||
old_range->set_associated_selection({}, nullptr);
|
||||
|
||||
auto range_changed = ((m_range == nullptr) != (range == nullptr)) || (m_range && *m_range != *range);
|
||||
m_range = range;
|
||||
|
||||
if (m_range)
|
||||
m_range->set_associated_selection({}, this);
|
||||
if (range)
|
||||
range->set_associated_selection({}, this);
|
||||
|
||||
// https://w3c.github.io/editing/docs/execCommand/#state-override
|
||||
// Whenever the number of ranges in the selection changes to something different, and whenever a boundary point of
|
||||
// the range at a given index in the selection changes to something different, the state override and value override
|
||||
// must be unset for every command.
|
||||
if (range_changed) {
|
||||
if (((old_range == nullptr) != (range == nullptr)) || (old_range && *old_range != *range)) {
|
||||
m_document->reset_command_state_overrides();
|
||||
m_document->reset_command_value_overrides();
|
||||
}
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/Selection#behavior_of_selection_api_in_terms_of_editing_host_focus_changes
|
||||
// AD-HOC: Focus editing host if the previous selection was outside of it. There seems to be no spec for this.
|
||||
if (range && range->start_container()->is_editable_or_editing_host()) {
|
||||
GC::Ptr old_editing_host = old_range ? old_range->start_container()->editing_host() : nullptr;
|
||||
GC::Ref new_editing_host = *range->start_container()->editing_host();
|
||||
if (new_editing_host != old_editing_host && document()->focused_element() != new_editing_host) {
|
||||
// FIXME: Determine and propagate the right focus trigger.
|
||||
HTML::run_focusing_steps(new_editing_host, nullptr, HTML::FocusTrigger::Other);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GC::Ptr<DOM::Position> Selection::cursor_position() const
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
Range: [object Text] 1 [object Text] 2
|
||||
document.activeElement: [object HTMLDivElement]
|
15
Tests/LibWeb/Text/input/selection-focuses-editing-host.html
Normal file
15
Tests/LibWeb/Text/input/selection-focuses-editing-host.html
Normal file
|
@ -0,0 +1,15 @@
|
|||
<!DOCTYPE html>
|
||||
<div contenteditable>foo</div>
|
||||
<script src="include.js"></script>
|
||||
<script>
|
||||
test(() => {
|
||||
const divElm = document.querySelector('div[contenteditable]');
|
||||
const range = document.createRange();
|
||||
range.setStart(divElm.childNodes[0], 1);
|
||||
range.setEnd(divElm.childNodes[0], 2);
|
||||
window.getSelection().addRange(range);
|
||||
|
||||
println(`Range: ${range.startContainer} ${range.startOffset} ${range.endContainer} ${range.endOffset}`);
|
||||
println(`document.activeElement: ${document.activeElement}`);
|
||||
});
|
||||
</script>
|
Loading…
Add table
Add a link
Reference in a new issue