LibWeb+WebContent: Rename Document::focused_element to ::focused_area

And make it a DOM::Node, not DOM::Element. This makes everything flow
much better, such as spec texts that explicitly mention "focused area"
as the fact that we don't necessarily need to traverse a tree of
elements, since a Node can be focusable as well.

Eventually this will need to be a struct with a separate "focused area"
and "DOM anchor", but this change will make it easier to achieve that.
This commit is contained in:
Jelle Raaijmakers 2025-08-21 17:09:40 +02:00 committed by Jelle Raaijmakers
parent 90f1c8724b
commit 518c048eb4
Notes: github-actions[bot] 2025-08-26 08:27:18 +00:00
11 changed files with 92 additions and 91 deletions

View file

@ -683,8 +683,8 @@ EventResult EventHandler::handle_mousedown(CSSPixelPoint viewport_position, CSSP
// Spec Note: Note that focusing is not an activation behavior, i.e. calling the click() method on an element or dispatching a synthetic click event on it won't cause the element to get focused.
if (focus_candidate)
HTML::run_focusing_steps(focus_candidate, nullptr, HTML::FocusTrigger::Click);
else if (auto* focused_element = document->focused_element())
HTML::run_unfocusing_steps(focused_element);
else if (auto focused_area = document->focused_area())
HTML::run_unfocusing_steps(focused_area);
// https://drafts.csswg.org/css-ui/#valdef-user-select-none
// Attempting to start a selection in an element where user-select is none, such as by clicking in it or starting
@ -1066,17 +1066,17 @@ EventResult EventHandler::focus_next_element()
return EventResult::Dropped;
};
auto* element = m_navigable->active_document()->focused_element();
if (!element)
auto node = m_navigable->active_document()->focused_area();
if (!node)
return set_focus_to_first_focusable_element();
for (element = element->next_element_in_pre_order(); element && !element->is_focusable(); element = element->next_element_in_pre_order())
for (node = node->next_in_pre_order(); node && !node->is_focusable(); node = node->next_in_pre_order())
;
if (!element)
if (!node)
return set_focus_to_first_focusable_element();
HTML::run_focusing_steps(element, nullptr, HTML::FocusTrigger::Key);
HTML::run_focusing_steps(node, nullptr, HTML::FocusTrigger::Key);
return EventResult::Handled;
}
@ -1101,17 +1101,17 @@ EventResult EventHandler::focus_previous_element()
return EventResult::Dropped;
};
auto* element = m_navigable->active_document()->focused_element();
if (!element)
auto node = m_navigable->active_document()->focused_area();
if (!node)
return set_focus_to_last_focusable_element();
for (element = element->previous_element_in_pre_order(); element && !element->is_focusable(); element = element->previous_element_in_pre_order())
for (node = node->previous_in_pre_order(); node && !node->is_focusable(); node = node->previous_in_pre_order())
;
if (!element)
if (!node)
return set_focus_to_last_focusable_element();
HTML::run_focusing_steps(element, nullptr, HTML::FocusTrigger::Key);
HTML::run_focusing_steps(node, nullptr, HTML::FocusTrigger::Key);
return EventResult::Handled;
}
@ -1132,15 +1132,15 @@ EventResult EventHandler::fire_keyboard_event(FlyString const& event_name, HTML:
if (!document->is_fully_active())
return EventResult::Dropped;
if (GC::Ptr<DOM::Element> focused_element = document->focused_element()) {
if (is<HTML::NavigableContainer>(*focused_element)) {
auto& navigable_container = as<HTML::NavigableContainer>(*focused_element);
if (GC::Ptr focused_area = document->focused_area()) {
if (is<HTML::NavigableContainer>(*focused_area)) {
auto& navigable_container = as<HTML::NavigableContainer>(*focused_area);
if (navigable_container.content_navigable())
return fire_keyboard_event(event_name, *navigable_container.content_navigable(), key, modifiers, code_point, repeat);
}
auto event = UIEvents::KeyboardEvent::create_from_platform_event(document->realm(), event_name, key, modifiers, code_point, repeat);
return focused_element->dispatch_event(event) ? EventResult::Accepted : EventResult::Cancelled;
return focused_area->dispatch_event(event) ? EventResult::Accepted : EventResult::Cancelled;
}
// FIXME: De-duplicate this. This is just to prevent wasting a KeyboardEvent allocation when recursing into an (i)frame.
@ -1207,15 +1207,15 @@ EventResult EventHandler::input_event(FlyString const& event_name, FlyString con
input_event_init.input_type = input_type;
if (auto* focused_element = document->focused_element()) {
if (is<HTML::NavigableContainer>(*focused_element)) {
auto& navigable_container = as<HTML::NavigableContainer>(*focused_element);
if (auto focused_area = document->focused_area()) {
if (is<HTML::NavigableContainer>(*focused_area)) {
auto& navigable_container = as<HTML::NavigableContainer>(*focused_area);
if (navigable_container.content_navigable())
return input_event(event_name, input_type, *navigable_container.content_navigable(), move(code_point_or_string));
}
auto event = UIEvents::InputEvent::create_from_platform_event(document->realm(), event_name, input_event_init, target_ranges_for_input_event(*document));
return focused_element->dispatch_event(event) ? EventResult::Accepted : EventResult::Cancelled;
return focused_area->dispatch_event(event) ? EventResult::Accepted : EventResult::Cancelled;
}
auto event = UIEvents::InputEvent::create_from_platform_event(document->realm(), event_name, input_event_init, target_ranges_for_input_event(*document));
@ -1270,8 +1270,8 @@ EventResult EventHandler::handle_keydown(UIEvents::KeyCode key, u32 modifiers, u
// instead interpret this interaction as some other action, instead of interpreting it as a close request.
}
auto* focused_element = m_navigable->active_document()->focused_element();
if (auto* media_element = as_if<HTML::HTMLMediaElement>(focused_element)) {
auto focused_area = m_navigable->active_document()->focused_area();
if (auto* media_element = as_if<HTML::HTMLMediaElement>(focused_area.ptr())) {
if (media_element->handle_keydown({}, key, modifiers).release_value_but_fixme_should_propagate_errors())
return EventResult::Handled;
}
@ -1347,8 +1347,8 @@ EventResult EventHandler::handle_keydown(UIEvents::KeyCode key, u32 modifiers, u
auto input_type = modifiers == UIEvents::Mod_Shift ? UIEvents::InputTypes::insertLineBreak : UIEvents::InputTypes::insertParagraph;
// If the editing host is contenteditable="plaintext-only", we force a line break.
if (focused_element) {
if (auto editing_host = focused_element->editing_host(); editing_host
if (focused_area) {
if (auto editing_host = focused_area->editing_host(); editing_host
&& as<HTML::HTMLElement>(*editing_host).content_editable_state() == HTML::ContentEditableState::PlaintextOnly)
input_type = UIEvents::InputTypes::insertLineBreak;
}