script: Keep the DOM-side viewport up to date when scrolling happens in

WebRender.

This happens asynchronously, just as it does in non-WebRender mode.

This functionality is a prerequisite for doing proper display-list-based
hit testing in WebRender, since it moves the scroll offsets into Servo
(and, specifically, into the script thread, enabling iframe event
forwarding) instead of keeping them private to WebRender.

Requires servo/webrender_traits#55 and servo/webrender#277.

Partially addresses #11108.
This commit is contained in:
Patrick Walton 2016-05-24 18:40:39 -07:00
parent 55b0bb027c
commit a86f77e36d
32 changed files with 318 additions and 99 deletions

View file

@ -15,7 +15,8 @@ use euclid::scale_factor::ScaleFactor;
use euclid::size::TypedSize2D;
use euclid::{Matrix4D, Point2D, Rect, Size2D};
use gfx::paint_thread::{ChromeToPaintMsg, PaintRequest};
use gfx_traits::{color, Epoch, FrameTreeId, LayerId, LayerKind, LayerProperties, ScrollPolicy};
use gfx_traits::{ScrollPolicy, StackingContextId};
use gfx_traits::{color, Epoch, FrameTreeId, FragmentType, LayerId, LayerKind, LayerProperties};
use gleam::gl;
use gleam::gl::types::{GLint, GLsizei};
use image::{DynamicImage, ImageFormat, RgbImage};
@ -35,8 +36,8 @@ use profile_traits::mem::{self, ReportKind, Reporter, ReporterRequest};
use profile_traits::time::{self, ProfilerCategory, profile};
use script_traits::CompositorEvent::{MouseMoveEvent, MouseButtonEvent, TouchEvent};
use script_traits::{AnimationState, AnimationTickType, ConstellationControlMsg};
use script_traits::{ConstellationMsg, LayoutControlMsg, MouseButton};
use script_traits::{MouseEventType, TouchpadPressurePhase, TouchEventType, TouchId};
use script_traits::{ConstellationMsg, LayoutControlMsg, MouseButton, MouseEventType};
use script_traits::{StackingContextScrollState, TouchpadPressurePhase, TouchEventType, TouchId};
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::collections::{HashMap, HashSet};
use std::fs::File;
@ -91,6 +92,32 @@ impl ConvertPipelineIdFromWebRender for webrender_traits::PipelineId {
}
}
trait ConvertStackingContextFromWebRender {
fn from_webrender(&self) -> StackingContextId;
}
impl ConvertStackingContextFromWebRender for webrender_traits::ServoStackingContextId {
fn from_webrender(&self) -> StackingContextId {
StackingContextId::new_of_type(self.1, self.0.from_webrender())
}
}
trait ConvertFragmentTypeFromWebRender {
fn from_webrender(&self) -> FragmentType;
}
impl ConvertFragmentTypeFromWebRender for webrender_traits::FragmentType {
fn from_webrender(&self) -> FragmentType {
match *self {
webrender_traits::FragmentType::FragmentBody => FragmentType::FragmentBody,
webrender_traits::FragmentType::BeforePseudoContent => {
FragmentType::BeforePseudoContent
}
webrender_traits::FragmentType::AfterPseudoContent => FragmentType::AfterPseudoContent,
}
}
}
/// Holds the state when running reftests that determines when it is
/// safe to save the output image.
#[derive(Copy, Clone, PartialEq)]
@ -1620,13 +1647,13 @@ impl<Window: WindowMethods> IOCompositor<Window> {
self.perform_updates_after_scroll();
}
}
}
if had_events {
self.send_viewport_rects_for_all_layers();
}
}
}
}
/// Computes new display ports for each layer, taking the scroll position into account, and
/// sends them to layout as necessary. This ultimately triggers a rerender of the content.
@ -1887,9 +1914,40 @@ impl<Window: WindowMethods> IOCompositor<Window> {
}
fn send_viewport_rects_for_all_layers(&self) {
match self.scene.root {
Some(ref root) => self.send_viewport_rect_for_layer(root.clone()),
None => {},
if opts::get().use_webrender {
return self.send_webrender_viewport_rects()
}
if let Some(ref root) = self.scene.root {
self.send_viewport_rect_for_layer(root.clone())
}
}
fn send_webrender_viewport_rects(&self) {
let mut stacking_context_scroll_states_per_pipeline = HashMap::new();
if let Some(ref webrender_api) = self.webrender_api {
for scroll_layer_state in webrender_api.get_scroll_layer_state() {
let stacking_context_scroll_state = StackingContextScrollState {
stacking_context_id: scroll_layer_state.stacking_context_id.from_webrender(),
scroll_offset: scroll_layer_state.scroll_offset,
};
let pipeline_id = scroll_layer_state.pipeline_id;
match stacking_context_scroll_states_per_pipeline.entry(pipeline_id) {
Vacant(mut entry) => {
entry.insert(vec![stacking_context_scroll_state]);
}
Occupied(mut entry) => entry.get_mut().push(stacking_context_scroll_state),
}
}
for (pipeline_id, stacking_context_scroll_states) in
stacking_context_scroll_states_per_pipeline {
if let Some(pipeline) = self.pipeline(pipeline_id.from_webrender()) {
let msg = LayoutControlMsg::SetStackingContextScrollStates(
stacking_context_scroll_states);
let _ = pipeline.layout_chan.send(msg);
}
}
}
}

View file

@ -22,7 +22,7 @@ use euclid::num::Zero;
use euclid::rect::TypedRect;
use euclid::{Matrix2D, Matrix4D, Point2D, Rect, SideOffsets2D, Size2D};
use fnv::FnvHasher;
use gfx_traits::{LayerId, ScrollPolicy};
use gfx_traits::{LayerId, ScrollPolicy, StackingContextId};
use ipc_channel::ipc::IpcSharedMemory;
use msg::constellation_msg::PipelineId;
use net_traits::image::base::{Image, PixelFormat};
@ -1395,37 +1395,6 @@ impl fmt::Debug for DisplayItem {
}
}
#[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, Deserialize, Serialize, HeapSizeOf, RustcEncodable)]
pub enum FragmentType {
/// A StackingContext for the fragment body itself.
FragmentBody,
/// A StackingContext created to contain ::before pseudo-element content.
BeforePseudoContent,
/// A StackingContext created to contain ::after pseudo-element content.
AfterPseudoContent,
}
/// A unique ID for every stacking context.
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, HeapSizeOf, PartialEq, RustcEncodable, Serialize)]
pub struct StackingContextId(
/// The identifier for this StackingContext, derived from the Flow's memory address
/// and fragment type. As a space optimization, these are combined into a single word.
usize
);
impl StackingContextId {
#[inline(always)]
pub fn new(id: usize) -> StackingContextId {
StackingContextId::new_of_type(id, FragmentType::FragmentBody)
}
#[inline(always)]
pub fn new_of_type(id: usize, fragment_type: FragmentType) -> StackingContextId {
debug_assert_eq!(id & fragment_type as usize, 0);
StackingContextId(id | fragment_type as usize)
}
}
#[derive(Copy, Clone, HeapSizeOf, Deserialize, Serialize)]
pub struct WebRenderImageInfo {
pub width: u32,

View file

@ -8,13 +8,14 @@ use app_units::Au;
use azure::AzFloat;
use azure::azure_hl::{BackendType, Color, DrawTarget, SurfaceFormat};
use display_list::{DisplayItem, DisplayList, DisplayListTraversal};
use display_list::{LayerInfo, StackingContext, StackingContextId, StackingContextType};
use display_list::{LayerInfo, StackingContext, StackingContextType};
use euclid::Matrix4D;
use euclid::point::Point2D;
use euclid::rect::Rect;
use euclid::size::Size2D;
use font_cache_thread::FontCacheThread;
use font_context::FontContext;
use gfx_traits::StackingContextId;
use gfx_traits::{Epoch, FrameTreeId, LayerId, LayerKind, LayerProperties, PaintListener};
use ipc_channel::ipc::IpcSender;
use layers::layers::{BufferRequest, LayerBuffer, LayerBufferSet};

View file

@ -149,3 +149,58 @@ impl FrameTreeId {
self.0 += 1;
}
}
/// A unique ID for every stacking context.
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, HeapSizeOf, PartialEq, Serialize)]
pub struct StackingContextId(
/// The identifier for this StackingContext, derived from the Flow's memory address
/// and fragment type. As a space optimization, these are combined into a single word.
usize
);
impl StackingContextId {
#[inline(always)]
pub fn new(id: usize) -> StackingContextId {
StackingContextId::new_of_type(id, FragmentType::FragmentBody)
}
#[inline(always)]
pub fn new_of_type(id: usize, fragment_type: FragmentType) -> StackingContextId {
debug_assert_eq!(id & fragment_type as usize, 0);
StackingContextId(id | fragment_type as usize)
}
#[inline]
pub fn fragment_type(&self) -> FragmentType {
FragmentType::from_usize(self.0 & 3)
}
#[inline]
pub fn id(&self) -> usize {
self.0 & !3
}
}
#[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, Deserialize, Serialize, HeapSizeOf)]
pub enum FragmentType {
/// A StackingContext for the fragment body itself.
FragmentBody,
/// A StackingContext created to contain ::before pseudo-element content.
BeforePseudoContent,
/// A StackingContext created to contain ::after pseudo-element content.
AfterPseudoContent,
}
impl FragmentType {
#[inline]
pub fn from_usize(n: usize) -> FragmentType {
debug_assert!(n < 3);
match n {
0 => FragmentType::FragmentBody,
1 => FragmentType::BeforePseudoContent,
_ => FragmentType::AfterPseudoContent,
}
}
}

View file

@ -43,8 +43,8 @@ use flow_list::FlowList;
use flow_ref::FlowRef;
use fragment::SpecificFragmentInfo;
use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, HAS_LAYER, Overflow};
use gfx::display_list::{ClippingRegion, StackingContext, StackingContextId};
use gfx_traits::LayerId;
use gfx::display_list::{ClippingRegion, StackingContext};
use gfx_traits::{LayerId, StackingContextId};
use incremental::{BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT};
use layout_debug;
use layout_thread::DISPLAY_PORT_SIZE_FACTOR;

View file

@ -21,17 +21,16 @@ use flow::{BaseFlow, Flow, IS_ABSOLUTELY_POSITIONED};
use flow_ref;
use fragment::SpecificFragmentInfo;
use fragment::{CoordinateSystem, Fragment, HAS_LAYER, ImageFragmentInfo, ScannedTextFragmentInfo};
use gfx::display_list::GradientDisplayItem;
use gfx::display_list::{BLUR_INFLATION_FACTOR, BaseDisplayItem, BorderDisplayItem};
use gfx::display_list::{BorderRadii, BoxShadowClipMode, BoxShadowDisplayItem, ClippingRegion};
use gfx::display_list::{DisplayItem, DisplayItemMetadata, DisplayListSection};
use gfx::display_list::{GradientStop, IframeDisplayItem, ImageDisplayItem, WebGLDisplayItem, LayeredItem, LayerInfo};
use gfx::display_list::{LineDisplayItem, OpaqueNode, SolidColorDisplayItem};
use gfx::display_list::{StackingContext, StackingContextId, StackingContextType};
use gfx::display_list::{DisplayItem, DisplayItemMetadata, DisplayListSection, GradientDisplayItem};
use gfx::display_list::{GradientStop, IframeDisplayItem, ImageDisplayItem, WebGLDisplayItem};
use gfx::display_list::{LayeredItem, LayerInfo, LineDisplayItem, OpaqueNode};
use gfx::display_list::{SolidColorDisplayItem, StackingContext, StackingContextType};
use gfx::display_list::{TextDisplayItem, TextOrientation, WebRenderImageInfo};
use gfx::paint_thread::THREAD_TINT_COLORS;
use gfx::text::glyph::ByteIndex;
use gfx_traits::{color, ScrollPolicy};
use gfx_traits::{color, ScrollPolicy, StackingContextId};
use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFlow, LAST_FRAGMENT_OF_ELEMENT};
use ipc_channel::ipc;
use list_item::ListItemFlow;

View file

@ -17,7 +17,8 @@ use flow::{Flow, FlowClass, ImmutableFlowUtils, OpaqueFlow};
use flow::{INLINE_POSITION_IS_STATIC, IS_ABSOLUTELY_POSITIONED};
use flow_ref::{self, FlowRef};
use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
use gfx::display_list::{StackingContext, StackingContextId};
use gfx::display_list::StackingContext;
use gfx_traits::StackingContextId;
use incremental::{REFLOW, REFLOW_OUT_OF_FLOW};
use layout_debug;
use model::{IntrinsicISizes, MaybeAuto, MinMaxConstraint};

View file

@ -34,8 +34,8 @@ use floats::{Floats, SpeculatedFloatPlacement};
use flow_list::{FlowList, FlowListIterator, MutFlowListIterator};
use flow_ref::{self, FlowRef, WeakFlowRef};
use fragment::{Fragment, FragmentBorderBoxIterator, Overflow, SpecificFragmentInfo};
use gfx::display_list::{ClippingRegion, StackingContext, StackingContextId};
use gfx_traits::{LayerId, LayerType};
use gfx::display_list::{ClippingRegion, StackingContext};
use gfx_traits::{LayerId, LayerType, StackingContextId};
use incremental::{RECONSTRUCT_FLOW, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, RestyleDamage};
use inline::InlineFlow;
use model::{CollapsibleMargins, IntrinsicISizes, MarginCollapseInfo};

View file

@ -14,10 +14,10 @@ use floats::ClearType;
use flow::{self, ImmutableFlowUtils};
use flow_ref::{self, FlowRef};
use gfx;
use gfx::display_list::{BLUR_INFLATION_FACTOR, FragmentType, OpaqueNode, StackingContextId};
use gfx::display_list::{BLUR_INFLATION_FACTOR, OpaqueNode};
use gfx::text::glyph::ByteIndex;
use gfx::text::text_run::{TextRun, TextRunSlice};
use gfx_traits::{LayerId, LayerType};
use gfx_traits::{FragmentType, LayerId, LayerType, StackingContextId};
use incremental::{RECONSTRUCT_FLOW, RestyleDamage};
use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFragmentContext, InlineFragmentNodeInfo};
use inline::{InlineMetrics, LAST_FRAGMENT_OF_ELEMENT};

View file

@ -17,9 +17,10 @@ use flow::{self, BaseFlow, Flow, FlowClass, ForceNonfloatedFlag, IS_ABSOLUTELY_P
use flow_ref;
use fragment::SpecificFragmentInfo;
use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, Overflow};
use gfx::display_list::{OpaqueNode, StackingContext, StackingContextId};
use gfx::display_list::{OpaqueNode, StackingContext};
use gfx::font::FontMetrics;
use gfx::font_context::FontContext;
use gfx_traits::StackingContextId;
use incremental::{BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, RESOLVE_GENERATED_CONTENT};
use layout_debug;
use model::IntrinsicISizesContribution;

View file

@ -21,14 +21,13 @@ use euclid::size::Size2D;
use flow::{self, Flow, ImmutableFlowUtils, MutableOwnedFlowUtils};
use flow_ref::{self, FlowRef};
use fnv::FnvHasher;
use gfx::display_list::WebRenderImageInfo;
use gfx::display_list::{ClippingRegion, DisplayItemMetadata, DisplayList, LayerInfo};
use gfx::display_list::{OpaqueNode, StackingContext, StackingContextId, StackingContextType};
use gfx::display_list::{OpaqueNode, StackingContext, StackingContextType, WebRenderImageInfo};
use gfx::font;
use gfx::font_cache_thread::FontCacheThread;
use gfx::font_context;
use gfx::paint_thread::LayoutToPaintMsg;
use gfx_traits::{color, Epoch, LayerId, ScrollPolicy};
use gfx_traits::{color, Epoch, LayerId, ScrollPolicy, StackingContextId};
use heapsize::HeapSizeOf;
use incremental::LayoutDamageComputation;
use incremental::{REPAINT, STORE_OVERFLOW, REFLOW_OUT_OF_FLOW, REFLOW, REFLOW_ENTIRE_DOCUMENT};
@ -52,8 +51,8 @@ use script::dom::node::OpaqueStyleAndLayoutData;
use script::layout_interface::{LayoutRPC, OffsetParentResponse, NodeOverflowResponse, MarginStyleResponse};
use script::layout_interface::{Msg, NewLayoutThreadInfo, Reflow, ReflowQueryType, ScriptReflow};
use script::reporter::CSSErrorReporter;
use script_traits::ConstellationControlMsg;
use script_traits::{LayoutControlMsg, LayoutMsg as ConstellationMsg};
use script_traits::StackingContextScrollState;
use script_traits::{ConstellationControlMsg, LayoutControlMsg, LayoutMsg as ConstellationMsg};
use sequential;
use serde_json;
use std::borrow::ToOwned;
@ -559,6 +558,11 @@ impl LayoutThread {
self.handle_request_helper(Msg::SetVisibleRects(new_visible_rects),
possibly_locked_rw_data)
},
Request::FromPipeline(LayoutControlMsg::SetStackingContextScrollStates(
new_scroll_states)) => {
self.handle_request_helper(Msg::SetStackingContextScrollStates(new_scroll_states),
possibly_locked_rw_data)
},
Request::FromPipeline(LayoutControlMsg::TickAnimations) => {
self.handle_request_helper(Msg::TickAnimations, possibly_locked_rw_data)
},
@ -644,6 +648,10 @@ impl LayoutThread {
Msg::SetVisibleRects(new_visible_rects) => {
self.set_visible_rects(new_visible_rects, possibly_locked_rw_data);
}
Msg::SetStackingContextScrollStates(new_scroll_states) => {
self.set_stacking_context_scroll_states(new_scroll_states,
possibly_locked_rw_data);
}
Msg::ReapStyleAndLayoutData(dead_data) => {
unsafe {
self.handle_reap_style_and_layout_data(dead_data)
@ -883,8 +891,7 @@ impl LayoutThread {
if flow::base(&**layout_root).restyle_damage.contains(REPAINT) ||
rw_data.display_list.is_none() {
let mut root_stacking_context =
StackingContext::new(StackingContextId::new(0),
let mut root_stacking_context = StackingContext::new(StackingContextId::new(0),
StackingContextType::Real,
&Rect::zero(),
&Rect::zero(),
@ -1264,6 +1271,19 @@ impl LayoutThread {
true
}
fn set_stacking_context_scroll_states<'a, 'b>(
&mut self,
new_scroll_states: Vec<StackingContextScrollState>,
_: &mut RwData<'a, 'b>) {
for new_scroll_state in &new_scroll_states {
if self.root_flow.is_some() && new_scroll_state.stacking_context_id.id() == 0 {
let _ = self.script_chan.send(ConstellationControlMsg::SetScrollState(
self.id,
new_scroll_state.scroll_offset));
}
}
}
fn tick_all_animations<'a, 'b>(&mut self, possibly_locked_rw_data: &mut RwData<'a, 'b>) {
let mut rw_data = possibly_locked_rw_data.lock();
self.tick_animations(&mut rw_data);

View file

@ -17,7 +17,8 @@ use flow::{Flow, FlowClass, OpaqueFlow};
use fragment::Overflow;
use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, GeneratedContentInfo};
use generated_content;
use gfx::display_list::{StackingContext, StackingContextId};
use gfx::display_list::StackingContext;
use gfx_traits::StackingContextId;
use incremental::RESOLVE_GENERATED_CONTENT;
use inline::InlineMetrics;
use std::sync::Arc;

View file

@ -15,7 +15,8 @@ use floats::FloatKind;
use flow::{Flow, FlowClass, OpaqueFlow, mut_base, FragmentationContext};
use flow_ref::{self, FlowRef};
use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
use gfx::display_list::{StackingContext, StackingContextId};
use gfx::display_list::StackingContext;
use gfx_traits::StackingContextId;
use std::cmp::{min, max};
use std::fmt;
use std::sync::Arc;

View file

@ -16,7 +16,8 @@ use flow;
use flow::{BaseFlow, EarlyAbsolutePositionInfo, Flow, FlowClass, ImmutableFlowUtils, OpaqueFlow};
use flow_list::MutFlowListIterator;
use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
use gfx::display_list::{StackingContext, StackingContextId};
use gfx::display_list::StackingContext;
use gfx_traits::StackingContextId;
use incremental::{REFLOW, REFLOW_OUT_OF_FLOW};
use layout_debug;
use model::{IntrinsicISizes, IntrinsicISizesContribution, MaybeAuto};

View file

@ -13,7 +13,8 @@ use display_list_builder::DisplayListBuildState;
use euclid::Point2D;
use flow::{Flow, FlowClass, OpaqueFlow};
use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
use gfx::display_list::{StackingContext, StackingContextId};
use gfx::display_list::StackingContext;
use gfx_traits::StackingContextId;
use std::fmt;
use std::sync::Arc;
use style::logical_geometry::LogicalSize;

View file

@ -14,7 +14,8 @@ use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode, Dis
use euclid::{Point2D, Rect, SideOffsets2D, Size2D};
use flow::{self, Flow, FlowClass, OpaqueFlow};
use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
use gfx::display_list::{StackingContext, StackingContextId};
use gfx::display_list::StackingContext;
use gfx_traits::StackingContextId;
use incremental::REFLOW;
use layout_debug;
use model::MaybeAuto;

View file

@ -12,7 +12,8 @@ use display_list_builder::DisplayListBuildState;
use euclid::Point2D;
use flow::{BaseFlow, Flow, FlowClass, ForceNonfloatedFlag, OpaqueFlow};
use fragment::{Fragment, FragmentBorderBoxIterator, Overflow, SpecificFragmentInfo};
use gfx::display_list::{StackingContext, StackingContextId};
use gfx::display_list::StackingContext;
use gfx_traits::StackingContextId;
use layout_debug;
use std::cmp::max;
use std::fmt;

View file

@ -15,7 +15,8 @@ use euclid::Point2D;
use flow::{self, EarlyAbsolutePositionInfo, Flow, FlowClass, ImmutableFlowUtils, OpaqueFlow};
use flow_list::MutFlowListIterator;
use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
use gfx::display_list::{StackingContext, StackingContextId};
use gfx::display_list::StackingContext;
use gfx_traits::StackingContextId;
use layout_debug;
use model::MaybeAuto;
use rustc_serialize::{Encodable, Encoder};

View file

@ -13,7 +13,8 @@ use display_list_builder::DisplayListBuildState;
use euclid::Point2D;
use flow::{Flow, FlowClass, OpaqueFlow};
use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
use gfx::display_list::{StackingContext, StackingContextId};
use gfx::display_list::StackingContext;
use gfx_traits::StackingContextId;
use layout_debug;
use rustc_serialize::{Encodable, Encoder};
use std::fmt;

View file

@ -22,7 +22,8 @@ use euclid::Point2D;
use floats::FloatKind;
use flow::{Flow, FlowClass, ImmutableFlowUtils, INLINE_POSITION_IS_STATIC, OpaqueFlow};
use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
use gfx::display_list::{StackingContext, StackingContextId};
use gfx::display_list::StackingContext;
use gfx_traits::StackingContextId;
use model::MaybeAuto;
use std::cmp::{max, min};
use std::fmt;

View file

@ -11,13 +11,13 @@ use app_units::Au;
use azure::azure_hl::Color;
use euclid::{Point2D, Rect, Size2D};
use gfx::display_list::{BorderRadii, BoxShadowClipMode, ClippingRegion};
use gfx::display_list::{DisplayItem, DisplayList};
use gfx::display_list::{DisplayListTraversal, GradientStop, StackingContext, StackingContextType};
use gfx_traits::ScrollPolicy;
use gfx::display_list::{DisplayItem, DisplayList, DisplayListTraversal};
use gfx::display_list::{GradientStop, StackingContext, StackingContextType};
use gfx_traits::{FragmentType, ScrollPolicy, StackingContextId};
use style::computed_values::filter::{self, Filter};
use style::computed_values::{image_rendering, mix_blend_mode};
use style::values::computed::BorderStyle;
use webrender_traits::{self, AuxiliaryListsBuilder, DisplayListId, PipelineId, StackingContextId};
use webrender_traits::{self, AuxiliaryListsBuilder, DisplayListId, PipelineId};
trait WebRenderStackingContextConverter {
fn convert_to_webrender<'a>(&self,
@ -315,8 +315,11 @@ impl WebRenderStackingContextConverter for StackingContext {
ScrollPolicy::FixedPosition => webrender_traits::ScrollPolicy::Fixed,
};
let webrender_stacking_context_id = self.id.convert_to_webrender();
let mut sc =
webrender_traits::StackingContext::new(scroll_layer_id,
webrender_traits::StackingContext::new(webrender_stacking_context_id,
scroll_layer_id,
webrender_scroll_policy,
self.bounds.to_rectf(),
self.overflow.to_rectf(),
@ -514,7 +517,8 @@ impl WebRenderDisplayItemConverter for DisplayItem {
}
pub struct WebRenderFrameBuilder {
pub stacking_contexts: Vec<(StackingContextId, webrender_traits::StackingContext)>,
pub stacking_contexts: Vec<(webrender_traits::StackingContextId,
webrender_traits::StackingContext)>,
pub display_lists: Vec<(DisplayListId, webrender_traits::BuiltDisplayList)>,
pub auxiliary_lists_builder: AuxiliaryListsBuilder,
pub root_pipeline_id: PipelineId,
@ -536,7 +540,7 @@ impl WebRenderFrameBuilder {
api: &mut webrender_traits::RenderApi,
pipeline_id: PipelineId,
stacking_context: webrender_traits::StackingContext)
-> StackingContextId {
-> webrender_traits::StackingContextId {
assert!(pipeline_id == self.root_pipeline_id);
let id = api.next_stacking_context_id();
self.stacking_contexts.push((id, stacking_context));
@ -561,5 +565,32 @@ impl WebRenderFrameBuilder {
self.next_scroll_layer_id += 1;
webrender_traits::ScrollLayerId::new(self.root_pipeline_id, scroll_layer_id)
}
}
trait WebRenderStackingContextIdConverter {
fn convert_to_webrender(&self) -> webrender_traits::ServoStackingContextId;
}
impl WebRenderStackingContextIdConverter for StackingContextId {
fn convert_to_webrender(&self) -> webrender_traits::ServoStackingContextId {
webrender_traits::ServoStackingContextId(self.fragment_type().convert_to_webrender(),
self.id())
}
}
trait WebRenderFragmentTypeConverter {
fn convert_to_webrender(&self) -> webrender_traits::FragmentType;
}
impl WebRenderFragmentTypeConverter for FragmentType {
fn convert_to_webrender(&self) -> webrender_traits::FragmentType {
match *self {
FragmentType::FragmentBody => webrender_traits::FragmentType::FragmentBody,
FragmentType::BeforePseudoContent => {
webrender_traits::FragmentType::BeforePseudoContent
}
FragmentType::AfterPseudoContent => webrender_traits::FragmentType::AfterPseudoContent,
}
}
}

View file

@ -143,6 +143,7 @@ impl Formattable for ProfilerCategory {
ProfilerCategory::ScriptResize => "Script Resize",
ProfilerCategory::ScriptEvent => "Script Event",
ProfilerCategory::ScriptUpdateReplacedElement => "Script Update Replaced Element",
ProfilerCategory::ScriptSetScrollState => "Script Set Scroll State",
ProfilerCategory::ScriptSetViewport => "Script Set Viewport",
ProfilerCategory::ScriptTimerEvent => "Script Timer Event",
ProfilerCategory::ScriptStylesheetLoad => "Script Stylesheet Load",

View file

@ -73,6 +73,7 @@ pub enum ProfilerCategory {
ScriptParseHTML,
ScriptPlannedNavigation,
ScriptResize,
ScriptSetScrollState,
ScriptSetViewport,
ScriptTimerEvent,
ScriptStylesheetLoad,

View file

@ -995,13 +995,18 @@ impl Window {
};
// TODO (farodin91): Raise an event to stop the current_viewport
let size = self.current_viewport.get().size;
self.current_viewport.set(Rect::new(Point2D::new(Au::from_f32_px(x), Au::from_f32_px(y)), size));
self.update_viewport_for_scroll(x, y);
let message = ConstellationMsg::ScrollFragmentPoint(self.pipeline(), layer_id, point, smooth);
self.constellation_chan.send(message).unwrap();
}
pub fn update_viewport_for_scroll(&self, x: f32, y: f32) {
let size = self.current_viewport.get().size;
let new_viewport = Rect::new(Point2D::new(Au::from_f32_px(x), Au::from_f32_px(y)), size);
self.current_viewport.set(new_viewport)
}
pub fn client_window(&self) -> (Size2D<u32>, Point2D<i32>) {
let (send, recv) = ipc::channel::<(Size2D<u32>, Point2D<i32>)>().unwrap();
self.constellation_chan.send(ConstellationMsg::GetClientWindow(send)).unwrap();

View file

@ -15,8 +15,8 @@ use ipc_channel::ipc::{IpcReceiver, IpcSender};
use msg::constellation_msg::{PanicMsg, PipelineId, WindowSizeData};
use net_traits::image_cache_thread::ImageCacheThread;
use profile_traits::mem::ReportsChan;
use script_traits::UntrustedNodeAddress;
use script_traits::{ConstellationControlMsg, LayoutControlMsg, LayoutMsg as ConstellationMsg};
use script_traits::{StackingContextScrollState, UntrustedNodeAddress};
use std::sync::Arc;
use std::sync::mpsc::{Receiver, Sender};
use string_cache::Atom;
@ -85,6 +85,9 @@ pub enum Msg {
/// Set the final Url.
SetFinalUrl(Url),
/// Tells layout about the new scrolling offsets of each scrollable stacking context.
SetStackingContextScrollStates(Vec<StackingContextScrollState>),
}
/// Synchronous messages that script can send to layout.

View file

@ -62,6 +62,7 @@ pub enum ScriptThreadEventCategory {
NetworkEvent,
Resize,
ScriptEvent,
SetScrollState,
SetViewport,
StylesheetLoad,
TimerEvent,

View file

@ -708,6 +708,11 @@ impl ScriptThread {
self.handle_viewport(id, rect);
})
}
FromConstellation(ConstellationControlMsg::SetScrollState(id, scroll_offset)) => {
self.profile_event(ScriptThreadEventCategory::SetScrollState, || {
self.handle_set_scroll_state(id, &scroll_offset);
})
}
FromConstellation(ConstellationControlMsg::TickAllAnimations(
pipeline_id)) => {
if !animation_ticks.contains(&pipeline_id) {
@ -850,6 +855,9 @@ impl ScriptThread {
ScriptThreadEventCategory::NetworkEvent => ProfilerCategory::ScriptNetworkEvent,
ScriptThreadEventCategory::Resize => ProfilerCategory::ScriptResize,
ScriptThreadEventCategory::ScriptEvent => ProfilerCategory::ScriptEvent,
ScriptThreadEventCategory::SetScrollState => {
ProfilerCategory::ScriptSetScrollState
}
ScriptThreadEventCategory::UpdateReplacedElement => {
ProfilerCategory::ScriptUpdateReplacedElement
}
@ -877,6 +885,8 @@ impl ScriptThread {
self.handle_resize_inactive_msg(id, new_size),
ConstellationControlMsg::Viewport(..) =>
panic!("should have handled Viewport already"),
ConstellationControlMsg::SetScrollState(..) =>
panic!("should have handled SetScrollState already"),
ConstellationControlMsg::Resize(..) =>
panic!("should have handled Resize already"),
ConstellationControlMsg::ExitPipeline(..) =>
@ -1077,6 +1087,19 @@ impl ScriptThread {
panic!("Page rect message sent to nonexistent pipeline");
}
fn handle_set_scroll_state(&self, id: PipelineId, scroll_state: &Point2D<f32>) {
let context = self.browsing_context.get();
if let Some(context) = context {
if let Some(inner_context) = context.find(id) {
let window = inner_context.active_window();
window.update_viewport_for_scroll(-scroll_state.x, -scroll_state.y);
return
}
}
panic!("Set scroll state message message sent to nonexistent pipeline: {:?}", id);
}
fn handle_new_layout(&self, new_layout_info: NewLayoutInfo) {
let NewLayoutInfo {
containing_pipeline_id,

View file

@ -39,6 +39,7 @@ use euclid::point::Point2D;
use euclid::rect::Rect;
use gfx_traits::Epoch;
use gfx_traits::LayerId;
use gfx_traits::StackingContextId;
use ipc_channel::ipc::{IpcReceiver, IpcSender};
use libc::c_void;
use msg::constellation_msg::{FrameId, FrameType, Key, KeyModifiers, KeyState, LoadData};
@ -76,6 +77,8 @@ pub enum LayoutControlMsg {
TickAnimations,
/// Informs layout as to which regions of the page are visible.
SetVisibleRects(Vec<(LayerId, Rect<Au>)>),
/// Tells layout about the new scrolling offsets of each scrollable stacking context.
SetStackingContextScrollStates(Vec<StackingContextScrollState>),
/// Requests the current load state of Web fonts. `true` is returned if fonts are still loading
/// and `false` is returned if all fonts have loaded.
GetWebFontLoadState(IpcSender<bool>),
@ -122,6 +125,8 @@ pub enum ConstellationControlMsg {
SendEvent(PipelineId, CompositorEvent),
/// Notifies script of the viewport.
Viewport(PipelineId, Rect<f32>),
/// Notifies script of a new scroll offset.
SetScrollState(PipelineId, Point2D<f32>),
/// Requests that the script thread immediately send the constellation the title of a pipeline.
GetTitle(PipelineId),
/// Notifies script thread to suspend all its timers
@ -463,6 +468,15 @@ pub enum AnimationTickType {
Layout,
}
/// The scroll state of a stacking context.
#[derive(Copy, Clone, Debug, Deserialize, Serialize)]
pub struct StackingContextScrollState {
/// The ID of the stacking context.
pub stacking_context_id: StackingContextId,
/// The scrolling offset of this stacking context.
pub scroll_offset: Point2D<f32>,
}
/// Messages to the constellation.
#[derive(Deserialize, Serialize)]
pub enum ConstellationMsg {

View file

@ -2517,7 +2517,7 @@ dependencies = [
[[package]]
name = "webrender"
version = "0.1.0"
source = "git+https://github.com/servo/webrender#02bfa59b3f15145cfc559684deba8153dc33a5af"
source = "git+https://github.com/servo/webrender#4ee826b19c23e63ecab7f5a8d0a68faa1f05b70c"
dependencies = [
"app_units 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2540,7 +2540,7 @@ dependencies = [
[[package]]
name = "webrender_traits"
version = "0.1.0"
source = "git+https://github.com/servo/webrender_traits#f74a744614b4c0c2fc64d39916386848124f4d52"
source = "git+https://github.com/servo/webrender_traits#e4cbde9880d118e50de425d37bd93d4e7c866e44"
dependencies = [
"app_units 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",

4
ports/cef/Cargo.lock generated
View file

@ -2378,7 +2378,7 @@ dependencies = [
[[package]]
name = "webrender"
version = "0.1.0"
source = "git+https://github.com/servo/webrender#02bfa59b3f15145cfc559684deba8153dc33a5af"
source = "git+https://github.com/servo/webrender#4ee826b19c23e63ecab7f5a8d0a68faa1f05b70c"
dependencies = [
"app_units 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2401,7 +2401,7 @@ dependencies = [
[[package]]
name = "webrender_traits"
version = "0.1.0"
source = "git+https://github.com/servo/webrender_traits#f74a744614b4c0c2fc64d39916386848124f4d52"
source = "git+https://github.com/servo/webrender_traits#e4cbde9880d118e50de425d37bd93d4e7c866e44"
dependencies = [
"app_units 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",

View file

@ -6874,6 +6874,12 @@
"url": "/_mozilla/mozilla/script_type.html"
}
],
"mozilla/scrollTo.html": [
{
"path": "mozilla/scrollTo.html",
"url": "/_mozilla/mozilla/scrollTo.html"
}
],
"mozilla/send-arraybuffer.htm": [
{
"path": "mozilla/send-arraybuffer.htm",

View file

@ -0,0 +1,21 @@
<!doctype html>
<meta charset="utf-8">
<title></title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
test(function() {
scrollTo(0, 5000);
assert_equals(scrollX, 0);
assert_equals(pageXOffset, 0);
assert_equals(scrollY, 5000);
assert_equals(pageYOffset, 5000);
scrollTo(5000, 0);
assert_equals(scrollX, 5000);
assert_equals(pageXOffset, 5000);
assert_equals(scrollY, 0);
assert_equals(pageYOffset, 0);
});
</script>
<div style="position: absolute; top: 0; left: 0; width: 10000px; height: 10000px; background: purple"></div>