Bug 1483111 - Implement any-hover and any-pointer media queries features. r=emilio

Differential Revision: https://phabricator.services.mozilla.com/D3609
This commit is contained in:
Hiroyuki Ikezoe 2018-08-17 20:29:37 +09:00
Родитель b2160ed2cf
Коммит 17186e2c2f
6 изменённых файлов: 170 добавлений и 18 удалений

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

@ -752,6 +752,7 @@ void Gecko_MediaFeatures_GetDeviceSize(nsIDocument*, nscoord* width, nscoord* he
float Gecko_MediaFeatures_GetResolution(nsIDocument*);
bool Gecko_MediaFeatures_PrefersReducedMotion(nsIDocument*);
mozilla::PointerCapabilities Gecko_MediaFeatures_PrimaryPointerCapabilities(nsIDocument*);
mozilla::PointerCapabilities Gecko_MediaFeatures_AllPointerCapabilities(nsIDocument*);
float Gecko_MediaFeatures_GetDevicePixelRatio(nsIDocument*);
bool Gecko_MediaFeatures_HasSystemMetric(nsIDocument*,
nsAtom* metric,

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

@ -262,9 +262,12 @@ Gecko_MediaFeatures_PrefersReducedMotion(nsIDocument* aDocument)
return LookAndFeel::GetInt(LookAndFeel::eIntID_PrefersReducedMotion, 0) == 1;
}
PointerCapabilities
Gecko_MediaFeatures_PrimaryPointerCapabilities(nsIDocument* aDocument)
static PointerCapabilities
GetPointerCapabilities(nsIDocument* aDocument, LookAndFeel::IntID aID)
{
MOZ_ASSERT(aID == LookAndFeel::eIntID_PrimaryPointerCapabilities ||
aID == LookAndFeel::eIntID_AllPointerCapabilities);
// The default value is mouse-type pointer.
const PointerCapabilities kDefaultCapabilities =
PointerCapabilities::Fine | PointerCapabilities::Hover;
@ -274,9 +277,7 @@ Gecko_MediaFeatures_PrimaryPointerCapabilities(nsIDocument* aDocument)
}
int32_t intValue;
nsresult rv =
LookAndFeel::GetInt(LookAndFeel::eIntID_PrimaryPointerCapabilities,
&intValue);
nsresult rv = LookAndFeel::GetInt(aID, &intValue);
if (NS_FAILED(rv)) {
return kDefaultCapabilities;
}
@ -284,6 +285,20 @@ Gecko_MediaFeatures_PrimaryPointerCapabilities(nsIDocument* aDocument)
return static_cast<PointerCapabilities>(intValue);
}
PointerCapabilities
Gecko_MediaFeatures_PrimaryPointerCapabilities(nsIDocument* aDocument)
{
return GetPointerCapabilities(aDocument,
LookAndFeel::eIntID_PrimaryPointerCapabilities);
}
PointerCapabilities
Gecko_MediaFeatures_AllPointerCapabilities(nsIDocument* aDocument)
{
return GetPointerCapabilities(aDocument,
LookAndFeel::eIntID_AllPointerCapabilities);
}
/* static */ void
nsMediaFeatures::InitSystemMetrics()
{

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

@ -257,6 +257,7 @@ skip-if = android_version == '18' #debug-only failure; timed out #Android 4.3 aw
[test_media_queries_dynamic_xbl.html]
[test_media_query_list.html]
[test_media_query_serialization.html]
[test_mq_any_hover_and_any_pointer.html]
[test_mq_hover_and_pointer.html]
[test_moz_device_pixel_ratio.html]
[test_namespace_rule.html]

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

@ -0,0 +1,93 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1483111
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 1035774</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script src="/tests/SimpleTest/AddTask.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1483111">Mozilla Bug 1483111</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
<script>
const NO_POINTER = 0x00;
const COARSE_POINTER = 0x01;
const FINE_POINTER = 0x02;
const HOVER_CAPABLE_POINTER = 0x04;
add_task(async () => {
await SpecialPowers.pushPrefEnv({
set: [ ['privacy.resistFingerprinting', true] ]
});
// When resistFingerprinting is enabled, we pretend that the system has a
// mouse pointer.
ok(!matchMedia("(any-pointer: none)").matches,
"Doesn't match (any-pointer: none)");
ok(!matchMedia("(any-pointer: coarse)").matches,
"Doesn't match (any-pointer: coarse)");
ok(matchMedia("(any-pointer: fine)").matches, "Matches (any-pointer: fine)");
ok(matchMedia("(any-pointer)").matches, "Matches (any-pointer)");
ok(!matchMedia("(any-hover: none)").matches,
"Doesn't match (any-hover: none)");
ok(matchMedia("(any-hover: hover)").matches,
"Matches (any-hover: hover)");
ok(matchMedia("(any-hover)").matches, "Matches (any-hover)");
await SpecialPowers.flushPrefEnv();
});
add_task(async () => {
// No pointer.
await SpecialPowers.pushPrefEnv({
set: [ ['ui.allPointerCapabilities', NO_POINTER] ]
});
ok(matchMedia("(any-pointer: none)").matches, "Matches (any-pointer: none)");
ok(!matchMedia("(any-pointer: coarse)").matches,
"Doesn't match (any-pointer: coarse)");
ok(!matchMedia("(any-pointer: fine)").matches,
"Doesn't match (any-pointer: fine)");
ok(!matchMedia("(any-pointer)").matches, "Matches (any-pointer)");
ok(matchMedia("(any-hover: none)").matches, "Matches (any-hover: none)");
ok(!matchMedia("(any-hover: hover)").matches,
"Doesn't match (any-hover: hover)");
ok(!matchMedia("(any-hover)").matches, "Doesn't match (any-hover)");
});
add_task(async () => {
// Mouse type pointer and touchscreen
await SpecialPowers.pushPrefEnv({
set: [ ['ui.allPointerCapabilities',
FINE_POINTER | COARSE_POINTER | HOVER_CAPABLE_POINTER] ]
});
ok(!matchMedia("(any-pointer: none)").matches,
"Doesn't match (any-pointer: none)");
ok(matchMedia("(any-pointer: coarse)").matches,
"Matches (any-pointer: coarse)");
ok(matchMedia("(any-pointer: fine)").matches, "Matches (any-pointer: fine)");
ok(matchMedia("(any-pointer)").matches, "Matches (any-pointer)");
ok(!matchMedia("(any-hover: none)").matches,
"Doesn't match (any-hover: none)");
ok(matchMedia("(any-hover: hover)").matches,
"Matches (any-hover: hover)");
ok(matchMedia("(any-hover)").matches, "Matches (any-hover)");
});
</script>
</body>
</html>

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

@ -310,6 +310,18 @@ bitflags! {
}
}
fn primary_pointer_capabilities(device: &Device) -> PointerCapabilities {
PointerCapabilities::from_bits_truncate(
unsafe { bindings::Gecko_MediaFeatures_PrimaryPointerCapabilities(device.document()) }
)
}
fn all_pointer_capabilities(device: &Device) -> PointerCapabilities {
PointerCapabilities::from_bits_truncate(
unsafe { bindings::Gecko_MediaFeatures_AllPointerCapabilities(device.document()) }
)
}
#[derive(Debug, Copy, Clone, FromPrimitive, ToCss, Parse)]
#[repr(u8)]
enum Pointer {
@ -318,15 +330,10 @@ enum Pointer {
Fine,
}
fn primary_pointer_capabilities(device: &Device) -> PointerCapabilities {
PointerCapabilities::from_bits_truncate(
unsafe { bindings::Gecko_MediaFeatures_PrimaryPointerCapabilities(device.document()) }
)
}
/// https://drafts.csswg.org/mediaqueries-4/#pointer
fn eval_pointer(device: &Device, query_value: Option<Pointer>) -> bool {
let pointer_capabilities = primary_pointer_capabilities(device);
fn eval_pointer_capabilities(
query_value: Option<Pointer>,
pointer_capabilities: PointerCapabilities,
) -> bool {
let query_value = match query_value {
Some(v) => v,
None => return !pointer_capabilities.is_empty(),
@ -339,6 +346,16 @@ fn eval_pointer(device: &Device, query_value: Option<Pointer>) -> bool {
}
}
/// https://drafts.csswg.org/mediaqueries-4/#pointer
fn eval_pointer(device: &Device, query_value: Option<Pointer>) -> bool {
eval_pointer_capabilities(query_value, primary_pointer_capabilities(device))
}
/// https://drafts.csswg.org/mediaqueries-4/#descdef-media-any-pointer
fn eval_any_pointer(device: &Device, query_value: Option<Pointer>) -> bool {
eval_pointer_capabilities(query_value, all_pointer_capabilities(device))
}
#[derive(Debug, Copy, Clone, FromPrimitive, ToCss, Parse)]
#[repr(u8)]
enum Hover {
@ -346,9 +363,10 @@ enum Hover {
Hover,
}
/// https://drafts.csswg.org/mediaqueries-4/#hover
fn eval_hover(device: &Device, query_value: Option<Hover>) -> bool {
let pointer_capabilities = primary_pointer_capabilities(device);
fn eval_hover_capabilities(
query_value: Option<Hover>,
pointer_capabilities: PointerCapabilities,
) -> bool {
let can_hover = pointer_capabilities.intersects(PointerCapabilities::HOVER);
let query_value = match query_value {
Some(v) => v,
@ -361,6 +379,16 @@ fn eval_hover(device: &Device, query_value: Option<Hover>) -> bool {
}
}
/// https://drafts.csswg.org/mediaqueries-4/#hover
fn eval_hover(device: &Device, query_value: Option<Hover>) -> bool {
eval_hover_capabilities(query_value, primary_pointer_capabilities(device))
}
/// https://drafts.csswg.org/mediaqueries-4/#descdef-media-any-hover
fn eval_any_hover(device: &Device, query_value: Option<Hover>) -> bool {
eval_hover_capabilities(query_value, all_pointer_capabilities(device))
}
fn eval_moz_is_glyph(
device: &Device,
query_value: Option<bool>,
@ -451,7 +479,7 @@ lazy_static! {
/// to support new types in these entries and (2) ensuring that either
/// nsPresContext::MediaFeatureValuesChanged is called when the value that
/// would be returned by the evaluator function could change.
pub static ref MEDIA_FEATURES: [MediaFeatureDescription; 45] = [
pub static ref MEDIA_FEATURES: [MediaFeatureDescription; 47] = [
feature!(
atom!("width"),
AllowsRanges::Yes,
@ -576,12 +604,24 @@ lazy_static! {
keyword_evaluator!(eval_pointer, Pointer),
ParsingRequirements::empty(),
),
feature!(
atom!("any-pointer"),
AllowsRanges::No,
keyword_evaluator!(eval_any_pointer, Pointer),
ParsingRequirements::empty(),
),
feature!(
atom!("hover"),
AllowsRanges::No,
keyword_evaluator!(eval_hover, Hover),
ParsingRequirements::empty(),
),
feature!(
atom!("any-hover"),
AllowsRanges::No,
keyword_evaluator!(eval_any_hover, Hover),
ParsingRequirements::empty(),
),
// Internal -moz-is-glyph media feature: applies only inside SVG glyphs.
// Internal because it is really only useful in the user agent anyway

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

@ -89,6 +89,8 @@ STATIC_ATOMS = [
Atom("anonid", "anonid"),
Atom("anonlocation", "anonlocation"),
Atom("any", "any"),
Atom("any_hover", "any-hover"),
Atom("any_pointer", "any-pointer"),
Atom("applet", "applet"),
Atom("applyImports", "apply-imports"),
Atom("applyTemplates", "apply-templates"),