mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
Implement offsetParent/Top/Left/Width/Height.
This commit is contained in:
parent
1809748dc1
commit
9e5687e3e7
21 changed files with 325 additions and 24 deletions
|
@ -12,7 +12,7 @@ use dom::bindings::codegen::Bindings::HTMLInputElementBinding::HTMLInputElementM
|
|||
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
|
||||
use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLFrameSetElementDerived};
|
||||
use dom::bindings::codegen::InheritTypes::{EventTargetCast, HTMLInputElementCast, NodeCast};
|
||||
use dom::bindings::codegen::InheritTypes::{HTMLElementDerived, HTMLBodyElementDerived};
|
||||
use dom::bindings::codegen::InheritTypes::{HTMLElementDerived, HTMLBodyElementDerived, HTMLHtmlElementDerived};
|
||||
use dom::bindings::js::{JS, MutNullableHeap, Root};
|
||||
use dom::bindings::error::ErrorResult;
|
||||
use dom::bindings::error::Error::Syntax;
|
||||
|
@ -216,6 +216,63 @@ impl<'a> HTMLElementMethods for &'a HTMLElement {
|
|||
// If `request_focus` is not called, focus will be set to None.
|
||||
document.r().commit_focus_transaction(FocusType::Element);
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/cssom-view/#extensions-to-the-htmlelement-interface
|
||||
fn GetOffsetParent(self) -> Option<Root<Element>> {
|
||||
if self.is_htmlbodyelement() || self.is_htmlhtmlelement() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let node = NodeCast::from_ref(self);
|
||||
let window = window_from_node(self);
|
||||
let (element, _) = window.offset_parent_query(node.to_trusted_node_address());
|
||||
|
||||
element
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/cssom-view/#extensions-to-the-htmlelement-interface
|
||||
fn OffsetTop(self) -> i32 {
|
||||
if self.is_htmlbodyelement() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let node = NodeCast::from_ref(self);
|
||||
let window = window_from_node(self);
|
||||
let (_, rect) = window.offset_parent_query(node.to_trusted_node_address());
|
||||
|
||||
rect.origin.y.to_nearest_px()
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/cssom-view/#extensions-to-the-htmlelement-interface
|
||||
fn OffsetLeft(self) -> i32 {
|
||||
if self.is_htmlbodyelement() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let node = NodeCast::from_ref(self);
|
||||
let window = window_from_node(self);
|
||||
let (_, rect) = window.offset_parent_query(node.to_trusted_node_address());
|
||||
|
||||
rect.origin.x.to_nearest_px()
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/cssom-view/#extensions-to-the-htmlelement-interface
|
||||
fn OffsetWidth(self) -> i32 {
|
||||
let node = NodeCast::from_ref(self);
|
||||
let window = window_from_node(self);
|
||||
let (_, rect) = window.offset_parent_query(node.to_trusted_node_address());
|
||||
|
||||
rect.size.width.to_nearest_px()
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/cssom-view/#extensions-to-the-htmlelement-interface
|
||||
fn OffsetHeight(self) -> i32 {
|
||||
let node = NodeCast::from_ref(self);
|
||||
let window = window_from_node(self);
|
||||
let (_, rect) = window.offset_parent_query(node.to_trusted_node_address());
|
||||
|
||||
rect.size.height.to_nearest_px()
|
||||
}
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/#attr-data-*
|
||||
|
|
|
@ -45,5 +45,16 @@ interface HTMLElement : Element {
|
|||
//readonly attribute boolean? commandDisabled;
|
||||
//readonly attribute boolean? commandChecked;
|
||||
};
|
||||
|
||||
// http://dev.w3.org/csswg/cssom-view/#extensions-to-the-htmlelement-interface
|
||||
partial interface HTMLElement {
|
||||
// CSSOM things are not [Pure] because they can flush
|
||||
readonly attribute Element? offsetParent;
|
||||
readonly attribute long offsetTop;
|
||||
readonly attribute long offsetLeft;
|
||||
readonly attribute long offsetWidth;
|
||||
readonly attribute long offsetHeight;
|
||||
};
|
||||
|
||||
HTMLElement implements GlobalEventHandlers;
|
||||
HTMLElement implements ElementCSSInlineStyle;
|
||||
|
|
|
@ -8,7 +8,7 @@ use dom::bindings::codegen::Bindings::EventHandlerBinding::{OnErrorEventHandlerN
|
|||
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
|
||||
use dom::bindings::codegen::Bindings::FunctionBinding::Function;
|
||||
use dom::bindings::codegen::Bindings::WindowBinding::{self, WindowMethods, FrameRequestCallback};
|
||||
use dom::bindings::codegen::InheritTypes::{NodeCast, EventTargetCast};
|
||||
use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast, EventTargetCast};
|
||||
use dom::bindings::global::global_object_for_js_object;
|
||||
use dom::bindings::error::{report_pending_exception, Fallible};
|
||||
use dom::bindings::error::Error::InvalidCharacter;
|
||||
|
@ -27,7 +27,7 @@ use dom::eventtarget::{EventTarget, EventTargetHelpers, EventTargetTypeId};
|
|||
use dom::htmlelement::HTMLElement;
|
||||
use dom::location::Location;
|
||||
use dom::navigator::Navigator;
|
||||
use dom::node::{window_from_node, TrustedNodeAddress, NodeHelpers};
|
||||
use dom::node::{window_from_node, TrustedNodeAddress, NodeHelpers, from_untrusted_node_address};
|
||||
use dom::performance::Performance;
|
||||
use dom::screen::Screen;
|
||||
use dom::storage::Storage;
|
||||
|
@ -578,6 +578,7 @@ pub trait WindowHelpers {
|
|||
fn client_rect_query(self, node_geometry_request: TrustedNodeAddress) -> Rect<i32>;
|
||||
fn resolved_style_query(self, element: TrustedNodeAddress,
|
||||
pseudo: Option<PseudoElement>, property: &Atom) -> Option<String>;
|
||||
fn offset_parent_query(self, node: TrustedNodeAddress) -> (Option<Root<Element>>, Rect<Au>);
|
||||
fn handle_reflow_complete_msg(self, reflow_id: u32);
|
||||
fn set_fragment_name(self, fragment: Option<String>);
|
||||
fn steal_fragment_name(self) -> Option<String>;
|
||||
|
@ -827,6 +828,27 @@ impl<'a> WindowHelpers for &'a Window {
|
|||
resolved
|
||||
}
|
||||
|
||||
fn offset_parent_query(self, node: TrustedNodeAddress) -> (Option<Root<Element>>, Rect<Au>) {
|
||||
self.reflow(ReflowGoal::ForScriptQuery,
|
||||
ReflowQueryType::OffsetParentQuery(node),
|
||||
ReflowReason::Query);
|
||||
let response = self.layout_rpc.offset_parent();
|
||||
let js_runtime = self.js_runtime.borrow();
|
||||
let js_runtime = js_runtime.as_ref().unwrap();
|
||||
let element = match response.node_address {
|
||||
Some(parent_node_address) => {
|
||||
let node = from_untrusted_node_address(js_runtime.rt(),
|
||||
parent_node_address);
|
||||
let element = ElementCast::to_ref(node.r()).unwrap();
|
||||
Some(Root::from_ref(element))
|
||||
}
|
||||
None => {
|
||||
None
|
||||
}
|
||||
};
|
||||
(element, response.rect)
|
||||
}
|
||||
|
||||
fn handle_reflow_complete_msg(self, reflow_id: u32) {
|
||||
let last_reflow_id = self.last_reflow_id.get();
|
||||
if last_reflow_id == reflow_id {
|
||||
|
@ -1135,6 +1157,7 @@ fn debug_reflow_events(goal: &ReflowGoal, query_type: &ReflowQueryType, reason:
|
|||
ReflowQueryType::ContentBoxesQuery(_n) => "\tContentBoxesQuery",
|
||||
ReflowQueryType::NodeGeometryQuery(_n) => "\tNodeGeometryQuery",
|
||||
ReflowQueryType::ResolvedStyleQuery(_, _, _) => "\tResolvedStyleQuery",
|
||||
ReflowQueryType::OffsetParentQuery(_n) => "\tOffsetParentQuery",
|
||||
});
|
||||
|
||||
debug_msg.push_str(match *reason {
|
||||
|
|
|
@ -104,6 +104,7 @@ pub trait LayoutRPC {
|
|||
fn mouse_over(&self, node: TrustedNodeAddress, point: Point2D<f32>) -> Result<MouseOverResponse, ()>;
|
||||
/// Query layout for the resolved value of a given CSS property
|
||||
fn resolved_style(&self) -> ResolvedStyleResponse;
|
||||
fn offset_parent(&self) -> OffsetParentResponse;
|
||||
}
|
||||
|
||||
|
||||
|
@ -116,6 +117,21 @@ pub struct HitTestResponse(pub UntrustedNodeAddress);
|
|||
pub struct MouseOverResponse(pub Vec<UntrustedNodeAddress>);
|
||||
pub struct ResolvedStyleResponse(pub Option<String>);
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct OffsetParentResponse {
|
||||
pub node_address: Option<UntrustedNodeAddress>,
|
||||
pub rect: Rect<Au>,
|
||||
}
|
||||
|
||||
impl OffsetParentResponse {
|
||||
pub fn empty() -> OffsetParentResponse {
|
||||
OffsetParentResponse {
|
||||
node_address: None,
|
||||
rect: Rect::zero(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Why we're doing reflow.
|
||||
#[derive(PartialEq, Copy, Clone, Debug)]
|
||||
pub enum ReflowGoal {
|
||||
|
@ -133,6 +149,7 @@ pub enum ReflowQueryType {
|
|||
ContentBoxesQuery(TrustedNodeAddress),
|
||||
NodeGeometryQuery(TrustedNodeAddress),
|
||||
ResolvedStyleQuery(TrustedNodeAddress, Option<PseudoElement>, Atom),
|
||||
OffsetParentQuery(TrustedNodeAddress),
|
||||
}
|
||||
|
||||
/// Information needed for a reflow.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue