diff options
Diffstat (limited to 'components/gfx/display_list/mod.rs')
-rw-r--r-- | components/gfx/display_list/mod.rs | 105 |
1 files changed, 73 insertions, 32 deletions
diff --git a/components/gfx/display_list/mod.rs b/components/gfx/display_list/mod.rs index b0cb1e609a6..1d81f39f612 100644 --- a/components/gfx/display_list/mod.rs +++ b/components/gfx/display_list/mod.rs @@ -14,12 +14,13 @@ //! They are therefore not exactly analogous to constructs like Skia pictures, which consist of //! low-level drawing primitives. -use self::DisplayItem::*; -use self::DisplayItemIterator::*; +#![deny(unsafe_blocks)] use color::Color; use display_list::optimizer::DisplayListOptimizer; use paint_context::{PaintContext, ToAzureRect}; +use self::DisplayItem::*; +use self::DisplayItemIterator::*; use text::glyph::CharIndex; use text::TextRun; @@ -28,17 +29,18 @@ use collections::dlist::{mod, DList}; use geom::{Point2D, Rect, SideOffsets2D, Size2D, Matrix2D}; use libc::uintptr_t; use paint_task::PaintLayer; -use script_traits::UntrustedNodeAddress; use servo_msg::compositor_msg::LayerId; use servo_net::image::base::Image; +use servo_util::cursor::Cursor; use servo_util::dlist as servo_dlist; use servo_util::geometry::{mod, Au, ZERO_POINT}; use servo_util::range::Range; use servo_util::smallvec::{SmallVec, SmallVec8}; use std::fmt; -use std::mem; use std::slice::Items; +use style::ComputedValues; use style::computed_values::border_style; +use style::computed_values::cursor::{AutoCursor, SpecifiedCursor}; use sync::Arc; // It seems cleaner to have layout code not mention Azure directly, so let's just reexport this for @@ -338,20 +340,45 @@ impl StackingContext { /// upon entry to this function. pub fn hit_test(&self, point: Point2D<Au>, - result: &mut Vec<UntrustedNodeAddress>, + result: &mut Vec<DisplayItemMetadata>, topmost_only: bool) { fn hit_test_in_list<'a,I>(point: Point2D<Au>, - result: &mut Vec<UntrustedNodeAddress>, + result: &mut Vec<DisplayItemMetadata>, topmost_only: bool, mut iterator: I) where I: Iterator<&'a DisplayItem> { for item in iterator { - if geometry::rect_contains_point(item.base().clip_rect, point) && - geometry::rect_contains_point(item.bounds(), point) { - result.push(item.base().node.to_untrusted_node_address()); - if topmost_only { - return + if !geometry::rect_contains_point(item.base().clip_rect, point) { + // Clipped out. + continue + } + if !geometry::rect_contains_point(item.bounds(), point) { + // Can't possibly hit. + continue + } + match *item { + BorderDisplayItemClass(ref border) => { + // If the point is inside the border, it didn't hit the border! + let interior_rect = + Rect(Point2D(border.base.bounds.origin.x + border.border_widths.left, + border.base.bounds.origin.y + border.border_widths.top), + Size2D(border.base.bounds.size.width - + (border.border_widths.left + + border.border_widths.right), + border.base.bounds.size.height - + (border.border_widths.top + + border.border_widths.bottom))); + if geometry::rect_contains_point(interior_rect, point) { + continue + } } + _ => {} + } + + // We found a hit! + result.push(item.base().metadata); + if topmost_only { + return } } } @@ -447,8 +474,8 @@ pub struct BaseDisplayItem { /// The boundaries of the display item, in layer coordinates. pub bounds: Rect<Au>, - /// The originating DOM node. - pub node: OpaqueNode, + /// Metadata attached to this display item. + pub metadata: DisplayItemMetadata, /// The rectangle to clip to. /// @@ -459,15 +486,45 @@ pub struct BaseDisplayItem { impl BaseDisplayItem { #[inline(always)] - pub fn new(bounds: Rect<Au>, node: OpaqueNode, clip_rect: Rect<Au>) -> BaseDisplayItem { + pub fn new(bounds: Rect<Au>, metadata: DisplayItemMetadata, clip_rect: Rect<Au>) + -> BaseDisplayItem { BaseDisplayItem { bounds: bounds, - node: node, + metadata: metadata, clip_rect: clip_rect, } } } +/// Metadata attached to each display item. This is useful for performing auxiliary tasks with +/// the display list involving hit testing: finding the originating DOM node and determining the +/// cursor to use when the element is hovered over. +#[deriving(Clone)] +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, +} + +impl DisplayItemMetadata { + /// Creates a new set of display metadata for a display item constributed by a DOM node. + /// `default_cursor` specifies the cursor to use if `cursor` is `auto`. Typically, this will + /// be `PointerCursor`, but for text display items it may be `TextCursor` or + /// `VerticalTextCursor`. + #[inline] + pub fn new(node: OpaqueNode, style: &ComputedValues, default_cursor: Cursor) + -> DisplayItemMetadata { + DisplayItemMetadata { + node: node, + cursor: match style.get_pointing().cursor { + AutoCursor => default_cursor, + SpecifiedCursor(cursor) => cursor, + }, + } + } +} + /// Paints a solid color. #[deriving(Clone)] pub struct SolidColorDisplayItem { @@ -738,24 +795,8 @@ impl fmt::Show for DisplayItem { BoxShadowDisplayItemClass(_) => "BoxShadow", }, self.base().bounds, - self.base().node.id() + self.base().metadata.node.id() ) } } -pub trait OpaqueNodeMethods { - /// Converts this node to an `UntrustedNodeAddress`. An `UntrustedNodeAddress` is just the type - /// of node that script expects to receive in a hit test. - fn to_untrusted_node_address(&self) -> UntrustedNodeAddress; -} - - -impl OpaqueNodeMethods for OpaqueNode { - fn to_untrusted_node_address(&self) -> UntrustedNodeAddress { - unsafe { - let OpaqueNode(addr) = *self; - let addr: UntrustedNodeAddress = mem::transmute(addr); - addr - } - } -} |