diff --git a/components/constellation/tracing.rs b/components/constellation/tracing.rs
index fd7fe7dd251..940cc9614cc 100644
--- a/components/constellation/tracing.rs
+++ b/components/constellation/tracing.rs
@@ -239,7 +239,7 @@ mod from_script {
Self::StopGamepadHapticEffect(..) => target_variant!("StopGamepadHapticEffect"),
Self::ShutdownComplete => target_variant!("ShutdownComplete"),
Self::ShowNotification(..) => target_variant!("ShowNotification"),
- Self::ShowSelectElementMenu(..) => target_variant!("ShowSelectElementMenu"),
+ Self::ShowFormControl(..) => target_variant!("ShowFormControl"),
Self::FinishJavaScriptEvaluation(..) => {
target_variant!("FinishJavaScriptEvaluation")
},
diff --git a/components/layout/dom_traversal.rs b/components/layout/dom_traversal.rs
index 0201d72dbe2..8bf6d919fa3 100644
--- a/components/layout/dom_traversal.rs
+++ b/components/layout/dom_traversal.rs
@@ -201,17 +201,7 @@ fn traverse_children_of<'dom>(
) {
traverse_eager_pseudo_element(PseudoElement::Before, parent_element, context, handler);
- let is_text_input_element = matches!(
- parent_element.type_id(),
- LayoutNodeType::Element(LayoutElementType::HTMLInputElement)
- );
-
- let is_textarea_element = matches!(
- parent_element.type_id(),
- LayoutNodeType::Element(LayoutElementType::HTMLTextAreaElement)
- );
-
- if is_text_input_element || is_textarea_element {
+ if parent_element.is_text_input() {
let info = NodeAndStyleInfo::new(
parent_element,
parent_element.style(context.shared_context()),
@@ -229,9 +219,7 @@ fn traverse_children_of<'dom>(
} else {
handler.handle_text(&info, node_text_content);
}
- }
-
- if !is_text_input_element && !is_textarea_element {
+ } else {
for child in iter_child_nodes(parent_element) {
if child.is_text_node() {
let info = NodeAndStyleInfo::new(child, child.style(context.shared_context()));
diff --git a/components/layout/stylesheets/servo.css b/components/layout/stylesheets/servo.css
index bc72f01cc56..c025b19f364 100644
--- a/components/layout/stylesheets/servo.css
+++ b/components/layout/stylesheets/servo.css
@@ -87,6 +87,15 @@ input[type="file"] {
border-style: none;
}
+input[type="color"] {
+ padding: 6px;
+ width: 64px;
+ height: 32px;
+ border-radius: 2px;
+ background: lightgrey;
+ border: 1px solid gray;
+}
+
td[align="left"] { text-align: left; }
td[align="center"] { text-align: center; }
td[align="right"] { text-align: right; }
diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs
index aff8168b8fe..3c78ba67772 100644
--- a/components/script/dom/htmlinputelement.rs
+++ b/components/script/dom/htmlinputelement.rs
@@ -12,9 +12,13 @@ use std::str::FromStr;
use std::{f64, ptr};
use dom_struct::dom_struct;
-use embedder_traits::{FilterPattern, InputMethodType};
+use embedder_traits::{
+ EmbedderMsg, FilterPattern, FormControl as EmbedderFormControl, InputMethodType, RgbColor,
+};
use encoding_rs::Encoding;
+use euclid::{Point2D, Rect, Size2D};
use html5ever::{LocalName, Prefix, local_name, ns};
+use ipc_channel::ipc;
use js::jsapi::{
ClippedTime, DateGetMsecSinceEpoch, Handle, JS_ClearPendingException, JSObject, NewDateObject,
NewUCRegExpObject, ObjectIsDate, RegExpFlag_UnicodeSets, RegExpFlags,
@@ -25,7 +29,9 @@ use js::rust::{HandleObject, MutableHandleObject};
use net_traits::blob_url_store::get_blob_origin;
use net_traits::filemanager_thread::FileManagerThreadMsg;
use net_traits::{CoreResourceMsg, IpcSend};
-use profile_traits::ipc;
+use script_bindings::codegen::GenericBindings::ShadowRootBinding::{
+ ShadowRootMode, SlotAssignmentMode,
+};
use style::attr::AttrValue;
use style::str::{split_commas, str_join};
use stylo_atoms::Atom;
@@ -33,12 +39,12 @@ use stylo_dom::ElementState;
use time::{Month, OffsetDateTime, Time};
use unicode_bidi::{BidiClass, bidi_class};
use url::Url;
+use webrender_api::units::DeviceIntRect;
-use super::bindings::str::{FromInputValueString, ToInputValueString};
use crate::clipboard_provider::EmbedderClipboardProvider;
use crate::dom::activation::Activatable;
use crate::dom::attr::Attr;
-use crate::dom::bindings::cell::DomRefCell;
+use crate::dom::bindings::cell::{DomRefCell, Ref};
use crate::dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
use crate::dom::bindings::codegen::Bindings::EventBinding::EventMethods;
use crate::dom::bindings::codegen::Bindings::FileListBinding::FileListMethods;
@@ -48,30 +54,33 @@ use crate::dom::bindings::codegen::Bindings::NodeBinding::{GetRootNodeOptions, N
use crate::dom::bindings::error::{Error, ErrorResult};
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::reflector::DomGlobal;
-use crate::dom::bindings::root::{DomRoot, LayoutDom, MutNullableDom};
-use crate::dom::bindings::str::{DOMString, USVString};
+use crate::dom::bindings::root::{Dom, DomRoot, LayoutDom, MutNullableDom};
+use crate::dom::bindings::str::{DOMString, FromInputValueString, ToInputValueString, USVString};
use crate::dom::clipboardevent::ClipboardEvent;
use crate::dom::compositionevent::CompositionEvent;
use crate::dom::document::Document;
-use crate::dom::element::{AttributeMutation, Element, LayoutElementHelpers};
+use crate::dom::element::{AttributeMutation, Element, ElementCreator, LayoutElementHelpers};
use crate::dom::event::{Event, EventBubbles, EventCancelable};
use crate::dom::eventtarget::EventTarget;
use crate::dom::file::File;
use crate::dom::filelist::{FileList, LayoutFileListHelpers};
use crate::dom::globalscope::GlobalScope;
use crate::dom::htmldatalistelement::HTMLDataListElement;
+use crate::dom::htmldivelement::HTMLDivElement;
use crate::dom::htmlelement::HTMLElement;
use crate::dom::htmlfieldsetelement::HTMLFieldSetElement;
use crate::dom::htmlformelement::{
FormControl, FormDatum, FormDatumValue, FormSubmitterElement, HTMLFormElement, ResetFrom,
SubmittedFrom,
};
+use crate::dom::htmlstyleelement::HTMLStyleElement;
use crate::dom::keyboardevent::KeyboardEvent;
use crate::dom::mouseevent::MouseEvent;
use crate::dom::node::{
BindContext, CloneChildrenFlag, Node, NodeDamage, NodeTraits, ShadowIncluding, UnbindContext,
};
use crate::dom::nodelist::NodeList;
+use crate::dom::shadowroot::{IsUserAgentWidget, ShadowRoot};
use crate::dom::textcontrol::{TextControlElement, TextControlSelection};
use crate::dom::validation::{Validatable, is_barred_by_datalist_ancestor};
use crate::dom::validitystate::{ValidationFlags, ValidityState};
@@ -92,6 +101,34 @@ const DEFAULT_RESET_VALUE: &str = "Reset";
const PASSWORD_REPLACEMENT_CHAR: char = '●';
const DEFAULT_FILE_INPUT_VALUE: &str = "No file chosen";
+#[derive(Clone, JSTraceable, MallocSizeOf)]
+#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
+/// Contains references to the elements in the shadow tree for ``.
+///
+/// The shadow tree consists of a single div with the currently selected color as
+/// the background.
+struct InputTypeColorShadowTree {
+ color_value: Dom,
+}
+
+#[derive(Clone, JSTraceable, MallocSizeOf)]
+#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
+#[non_exhaustive]
+enum ShadowTree {
+ Color(InputTypeColorShadowTree),
+ // TODO: Add shadow trees for other input types (range etc) here
+}
+
+const COLOR_TREE_STYLE: &str = "
+#color-value {
+ width: 100%;
+ height: 100%;
+ box-sizing: border-box;
+ border: 1px solid gray;
+ border-radius: 2px;
+}
+";
+
///
#[derive(Clone, Copy, Default, JSTraceable, PartialEq)]
#[allow(dead_code)]
@@ -172,8 +209,7 @@ impl InputType {
fn is_textual(&self) -> bool {
matches!(
*self,
- InputType::Color |
- InputType::Date |
+ InputType::Date |
InputType::DatetimeLocal |
InputType::Email |
InputType::Hidden |
@@ -277,9 +313,16 @@ impl From<&Atom> for InputType {
#[derive(Debug, PartialEq)]
enum ValueMode {
+ ///
Value,
+
+ ///
Default,
+
+ ///
DefaultOn,
+
+ ///
Filename,
}
@@ -314,6 +357,7 @@ pub(crate) struct HTMLInputElement {
form_owner: MutNullableDom,
labels_node_list: MutNullableDom,
validity_state: MutNullableDom,
+ shadow_tree: DomRefCell