Files
servo/components/script/layout_dom/shadow_root.rs
TIN TUN AUNG 6fda77da05 Media: Display User Agent Controls widget for video element. (#40578)
Add Contents::ReplacedWithWidget for video elements with UA control
widget, to allow Traverse into the children of video element during Box
Tree Construction, Generate
IndependentFormattingContextContent::ReplacedWithWidgets, to store both
the `ReplacedContents` and `BlockFormattingContext`. During fragment
tree generation process, first layout the Image Fragment, and then
Layout the Inner Controls BlockFormattingContext. Doing this allow us to
determine the size of Inner Controls widget based on the size of the
Image Fragment. Minor Fix: ::before/::after pseudo elment should be
suppress for replaced element.

Testing: Should show the controls widget for `<video controls></video>`,
and should not affect any existing WPT test. Since how to display UA
widget of Video Element is not defined in the spec, expectedly there has
no existing WPT test that testing this.
Fixes https://github.com/servo/servo/issues/40452
Fixes https://github.com/servo/servo/issues/31414

---------

Signed-off-by: rayguo17 <tin.tun.aung1@huawei.com>
2025-11-18 07:02:13 +00:00

72 lines
2.1 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 https://mozilla.org/MPL/2.0/. */
use std::fmt;
use style::dom::TShadowRoot;
use style::shared_lock::SharedRwLockReadGuard as StyleSharedRwLockReadGuard;
use style::stylist::{CascadeData, Stylist};
use crate::dom::bindings::root::LayoutDom;
use crate::dom::shadowroot::{LayoutShadowRootHelpers, ShadowRoot};
use crate::layout_dom::{ServoLayoutElement, ServoLayoutNode};
#[derive(Clone, Copy, PartialEq)]
pub struct ServoShadowRoot<'dom> {
/// The wrapped private DOM ShadowRoot.
shadow_root: LayoutDom<'dom, ShadowRoot>,
}
impl fmt::Debug for ServoShadowRoot<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.as_node().fmt(f)
}
}
impl<'dom> TShadowRoot for ServoShadowRoot<'dom> {
type ConcreteNode = ServoLayoutNode<'dom>;
fn as_node(&self) -> Self::ConcreteNode {
ServoLayoutNode::from_layout_js(self.shadow_root.upcast())
}
fn host(&self) -> ServoLayoutElement<'dom> {
ServoLayoutElement::from_layout_js(self.shadow_root.get_host_for_layout())
}
fn style_data<'a>(&self) -> Option<&'a CascadeData>
where
Self: 'a,
{
Some(self.shadow_root.get_style_data_for_layout())
}
}
impl<'dom> ServoShadowRoot<'dom> {
pub(super) fn from_layout_js(shadow_root: LayoutDom<'dom, ShadowRoot>) -> Self {
ServoShadowRoot { shadow_root }
}
/// Flush the stylesheets for the underlying shadow root.
///
/// # Safety
///
/// This modifies a DOM object, so should care should be taken that only one
/// thread has a reference to this object.
pub unsafe fn flush_stylesheets(
&self,
stylist: &mut Stylist,
guard: &StyleSharedRwLockReadGuard,
) {
unsafe {
self.shadow_root
.flush_stylesheets::<ServoLayoutElement>(stylist, guard)
}
}
pub fn is_ua_widget(&self) -> bool {
self.shadow_root.is_ua_widget()
}
}