diff --git a/Libraries/LibWeb/Selection/Selection.cpp b/Libraries/LibWeb/Selection/Selection.cpp index d89f0586c79..1c34cd543b0 100644 --- a/Libraries/LibWeb/Selection/Selection.cpp +++ b/Libraries/LibWeb/Selection/Selection.cpp @@ -525,26 +525,37 @@ GC::Ptr Selection::range() const void Selection::set_range(GC::Ptr 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 Selection::cursor_position() const diff --git a/Tests/LibWeb/Text/expected/selection-focuses-editing-host.txt b/Tests/LibWeb/Text/expected/selection-focuses-editing-host.txt new file mode 100644 index 00000000000..be2795ad27e --- /dev/null +++ b/Tests/LibWeb/Text/expected/selection-focuses-editing-host.txt @@ -0,0 +1,2 @@ +Range: [object Text] 1 [object Text] 2 +document.activeElement: [object HTMLDivElement] diff --git a/Tests/LibWeb/Text/input/selection-focuses-editing-host.html b/Tests/LibWeb/Text/input/selection-focuses-editing-host.html new file mode 100644 index 00000000000..bad433e94f7 --- /dev/null +++ b/Tests/LibWeb/Text/input/selection-focuses-editing-host.html @@ -0,0 +1,15 @@ + +
foo
+ +