mirror of
https://github.com/servo/servo.git
synced 2025-08-06 22:15:33 +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
|
// 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 {
|
if clip_chain_id != ClipChainId::INVALID && state.clip_chain_id != ClipChainId::INVALID {
|
||||||
debug_assert_eq!(
|
debug_assert_eq!(
|
||||||
clip_chain_id, state.clip_chain_id,
|
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 {
|
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(
|
pub(crate) fn pseudo(
|
||||||
|
|
|
@ -4,8 +4,6 @@ button {
|
||||||
|
|
||||||
button,
|
button,
|
||||||
input {
|
input {
|
||||||
padding-block: 2px;
|
|
||||||
padding-inline: 1px;
|
|
||||||
background: white;
|
background: white;
|
||||||
border: solid lightgrey 1px;
|
border: solid lightgrey 1px;
|
||||||
color: black;
|
color: black;
|
||||||
|
|
|
@ -865,13 +865,6 @@ impl LayoutDom<'_, Element> {
|
||||||
pub(super) fn focus_state(self) -> bool {
|
pub(super) fn focus_state(self) -> bool {
|
||||||
self.unsafe_get().state.get().contains(ElementState::FOCUS)
|
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> {
|
impl<'dom> LayoutElementHelpers<'dom> for LayoutDom<'dom, Element> {
|
||||||
|
@ -4886,10 +4879,6 @@ impl Element {
|
||||||
self.set_state(ElementState::FULLSCREEN, value)
|
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>
|
/// <https://dom.spec.whatwg.org/#connected>
|
||||||
pub(crate) fn is_connected(&self) -> bool {
|
pub(crate) fn is_connected(&self) -> bool {
|
||||||
self.upcast::<Node>().is_connected()
|
self.upcast::<Node>().is_connected()
|
||||||
|
|
|
@ -119,12 +119,19 @@ struct InputTypeColorShadowTree {
|
||||||
color_value: Dom<HTMLDivElement>,
|
color_value: Dom<HTMLDivElement>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: These styles should be inside UA stylesheet,
|
// FIXME: These styles should be inside UA stylesheet, but it is not possible without internal pseudo element support.
|
||||||
// but we should support pseudo element first.
|
// 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 = "
|
const TEXT_TREE_STYLE: &str = "
|
||||||
#input-editing-root::selection, #input-placeholder::selection {
|
#input-editing-root::selection, #input-placeholder::selection {
|
||||||
background: rgba(176, 214, 255, 1.0);
|
background: rgba(176, 214, 255, 1.0);
|
||||||
color: black;
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
#input-container {
|
||||||
|
position: relative;
|
||||||
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#input-editing-root, #input-placeholder {
|
#input-editing-root, #input-placeholder {
|
||||||
|
@ -134,6 +141,7 @@ const TEXT_TREE_STYLE: &str = "
|
||||||
}
|
}
|
||||||
|
|
||||||
#input-placeholder {
|
#input-placeholder {
|
||||||
|
position: absolute;
|
||||||
color: grey;
|
color: grey;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
@ -1113,18 +1121,22 @@ impl HTMLInputElement {
|
||||||
let shadow_root = self.shadow_root(can_gc);
|
let shadow_root = self.shadow_root(can_gc);
|
||||||
Node::replace_all(None, shadow_root.upcast::<Node>(), 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 =
|
let placeholder_container =
|
||||||
HTMLDivElement::new(local_name!("div"), None, &document, None, can_gc);
|
HTMLDivElement::new(local_name!("div"), None, &document, None, can_gc);
|
||||||
placeholder_container
|
placeholder_container
|
||||||
.upcast::<Element>()
|
.upcast::<Element>()
|
||||||
.SetId(DOMString::from("input-placeholder"), can_gc);
|
.SetId(DOMString::from("input-placeholder"), can_gc);
|
||||||
// MYNOTES:
|
inner_container
|
||||||
// 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
|
|
||||||
.upcast::<Node>()
|
.upcast::<Node>()
|
||||||
.AppendChild(placeholder_container.upcast::<Node>(), can_gc)
|
.AppendChild(placeholder_container.upcast::<Node>(), can_gc)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -1136,9 +1148,9 @@ impl HTMLInputElement {
|
||||||
// We should probably use pseudo element to check this.
|
// We should probably use pseudo element to check this.
|
||||||
// Chrome is using (private?) element attrs,
|
// Chrome is using (private?) element attrs,
|
||||||
text_container
|
text_container
|
||||||
.upcast::<Element>()
|
.upcast::<Node>()
|
||||||
.set_text_editing_root_state(true);
|
.set_text_editing_root();
|
||||||
shadow_root
|
inner_container
|
||||||
.upcast::<Node>()
|
.upcast::<Node>()
|
||||||
.AppendChild(text_container.upcast::<Node>(), can_gc)
|
.AppendChild(text_container.upcast::<Node>(), can_gc)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -1265,10 +1277,14 @@ impl HTMLInputElement {
|
||||||
|
|
||||||
let placeholder_text = match (value.is_empty(), self.placeholder.borrow().is_empty()) {
|
let placeholder_text = match (value.is_empty(), self.placeholder.borrow().is_empty()) {
|
||||||
(true, false) => self.placeholder.to_owned().take(),
|
(true, false) => self.placeholder.to_owned().take(),
|
||||||
(true, true) => "\u{200B}".into(),
|
|
||||||
_ => DOMString::new(),
|
_ => DOMString::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let value_text = match value.is_empty() {
|
||||||
|
false => value,
|
||||||
|
true => "\u{200B}".into(),
|
||||||
|
};
|
||||||
|
|
||||||
text_shadow_tree
|
text_shadow_tree
|
||||||
.placeholder_container
|
.placeholder_container
|
||||||
.upcast::<Node>()
|
.upcast::<Node>()
|
||||||
|
@ -1276,7 +1292,7 @@ impl HTMLInputElement {
|
||||||
text_shadow_tree
|
text_shadow_tree
|
||||||
.text_container
|
.text_container
|
||||||
.upcast::<Node>()
|
.upcast::<Node>()
|
||||||
.SetTextContent(Some(value), can_gc);
|
.SetTextContent(Some(value_text), can_gc);
|
||||||
}
|
}
|
||||||
if self.input_type() == InputType::Color {
|
if self.input_type() == InputType::Color {
|
||||||
let color_shadow_tree = self.color_shadow_tree(can_gc);
|
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
|
/// Whether this node has a weird parser insertion mode. i.e whether setting innerHTML
|
||||||
/// needs extra work or not
|
/// needs extra work or not
|
||||||
const HAS_WEIRD_PARSER_INSERTION_MODE = 1 << 11;
|
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)
|
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.
|
/// Returns the type ID of this node.
|
||||||
pub(crate) fn type_id(&self) -> NodeTypeId {
|
pub(crate) fn type_id(&self) -> NodeTypeId {
|
||||||
match *self.eventtarget.type_id() {
|
match *self.eventtarget.type_id() {
|
||||||
|
@ -1619,7 +1631,7 @@ pub(crate) trait LayoutNodeHelpers<'dom> {
|
||||||
fn is_text_input_with_shadow_dom(&self) -> bool;
|
fn is_text_input_with_shadow_dom(&self) -> bool;
|
||||||
|
|
||||||
/// Whether this element serve as a container of editable text for a text input.
|
/// 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 text_content(self) -> Cow<'dom, str>;
|
||||||
fn selection(self) -> Option<Range<usize>>;
|
fn selection(self) -> Option<Range<usize>>;
|
||||||
fn image_url(self) -> Option<ServoUrl>;
|
fn image_url(self) -> Option<ServoUrl>;
|
||||||
|
@ -1818,11 +1830,8 @@ impl<'dom> LayoutNodeHelpers<'dom> for LayoutDom<'dom, Node> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn text_editing_root(&self) -> bool {
|
fn is_text_editing_root(&self) -> bool {
|
||||||
match self.downcast::<Element>() {
|
self.unsafe_get().is_text_editing_root()
|
||||||
Some(element) => element.text_editing_root(),
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn text_content(self) -> Cow<'dom, str> {
|
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>> {
|
fn selection(self) -> Option<Range<usize>> {
|
||||||
// This container is a text editing root of a <input> or <textarea> element.
|
// This container is a text editing root of a <input> or <textarea> element.
|
||||||
// So we should find those corresponding element, and get its selection.
|
// 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();
|
let mut maybe_parent_node = self.composed_parent_node_ref();
|
||||||
while let Some(parent_node) = maybe_parent_node {
|
while let Some(parent_node) = maybe_parent_node {
|
||||||
if let Some(area) = parent_node.downcast::<HTMLTextAreaElement>() {
|
if let Some(area) = parent_node.downcast::<HTMLTextAreaElement>() {
|
||||||
|
|
|
@ -102,7 +102,7 @@ impl<'dom> ServoLayoutNode<'dom> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_text_editing_root(&self) -> bool {
|
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