diff options
-rw-r--r-- | components/script/dom/activation.rs | 22 | ||||
-rw-r--r-- | components/script/dom/document.rs | 16 | ||||
-rw-r--r-- | components/script/dom/element.rs | 7 | ||||
-rw-r--r-- | components/script/dom/window.rs | 2 | ||||
-rw-r--r-- | tests/html/active_selector.html | 18 |
5 files changed, 63 insertions, 2 deletions
diff --git a/components/script/dom/activation.rs b/components/script/dom/activation.rs index ff8d59aac96..5c59393f766 100644 --- a/components/script/dom/activation.rs +++ b/components/script/dom/activation.rs @@ -10,6 +10,9 @@ use dom::event::{Event, EventBubbles, EventCancelable}; use dom::eventtarget::EventTarget; use dom::mouseevent::MouseEvent; use dom::node::window_from_node; +use dom::window::ReflowReason; +use script_layout_interface::message::ReflowQueryType; +use style::context::ReflowGoal; /// Trait for elements with defined activation behavior pub trait Activatable { @@ -29,6 +32,25 @@ pub trait Activatable { // https://html.spec.whatwg.org/multipage/#implicit-submission fn implicit_submission(&self, ctrlKey: bool, shiftKey: bool, altKey: bool, metaKey: bool); + + // https://html.spec.whatwg.org/multipage/#concept-selector-active + fn enter_formal_activation_state(&self) { + self.as_element().set_active_state(true); + + let win = window_from_node(self.as_element()); + win.reflow(ReflowGoal::ForDisplay, + ReflowQueryType::NoQuery, + ReflowReason::ElementStateChanged); + } + + fn exit_formal_activation_state(&self) { + self.as_element().set_active_state(false); + + let win = window_from_node(self.as_element()); + win.reflow(ReflowGoal::ForDisplay, + ReflowQueryType::NoQuery, + ReflowReason::ElementStateChanged); + } } /// Whether an activation was initiated via the click() method diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 8c3ee29bf1a..f0a77d85f39 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -735,9 +735,22 @@ impl Document { // https://w3c.github.io/uievents/#trusted-events event.set_trusted(true); // https://html.spec.whatwg.org/multipage/#run-authentic-click-activation-steps + let activatable = el.as_maybe_activatable(); match mouse_event_type { MouseEventType::Click => el.authentic_click_activation(event), - _ => { + MouseEventType::MouseDown => { + if let Some(a) = activatable { + a.enter_formal_activation_state(); + } + + let target = node.upcast(); + event.fire(target); + }, + MouseEventType::MouseUp => { + if let Some(a) = activatable { + a.exit_formal_activation_state(); + } + let target = node.upcast(); event.fire(target); }, @@ -904,6 +917,7 @@ impl Document { .inclusive_ancestors() .filter_map(Root::downcast::<Element>) { element.set_hover_state(false); + element.set_active_state(false); } } diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index 479a73dee86..939561e9d1a 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -2519,8 +2519,13 @@ impl Element { self.state.get().contains(IN_ACTIVE_STATE) } + /// https://html.spec.whatwg.org/multipage/#concept-selector-active pub fn set_active_state(&self, value: bool) { - self.set_state(IN_ACTIVE_STATE, value) + self.set_state(IN_ACTIVE_STATE, value); + + if let Some(parent) = self.upcast::<Node>().GetParentElement() { + parent.set_active_state(value); + } } pub fn focus_state(&self) -> bool { diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index 6f012e9c31e..2fc1824cde0 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -129,6 +129,7 @@ pub enum ReflowReason { FramedContentChanged, IFrameLoadEvent, MissingExplicitReflow, + ElementStateChanged, } pub type ScrollPoint = Point2D<Au>; @@ -1753,6 +1754,7 @@ fn debug_reflow_events(id: PipelineId, goal: &ReflowGoal, query_type: &ReflowQue ReflowReason::FramedContentChanged => "\tFramedContentChanged", ReflowReason::IFrameLoadEvent => "\tIFrameLoadEvent", ReflowReason::MissingExplicitReflow => "\tMissingExplicitReflow", + ReflowReason::ElementStateChanged => "\tElementStateChanged", }); println!("{}", debug_msg); diff --git a/tests/html/active_selector.html b/tests/html/active_selector.html new file mode 100644 index 00000000000..8bf352b2dcc --- /dev/null +++ b/tests/html/active_selector.html @@ -0,0 +1,18 @@ +<!DOCTYPE html> +<html> +<style> +:active {border:1px solid #A61D61; background-color:#DC2F85; color:#333232;} +</style> +<body> + <fieldset> + <a href="https://servo.org/"> + Link + </a> + <button>Click Me!</button> + <button disabled>You can't activate me</button> + <a>Anchor with no href</a> + <link href="www.mozilla.com">Link</link> + <link>Link with no href</link> + </fieldset> +</body> +</html> |