Implement Input type=text UA Shadow DOM (#37065)

Implement Shadow Tree construction for input `type=text`, adding a text
control inner editor container and placeholder container. Subsequently,
due to the changes of the DOM tree structure, the changes will add a new
NodeFlag `IS_TEXT_CONTROL_INNER_EDITOR` to handle the following cases.
- If a mouse click button event hits a text control inner editor, it
will redirect the focus target to its shadow host.
- In text run's construction, the text control inner editor container
queries the selection from its shadow host. This is later used to
resolve caret and selection painting in the display list.

This will be the first step of fixing input `type=text` and other
single-line text input element widgets. Such as, implementing
`::placeholder` selector.



Testing: Existing WPT test and new Servo specific appearance WPT.
Fixes: #36307

---------

Signed-off-by: stevennovaryo <steven.novaryo@gmail.com>
This commit is contained in:
Steven Novaryo 2025-05-30 20:02:10 +08:00 committed by GitHub
parent 578c52fe2b
commit 5580704438
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
24 changed files with 635 additions and 36 deletions

View file

@ -28,7 +28,7 @@ use style::selector_parser::PseudoElement;
use super::{
ServoLayoutDocument, ServoLayoutElement, ServoShadowRoot, ServoThreadSafeLayoutElement,
};
use crate::dom::bindings::inheritance::{CharacterDataTypeId, NodeTypeId, TextTypeId};
use crate::dom::bindings::inheritance::NodeTypeId;
use crate::dom::bindings::root::LayoutDom;
use crate::dom::element::{Element, LayoutElementHelpers};
use crate::dom::node::{LayoutNodeHelpers, Node, NodeFlags, NodeTypeIdWrapper};
@ -100,6 +100,10 @@ impl<'dom> ServoLayoutNode<'dom> {
pub fn is_text_input(&self) -> bool {
self.node.is_text_input()
}
pub fn is_text_control_inner_editor(&self) -> bool {
self.node.is_text_control_inner_editor()
}
}
impl style::dom::NodeInfo for ServoLayoutNode<'_> {
@ -108,8 +112,7 @@ impl style::dom::NodeInfo for ServoLayoutNode<'_> {
}
fn is_text_node(&self) -> bool {
self.script_type_id() ==
NodeTypeId::CharacterData(CharacterDataTypeId::Text(TextTypeId::Text))
self.node.is_text_node_for_layout()
}
}