Completed implementation of devtools' getLayout.

This commit is contained in:
benshu 2015-08-18 15:11:09 +02:00 committed by Josh Matthews
parent 9ab2da3cd1
commit 0785d91ae4
13 changed files with 225 additions and 42 deletions

View file

@ -2,18 +2,22 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use devtools_traits::{CONSOLE_API, CachedConsoleMessage, CachedConsoleMessageTypes, PAGE_ERROR};
use devtools_traits::TimelineMarkerType;
use devtools_traits::{AutoMargins, CONSOLE_API, CachedConsoleMessage, CachedConsoleMessageTypes};
use devtools_traits::{ComputedNodeLayout, ConsoleAPI, PageError, ScriptToDevtoolsControlMsg};
use devtools_traits::{EvaluateJSReply, Modification, NodeInfo, TimelineMarker, TimelineMarkerType};
use devtools_traits::{EvaluateJSReply, Modification, NodeInfo, PAGE_ERROR, TimelineMarker};
use dom::bindings::codegen::Bindings::CSSStyleDeclarationBinding::CSSStyleDeclarationMethods;
use dom::bindings::codegen::Bindings::DOMRectBinding::DOMRectMethods;
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
use dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use dom::bindings::conversions::{FromJSValConvertible, jsstring_to_str};
use dom::bindings::global::GlobalRef;
use dom::bindings::inheritance::Castable;
use dom::bindings::js::Root;
use dom::element::Element;
use dom::node::Node;
use dom::window::Window;
use ipc_channel::ipc::IpcSender;
use js::jsapi::{ObjectClassName, RootedObject, RootedValue};
use js::jsval::UndefinedValue;
@ -23,6 +27,7 @@ use script_thread::get_page;
use std::ffi::CStr;
use std::rc::Rc;
use std::str;
use style::properties::longhands::{margin_top, margin_right, margin_bottom, margin_left};
use util::str::DOMString;
use uuid::Uuid;
@ -110,15 +115,47 @@ pub fn handle_get_layout(page: &Rc<Page>,
node_id: String,
reply: IpcSender<ComputedNodeLayout>) {
let node = find_node_by_unique_id(&*page, pipeline, node_id);
let elem = node.downcast::<Element>().expect("should be getting layout of element");
let rect = elem.GetBoundingClientRect();
let width = rect.Width() as f32;
let height = rect.Height() as f32;
let window = page.window();
let elem = node.downcast::<Element>().expect("should be getting layout of element");
let computed_style = window.r().GetComputedStyle(elem, None);
reply.send(ComputedNodeLayout {
width: width,
height: height,
})
.unwrap();
display: String::from(computed_style.Display()),
position: String::from(computed_style.Position()),
zIndex: String::from(computed_style.ZIndex()),
boxSizing: String::from(computed_style.BoxSizing()),
autoMargins: determine_auto_margins(&window, &*node),
marginTop: String::from(computed_style.MarginTop()),
marginRight: String::from(computed_style.MarginRight()),
marginBottom: String::from(computed_style.MarginBottom()),
marginLeft: String::from(computed_style.MarginLeft()),
borderTopWidth: String::from(computed_style.BorderTopWidth()),
borderRightWidth: String::from(computed_style.BorderRightWidth()),
borderBottomWidth: String::from(computed_style.BorderBottomWidth()),
borderLeftWidth: String::from(computed_style.BorderLeftWidth()),
paddingTop: String::from(computed_style.PaddingTop()),
paddingRight: String::from(computed_style.PaddingRight()),
paddingBottom: String::from(computed_style.PaddingBottom()),
paddingLeft: String::from(computed_style.PaddingLeft()),
width: width,
height: height,
}).unwrap();
}
fn determine_auto_margins(window: &Window, node: &Node) -> AutoMargins {
let margin = window.margin_style_query(node.to_trusted_node_address());
AutoMargins {
top: margin.top == margin_top::computed_value::T::Auto,
right: margin.right == margin_right::computed_value::T::Auto,
bottom: margin.bottom == margin_bottom::computed_value::T::Auto,
left: margin.left == margin_left::computed_value::T::Auto,
}
}
pub fn handle_get_cached_messages(_pipeline_id: PipelineId,

View file

@ -185,7 +185,6 @@ unsafe impl Send for OpaqueStyleAndLayoutData {}
no_jsmanaged_fields!(OpaqueStyleAndLayoutData);
impl OpaqueStyleAndLayoutData {
/// Sends the style and layout data, if any, back to the layout thread to be destroyed.
pub fn dispose(self, node: &Node) {

View file

@ -41,7 +41,7 @@ use js::jsapi::{JSAutoCompartment, JSAutoRequest, JS_GC, JS_GetRuntime};
use js::rust::CompileOptionsWrapper;
use js::rust::Runtime;
use layout_interface::{ContentBoxResponse, ContentBoxesResponse, ResolvedStyleResponse, ScriptReflow};
use layout_interface::{LayoutChan, LayoutRPC, Msg, Reflow, ReflowQueryType};
use layout_interface::{LayoutChan, LayoutRPC, Msg, Reflow, ReflowQueryType, MarginStyleResponse};
use libc;
use msg::constellation_msg::{ConstellationChan, LoadData, PipelineId, SubpageId, WindowSizeData};
use msg::webdriver_msg::{WebDriverJSError, WebDriverJSResult};
@ -1099,6 +1099,13 @@ impl Window {
(element, response.rect)
}
pub fn margin_style_query(&self, node: TrustedNodeAddress) -> MarginStyleResponse {
self.reflow(ReflowGoal::ForScriptQuery,
ReflowQueryType::MarginStyleQuery(node),
ReflowReason::Query);
self.layout_rpc.margin_style()
}
pub fn init_browsing_context(&self, browsing_context: &BrowsingContext) {
assert!(self.browsing_context.get().is_none());
self.browsing_context.set(Some(&browsing_context));
@ -1420,6 +1427,7 @@ fn debug_reflow_events(goal: &ReflowGoal, query_type: &ReflowQueryType, reason:
ReflowQueryType::NodeGeometryQuery(_n) => "\tNodeGeometryQuery",
ReflowQueryType::ResolvedStyleQuery(_, _, _) => "\tResolvedStyleQuery",
ReflowQueryType::OffsetParentQuery(_n) => "\tOffsetParentQuery",
ReflowQueryType::MarginStyleQuery(_n) => "\tMarginStyleQuery",
});
debug_msg.push_str(match *reason {

View file

@ -23,6 +23,7 @@ use std::sync::Arc;
use std::sync::mpsc::{Receiver, Sender, channel};
use string_cache::Atom;
use style::context::ReflowGoal;
use style::properties::longhands::{margin_top, margin_right, margin_bottom, margin_left};
use style::selector_impl::PseudoElement;
use style::servo::Stylesheet;
use url::Url;
@ -109,8 +110,28 @@ pub trait LayoutRPC {
/// Query layout for the resolved value of a given CSS property
fn resolved_style(&self) -> ResolvedStyleResponse;
fn offset_parent(&self) -> OffsetParentResponse;
/// Query layout for the resolve values of the margin properties for an element.
fn margin_style(&self) -> MarginStyleResponse;
}
#[derive(Clone)]
pub struct MarginStyleResponse {
pub top: margin_top::computed_value::T,
pub right: margin_right::computed_value::T,
pub bottom: margin_bottom::computed_value::T,
pub left: margin_left::computed_value::T,
}
impl MarginStyleResponse {
pub fn empty() -> MarginStyleResponse {
MarginStyleResponse {
top: margin_top::computed_value::T::Auto,
right: margin_right::computed_value::T::Auto,
bottom: margin_bottom::computed_value::T::Auto,
left: margin_left::computed_value::T::Auto,
}
}
}
pub struct ContentBoxResponse(pub Rect<Au>);
pub struct ContentBoxesResponse(pub Vec<Rect<Au>>);
@ -145,6 +166,7 @@ pub enum ReflowQueryType {
NodeGeometryQuery(TrustedNodeAddress),
ResolvedStyleQuery(TrustedNodeAddress, Option<PseudoElement>, Atom),
OffsetParentQuery(TrustedNodeAddress),
MarginStyleQuery(TrustedNodeAddress),
}
/// Information needed for a reflow.