Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Details ui #9586

Merged
merged 1 commit into from Mar 20, 2016
Merged

Details ui #9586

Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

@@ -676,7 +676,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
HTMLElementTypeId::HTMLInputElement))) ||
node.type_id() == Some(NodeTypeId::Element(ElementTypeId::HTMLElement(
HTMLElementTypeId::HTMLTextAreaElement)));
if node.get_pseudo_element_type() != PseudoElementType::Normal ||
if node.get_pseudo_element_type().is_before_or_after() ||
node_is_input_or_text_area {
// A TextArea's text contents are displayed through the input text
// box, so don't construct them.
@@ -1461,6 +1461,8 @@ impl<'a, ConcreteThreadSafeLayoutNode> PostorderNodeMutTraversal<ConcreteThreadS
PseudoElementType::Normal => display::T::inline,
PseudoElementType::Before(display) => display,
PseudoElementType::After(display) => display,
PseudoElementType::DetailsContent(display) => display,
PseudoElementType::DetailsSummary(display) => display,
};
(display, style.get_box().float, style.get_box().position)
}
@@ -1646,6 +1648,8 @@ impl<ConcreteThreadSafeLayoutNode> NodeUtils for ConcreteThreadSafeLayoutNode
match self.get_pseudo_element_type() {
PseudoElementType::Before(_) => &mut data.before_flow_construction_result,
PseudoElementType::After (_) => &mut data.after_flow_construction_result,
PseudoElementType::DetailsSummary(_) => &mut data.details_summary_flow_construction_result,
PseudoElementType::DetailsContent(_) => &mut data.details_content_flow_construction_result,
PseudoElementType::Normal => &mut data.flow_construction_result,
}
}
@@ -25,6 +25,10 @@ pub struct PrivateLayoutData {

pub after_flow_construction_result: ConstructionResult,

pub details_summary_flow_construction_result: ConstructionResult,

pub details_content_flow_construction_result: ConstructionResult,

/// Various flags.
pub flags: LayoutDataFlags,
}
@@ -38,6 +42,8 @@ impl PrivateLayoutData {
flow_construction_result: ConstructionResult::None,
before_flow_construction_result: ConstructionResult::None,
after_flow_construction_result: ConstructionResult::None,
details_summary_flow_construction_result: ConstructionResult::None,
details_content_flow_construction_result: ConstructionResult::None,
flags: LayoutDataFlags::empty(),
}
}
@@ -2445,15 +2445,19 @@ impl Fragment {
match self.pseudo {
PseudoElementType::Normal => FragmentType::FragmentBody,
PseudoElementType::Before(_) => FragmentType::BeforePseudoContent,
PseudoElementType::After(_) => FragmentType::AfterPseudoContent
PseudoElementType::After(_) => FragmentType::AfterPseudoContent,
PseudoElementType::DetailsSummary(_) => FragmentType::FragmentBody,
PseudoElementType::DetailsContent(_) => FragmentType::FragmentBody,
}
}

pub fn layer_id(&self) -> LayerId {
let layer_type = match self.pseudo {
PseudoElementType::Normal => LayerType::FragmentBody,
PseudoElementType::Before(_) => LayerType::BeforePseudoContent,
PseudoElementType::After(_) => LayerType::AfterPseudoContent
PseudoElementType::After(_) => LayerType::AfterPseudoContent,
PseudoElementType::DetailsSummary(_) => LayerType::FragmentBody,
PseudoElementType::DetailsContent(_) => LayerType::FragmentBody,
};
LayerId::new_of_type(layer_type, self.node.id() as usize)
}
@@ -536,6 +536,8 @@ pub fn process_resolved_style_request<N: LayoutNode>(
let layout_node = match pseudo {
&Some(PseudoElement::Before) => layout_node.get_before_pseudo(),
&Some(PseudoElement::After) => layout_node.get_after_pseudo(),
&Some(PseudoElement::DetailsSummary) => layout_node.get_details_summary_pseudo(),
&Some(PseudoElement::DetailsContent) => layout_node.get_details_content_pseudo(),
_ => Some(layout_node)
};

@@ -615,6 +615,8 @@ pub enum PseudoElementType<T> {
Normal,
Before(T),
After(T),
DetailsSummary(T),
DetailsContent(T),
}

impl<T> PseudoElementType<T> {
@@ -625,19 +627,28 @@ impl<T> PseudoElementType<T> {
}
}

pub fn is_before_or_after(&self) -> bool {
match *self {
PseudoElementType::Before(_) | PseudoElementType::After(_) => true,
_ => false,
}
}

pub fn strip(&self) -> PseudoElementType<()> {
match *self {
PseudoElementType::Normal => PseudoElementType::Normal,
PseudoElementType::Before(_) => PseudoElementType::Before(()),
PseudoElementType::After(_) => PseudoElementType::After(()),
PseudoElementType::DetailsSummary(_) => PseudoElementType::DetailsSummary(()),
PseudoElementType::DetailsContent(_) => PseudoElementType::DetailsContent(()),
}
}
}

/// A thread-safe version of `LayoutNode`, used during flow construction. This type of layout
/// node does not allow any parents or siblings of nodes to be accessed, to avoid races.

pub trait ThreadSafeLayoutNode : Clone + Copy + Sized {
pub trait ThreadSafeLayoutNode : Clone + Copy + Sized + PartialEq {
type ConcreteThreadSafeLayoutElement: ThreadSafeLayoutElement<ConcreteThreadSafeLayoutNode = Self>;
type ChildrenIterator: Iterator<Item = Self> + Sized;

@@ -659,6 +670,9 @@ pub trait ThreadSafeLayoutNode : Clone + Copy + Sized {
/// Returns an iterator over this node's children.
fn children(&self) -> Self::ChildrenIterator;

#[inline]
fn is_element(&self) -> bool { if let Some(NodeTypeId::Element(_)) = self.type_id() { true } else { false } }

/// If this is an element, accesses the element data. Fails if this is not an element node.
#[inline]
fn as_element(&self) -> Self::ConcreteThreadSafeLayoutElement;
@@ -686,6 +700,38 @@ pub trait ThreadSafeLayoutNode : Clone + Copy + Sized {
})
}

#[inline]
fn get_details_summary_pseudo(&self) -> Option<Self> {
if self.is_element() &&
self.as_element().get_local_name() == &atom!("details") &&
self.as_element().get_namespace() == &ns!(html) {
self.borrow_layout_data().unwrap()
.style_data.per_pseudo
.get(&PseudoElement::DetailsSummary)
.map(|style| {
self.with_pseudo(PseudoElementType::DetailsSummary(style.get_box().display))
})
} else {
None
}
}

#[inline]
fn get_details_content_pseudo(&self) -> Option<Self> {
if self.is_element() &&
self.as_element().get_local_name() == &atom!("details") &&
self.as_element().get_namespace() == &ns!(html) {
self.borrow_layout_data().unwrap()
.style_data.per_pseudo
.get(&PseudoElement::DetailsContent)
.map(|style| {
self.with_pseudo(PseudoElementType::DetailsContent(style.get_box().display))
})
} else {
None
}
}

/// Borrows the layout data immutably. Fails on a conflicting borrow.
///
/// TODO(pcwalton): Make this private. It will let us avoid borrow flag checks in some cases.
@@ -708,6 +754,8 @@ pub trait ThreadSafeLayoutNode : Clone + Copy + Sized {
let style = match self.get_pseudo_element_type() {
PseudoElementType::Before(_) => data.style_data.per_pseudo.get(&PseudoElement::Before),
PseudoElementType::After(_) => data.style_data.per_pseudo.get(&PseudoElement::After),
PseudoElementType::DetailsSummary(_) => data.style_data.per_pseudo.get(&PseudoElement::DetailsSummary),
PseudoElementType::DetailsContent(_) => data.style_data.per_pseudo.get(&PseudoElement::DetailsContent),
PseudoElementType::Normal => data.style_data.style.as_ref(),
};
style.unwrap()
@@ -727,6 +775,13 @@ pub trait ThreadSafeLayoutNode : Clone + Copy + Sized {
PseudoElementType::After(_) => {
data.style_data.per_pseudo.remove(&PseudoElement::After);
}
PseudoElementType::DetailsSummary(_) => {
data.style_data.per_pseudo.remove(&PseudoElement::DetailsSummary);
}
PseudoElementType::DetailsContent(_) => {
data.style_data.per_pseudo.remove(&PseudoElement::DetailsContent);
}

PseudoElementType::Normal => {
data.style_data.style = None;
}
@@ -798,6 +853,12 @@ pub trait ThreadSafeLayoutElement: Clone + Copy + Sized {

#[inline]
fn get_attr<'a>(&'a self, namespace: &Namespace, name: &Atom) -> Option<&'a str>;

#[inline]
fn get_local_name(&self) -> &Atom;

#[inline]
fn get_namespace(&self) -> &Namespace;
}

#[derive(Copy, Clone)]
@@ -808,7 +869,15 @@ pub struct ServoThreadSafeLayoutNode<'ln> {
pseudo: PseudoElementType<display::T>,
}

impl<'a> PartialEq for ServoThreadSafeLayoutNode<'a> {
#[inline]
fn eq(&self, other: &ServoThreadSafeLayoutNode<'a>) -> bool {
self.node == other.node
}
}

impl<'ln> DangerousThreadSafeLayoutNode for ServoThreadSafeLayoutNode<'ln> {

unsafe fn dangerous_first_child(&self) -> Option<Self> {
self.get_jsmanaged().first_child_ref()
.map(|node| self.new_with_this_lifetime(&node))
@@ -1041,10 +1110,13 @@ impl<ConcreteNode> ThreadSafeLayoutNodeChildrenIterator<ConcreteNode>
pub fn new(parent: ConcreteNode) -> Self {
let first_child: Option<ConcreteNode> = match parent.get_pseudo_element_type() {
PseudoElementType::Normal => {
parent.get_before_pseudo().or_else(|| {
parent.get_before_pseudo().or_else(|| parent.get_details_summary_pseudo()).or_else(|| {
unsafe { parent.dangerous_first_child() }
})
},
PseudoElementType::DetailsContent(_) | PseudoElementType::DetailsSummary(_) => {
unsafe { parent.dangerous_first_child() }
},
_ => None,
};
ThreadSafeLayoutNodeChildrenIterator {
@@ -1058,29 +1130,74 @@ impl<ConcreteNode> Iterator for ThreadSafeLayoutNodeChildrenIterator<ConcreteNod
where ConcreteNode: DangerousThreadSafeLayoutNode {
type Item = ConcreteNode;
fn next(&mut self) -> Option<ConcreteNode> {
let node = self.current_node.clone();

if let Some(ref node) = node {
self.current_node = match node.get_pseudo_element_type() {
PseudoElementType::Before(_) => {
match unsafe { self.parent_node.dangerous_first_child() } {
Some(first) => Some(first),
None => self.parent_node.get_after_pseudo(),
}
},
PseudoElementType::Normal => {
match unsafe { node.dangerous_next_sibling() } {
Some(next) => Some(next),
None => self.parent_node.get_after_pseudo(),
match self.parent_node.get_pseudo_element_type() {

PseudoElementType::Before(_) | PseudoElementType::After(_) => None,

PseudoElementType::DetailsSummary(_) => {
let mut current_node = self.current_node.clone();
loop {
let next_node = if let Some(ref node) = current_node {
if node.is_element() &&
node.as_element().get_local_name() == &atom!("summary") &&
node.as_element().get_namespace() == &ns!(html) {
self.current_node = None;
return Some(node.clone());
}
unsafe { node.dangerous_next_sibling() }
} else {
self.current_node = None;
return None
};
current_node = next_node;
}
}

PseudoElementType::DetailsContent(_) => {
let node = self.current_node.clone();
let node = node.and_then(|node| {
if node.is_element() &&
node.as_element().get_local_name() == &atom!("summary") &&
node.as_element().get_namespace() == &ns!(html) {
unsafe { node.dangerous_next_sibling() }
} else {
Some(node)
}
},
PseudoElementType::After(_) => {
None
},
};
}
});
self.current_node = node.and_then(|node| unsafe { node.dangerous_next_sibling() });
node
}

PseudoElementType::Normal => {
let node = self.current_node.clone();
if let Some(ref node) = node {
self.current_node = match node.get_pseudo_element_type() {
PseudoElementType::Before(_) => {
let first = self.parent_node.get_details_summary_pseudo().or_else(|| unsafe {
self.parent_node.dangerous_first_child()
});
match first {
Some(first) => Some(first),
None => self.parent_node.get_after_pseudo(),
}
},
PseudoElementType::Normal => {
match unsafe { node.dangerous_next_sibling() } {
Some(next) => Some(next),
None => self.parent_node.get_after_pseudo(),
}
},
PseudoElementType::DetailsSummary(_) => self.parent_node.get_details_content_pseudo(),
PseudoElementType::DetailsContent(_) => self.parent_node.get_after_pseudo(),
PseudoElementType::After(_) => {
None
},
};
}
node
}

node
}
}
}

@@ -1099,6 +1216,16 @@ impl<'le> ThreadSafeLayoutElement for ServoThreadSafeLayoutElement<'le> {
self.element.get_attr_val_for_layout(namespace, name)
}
}

#[inline]
fn get_local_name(&self) -> &Atom {
self.element.local_name()
}

#[inline]
fn get_namespace(&self) -> &Namespace {
self.element.namespace()
}
}

pub enum TextContent {
@@ -26,6 +26,8 @@ pub trait SelectorImplExt : SelectorImpl + Sized {
pub enum PseudoElement {
Before,
After,
DetailsSummary,
DetailsContent,
}

#[derive(Clone, Debug, PartialEq, Eq, HeapSizeOf, Hash)]
@@ -97,12 +99,22 @@ impl SelectorImpl for ServoSelectorImpl {
Ok(pseudo_class)
}

fn parse_pseudo_element(_context: &ParserContext,
fn parse_pseudo_element(context: &ParserContext,
name: &str) -> Result<PseudoElement, ()> {
use self::PseudoElement::*;
let pseudo_element = match_ignore_ascii_case! { name,
"before" => Before,
"after" => After,
"-servo-details-summary" => if context.in_user_agent_stylesheet {
DetailsSummary
} else {
return Err(())
},
"-servo-details-content" => if context.in_user_agent_stylesheet {
DetailsContent
} else {
return Err(())
},
_ => return Err(())
};

@@ -122,6 +134,8 @@ impl SelectorImplExt for ServoSelectorImpl {
where F: FnMut(PseudoElement) {
fun(PseudoElement::Before);
fun(PseudoElement::After);
fun(PseudoElement::DetailsContent);
fun(PseudoElement::DetailsSummary);
}

#[inline]
@@ -164,7 +164,6 @@ impl<Impl: SelectorImplExt> Stylist<Impl> {
if !stylesheet.is_effective_for_device(device) {
return;
}

let mut rules_source_order = self.rules_source_order;

// Take apart the StyleRule into individual Rules and insert
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.