diff options
-rw-r--r-- | components/gfx/display_list/mod.rs | 27 | ||||
-rw-r--r-- | components/layout/layout_task.rs | 2 | ||||
-rw-r--r-- | components/style/properties/mod.rs.mako | 5 | ||||
-rw-r--r-- | tests/html/pointer_events.html | 36 |
4 files changed, 58 insertions, 12 deletions
diff --git a/components/gfx/display_list/mod.rs b/components/gfx/display_list/mod.rs index 469d4121f6a..6d524a85cd2 100644 --- a/components/gfx/display_list/mod.rs +++ b/components/gfx/display_list/mod.rs @@ -39,10 +39,9 @@ use servo_util::range::Range; use servo_util::smallvec::{SmallVec, SmallVec8}; use std::fmt; use std::slice::Items; -use style::ComputedValues; -use style::computed_values::border_style; -use style::computed_values::cursor; use std::sync::Arc; +use style::ComputedValues; +use style::computed_values::{border_style, cursor, pointer_events}; // It seems cleaner to have layout code not mention Azure directly, so let's just reexport this for // layout to use. @@ -340,9 +339,9 @@ impl StackingContext { tile_subrect.translate(&-child_stacking_context.bounds.to_azure_rect().origin) } - /// Places all nodes containing the point of interest into `result`, topmost first. If - /// `topmost_only` is true, stops after placing one node into the list. `result` must be empty - /// upon entry to this function. + /// Places all nodes containing the point of interest into `result`, topmost first. Respects + /// the `pointer-events` CSS property If `topmost_only` is true, stops after placing one node + /// into the list. `result` must be empty upon entry to this function. pub fn hit_test(&self, point: Point2D<Au>, result: &mut Vec<DisplayItemMetadata>, @@ -363,6 +362,10 @@ impl StackingContext { // Can't possibly hit. continue } + if item.base().metadata.pointing.is_none() { + // `pointer-events` is `none`. Ignore this item. + continue + } match *item { DisplayItem::BorderClass(ref border) => { // If the point is inside the border, it didn't hit the border! @@ -632,8 +635,9 @@ impl ClippingRegion { pub struct DisplayItemMetadata { /// The DOM node from which this display item originated. pub node: OpaqueNode, - /// The value of the `cursor` property when the mouse hovers over this display item. - pub cursor: Cursor, + /// The value of the `cursor` property when the mouse hovers over this display item. If `None`, + /// this display item is ineligible for pointer events (`pointer-events: none`). + pub pointing: Option<Cursor>, } impl DisplayItemMetadata { @@ -646,9 +650,10 @@ impl DisplayItemMetadata { -> DisplayItemMetadata { DisplayItemMetadata { node: node, - cursor: match style.get_pointing().cursor { - cursor::T::AutoCursor => default_cursor, - cursor::T::SpecifiedCursor(cursor) => cursor, + pointing: match (style.get_pointing().pointer_events, style.get_pointing().cursor) { + (pointer_events::T::none, _) => None, + (pointer_events::T::auto, cursor::T::AutoCursor) => Some(default_cursor), + (pointer_events::T::auto, cursor::T::SpecifiedCursor(cursor)) => Some(cursor), }, } } diff --git a/components/layout/layout_task.rs b/components/layout/layout_task.rs index 48c1bb10496..f5301c27867 100644 --- a/components/layout/layout_task.rs +++ b/components/layout/layout_task.rs @@ -998,7 +998,7 @@ impl LayoutRPC for LayoutRPCImpl { // Compute the new cursor. let cursor = if !mouse_over_list.is_empty() { - mouse_over_list[0].cursor + mouse_over_list[0].pointing.unwrap() } else { Cursor::DefaultCursor }; diff --git a/components/style/properties/mod.rs.mako b/components/style/properties/mod.rs.mako index 18c947f3dff..272b6bade4d 100644 --- a/components/style/properties/mod.rs.mako +++ b/components/style/properties/mod.rs.mako @@ -1543,6 +1543,11 @@ pub mod longhands { } </%self:single_component_value> + // NB: `pointer-events: auto` (and use of `pointer-events` in anything that isn't SVG, in fact) + // is nonstandard, slated for CSS4-UI. + // TODO(pcwalton): SVG-only values. + ${single_keyword("pointer-events", "auto none")} + // Box-shadow, etc. ${new_style_struct("Effects", is_inherited=False)} diff --git a/tests/html/pointer_events.html b/tests/html/pointer_events.html new file mode 100644 index 00000000000..dc1581f98c3 --- /dev/null +++ b/tests/html/pointer_events.html @@ -0,0 +1,36 @@ +<!DOCTYPE html> +<html> +<head> +<style> +#overlay { + width: 200px; + height: 150px; + background: green; + opacity: 0.5; + pointer-events: none; +} + +button { + position: relative; + top: 10px; + width: 150px; + height: 50px; + border: solid black 2px; + box-sizing: border-box; + font: Helvetica bold; + font-size: 18px; + text-align: center; + background: black; + color: white; +} +</style> +</head> +<body> +<button id=button>Click me!</button> +<div id=overlay></div> +<script> +document.getElementById('button').addEventListener('click', function() { alert("Ouch!"); }); +</script> +</body> +</html> + |