зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
b2160ed2cf
Коммит
17186e2c2f
|
@ -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"),
|
||||
|
|
Загрузка…
Ссылка в новой задаче