mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
script: Unify script-based "update the rendering" and throttle it to 60 FPS (#38431)
Instead of running "update the rendering" at every IPC message, only run it when a timeout has occured in script. In addition, avoid updating the rendering if a rendering update isn't necessary. This should greatly reduce the amount of processing that has to happen in script. Because we are running many fewer calls to "update the rendering" it is reasonable now to ensure that these always work the same way. In particular, we always run rAF and update the animation timeline when updating the ernder In addition, pull the following things out of reflow: - Code dealing with informing the Constellation that a Pipeline has become Idle when waiting for a screenshot. - Detecting when it is time to fulfill the `document.fonts.ready` promise. The latter means that reflow can never cause a garbage collection, making timing of reflows more consistent and simplifying many callsites that need to do script queries. Followup changes will seek to simplify the way that ScriptThread-driven animation timeouts happen even simpler. Testing: In general, this should not change testable behavior so much, though it does seem to fix one test. The main improvement here should be that the ScriptThread does less work. Signed-off-by: Martin Robinson <mrobinson@igalia.com> Co-authored-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
parent
bcc8314dd5
commit
9416251cab
39 changed files with 607 additions and 672 deletions
|
@ -1634,7 +1634,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
|
||||
|
@ -1644,7 +1644,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
|
||||
|
@ -1653,47 +1653,47 @@ impl WindowMethods<crate::DomTypeHolder> for Window {
|
|||
}
|
||||
|
||||
// https://drafts.csswg.org/cssom-view/#dom-window-scroll
|
||||
fn Scroll(&self, options: &ScrollToOptions, can_gc: CanGc) {
|
||||
fn Scroll(&self, options: &ScrollToOptions) {
|
||||
// Step 1
|
||||
let left = options.left.unwrap_or(0.0f64);
|
||||
let top = options.top.unwrap_or(0.0f64);
|
||||
self.scroll(left, top, options.parent.behavior, can_gc);
|
||||
self.scroll(left, top, options.parent.behavior);
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/cssom-view/#dom-window-scroll
|
||||
fn Scroll_(&self, x: f64, y: f64, can_gc: CanGc) {
|
||||
self.scroll(x, y, ScrollBehavior::Auto, can_gc);
|
||||
fn Scroll_(&self, x: f64, y: f64) {
|
||||
self.scroll(x, y, ScrollBehavior::Auto);
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/cssom-view/#dom-window-scrollto
|
||||
fn ScrollTo(&self, options: &ScrollToOptions) {
|
||||
self.Scroll(options, CanGc::note());
|
||||
self.Scroll(options);
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/cssom-view/#dom-window-scrollto
|
||||
fn ScrollTo_(&self, x: f64, y: f64) {
|
||||
self.scroll(x, y, ScrollBehavior::Auto, CanGc::note());
|
||||
self.scroll(x, y, ScrollBehavior::Auto);
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/cssom-view/#dom-window-scrollby
|
||||
fn ScrollBy(&self, options: &ScrollToOptions, can_gc: CanGc) {
|
||||
fn ScrollBy(&self, options: &ScrollToOptions) {
|
||||
// Step 1
|
||||
let x = options.left.unwrap_or(0.0f64);
|
||||
let y = options.top.unwrap_or(0.0f64);
|
||||
self.ScrollBy_(x, y, can_gc);
|
||||
self.scroll(x, y, options.parent.behavior, can_gc);
|
||||
self.ScrollBy_(x, y);
|
||||
self.scroll(x, y, options.parent.behavior);
|
||||
}
|
||||
|
||||
// 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);
|
||||
fn ScrollBy_(&self, x: f64, y: f64) {
|
||||
let scroll_offset = self.scroll_offset();
|
||||
// Step 3
|
||||
let left = x + scroll_offset.x as f64;
|
||||
// Step 4
|
||||
let top = y + scroll_offset.y as f64;
|
||||
|
||||
// Step 5
|
||||
self.scroll(left, top, ScrollBehavior::Auto, can_gc);
|
||||
self.scroll(left, top, ScrollBehavior::Auto);
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/cssom-view/#dom-window-resizeto
|
||||
|
@ -2012,11 +2012,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
|
||||
|
@ -2114,7 +2111,7 @@ impl Window {
|
|||
}
|
||||
|
||||
/// <https://drafts.csswg.org/cssom-view/#dom-window-scroll>
|
||||
pub(crate) fn scroll(&self, x_: f64, y_: f64, behavior: ScrollBehavior, can_gc: CanGc) {
|
||||
pub(crate) fn scroll(&self, x_: f64, y_: f64, behavior: ScrollBehavior) {
|
||||
// Step 3
|
||||
let xfinite = if x_.is_finite() { x_ } else { 0.0f64 };
|
||||
let yfinite = if y_.is_finite() { y_ } else { 0.0f64 };
|
||||
|
@ -2127,7 +2124,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);
|
||||
|
@ -2137,7 +2134,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;
|
||||
}
|
||||
|
@ -2153,7 +2150,6 @@ impl Window {
|
|||
self.pipeline_id().root_scroll_id(),
|
||||
behavior,
|
||||
None,
|
||||
can_gc,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2165,7 +2161,6 @@ 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
|
||||
|
@ -2173,10 +2168,7 @@ impl Window {
|
|||
let WindowReflowResult {
|
||||
update_scroll_reflow_target_scrolled,
|
||||
..
|
||||
} = self.reflow(
|
||||
ReflowGoal::UpdateScrollNode(scroll_id, Vector2D::new(x, y)),
|
||||
can_gc,
|
||||
);
|
||||
} = self.reflow(ReflowGoal::UpdateScrollNode(scroll_id, Vector2D::new(x, y)));
|
||||
|
||||
// > If the scroll position did not change as a result of the user interaction or programmatic
|
||||
// > invocation, where no translations were applied as a result, then no scrollend event fires
|
||||
|
@ -2218,9 +2210,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*.
|
||||
fn force_reflow(&self, reflow_goal: ReflowGoal) -> WindowReflowResult {
|
||||
pub(crate) fn reflow(&self, reflow_goal: ReflowGoal) -> WindowReflowResult {
|
||||
let document = self.Document();
|
||||
document.ensure_safe_to_run_script_or_layout();
|
||||
|
||||
// Never reflow inactive Documents.
|
||||
if !document.is_fully_active() {
|
||||
return WindowReflowResult::new_empty();
|
||||
}
|
||||
|
||||
self.Document().ensure_safe_to_run_script_or_layout();
|
||||
|
||||
// If layouts are blocked, we block all layouts that are for display only. Other
|
||||
// layouts (for queries and scrolling) are not blocked, as they do not display
|
||||
|
@ -2314,88 +2312,60 @@ impl Window {
|
|||
}
|
||||
}
|
||||
|
||||
/// Reflows the page if it's possible to do so and the page is dirty. Returns true if layout
|
||||
/// actually happened and produced a new display list, false otherwise.
|
||||
///
|
||||
/// 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) -> WindowReflowResult {
|
||||
// Never reflow inactive Documents.
|
||||
if !self.Document().is_fully_active() {
|
||||
return WindowReflowResult::new_empty();
|
||||
pub(crate) fn maybe_send_idle_document_state_to_constellation(&self) {
|
||||
if !opts::get().wait_for_stable_image {
|
||||
return;
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
self.Document().ensure_safe_to_run_script_or_layout();
|
||||
|
||||
let updating_the_rendering = reflow_goal == ReflowGoal::UpdateTheRendering;
|
||||
let reflow_result = self.force_reflow(reflow_goal);
|
||||
if self.has_sent_idle_message.get() {
|
||||
return;
|
||||
}
|
||||
|
||||
let document = self.Document();
|
||||
let font_face_set = document.Fonts(can_gc);
|
||||
let is_ready_state_complete = document.ReadyState() == DocumentReadyState::Complete;
|
||||
|
||||
// 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.
|
||||
if !waiting_for_web_fonts_to_load && is_ready_state_complete {
|
||||
font_face_set.fulfill_ready_promise_if_needed(can_gc);
|
||||
if document.ReadyState() != DocumentReadyState::Complete {
|
||||
return;
|
||||
}
|
||||
|
||||
// Checks if the html element has reftest-wait attribute present.
|
||||
// See http://testthewebforward.org/docs/reftests.html
|
||||
// and https://web-platform-tests.org/writing-tests/crashtest.html
|
||||
if document.GetDocumentElement().is_some_and(|elem| {
|
||||
elem.has_class(&atom!("reftest-wait"), CaseSensitivity::CaseSensitive) ||
|
||||
elem.has_class(&Atom::from("test-wait"), CaseSensitivity::CaseSensitive)
|
||||
}) {
|
||||
return;
|
||||
}
|
||||
|
||||
if self.font_context.web_fonts_still_loading() != 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
if !self.pending_layout_images.borrow().is_empty() ||
|
||||
!self.pending_images_for_rasterization.borrow().is_empty()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if self.Document().needs_rendering_update() {
|
||||
return;
|
||||
}
|
||||
|
||||
// If writing a screenshot, check if the script has reached a state
|
||||
// where it's safe to write the image. This means that:
|
||||
// 1) The reflow is for display (otherwise it could be a query)
|
||||
// 2) The html element doesn't contain the 'reftest-wait' class
|
||||
// 3) The load event has fired.
|
||||
// When all these conditions are met, notify the constellation
|
||||
// that this pipeline is ready to write the image (from the script thread
|
||||
// perspective at least).
|
||||
if opts::get().wait_for_stable_image && updating_the_rendering {
|
||||
// Checks if the html element has reftest-wait attribute present.
|
||||
// See http://testthewebforward.org/docs/reftests.html
|
||||
// and https://web-platform-tests.org/writing-tests/crashtest.html
|
||||
let html_element = document.GetDocumentElement();
|
||||
let reftest_wait = html_element.is_some_and(|elem| {
|
||||
elem.has_class(&atom!("reftest-wait"), CaseSensitivity::CaseSensitive) ||
|
||||
elem.has_class(&Atom::from("test-wait"), CaseSensitivity::CaseSensitive)
|
||||
});
|
||||
|
||||
let has_sent_idle_message = self.has_sent_idle_message.get();
|
||||
let no_pending_images = self.pending_layout_images.borrow().is_empty() &&
|
||||
self.pending_images_for_rasterization.borrow().is_empty();
|
||||
|
||||
if !has_sent_idle_message &&
|
||||
is_ready_state_complete &&
|
||||
!reftest_wait &&
|
||||
no_pending_images &&
|
||||
!waiting_for_web_fonts_to_load
|
||||
{
|
||||
debug!(
|
||||
"{:?}: Sending DocumentState::Idle to Constellation",
|
||||
self.pipeline_id()
|
||||
);
|
||||
let event = ScriptToConstellationMessage::SetDocumentState(DocumentState::Idle);
|
||||
self.send_to_constellation(event);
|
||||
self.has_sent_idle_message.set(true);
|
||||
}
|
||||
}
|
||||
|
||||
reflow_result
|
||||
debug!(
|
||||
"{:?}: Sending DocumentState::Idle to Constellation",
|
||||
self.pipeline_id()
|
||||
);
|
||||
self.send_to_constellation(ScriptToConstellationMessage::SetDocumentState(
|
||||
DocumentState::Idle,
|
||||
));
|
||||
self.has_sent_idle_message.set(true);
|
||||
}
|
||||
|
||||
/// If parsing has taken a long time and reflows are still waiting for the `load` event,
|
||||
/// start allowing them. See <https://github.com/servo/servo/pull/6028>.
|
||||
pub(crate) fn reflow_if_reflow_timer_expired(&self, can_gc: CanGc) {
|
||||
pub(crate) fn reflow_if_reflow_timer_expired(&self) {
|
||||
// Only trigger a long parsing time reflow if we are in the first parse of `<body>`
|
||||
// and it started more than `INITIAL_REFLOW_DELAY` ago.
|
||||
if !matches!(
|
||||
|
@ -2404,7 +2374,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,
|
||||
|
@ -2423,7 +2393,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
|
||||
|
@ -2445,7 +2415,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 {
|
||||
|
@ -2471,17 +2441,16 @@ impl Window {
|
|||
}
|
||||
|
||||
/// Trigger a reflow that is required by a certain queries.
|
||||
pub(crate) fn layout_reflow(&self, query_msg: QueryMsg, can_gc: CanGc) {
|
||||
self.reflow(ReflowGoal::LayoutQuery(query_msg), can_gc);
|
||||
pub(crate) fn layout_reflow(&self, query_msg: QueryMsg) {
|
||||
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();
|
||||
|
@ -2500,20 +2469,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())
|
||||
|
@ -2521,35 +2490,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.scroll_offset_query_with_external_scroll_id_no_reflow(external_scroll_id)
|
||||
}
|
||||
|
||||
|
@ -2571,7 +2531,6 @@ impl Window {
|
|||
x_: f64,
|
||||
y_: f64,
|
||||
behavior: ScrollBehavior,
|
||||
can_gc: CanGc,
|
||||
) {
|
||||
let scroll_id = ExternalScrollId(
|
||||
combine_id_with_fragment_type(
|
||||
|
@ -2590,7 +2549,6 @@ impl Window {
|
|||
scroll_id,
|
||||
behavior,
|
||||
Some(element),
|
||||
can_gc,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2599,9 +2557,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();
|
||||
|
@ -2620,10 +2577,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)
|
||||
|
@ -2634,9 +2590,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()
|
||||
|
@ -2652,9 +2607,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)
|
||||
|
@ -2710,7 +2664,7 @@ impl Window {
|
|||
load_data.url.clone(),
|
||||
history_handling,
|
||||
));
|
||||
doc.check_and_scroll_fragment(fragment, can_gc);
|
||||
doc.check_and_scroll_fragment(fragment);
|
||||
let this = Trusted::new(self);
|
||||
let old_url = doc.url().into_string();
|
||||
let new_url = load_data.url.clone().into_string();
|
||||
|
@ -2832,6 +2786,11 @@ impl Window {
|
|||
self.unhandled_resize_event.borrow_mut().take()
|
||||
}
|
||||
|
||||
/// Whether or not this [`Window`] has any resize events that have not been processed.
|
||||
pub(crate) fn has_unhandled_resize_event(&self) -> bool {
|
||||
self.unhandled_resize_event.borrow().is_some()
|
||||
}
|
||||
|
||||
pub(crate) fn set_viewport_size(&self, new_viewport_size: UntypedSize2D<f32>) {
|
||||
let new_viewport_size = Size2D::new(
|
||||
Au::from_f32_px(new_viewport_size.width),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue