mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
Support cursor property url() values in stylo. r=manishearth
MozReview-Commit-ID: 6herzaXUz4i
This commit is contained in:
parent
c6be1a8995
commit
830cc88283
3 changed files with 140 additions and 22 deletions
|
@ -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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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, ()> {
|
|
||||||
use std::ascii::AsciiExt;
|
#[cfg(feature = "gecko")]
|
||||||
use style_traits::cursor::Cursor;
|
#[inline]
|
||||||
let ident = try!(input.expect_ident());
|
pub fn get_initial_value() -> computed_value::T {
|
||||||
if ident.eq_ignore_ascii_case("auto") {
|
computed_value::T {
|
||||||
Ok(SpecifiedValue::AutoCursor)
|
images: vec![],
|
||||||
} else {
|
keyword: computed_value::Keyword::AutoCursor
|
||||||
Cursor::from_css_keyword(&ident)
|
|
||||||
.map(SpecifiedValue::SpecifiedCursor)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Parse for computed_value::Keyword {
|
||||||
|
fn parse(input: &mut Parser) -> Result<computed_value::Keyword, ()> {
|
||||||
|
use std::ascii::AsciiExt;
|
||||||
|
use style_traits::cursor::Cursor;
|
||||||
|
let ident = try!(input.expect_ident());
|
||||||
|
if ident.eq_ignore_ascii_case("auto") {
|
||||||
|
Ok(computed_value::Keyword::AutoCursor)
|
||||||
|
} else {
|
||||||
|
Cursor::from_css_keyword(&ident).map(computed_value::Keyword::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)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue