mirror of
https://github.com/servo/servo.git
synced 2025-06-14 19:34:29 +00:00
each iframe. The old code that attempted to do this during layout wasn't able to work for multiple reasons: it couldn't know where the iframe was going to be on the page (because of nested iframes), and at the time it was building the display list for a fragment it couldn't know where that fragment was going to be in page coordinates. This patch rewrites that code so that both the sizes and positions of iframes are determined by the compositor. Layout layerizes all iframes and marks the iframe layers with the appropriate pipeline and subpage IDs so that the compositor can place them correctly. This approach is similar in spirit to Gecko's `RefLayer` infrastructure. The logic that determines when it is time to take the screenshot for reftests has been significantly revamped to deal with this change in delegation of responsibility. Additionally, this code removes the infrastructure that sends layout data back to the layout task to be destroyed, since it is now all thread-safe and can be destroyed on the script task. The failing tests now fail because of a pre-existing bug related to intrinsic heights and borders on inline replaced elements. They happened to pass before because we never rendered the iframes at all, which meant they never had a chance to draw the red border the tests expect to not render! Closes #7377.
146 lines
5.2 KiB
Rust
146 lines
5.2 KiB
Rust
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* 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 compositor_task::{CompositorEventListener, CompositorReceiver};
|
|
use compositor_task::{InitialCompositorState, Msg};
|
|
use euclid::scale_factor::ScaleFactor;
|
|
use euclid::{Point2D, Size2D};
|
|
use msg::constellation_msg::AnimationState;
|
|
use msg::constellation_msg::Msg as ConstellationMsg;
|
|
use msg::constellation_msg::{ConstellationChan, WindowSizeData};
|
|
use profile_traits::mem;
|
|
use profile_traits::time;
|
|
use windowing::WindowEvent;
|
|
|
|
/// Starts the compositor, which listens for messages on the specified port.
|
|
///
|
|
/// This is the null compositor which doesn't draw anything to the screen.
|
|
/// It's intended for headless testing.
|
|
pub struct NullCompositor {
|
|
/// The port on which we receive messages.
|
|
pub port: Box<CompositorReceiver>,
|
|
/// A channel to the constellation.
|
|
constellation_chan: ConstellationChan,
|
|
/// A channel to the time profiler.
|
|
time_profiler_chan: time::ProfilerChan,
|
|
/// A channel to the memory profiler.
|
|
mem_profiler_chan: mem::ProfilerChan,
|
|
}
|
|
|
|
impl NullCompositor {
|
|
fn new(state: InitialCompositorState) -> NullCompositor {
|
|
NullCompositor {
|
|
port: state.receiver,
|
|
constellation_chan: state.constellation_chan,
|
|
time_profiler_chan: state.time_profiler_chan,
|
|
mem_profiler_chan: state.mem_profiler_chan,
|
|
}
|
|
}
|
|
|
|
pub fn create(state: InitialCompositorState) -> NullCompositor {
|
|
let compositor = NullCompositor::new(state);
|
|
|
|
// Tell the constellation about the initial fake size.
|
|
{
|
|
let ConstellationChan(ref chan) = compositor.constellation_chan;
|
|
chan.send(ConstellationMsg::ResizedWindow(WindowSizeData {
|
|
initial_viewport: Size2D::typed(640_f32, 480_f32),
|
|
visible_viewport: Size2D::typed(640_f32, 480_f32),
|
|
device_pixel_ratio: ScaleFactor::new(1.0),
|
|
})).unwrap();
|
|
}
|
|
|
|
compositor
|
|
}
|
|
}
|
|
|
|
impl CompositorEventListener for NullCompositor {
|
|
fn handle_events(&mut self, _: Vec<WindowEvent>) -> bool {
|
|
match self.port.recv_compositor_msg() {
|
|
Msg::Exit(chan) => {
|
|
debug!("shutting down the constellation");
|
|
let ConstellationChan(ref con_chan) = self.constellation_chan;
|
|
con_chan.send(ConstellationMsg::Exit).unwrap();
|
|
chan.send(()).unwrap();
|
|
}
|
|
|
|
Msg::ShutdownComplete => {
|
|
debug!("constellation completed shutdown");
|
|
return false
|
|
}
|
|
|
|
Msg::GetNativeDisplay(chan) => {
|
|
chan.send(None).unwrap();
|
|
}
|
|
|
|
Msg::SetFrameTree(_, response_chan, _) => {
|
|
response_chan.send(()).unwrap();
|
|
}
|
|
|
|
Msg::GetClientWindow(send) => {
|
|
let rect = (Size2D::zero(), Point2D::zero());
|
|
send.send(rect).unwrap();
|
|
}
|
|
|
|
Msg::ChangeRunningAnimationsState(pipeline_id, animation_state) => {
|
|
match animation_state {
|
|
AnimationState::AnimationsPresent |
|
|
AnimationState::NoAnimationsPresent |
|
|
AnimationState::NoAnimationCallbacksPresent => {}
|
|
AnimationState::AnimationCallbacksPresent => {
|
|
let msg = ConstellationMsg::TickAnimation(pipeline_id);
|
|
self.constellation_chan.0.send(msg).unwrap()
|
|
}
|
|
}
|
|
}
|
|
|
|
// Explicitly list ignored messages so that when we add a new one,
|
|
// we'll notice and think about whether it needs a response, like
|
|
// SetFrameTree.
|
|
|
|
Msg::InitializeLayersForPipeline(..) |
|
|
Msg::AssignPaintedBuffers(..) |
|
|
Msg::ScrollFragmentPoint(..) |
|
|
Msg::Status(..) |
|
|
Msg::LoadStart(..) |
|
|
Msg::LoadComplete(..) |
|
|
Msg::ScrollTimeout(..) |
|
|
Msg::RecompositeAfterScroll |
|
|
Msg::ChangePageTitle(..) |
|
|
Msg::ChangePageUrl(..) |
|
|
Msg::KeyEvent(..) |
|
|
Msg::SetCursor(..) |
|
|
Msg::ViewportConstrained(..) => {}
|
|
Msg::CreatePng(..) |
|
|
Msg::PaintTaskExited(..) |
|
|
Msg::MoveTo(..) |
|
|
Msg::ResizeTo(..) |
|
|
Msg::IsReadyToSaveImageReply(..) => {}
|
|
Msg::NewFavicon(..) => {}
|
|
Msg::HeadParsed => {}
|
|
Msg::ReturnUnusedNativeSurfaces(..) => {}
|
|
Msg::CollectMemoryReports(..) => {}
|
|
Msg::PipelineExited(..) => {}
|
|
Msg::CreateLayerForSubpage(..) => {}
|
|
}
|
|
true
|
|
}
|
|
|
|
fn repaint_synchronously(&mut self) {}
|
|
|
|
fn shutdown(&mut self) {
|
|
// Drain compositor port, sometimes messages contain channels that are blocking
|
|
// another task from finishing (i.e. SetIds)
|
|
while self.port.try_recv_compositor_msg().is_some() {}
|
|
|
|
self.time_profiler_chan.send(time::ProfilerMsg::Exit);
|
|
self.mem_profiler_chan.send(mem::ProfilerMsg::Exit);
|
|
}
|
|
|
|
fn pinch_zoom_level(&self) -> f32 {
|
|
1.0
|
|
}
|
|
|
|
fn title_for_main_frame(&self) {}
|
|
}
|