mirror of
https://github.com/servo/servo.git
synced 2025-07-24 07:40:27 +01:00
Basic wrappers and glue for GeckoLib.
This commit is contained in:
parent
77b1027646
commit
84f24a04a4
9 changed files with 693 additions and 11 deletions
|
@ -292,7 +292,7 @@ impl<'ln> LayoutNode<'ln> for ServoLayoutNode<'ln> {
|
|||
|
||||
unsafe fn borrow_layout_data_unchecked(&self) -> Option<*const PrivateLayoutData> {
|
||||
self.get_jsmanaged().get_style_and_layout_data().map(|opaque| {
|
||||
let container: NonOpaqueStyleAndLayoutData = transmute(opaque.ptr);
|
||||
let container = *opaque.ptr as NonOpaqueStyleAndLayoutData;
|
||||
&(*(*container).as_unsafe_cell().get()) as *const PrivateLayoutData
|
||||
})
|
||||
}
|
||||
|
@ -300,7 +300,7 @@ impl<'ln> LayoutNode<'ln> for ServoLayoutNode<'ln> {
|
|||
fn borrow_layout_data(&self) -> Option<Ref<PrivateLayoutData>> {
|
||||
unsafe {
|
||||
self.get_jsmanaged().get_style_and_layout_data().map(|opaque| {
|
||||
let container: NonOpaqueStyleAndLayoutData = transmute(opaque.ptr);
|
||||
let container = *opaque.ptr as NonOpaqueStyleAndLayoutData;
|
||||
(*container).borrow()
|
||||
})
|
||||
}
|
||||
|
@ -309,7 +309,7 @@ impl<'ln> LayoutNode<'ln> for ServoLayoutNode<'ln> {
|
|||
fn mutate_layout_data(&self) -> Option<RefMut<PrivateLayoutData>> {
|
||||
unsafe {
|
||||
self.get_jsmanaged().get_style_and_layout_data().map(|opaque| {
|
||||
let container: NonOpaqueStyleAndLayoutData = transmute(opaque.ptr);
|
||||
let container = *opaque.ptr as NonOpaqueStyleAndLayoutData;
|
||||
(*container).borrow_mut()
|
||||
})
|
||||
}
|
||||
|
|
|
@ -115,10 +115,6 @@ pub trait DomTraversalContext<'ln, N: TNode<'ln>> {
|
|||
fn process_postorder(&self, node: N);
|
||||
}
|
||||
|
||||
/// FIXME(bholley): I added this now to demonstrate the usefulness of the new design.
|
||||
/// This is currently unused, but will be used shortly.
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub struct StandaloneStyleContext<'a> {
|
||||
pub shared: &'a SharedStyleContext,
|
||||
cached_local_style_context: Rc<LocalStyleContext>,
|
||||
|
@ -138,7 +134,6 @@ impl<'a> StyleContext<'a> for StandaloneStyleContext<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub struct RecalcStyleOnly<'lc> {
|
||||
context: StandaloneStyleContext<'lc>,
|
||||
root: OpaqueNode,
|
||||
|
|
7
ports/geckolib/Cargo.lock
generated
7
ports/geckolib/Cargo.lock
generated
|
@ -2,9 +2,16 @@
|
|||
name = "geckoservo"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"app_units 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"selectors 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"string_cache 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"style 0.0.1",
|
||||
"url 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"util 0.0.1",
|
||||
|
|
|
@ -9,10 +9,17 @@ path = "lib.rs"
|
|||
crate-type = ["staticlib"]
|
||||
|
||||
[dependencies]
|
||||
log = "0.3"
|
||||
url = "0.5.2"
|
||||
libc = "0.2"
|
||||
app_units = {version = "0.1", features = ["plugins"]}
|
||||
bitflags = "0.3"
|
||||
cssparser = { version = "0.4", features = [ "serde-serialization" ] }
|
||||
euclid = {version = "0.4", features = ["plugins"]}
|
||||
libc = "0.2"
|
||||
log = "0.3"
|
||||
num_cpus = "0.2.2"
|
||||
selectors = "0.2"
|
||||
smallvec = "0.1"
|
||||
string_cache = "0.2"
|
||||
url = "0.5.2"
|
||||
|
||||
[dependencies.util]
|
||||
path = "../../components/util"
|
||||
|
|
81
ports/geckolib/bindings.rs
Normal file
81
ports/geckolib/bindings.rs
Normal file
|
@ -0,0 +1,81 @@
|
|||
/* automatically generated by rust-bindgen */
|
||||
|
||||
pub type int64_t = ::libc::c_longlong;
|
||||
pub type uint64_t = ::libc::c_ulonglong;
|
||||
pub type int_least64_t = int64_t;
|
||||
pub type uint_least64_t = uint64_t;
|
||||
pub type int_fast64_t = int64_t;
|
||||
pub type uint_fast64_t = uint64_t;
|
||||
pub type int32_t = ::libc::c_int;
|
||||
pub type uint32_t = ::libc::c_uint;
|
||||
pub type int_least32_t = int32_t;
|
||||
pub type uint_least32_t = uint32_t;
|
||||
pub type int_fast32_t = int32_t;
|
||||
pub type uint_fast32_t = uint32_t;
|
||||
pub type int16_t = ::libc::c_short;
|
||||
pub type uint16_t = ::libc::c_ushort;
|
||||
pub type int_least16_t = int16_t;
|
||||
pub type uint_least16_t = uint16_t;
|
||||
pub type int_fast16_t = int16_t;
|
||||
pub type uint_fast16_t = uint16_t;
|
||||
pub type int8_t = ::libc::c_char;
|
||||
pub type uint8_t = ::libc::c_uchar;
|
||||
pub type int_least8_t = int8_t;
|
||||
pub type uint_least8_t = uint8_t;
|
||||
pub type int_fast8_t = int8_t;
|
||||
pub type uint_fast8_t = uint8_t;
|
||||
pub type intptr_t = int64_t;
|
||||
pub type uintptr_t = uint64_t;
|
||||
pub type intmax_t = ::libc::c_long;
|
||||
pub type uintmax_t = ::libc::c_ulong;
|
||||
pub type Enum_NodeType = ::libc::c_uint;
|
||||
pub const ELEMENT_NODE: ::libc::c_uint = 1;
|
||||
pub const ATTRIBUTE_NODE: ::libc::c_uint = 2;
|
||||
pub const TEXT_NODE: ::libc::c_uint = 3;
|
||||
pub const CDATA_SECTION_NODE: ::libc::c_uint = 4;
|
||||
pub const ENTITY_REFERENCE_NODE: ::libc::c_uint = 5;
|
||||
pub const ENTITY_NODE: ::libc::c_uint = 6;
|
||||
pub const PROCESSING_INSTRUCTION_NODE: ::libc::c_uint = 7;
|
||||
pub const COMMENT_NODE: ::libc::c_uint = 8;
|
||||
pub const DOCUMENT_NODE: ::libc::c_uint = 9;
|
||||
pub const DOCUMENT_TYPE_NODE: ::libc::c_uint = 10;
|
||||
pub const DOCUMENT_FRAGMENT_NODE: ::libc::c_uint = 11;
|
||||
pub const NOTATION_NODE: ::libc::c_uint = 12;
|
||||
pub enum Struct_RawGeckoNode { }
|
||||
pub type RawGeckoNode = Struct_RawGeckoNode;
|
||||
pub enum Struct_RawGeckoElement { }
|
||||
pub type RawGeckoElement = Struct_RawGeckoElement;
|
||||
pub enum Struct_RawGeckoDocument { }
|
||||
pub type RawGeckoDocument = Struct_RawGeckoDocument;
|
||||
pub enum Struct_ServoNodeData { }
|
||||
pub type ServoNodeData = Struct_ServoNodeData;
|
||||
extern "C" {
|
||||
pub fn Gecko_ElementState(element: *mut RawGeckoElement) -> uint8_t;
|
||||
pub fn Gecko_GetAttrAsUTF8(element: *mut RawGeckoElement, ns: *const uint8_t,
|
||||
name: *const uint8_t, length: *mut uint32_t)
|
||||
-> *const ::libc::c_char;
|
||||
pub fn Gecko_ChildrenCount(node: *mut RawGeckoNode) -> uint32_t;
|
||||
pub fn Gecko_GetDocumentElement(document: *mut RawGeckoDocument)
|
||||
-> *mut RawGeckoElement;
|
||||
pub fn Gecko_GetFirstChild(node: *mut RawGeckoNode) -> *mut RawGeckoNode;
|
||||
pub fn Gecko_GetLastChild(node: *mut RawGeckoNode) -> *mut RawGeckoNode;
|
||||
pub fn Gecko_GetPrevSibling(node: *mut RawGeckoNode) -> *mut RawGeckoNode;
|
||||
pub fn Gecko_GetNextSibling(node: *mut RawGeckoNode) -> *mut RawGeckoNode;
|
||||
pub fn Gecko_GetNodeData(node: *mut RawGeckoNode) -> *mut ServoNodeData;
|
||||
pub fn Gecko_GetParentNode(node: *mut RawGeckoNode) -> *mut RawGeckoNode;
|
||||
pub fn Gecko_LocalName(element: *mut RawGeckoElement, length: *mut uint32_t)
|
||||
-> *const uint16_t;
|
||||
pub fn Gecko_IsHTMLElementInHTMLDocument(element: *mut RawGeckoElement)
|
||||
-> ::libc::c_int;
|
||||
pub fn Gecko_IsLink(element: *mut RawGeckoElement) -> ::libc::c_int;
|
||||
pub fn Gecko_IsTextNode(node: *mut RawGeckoNode) -> ::libc::c_int;
|
||||
pub fn Gecko_IsVisitedLink(element: *mut RawGeckoElement) -> ::libc::c_int;
|
||||
pub fn Gecko_IsUnvisitedLink(element: *mut RawGeckoElement) -> ::libc::c_int;
|
||||
pub fn Gecko_Namespace(element: *mut RawGeckoElement, length: *mut uint32_t)
|
||||
-> *const uint16_t;
|
||||
pub fn Gecko_NodeIsElement(node: *mut RawGeckoNode) -> ::libc::c_int;
|
||||
pub fn Gecko_SetNodeData(node: *mut RawGeckoNode,
|
||||
data: *mut ServoNodeData) -> ();
|
||||
pub fn Servo_RestyleDocument(aDoc: *mut RawGeckoDocument) -> ();
|
||||
pub fn Servo_DropNodeData(data: *mut ServoNodeData) -> ();
|
||||
}
|
92
ports/geckolib/glue.rs
Normal file
92
ports/geckolib/glue.rs
Normal file
|
@ -0,0 +1,92 @@
|
|||
/* 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 http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#![allow(unsafe_code)]
|
||||
|
||||
use app_units::Au;
|
||||
use bindings::RawGeckoDocument;
|
||||
use bindings::ServoNodeData;
|
||||
use euclid::Size2D;
|
||||
use euclid::size::TypedSize2D;
|
||||
use num_cpus;
|
||||
use std::cmp;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::mpsc::{channel, Sender};
|
||||
use std::sync::{Arc, Mutex, RwLock};
|
||||
use style::animation::Animation;
|
||||
use style::context::{ReflowGoal, SharedStyleContext, StylistWrapper};
|
||||
use style::dom::{TDocument, TNode};
|
||||
use style::error_reporting::StdoutErrorReporter;
|
||||
use style::media_queries::{Device, MediaType};
|
||||
use style::parallel::{self, WorkQueueData};
|
||||
use style::selector_matching::Stylist;
|
||||
use style::stylesheets::Stylesheet;
|
||||
use style::traversal::RecalcStyleOnly;
|
||||
use util::geometry::ViewportPx;
|
||||
use util::resource_files::set_resources_path;
|
||||
use util::thread_state;
|
||||
use util::workqueue::WorkQueue;
|
||||
use wrapper::{GeckoDocument, GeckoNode, NonOpaqueStyleData};
|
||||
|
||||
/*
|
||||
* For Gecko->Servo function calls, we need to redeclare the same signature that was declared in
|
||||
* the C header in Gecko. In order to catch accidental mismatches, we run rust-bindgen against
|
||||
* those signatures as well, giving us a second declaration of all the Servo_* functions in this
|
||||
* crate. If there's a mismatch, LLVM will assert and abort, which is a rather awful thing to
|
||||
* depend on but good enough for our purposes.
|
||||
*/
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_RestyleDocument(doc: *mut RawGeckoDocument) -> () {
|
||||
let document = unsafe { GeckoDocument::from_raw(doc) };
|
||||
let node = match document.root_node() {
|
||||
Some(x) => x,
|
||||
None => return,
|
||||
};
|
||||
|
||||
// FIXME(bholley): Don't hardcode resources path. We may want to use Gecko's UA stylesheets
|
||||
// anyway.
|
||||
set_resources_path(Some("/files/mozilla/stylo/servo/resources/".to_owned()));
|
||||
|
||||
// FIXME(bholley): Real window size.
|
||||
let window_size: TypedSize2D<ViewportPx, f32> = Size2D::typed(800.0, 600.0);
|
||||
let device = Device::new(MediaType::Screen, window_size);
|
||||
|
||||
// FIXME(bholley): Real stylist and stylesheets.
|
||||
let stylesheets: Vec<Arc<Stylesheet>> = Vec::new();
|
||||
let mut stylist = Box::new(Stylist::new(device));
|
||||
let _needs_dirtying = stylist.update(&stylesheets, false);
|
||||
|
||||
// FIXME(bholley): Hook this up to something.
|
||||
let new_animations_sender: Sender<Animation> = channel().0;
|
||||
|
||||
let shared_style_context = SharedStyleContext {
|
||||
viewport_size: Size2D::new(Au(0), Au(0)),
|
||||
screen_size_changed: false,
|
||||
generation: 0,
|
||||
goal: ReflowGoal::ForScriptQuery,
|
||||
stylist: StylistWrapper(&*stylist),
|
||||
new_animations_sender: Mutex::new(new_animations_sender),
|
||||
running_animations: Arc::new(RwLock::new(HashMap::new())),
|
||||
expired_animations: Arc::new(RwLock::new(HashMap::new())),
|
||||
error_reporter: Box::new(StdoutErrorReporter),
|
||||
};
|
||||
|
||||
let num_threads = cmp::max(num_cpus::get() * 3 / 4, 1);
|
||||
let mut parallel_traversal: WorkQueue<SharedStyleContext, WorkQueueData> =
|
||||
WorkQueue::new("StyleWorker", thread_state::LAYOUT, num_threads);
|
||||
|
||||
if node.is_dirty() || node.has_dirty_descendants() {
|
||||
parallel::traverse_dom::<GeckoNode, RecalcStyleOnly>(node, &shared_style_context, &mut parallel_traversal);
|
||||
}
|
||||
|
||||
parallel_traversal.shutdown();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_DropNodeData(data: *mut ServoNodeData) -> () {
|
||||
unsafe {
|
||||
let _ = Box::<NonOpaqueStyleData>::from_raw(data as *mut NonOpaqueStyleData);
|
||||
}
|
||||
}
|
|
@ -2,4 +2,28 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#![feature(as_unsafe_cell)]
|
||||
#![feature(box_syntax)]
|
||||
#![feature(ptr_as_ref)]
|
||||
|
||||
extern crate app_units;
|
||||
#[macro_use]
|
||||
extern crate bitflags;
|
||||
extern crate cssparser;
|
||||
extern crate euclid;
|
||||
extern crate libc;
|
||||
extern crate num_cpus;
|
||||
#[macro_use(state_pseudo_classes)]
|
||||
extern crate selectors;
|
||||
extern crate smallvec;
|
||||
#[macro_use(atom, ns)]
|
||||
extern crate string_cache;
|
||||
extern crate style;
|
||||
extern crate url;
|
||||
extern crate util;
|
||||
|
||||
#[allow(dead_code, non_camel_case_types)]
|
||||
mod bindings;
|
||||
#[allow(non_snake_case)]
|
||||
pub mod glue;
|
||||
mod wrapper;
|
||||
|
|
475
ports/geckolib/wrapper.rs
Normal file
475
ports/geckolib/wrapper.rs
Normal file
|
@ -0,0 +1,475 @@
|
|||
/* 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 http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#![allow(unsafe_code)]
|
||||
|
||||
use bindings::{Gecko_ChildrenCount};
|
||||
use bindings::{Gecko_ElementState, Gecko_GetAttrAsUTF8, Gecko_GetDocumentElement};
|
||||
use bindings::{Gecko_GetFirstChild, Gecko_GetLastChild, Gecko_GetNodeData};
|
||||
use bindings::{Gecko_GetParentNode, Gecko_GetPrevSibling, Gecko_GetNextSibling};
|
||||
use bindings::{Gecko_IsHTMLElementInHTMLDocument, Gecko_IsLink, Gecko_IsTextNode};
|
||||
use bindings::{Gecko_IsUnvisitedLink, Gecko_IsVisitedLink};
|
||||
#[allow(unused_imports)] // Used in commented-out code.
|
||||
use bindings::{Gecko_LocalName, Gecko_Namespace, Gecko_NodeIsElement, Gecko_SetNodeData};
|
||||
use bindings::{RawGeckoDocument, RawGeckoElement, RawGeckoNode};
|
||||
use bindings::{ServoNodeData};
|
||||
use libc::uintptr_t;
|
||||
use selectors::matching::DeclarationBlock;
|
||||
use selectors::parser::{AttrSelector, NamespaceConstraint};
|
||||
use selectors::states::*;
|
||||
use smallvec::VecLike;
|
||||
use std::cell::{Ref, RefCell, RefMut};
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::BitOr;
|
||||
use std::slice;
|
||||
use std::str::from_utf8_unchecked;
|
||||
use std::sync::Arc;
|
||||
use string_cache::{Atom, Namespace};
|
||||
use style::data::PrivateStyleData;
|
||||
use style::dom::{OpaqueNode, TDocument, TElement, TNode, TRestyleDamage, UnsafeNode};
|
||||
#[allow(unused_imports)] // Used in commented-out code.
|
||||
use style::error_reporting::StdoutErrorReporter;
|
||||
use style::properties::{ComputedValues, PropertyDeclaration, PropertyDeclarationBlock};
|
||||
#[allow(unused_imports)] // Used in commented-out code.
|
||||
use style::properties::{parse_style_attribute};
|
||||
use style::restyle_hints::ElementSnapshot;
|
||||
#[allow(unused_imports)] // Used in commented-out code.
|
||||
use url::Url;
|
||||
|
||||
pub type NonOpaqueStyleData = *mut RefCell<PrivateStyleData>;
|
||||
|
||||
// Important: We don't currently refcount the DOM, because the wrapper lifetime
|
||||
// magic guarantees that our LayoutFoo references won't outlive the root, and
|
||||
// we don't mutate any of the references on the Gecko side during restyle. We
|
||||
// could implement refcounting if need be (at a potentially non-trivial
|
||||
// performance cost) by implementing Drop and making LayoutFoo non-Copy.
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct GeckoNode<'ln> {
|
||||
node: *mut RawGeckoNode,
|
||||
chain: PhantomData<&'ln ()>,
|
||||
}
|
||||
|
||||
impl<'ln> GeckoNode<'ln> {
|
||||
unsafe fn from_raw(n: *mut RawGeckoNode) -> GeckoNode<'ln> {
|
||||
GeckoNode {
|
||||
node: n,
|
||||
chain: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn from_ref(n: &RawGeckoNode) -> GeckoNode<'ln> {
|
||||
GeckoNode::from_raw(n as *const RawGeckoNode as *mut RawGeckoNode)
|
||||
}
|
||||
|
||||
fn get_node_data(&self) -> NonOpaqueStyleData {
|
||||
unsafe {
|
||||
Gecko_GetNodeData(self.node) as NonOpaqueStyleData
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct DummyRestyleDamage;
|
||||
impl TRestyleDamage for DummyRestyleDamage {
|
||||
fn compute(_: &Option<Arc<ComputedValues>>, _: &ComputedValues) -> Self { DummyRestyleDamage }
|
||||
fn rebuild_and_reflow() -> Self { DummyRestyleDamage }
|
||||
}
|
||||
impl BitOr for DummyRestyleDamage {
|
||||
type Output = Self;
|
||||
fn bitor(self, _: Self) -> Self { DummyRestyleDamage }
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl<'ln> TNode<'ln> for GeckoNode<'ln> {
|
||||
type ConcreteDocument = GeckoDocument<'ln>;
|
||||
type ConcreteElement = GeckoElement<'ln>;
|
||||
type ConcreteRestyleDamage = DummyRestyleDamage;
|
||||
|
||||
fn to_unsafe(&self) -> UnsafeNode {
|
||||
(self.node as usize, 0)
|
||||
}
|
||||
|
||||
unsafe fn from_unsafe(n: &UnsafeNode) -> Self {
|
||||
GeckoNode::from_raw(n.0 as *mut RawGeckoNode)
|
||||
}
|
||||
|
||||
fn is_text_node(&self) -> bool {
|
||||
unsafe {
|
||||
Gecko_IsTextNode(self.node) != 0
|
||||
}
|
||||
}
|
||||
|
||||
fn is_element(&self) -> bool {
|
||||
unsafe {
|
||||
Gecko_NodeIsElement(self.node) != 0
|
||||
}
|
||||
}
|
||||
|
||||
fn dump(self) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn opaque(&self) -> OpaqueNode {
|
||||
let ptr: uintptr_t = self.node as uintptr_t;
|
||||
OpaqueNode(ptr)
|
||||
}
|
||||
|
||||
fn initialize_data(self) {
|
||||
unsafe {
|
||||
if self.get_node_data().is_null() {
|
||||
let ptr: NonOpaqueStyleData = Box::into_raw(box RefCell::new(PrivateStyleData::new()));
|
||||
Gecko_SetNodeData(self.node, ptr as *mut ServoNodeData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn layout_parent_node(self, reflow_root: OpaqueNode) -> Option<GeckoNode<'ln>> {
|
||||
if self.opaque() == reflow_root {
|
||||
None
|
||||
} else {
|
||||
self.parent_node()
|
||||
}
|
||||
}
|
||||
|
||||
fn debug_id(self) -> usize {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn children_count(&self) -> u32 {
|
||||
unsafe {
|
||||
Gecko_ChildrenCount(self.node)
|
||||
}
|
||||
}
|
||||
|
||||
fn as_element(&self) -> Option<GeckoElement<'ln>> {
|
||||
if self.is_element() {
|
||||
unsafe { Some(GeckoElement::from_raw(self.node as *mut RawGeckoElement)) }
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn as_document(&self) -> Option<GeckoDocument<'ln>> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn has_changed(&self) -> bool {
|
||||
// FIXME(bholley) - Implement this to allow incremental reflows!
|
||||
true
|
||||
}
|
||||
|
||||
unsafe fn set_changed(&self, _value: bool) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn is_dirty(&self) -> bool {
|
||||
// FIXME(bholley)
|
||||
true
|
||||
}
|
||||
|
||||
unsafe fn set_dirty(&self, _value: bool) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn has_dirty_descendants(&self) -> bool {
|
||||
// FIXME(bholley)
|
||||
true
|
||||
}
|
||||
|
||||
unsafe fn set_dirty_descendants(&self, _value: bool) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
unsafe fn borrow_data_unchecked(&self) -> Option<*const PrivateStyleData> {
|
||||
self.get_node_data().as_ref().map(|d| d.as_unsafe_cell().get() as *const PrivateStyleData)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn borrow_data(&self) -> Option<Ref<PrivateStyleData>> {
|
||||
unsafe {
|
||||
self.get_node_data().as_ref().map(|d| d.borrow())
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn mutate_data(&self) -> Option<RefMut<PrivateStyleData>> {
|
||||
unsafe {
|
||||
self.get_node_data().as_ref().map(|d| d.borrow_mut())
|
||||
}
|
||||
}
|
||||
|
||||
fn restyle_damage(self) -> Self::ConcreteRestyleDamage { DummyRestyleDamage }
|
||||
|
||||
fn set_restyle_damage(self, _: Self::ConcreteRestyleDamage) {}
|
||||
|
||||
fn parent_node(&self) -> Option<GeckoNode<'ln>> {
|
||||
unsafe {
|
||||
Gecko_GetParentNode(self.node).as_ref().map(|n| GeckoNode::from_ref(n))
|
||||
}
|
||||
}
|
||||
|
||||
fn first_child(&self) -> Option<GeckoNode<'ln>> {
|
||||
unsafe {
|
||||
Gecko_GetFirstChild(self.node).as_ref().map(|n| GeckoNode::from_ref(n))
|
||||
}
|
||||
}
|
||||
|
||||
fn last_child(&self) -> Option<GeckoNode<'ln>> {
|
||||
unsafe {
|
||||
Gecko_GetLastChild(self.node).as_ref().map(|n| GeckoNode::from_ref(n))
|
||||
}
|
||||
}
|
||||
|
||||
fn prev_sibling(&self) -> Option<GeckoNode<'ln>> {
|
||||
unsafe {
|
||||
Gecko_GetPrevSibling(self.node).as_ref().map(|n| GeckoNode::from_ref(n))
|
||||
}
|
||||
}
|
||||
|
||||
fn next_sibling(&self) -> Option<GeckoNode<'ln>> {
|
||||
unsafe {
|
||||
Gecko_GetNextSibling(self.node).as_ref().map(|n| GeckoNode::from_ref(n))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct GeckoDocument<'ld> {
|
||||
document: *mut RawGeckoDocument,
|
||||
chain: PhantomData<&'ld ()>,
|
||||
}
|
||||
|
||||
impl<'ld> GeckoDocument<'ld> {
|
||||
pub unsafe fn from_raw(doc: *mut RawGeckoDocument) -> GeckoDocument<'ld> {
|
||||
GeckoDocument {
|
||||
document: doc,
|
||||
chain: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ld> TDocument<'ld> for GeckoDocument<'ld> {
|
||||
type ConcreteNode = GeckoNode<'ld>;
|
||||
type ConcreteElement = GeckoElement<'ld>;
|
||||
|
||||
fn as_node(&self) -> GeckoNode<'ld> {
|
||||
unsafe { GeckoNode::from_raw(self.document as *mut RawGeckoNode) }
|
||||
}
|
||||
|
||||
fn root_node(&self) -> Option<GeckoNode<'ld>> {
|
||||
unsafe {
|
||||
Gecko_GetDocumentElement(self.document).as_ref().map(|el| GeckoElement::from_ref(el).as_node())
|
||||
}
|
||||
}
|
||||
|
||||
fn drain_modified_elements(&self) -> Vec<(GeckoElement<'ld>, ElementSnapshot)> {
|
||||
unimplemented!()
|
||||
/*
|
||||
let elements = unsafe { self.document.drain_modified_elements() };
|
||||
elements.into_iter().map(|(el, snapshot)| (ServoLayoutElement::from_layout_js(el), snapshot)).collect()*/
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct GeckoElement<'le> {
|
||||
element: *mut RawGeckoElement,
|
||||
chain: PhantomData<&'le ()>,
|
||||
}
|
||||
|
||||
impl<'le> GeckoElement<'le> {
|
||||
unsafe fn from_raw(el: *mut RawGeckoElement) -> GeckoElement<'le> {
|
||||
GeckoElement {
|
||||
element: el,
|
||||
chain: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn from_ref(el: &RawGeckoElement) -> GeckoElement<'le> {
|
||||
GeckoElement::from_raw(el as *const RawGeckoElement as *mut RawGeckoElement)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'le> TElement<'le> for GeckoElement<'le> {
|
||||
type ConcreteNode = GeckoNode<'le>;
|
||||
type ConcreteDocument = GeckoDocument<'le>;
|
||||
|
||||
fn as_node(&self) -> Self::ConcreteNode {
|
||||
unsafe { GeckoNode::from_raw(self.element as *mut RawGeckoNode) }
|
||||
}
|
||||
|
||||
fn style_attribute(&self) -> &'le Option<PropertyDeclarationBlock> {
|
||||
panic!("Requires signature modification - only implemented in stylo branch");
|
||||
/*
|
||||
// FIXME(bholley): We should do what Servo does here. Gecko needs to
|
||||
// call into the Servo CSS parser and then cache the resulting block
|
||||
// in the nsAttrValue. That will allow us to borrow it from here.
|
||||
let attr = self.get_attr(&ns!(), &atom!("style"));
|
||||
// FIXME(bholley): Real base URL and error reporter.
|
||||
let base_url = Url::parse("http://www.example.org").unwrap();
|
||||
attr.map(|v| parse_style_attribute(&v, &base_url, Box::new(StdoutErrorReporter)))
|
||||
*/
|
||||
}
|
||||
|
||||
fn get_state(&self) -> ElementState {
|
||||
unsafe {
|
||||
ElementState::from_bits_truncate(Gecko_ElementState(self.element))
|
||||
}
|
||||
}
|
||||
|
||||
fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, _hints: &mut V)
|
||||
where V: VecLike<DeclarationBlock<Vec<PropertyDeclaration>>>
|
||||
{
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_attr<'a>(&'a self, namespace: &Namespace, name: &Atom) -> Option<&'a str> {
|
||||
unsafe {
|
||||
let mut length: u32 = 0;
|
||||
let ptr = Gecko_GetAttrAsUTF8(self.element, namespace.0.as_ptr(), name.as_ptr(), &mut length);
|
||||
reinterpret_string(ptr, length)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_attrs<'a>(&'a self, _name: &Atom) -> Vec<&'a str> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! state_getter {
|
||||
($(
|
||||
$(#[$Flag_attr: meta])*
|
||||
state $css: expr => $variant: ident / $method: ident /
|
||||
$flag: ident = $value: expr,
|
||||
)+) => {
|
||||
$( fn $method(&self) -> bool { self.get_state().contains($flag) } )+
|
||||
}
|
||||
}
|
||||
|
||||
impl<'le> ::selectors::Element for GeckoElement<'le> {
|
||||
fn parent_element(&self) -> Option<Self> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn first_child_element(&self) -> Option<Self> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn last_child_element(&self) -> Option<Self> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn prev_sibling_element(&self) -> Option<Self> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn next_sibling_element(&self) -> Option<Self> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn is_root(&self) -> bool {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn is_empty(&self) -> bool {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn get_local_name(&self) -> &Atom {
|
||||
panic!("Requires signature modification - only implemented in stylo branch");
|
||||
/*
|
||||
unsafe {
|
||||
let mut length: u32 = 0;
|
||||
let p = Gecko_LocalName(self.element, &mut length);
|
||||
Atom::from(&*String::from_utf16(slice::from_raw_parts(p, length as usize)).unwrap())
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
fn get_namespace(&self) -> &Namespace {
|
||||
panic!("Requires signature modification - only implemented in stylo branch");
|
||||
/*
|
||||
unsafe {
|
||||
let mut length: u32 = 0;
|
||||
let p = Gecko_Namespace(self.element, &mut length);
|
||||
Namespace(Atom::from(&*String::from_utf16(slice::from_raw_parts(p, length as usize)).unwrap()))
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
fn is_link(&self) -> bool {
|
||||
unsafe {
|
||||
Gecko_IsLink(self.element) != 0
|
||||
}
|
||||
}
|
||||
|
||||
fn is_unvisited_link(&self) -> bool {
|
||||
unsafe {
|
||||
Gecko_IsUnvisitedLink(self.element) != 0
|
||||
}
|
||||
}
|
||||
|
||||
fn is_visited_link(&self) -> bool {
|
||||
unsafe {
|
||||
Gecko_IsVisitedLink(self.element) != 0
|
||||
}
|
||||
}
|
||||
|
||||
state_pseudo_classes!(state_getter);
|
||||
|
||||
fn get_id(&self) -> Option<Atom> {
|
||||
// FIXME(bholley): Servo caches the id atom directly on the element to
|
||||
// make this blazing fast. Assuming that was a measured optimization, doing
|
||||
// the dumb thing like we do below will almost certainly be a bottleneck.
|
||||
self.get_attr(&ns!(), &atom!("id")).map(|s| Atom::from(s))
|
||||
}
|
||||
|
||||
fn has_class(&self, _name: &Atom) -> bool {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn each_class<F>(&self, mut callback: F) where F: FnMut(&Atom) {
|
||||
// FIXME(bholley): Synergize with the DOM to stop splitting strings here.
|
||||
if let Some(classes) = self.get_attr(&ns!(), &atom!("class")) {
|
||||
for c in classes.split(" ") {
|
||||
callback(&Atom::from(c));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn has_servo_nonzero_border(&self) -> bool {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn match_attr<F>(&self, attr: &AttrSelector, test: F) -> bool where F: Fn(&str) -> bool {
|
||||
// FIXME(bholley): This is copy-pasted from the servo wrapper's version.
|
||||
// We should find a way to share it.
|
||||
let name = if self.is_html_element_in_html_document() {
|
||||
&attr.lower_name
|
||||
} else {
|
||||
&attr.name
|
||||
};
|
||||
match attr.namespace {
|
||||
NamespaceConstraint::Specific(ref ns) => {
|
||||
self.get_attr(ns, name).map_or(false, |attr| test(attr))
|
||||
},
|
||||
NamespaceConstraint::Any => {
|
||||
self.get_attrs(name).iter().any(|attr| test(*attr))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_html_element_in_html_document(&self) -> bool {
|
||||
unsafe {
|
||||
Gecko_IsHTMLElementInHTMLDocument(self.element) != 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn reinterpret_string<'a>(ptr: *const ::libc::c_char, length: u32) -> Option<&'a str> {
|
||||
(ptr as *const u8).as_ref().map(|p| from_utf8_unchecked(slice::from_raw_parts(p, length as usize)))
|
||||
}
|
|
@ -39,6 +39,7 @@ ignored_files = [
|
|||
os.path.join(".", "target", "*"),
|
||||
os.path.join(".", "ports", "gonk", "src", "native_window_glue.cpp"),
|
||||
os.path.join(".", "ports", "cef", "*"),
|
||||
os.path.join(".", "ports", "geckolib", "bindings.rs"),
|
||||
|
||||
# MIT license
|
||||
os.path.join(".", "components", "util", "deque", "mod.rs"),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue