mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
Use NodeFlag for marking and fix caret color
Signed-off-by: stevennovaryo <steven.novaryo@gmail.com>
This commit is contained in:
parent
f638c05710
commit
335a1d7ad2
7 changed files with 53 additions and 40 deletions
|
@ -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,
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -4,8 +4,6 @@ button {
|
|||
|
||||
button,
|
||||
input {
|
||||
padding-block: 2px;
|
||||
padding-inline: 1px;
|
||||
background: white;
|
||||
border: solid lightgrey 1px;
|
||||
color: black;
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
/// <https://dom.spec.whatwg.org/#connected>
|
||||
pub(crate) fn is_connected(&self) -> bool {
|
||||
self.upcast::<Node>().is_connected()
|
||||
|
|
|
@ -119,12 +119,19 @@ struct InputTypeColorShadowTree {
|
|||
color_value: Dom<HTMLDivElement>,
|
||||
}
|
||||
|
||||
// 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::<Node>(), can_gc);
|
||||
|
||||
let inner_container =
|
||||
HTMLDivElement::new(local_name!("div"), None, &document, None, can_gc);
|
||||
inner_container
|
||||
.upcast::<Element>()
|
||||
.SetId(DOMString::from("input-container"), can_gc);
|
||||
shadow_root
|
||||
.upcast::<Node>()
|
||||
.AppendChild(inner_container.upcast::<Node>(), can_gc)
|
||||
.unwrap();
|
||||
|
||||
let placeholder_container =
|
||||
HTMLDivElement::new(local_name!("div"), None, &document, None, can_gc);
|
||||
placeholder_container
|
||||
.upcast::<Element>()
|
||||
.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::<Element>()
|
||||
.set_text_editing_root_state(true);
|
||||
shadow_root
|
||||
inner_container
|
||||
.upcast::<Node>()
|
||||
.AppendChild(placeholder_container.upcast::<Node>(), 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::<Element>()
|
||||
.set_text_editing_root_state(true);
|
||||
shadow_root
|
||||
.upcast::<Node>()
|
||||
.set_text_editing_root();
|
||||
inner_container
|
||||
.upcast::<Node>()
|
||||
.AppendChild(text_container.upcast::<Node>(), 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::<Node>()
|
||||
|
@ -1276,7 +1292,7 @@ impl HTMLInputElement {
|
|||
text_shadow_tree
|
||||
.text_container
|
||||
.upcast::<Node>()
|
||||
.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);
|
||||
|
|
|
@ -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
|
||||
/// <input> or <textarea> element.
|
||||
const IS_TEXT_EDITING_ROOT = 1 << 13;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -697,6 +701,14 @@ impl Node {
|
|||
self.flags.get().contains(NodeFlags::IS_CONNECTED)
|
||||
}
|
||||
|
||||
pub(crate) fn set_text_editing_root(&self) {
|
||||
self.set_flag(NodeFlags::IS_TEXT_EDITING_ROOT, true)
|
||||
}
|
||||
|
||||
pub(crate) fn is_text_editing_root(&self) -> bool {
|
||||
self.flags.get().contains(NodeFlags::IS_TEXT_EDITING_ROOT)
|
||||
}
|
||||
|
||||
/// Returns the type ID of this node.
|
||||
pub(crate) fn type_id(&self) -> NodeTypeId {
|
||||
match *self.eventtarget.type_id() {
|
||||
|
@ -1619,7 +1631,7 @@ pub(crate) trait LayoutNodeHelpers<'dom> {
|
|||
fn is_text_input_with_shadow_dom(&self) -> bool;
|
||||
|
||||
/// Whether this element serve as a container of editable text for a text input.
|
||||
fn text_editing_root(&self) -> bool;
|
||||
fn is_text_editing_root(&self) -> bool;
|
||||
fn text_content(self) -> Cow<'dom, str>;
|
||||
fn selection(self) -> Option<Range<usize>>;
|
||||
fn image_url(self) -> Option<ServoUrl>;
|
||||
|
@ -1818,11 +1830,8 @@ impl<'dom> LayoutNodeHelpers<'dom> for LayoutDom<'dom, Node> {
|
|||
}
|
||||
}
|
||||
|
||||
fn text_editing_root(&self) -> bool {
|
||||
match self.downcast::<Element>() {
|
||||
Some(element) => element.text_editing_root(),
|
||||
_ => false,
|
||||
}
|
||||
fn is_text_editing_root(&self) -> bool {
|
||||
self.unsafe_get().is_text_editing_root()
|
||||
}
|
||||
|
||||
fn text_content(self) -> Cow<'dom, str> {
|
||||
|
@ -1844,7 +1853,7 @@ impl<'dom> LayoutNodeHelpers<'dom> for LayoutDom<'dom, Node> {
|
|||
fn selection(self) -> Option<Range<usize>> {
|
||||
// This container is a text editing root of a <input> or <textarea> element.
|
||||
// So we should find those corresponding element, and get its selection.
|
||||
if self.text_editing_root() {
|
||||
if self.is_text_editing_root() {
|
||||
let mut maybe_parent_node = self.composed_parent_node_ref();
|
||||
while let Some(parent_node) = maybe_parent_node {
|
||||
if let Some(area) = parent_node.downcast::<HTMLTextAreaElement>() {
|
||||
|
|
|
@ -102,7 +102,7 @@ impl<'dom> ServoLayoutNode<'dom> {
|
|||
}
|
||||
|
||||
pub fn is_text_editing_root(&self) -> bool {
|
||||
self.node.text_editing_root()
|
||||
self.node.is_text_editing_root()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue