diff options
author | Patrick Walton <pcwalton@mimiga.net> | 2016-06-08 18:46:02 -0700 |
---|---|---|
committer | Patrick Walton <pcwalton@mimiga.net> | 2016-06-10 18:43:04 -0700 |
commit | 041cfe6d0a07882819ae35380c286e7fe09c1013 (patch) | |
tree | 464033c42b2417f4f993e70840ea8a2bae03b3c9 /components/script/dom/window.rs | |
parent | ce88b8ed30feff9c7d3f067041fe5d781e012351 (diff) | |
download | servo-041cfe6d0a07882819ae35380c286e7fe09c1013.tar.gz servo-041cfe6d0a07882819ae35380c286e7fe09c1013.zip |
script: When using WebRender, keep the DOM-side scroll positions for
elements with `overflow: scroll` up to date, and take them into account
when doing hit testing.
Closes #11648.
Diffstat (limited to 'components/script/dom/window.rs')
-rw-r--r-- | components/script/dom/window.rs | 37 |
1 files changed, 35 insertions, 2 deletions
diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index 4bfbb1993d1..34f7c1acdb0 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -12,6 +12,7 @@ use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull; use dom::bindings::codegen::Bindings::EventHandlerBinding::OnBeforeUnloadEventHandlerNonNull; use dom::bindings::codegen::Bindings::EventHandlerBinding::OnErrorEventHandlerNonNull; use dom::bindings::codegen::Bindings::FunctionBinding::Function; +use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; use dom::bindings::codegen::Bindings::WindowBinding::{ScrollBehavior, ScrollToOptions}; use dom::bindings::codegen::Bindings::WindowBinding::{self, FrameRequestCallback, WindowMethods}; use dom::bindings::error::{Error, ErrorResult, Fallible, report_pending_exception}; @@ -68,7 +69,7 @@ use script_traits::{ScriptMsg as ConstellationMsg, TimerEventRequest, TimerSourc use std::ascii::AsciiExt; use std::borrow::ToOwned; use std::cell::Cell; -use std::collections::HashSet; +use std::collections::{HashMap, HashSet}; use std::default::Default; use std::ffi::CString; use std::io::{Write, stderr, stdout}; @@ -264,6 +265,9 @@ pub struct Window { error_reporter: CSSErrorReporter, + /// A list of scroll offsets for each scrollable element. + scroll_offsets: DOMRefCell<HashMap<UntrustedNodeAddress, Point2D<f32>>>, + #[ignore_heap_size_of = "Defined in ipc-channel"] panic_chan: IpcSender<PanicMsg>, } @@ -354,6 +358,13 @@ impl Window { pub fn css_error_reporter(&self) -> Box<ParseErrorReporter + Send> { self.error_reporter.clone() } + + /// Sets a new list of scroll offsets. + /// + /// This is called when layout gives us new ones and WebRender is in use. + pub fn set_scroll_offsets(&self, offsets: HashMap<UntrustedNodeAddress, Point2D<f32>>) { + *self.scroll_offsets.borrow_mut() = offsets + } } #[cfg(any(target_os = "macos", target_os = "linux"))] @@ -1243,7 +1254,28 @@ impl Window { self.layout_rpc.node_overflow().0.unwrap() } - pub fn scroll_offset_query(&self, node: TrustedNodeAddress) -> Point2D<f32> { + pub fn scroll_offset_query(&self, node: &Node) -> Point2D<f32> { + // WebRender always keeps the scroll offsets up to date and stored here in the window. So, + // if WR is in use, all we need to do is to check our list of scroll offsets and return the + // result. + if opts::get().use_webrender { + let mut node = Root::from_ref(node); + loop { + if let Some(scroll_offset) = self.scroll_offsets + .borrow() + .get(&node.to_untrusted_node_address()) { + return *scroll_offset + } + node = match node.GetParentNode() { + Some(node) => node, + None => break, + } + } + let offset = self.current_viewport.get().origin; + return Point2D::new(offset.x.to_f32_px(), offset.y.to_f32_px()) + } + + let node = node.to_trusted_node_address(); if !self.reflow(ReflowGoal::ForScriptQuery, ReflowQueryType::NodeLayerIdQuery(node), ReflowReason::Query) { @@ -1642,6 +1674,7 @@ impl Window { webdriver_script_chan: DOMRefCell::new(None), ignore_further_async_events: Arc::new(AtomicBool::new(false)), error_reporter: error_reporter, + scroll_offsets: DOMRefCell::new(HashMap::new()), panic_chan: panic_chan, }; |