Skip to content

Commit 29c061e

Browse files
author
bors-servo
committed
Auto merge of #7423 - pcwalton:iframe-stacking-context-position, r=glennw
layout: Make the compositor rather than layout determine the position of 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 only the size of an iframe is determined during layout, and the position is determined by the compositor. Layout layerizes iframes and marks the iframe layers with the appropriate subpage ID so that the compositor can place them correctly. Closes #7377. <!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/7423) <!-- Reviewable:end -->
2 parents 4823ec9 + c72d0c2 commit 29c061e

20 files changed

+602
-389
lines changed

components/compositing/compositor.rs

Lines changed: 184 additions & 63 deletions
Large diffs are not rendered by default.

components/compositing/compositor_layer.rs

Lines changed: 123 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
44

55
use azure::azure_hl;
6-
use compositor::IOCompositor;
6+
use compositor::{IOCompositor, RemovedPipelineInfo};
77
use euclid::length::Length;
88
use euclid::point::{Point2D, TypedPoint2D};
99
use euclid::rect::Rect;
@@ -12,7 +12,7 @@ use layers::color::Color;
1212
use layers::geometry::LayerPixel;
1313
use layers::layers::{Layer, LayerBufferSet};
1414
use msg::compositor_msg::{Epoch, LayerId, LayerProperties, ScrollPolicy};
15-
use msg::constellation_msg::PipelineId;
15+
use msg::constellation_msg::{PipelineId, SubpageId};
1616
use script_traits::CompositorEvent::{ClickEvent, MouseDownEvent, MouseMoveEvent, MouseUpEvent};
1717
use script_traits::ConstellationControlMsg;
1818
use std::rc::Rc;
@@ -42,6 +42,9 @@ pub struct CompositorData {
4242
/// The scroll offset originating from this scrolling root. This allows scrolling roots
4343
/// to track their current scroll position even while their content_offset does not change.
4444
pub scroll_offset: TypedPoint2D<LayerPixel, f32>,
45+
46+
/// The pipeline ID and subpage ID of this layer, if it represents a subpage.
47+
pub subpage_info: Option<(PipelineId, SubpageId)>,
4548
}
4649

4750
impl CompositorData {
@@ -58,6 +61,9 @@ impl CompositorData {
5861
requested_epoch: Epoch(0),
5962
painted_epoch: Epoch(0),
6063
scroll_offset: Point2D::typed(0., 0.),
64+
subpage_info: layer_properties.subpage_layer_info.map(|subpage_layer_info| {
65+
(subpage_layer_info.pipeline_id, subpage_layer_info.subpage_id)
66+
}),
6167
};
6268

6369
Rc::new(Layer::new(Rect::from_untyped(&layer_properties.rect),
@@ -97,14 +103,6 @@ pub trait CompositorLayer {
97103
pipeline_id: PipelineId)
98104
where Window: WindowMethods;
99105

100-
/// Traverses the existing layer hierarchy and removes any layers that
101-
/// currently exist but which are no longer required.
102-
fn collect_old_layers<Window>(&self,
103-
compositor: &mut IOCompositor<Window>,
104-
pipeline_id: PipelineId,
105-
new_layers: &[LayerProperties])
106-
where Window: WindowMethods;
107-
108106
/// Destroys all tiles of all layers, including children, *without* sending them back to the
109107
/// painter. You must call this only when the paint task is destined to be going down;
110108
/// otherwise, you will leak tiles.
@@ -151,6 +149,17 @@ pub trait CompositorLayer {
151149
fn pipeline_id(&self) -> PipelineId;
152150
}
153151

152+
pub trait RcCompositorLayer {
153+
/// Traverses the existing layer hierarchy and removes any layers that
154+
/// currently exist but which are no longer required.
155+
fn collect_old_layers<Window>(&self,
156+
compositor: &mut IOCompositor<Window>,
157+
pipeline_id: PipelineId,
158+
new_layers: &[LayerProperties],
159+
pipelines_removed: &mut Vec<RemovedPipelineInfo>)
160+
where Window: WindowMethods;
161+
}
162+
154163
#[derive(Copy, PartialEq, Clone, Debug)]
155164
pub enum WantsScrollEventsFlag {
156165
WantsScrollEvents,
@@ -279,43 +288,6 @@ impl CompositorLayer for Layer<CompositorData> {
279288
}
280289
}
281290

282-
fn collect_old_layers<Window>(&self,
283-
compositor: &mut IOCompositor<Window>,
284-
pipeline_id: PipelineId,
285-
new_layers: &[LayerProperties])
286-
where Window: WindowMethods {
287-
// Traverse children first so that layers are removed
288-
// bottom up - allowing each layer being removed to properly
289-
// clean up any tiles it owns.
290-
for kid in &*self.children() {
291-
kid.collect_old_layers(compositor, pipeline_id, new_layers);
292-
}
293-
294-
// Retain child layers that also exist in the new layer list.
295-
self.children().retain(|child| {
296-
let extra_data = child.extra_data.borrow();
297-
298-
// Never remove root layers or layers from other pipelines.
299-
if pipeline_id != extra_data.pipeline_id ||
300-
extra_data.id == LayerId::null() {
301-
true
302-
} else {
303-
// Keep this layer if it exists in the new layer list.
304-
let keep_layer = new_layers.iter().any(|properties| {
305-
properties.id == extra_data.id
306-
});
307-
308-
// When removing a layer, clear any tiles and surfaces
309-
// associated with the layer.
310-
if !keep_layer {
311-
child.clear_all_tiles(compositor);
312-
}
313-
314-
keep_layer
315-
}
316-
});
317-
}
318-
319291
/// Destroys all tiles of all layers, including children, *without* sending them back to the
320292
/// painter. You must call this only when the paint task is destined to be going down;
321293
/// otherwise, you will leak tiles.
@@ -403,17 +375,23 @@ impl CompositorLayer for Layer<CompositorData> {
403375
MouseUpEvent(button, event_point),
404376
};
405377

406-
let pipeline = compositor.pipeline(self.pipeline_id());
407-
let _ = pipeline.script_chan.send(ConstellationControlMsg::SendEvent(pipeline.id.clone(), message));
378+
if let Some(pipeline) = compositor.pipeline(self.pipeline_id()) {
379+
pipeline.script_chan
380+
.send(ConstellationControlMsg::SendEvent(pipeline.id.clone(), message))
381+
.unwrap();
382+
}
408383
}
409384

410385
fn send_mouse_move_event<Window>(&self,
411386
compositor: &IOCompositor<Window>,
412387
cursor: TypedPoint2D<LayerPixel, f32>)
413388
where Window: WindowMethods {
414389
let message = MouseMoveEvent(cursor.to_untyped());
415-
let pipeline = compositor.pipeline(self.pipeline_id());
416-
let _ = pipeline.script_chan.send(ConstellationControlMsg::SendEvent(pipeline.id.clone(), message));
390+
if let Some(pipeline) = compositor.pipeline(self.pipeline_id()) {
391+
pipeline.script_chan
392+
.send(ConstellationControlMsg::SendEvent(pipeline.id.clone(), message))
393+
.unwrap();
394+
}
417395
}
418396

419397
fn scroll_layer_and_all_child_layers(&self, new_offset: TypedPoint2D<LayerPixel, f32>)
@@ -443,3 +421,97 @@ impl CompositorLayer for Layer<CompositorData> {
443421
self.extra_data.borrow().pipeline_id
444422
}
445423
}
424+
425+
impl RcCompositorLayer for Rc<Layer<CompositorData>> {
426+
fn collect_old_layers<Window>(&self,
427+
compositor: &mut IOCompositor<Window>,
428+
pipeline_id: PipelineId,
429+
new_layers: &[LayerProperties],
430+
pipelines_removed: &mut Vec<RemovedPipelineInfo>)
431+
where Window: WindowMethods {
432+
fn find_root_layer_for_pipeline(layer: &Rc<Layer<CompositorData>>, pipeline_id: PipelineId)
433+
-> Option<Rc<Layer<CompositorData>>> {
434+
let extra_data = layer.extra_data.borrow();
435+
if extra_data.pipeline_id == pipeline_id {
436+
return Some((*layer).clone())
437+
}
438+
439+
for kid in &*layer.children() {
440+
if let Some(layer) = find_root_layer_for_pipeline(kid, pipeline_id) {
441+
return Some(layer.clone())
442+
}
443+
}
444+
None
445+
}
446+
447+
fn collect_old_layers_for_pipeline<Window>(
448+
layer: &Layer<CompositorData>,
449+
compositor: &mut IOCompositor<Window>,
450+
pipeline_id: PipelineId,
451+
new_layers: &[LayerProperties],
452+
pipelines_removed: &mut Vec<RemovedPipelineInfo>)
453+
where Window: WindowMethods {
454+
// Traverse children first so that layers are removed
455+
// bottom up - allowing each layer being removed to properly
456+
// clean up any tiles it owns.
457+
for kid in &*layer.children() {
458+
collect_old_layers_for_pipeline(kid,
459+
compositor,
460+
pipeline_id,
461+
new_layers,
462+
pipelines_removed);
463+
}
464+
465+
// Retain child layers that also exist in the new layer list.
466+
layer.children().retain(|child| {
467+
let extra_data = child.extra_data.borrow();
468+
if pipeline_id == extra_data.pipeline_id {
469+
// Never remove our own root layer.
470+
if extra_data.id == LayerId::null() {
471+
return true
472+
}
473+
474+
// Keep this layer if it exists in the new layer list.
475+
return new_layers.iter().any(|properties| properties.id == extra_data.id);
476+
}
477+
478+
if let Some(ref subpage_info_for_this_layer) = extra_data.subpage_info {
479+
for layer_properties in new_layers.iter() {
480+
// Keep this layer if a reference to it exists.
481+
if let Some(ref subpage_layer_info) = layer_properties.subpage_layer_info {
482+
if subpage_layer_info.pipeline_id == subpage_info_for_this_layer.0 &&
483+
subpage_layer_info.subpage_id ==
484+
subpage_info_for_this_layer.1 {
485+
return true
486+
}
487+
}
488+
}
489+
490+
pipelines_removed.push(RemovedPipelineInfo {
491+
parent_pipeline_id: subpage_info_for_this_layer.0,
492+
parent_subpage_id: subpage_info_for_this_layer.1,
493+
child_pipeline_id: extra_data.pipeline_id,
494+
});
495+
}
496+
497+
// When removing a layer, clear any tiles and surfaces associated with the layer.
498+
child.clear_all_tiles(compositor);
499+
false
500+
});
501+
}
502+
503+
// First, find the root layer with the given pipeline ID.
504+
let root_layer = match find_root_layer_for_pipeline(self, pipeline_id) {
505+
Some(root_layer) => root_layer,
506+
None => return,
507+
};
508+
509+
// Then collect all old layers underneath that layer.
510+
collect_old_layers_for_pipeline(&root_layer,
511+
compositor,
512+
pipeline_id,
513+
new_layers,
514+
pipelines_removed);
515+
}
516+
}
517+

components/compositing/compositor_task.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@
55
//! Communication with the compositor task.
66
77
use compositor;
8-
use euclid::{Point2D, Rect, Size2D};
8+
use euclid::{Point2D, Size2D};
99
use headless;
1010
use ipc_channel::ipc::{IpcReceiver, IpcSender};
1111
use layers::layers::{BufferRequest, LayerBufferSet};
1212
use layers::platform::surface::{NativeDisplay, NativeSurface};
1313
use msg::compositor_msg::{Epoch, FrameTreeId, LayerId, LayerProperties};
1414
use msg::compositor_msg::{PaintListener, ScriptToCompositorMsg};
15-
use msg::constellation_msg::{AnimationState, ConstellationChan, PipelineId};
15+
use msg::constellation_msg::{AnimationState, ConstellationChan, PipelineId, SubpageId};
1616
use msg::constellation_msg::{Key, KeyModifiers, KeyState};
1717
use png;
1818
use profile_traits::mem;
@@ -64,7 +64,10 @@ pub fn run_script_listener_thread(compositor_proxy: Box<CompositorProxy + 'stati
6464
while let Ok(msg) = receiver.recv() {
6565
match msg {
6666
ScriptToCompositorMsg::ScrollFragmentPoint(pipeline_id, layer_id, point, _smooth) => {
67-
compositor_proxy.send(Msg::ScrollFragmentPoint(pipeline_id, layer_id, point, _smooth));
67+
compositor_proxy.send(Msg::ScrollFragmentPoint(pipeline_id,
68+
layer_id,
69+
point,
70+
_smooth));
6871
}
6972

7073
ScriptToCompositorMsg::GetClientWindow(send) => {
@@ -165,8 +168,6 @@ pub enum Msg {
165168
/// Tells the compositor to create or update the layers for a pipeline if necessary
166169
/// (i.e. if no layer with that ID exists).
167170
InitializeLayersForPipeline(PipelineId, Epoch, Vec<LayerProperties>),
168-
/// Alerts the compositor that the specified layer's rect has changed.
169-
SetLayerRect(PipelineId, LayerId, Rect<f32>),
170171
/// Scroll a page in a window
171172
ScrollFragmentPoint(PipelineId, LayerId, Point2D<f32>, bool),
172173
/// Requests that the compositor assign the painted buffers to the given layers.
@@ -216,6 +217,12 @@ pub enum Msg {
216217
MoveTo(Point2D<i32>),
217218
/// Resize the window to size
218219
ResizeTo(Size2D<u32>),
220+
/// A pipeline was shut down.
221+
PipelineExited(PipelineId),
222+
/// The layer for a subpage should be created. The first two IDs are the IDs of the *parent*
223+
/// pipeline and subpage, respectively, while the last ID is the pipeline ID of the subpage
224+
/// itself (or `None` if it has shut down).
225+
CreateLayerForSubpage(PipelineId, SubpageId, Option<PipelineId>),
219226
}
220227

221228
impl Debug for Msg {
@@ -225,7 +232,6 @@ impl Debug for Msg {
225232
Msg::ShutdownComplete(..) => write!(f, "ShutdownComplete"),
226233
Msg::GetNativeDisplay(..) => write!(f, "GetNativeDisplay"),
227234
Msg::InitializeLayersForPipeline(..) => write!(f, "InitializeLayersForPipeline"),
228-
Msg::SetLayerRect(..) => write!(f, "SetLayerRect"),
229235
Msg::ScrollFragmentPoint(..) => write!(f, "ScrollFragmentPoint"),
230236
Msg::AssignPaintedBuffers(..) => write!(f, "AssignPaintedBuffers"),
231237
Msg::ChangeRunningAnimationsState(..) => write!(f, "ChangeRunningAnimationsState"),
@@ -250,6 +256,8 @@ impl Debug for Msg {
250256
Msg::GetClientWindow(..) => write!(f, "GetClientWindow"),
251257
Msg::MoveTo(..) => write!(f, "MoveTo"),
252258
Msg::ResizeTo(..) => write!(f, "ResizeTo"),
259+
Msg::PipelineExited(..) => write!(f, "PipelineExited"),
260+
Msg::CreateLayerForSubpage(..) => write!(f, "CreateLayerForSubpage"),
253261
}
254262
}
255263
}

0 commit comments

Comments
 (0)