diff --git a/Cargo.lock b/Cargo.lock index c3147a11ec..59cebe5a35 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1029,7 +1029,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "webrender" -version = "0.54.0" +version = "0.55.0" dependencies = [ "angle 0.5.0 (git+https://github.com/servo/angle?branch=servo)", "app_units 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1057,13 +1057,13 @@ dependencies = [ "servo-glutin 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", "thread_profiler 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_api 0.54.0", + "webrender_api 0.55.0", "ws 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "webrender_api" -version = "0.54.0" +version = "0.55.0" dependencies = [ "app_units 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "bincode 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1090,7 +1090,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "wrench" -version = "0.2.4" +version = "0.2.5" dependencies = [ "app_units 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "base64 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1112,7 +1112,7 @@ dependencies = [ "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "servo-glutin 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender 0.54.0", + "webrender 0.55.0", "yaml-rust 0.3.4 (git+https://github.com/vvuk/yaml-rust)", ] diff --git a/webrender/Cargo.toml b/webrender/Cargo.toml index 3587f09be3..379d8d439b 100644 --- a/webrender/Cargo.toml +++ b/webrender/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "webrender" -version = "0.54.0" +version = "0.55.0" authors = ["Glenn Watson "] license = "MPL-2.0" repository = "https://github.com/servo/webrender" diff --git a/webrender/examples/scrolling.rs b/webrender/examples/scrolling.rs index 31e072af1b..59c78fec92 100644 --- a/webrender/examples/scrolling.rs +++ b/webrender/examples/scrolling.rs @@ -63,6 +63,7 @@ impl Example for App { vec![], None, ScrollSensitivity::ScriptAndInputEvents, + IframeScrollbars::Disabled ); builder.push_clip_id(clip_id); @@ -91,6 +92,7 @@ impl Example for App { vec![], None, ScrollSensitivity::ScriptAndInputEvents, + IframeScrollbars::Enabled ); builder.push_clip_id(nested_clip_id); diff --git a/webrender/src/clip_scroll_node.rs b/webrender/src/clip_scroll_node.rs index 3eeca0955d..4a39b39f99 100644 --- a/webrender/src/clip_scroll_node.rs +++ b/webrender/src/clip_scroll_node.rs @@ -161,7 +161,7 @@ impl ClipScrollNode { parent_id: ClipId, frame_rect: &LayerRect, content_size: &LayerSize, - scroll_sensitivity: ScrollSensitivity, + scroll_sensitivity: ScrollSensitivity ) -> Self { let node_type = NodeType::ScrollFrame(ScrollingState::new( scroll_sensitivity, @@ -747,7 +747,7 @@ pub struct ScrollingState { /// Manages scrolling offset, overscroll state, etc. impl ScrollingState { pub fn new(scroll_sensitivity: ScrollSensitivity, - scrollable_size: LayerSize + scrollable_size: LayerSize, ) -> ScrollingState { ScrollingState { offset: LayerVector2D::zero(), diff --git a/webrender/src/frame.rs b/webrender/src/frame.rs index 9f0921ff13..b35559c40a 100644 --- a/webrender/src/frame.rs +++ b/webrender/src/frame.rs @@ -8,7 +8,7 @@ use api::{DeviceUintRect, DeviceUintSize, DisplayItemRef, DocumentLayer, Epoch, use api::{ImageDisplayItem, ItemRange, LayerPoint, LayerPrimitiveInfo, LayerRect}; use api::{LayerSize, LayerVector2D}; use api::{LayoutRect, LayoutSize}; -use api::{LocalClip, PipelineId, ScrollClamping, ScrollEventPhase, ScrollLayerState}; +use api::{LocalClip, PipelineId, ScrollClamping, ScrollEventPhase, ScrollLayerState, IframeScrollbars}; use api::{ScrollLocation, ScrollPolicy, ScrollSensitivity, SpecificDisplayItem, StackingContext}; use api::{ClipMode, TileOffset, TransformStyle, WorldPoint}; use clip::ClipRegion; @@ -28,7 +28,7 @@ use util::ComplexClipRegionHelpers; #[derive(Copy, Clone, PartialEq, PartialOrd, Debug, Eq, Ord)] pub struct FrameId(pub u32); -static DEFAULT_SCROLLBAR_COLOR: ColorF = ColorF { +pub static DEFAULT_SCROLLBAR_COLOR: ColorF = ColorF { r: 0.3, g: 0.3, b: 0.3, @@ -196,6 +196,7 @@ impl<'a> FlattenContext<'a> { content_rect: &LayerRect, clip_region: ClipRegion, scroll_sensitivity: ScrollSensitivity, + enable_scrollbars: bool ) { let clip_id = self.clip_scroll_tree.generate_new_clip_id(pipeline_id); self.builder.add_clip_node( @@ -213,6 +214,7 @@ impl<'a> FlattenContext<'a> { &frame_rect, &content_rect.size, scroll_sensitivity, + enable_scrollbars, self.clip_scroll_tree, ); } @@ -362,6 +364,7 @@ impl<'a> FlattenContext<'a> { &iframe_rect, &pipeline.content_size, ScrollSensitivity::ScriptAndInputEvents, + false, self.clip_scroll_tree, ); @@ -589,6 +592,9 @@ impl<'a> FlattenContext<'a> { .clip_rect() .translate(&reference_frame_relative_offset); let content_rect = item.rect().translate(&reference_frame_relative_offset); + + let enable_scrollbars = IframeScrollbars::Enabled == info.enable_scrollbars; + self.flatten_scroll_frame( pipeline_id, &clip_and_scroll.scroll_node_id, @@ -597,6 +603,7 @@ impl<'a> FlattenContext<'a> { &content_rect, clip_region, info.scroll_sensitivity, + enable_scrollbars ); } SpecificDisplayItem::StickyFrame(ref info) => { diff --git a/webrender/src/frame_builder.rs b/webrender/src/frame_builder.rs index 3805cd1994..b0504f9c88 100644 --- a/webrender/src/frame_builder.rs +++ b/webrender/src/frame_builder.rs @@ -18,7 +18,7 @@ use clip::{ClipRegion, ClipSource, ClipSources, ClipStore, Contains, MAX_CLIP}; use clip_scroll_node::{ClipScrollNode, NodeType}; use clip_scroll_tree::ClipScrollTree; use euclid::{SideOffsets2D, vec2}; -use frame::FrameId; +use frame::{FrameId, DEFAULT_SCROLLBAR_COLOR}; use glyph_rasterizer::FontInstance; use gpu_cache::GpuCache; use internal_types::{FastHashMap, FastHashSet}; @@ -117,6 +117,8 @@ pub struct FrameBuilder { /// A stack of the current pictures, used during scene building. pub picture_stack: Vec, + parent_scroll_frame_id: ClipId, + pending_scrollbar_info: Option<(ClipId, ClipId, LayerRect)>, /// A temporary stack of stacking context properties, used only /// during scene building. @@ -147,7 +149,9 @@ impl<'a> PrimitiveContext<'a> { } impl FrameBuilder { - pub fn empty() -> Self { + pub fn empty() -> Self { + let dummy_pipeline = PipelineId::dummy(); + FrameBuilder { hit_testing_runs: Vec::new(), shadow_prim_stack: Vec::new(), @@ -155,6 +159,8 @@ impl FrameBuilder { scrollbar_prims: Vec::new(), reference_frame_stack: Vec::new(), picture_stack: Vec::new(), + parent_scroll_frame_id: ClipId::root_scroll_node(dummy_pipeline), + pending_scrollbar_info: None, sc_stack: Vec::new(), prim_store: PrimitiveStore::new(), clip_store: ClipStore::new(), @@ -181,6 +187,8 @@ impl FrameBuilder { scrollbar_prims: recycle_vec(self.scrollbar_prims), reference_frame_stack: recycle_vec(self.reference_frame_stack), picture_stack: recycle_vec(self.picture_stack), + parent_scroll_frame_id: self.parent_scroll_frame_id, + pending_scrollbar_info: self.pending_scrollbar_info, sc_stack: recycle_vec(self.sc_stack), prim_store: self.prim_store.recycle(), clip_store: self.clip_store.recycle(), @@ -556,6 +564,11 @@ impl FrameBuilder { self.shadow_prim_stack.is_empty(), "Found unpopped text shadows when popping stacking context!" ); + + self.add_pending_scrollbars(); + assert!(self.pending_scrollbar_info.is_none(), + "Found pending scrollbar info when popping stacking context!" + ); } pub fn push_reference_frame( @@ -660,6 +673,7 @@ impl FrameBuilder { &viewport_rect, content_size, ScrollSensitivity::ScriptAndInputEvents, + false, clip_scroll_tree, ); @@ -692,6 +706,7 @@ impl FrameBuilder { frame_rect: &LayerRect, content_size: &LayerSize, scroll_sensitivity: ScrollSensitivity, + enable_scrollbars: bool, clip_scroll_tree: &mut ClipScrollTree, ) { let node = ClipScrollNode::new_scroll_frame( @@ -699,10 +714,34 @@ impl FrameBuilder { parent_id, frame_rect, content_size, - scroll_sensitivity, + scroll_sensitivity ); - + clip_scroll_tree.add_node(node, new_node_id); + + if enable_scrollbars { + self.add_pending_scrollbars(); + + // The root scroll node will never have enable_scrollbars set to true, so there will a parent_scroll_frame id + let parent_scroll_frame_id = self.parent_scroll_frame_id; + self.pending_scrollbar_info = Some((parent_scroll_frame_id, new_node_id, *frame_rect)); + } + + self.parent_scroll_frame_id = new_node_id; + } + + fn add_pending_scrollbars(&mut self) { + if let Some((parent_scroll_frame_id, clip_id, frame_rect)) = self.pending_scrollbar_info { + let scrollbar_rect = LayerRect::new(LayerPoint::zero(), LayerSize::new(10.0, 70.0)); + self.add_solid_rectangle( + ClipAndScrollInfo::simple(parent_scroll_frame_id), + &LayerPrimitiveInfo::new(scrollbar_rect), + RectangleContent::Fill(DEFAULT_SCROLLBAR_COLOR), + Some(ScrollbarInfo(clip_id, frame_rect)) + ); + + self.pending_scrollbar_info = None; + } } pub fn pop_reference_frame(&mut self) { diff --git a/webrender_api/Cargo.toml b/webrender_api/Cargo.toml index accb88f3a8..1ab8d29c27 100644 --- a/webrender_api/Cargo.toml +++ b/webrender_api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "webrender_api" -version = "0.54.0" +version = "0.55.0" authors = ["Glenn Watson "] license = "MPL-2.0" repository = "https://github.com/servo/webrender" diff --git a/webrender_api/src/display_item.rs b/webrender_api/src/display_item.rs index 9dddb07880..d193fe766f 100644 --- a/webrender_api/src/display_item.rs +++ b/webrender_api/src/display_item.rs @@ -194,6 +194,13 @@ pub struct ScrollFrameDisplayItem { pub id: ClipId, pub image_mask: Option, pub scroll_sensitivity: ScrollSensitivity, + pub enable_scrollbars: IframeScrollbars +} + +#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] +pub enum IframeScrollbars { + Enabled, + Disabled } #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] diff --git a/webrender_api/src/display_list.rs b/webrender_api/src/display_list.rs index 55df385846..50d9993e1d 100644 --- a/webrender_api/src/display_list.rs +++ b/webrender_api/src/display_list.rs @@ -11,7 +11,7 @@ use {LayoutTransform, LayoutVector2D, LineDisplayItem, LineOrientation, LineStyl use {MixBlendMode, PipelineId, PropertyBinding, PushStackingContextDisplayItem, RadialGradient}; use {RadialGradientDisplayItem, RectangleDisplayItem, ScrollFrameDisplayItem, ScrollPolicy}; use {ScrollSensitivity, Shadow, SpecificDisplayItem, StackingContext, StickyFrameDisplayItem}; -use {StickyOffsetBounds, TextDisplayItem, TransformStyle, YuvColorSpace, YuvData}; +use {StickyOffsetBounds, IframeScrollbars, TextDisplayItem, TransformStyle, YuvColorSpace, YuvData}; use YuvImageDisplayItem; use bincode; use euclid::SideOffsets2D; @@ -1217,6 +1217,7 @@ impl DisplayListBuilder { complex_clips: I, image_mask: Option, scroll_sensitivity: ScrollSensitivity, + enable_scrollbars: IframeScrollbars ) -> ClipId where I: IntoIterator, @@ -1230,7 +1231,8 @@ impl DisplayListBuilder { clip_rect, complex_clips, image_mask, - scroll_sensitivity) + scroll_sensitivity, + enable_scrollbars) } pub fn define_scroll_frame_with_parent( @@ -1242,6 +1244,7 @@ impl DisplayListBuilder { complex_clips: I, image_mask: Option, scroll_sensitivity: ScrollSensitivity, + enable_scrollbars: IframeScrollbars ) -> ClipId where I: IntoIterator, @@ -1252,6 +1255,7 @@ impl DisplayListBuilder { id: id, image_mask: image_mask, scroll_sensitivity, + enable_scrollbars }); let info = LayoutPrimitiveInfo::with_clip_rect(content_rect, clip_rect); diff --git a/wrench/Cargo.toml b/wrench/Cargo.toml index 06b3678f79..96b6c859f6 100644 --- a/wrench/Cargo.toml +++ b/wrench/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wrench" -version = "0.2.4" +version = "0.2.5" authors = ["Vladimir Vukicevic "] build = "build.rs" license = "MPL-2.0" diff --git a/wrench/src/yaml_frame_reader.rs b/wrench/src/yaml_frame_reader.rs index f08b549e66..15f5dbe608 100644 --- a/wrench/src/yaml_frame_reader.rs +++ b/wrench/src/yaml_frame_reader.rs @@ -1179,6 +1179,10 @@ impl YamlFrameReader { let complex_clips = self.to_complex_clip_regions(&yaml["complex"]); let image_mask = self.to_image_mask(&yaml["image-mask"], wrench); + let iframe_scrollbars = yaml["iframe-scrollbars"] + .as_iframe_scrollbars() + .unwrap_or(IframeScrollbars::Disabled); + let id = dl.define_scroll_frame( id, content_rect, @@ -1186,6 +1190,7 @@ impl YamlFrameReader { complex_clips, image_mask, ScrollSensitivity::Script, + iframe_scrollbars ); if let Some(size) = yaml["scroll-offset"].as_point() { diff --git a/wrench/src/yaml_frame_writer.rs b/wrench/src/yaml_frame_writer.rs index 3a85b90989..bc70e3cf7b 100644 --- a/wrench/src/yaml_frame_writer.rs +++ b/wrench/src/yaml_frame_writer.rs @@ -977,6 +977,7 @@ impl YamlFrameWriter { usize_node(&mut v, "id", clip_id_mapper.add_id(item.id)); size_node(&mut v, "content-size", &base.rect().size); rect_node(&mut v, "bounds", &base.local_clip().clip_rect()); + enum_node(&mut v, "iframe-scrollbars", item.enable_scrollbars); let &(complex_clips, complex_clip_count) = base.complex_clip(); if let Some(complex) = self.make_complex_clips_node( diff --git a/wrench/src/yaml_helper.rs b/wrench/src/yaml_helper.rs index de9e8b16fa..f788ed6663 100644 --- a/wrench/src/yaml_helper.rs +++ b/wrench/src/yaml_helper.rs @@ -34,6 +34,7 @@ pub trait YamlHelper { fn as_clip_mode(&self) -> Option; fn as_mix_blend_mode(&self) -> Option; fn as_scroll_policy(&self) -> Option; + fn as_iframe_scrollbars(&self) -> Option; fn as_filter_op(&self) -> Option; fn as_vec_filter_op(&self) -> Option>; } @@ -123,6 +124,8 @@ define_string_enum!( define_string_enum!(ScrollPolicy, [Scrollable = "scrollable", Fixed = "fixed"]); +define_string_enum!(IframeScrollbars, [Enabled = "enabled", Disabled = "disabled"]); + define_string_enum!( LineOrientation, [Horizontal = "horizontal", Vertical = "vertical"] @@ -529,6 +532,10 @@ impl YamlHelper for Yaml { self.as_str().and_then(|x| StringEnum::from_str(x)) } + fn as_iframe_scrollbars(&self) -> Option { + self.as_str().and_then(|x| StringEnum::from_str(x)) + } + fn as_clip_mode(&self) -> Option { self.as_str().and_then(|x| StringEnum::from_str(x)) }