servo: Merge #14055 - support cursor property url() values in stylo (from heycam:cursor); r=Manishearth

<!-- Please describe your changes on the following line: -->

This is the Servo-side change for [bug 1310560](https://bugzilla.mozilla.org/show_bug.cgi?id=1310560), which @Manishearth has already r+ed.

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->
- [ ] `./mach build -d` does not report any errors
- [X] `./mach test-tidy` does not report any errors
- [ ] These changes fix #__ (github issue number if applicable).

<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because _____

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->

Source-Repo: https://github.com/servo/servo
Source-Revision: eb531c15d990391f73f3a1030b103dfc3e023427
This commit is contained in:
Cameron McCormack 2016-11-21 05:49:05 -06:00
Родитель 27d132363a
Коммит ed81f90b37
7 изменённых файлов: 159 добавлений и 24 удалений

Просмотреть файл

@ -2246,8 +2246,8 @@ impl ServoComputedValuesCursorUtility for ServoComputedValues {
fn get_cursor(&self, default_cursor: Cursor) -> Option<Cursor> { fn get_cursor(&self, default_cursor: Cursor) -> Option<Cursor> {
match (self.get_pointing().pointer_events, self.get_pointing().cursor) { match (self.get_pointing().pointer_events, self.get_pointing().cursor) {
(pointer_events::T::none, _) => None, (pointer_events::T::none, _) => None,
(pointer_events::T::auto, cursor::T::AutoCursor) => Some(default_cursor), (pointer_events::T::auto, cursor::Keyword::AutoCursor) => Some(default_cursor),
(pointer_events::T::auto, cursor::T::SpecifiedCursor(cursor)) => Some(cursor), (pointer_events::T::auto, cursor::Keyword::SpecifiedCursor(cursor)) => Some(cursor),
} }
} }
} }

Просмотреть файл

@ -278,6 +278,7 @@ COMPILATION_TARGETS = {
"nsCSSValue", "nsCSSValue",
"nsCSSValueSharedList", "nsCSSValueSharedList",
"nsChangeHint", "nsChangeHint",
"nsCursorImage",
"nsFont", "nsFont",
"nsIAtom", "nsIAtom",
"nsIDocument", "nsIDocument",

Просмотреть файл

@ -60,6 +60,7 @@ use gecko_bindings::structs::nsCSSShadowArray;
use gecko_bindings::structs::nsCSSValue; use gecko_bindings::structs::nsCSSValue;
use gecko_bindings::structs::nsCSSValueSharedList; use gecko_bindings::structs::nsCSSValueSharedList;
use gecko_bindings::structs::nsChangeHint; use gecko_bindings::structs::nsChangeHint;
use gecko_bindings::structs::nsCursorImage;
use gecko_bindings::structs::nsFont; use gecko_bindings::structs::nsFont;
use gecko_bindings::structs::nsIAtom; use gecko_bindings::structs::nsIAtom;
use gecko_bindings::structs::nsIDocument; use gecko_bindings::structs::nsIDocument;
@ -510,6 +511,21 @@ extern "C" {
pub fn Gecko_CopyListStyleImageFrom(dest: *mut nsStyleList, pub fn Gecko_CopyListStyleImageFrom(dest: *mut nsStyleList,
src: *const nsStyleList); src: *const nsStyleList);
} }
extern "C" {
pub fn Gecko_SetCursorArrayLength(ui: *mut nsStyleUserInterface,
len: usize);
}
extern "C" {
pub fn Gecko_SetCursorImage(cursor: *mut nsCursorImage,
string_bytes: *const u8, string_length: u32,
base_uri: *mut ThreadSafeURIHolder,
referrer: *mut ThreadSafeURIHolder,
principal: *mut ThreadSafePrincipalHolder);
}
extern "C" {
pub fn Gecko_CopyCursorArrayFrom(dest: *mut nsStyleUserInterface,
src: *const nsStyleUserInterface);
}
extern "C" { extern "C" {
pub fn Gecko_SetMozBinding(style_struct: *mut nsStyleDisplay, pub fn Gecko_SetMozBinding(style_struct: *mut nsStyleDisplay,
string_bytes: *const u8, string_length: u32, string_bytes: *const u8, string_length: u32,

Просмотреть файл

@ -11866,7 +11866,7 @@ pub struct nsCursorImage {
pub mHaveHotspot: bool, pub mHaveHotspot: bool,
pub mHotspotX: f32, pub mHotspotX: f32,
pub mHotspotY: f32, pub mHotspotY: f32,
pub mImage: nsCOMPtr<imgIRequest>, pub mImage: RefPtr<nsStyleImageRequest>,
} }
#[test] #[test]
fn bindgen_test_layout_nsCursorImage() { fn bindgen_test_layout_nsCursorImage() {

Просмотреть файл

@ -11822,7 +11822,7 @@ pub struct nsCursorImage {
pub mHaveHotspot: bool, pub mHaveHotspot: bool,
pub mHotspotX: f32, pub mHotspotX: f32,
pub mHotspotY: f32, pub mHotspotY: f32,
pub mImage: nsCOMPtr<imgIRequest>, pub mImage: RefPtr<nsStyleImageRequest>,
} }
#[test] #[test]
fn bindgen_test_layout_nsCursorImage() { fn bindgen_test_layout_nsCursorImage() {

Просмотреть файл

@ -19,6 +19,7 @@ use gecko_bindings::bindings::Gecko_Construct_${style_struct.gecko_ffi_name};
use gecko_bindings::bindings::Gecko_CopyConstruct_${style_struct.gecko_ffi_name}; use gecko_bindings::bindings::Gecko_CopyConstruct_${style_struct.gecko_ffi_name};
use gecko_bindings::bindings::Gecko_Destroy_${style_struct.gecko_ffi_name}; use gecko_bindings::bindings::Gecko_Destroy_${style_struct.gecko_ffi_name};
% endfor % endfor
use gecko_bindings::bindings::Gecko_CopyCursorArrayFrom;
use gecko_bindings::bindings::Gecko_CopyFontFamilyFrom; use gecko_bindings::bindings::Gecko_CopyFontFamilyFrom;
use gecko_bindings::bindings::Gecko_CopyImageValueFrom; use gecko_bindings::bindings::Gecko_CopyImageValueFrom;
use gecko_bindings::bindings::Gecko_CopyListStyleImageFrom; use gecko_bindings::bindings::Gecko_CopyListStyleImageFrom;
@ -28,6 +29,8 @@ use gecko_bindings::bindings::Gecko_EnsureImageLayersLength;
use gecko_bindings::bindings::Gecko_FontFamilyList_AppendGeneric; use gecko_bindings::bindings::Gecko_FontFamilyList_AppendGeneric;
use gecko_bindings::bindings::Gecko_FontFamilyList_AppendNamed; use gecko_bindings::bindings::Gecko_FontFamilyList_AppendNamed;
use gecko_bindings::bindings::Gecko_FontFamilyList_Clear; use gecko_bindings::bindings::Gecko_FontFamilyList_Clear;
use gecko_bindings::bindings::Gecko_SetCursorArrayLength;
use gecko_bindings::bindings::Gecko_SetCursorImage;
use gecko_bindings::bindings::Gecko_SetListStyleImage; use gecko_bindings::bindings::Gecko_SetListStyleImage;
use gecko_bindings::bindings::Gecko_SetListStyleImageNone; use gecko_bindings::bindings::Gecko_SetListStyleImageNone;
use gecko_bindings::bindings::Gecko_SetListStyleType; use gecko_bindings::bindings::Gecko_SetListStyleType;
@ -2195,12 +2198,12 @@ clip-path
<%self:impl_trait style_struct_name="Pointing" <%self:impl_trait style_struct_name="Pointing"
skip_longhands="cursor"> skip_longhands="cursor">
pub fn set_cursor(&mut self, v: longhands::cursor::computed_value::T) { pub fn set_cursor(&mut self, v: longhands::cursor::computed_value::T) {
use properties::longhands::cursor::computed_value::T; use properties::longhands::cursor::computed_value::Keyword;
use style_traits::cursor::Cursor; use style_traits::cursor::Cursor;
self.gecko.mCursor = match v { self.gecko.mCursor = match v.keyword {
T::AutoCursor => structs::NS_STYLE_CURSOR_AUTO, Keyword::AutoCursor => structs::NS_STYLE_CURSOR_AUTO,
T::SpecifiedCursor(cursor) => match cursor { Keyword::SpecifiedCursor(cursor) => match cursor {
Cursor::None => structs::NS_STYLE_CURSOR_NONE, Cursor::None => structs::NS_STYLE_CURSOR_NONE,
Cursor::Default => structs::NS_STYLE_CURSOR_DEFAULT, Cursor::Default => structs::NS_STYLE_CURSOR_DEFAULT,
Cursor::Pointer => structs::NS_STYLE_CURSOR_POINTER, Cursor::Pointer => structs::NS_STYLE_CURSOR_POINTER,
@ -2238,9 +2241,34 @@ clip-path
Cursor::ZoomOut => structs::NS_STYLE_CURSOR_ZOOM_OUT, Cursor::ZoomOut => structs::NS_STYLE_CURSOR_ZOOM_OUT,
} }
} as u8; } as u8;
unsafe {
Gecko_SetCursorArrayLength(&mut self.gecko, v.images.len());
}
for i in 0..v.images.len() {
let image = &v.images[i];
let extra_data = image.url.extra_data();
let (ptr, len) = image.url.as_slice_components();
unsafe {
Gecko_SetCursorImage(&mut self.gecko.mCursorImages[i],
ptr, len as u32,
extra_data.base.get(),
extra_data.referrer.get(),
extra_data.principal.get());
}
// We don't need to record this struct as uncacheable, like when setting
// background-image to a url() value, since only properties in reset structs
// are re-used from the applicable declaration cache, and the Pointing struct
// is an inherited struct.
}
} }
${impl_simple_copy('cursor', 'mCursor')} pub fn copy_cursor_from(&mut self, other: &Self) {
self.gecko.mCursor = other.gecko.mCursor;
unsafe {
Gecko_CopyCursorArrayFrom(&mut self.gecko, &other.gecko);
}
}
</%self:impl_trait> </%self:impl_trait>
<%self:impl_trait style_struct_name="Column" <%self:impl_trait style_struct_name="Column"

Просмотреть файл

@ -10,6 +10,7 @@
pub use self::computed_value::T as SpecifiedValue; pub use self::computed_value::T as SpecifiedValue;
use values::NoViewportPercentage; use values::NoViewportPercentage;
use values::computed::ComputedValueAsSpecified; use values::computed::ComputedValueAsSpecified;
use values::specified::url::SpecifiedUrl;
impl ComputedValueAsSpecified for SpecifiedValue {} impl ComputedValueAsSpecified for SpecifiedValue {}
impl NoViewportPercentage for SpecifiedValue {} impl NoViewportPercentage for SpecifiedValue {}
@ -18,39 +19,128 @@
use std::fmt; use std::fmt;
use style_traits::cursor::Cursor; use style_traits::cursor::Cursor;
use style_traits::ToCss; use style_traits::ToCss;
use values::specified::url::SpecifiedUrl;
#[derive(Clone, PartialEq, Eq, Copy, Debug)] #[derive(Clone, PartialEq, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum T { pub enum Keyword {
AutoCursor, AutoCursor,
SpecifiedCursor(Cursor), SpecifiedCursor(Cursor),
} }
impl ToCss for T { #[cfg(not(feature = "gecko"))]
pub type T = Keyword;
#[cfg(feature = "gecko")]
#[derive(Clone, PartialEq, Debug)]
pub struct Image {
pub url: SpecifiedUrl,
pub hotspot: Option<(f32, f32)>,
}
#[cfg(feature = "gecko")]
#[derive(Clone, PartialEq, Debug)]
pub struct T {
pub images: Vec<Image>,
pub keyword: Keyword,
}
impl ToCss for Keyword {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self { match *self {
T::AutoCursor => dest.write_str("auto"), Keyword::AutoCursor => dest.write_str("auto"),
T::SpecifiedCursor(c) => c.to_css(dest), Keyword::SpecifiedCursor(c) => c.to_css(dest),
}
} }
} }
} }
#[cfg(feature = "gecko")]
impl ToCss for Image {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
try!(self.url.to_css(dest));
if let Some((x, y)) = self.hotspot {
try!(dest.write_str(" "));
try!(x.to_css(dest));
try!(dest.write_str(" "));
try!(y.to_css(dest));
}
Ok(())
}
}
#[cfg(feature = "gecko")]
impl ToCss for T {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
for url in &self.images {
try!(url.to_css(dest));
try!(dest.write_str(", "));
}
self.keyword.to_css(dest)
}
}
}
#[cfg(not(feature = "gecko"))]
#[inline] #[inline]
pub fn get_initial_value() -> computed_value::T { pub fn get_initial_value() -> computed_value::T {
computed_value::T::AutoCursor computed_value::Keyword::AutoCursor
} }
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
#[cfg(feature = "gecko")]
#[inline]
pub fn get_initial_value() -> computed_value::T {
computed_value::T {
images: vec![],
keyword: computed_value::Keyword::AutoCursor
}
}
impl Parse for computed_value::Keyword {
fn parse(input: &mut Parser) -> Result<computed_value::Keyword, ()> {
use std::ascii::AsciiExt; use std::ascii::AsciiExt;
use style_traits::cursor::Cursor; use style_traits::cursor::Cursor;
let ident = try!(input.expect_ident()); let ident = try!(input.expect_ident());
if ident.eq_ignore_ascii_case("auto") { if ident.eq_ignore_ascii_case("auto") {
Ok(SpecifiedValue::AutoCursor) Ok(computed_value::Keyword::AutoCursor)
} else { } else {
Cursor::from_css_keyword(&ident) Cursor::from_css_keyword(&ident).map(computed_value::Keyword::SpecifiedCursor)
.map(SpecifiedValue::SpecifiedCursor)
} }
} }
}
#[cfg(feature = "gecko")]
fn parse_image(context: &ParserContext, input: &mut Parser) -> Result<computed_value::Image, ()> {
Ok(computed_value::Image {
url: try!(SpecifiedUrl::parse(context, input)),
hotspot: match input.try(|input| input.expect_number()) {
Ok(number) => Some((number, try!(input.expect_number()))),
Err(()) => None,
},
})
}
#[cfg(not(feature = "gecko"))]
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
computed_value::Keyword::parse(input)
}
/// cursor: [<url> [<number> <number>]?]# [auto | default | ...]
#[cfg(feature = "gecko")]
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
let mut images = vec![];
loop {
match input.try(|input| parse_image(context, input)) {
Ok(image) => images.push(image),
Err(()) => break,
}
try!(input.expect_comma());
}
Ok(computed_value::T {
images: images,
keyword: try!(computed_value::Keyword::parse(input)),
})
}
</%helpers:longhand> </%helpers:longhand>
// NB: `pointer-events: auto` (and use of `pointer-events` in anything that isn't SVG, in fact) // NB: `pointer-events: auto` (and use of `pointer-events` in anything that isn't SVG, in fact)