mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
layout: Add a hit test item that covers all scroll frame contents (#34347)
When building scroll frames, add a special `StackingContextContent::Fragment` type for a hit test that covers all scroll frame contents. This makes it so that you don't have to be hovering over actual content to scroll the scroll frame. Signed-off-by: Martin Robinson <mrobinson@igalia.com> Co-authored-by: Mukilan Thiyagarajan <mukilan@igalia.com>
This commit is contained in:
parent
c60e4afbee
commit
c11e0e8e70
3 changed files with 104 additions and 55 deletions
|
@ -33,7 +33,7 @@ use style::values::specified::text::TextDecorationLine;
|
|||
use style::values::specified::ui::CursorKind;
|
||||
use style::Zero;
|
||||
use style_traits::{CSSPixel, DevicePixel};
|
||||
use webrender_api::units::{LayoutPixel, LayoutSize};
|
||||
use webrender_api::units::{LayoutPixel, LayoutRect, LayoutSize};
|
||||
use webrender_api::{
|
||||
self as wr, units, BorderDetails, BoxShadowClipMode, ClipChainId, CommonItemProperties,
|
||||
ImageRendering, NinePatchBorder, NinePatchBorderSource,
|
||||
|
@ -250,14 +250,20 @@ impl Fragment {
|
|||
builder: &mut DisplayListBuilder,
|
||||
containing_block: &PhysicalRect<Au>,
|
||||
section: StackingContextSection,
|
||||
is_hit_test_for_scrollable_overflow: bool,
|
||||
) {
|
||||
match self {
|
||||
Fragment::Box(b) | Fragment::Float(b) => match b.style.get_inherited_box().visibility {
|
||||
Visibility::Visible => {
|
||||
BuilderForBoxFragment::new(b, containing_block).build(builder, section)
|
||||
},
|
||||
Visibility::Hidden => (),
|
||||
Visibility::Collapse => (),
|
||||
Fragment::Box(box_fragment) | Fragment::Float(box_fragment) => {
|
||||
match box_fragment.style.get_inherited_box().visibility {
|
||||
Visibility::Visible => BuilderForBoxFragment::new(
|
||||
box_fragment,
|
||||
containing_block,
|
||||
is_hit_test_for_scrollable_overflow,
|
||||
)
|
||||
.build(builder, section),
|
||||
Visibility::Hidden => (),
|
||||
Visibility::Collapse => (),
|
||||
}
|
||||
},
|
||||
Fragment::AbsoluteOrFixedPositioned(_) => {},
|
||||
Fragment::Positioning(positioning_fragment) => {
|
||||
|
@ -508,10 +514,15 @@ struct BuilderForBoxFragment<'a> {
|
|||
border_edge_clip_chain_id: RefCell<Option<ClipChainId>>,
|
||||
padding_edge_clip_chain_id: RefCell<Option<ClipChainId>>,
|
||||
content_edge_clip_chain_id: RefCell<Option<ClipChainId>>,
|
||||
is_hit_test_for_scrollable_overflow: bool,
|
||||
}
|
||||
|
||||
impl<'a> BuilderForBoxFragment<'a> {
|
||||
fn new(fragment: &'a BoxFragment, containing_block: &'a PhysicalRect<Au>) -> Self {
|
||||
fn new(
|
||||
fragment: &'a BoxFragment,
|
||||
containing_block: &'a PhysicalRect<Au>,
|
||||
is_hit_test_for_scrollable_overflow: bool,
|
||||
) -> Self {
|
||||
let border_rect = fragment
|
||||
.border_rect()
|
||||
.translate(containing_block.origin.to_vector());
|
||||
|
@ -550,6 +561,7 @@ impl<'a> BuilderForBoxFragment<'a> {
|
|||
border_edge_clip_chain_id: RefCell::new(None),
|
||||
padding_edge_clip_chain_id: RefCell::new(None),
|
||||
content_edge_clip_chain_id: RefCell::new(None),
|
||||
is_hit_test_for_scrollable_overflow,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -635,25 +647,31 @@ impl<'a> BuilderForBoxFragment<'a> {
|
|||
}
|
||||
|
||||
fn build(&mut self, builder: &mut DisplayListBuilder, section: StackingContextSection) {
|
||||
if self.is_hit_test_for_scrollable_overflow {
|
||||
self.build_hit_test(builder, self.fragment.scrollable_overflow().to_webrender());
|
||||
return;
|
||||
}
|
||||
|
||||
if section == StackingContextSection::Outline {
|
||||
self.build_outline(builder);
|
||||
} else {
|
||||
self.build_hit_test(builder);
|
||||
if self
|
||||
.fragment
|
||||
.base
|
||||
.flags
|
||||
.contains(FragmentFlags::DO_NOT_PAINT)
|
||||
{
|
||||
return;
|
||||
}
|
||||
self.build_background(builder);
|
||||
self.build_box_shadow(builder);
|
||||
self.build_border(builder);
|
||||
return;
|
||||
}
|
||||
|
||||
self.build_hit_test(builder, self.border_rect);
|
||||
if self
|
||||
.fragment
|
||||
.base
|
||||
.flags
|
||||
.contains(FragmentFlags::DO_NOT_PAINT)
|
||||
{
|
||||
return;
|
||||
}
|
||||
self.build_background(builder);
|
||||
self.build_box_shadow(builder);
|
||||
self.build_border(builder);
|
||||
}
|
||||
|
||||
fn build_hit_test(&self, builder: &mut DisplayListBuilder) {
|
||||
fn build_hit_test(&self, builder: &mut DisplayListBuilder, rect: LayoutRect) {
|
||||
let hit_info = builder.hit_info(
|
||||
&self.fragment.style,
|
||||
self.fragment.base.tag,
|
||||
|
@ -664,7 +682,7 @@ impl<'a> BuilderForBoxFragment<'a> {
|
|||
None => return,
|
||||
};
|
||||
|
||||
let mut common = builder.common_properties(self.border_rect, &self.fragment.style);
|
||||
let mut common = builder.common_properties(rect, &self.fragment.style);
|
||||
if let Some(clip_chain_id) = self.border_edge_clip(builder, false) {
|
||||
common.clip_chain_id = clip_chain_id;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue