mirror of
https://github.com/servo/servo.git
synced 2025-06-11 01:50:10 +00:00
commit
4fac8b6810
7 changed files with 65 additions and 20 deletions
|
@ -10,6 +10,7 @@
|
||||||
use animation;
|
use animation;
|
||||||
use construct::ConstructionResult;
|
use construct::ConstructionResult;
|
||||||
use context::{SharedLayoutContext, SharedLayoutContextWrapper};
|
use context::{SharedLayoutContext, SharedLayoutContextWrapper};
|
||||||
|
use css::node_style::StyledNode;
|
||||||
use display_list_builder::ToGfxColor;
|
use display_list_builder::ToGfxColor;
|
||||||
use flow::{self, Flow, ImmutableFlowUtils, MutableFlowUtils, MutableOwnedFlowUtils};
|
use flow::{self, Flow, ImmutableFlowUtils, MutableFlowUtils, MutableOwnedFlowUtils};
|
||||||
use flow_ref::FlowRef;
|
use flow_ref::FlowRef;
|
||||||
|
@ -713,7 +714,10 @@ impl LayoutTask {
|
||||||
let requested_node: OpaqueNode = OpaqueNodeMethods::from_script_node(requested_node);
|
let requested_node: OpaqueNode = OpaqueNodeMethods::from_script_node(requested_node);
|
||||||
let mut iterator = UnioningFragmentBorderBoxIterator::new(requested_node);
|
let mut iterator = UnioningFragmentBorderBoxIterator::new(requested_node);
|
||||||
sequential::iterate_through_flow_tree_fragment_border_boxes(layout_root, &mut iterator);
|
sequential::iterate_through_flow_tree_fragment_border_boxes(layout_root, &mut iterator);
|
||||||
rw_data.content_box_response = iterator.rect;
|
rw_data.content_box_response = match iterator.rect {
|
||||||
|
Some(rect) => rect,
|
||||||
|
None => Rect::zero()
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_content_boxes_request<'a>(&'a self,
|
fn process_content_boxes_request<'a>(&'a self,
|
||||||
|
@ -1158,25 +1162,28 @@ impl LayoutRPC for LayoutRPCImpl {
|
||||||
|
|
||||||
struct UnioningFragmentBorderBoxIterator {
|
struct UnioningFragmentBorderBoxIterator {
|
||||||
node_address: OpaqueNode,
|
node_address: OpaqueNode,
|
||||||
rect: Rect<Au>,
|
rect: Option<Rect<Au>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UnioningFragmentBorderBoxIterator {
|
impl UnioningFragmentBorderBoxIterator {
|
||||||
fn new(node_address: OpaqueNode) -> UnioningFragmentBorderBoxIterator {
|
fn new(node_address: OpaqueNode) -> UnioningFragmentBorderBoxIterator {
|
||||||
UnioningFragmentBorderBoxIterator {
|
UnioningFragmentBorderBoxIterator {
|
||||||
node_address: node_address,
|
node_address: node_address,
|
||||||
rect: Rect::zero(),
|
rect: None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FragmentBorderBoxIterator for UnioningFragmentBorderBoxIterator {
|
impl FragmentBorderBoxIterator for UnioningFragmentBorderBoxIterator {
|
||||||
fn process(&mut self, _: &Fragment, border_box: &Rect<Au>) {
|
fn process(&mut self, _: &Fragment, border_box: &Rect<Au>) {
|
||||||
self.rect = if self.rect.is_empty() {
|
self.rect = match self.rect {
|
||||||
*border_box
|
Some(rect) => {
|
||||||
} else {
|
Some(rect.union(border_box))
|
||||||
self.rect.union(border_box)
|
|
||||||
}
|
}
|
||||||
|
None => {
|
||||||
|
Some(*border_box)
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn should_process(&mut self, fragment: &Fragment) -> bool {
|
fn should_process(&mut self, fragment: &Fragment) -> bool {
|
||||||
|
|
|
@ -27,7 +27,7 @@ pub trait Activatable : Copy {
|
||||||
fn canceled_activation(&self);
|
fn canceled_activation(&self);
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/interaction.html#run-post-click-activation-steps
|
// https://html.spec.whatwg.org/multipage/interaction.html#run-post-click-activation-steps
|
||||||
fn activation_behavior(&self);
|
fn activation_behavior(&self, event: JSRef<Event>, target: JSRef<EventTarget>);
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/forms.html#implicit-submission
|
// https://html.spec.whatwg.org/multipage/forms.html#implicit-submission
|
||||||
fn implicit_submission(&self, ctrlKey: bool, shiftKey: bool, altKey: bool, metaKey: bool);
|
fn implicit_submission(&self, ctrlKey: bool, shiftKey: bool, altKey: bool, metaKey: bool);
|
||||||
|
@ -60,7 +60,7 @@ pub trait Activatable : Copy {
|
||||||
self.canceled_activation();
|
self.canceled_activation();
|
||||||
} else {
|
} else {
|
||||||
// post click activation
|
// post click activation
|
||||||
self.activation_behavior();
|
self.activation_behavior(event, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 6
|
// Step 6
|
||||||
|
|
|
@ -1675,7 +1675,7 @@ impl<'a> ActivationElementHelpers<'a> for JSRef<'a, Element> {
|
||||||
event.fire(target);
|
event.fire(target);
|
||||||
if !event.DefaultPrevented() {
|
if !event.DefaultPrevented() {
|
||||||
// post click activation
|
// post click activation
|
||||||
elem.activation_behavior();
|
elem.activation_behavior(event, target);
|
||||||
} else {
|
} else {
|
||||||
elem.canceled_activation();
|
elem.canceled_activation();
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,14 +2,17 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
|
||||||
use dom::activation::Activatable;
|
use dom::activation::Activatable;
|
||||||
use dom::attr::AttrValue;
|
use dom::attr::AttrValue;
|
||||||
use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
|
use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
|
||||||
use dom::bindings::codegen::Bindings::HTMLAnchorElementBinding;
|
use dom::bindings::codegen::Bindings::HTMLAnchorElementBinding;
|
||||||
use dom::bindings::codegen::Bindings::HTMLAnchorElementBinding::HTMLAnchorElementMethods;
|
use dom::bindings::codegen::Bindings::HTMLAnchorElementBinding::HTMLAnchorElementMethods;
|
||||||
|
use dom::bindings::codegen::Bindings::MouseEventBinding::MouseEventMethods;
|
||||||
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
|
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
|
||||||
use dom::bindings::codegen::InheritTypes::HTMLAnchorElementDerived;
|
use dom::bindings::codegen::InheritTypes::{HTMLAnchorElementDerived, HTMLImageElementDerived};
|
||||||
use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast, NodeCast};
|
use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast};
|
||||||
|
use dom::bindings::codegen::InheritTypes::{MouseEventCast, NodeCast};
|
||||||
use dom::bindings::js::{MutNullableJS, JSRef, Temporary, OptionalRootable};
|
use dom::bindings::js::{MutNullableJS, JSRef, Temporary, OptionalRootable};
|
||||||
use dom::document::{Document, DocumentHelpers};
|
use dom::document::{Document, DocumentHelpers};
|
||||||
use dom::domtokenlist::DOMTokenList;
|
use dom::domtokenlist::DOMTokenList;
|
||||||
|
@ -17,10 +20,12 @@ use dom::element::{Element, AttributeHandlers, ElementTypeId};
|
||||||
use dom::event::Event;
|
use dom::event::Event;
|
||||||
use dom::eventtarget::{EventTarget, EventTargetTypeId};
|
use dom::eventtarget::{EventTarget, EventTargetTypeId};
|
||||||
use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
|
use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
|
||||||
use dom::node::{Node, NodeHelpers, NodeTypeId, document_from_node};
|
use dom::node::{Node, NodeHelpers, NodeTypeId, document_from_node, window_from_node};
|
||||||
use dom::virtualmethods::VirtualMethods;
|
use dom::virtualmethods::VirtualMethods;
|
||||||
|
use dom::window::WindowHelpers;
|
||||||
|
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
|
use std::num::ToPrimitive;
|
||||||
use string_cache::Atom;
|
use string_cache::Atom;
|
||||||
use util::str::DOMString;
|
use util::str::DOMString;
|
||||||
|
|
||||||
|
@ -112,20 +117,35 @@ impl<'a> Activatable for JSRef<'a, HTMLAnchorElement> {
|
||||||
}
|
}
|
||||||
|
|
||||||
//https://html.spec.whatwg.org/multipage/semantics.html#the-a-element:activation-behaviour
|
//https://html.spec.whatwg.org/multipage/semantics.html#the-a-element:activation-behaviour
|
||||||
fn activation_behavior(&self) {
|
fn activation_behavior(&self, event: JSRef<Event>, target: JSRef<EventTarget>) {
|
||||||
//Step 1. If the node document is not fully active, abort.
|
//Step 1. If the node document is not fully active, abort.
|
||||||
let doc = document_from_node(*self).root();
|
let doc = document_from_node(*self).root();
|
||||||
if !doc.r().is_fully_active() {
|
if !doc.r().is_fully_active() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//TODO: Step 2. Check if browsing context is specified and act accordingly.
|
//TODO: Step 2. Check if browsing context is specified and act accordingly.
|
||||||
//TODO: Step 3. Handle <img ismap/>.
|
//Step 3. Handle <img ismap/>.
|
||||||
//TODO: Step 4. Download the link is `download` attribute is set.
|
|
||||||
let element: JSRef<Element> = ElementCast::from_ref(*self);
|
let element: JSRef<Element> = ElementCast::from_ref(*self);
|
||||||
|
let mouse_event = MouseEventCast::to_ref(event).unwrap();
|
||||||
|
let mut ismap_suffix = None;
|
||||||
|
if let Some(element) = ElementCast::to_ref(target) {
|
||||||
|
if target.is_htmlimageelement() && element.has_attribute(&atom!("ismap")) {
|
||||||
|
|
||||||
|
let target_node = NodeCast::to_ref(target).unwrap();
|
||||||
|
let rect = window_from_node(target_node).root().r().content_box_query(target_node.to_trusted_node_address());
|
||||||
|
ismap_suffix = Some(
|
||||||
|
format!("?{},{}", mouse_event.ClientX().to_f32().unwrap() - rect.origin.x.to_frac32_px(),
|
||||||
|
mouse_event.ClientY().to_f32().unwrap() - rect.origin.y.to_frac32_px())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: Step 4. Download the link is `download` attribute is set.
|
||||||
|
|
||||||
let attr = element.get_attribute(&ns!(""), &atom!("href")).root();
|
let attr = element.get_attribute(&ns!(""), &atom!("href")).root();
|
||||||
match attr {
|
match attr {
|
||||||
Some(ref href) => {
|
Some(ref href) => {
|
||||||
let value = href.r().Value();
|
let value = href.r().Value() + ismap_suffix.as_ref().map(|s| &**s).unwrap_or("");
|
||||||
debug!("clicked on link to {}", value);
|
debug!("clicked on link to {}", value);
|
||||||
doc.r().load_anchor_href(value);
|
doc.r().load_anchor_href(value);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ use dom::bindings::js::{JSRef, Temporary};
|
||||||
use dom::document::Document;
|
use dom::document::Document;
|
||||||
use dom::element::{AttributeHandlers, Element, ElementTypeId};
|
use dom::element::{AttributeHandlers, Element, ElementTypeId};
|
||||||
use dom::element::ActivationElementHelpers;
|
use dom::element::ActivationElementHelpers;
|
||||||
|
use dom::event::Event;
|
||||||
use dom::eventtarget::{EventTarget, EventTargetTypeId};
|
use dom::eventtarget::{EventTarget, EventTargetTypeId};
|
||||||
use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
|
use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
|
||||||
use dom::htmlformelement::{FormSubmitter, FormControl, HTMLFormElementHelpers};
|
use dom::htmlformelement::{FormSubmitter, FormControl, HTMLFormElementHelpers};
|
||||||
|
@ -196,7 +197,7 @@ impl<'a> Activatable for JSRef<'a, HTMLButtonElement> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/interaction.html#run-post-click-activation-steps
|
// https://html.spec.whatwg.org/multipage/interaction.html#run-post-click-activation-steps
|
||||||
fn activation_behavior(&self) {
|
fn activation_behavior(&self, _event: JSRef<Event>, _target: JSRef<EventTarget>) {
|
||||||
let ty = self.button_type.get();
|
let ty = self.button_type.get();
|
||||||
match ty {
|
match ty {
|
||||||
//https://html.spec.whatwg.org/multipage/forms.html#attr-button-type-submit-state
|
//https://html.spec.whatwg.org/multipage/forms.html#attr-button-type-submit-state
|
||||||
|
|
|
@ -753,7 +753,7 @@ impl<'a> Activatable for JSRef<'a, HTMLInputElement> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/interaction.html#run-post-click-activation-steps
|
// https://html.spec.whatwg.org/multipage/interaction.html#run-post-click-activation-steps
|
||||||
fn activation_behavior(&self) {
|
fn activation_behavior(&self, _event: JSRef<Event>, _target: JSRef<EventTarget>) {
|
||||||
let ty = self.input_type.get();
|
let ty = self.input_type.get();
|
||||||
if self.activation_state.borrow().old_type != ty {
|
if self.activation_state.borrow().old_type != ty {
|
||||||
// Type changed, abandon ship
|
// Type changed, abandon ship
|
||||||
|
|
17
tests/html/test_img_ismap.html
Normal file
17
tests/html/test_img_ismap.html
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>img element ismap activation test</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>Click my nose to get the coordinates!</p>
|
||||||
|
<a href="test_img_ismap.html">
|
||||||
|
<img src="andreas.jpeg" alt="andreas" ismap/>
|
||||||
|
</a>
|
||||||
|
<p>Nothing happends if you click my nose</p>
|
||||||
|
<a href="test_img_ismap.html">
|
||||||
|
<img src="andreas.jpeg" alt="andreas"/>
|
||||||
|
</a>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Add table
Add a link
Reference in a new issue