mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-09-22 17:29:01 +00:00
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:
parent
90f1c8724b
commit
518c048eb4
Notes:
github-actions[bot]
2025-08-26 08:27:18 +00:00
Author: https://github.com/gmta
Commit: 518c048eb4
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/5952
11 changed files with 92 additions and 91 deletions
|
@ -552,8 +552,8 @@ static inline bool matches_pseudo_class(CSS::Selector::SimpleSelector::PseudoCla
|
||||||
case CSS::PseudoClass::FocusVisible:
|
case CSS::PseudoClass::FocusVisible:
|
||||||
return element.is_focused() && element.should_indicate_focus();
|
return element.is_focused() && element.should_indicate_focus();
|
||||||
case CSS::PseudoClass::FocusWithin: {
|
case CSS::PseudoClass::FocusWithin: {
|
||||||
auto* focused_element = element.document().focused_element();
|
auto focused_area = element.document().focused_area();
|
||||||
return focused_element && element.is_inclusive_ancestor_of(*focused_element);
|
return focused_area && element.is_inclusive_ancestor_of(*focused_area);
|
||||||
}
|
}
|
||||||
case CSS::PseudoClass::FirstChild:
|
case CSS::PseudoClass::FirstChild:
|
||||||
if (context.collect_per_element_selector_involvement_metadata) {
|
if (context.collect_per_element_selector_involvement_metadata) {
|
||||||
|
|
|
@ -547,7 +547,7 @@ void Document::visit_edges(Cell::Visitor& visitor)
|
||||||
visitor.visit(m_highlighted_node);
|
visitor.visit(m_highlighted_node);
|
||||||
visitor.visit(m_active_favicon);
|
visitor.visit(m_active_favicon);
|
||||||
visitor.visit(m_browsing_context);
|
visitor.visit(m_browsing_context);
|
||||||
visitor.visit(m_focused_element);
|
visitor.visit(m_focused_area);
|
||||||
visitor.visit(m_active_element);
|
visitor.visit(m_active_element);
|
||||||
visitor.visit(m_target_element);
|
visitor.visit(m_target_element);
|
||||||
visitor.visit(m_implementation);
|
visitor.visit(m_implementation);
|
||||||
|
@ -2443,7 +2443,7 @@ String const& Document::compat_mode() const
|
||||||
void Document::update_active_element()
|
void Document::update_active_element()
|
||||||
{
|
{
|
||||||
// 1. Let candidate be this's node document's focused area's DOM anchor.
|
// 1. Let candidate be this's node document's focused area's DOM anchor.
|
||||||
Node* candidate = focused_element();
|
Node* candidate = focused_area();
|
||||||
|
|
||||||
// 2. Set candidate to the result of retargeting candidate against this.
|
// 2. Set candidate to the result of retargeting candidate against this.
|
||||||
candidate = as<Node>(retarget(candidate, this));
|
candidate = as<Node>(retarget(candidate, this));
|
||||||
|
@ -2478,56 +2478,57 @@ void Document::update_active_element()
|
||||||
set_active_element(nullptr);
|
set_active_element(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Document::set_focused_element(GC::Ptr<Element> element)
|
void Document::set_focused_area(GC::Ptr<Node> node)
|
||||||
{
|
{
|
||||||
if (m_focused_element.ptr() == element)
|
if (m_focused_area == node)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
GC::Ptr<Element> old_focused_element = move(m_focused_element);
|
GC::Ptr old_focused_area = m_focused_area;
|
||||||
|
|
||||||
if (old_focused_element)
|
if (auto* old_focused_element = as_if<Element>(old_focused_area.ptr()))
|
||||||
old_focused_element->did_lose_focus();
|
old_focused_element->did_lose_focus();
|
||||||
|
|
||||||
auto* common_ancestor = find_common_ancestor(old_focused_element, element);
|
auto* common_ancestor = find_common_ancestor(old_focused_area, node);
|
||||||
|
|
||||||
GC::Ptr<Node> old_focused_node_root = nullptr;
|
GC::Ptr<Node> old_focused_node_root = nullptr;
|
||||||
GC::Ptr<Node> new_focused_node_root = nullptr;
|
GC::Ptr<Node> new_focused_node_root = nullptr;
|
||||||
if (old_focused_element)
|
if (old_focused_area)
|
||||||
old_focused_node_root = old_focused_element->root();
|
old_focused_node_root = old_focused_area->root();
|
||||||
if (element)
|
if (node)
|
||||||
new_focused_node_root = element->root();
|
new_focused_node_root = node->root();
|
||||||
if (old_focused_node_root != new_focused_node_root) {
|
if (old_focused_node_root != new_focused_node_root) {
|
||||||
if (old_focused_node_root) {
|
if (old_focused_node_root) {
|
||||||
invalidate_style_for_elements_affected_by_pseudo_class_change(CSS::PseudoClass::Focus, m_focused_element, *old_focused_node_root, element);
|
invalidate_style_for_elements_affected_by_pseudo_class_change(CSS::PseudoClass::Focus, m_focused_area, *old_focused_node_root, node);
|
||||||
invalidate_style_for_elements_affected_by_pseudo_class_change(CSS::PseudoClass::FocusWithin, m_focused_element, *old_focused_node_root, element);
|
invalidate_style_for_elements_affected_by_pseudo_class_change(CSS::PseudoClass::FocusWithin, m_focused_area, *old_focused_node_root, node);
|
||||||
invalidate_style_for_elements_affected_by_pseudo_class_change(CSS::PseudoClass::FocusVisible, m_focused_element, *old_focused_node_root, element);
|
invalidate_style_for_elements_affected_by_pseudo_class_change(CSS::PseudoClass::FocusVisible, m_focused_area, *old_focused_node_root, node);
|
||||||
}
|
}
|
||||||
if (new_focused_node_root) {
|
if (new_focused_node_root) {
|
||||||
invalidate_style_for_elements_affected_by_pseudo_class_change(CSS::PseudoClass::Focus, m_focused_element, *new_focused_node_root, element);
|
invalidate_style_for_elements_affected_by_pseudo_class_change(CSS::PseudoClass::Focus, m_focused_area, *new_focused_node_root, node);
|
||||||
invalidate_style_for_elements_affected_by_pseudo_class_change(CSS::PseudoClass::FocusWithin, m_focused_element, *new_focused_node_root, element);
|
invalidate_style_for_elements_affected_by_pseudo_class_change(CSS::PseudoClass::FocusWithin, m_focused_area, *new_focused_node_root, node);
|
||||||
invalidate_style_for_elements_affected_by_pseudo_class_change(CSS::PseudoClass::FocusVisible, m_focused_element, *new_focused_node_root, element);
|
invalidate_style_for_elements_affected_by_pseudo_class_change(CSS::PseudoClass::FocusVisible, m_focused_area, *new_focused_node_root, node);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
invalidate_style_for_elements_affected_by_pseudo_class_change(CSS::PseudoClass::Focus, m_focused_element, *common_ancestor, element);
|
invalidate_style_for_elements_affected_by_pseudo_class_change(CSS::PseudoClass::Focus, m_focused_area, *common_ancestor, node);
|
||||||
invalidate_style_for_elements_affected_by_pseudo_class_change(CSS::PseudoClass::FocusWithin, m_focused_element, *common_ancestor, element);
|
invalidate_style_for_elements_affected_by_pseudo_class_change(CSS::PseudoClass::FocusWithin, m_focused_area, *common_ancestor, node);
|
||||||
invalidate_style_for_elements_affected_by_pseudo_class_change(CSS::PseudoClass::FocusVisible, m_focused_element, *common_ancestor, element);
|
invalidate_style_for_elements_affected_by_pseudo_class_change(CSS::PseudoClass::FocusVisible, m_focused_area, *common_ancestor, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_focused_element = element;
|
m_focused_area = node;
|
||||||
|
|
||||||
if (m_focused_element)
|
auto* new_focused_element = as_if<Element>(node.ptr());
|
||||||
m_focused_element->did_receive_focus();
|
if (new_focused_element)
|
||||||
|
new_focused_element->did_receive_focus();
|
||||||
|
|
||||||
if (paintable())
|
if (paintable())
|
||||||
paintable()->set_needs_display();
|
paintable()->set_needs_display();
|
||||||
|
|
||||||
// Scroll the viewport if necessary to make the newly focused element visible.
|
// Scroll the viewport if necessary to make the newly focused element visible.
|
||||||
if (m_focused_element) {
|
if (new_focused_element) {
|
||||||
m_focused_element->queue_an_element_task(HTML::Task::Source::UserInteraction, [&]() {
|
new_focused_element->queue_an_element_task(HTML::Task::Source::UserInteraction, [&] {
|
||||||
ScrollIntoViewOptions scroll_options;
|
ScrollIntoViewOptions scroll_options;
|
||||||
scroll_options.block = Bindings::ScrollLogicalPosition::Nearest;
|
scroll_options.block = Bindings::ScrollLogicalPosition::Nearest;
|
||||||
scroll_options.inline_ = Bindings::ScrollLogicalPosition::Nearest;
|
scroll_options.inline_ = Bindings::ScrollLogicalPosition::Nearest;
|
||||||
(void)m_focused_element->scroll_into_view(scroll_options);
|
(void)as<Element>(*m_focused_area).scroll_into_view(scroll_options);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6338,38 +6339,38 @@ GC::Ref<Document> Document::parse_html_unsafe(JS::VM& vm, StringView html)
|
||||||
|
|
||||||
InputEventsTarget* Document::active_input_events_target()
|
InputEventsTarget* Document::active_input_events_target()
|
||||||
{
|
{
|
||||||
auto* focused_element = this->focused_element();
|
auto focused_area = this->focused_area();
|
||||||
if (!focused_element)
|
if (!focused_area)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
if (is<HTML::HTMLInputElement>(*focused_element))
|
if (auto* input_element = as_if<HTML::HTMLInputElement>(*focused_area))
|
||||||
return static_cast<HTML::HTMLInputElement*>(focused_element);
|
return input_element;
|
||||||
if (is<HTML::HTMLTextAreaElement>(*focused_element))
|
if (auto* text_area_element = as_if<HTML::HTMLTextAreaElement>(*focused_area))
|
||||||
return static_cast<HTML::HTMLTextAreaElement*>(focused_element);
|
return text_area_element;
|
||||||
if (focused_element->is_editable_or_editing_host())
|
if (focused_area->is_editable_or_editing_host())
|
||||||
return m_editing_host_manager;
|
return m_editing_host_manager;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
GC::Ptr<DOM::Position> Document::cursor_position() const
|
GC::Ptr<DOM::Position> Document::cursor_position() const
|
||||||
{
|
{
|
||||||
auto const* focused_element = this->focused_element();
|
auto const focused_area = this->focused_area();
|
||||||
if (!focused_element)
|
if (!focused_area)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
Optional<HTML::FormAssociatedTextControlElement const&> target {};
|
Optional<HTML::FormAssociatedTextControlElement const&> target {};
|
||||||
if (auto const* input_element = as_if<HTML::HTMLInputElement>(*focused_element)) {
|
if (auto const* input_element = as_if<HTML::HTMLInputElement>(*focused_area)) {
|
||||||
// Some types of <input> tags shouldn't have a cursor, like buttons
|
// Some types of <input> tags shouldn't have a cursor, like buttons
|
||||||
if (!input_element->can_have_text_editing_cursor())
|
if (!input_element->can_have_text_editing_cursor())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
target = *input_element;
|
target = *input_element;
|
||||||
} else if (is<HTML::HTMLTextAreaElement>(*focused_element))
|
} else if (is<HTML::HTMLTextAreaElement>(*focused_area))
|
||||||
target = static_cast<HTML::HTMLTextAreaElement const&>(*focused_element);
|
target = static_cast<HTML::HTMLTextAreaElement const&>(*focused_area);
|
||||||
|
|
||||||
if (target.has_value())
|
if (target.has_value())
|
||||||
return target->cursor_position();
|
return target->cursor_position();
|
||||||
|
|
||||||
if (focused_element->is_editable_or_editing_host())
|
if (focused_area->is_editable_or_editing_host())
|
||||||
return m_selection->cursor_position();
|
return m_selection->cursor_position();
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -35,7 +35,6 @@
|
||||||
#include <LibWeb/HTML/Focus.h>
|
#include <LibWeb/HTML/Focus.h>
|
||||||
#include <LibWeb/HTML/HTMLScriptElement.h>
|
#include <LibWeb/HTML/HTMLScriptElement.h>
|
||||||
#include <LibWeb/HTML/History.h>
|
#include <LibWeb/HTML/History.h>
|
||||||
#include <LibWeb/HTML/LazyLoadingElement.h>
|
|
||||||
#include <LibWeb/HTML/NavigationType.h>
|
#include <LibWeb/HTML/NavigationType.h>
|
||||||
#include <LibWeb/HTML/SandboxingFlagSet.h>
|
#include <LibWeb/HTML/SandboxingFlagSet.h>
|
||||||
#include <LibWeb/HTML/Scripting/Environments.h>
|
#include <LibWeb/HTML/Scripting/Environments.h>
|
||||||
|
@ -431,10 +430,10 @@ public:
|
||||||
|
|
||||||
void set_editable(bool editable) { m_editable = editable; }
|
void set_editable(bool editable) { m_editable = editable; }
|
||||||
|
|
||||||
Element* focused_element() { return m_focused_element.ptr(); }
|
// // https://html.spec.whatwg.org/multipage/interaction.html#focused-area-of-the-document
|
||||||
Element const* focused_element() const { return m_focused_element.ptr(); }
|
GC::Ptr<Node> focused_area() { return m_focused_area; }
|
||||||
|
GC::Ptr<Node const> focused_area() const { return m_focused_area; }
|
||||||
void set_focused_element(GC::Ptr<Element>);
|
void set_focused_area(GC::Ptr<Node>);
|
||||||
|
|
||||||
HTML::FocusTrigger last_focus_trigger() const { return m_last_focus_trigger; }
|
HTML::FocusTrigger last_focus_trigger() const { return m_last_focus_trigger; }
|
||||||
void set_last_focus_trigger(HTML::FocusTrigger trigger) { m_last_focus_trigger = trigger; }
|
void set_last_focus_trigger(HTML::FocusTrigger trigger) { m_last_focus_trigger = trigger; }
|
||||||
|
@ -1017,7 +1016,9 @@ private:
|
||||||
|
|
||||||
bool m_editable { false };
|
bool m_editable { false };
|
||||||
|
|
||||||
GC::Ptr<Element> m_focused_element;
|
// https://html.spec.whatwg.org/multipage/interaction.html#focused-area-of-the-document
|
||||||
|
GC::Ptr<Node> m_focused_area;
|
||||||
|
|
||||||
HTML::FocusTrigger m_last_focus_trigger { HTML::FocusTrigger::Other };
|
HTML::FocusTrigger m_last_focus_trigger { HTML::FocusTrigger::Other };
|
||||||
|
|
||||||
GC::Ptr<Element> m_active_element;
|
GC::Ptr<Element> m_active_element;
|
||||||
|
|
|
@ -1077,7 +1077,7 @@ WebIDL::ExceptionOr<String> Element::inner_html() const
|
||||||
|
|
||||||
bool Element::is_focused() const
|
bool Element::is_focused() const
|
||||||
{
|
{
|
||||||
return document().focused_element() == this;
|
return document().focused_area() == this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Element::is_active() const
|
bool Element::is_active() const
|
||||||
|
@ -3291,8 +3291,8 @@ bool Element::is_relevant_to_the_user()
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Either the element or its contents are focused, as described in the focus section of the HTML spec.
|
// Either the element or its contents are focused, as described in the focus section of the HTML spec.
|
||||||
auto* focused_element = document().focused_element();
|
auto focused_area = document().focused_area();
|
||||||
if (focused_element && is_inclusive_ancestor_of(*focused_element))
|
if (focused_area && is_inclusive_ancestor_of(*focused_area))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Either the element or its contents are selected, where selection is described in the selection API.
|
// Either the element or its contents are selected, where selection is described in the selection API.
|
||||||
|
|
|
@ -113,9 +113,9 @@ static void run_focus_update_steps(Vector<GC::Root<DOM::Node>> old_chain, Vector
|
||||||
// 1. If entry is a focusable area: designate entry as the focused area of the document.
|
// 1. If entry is a focusable area: designate entry as the focused area of the document.
|
||||||
// FIXME: This isn't entirely right.
|
// FIXME: This isn't entirely right.
|
||||||
if (is<DOM::Element>(*entry))
|
if (is<DOM::Element>(*entry))
|
||||||
entry->document().set_focused_element(&static_cast<DOM::Element&>(*entry));
|
entry->document().set_focused_area(*entry);
|
||||||
else if (is<DOM::Document>(*entry))
|
else if (is<DOM::Document>(*entry))
|
||||||
entry->document().set_focused_element(static_cast<DOM::Document&>(*entry).document_element());
|
entry->document().set_focused_area(static_cast<DOM::Document&>(*entry).document_element());
|
||||||
|
|
||||||
GC::Ptr<DOM::EventTarget> focus_event_target;
|
GC::Ptr<DOM::EventTarget> focus_event_target;
|
||||||
if (is<DOM::Element>(*entry)) {
|
if (is<DOM::Element>(*entry)) {
|
||||||
|
|
|
@ -1369,17 +1369,17 @@ GC::Ptr<DOM::Node> TraversableNavigable::currently_focused_area()
|
||||||
|
|
||||||
// 3. While candidate's focused area is a navigable container with a non-null content navigable:
|
// 3. While candidate's focused area is a navigable container with a non-null content navigable:
|
||||||
// set candidate to the active document of that navigable container's content navigable.
|
// set candidate to the active document of that navigable container's content navigable.
|
||||||
while (candidate->focused_element()
|
while (candidate->focused_area()
|
||||||
&& is<HTML::NavigableContainer>(candidate->focused_element())
|
&& is<NavigableContainer>(candidate->focused_area().ptr())
|
||||||
&& static_cast<HTML::NavigableContainer&>(*candidate->focused_element()).content_navigable()) {
|
&& as<NavigableContainer>(*candidate->focused_area()).content_navigable()) {
|
||||||
candidate = static_cast<HTML::NavigableContainer&>(*candidate->focused_element()).content_navigable()->active_document();
|
candidate = as<NavigableContainer>(*candidate->focused_area()).content_navigable()->active_document();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. If candidate's focused area is non-null, set candidate to candidate's focused area.
|
// 4. If candidate's focused area is non-null, set candidate to candidate's focused area.
|
||||||
if (candidate->focused_element()) {
|
if (candidate->focused_area()) {
|
||||||
// NOTE: We return right away here instead of assigning to candidate,
|
// NOTE: We return right away here instead of assigning to candidate,
|
||||||
// since that would require compromising type safety.
|
// since that would require compromising type safety.
|
||||||
return candidate->focused_element();
|
return candidate->focused_area();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. Return candidate.
|
// 5. Return candidate.
|
||||||
|
|
|
@ -9,9 +9,7 @@
|
||||||
|
|
||||||
#include <AK/Badge.h>
|
#include <AK/Badge.h>
|
||||||
#include <AK/RefPtr.h>
|
#include <AK/RefPtr.h>
|
||||||
#include <AK/TypeCasts.h>
|
|
||||||
#include <LibGC/Heap.h>
|
#include <LibGC/Heap.h>
|
||||||
#include <LibURL/URL.h>
|
|
||||||
#include <LibWeb/Bindings/Intrinsics.h>
|
#include <LibWeb/Bindings/Intrinsics.h>
|
||||||
#include <LibWeb/Bindings/WindowGlobalMixin.h>
|
#include <LibWeb/Bindings/WindowGlobalMixin.h>
|
||||||
#include <LibWeb/DOM/EventTarget.h>
|
#include <LibWeb/DOM/EventTarget.h>
|
||||||
|
@ -22,6 +20,7 @@
|
||||||
#include <LibWeb/HTML/GlobalEventHandlers.h>
|
#include <LibWeb/HTML/GlobalEventHandlers.h>
|
||||||
#include <LibWeb/HTML/MimeType.h>
|
#include <LibWeb/HTML/MimeType.h>
|
||||||
#include <LibWeb/HTML/Navigable.h>
|
#include <LibWeb/HTML/Navigable.h>
|
||||||
|
#include <LibWeb/HTML/Navigation.h>
|
||||||
#include <LibWeb/HTML/Plugin.h>
|
#include <LibWeb/HTML/Plugin.h>
|
||||||
#include <LibWeb/HTML/ScrollOptions.h>
|
#include <LibWeb/HTML/ScrollOptions.h>
|
||||||
#include <LibWeb/HTML/StructuredSerializeOptions.h>
|
#include <LibWeb/HTML/StructuredSerializeOptions.h>
|
||||||
|
|
|
@ -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.
|
// 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)
|
if (focus_candidate)
|
||||||
HTML::run_focusing_steps(focus_candidate, nullptr, HTML::FocusTrigger::Click);
|
HTML::run_focusing_steps(focus_candidate, nullptr, HTML::FocusTrigger::Click);
|
||||||
else if (auto* focused_element = document->focused_element())
|
else if (auto focused_area = document->focused_area())
|
||||||
HTML::run_unfocusing_steps(focused_element);
|
HTML::run_unfocusing_steps(focused_area);
|
||||||
|
|
||||||
// https://drafts.csswg.org/css-ui/#valdef-user-select-none
|
// 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
|
// 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;
|
return EventResult::Dropped;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto* element = m_navigable->active_document()->focused_element();
|
auto node = m_navigable->active_document()->focused_area();
|
||||||
if (!element)
|
if (!node)
|
||||||
return set_focus_to_first_focusable_element();
|
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();
|
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;
|
return EventResult::Handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1101,17 +1101,17 @@ EventResult EventHandler::focus_previous_element()
|
||||||
return EventResult::Dropped;
|
return EventResult::Dropped;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto* element = m_navigable->active_document()->focused_element();
|
auto node = m_navigable->active_document()->focused_area();
|
||||||
if (!element)
|
if (!node)
|
||||||
return set_focus_to_last_focusable_element();
|
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();
|
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;
|
return EventResult::Handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1132,15 +1132,15 @@ EventResult EventHandler::fire_keyboard_event(FlyString const& event_name, HTML:
|
||||||
if (!document->is_fully_active())
|
if (!document->is_fully_active())
|
||||||
return EventResult::Dropped;
|
return EventResult::Dropped;
|
||||||
|
|
||||||
if (GC::Ptr<DOM::Element> focused_element = document->focused_element()) {
|
if (GC::Ptr focused_area = document->focused_area()) {
|
||||||
if (is<HTML::NavigableContainer>(*focused_element)) {
|
if (is<HTML::NavigableContainer>(*focused_area)) {
|
||||||
auto& navigable_container = as<HTML::NavigableContainer>(*focused_element);
|
auto& navigable_container = as<HTML::NavigableContainer>(*focused_area);
|
||||||
if (navigable_container.content_navigable())
|
if (navigable_container.content_navigable())
|
||||||
return fire_keyboard_event(event_name, *navigable_container.content_navigable(), key, modifiers, code_point, repeat);
|
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);
|
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.
|
// 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;
|
input_event_init.input_type = input_type;
|
||||||
|
|
||||||
if (auto* focused_element = document->focused_element()) {
|
if (auto focused_area = document->focused_area()) {
|
||||||
if (is<HTML::NavigableContainer>(*focused_element)) {
|
if (is<HTML::NavigableContainer>(*focused_area)) {
|
||||||
auto& navigable_container = as<HTML::NavigableContainer>(*focused_element);
|
auto& navigable_container = as<HTML::NavigableContainer>(*focused_area);
|
||||||
if (navigable_container.content_navigable())
|
if (navigable_container.content_navigable())
|
||||||
return input_event(event_name, input_type, *navigable_container.content_navigable(), move(code_point_or_string));
|
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));
|
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));
|
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.
|
// 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();
|
auto focused_area = m_navigable->active_document()->focused_area();
|
||||||
if (auto* media_element = as_if<HTML::HTMLMediaElement>(focused_element)) {
|
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())
|
if (media_element->handle_keydown({}, key, modifiers).release_value_but_fixme_should_propagate_errors())
|
||||||
return EventResult::Handled;
|
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;
|
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 the editing host is contenteditable="plaintext-only", we force a line break.
|
||||||
if (focused_element) {
|
if (focused_area) {
|
||||||
if (auto editing_host = focused_element->editing_host(); editing_host
|
if (auto editing_host = focused_area->editing_host(); editing_host
|
||||||
&& as<HTML::HTMLElement>(*editing_host).content_editable_state() == HTML::ContentEditableState::PlaintextOnly)
|
&& as<HTML::HTMLElement>(*editing_host).content_editable_state() == HTML::ContentEditableState::PlaintextOnly)
|
||||||
input_type = UIEvents::InputTypes::insertLineBreak;
|
input_type = UIEvents::InputTypes::insertLineBreak;
|
||||||
}
|
}
|
||||||
|
|
|
@ -180,12 +180,12 @@ Gfx::Orientation PaintableFragment::orientation() const
|
||||||
|
|
||||||
CSSPixelRect PaintableFragment::selection_rect() const
|
CSSPixelRect PaintableFragment::selection_rect() const
|
||||||
{
|
{
|
||||||
if (auto const* focused_element = paintable().document().focused_element(); focused_element && is<HTML::FormAssociatedTextControlElement>(*focused_element)) {
|
if (auto focused_area = paintable().document().focused_area(); is<HTML::FormAssociatedTextControlElement>(focused_area.ptr())) {
|
||||||
HTML::FormAssociatedTextControlElement const* text_control_element = nullptr;
|
HTML::FormAssociatedTextControlElement const* text_control_element = nullptr;
|
||||||
if (is<HTML::HTMLInputElement>(*focused_element)) {
|
if (auto const* input_element = as_if<HTML::HTMLInputElement>(*focused_area)) {
|
||||||
text_control_element = static_cast<HTML::HTMLInputElement const*>(focused_element);
|
text_control_element = input_element;
|
||||||
} else if (is<HTML::HTMLTextAreaElement>(*focused_element)) {
|
} else if (auto const* text_area_element = as_if<HTML::HTMLTextAreaElement>(*focused_area)) {
|
||||||
text_control_element = static_cast<HTML::HTMLTextAreaElement const*>(focused_element);
|
text_control_element = text_area_element;
|
||||||
} else {
|
} else {
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
|
@ -552,7 +552,7 @@ void Selection::set_range(GC::Ptr<DOM::Range> range)
|
||||||
GC::Ref new_editing_host = *range->start_container()->editing_host();
|
GC::Ref new_editing_host = *range->start_container()->editing_host();
|
||||||
while (new_editing_host->parent() && new_editing_host->parent()->is_editing_host())
|
while (new_editing_host->parent() && new_editing_host->parent()->is_editing_host())
|
||||||
new_editing_host = *new_editing_host->parent();
|
new_editing_host = *new_editing_host->parent();
|
||||||
if (document()->focused_element() != new_editing_host) {
|
if (document()->focused_area() != new_editing_host) {
|
||||||
// FIXME: Determine and propagate the right focus trigger.
|
// FIXME: Determine and propagate the right focus trigger.
|
||||||
HTML::run_focusing_steps(new_editing_host, nullptr, HTML::FocusTrigger::Other);
|
HTML::run_focusing_steps(new_editing_host, nullptr, HTML::FocusTrigger::Other);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1961,7 +1961,7 @@ Web::WebDriver::Response WebDriverConnection::element_send_keys_impl(StringView
|
||||||
else if (is<Web::HTML::HTMLElement>(*element) && static_cast<Web::HTML::HTMLElement&>(*element).is_content_editable()) {
|
else if (is<Web::HTML::HTMLElement>(*element) && static_cast<Web::HTML::HTMLElement&>(*element).is_content_editable()) {
|
||||||
// If element does not currently have focus, set the text insertion caret after any child content.
|
// If element does not currently have focus, set the text insertion caret after any child content.
|
||||||
auto* document = current_browsing_context().active_document();
|
auto* document = current_browsing_context().active_document();
|
||||||
document->set_focused_element(element);
|
document->set_focused_area(element);
|
||||||
}
|
}
|
||||||
// -> otherwise
|
// -> otherwise
|
||||||
else if (is<Web::HTML::FormAssociatedTextControlElement>(*element)) {
|
else if (is<Web::HTML::FormAssociatedTextControlElement>(*element)) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue