mirror of
https://github.com/servo/servo.git
synced 2025-08-07 06:25:32 +01:00
Move font.ready trigger out of reflow
This commit is contained in:
parent
31096e1a0f
commit
4b8a25afab
19 changed files with 130 additions and 151 deletions
|
@ -1475,11 +1475,10 @@ impl CanvasState {
|
|||
};
|
||||
let node = canvas.upcast::<Node>();
|
||||
let window = canvas.owner_window();
|
||||
let resolved_font_style =
|
||||
match window.resolved_font_style_query(node, value.to_string(), can_gc) {
|
||||
Some(value) => value,
|
||||
None => return, // syntax error
|
||||
};
|
||||
let resolved_font_style = match window.resolved_font_style_query(node, value.to_string()) {
|
||||
Some(value) => value,
|
||||
None => return, // syntax error
|
||||
};
|
||||
self.state.borrow_mut().font_style = Some((*resolved_font_style).clone());
|
||||
}
|
||||
|
||||
|
|
|
@ -395,7 +395,7 @@ pub(crate) fn handle_get_layout(
|
|||
}
|
||||
|
||||
fn determine_auto_margins(node: &Node, can_gc: CanGc) -> AutoMargins {
|
||||
let style = node.style(can_gc).unwrap();
|
||||
let style = node.style().unwrap();
|
||||
let margin = style.get_margin();
|
||||
AutoMargins {
|
||||
top: margin.margin_top.is_auto(),
|
||||
|
|
|
@ -280,7 +280,7 @@ impl CSSStyleDeclaration {
|
|||
}
|
||||
let addr = node.to_trusted_node_address();
|
||||
node.owner_window()
|
||||
.resolved_style_query(addr, self.pseudo, property, can_gc)
|
||||
.resolved_style_query(addr, self.pseudo, property)
|
||||
},
|
||||
CSSStyleOwner::Null => DOMString::new(),
|
||||
}
|
||||
|
|
|
@ -2886,7 +2886,7 @@ impl Document {
|
|||
// We finished loading the page, so if the `Window` is still waiting for
|
||||
// the first layout, allow it.
|
||||
if self.has_browsing_context && self.is_fully_active() {
|
||||
self.window().allow_layout_if_necessary(can_gc);
|
||||
self.window().allow_layout_if_necessary();
|
||||
}
|
||||
|
||||
// Deferred scripts have to wait for page to finish loading,
|
||||
|
@ -3688,7 +3688,7 @@ impl Document {
|
|||
// > doc and its node navigable to reflect the current state.
|
||||
//
|
||||
// Returns true if a reflow occured.
|
||||
pub(crate) fn update_the_rendering(&self, can_gc: CanGc) -> bool {
|
||||
pub(crate) fn update_the_rendering(&self) -> bool {
|
||||
self.update_animating_images();
|
||||
|
||||
// All dirty canvases are flushed before updating the rendering.
|
||||
|
@ -3723,7 +3723,41 @@ impl Document {
|
|||
receiver.recv().unwrap();
|
||||
}
|
||||
|
||||
self.window().reflow(ReflowGoal::UpdateTheRendering, can_gc)
|
||||
self.window().reflow(ReflowGoal::UpdateTheRendering)
|
||||
}
|
||||
|
||||
/// From https://drafts.csswg.org/css-font-loading/#font-face-set-ready:
|
||||
/// > A FontFaceSet is pending on the environment if any of the following are true:
|
||||
/// > - the document is still loading
|
||||
/// > - the document has pending stylesheet requests
|
||||
/// > - the document has pending layout operations which might cause the user agent to request
|
||||
/// > a font, or which depend on recently-loaded fonts
|
||||
pub(crate) fn maybe_send_document_fonts_ready_message(&self, can_gc: CanGc) {
|
||||
if !self.is_fully_active() {
|
||||
return;
|
||||
}
|
||||
|
||||
let fonts = self.Fonts(can_gc);
|
||||
//println!(
|
||||
// "fonts: {:?} {:?} {:?} {:?}",
|
||||
// fonts.waiting_to_fullfill_promise(),
|
||||
// self.window().font_context().web_fonts_still_loading() == 0,
|
||||
// self.ReadyState() == DocumentReadyState::Complete,
|
||||
// !self.needs_rendering_update()
|
||||
//);
|
||||
if !fonts.waiting_to_fullfill_promise() {
|
||||
return;
|
||||
}
|
||||
if self.window().font_context().web_fonts_still_loading() != 0 {
|
||||
return;
|
||||
}
|
||||
if self.ReadyState() != DocumentReadyState::Complete {
|
||||
return;
|
||||
}
|
||||
if self.needs_rendering_update() {
|
||||
return;
|
||||
}
|
||||
fonts.fulfill_ready_promise_if_needed(can_gc);
|
||||
}
|
||||
|
||||
pub(crate) fn id_map(&self) -> Ref<HashMapTracedValues<Atom, Vec<Dom<Element>>>> {
|
||||
|
|
|
@ -141,10 +141,8 @@ impl DocumentOrShadowRoot {
|
|||
&self,
|
||||
client_point: &Point2D<f32>,
|
||||
query_type: NodesFromPointQueryType,
|
||||
can_gc: CanGc,
|
||||
) -> Vec<UntrustedNodeAddress> {
|
||||
self.window
|
||||
.layout_reflow(QueryMsg::NodesFromPointQuery, can_gc);
|
||||
self.window.layout_reflow(QueryMsg::NodesFromPointQuery);
|
||||
self.window
|
||||
.layout()
|
||||
.query_nodes_from_point(*client_point, query_type)
|
||||
|
@ -174,7 +172,7 @@ impl DocumentOrShadowRoot {
|
|||
}
|
||||
|
||||
match self
|
||||
.nodes_from_point(point, NodesFromPointQueryType::Topmost, can_gc)
|
||||
.nodes_from_point(point, NodesFromPointQueryType::Topmost)
|
||||
.first()
|
||||
{
|
||||
Some(address) => {
|
||||
|
@ -223,7 +221,7 @@ impl DocumentOrShadowRoot {
|
|||
}
|
||||
|
||||
// Step 1 and Step 3
|
||||
let nodes = self.nodes_from_point(point, NodesFromPointQueryType::All, can_gc);
|
||||
let nodes = self.nodes_from_point(point, NodesFromPointQueryType::All);
|
||||
let mut elements: Vec<DomRoot<Element>> = nodes
|
||||
.iter()
|
||||
.flat_map(|&untrusted_node_address| {
|
||||
|
|
|
@ -465,7 +465,7 @@ impl Element {
|
|||
/// style will be `None` for elements in a `display: none` subtree. otherwise, the element has a
|
||||
/// layout box iff it doesn't have `display: none`.
|
||||
pub(crate) fn style(&self, can_gc: CanGc) -> Option<Arc<ComputedValues>> {
|
||||
self.upcast::<Node>().style(can_gc)
|
||||
self.upcast::<Node>().style()
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/cssom-view/#css-layout-box
|
||||
|
@ -2524,7 +2524,7 @@ impl Element {
|
|||
}
|
||||
|
||||
// Step 11
|
||||
win.scroll_node(node, x, y, behavior, can_gc);
|
||||
win.scroll_node(node, x, y, behavior);
|
||||
}
|
||||
|
||||
/// <https://html.spec.whatwg.org/multipage/#fragment-parsing-algorithm-steps>
|
||||
|
@ -3057,7 +3057,7 @@ impl ElementMethods<crate::DomTypeHolder> for Element {
|
|||
// https://drafts.csswg.org/cssom-view/#dom-element-getclientrects
|
||||
fn GetClientRects(&self, can_gc: CanGc) -> DomRoot<DOMRectList> {
|
||||
let win = self.owner_window();
|
||||
let raw_rects = self.upcast::<Node>().content_boxes(can_gc);
|
||||
let raw_rects = self.upcast::<Node>().content_boxes();
|
||||
let rects: Vec<DomRoot<DOMRect>> = raw_rects
|
||||
.iter()
|
||||
.map(|rect| {
|
||||
|
@ -3175,7 +3175,7 @@ impl ElementMethods<crate::DomTypeHolder> for Element {
|
|||
}
|
||||
|
||||
// Step 9
|
||||
let point = win.scroll_offset_query(node, can_gc);
|
||||
let point = win.scroll_offset_query(node);
|
||||
point.y.abs() as f64
|
||||
}
|
||||
|
||||
|
@ -3229,7 +3229,7 @@ impl ElementMethods<crate::DomTypeHolder> for Element {
|
|||
}
|
||||
|
||||
// Step 11
|
||||
win.scroll_node(node, self.ScrollLeft(can_gc), y, behavior, can_gc);
|
||||
win.scroll_node(node, self.ScrollLeft(can_gc), y, behavior);
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/cssom-view/#dom-element-scrolltop
|
||||
|
@ -3274,7 +3274,7 @@ impl ElementMethods<crate::DomTypeHolder> for Element {
|
|||
}
|
||||
|
||||
// Step 9
|
||||
let point = win.scroll_offset_query(node, can_gc);
|
||||
let point = win.scroll_offset_query(node);
|
||||
point.x.abs() as f64
|
||||
}
|
||||
|
||||
|
@ -3329,7 +3329,7 @@ impl ElementMethods<crate::DomTypeHolder> for Element {
|
|||
}
|
||||
|
||||
// Step 11
|
||||
win.scroll_node(node, x, self.ScrollTop(can_gc), behavior, can_gc);
|
||||
win.scroll_node(node, x, self.ScrollTop(can_gc), behavior);
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/cssom-view/#dom-element-scrollwidth
|
||||
|
@ -4789,7 +4789,7 @@ impl Element {
|
|||
}
|
||||
}
|
||||
|
||||
let mut rect = self.upcast::<Node>().client_rect(can_gc);
|
||||
let mut rect = self.upcast::<Node>().client_rect();
|
||||
let in_quirks_mode = doc.quirks_mode() == QuirksMode::Quirks;
|
||||
|
||||
if (in_quirks_mode && doc.GetBody().as_deref() == self.downcast::<HTMLElement>()) ||
|
||||
|
|
|
@ -74,6 +74,10 @@ impl FontFaceSet {
|
|||
self.promise.resolve_native(self, can_gc);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn waiting_to_fullfill_promise(&self) -> bool {
|
||||
!self.promise.is_fulfilled()
|
||||
}
|
||||
}
|
||||
|
||||
impl FontFaceSetMethods<crate::DomTypeHolder> for FontFaceSet {
|
||||
|
|
|
@ -127,7 +127,7 @@ impl HTMLElement {
|
|||
return node.GetTextContent().unwrap();
|
||||
}
|
||||
|
||||
window.layout_reflow(QueryMsg::ElementInnerOuterTextQuery, can_gc);
|
||||
window.layout_reflow(QueryMsg::ElementInnerOuterTextQuery);
|
||||
let text = window
|
||||
.layout()
|
||||
.query_element_inner_outer_text(node.to_trusted_node_address());
|
||||
|
@ -445,7 +445,7 @@ impl HTMLElementMethods<crate::DomTypeHolder> for HTMLElement {
|
|||
|
||||
let node = self.upcast::<Node>();
|
||||
let window = self.owner_window();
|
||||
let (element, _) = window.offset_parent_query(node, can_gc);
|
||||
let (element, _) = window.offset_parent_query(node);
|
||||
|
||||
element
|
||||
}
|
||||
|
@ -458,7 +458,7 @@ impl HTMLElementMethods<crate::DomTypeHolder> for HTMLElement {
|
|||
|
||||
let node = self.upcast::<Node>();
|
||||
let window = self.owner_window();
|
||||
let (_, rect) = window.offset_parent_query(node, can_gc);
|
||||
let (_, rect) = window.offset_parent_query(node);
|
||||
|
||||
rect.origin.y.to_nearest_px()
|
||||
}
|
||||
|
@ -471,7 +471,7 @@ impl HTMLElementMethods<crate::DomTypeHolder> for HTMLElement {
|
|||
|
||||
let node = self.upcast::<Node>();
|
||||
let window = self.owner_window();
|
||||
let (_, rect) = window.offset_parent_query(node, can_gc);
|
||||
let (_, rect) = window.offset_parent_query(node);
|
||||
|
||||
rect.origin.x.to_nearest_px()
|
||||
}
|
||||
|
@ -480,7 +480,7 @@ impl HTMLElementMethods<crate::DomTypeHolder> for HTMLElement {
|
|||
fn OffsetWidth(&self, can_gc: CanGc) -> i32 {
|
||||
let node = self.upcast::<Node>();
|
||||
let window = self.owner_window();
|
||||
let (_, rect) = window.offset_parent_query(node, can_gc);
|
||||
let (_, rect) = window.offset_parent_query(node);
|
||||
|
||||
rect.size.width.to_nearest_px()
|
||||
}
|
||||
|
@ -489,7 +489,7 @@ impl HTMLElementMethods<crate::DomTypeHolder> for HTMLElement {
|
|||
fn OffsetHeight(&self, can_gc: CanGc) -> i32 {
|
||||
let node = self.upcast::<Node>();
|
||||
let window = self.owner_window();
|
||||
let (_, rect) = window.offset_parent_query(node, can_gc);
|
||||
let (_, rect) = window.offset_parent_query(node);
|
||||
|
||||
rect.size.height.to_nearest_px()
|
||||
}
|
||||
|
|
|
@ -210,7 +210,7 @@ impl HTMLIFrameElement {
|
|||
};
|
||||
|
||||
let viewport_details = window
|
||||
.get_iframe_viewport_details_if_known(browsing_context_id, can_gc)
|
||||
.get_iframe_viewport_details_if_known(browsing_context_id)
|
||||
.unwrap_or_else(|| ViewportDetails {
|
||||
hidpi_scale_factor: window.device_pixel_ratio(),
|
||||
..Default::default()
|
||||
|
|
|
@ -1657,7 +1657,7 @@ impl HTMLImageElementMethods<crate::DomTypeHolder> for HTMLImageElement {
|
|||
// https://html.spec.whatwg.org/multipage/#dom-img-width
|
||||
fn Width(&self, can_gc: CanGc) -> u32 {
|
||||
let node = self.upcast::<Node>();
|
||||
match node.bounding_content_box(can_gc) {
|
||||
match node.bounding_content_box() {
|
||||
Some(rect) => rect.size.width.to_px() as u32,
|
||||
None => self.NaturalWidth(),
|
||||
}
|
||||
|
@ -1671,7 +1671,7 @@ impl HTMLImageElementMethods<crate::DomTypeHolder> for HTMLImageElement {
|
|||
// https://html.spec.whatwg.org/multipage/#dom-img-height
|
||||
fn Height(&self, can_gc: CanGc) -> u32 {
|
||||
let node = self.upcast::<Node>();
|
||||
match node.bounding_content_box(can_gc) {
|
||||
match node.bounding_content_box() {
|
||||
Some(rect) => rect.size.height.to_px() as u32,
|
||||
None => self.NaturalHeight(),
|
||||
}
|
||||
|
|
|
@ -3074,11 +3074,8 @@ impl VirtualMethods for HTMLInputElement {
|
|||
// now.
|
||||
if let Some(point_in_target) = mouse_event.point_in_target() {
|
||||
let window = self.owner_window();
|
||||
let index = window.text_index_query(
|
||||
self.upcast::<Node>(),
|
||||
point_in_target.to_untyped(),
|
||||
can_gc,
|
||||
);
|
||||
let index = window
|
||||
.text_index_query(self.upcast::<Node>(), point_in_target.to_untyped());
|
||||
// Position the caret at the click position or at the end of the current
|
||||
// value.
|
||||
let edit_point_index = match index {
|
||||
|
|
|
@ -278,7 +278,7 @@ impl MouseEventMethods<crate::DomTypeHolder> for MouseEvent {
|
|||
) -> Fallible<DomRoot<MouseEvent>> {
|
||||
let bubbles = EventBubbles::from(init.parent.parent.parent.bubbles);
|
||||
let cancelable = EventCancelable::from(init.parent.parent.parent.cancelable);
|
||||
let scroll_offset = window.scroll_offset(can_gc);
|
||||
let scroll_offset = window.scroll_offset();
|
||||
let page_point = Point2D::new(
|
||||
scroll_offset.x as i32 + init.clientX,
|
||||
scroll_offset.y as i32 + init.clientY,
|
||||
|
@ -384,7 +384,7 @@ impl MouseEventMethods<crate::DomTypeHolder> for MouseEvent {
|
|||
let Some(node) = target.downcast::<Node>() else {
|
||||
return 0;
|
||||
};
|
||||
return self.ClientX() - node.client_rect(can_gc).origin.x;
|
||||
return self.ClientX() - node.client_rect().origin.x;
|
||||
}
|
||||
|
||||
// > 2. Return the value of the event’s pageX attribute.
|
||||
|
@ -406,7 +406,7 @@ impl MouseEventMethods<crate::DomTypeHolder> for MouseEvent {
|
|||
let Some(node) = target.downcast::<Node>() else {
|
||||
return 0;
|
||||
};
|
||||
return self.ClientY() - node.client_rect(can_gc).origin.y;
|
||||
return self.ClientY() - node.client_rect().origin.y;
|
||||
}
|
||||
|
||||
// 2. Return the value of the event’s pageY attribute.
|
||||
|
@ -498,7 +498,7 @@ impl MouseEventMethods<crate::DomTypeHolder> for MouseEvent {
|
|||
.set(Point2D::new(client_x_arg, client_y_arg));
|
||||
|
||||
let global = self.global();
|
||||
let scroll_offset = global.as_window().scroll_offset(can_gc);
|
||||
let scroll_offset = global.as_window().scroll_offset();
|
||||
self.page_point.set(Point2D::new(
|
||||
scroll_offset.x as i32 + client_x_arg,
|
||||
scroll_offset.y as i32 + client_y_arg,
|
||||
|
|
|
@ -944,24 +944,24 @@ impl Node {
|
|||
|
||||
/// Returns the rendered bounding content box if the element is rendered,
|
||||
/// and none otherwise.
|
||||
pub(crate) fn bounding_content_box(&self, can_gc: CanGc) -> Option<Rect<Au>> {
|
||||
self.owner_window().content_box_query(self, can_gc)
|
||||
pub(crate) fn bounding_content_box(&self) -> Option<Rect<Au>> {
|
||||
self.owner_window().content_box_query(self)
|
||||
}
|
||||
|
||||
pub(crate) fn bounding_content_box_or_zero(&self, can_gc: CanGc) -> Rect<Au> {
|
||||
self.bounding_content_box(can_gc).unwrap_or_else(Rect::zero)
|
||||
self.bounding_content_box().unwrap_or_else(Rect::zero)
|
||||
}
|
||||
|
||||
pub(crate) fn bounding_content_box_no_reflow(&self) -> Option<Rect<Au>> {
|
||||
self.owner_window().content_box_query_unchecked(self)
|
||||
}
|
||||
|
||||
pub(crate) fn content_boxes(&self, can_gc: CanGc) -> Vec<Rect<Au>> {
|
||||
self.owner_window().content_boxes_query(self, can_gc)
|
||||
pub(crate) fn content_boxes(&self) -> Vec<Rect<Au>> {
|
||||
self.owner_window().content_boxes_query(self)
|
||||
}
|
||||
|
||||
pub(crate) fn client_rect(&self, can_gc: CanGc) -> Rect<i32> {
|
||||
self.owner_window().client_rect_query(self, can_gc)
|
||||
pub(crate) fn client_rect(&self) -> Rect<i32> {
|
||||
self.owner_window().client_rect_query(self)
|
||||
}
|
||||
|
||||
/// <https://drafts.csswg.org/cssom-view/#dom-element-scrollwidth>
|
||||
|
@ -992,7 +992,7 @@ impl Node {
|
|||
// element is not potentially scrollable, return max(viewport scrolling area
|
||||
// width, viewport width)."
|
||||
if (is_root && !in_quirks_mode) || (is_body_element && in_quirks_mode) {
|
||||
let viewport_scrolling_area = window.scrolling_area_query(None, can_gc);
|
||||
let viewport_scrolling_area = window.scrolling_area_query(None);
|
||||
return Rect::new(
|
||||
viewport_scrolling_area.origin,
|
||||
viewport_scrolling_area.size.max(viewport),
|
||||
|
@ -1002,7 +1002,7 @@ impl Node {
|
|||
// "6. If the element does not have any associated box return zero and terminate
|
||||
// these steps."
|
||||
// "7. Return the width of the element’s scrolling area."
|
||||
window.scrolling_area_query(Some(self), can_gc)
|
||||
window.scrolling_area_query(Some(self))
|
||||
}
|
||||
|
||||
/// <https://dom.spec.whatwg.org/#dom-childnode-before>
|
||||
|
@ -1461,9 +1461,8 @@ impl Node {
|
|||
})
|
||||
}
|
||||
|
||||
pub(crate) fn style(&self, can_gc: CanGc) -> Option<Arc<ComputedValues>> {
|
||||
self.owner_window()
|
||||
.layout_reflow(QueryMsg::StyleQuery, can_gc);
|
||||
pub(crate) fn style(&self) -> Option<Arc<ComputedValues>> {
|
||||
self.owner_window().layout_reflow(QueryMsg::StyleQuery);
|
||||
self.style_data
|
||||
.borrow()
|
||||
.as_ref()
|
||||
|
|
|
@ -233,7 +233,7 @@ impl PointerEventMethods<crate::DomTypeHolder> for PointerEvent {
|
|||
) -> DomRoot<PointerEvent> {
|
||||
let bubbles = EventBubbles::from(init.parent.parent.parent.parent.bubbles);
|
||||
let cancelable = EventCancelable::from(init.parent.parent.parent.parent.cancelable);
|
||||
let scroll_offset = window.scroll_offset(can_gc);
|
||||
let scroll_offset = window.scroll_offset();
|
||||
let page_point = Point2D::new(
|
||||
scroll_offset.x as i32 + init.parent.clientX,
|
||||
scroll_offset.y as i32 + init.parent.clientY,
|
||||
|
|
|
@ -341,7 +341,7 @@ impl Range {
|
|||
.following_nodes(document.upcast::<Node>())
|
||||
.take_while(move |node| node != &end)
|
||||
.chain(iter::once(end_clone))
|
||||
.flat_map(move |node| node.content_boxes(can_gc))
|
||||
.flat_map(move |node| node.content_boxes())
|
||||
}
|
||||
|
||||
/// <https://dom.spec.whatwg.org/#concept-range-bp-set>
|
||||
|
|
|
@ -312,7 +312,7 @@ fn calculate_box_size(
|
|||
// but the spec will expand to cover all fragments.
|
||||
target
|
||||
.upcast::<Node>()
|
||||
.content_boxes(can_gc)
|
||||
.content_boxes()
|
||||
.pop()
|
||||
.unwrap_or_else(Rect::zero)
|
||||
},
|
||||
|
|
|
@ -204,7 +204,7 @@ impl WheelEventMethods<crate::DomTypeHolder> for WheelEvent {
|
|||
) -> Fallible<DomRoot<WheelEvent>> {
|
||||
let bubbles = EventBubbles::from(init.parent.parent.parent.parent.bubbles);
|
||||
let cancelable = EventCancelable::from(init.parent.parent.parent.parent.cancelable);
|
||||
let scroll_offset = window.scroll_offset(can_gc);
|
||||
let scroll_offset = window.scroll_offset();
|
||||
|
||||
let page_point = Point2D::<i32, CSSPixel>::new(
|
||||
scroll_offset.x as i32 + init.parent.clientX,
|
||||
|
|
|
@ -1615,7 +1615,7 @@ impl WindowMethods<crate::DomTypeHolder> for Window {
|
|||
|
||||
/// <https://drafts.csswg.org/cssom-view/#dom-window-scrollx>
|
||||
fn ScrollX(&self) -> i32 {
|
||||
self.scroll_offset(CanGc::note()).x as i32
|
||||
self.scroll_offset().x as i32
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/cssom-view/#dom-window-pagexoffset
|
||||
|
@ -1625,7 +1625,7 @@ impl WindowMethods<crate::DomTypeHolder> for Window {
|
|||
|
||||
/// <https://drafts.csswg.org/cssom-view/#dom-window-scrolly>
|
||||
fn ScrollY(&self) -> i32 {
|
||||
self.scroll_offset(CanGc::note()).y as i32
|
||||
self.scroll_offset().y as i32
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/cssom-view/#dom-window-pageyoffset
|
||||
|
@ -1667,7 +1667,7 @@ impl WindowMethods<crate::DomTypeHolder> for Window {
|
|||
|
||||
// https://drafts.csswg.org/cssom-view/#dom-window-scrollby
|
||||
fn ScrollBy_(&self, x: f64, y: f64, can_gc: CanGc) {
|
||||
let scroll_offset = self.scroll_offset(can_gc);
|
||||
let scroll_offset = self.scroll_offset();
|
||||
// Step 3
|
||||
let left = x + scroll_offset.x as f64;
|
||||
// Step 4
|
||||
|
@ -1993,11 +1993,8 @@ impl WindowMethods<crate::DomTypeHolder> for Window {
|
|||
}
|
||||
|
||||
impl Window {
|
||||
pub(crate) fn scroll_offset(&self, can_gc: CanGc) -> Vector2D<f32, LayoutPixel> {
|
||||
self.scroll_offset_query_with_external_scroll_id(
|
||||
self.pipeline_id().root_scroll_id(),
|
||||
can_gc,
|
||||
)
|
||||
pub(crate) fn scroll_offset(&self) -> Vector2D<f32, LayoutPixel> {
|
||||
self.scroll_offset_query_with_external_scroll_id(self.pipeline_id().root_scroll_id())
|
||||
}
|
||||
|
||||
// https://heycam.github.io/webidl/#named-properties-object
|
||||
|
@ -2108,7 +2105,7 @@ impl Window {
|
|||
|
||||
// Step 7 & 8
|
||||
// TODO: Consider `block-end` and `inline-end` overflow direction.
|
||||
let scrolling_area = self.scrolling_area_query(None, can_gc);
|
||||
let scrolling_area = self.scrolling_area_query(None);
|
||||
let x = xfinite
|
||||
.min(scrolling_area.width() as f64 - viewport.width as f64)
|
||||
.max(0.0f64);
|
||||
|
@ -2118,7 +2115,7 @@ impl Window {
|
|||
|
||||
// Step 10
|
||||
//TODO handling ongoing smooth scrolling
|
||||
let scroll_offset = self.scroll_offset(can_gc);
|
||||
let scroll_offset = self.scroll_offset();
|
||||
if x == scroll_offset.x as f64 && y == scroll_offset.y as f64 {
|
||||
return;
|
||||
}
|
||||
|
@ -2134,7 +2131,6 @@ impl Window {
|
|||
self.pipeline_id().root_scroll_id(),
|
||||
behavior,
|
||||
None,
|
||||
can_gc,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2146,15 +2142,11 @@ impl Window {
|
|||
scroll_id: ExternalScrollId,
|
||||
_behavior: ScrollBehavior,
|
||||
_element: Option<&Element>,
|
||||
can_gc: CanGc,
|
||||
) {
|
||||
// TODO Step 1
|
||||
// TODO(mrobinson, #18709): Add smooth scrolling support to WebRender so that we can
|
||||
// properly process ScrollBehavior here.
|
||||
self.reflow(
|
||||
ReflowGoal::UpdateScrollNode(scroll_id, Vector2D::new(x, y)),
|
||||
can_gc,
|
||||
);
|
||||
self.reflow(ReflowGoal::UpdateScrollNode(scroll_id, Vector2D::new(x, y)));
|
||||
}
|
||||
|
||||
pub(crate) fn device_pixel_ratio(&self) -> Scale<f32, CSSPixel, DevicePixel> {
|
||||
|
@ -2278,37 +2270,15 @@ impl Window {
|
|||
/// NOTE: This method should almost never be called directly! Layout and rendering updates
|
||||
/// should happen as part of the HTML event loop via *update the rendering*. Currerntly, the
|
||||
/// only exceptions are script queries and scroll requests.
|
||||
pub(crate) fn reflow(&self, reflow_goal: ReflowGoal, can_gc: CanGc) -> bool {
|
||||
pub(crate) fn reflow(&self, reflow_goal: ReflowGoal) -> bool {
|
||||
// Never reflow inactive Documents.
|
||||
let document = self.Document();
|
||||
if !document.is_fully_active() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Count the pending web fonts before layout, in case a font loads during the layout.
|
||||
let waiting_for_web_fonts_to_load = self.font_context.web_fonts_still_loading() != 0;
|
||||
|
||||
document.ensure_safe_to_run_script_or_layout();
|
||||
|
||||
let issued_reflow = self.force_reflow(reflow_goal);
|
||||
|
||||
// From https://drafts.csswg.org/css-font-loading/#font-face-set-ready:
|
||||
// > A FontFaceSet is pending on the environment if any of the following are true:
|
||||
// > - the document is still loading
|
||||
// > - the document has pending stylesheet requests
|
||||
// > - the document has pending layout operations which might cause the user agent to request
|
||||
// > a font, or which depend on recently-loaded fonts
|
||||
//
|
||||
// Thus, we are queueing promise resolution here. This reflow should have been triggered by
|
||||
// a "rendering opportunity" in `ScriptThread::handle_web_font_loaded, which should also
|
||||
// make sure a microtask checkpoint happens, triggering the promise callback.
|
||||
let font_face_set = document.Fonts(can_gc);
|
||||
let is_ready_state_complete = document.ReadyState() == DocumentReadyState::Complete;
|
||||
if !waiting_for_web_fonts_to_load && is_ready_state_complete {
|
||||
font_face_set.fulfill_ready_promise_if_needed(can_gc);
|
||||
}
|
||||
|
||||
issued_reflow
|
||||
self.force_reflow(reflow_goal)
|
||||
}
|
||||
|
||||
pub(crate) fn maybe_send_idle_document_state_to_constellation(&self) {
|
||||
|
@ -2373,7 +2343,7 @@ impl Window {
|
|||
) {
|
||||
return;
|
||||
}
|
||||
self.allow_layout_if_necessary(can_gc);
|
||||
self.allow_layout_if_necessary();
|
||||
}
|
||||
|
||||
/// Block layout for this `Window` until parsing is done. If parsing takes a long time,
|
||||
|
@ -2392,7 +2362,7 @@ impl Window {
|
|||
|
||||
/// Inform the [`Window`] that layout is allowed either because `load` has happened
|
||||
/// or because parsing the `<body>` took so long that we cannot wait any longer.
|
||||
pub(crate) fn allow_layout_if_necessary(&self, can_gc: CanGc) {
|
||||
pub(crate) fn allow_layout_if_necessary(&self) {
|
||||
if matches!(
|
||||
self.layout_blocker.get(),
|
||||
LayoutBlocker::FiredLoadEventOrParsingTimerExpired
|
||||
|
@ -2414,7 +2384,7 @@ impl Window {
|
|||
// iframe size updates.
|
||||
//
|
||||
// See <https://github.com/servo/servo/issues/14719>
|
||||
self.Document().update_the_rendering(can_gc);
|
||||
self.Document().update_the_rendering();
|
||||
}
|
||||
|
||||
pub(crate) fn layout_blocked(&self) -> bool {
|
||||
|
@ -2439,17 +2409,16 @@ impl Window {
|
|||
let _ = receiver.recv();
|
||||
}
|
||||
|
||||
pub(crate) fn layout_reflow(&self, query_msg: QueryMsg, can_gc: CanGc) -> bool {
|
||||
self.reflow(ReflowGoal::LayoutQuery(query_msg), can_gc)
|
||||
pub(crate) fn layout_reflow(&self, query_msg: QueryMsg) -> bool {
|
||||
self.reflow(ReflowGoal::LayoutQuery(query_msg))
|
||||
}
|
||||
|
||||
pub(crate) fn resolved_font_style_query(
|
||||
&self,
|
||||
node: &Node,
|
||||
value: String,
|
||||
can_gc: CanGc,
|
||||
) -> Option<ServoArc<Font>> {
|
||||
self.layout_reflow(QueryMsg::ResolvedFontStyleQuery, can_gc);
|
||||
self.layout_reflow(QueryMsg::ResolvedFontStyleQuery);
|
||||
|
||||
let document = self.Document();
|
||||
let animations = document.animations().sets.clone();
|
||||
|
@ -2468,20 +2437,20 @@ impl Window {
|
|||
.query_content_box(node.to_trusted_node_address())
|
||||
}
|
||||
|
||||
pub(crate) fn content_box_query(&self, node: &Node, can_gc: CanGc) -> Option<UntypedRect<Au>> {
|
||||
self.layout_reflow(QueryMsg::ContentBox, can_gc);
|
||||
pub(crate) fn content_box_query(&self, node: &Node) -> Option<UntypedRect<Au>> {
|
||||
self.layout_reflow(QueryMsg::ContentBox);
|
||||
self.content_box_query_unchecked(node)
|
||||
}
|
||||
|
||||
pub(crate) fn content_boxes_query(&self, node: &Node, can_gc: CanGc) -> Vec<UntypedRect<Au>> {
|
||||
self.layout_reflow(QueryMsg::ContentBoxes, can_gc);
|
||||
pub(crate) fn content_boxes_query(&self, node: &Node) -> Vec<UntypedRect<Au>> {
|
||||
self.layout_reflow(QueryMsg::ContentBoxes);
|
||||
self.layout
|
||||
.borrow()
|
||||
.query_content_boxes(node.to_trusted_node_address())
|
||||
}
|
||||
|
||||
pub(crate) fn client_rect_query(&self, node: &Node, can_gc: CanGc) -> UntypedRect<i32> {
|
||||
self.layout_reflow(QueryMsg::ClientRectQuery, can_gc);
|
||||
pub(crate) fn client_rect_query(&self, node: &Node) -> UntypedRect<i32> {
|
||||
self.layout_reflow(QueryMsg::ClientRectQuery);
|
||||
self.layout
|
||||
.borrow()
|
||||
.query_client_rect(node.to_trusted_node_address())
|
||||
|
@ -2489,35 +2458,26 @@ impl Window {
|
|||
|
||||
/// Find the scroll area of the given node, if it is not None. If the node
|
||||
/// is None, find the scroll area of the viewport.
|
||||
pub(crate) fn scrolling_area_query(
|
||||
&self,
|
||||
node: Option<&Node>,
|
||||
can_gc: CanGc,
|
||||
) -> UntypedRect<i32> {
|
||||
self.layout_reflow(QueryMsg::ScrollingAreaOrOffsetQuery, can_gc);
|
||||
pub(crate) fn scrolling_area_query(&self, node: Option<&Node>) -> UntypedRect<i32> {
|
||||
self.layout_reflow(QueryMsg::ScrollingAreaOrOffsetQuery);
|
||||
self.layout
|
||||
.borrow()
|
||||
.query_scrolling_area(node.map(Node::to_trusted_node_address))
|
||||
}
|
||||
|
||||
pub(crate) fn scroll_offset_query(
|
||||
&self,
|
||||
node: &Node,
|
||||
can_gc: CanGc,
|
||||
) -> Vector2D<f32, LayoutPixel> {
|
||||
pub(crate) fn scroll_offset_query(&self, node: &Node) -> Vector2D<f32, LayoutPixel> {
|
||||
let external_scroll_id = ExternalScrollId(
|
||||
combine_id_with_fragment_type(node.to_opaque().id(), FragmentType::FragmentBody),
|
||||
self.pipeline_id().into(),
|
||||
);
|
||||
self.scroll_offset_query_with_external_scroll_id(external_scroll_id, can_gc)
|
||||
self.scroll_offset_query_with_external_scroll_id(external_scroll_id)
|
||||
}
|
||||
|
||||
fn scroll_offset_query_with_external_scroll_id(
|
||||
&self,
|
||||
external_scroll_id: ExternalScrollId,
|
||||
can_gc: CanGc,
|
||||
) -> Vector2D<f32, LayoutPixel> {
|
||||
self.layout_reflow(QueryMsg::ScrollingAreaOrOffsetQuery, can_gc);
|
||||
self.layout_reflow(QueryMsg::ScrollingAreaOrOffsetQuery);
|
||||
self.layout
|
||||
.borrow()
|
||||
.scroll_offset(external_scroll_id)
|
||||
|
@ -2525,14 +2485,7 @@ impl Window {
|
|||
}
|
||||
|
||||
// https://drafts.csswg.org/cssom-view/#element-scrolling-members
|
||||
pub(crate) fn scroll_node(
|
||||
&self,
|
||||
node: &Node,
|
||||
x_: f64,
|
||||
y_: f64,
|
||||
behavior: ScrollBehavior,
|
||||
can_gc: CanGc,
|
||||
) {
|
||||
pub(crate) fn scroll_node(&self, node: &Node, x_: f64, y_: f64, behavior: ScrollBehavior) {
|
||||
let scroll_id = ExternalScrollId(
|
||||
combine_id_with_fragment_type(node.to_opaque().id(), FragmentType::FragmentBody),
|
||||
self.pipeline_id().into(),
|
||||
|
@ -2545,7 +2498,6 @@ impl Window {
|
|||
scroll_id,
|
||||
behavior,
|
||||
None,
|
||||
can_gc,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2554,9 +2506,8 @@ impl Window {
|
|||
element: TrustedNodeAddress,
|
||||
pseudo: Option<PseudoElement>,
|
||||
property: PropertyId,
|
||||
can_gc: CanGc,
|
||||
) -> DOMString {
|
||||
self.layout_reflow(QueryMsg::ResolvedStyleQuery, can_gc);
|
||||
self.layout_reflow(QueryMsg::ResolvedStyleQuery);
|
||||
|
||||
let document = self.Document();
|
||||
let animations = document.animations().sets.clone();
|
||||
|
@ -2575,10 +2526,9 @@ impl Window {
|
|||
pub(crate) fn get_iframe_viewport_details_if_known(
|
||||
&self,
|
||||
browsing_context_id: BrowsingContextId,
|
||||
can_gc: CanGc,
|
||||
) -> Option<ViewportDetails> {
|
||||
// Reflow might fail, but do a best effort to return the right size.
|
||||
self.layout_reflow(QueryMsg::InnerWindowDimensionsQuery, can_gc);
|
||||
self.layout_reflow(QueryMsg::InnerWindowDimensionsQuery);
|
||||
self.Document()
|
||||
.iframes()
|
||||
.get(browsing_context_id)
|
||||
|
@ -2589,9 +2539,8 @@ impl Window {
|
|||
pub(crate) fn offset_parent_query(
|
||||
&self,
|
||||
node: &Node,
|
||||
can_gc: CanGc,
|
||||
) -> (Option<DomRoot<Element>>, UntypedRect<Au>) {
|
||||
self.layout_reflow(QueryMsg::OffsetParentQuery, can_gc);
|
||||
self.layout_reflow(QueryMsg::OffsetParentQuery);
|
||||
let response = self
|
||||
.layout
|
||||
.borrow()
|
||||
|
@ -2607,9 +2556,8 @@ impl Window {
|
|||
&self,
|
||||
node: &Node,
|
||||
point_in_node: UntypedPoint2D<f32>,
|
||||
can_gc: CanGc,
|
||||
) -> Option<usize> {
|
||||
self.layout_reflow(QueryMsg::TextIndexQuery, can_gc);
|
||||
self.layout_reflow(QueryMsg::TextIndexQuery);
|
||||
self.layout
|
||||
.borrow()
|
||||
.query_text_indext(node.to_opaque(), point_in_node)
|
||||
|
|
|
@ -1359,7 +1359,7 @@ impl ScriptThread {
|
|||
|
||||
// > Step 22: For each doc of docs, update the rendering or user interface of
|
||||
// > doc and its node navigable to reflect the current state.
|
||||
saw_any_reflows = document.update_the_rendering(can_gc) || saw_any_reflows;
|
||||
saw_any_reflows = document.update_the_rendering() || saw_any_reflows;
|
||||
|
||||
// TODO: Process top layer removals according to
|
||||
// https://drafts.csswg.org/css-position-4/#process-top-layer-removals.
|
||||
|
@ -1437,15 +1437,15 @@ impl ScriptThread {
|
|||
);
|
||||
}
|
||||
|
||||
fn maybe_send_idle_document_state_to_constellation(&self) {
|
||||
if !opts::get().wait_for_stable_image {
|
||||
return;
|
||||
}
|
||||
|
||||
fn maybe_send_document_state_messages(&self, can_gc: CanGc) {
|
||||
let waiting_for_stable_image = opts::get().wait_for_stable_image;
|
||||
for (_, document) in self.documents.borrow().iter() {
|
||||
document
|
||||
.window()
|
||||
.maybe_send_idle_document_state_to_constellation();
|
||||
if waiting_for_stable_image {
|
||||
document
|
||||
.window()
|
||||
.maybe_send_idle_document_state_to_constellation();
|
||||
}
|
||||
document.maybe_send_document_fonts_ready_message(can_gc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1659,7 +1659,7 @@ impl ScriptThread {
|
|||
}
|
||||
|
||||
self.maybe_schedule_rendering_opportunity_after_ipc_message(can_gc);
|
||||
self.maybe_send_idle_document_state_to_constellation();
|
||||
self.maybe_send_document_state_messages(can_gc);
|
||||
|
||||
true
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue