Skip to content

Commit

Permalink
Auto merge of #9968 - izgzhen:scroll, r=asajeffrey
Browse files Browse the repository at this point in the history
Implement scroll, scrollLeft, scrollTop and friends, addressing issue #9650

This is a work in progress to solve #9650. Thanks a lot for helping the review.

- [x] scroll
- [x] scrollTo
- [x] scrollBy
- [x] scrollTop (setter and getter)
- [x] scrollLeft (setter and getter)

The setters will be implemented in another PR after this is merged.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="35" align="absmiddle" alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/9968)
<!-- Reviewable:end -->
  • Loading branch information
bors-servo committed Apr 20, 2016
2 parents eda7113 + 11b12f6 commit 8d988f2
Show file tree
Hide file tree
Showing 15 changed files with 569 additions and 12 deletions.
12 changes: 12 additions & 0 deletions components/compositing/compositor.rs
Expand Up @@ -714,6 +714,18 @@ impl<Window: WindowMethods> IOCompositor<Window> {
let _ = sender.send(());
}

(Msg::GetScrollOffset(pipeline_id, layer_id, sender), ShutdownState::NotShuttingDown) => {
match self.find_layer_with_pipeline_and_layer_id(pipeline_id, layer_id) {
Some(ref layer) => {
let typed = layer.extra_data.borrow().scroll_offset;
let _ = sender.send(Point2D::new(typed.x.get(), typed.y.get()));
},
None => {
warn!("Can't find requested layer in handling Msg::GetScrollOffset");
},
}
}

// When we are shutting_down, we need to avoid performing operations
// such as Paint that may crash because we have begun tearing down
// the rest of our resources.
Expand Down
7 changes: 7 additions & 0 deletions components/compositing/compositor_thread.rs
Expand Up @@ -98,6 +98,10 @@ pub fn run_script_listener_thread(compositor_proxy: Box<CompositorProxy + 'stati
compositor_proxy.send(Msg::TouchEventProcessed(result))
}

ScriptToCompositorMsg::GetScrollOffset(pid, lid, send) => {
compositor_proxy.send(Msg::GetScrollOffset(pid, lid, send));
}

ScriptToCompositorMsg::Exited => break,
}
}
Expand Down Expand Up @@ -231,6 +235,8 @@ pub enum Msg {
MoveTo(Point2D<i32>),
/// Resize the window to size
ResizeTo(Size2D<u32>),
/// Get scroll offset of a layer
GetScrollOffset(PipelineId, LayerId, IpcSender<Point2D<f32>>),
/// A pipeline was shut down.
// This message acts as a synchronization point between the constellation,
// when it shuts down a pipeline, to the compositor; when the compositor
Expand Down Expand Up @@ -272,6 +278,7 @@ impl Debug for Msg {
Msg::MoveTo(..) => write!(f, "MoveTo"),
Msg::ResizeTo(..) => write!(f, "ResizeTo"),
Msg::PipelineExited(..) => write!(f, "PipelineExited"),
Msg::GetScrollOffset(..) => write!(f, "GetScrollOffset"),
}
}
}
Expand Down
28 changes: 25 additions & 3 deletions components/layout/layout_thread.rs
Expand Up @@ -45,10 +45,11 @@ use profile_traits::mem::{self, Report, ReportKind, ReportsChan};
use profile_traits::time::{TimerMetadataFrameType, TimerMetadataReflowType};
use profile_traits::time::{self, TimerMetadata, profile};
use query::{LayoutRPCImpl, process_content_box_request, process_content_boxes_request};
use query::{process_node_geometry_request, process_node_scroll_area_request, process_offset_parent_query};
use query::{process_resolved_style_request, process_margin_style_query};
use query::{process_node_geometry_request, process_node_layer_id_request, process_node_scroll_area_request};
use query::{process_node_overflow_request, process_resolved_style_request, process_margin_style_query};
use query::{process_offset_parent_query};
use script::dom::node::OpaqueStyleAndLayoutData;
use script::layout_interface::{LayoutRPC, OffsetParentResponse, MarginStyleResponse};
use script::layout_interface::{LayoutRPC, OffsetParentResponse, NodeOverflowResponse, MarginStyleResponse};
use script::layout_interface::{Msg, NewLayoutThreadInfo, Reflow, ReflowQueryType};
use script::layout_interface::{ScriptLayoutChan, ScriptReflow};
use script::reporter::CSSErrorReporter;
Expand Down Expand Up @@ -117,9 +118,14 @@ pub struct LayoutThreadData {
/// A queued response for the client {top, left, width, height} of a node in pixels.
pub client_rect_response: Rect<i32>,

pub layer_id_response: Option<LayerId>,

/// A queued response for the node at a given point
pub hit_test_response: (Option<DisplayItemMetadata>, bool),

/// A pair of overflow property in x and y
pub overflow_response: NodeOverflowResponse,

/// A queued response for the scroll {top, left, width, height} of a node in pixels.
pub scroll_area_response: Rect<i32>,

Expand Down Expand Up @@ -463,8 +469,10 @@ impl LayoutThread {
content_box_response: Rect::zero(),
content_boxes_response: Vec::new(),
client_rect_response: Rect::zero(),
layer_id_response: None,
hit_test_response: (None, false),
scroll_area_response: Rect::zero(),
overflow_response: NodeOverflowResponse(None),
resolved_style_response: None,
offset_parent_response: OffsetParentResponse::empty(),
margin_style_response: MarginStyleResponse::empty(),
Expand Down Expand Up @@ -1015,9 +1023,15 @@ impl LayoutThread {
ReflowQueryType::NodeGeometryQuery(_) => {
rw_data.client_rect_response = Rect::zero();
},
ReflowQueryType::NodeLayerIdQuery(_) => {
rw_data.layer_id_response = None;
},
ReflowQueryType::NodeScrollGeometryQuery(_) => {
rw_data.scroll_area_response = Rect::zero();
},
ReflowQueryType::NodeOverflowQuery(_) => {
rw_data.overflow_response = NodeOverflowResponse(None);
},
ReflowQueryType::ResolvedStyleQuery(_, _, _) => {
rw_data.resolved_style_response = None;
},
Expand Down Expand Up @@ -1177,6 +1191,14 @@ impl LayoutThread {
let node = unsafe { ServoLayoutNode::new(&node) };
rw_data.scroll_area_response = process_node_scroll_area_request(node, &mut root_flow);
},
ReflowQueryType::NodeOverflowQuery(node) => {
let node = unsafe { ServoLayoutNode::new(&node) };
rw_data.overflow_response = process_node_overflow_request(node);
},
ReflowQueryType::NodeLayerIdQuery(node) => {
let node = unsafe { ServoLayoutNode::new(&node) };
rw_data.layer_id_response = Some(process_node_layer_id_request(node));
},
ReflowQueryType::ResolvedStyleQuery(node, ref pseudo, ref property) => {
let node = unsafe { ServoLayoutNode::new(&node) };
rw_data.resolved_style_response =
Expand Down
30 changes: 28 additions & 2 deletions components/layout/query.rs
Expand Up @@ -13,11 +13,12 @@ use flow;
use flow_ref::FlowRef;
use fragment::{Fragment, FragmentBorderBoxIterator, SpecificFragmentInfo};
use gfx::display_list::OpaqueNode;
use gfx_traits::{LayerId};
use layout_thread::LayoutThreadData;
use msg::constellation_msg::ConstellationChan;
use opaque_node::OpaqueNodeMethods;
use script::layout_interface::{ContentBoxResponse, ContentBoxesResponse, NodeGeometryResponse};
use script::layout_interface::{HitTestResponse, LayoutRPC, OffsetParentResponse};
use script::layout_interface::{ContentBoxResponse, NodeOverflowResponse, ContentBoxesResponse, NodeGeometryResponse};
use script::layout_interface::{HitTestResponse, LayoutRPC, OffsetParentResponse, NodeLayerIdResponse};
use script::layout_interface::{ResolvedStyleResponse, ScriptLayoutChan, MarginStyleResponse};
use script_traits::LayoutMsg as ConstellationMsg;
use script_traits::UntrustedNodeAddress;
Expand Down Expand Up @@ -112,12 +113,23 @@ impl LayoutRPC for LayoutRPCImpl {
}
}

fn node_overflow(&self) -> NodeOverflowResponse {
NodeOverflowResponse(self.0.lock().unwrap().overflow_response.0)
}

fn node_scroll_area(&self) -> NodeGeometryResponse {
NodeGeometryResponse {
client_rect: self.0.lock().unwrap().scroll_area_response
}
}

fn node_layer_id(&self) -> NodeLayerIdResponse {
NodeLayerIdResponse {
layer_id: self.0.lock().unwrap().layer_id_response
.expect("layer_id is not correctly fetched, see PR #9968")
}
}

/// Retrieves the resolved value for a CSS style property.
fn resolved_style(&self) -> ResolvedStyleResponse {
let &LayoutRPCImpl(ref rw_data) = self;
Expand Down Expand Up @@ -425,6 +437,7 @@ impl FragmentBorderBoxIterator for UnioningFragmentScrollAreaIterator {
let bottom_padding = (border_box.size.height - bottom_border - top_border).to_px();
let top_padding = top_border.to_px();
let left_padding = left_border.to_px();

match self.level {
Some(start_level) if level <= start_level => { self.is_child = false; }
Some(_) => {
Expand Down Expand Up @@ -517,6 +530,11 @@ pub fn process_node_geometry_request<N: LayoutNode>(requested_node: N, layout_ro
iterator.client_rect
}

pub fn process_node_layer_id_request<N: LayoutNode>(requested_node: N) -> LayerId {
let layout_node = requested_node.to_threadsafe();
layout_node.layer_id()
}

pub fn process_node_scroll_area_request< N: LayoutNode>(requested_node: N, layout_root: &mut FlowRef)
-> Rect<i32> {
let mut iterator = UnioningFragmentScrollAreaIterator::new(requested_node.opaque());
Expand Down Expand Up @@ -691,6 +709,14 @@ pub fn process_offset_parent_query<N: LayoutNode>(requested_node: N, layout_root
}
}

pub fn process_node_overflow_request<N: LayoutNode>(requested_node: N) -> NodeOverflowResponse {
let layout_node = requested_node.to_threadsafe();
let style = &*layout_node.style();
let style_box = style.get_box();

NodeOverflowResponse(Some((Point2D::new(style_box.overflow_x, style_box.overflow_y.0))))
}

pub fn process_margin_style_query<N: LayoutNode>(requested_node: N)
-> MarginStyleResponse {
let layout_node = requested_node.to_threadsafe();
Expand Down
16 changes: 16 additions & 0 deletions components/layout/wrapper.rs
Expand Up @@ -34,6 +34,7 @@ use core::nonzero::NonZero;
use data::{LayoutDataFlags, PrivateLayoutData};
use gfx::display_list::OpaqueNode;
use gfx::text::glyph::CharIndex;
use gfx_traits::{LayerId, LayerType};
use incremental::RestyleDamage;
use msg::constellation_msg::PipelineId;
use opaque_node::OpaqueNodeMethods;
Expand Down Expand Up @@ -851,6 +852,21 @@ pub trait ThreadSafeLayoutNode : Clone + Copy + Sized + PartialEq {
fn iframe_pipeline_id(&self) -> PipelineId;

fn get_colspan(&self) -> u32;

fn layer_id(&self) -> LayerId {
let layer_type = match self.get_pseudo_element_type() {
PseudoElementType::Normal => LayerType::FragmentBody,
PseudoElementType::Before(_) => LayerType::BeforePseudoContent,
PseudoElementType::After(_) => LayerType::AfterPseudoContent,
PseudoElementType::DetailsSummary(_) => LayerType::FragmentBody,
PseudoElementType::DetailsContent(_) => LayerType::FragmentBody,
};
LayerId::new_of_type(layer_type, self.opaque().id() as usize)
}

fn layer_id_for_overflow_scroll(&self) -> LayerId {
LayerId::new_of_type(LayerType::OverflowScroll, self.opaque().id() as usize)
}
}

// This trait is only public so that it can be implemented by the gecko wrapper.
Expand Down

0 comments on commit 8d988f2

Please sign in to comment.