@@ -192,12 +192,16 @@ pub struct StackingContextCollectionState {
192
192
/// recursively building and processing the display list.
193
193
pub current_stacking_context_id : StackingContextId ,
194
194
195
- /// The current stacking real context id, which doesn't include pseudo-stacking contexts .
195
+ /// The current reference frame ClipScrollNodeIndex .
196
196
pub current_real_stacking_context_id : StackingContextId ,
197
197
198
198
/// The next stacking context id that we will assign to a stacking context.
199
199
pub next_stacking_context_id : StackingContextId ,
200
200
201
+ /// The current reference frame id. This is used to assign items to the parent
202
+ /// reference frame when we encounter a fixed position stacking context.
203
+ pub current_parent_reference_frame_id : ClipScrollNodeIndex ,
204
+
201
205
/// The current clip and scroll info, used to keep track of state when
202
206
/// recursively building and processing the display list.
203
207
pub current_clipping_and_scrolling : ClippingAndScrolling ,
@@ -221,34 +225,31 @@ pub struct StackingContextCollectionState {
221
225
222
226
impl StackingContextCollectionState {
223
227
pub fn new ( pipeline_id : PipelineId ) -> StackingContextCollectionState {
224
- let root_clip_indices = ClippingAndScrolling :: simple ( ClipScrollNodeIndex ( 0 ) ) ;
225
-
226
- // This is just a dummy node to take up a slot in the array. WebRender
227
- // takes care of adding this root node and it can be ignored during DL conversion.
228
- let root_node = ClipScrollNode {
229
- parent_index : ClipScrollNodeIndex ( 0 ) ,
230
- clip : ClippingRegion :: from_rect ( LayoutRect :: zero ( ) ) ,
231
- content_rect : LayoutRect :: zero ( ) ,
232
- node_type : ClipScrollNodeType :: ScrollFrame (
233
- ScrollSensitivity :: ScriptAndInputEvents ,
234
- pipeline_id. root_scroll_id ( ) ,
235
- ) ,
236
- } ;
228
+ let root_clip_indices =
229
+ ClippingAndScrolling :: simple ( ClipScrollNodeIndex :: root_scroll_node ( ) ) ;
237
230
238
231
let mut stacking_context_info = FnvHashMap :: default ( ) ;
239
232
stacking_context_info. insert (
240
233
StackingContextId :: root ( ) ,
241
234
StackingContextInfo :: new ( StackingContextId :: root ( ) ) ,
242
235
) ;
243
236
237
+ // We add two empty nodes to represent the WebRender root reference frame and
238
+ // root scroll nodes. WebRender adds these automatically and we add them here
239
+ // so that the ids in the array match up with the ones we assign during display
240
+ // list building. We ignore these two nodes during conversion to WebRender
241
+ // display lists.
242
+ let clip_scroll_nodes = vec ! [ ClipScrollNode :: placeholder( ) , ClipScrollNode :: placeholder( ) ] ;
243
+
244
244
StackingContextCollectionState {
245
245
pipeline_id : pipeline_id,
246
246
root_stacking_context : StackingContext :: root ( ) ,
247
247
stacking_context_info,
248
- clip_scroll_nodes : vec ! [ root_node ] ,
248
+ clip_scroll_nodes,
249
249
current_stacking_context_id : StackingContextId :: root ( ) ,
250
250
current_real_stacking_context_id : StackingContextId :: root ( ) ,
251
251
next_stacking_context_id : StackingContextId :: root ( ) . next ( ) ,
252
+ current_parent_reference_frame_id : ClipScrollNodeIndex :: root_reference_frame ( ) ,
252
253
current_clipping_and_scrolling : root_clip_indices,
253
254
containing_block_clipping_and_scrolling : root_clip_indices,
254
255
clip_stack : Vec :: new ( ) ,
@@ -291,17 +292,27 @@ impl StackingContextCollectionState {
291
292
}
292
293
293
294
fn add_clip_scroll_node ( & mut self , clip_scroll_node : ClipScrollNode ) -> ClipScrollNodeIndex {
294
- // We want the scroll root to be defined before any possible item that could use it,
295
- // so we make sure that it is added to the beginning of the parent "real" (non-pseudo)
296
- // stacking context. This ensures that item reordering will not result in an item using
297
- // the scroll root before it is defined.
295
+ let is_placeholder = clip_scroll_node. is_placeholder ( ) ;
296
+
298
297
self . clip_scroll_nodes . push ( clip_scroll_node) ;
299
- let index = ClipScrollNodeIndex ( self . clip_scroll_nodes . len ( ) - 1 ) ;
300
- self . stacking_context_info
301
- . get_mut ( & self . current_real_stacking_context_id )
302
- . unwrap ( )
303
- . clip_scroll_nodes
304
- . push ( index) ;
298
+ let index = ClipScrollNodeIndex :: new ( self . clip_scroll_nodes . len ( ) - 1 ) ;
299
+
300
+ // If this node is a placeholder node (currently just reference frames), then don't add
301
+ // it to the stacking context list. Placeholder nodes are created automatically by
302
+ // WebRender and we don't want to explicitly create them in the display list. The node
303
+ // is just there to take up a spot in the global list of ClipScrollNodes.
304
+ if !is_placeholder {
305
+ // We want the scroll root to be defined before any possible item that could use it,
306
+ // so we make sure that it is added to the beginning of the parent "real" (non-pseudo)
307
+ // stacking context. This ensures that item reordering will not result in an item using
308
+ // the scroll root before it is defined.
309
+ self . stacking_context_info
310
+ . get_mut ( & self . current_real_stacking_context_id )
311
+ . unwrap ( )
312
+ . clip_scroll_nodes
313
+ . push ( index) ;
314
+ }
315
+
305
316
index
306
317
}
307
318
}
@@ -347,7 +358,6 @@ impl<'a> DisplayListBuildState<'a> {
347
358
layout_context : & ' a LayoutContext ,
348
359
state : StackingContextCollectionState ,
349
360
) -> DisplayListBuildState < ' a > {
350
- let root_clip_indices = ClippingAndScrolling :: simple ( ClipScrollNodeIndex ( 0 ) ) ;
351
361
DisplayListBuildState {
352
362
layout_context : layout_context,
353
363
root_stacking_context : state. root_stacking_context ,
@@ -356,7 +366,8 @@ impl<'a> DisplayListBuildState<'a> {
356
366
clip_scroll_nodes : state. clip_scroll_nodes ,
357
367
processing_scrolling_overflow_element : false ,
358
368
current_stacking_context_id : StackingContextId :: root ( ) ,
359
- current_clipping_and_scrolling : root_clip_indices,
369
+ current_clipping_and_scrolling :
370
+ ClippingAndScrolling :: simple ( ClipScrollNodeIndex :: root_scroll_node ( ) ) ,
360
371
iframe_sizes : Vec :: new ( ) ,
361
372
indexable_text : IndexableText :: default ( ) ,
362
373
}
@@ -374,7 +385,7 @@ impl<'a> DisplayListBuildState<'a> {
374
385
return index;
375
386
}
376
387
377
- self . clip_scroll_nodes [ index. 0 ] . parent_index
388
+ self . clip_scroll_nodes [ index. to_index ( ) ] . parent_index
378
389
}
379
390
380
391
fn is_background_or_border_of_clip_scroll_node ( & self , section : DisplayListSection ) -> bool {
@@ -429,7 +440,7 @@ impl<'a> DisplayListBuildState<'a> {
429
440
// stacking context. This ensures that item reordering will not result in an item using
430
441
// the scroll root before it is defined.
431
442
self . clip_scroll_nodes . push ( node) ;
432
- let index = ClipScrollNodeIndex ( self . clip_scroll_nodes . len ( ) - 1 ) ;
443
+ let index = ClipScrollNodeIndex :: new ( self . clip_scroll_nodes . len ( ) - 1 ) ;
433
444
let real_stacking_context_id =
434
445
self . stacking_context_info [ & self . current_stacking_context_id ] . real_stacking_context_id ;
435
446
self . stacking_context_info
@@ -751,6 +762,7 @@ pub trait FragmentDisplayListBuilding {
751
762
base_flow : & BaseFlow ,
752
763
scroll_policy : ScrollPolicy ,
753
764
context_type : StackingContextType ,
765
+ established_reference_frame : Option < ClipScrollNodeIndex > ,
754
766
parent_clipping_and_scrolling : ClippingAndScrolling ,
755
767
) -> StackingContext ;
756
768
@@ -1873,6 +1885,7 @@ impl FragmentDisplayListBuilding for Fragment {
1873
1885
base_flow : & BaseFlow ,
1874
1886
scroll_policy : ScrollPolicy ,
1875
1887
context_type : StackingContextType ,
1888
+ established_reference_frame : Option < ClipScrollNodeIndex > ,
1876
1889
parent_clipping_and_scrolling : ClippingAndScrolling ,
1877
1890
) -> StackingContext {
1878
1891
let border_box = self . stacking_relative_border_box (
@@ -1916,6 +1929,7 @@ impl FragmentDisplayListBuilding for Fragment {
1916
1929
self . perspective_matrix ( & border_box) ,
1917
1930
scroll_policy,
1918
1931
parent_clipping_and_scrolling,
1932
+ established_reference_frame,
1919
1933
)
1920
1934
}
1921
1935
@@ -2135,6 +2149,7 @@ pub trait BlockFlowDisplayListBuilding {
2135
2149
state : & mut StackingContextCollectionState ,
2136
2150
preserved_state : & mut SavedStackingContextCollectionState ,
2137
2151
stacking_context_type : Option < StackingContextType > ,
2152
+ established_reference_frame : Option < ClipScrollNodeIndex > ,
2138
2153
flags : StackingContextCollectionFlags ,
2139
2154
) -> ClippingAndScrolling ;
2140
2155
fn setup_clip_scroll_node_for_position (
@@ -2164,6 +2179,7 @@ pub trait BlockFlowDisplayListBuilding {
2164
2179
& mut self ,
2165
2180
parent_stacking_context_id : StackingContextId ,
2166
2181
parent_clipping_and_scrolling : ClippingAndScrolling ,
2182
+ established_reference_frame : Option < ClipScrollNodeIndex > ,
2167
2183
state : & mut StackingContextCollectionState ,
2168
2184
) ;
2169
2185
fn build_display_list_for_block (
@@ -2187,6 +2203,8 @@ pub trait BlockFlowDisplayListBuilding {
2187
2203
& self ,
2188
2204
flags : StackingContextCollectionFlags ,
2189
2205
) -> Option < StackingContextType > ;
2206
+
2207
+ fn is_reference_frame ( & self , context_type : Option < StackingContextType > ) -> bool ;
2190
2208
}
2191
2209
2192
2210
/// This structure manages ensuring that modification to StackingContextCollectionState is
@@ -2197,6 +2215,7 @@ pub trait BlockFlowDisplayListBuilding {
2197
2215
pub struct SavedStackingContextCollectionState {
2198
2216
stacking_context_id : StackingContextId ,
2199
2217
real_stacking_context_id : StackingContextId ,
2218
+ parent_reference_frame_id : ClipScrollNodeIndex ,
2200
2219
clipping_and_scrolling : ClippingAndScrolling ,
2201
2220
containing_block_clipping_and_scrolling : ClippingAndScrolling ,
2202
2221
clips_pushed : usize ,
@@ -2209,6 +2228,7 @@ impl SavedStackingContextCollectionState {
2209
2228
SavedStackingContextCollectionState {
2210
2229
stacking_context_id : state. current_stacking_context_id ,
2211
2230
real_stacking_context_id : state. current_real_stacking_context_id ,
2231
+ parent_reference_frame_id : state. current_parent_reference_frame_id ,
2212
2232
clipping_and_scrolling : state. current_clipping_and_scrolling ,
2213
2233
containing_block_clipping_and_scrolling : state. containing_block_clipping_and_scrolling ,
2214
2234
clips_pushed : 0 ,
@@ -2230,6 +2250,7 @@ impl SavedStackingContextCollectionState {
2230
2250
fn restore ( self , state : & mut StackingContextCollectionState ) {
2231
2251
state. current_stacking_context_id = self . stacking_context_id ;
2232
2252
state. current_real_stacking_context_id = self . real_stacking_context_id ;
2253
+ state. current_parent_reference_frame_id = self . parent_reference_frame_id ;
2233
2254
state. current_clipping_and_scrolling = self . clipping_and_scrolling ;
2234
2255
state. containing_block_clipping_and_scrolling =
2235
2256
self . containing_block_clipping_and_scrolling ;
@@ -2332,6 +2353,16 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
2332
2353
}
2333
2354
}
2334
2355
2356
+ /// Returns true if this fragment may establish a reference frame and this block
2357
+ /// creates a stacking context. Both are necessary in order to establish a reference
2358
+ /// frame.
2359
+ fn is_reference_frame ( & self , context_type : Option < StackingContextType > ) -> bool {
2360
+ match context_type {
2361
+ Some ( StackingContextType :: Real ) => self . fragment . can_establish_reference_frame ( ) ,
2362
+ _ => false ,
2363
+ }
2364
+ }
2365
+
2335
2366
fn collect_stacking_contexts_for_block (
2336
2367
& mut self ,
2337
2368
state : & mut StackingContextCollectionState ,
@@ -2348,8 +2379,17 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
2348
2379
2349
2380
if stacking_context_type == Some ( StackingContextType :: Real ) {
2350
2381
state. current_real_stacking_context_id = self . base . stacking_context_id ;
2382
+
2351
2383
}
2352
2384
2385
+ let established_reference_frame = if self . is_reference_frame ( stacking_context_type) {
2386
+ // WebRender currently creates reference frames automatically, so just add
2387
+ // a placeholder node to allocate a ClipScrollNodeIndex for this reference frame.
2388
+ Some ( state. add_clip_scroll_node ( ClipScrollNode :: placeholder ( ) ) )
2389
+ } else {
2390
+ None
2391
+ } ;
2392
+
2353
2393
// We are getting the id of the scroll root that contains us here, not the id of
2354
2394
// any scroll root that we create. If we create a scroll root, its index will be
2355
2395
// stored in state.current_clipping_and_scrolling. If we create a stacking context,
@@ -2358,6 +2398,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
2358
2398
state,
2359
2399
& mut preserved_state,
2360
2400
stacking_context_type,
2401
+ established_reference_frame,
2361
2402
flags,
2362
2403
) ;
2363
2404
@@ -2371,6 +2412,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
2371
2412
self . create_real_stacking_context_for_block (
2372
2413
preserved_state. stacking_context_id ,
2373
2414
containing_clipping_and_scrolling,
2415
+ established_reference_frame,
2374
2416
state,
2375
2417
) ;
2376
2418
} ,
@@ -2392,6 +2434,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
2392
2434
state : & mut StackingContextCollectionState ,
2393
2435
preserved_state : & mut SavedStackingContextCollectionState ,
2394
2436
stacking_context_type : Option < StackingContextType > ,
2437
+ established_reference_frame : Option < ClipScrollNodeIndex > ,
2395
2438
flags : StackingContextCollectionFlags ,
2396
2439
) -> ClippingAndScrolling {
2397
2440
// If this block is absolutely positioned, we should be clipped and positioned by
@@ -2404,13 +2447,23 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
2404
2447
state. containing_block_clipping_and_scrolling
2405
2448
} ,
2406
2449
StylePosition :: Fixed => {
2450
+ // If we are a fixed positioned stacking context, we want to be scrolled by
2451
+ // our reference frame instead of the clip scroll node that we are inside.
2407
2452
preserved_state. push_clip ( state, Rect :: max_rect ( ) , StylePosition :: Fixed ) ;
2453
+ state. current_clipping_and_scrolling . scrolling =
2454
+ state. current_parent_reference_frame_id ;
2408
2455
state. current_clipping_and_scrolling
2409
2456
} ,
2410
2457
_ => state. current_clipping_and_scrolling ,
2411
2458
} ;
2412
2459
self . base . clipping_and_scrolling = Some ( containing_clipping_and_scrolling) ;
2413
2460
2461
+ if let Some ( reference_frame_index) = established_reference_frame {
2462
+ let clipping_and_scrolling = ClippingAndScrolling :: simple ( reference_frame_index) ;
2463
+ state. current_clipping_and_scrolling = clipping_and_scrolling;
2464
+ self . base . clipping_and_scrolling = Some ( clipping_and_scrolling) ;
2465
+ }
2466
+
2414
2467
let stacking_relative_border_box = if self . fragment . establishes_stacking_context ( ) {
2415
2468
self . stacking_relative_border_box ( CoordinateSystem :: Own )
2416
2469
} else {
@@ -2658,6 +2711,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
2658
2711
& self . base ,
2659
2712
ScrollPolicy :: Scrollable ,
2660
2713
stacking_context_type,
2714
+ None ,
2661
2715
parent_clipping_and_scrolling,
2662
2716
) ;
2663
2717
state. add_stacking_context ( parent_stacking_context_id, new_context) ;
@@ -2683,19 +2737,15 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
2683
2737
& mut self ,
2684
2738
parent_stacking_context_id : StackingContextId ,
2685
2739
parent_clipping_and_scrolling : ClippingAndScrolling ,
2740
+ established_reference_frame : Option < ClipScrollNodeIndex > ,
2686
2741
state : & mut StackingContextCollectionState ,
2687
2742
) {
2688
- let scroll_policy = if self . is_fixed ( ) {
2689
- ScrollPolicy :: Fixed
2690
- } else {
2691
- ScrollPolicy :: Scrollable
2692
- } ;
2693
-
2694
2743
let stacking_context = self . fragment . create_stacking_context (
2695
2744
self . base . stacking_context_id ,
2696
2745
& self . base ,
2697
- scroll_policy ,
2746
+ ScrollPolicy :: Scrollable ,
2698
2747
StackingContextType :: Real ,
2748
+ established_reference_frame,
2699
2749
parent_clipping_and_scrolling,
2700
2750
) ;
2701
2751
@@ -2833,6 +2883,7 @@ impl InlineFlowDisplayListBuilding for InlineFlow {
2833
2883
& self . base ,
2834
2884
ScrollPolicy :: Scrollable ,
2835
2885
StackingContextType :: Real ,
2886
+ None ,
2836
2887
state. current_clipping_and_scrolling ,
2837
2888
) ;
2838
2889
0 commit comments