From 335a1d7ad2d9ef156e163b09eed185706737f977 Mon Sep 17 00:00:00 2001 From: stevennovaryo Date: Tue, 20 May 2025 19:45:10 +0800 Subject: [PATCH] Use NodeFlag for marking and fix caret color Signed-off-by: stevennovaryo --- components/layout/display_list/mod.rs | 3 +- components/layout/dom_traversal.rs | 4 +- components/layout/stylesheets/servo.css | 2 - components/script/dom/element.rs | 11 ------ components/script/dom/htmlinputelement.rs | 48 +++++++++++++++-------- components/script/dom/node.rs | 23 +++++++---- components/script/layout_dom/node.rs | 2 +- 7 files changed, 53 insertions(+), 40 deletions(-) diff --git a/components/layout/display_list/mod.rs b/components/layout/display_list/mod.rs index 5c88e843e62..3716ff35b2c 100644 --- a/components/layout/display_list/mod.rs +++ b/components/layout/display_list/mod.rs @@ -539,8 +539,7 @@ impl InspectorHighlight { }); // We expect all fragments generated by one node to be in the same scroll tree node and clip node - // MYNOTES: Error for Input type text shadow DOM. - // debug_assert_eq!(spatial_id, state.spatial_id); + debug_assert_eq!(spatial_id, state.spatial_id); if clip_chain_id != ClipChainId::INVALID && state.clip_chain_id != ClipChainId::INVALID { debug_assert_eq!( clip_chain_id, state.clip_chain_id, diff --git a/components/layout/dom_traversal.rs b/components/layout/dom_traversal.rs index 214d3882542..f3b1b756fcc 100644 --- a/components/layout/dom_traversal.rs +++ b/components/layout/dom_traversal.rs @@ -59,8 +59,10 @@ impl<'dom> NodeAndStyleInfo<'dom> { } } + // Whether this is a container for the editable text within a single-line text input. pub(crate) fn is_single_line_text_input(&self) -> bool { - self.node.type_id() == LayoutNodeType::Element(LayoutElementType::HTMLInputElement) + self.node.type_id() == LayoutNodeType::Element(LayoutElementType::HTMLInputElement) || + self.node.is_text_editing_root() } pub(crate) fn pseudo( diff --git a/components/layout/stylesheets/servo.css b/components/layout/stylesheets/servo.css index 90779382841..c025b19f364 100644 --- a/components/layout/stylesheets/servo.css +++ b/components/layout/stylesheets/servo.css @@ -4,8 +4,6 @@ button { button, input { - padding-block: 2px; - padding-inline: 1px; background: white; border: solid lightgrey 1px; color: black; diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index 0c84cc3e821..dbf0f14ab68 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -865,13 +865,6 @@ impl LayoutDom<'_, Element> { pub(super) fn focus_state(self) -> bool { self.unsafe_get().state.get().contains(ElementState::FOCUS) } - - pub(super) fn text_editing_root(self) -> bool { - self.unsafe_get() - .state - .get() - .contains(ElementState::TEXT_EDITING_ROOT) - } } impl<'dom> LayoutElementHelpers<'dom> for LayoutDom<'dom, Element> { @@ -4886,10 +4879,6 @@ impl Element { self.set_state(ElementState::FULLSCREEN, value) } - pub(crate) fn set_text_editing_root_state(&self, value: bool) { - self.set_state(ElementState::TEXT_EDITING_ROOT, value) - } - /// pub(crate) fn is_connected(&self) -> bool { self.upcast::().is_connected() diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs index dedc37eaaeb..2989e6c1a07 100644 --- a/components/script/dom/htmlinputelement.rs +++ b/components/script/dom/htmlinputelement.rs @@ -119,12 +119,19 @@ struct InputTypeColorShadowTree { color_value: Dom, } -// FIXME: These styles should be inside UA stylesheet, -// but we should support pseudo element first. +// FIXME: These styles should be inside UA stylesheet, but it is not possible without internal pseudo element support. +// FIXME: We are setting `pointer-events: none;` because focus is not propagated to its ancestor. +// FIXME: We are using `position: absolute` to put place the editing root and placeholder +// on top of each other, but this will create a unnecessary element in between. const TEXT_TREE_STYLE: &str = " #input-editing-root::selection, #input-placeholder::selection { - background: rgba(176, 214, 255, 1.0); - color: black; + background: rgba(176, 214, 255, 1.0); + color: black; +} + +#input-container { + position: relative; + pointer-events: none; } #input-editing-root, #input-placeholder { @@ -134,6 +141,7 @@ const TEXT_TREE_STYLE: &str = " } #input-placeholder { + position: absolute; color: grey; overflow: hidden; } @@ -1113,18 +1121,22 @@ impl HTMLInputElement { let shadow_root = self.shadow_root(can_gc); Node::replace_all(None, shadow_root.upcast::(), can_gc); + let inner_container = + HTMLDivElement::new(local_name!("div"), None, &document, None, can_gc); + inner_container + .upcast::() + .SetId(DOMString::from("input-container"), can_gc); + shadow_root + .upcast::() + .AppendChild(inner_container.upcast::(), can_gc) + .unwrap(); + let placeholder_container = HTMLDivElement::new(local_name!("div"), None, &document, None, can_gc); placeholder_container .upcast::() .SetId(DOMString::from("input-placeholder"), can_gc); - // MYNOTES: - // This is not a text editing root, but we should do this to show it's - // editing caret when placeholder is still visible - placeholder_container - .upcast::() - .set_text_editing_root_state(true); - shadow_root + inner_container .upcast::() .AppendChild(placeholder_container.upcast::(), can_gc) .unwrap(); @@ -1136,9 +1148,9 @@ impl HTMLInputElement { // We should probably use pseudo element to check this. // Chrome is using (private?) element attrs, text_container - .upcast::() - .set_text_editing_root_state(true); - shadow_root + .upcast::() + .set_text_editing_root(); + inner_container .upcast::() .AppendChild(text_container.upcast::(), can_gc) .unwrap(); @@ -1265,10 +1277,14 @@ impl HTMLInputElement { let placeholder_text = match (value.is_empty(), self.placeholder.borrow().is_empty()) { (true, false) => self.placeholder.to_owned().take(), - (true, true) => "\u{200B}".into(), _ => DOMString::new(), }; + let value_text = match value.is_empty() { + false => value, + true => "\u{200B}".into(), + }; + text_shadow_tree .placeholder_container .upcast::() @@ -1276,7 +1292,7 @@ impl HTMLInputElement { text_shadow_tree .text_container .upcast::() - .SetTextContent(Some(value), can_gc); + .SetTextContent(Some(value_text), can_gc); } if self.input_type() == InputType::Color { let color_shadow_tree = self.color_shadow_tree(can_gc); diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index e7f286cf673..aa26aa452a8 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -230,6 +230,10 @@ bitflags! { /// Whether this node has a weird parser insertion mode. i.e whether setting innerHTML /// needs extra work or not const HAS_WEIRD_PARSER_INSERTION_MODE = 1 << 11; + + /// Whether this node has a serve as the text container for editable content of + /// or