Bumping manifests a=b2g-bump
[gecko.git] / layout / style / nsMediaFeatures.cpp
blob63d597cd27080f9847700649a9e270198d028774
1 /* vim: set shiftwidth=4 tabstop=8 autoindent cindent expandtab: */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 /* the features that media queries can test */
8 #include "nsMediaFeatures.h"
9 #include "nsGkAtoms.h"
10 #include "nsCSSKeywords.h"
11 #include "nsStyleConsts.h"
12 #include "nsPresContext.h"
13 #include "nsCSSValue.h"
14 #ifdef XP_WIN
15 #include "mozilla/LookAndFeel.h"
16 #endif
17 #include "nsCSSRuleProcessor.h"
18 #include "nsDeviceContext.h"
19 #include "nsIDocument.h"
21 using namespace mozilla;
23 static const nsCSSProps::KTableValue kOrientationKeywords[] = {
24 eCSSKeyword_portrait, NS_STYLE_ORIENTATION_PORTRAIT,
25 eCSSKeyword_landscape, NS_STYLE_ORIENTATION_LANDSCAPE,
26 eCSSKeyword_UNKNOWN, -1
29 static const nsCSSProps::KTableValue kScanKeywords[] = {
30 eCSSKeyword_progressive, NS_STYLE_SCAN_PROGRESSIVE,
31 eCSSKeyword_interlace, NS_STYLE_SCAN_INTERLACE,
32 eCSSKeyword_UNKNOWN, -1
35 #ifdef XP_WIN
36 struct WindowsThemeName {
37 LookAndFeel::WindowsTheme id;
38 const wchar_t* name;
41 // Windows theme identities used in the -moz-windows-theme media query.
42 const WindowsThemeName themeStrings[] = {
43 { LookAndFeel::eWindowsTheme_Aero, L"aero" },
44 { LookAndFeel::eWindowsTheme_AeroLite, L"aero-lite" },
45 { LookAndFeel::eWindowsTheme_LunaBlue, L"luna-blue" },
46 { LookAndFeel::eWindowsTheme_LunaOlive, L"luna-olive" },
47 { LookAndFeel::eWindowsTheme_LunaSilver, L"luna-silver" },
48 { LookAndFeel::eWindowsTheme_Royale, L"royale" },
49 { LookAndFeel::eWindowsTheme_Zune, L"zune" },
50 { LookAndFeel::eWindowsTheme_Generic, L"generic" }
53 struct OperatingSystemVersionInfo {
54 LookAndFeel::OperatingSystemVersion id;
55 const wchar_t* name;
58 // Os version identities used in the -moz-os-version media query.
59 const OperatingSystemVersionInfo osVersionStrings[] = {
60 { LookAndFeel::eOperatingSystemVersion_WindowsXP, L"windows-xp" },
61 { LookAndFeel::eOperatingSystemVersion_WindowsVista, L"windows-vista" },
62 { LookAndFeel::eOperatingSystemVersion_Windows7, L"windows-win7" },
63 { LookAndFeel::eOperatingSystemVersion_Windows8, L"windows-win8" },
65 #endif
67 // A helper for four features below
68 static nsSize
69 GetSize(nsPresContext* aPresContext)
71 nsSize size;
72 if (aPresContext->IsRootPaginatedDocument())
73 // We want the page size, including unprintable areas and margins.
74 size = aPresContext->GetPageSize();
75 else
76 size = aPresContext->GetVisibleArea().Size();
77 return size;
80 static nsresult
81 GetWidth(nsPresContext* aPresContext, const nsMediaFeature*,
82 nsCSSValue& aResult)
84 nsSize size = GetSize(aPresContext);
85 float pixelWidth = aPresContext->AppUnitsToFloatCSSPixels(size.width);
86 aResult.SetFloatValue(pixelWidth, eCSSUnit_Pixel);
87 return NS_OK;
90 static nsresult
91 GetHeight(nsPresContext* aPresContext, const nsMediaFeature*,
92 nsCSSValue& aResult)
94 nsSize size = GetSize(aPresContext);
95 float pixelHeight = aPresContext->AppUnitsToFloatCSSPixels(size.height);
96 aResult.SetFloatValue(pixelHeight, eCSSUnit_Pixel);
97 return NS_OK;
100 inline static nsDeviceContext*
101 GetDeviceContextFor(nsPresContext* aPresContext)
103 // It would be nice to call
104 // nsLayoutUtils::GetDeviceContextForScreenInfo here, except for two
105 // things: (1) it can flush, and flushing is bad here, and (2) it
106 // doesn't really get us consistency in multi-monitor situations
107 // *anyway*.
108 return aPresContext->DeviceContext();
111 // A helper for three features below.
112 static nsSize
113 GetDeviceSize(nsPresContext* aPresContext)
115 nsSize size;
117 if (aPresContext->IsDeviceSizePageSize()) {
118 size = GetSize(aPresContext);
119 } else if (aPresContext->IsRootPaginatedDocument()) {
120 // We want the page size, including unprintable areas and margins.
121 // XXX The spec actually says we want the "page sheet size", but
122 // how is that different?
123 size = aPresContext->GetPageSize();
124 } else {
125 GetDeviceContextFor(aPresContext)->
126 GetDeviceSurfaceDimensions(size.width, size.height);
128 return size;
131 static nsresult
132 GetDeviceWidth(nsPresContext* aPresContext, const nsMediaFeature*,
133 nsCSSValue& aResult)
135 nsSize size = GetDeviceSize(aPresContext);
136 float pixelWidth = aPresContext->AppUnitsToFloatCSSPixels(size.width);
137 aResult.SetFloatValue(pixelWidth, eCSSUnit_Pixel);
138 return NS_OK;
141 static nsresult
142 GetDeviceHeight(nsPresContext* aPresContext, const nsMediaFeature*,
143 nsCSSValue& aResult)
145 nsSize size = GetDeviceSize(aPresContext);
146 float pixelHeight = aPresContext->AppUnitsToFloatCSSPixels(size.height);
147 aResult.SetFloatValue(pixelHeight, eCSSUnit_Pixel);
148 return NS_OK;
151 static nsresult
152 GetOrientation(nsPresContext* aPresContext, const nsMediaFeature*,
153 nsCSSValue& aResult)
155 nsSize size = GetSize(aPresContext);
156 int32_t orientation;
157 if (size.width > size.height) {
158 orientation = NS_STYLE_ORIENTATION_LANDSCAPE;
159 } else {
160 // Per spec, square viewports should be 'portrait'
161 orientation = NS_STYLE_ORIENTATION_PORTRAIT;
164 aResult.SetIntValue(orientation, eCSSUnit_Enumerated);
165 return NS_OK;
168 static nsresult
169 GetDeviceOrientation(nsPresContext* aPresContext, const nsMediaFeature*,
170 nsCSSValue& aResult)
172 nsSize size = GetDeviceSize(aPresContext);
173 int32_t orientation;
174 if (size.width > size.height) {
175 orientation = NS_STYLE_ORIENTATION_LANDSCAPE;
176 } else {
177 // Per spec, square viewports should be 'portrait'
178 orientation = NS_STYLE_ORIENTATION_PORTRAIT;
181 aResult.SetIntValue(orientation, eCSSUnit_Enumerated);
182 return NS_OK;
185 static nsresult
186 GetIsResourceDocument(nsPresContext* aPresContext, const nsMediaFeature*,
187 nsCSSValue& aResult)
189 nsIDocument* doc = aPresContext->Document();
190 aResult.SetIntValue(doc && doc->IsResourceDoc() ? 1 : 0, eCSSUnit_Integer);
191 return NS_OK;
194 // Helper for two features below
195 static nsresult
196 MakeArray(const nsSize& aSize, nsCSSValue& aResult)
198 nsRefPtr<nsCSSValue::Array> a = nsCSSValue::Array::Create(2);
200 a->Item(0).SetIntValue(aSize.width, eCSSUnit_Integer);
201 a->Item(1).SetIntValue(aSize.height, eCSSUnit_Integer);
203 aResult.SetArrayValue(a, eCSSUnit_Array);
204 return NS_OK;
207 static nsresult
208 GetAspectRatio(nsPresContext* aPresContext, const nsMediaFeature*,
209 nsCSSValue& aResult)
211 return MakeArray(GetSize(aPresContext), aResult);
214 static nsresult
215 GetDeviceAspectRatio(nsPresContext* aPresContext, const nsMediaFeature*,
216 nsCSSValue& aResult)
218 return MakeArray(GetDeviceSize(aPresContext), aResult);
221 static nsresult
222 GetColor(nsPresContext* aPresContext, const nsMediaFeature*,
223 nsCSSValue& aResult)
225 // FIXME: This implementation is bogus. nsDeviceContext
226 // doesn't provide reliable information (should be fixed in bug
227 // 424386).
228 // FIXME: On a monochrome device, return 0!
229 nsDeviceContext *dx = GetDeviceContextFor(aPresContext);
230 uint32_t depth;
231 dx->GetDepth(depth);
232 // The spec says to use bits *per color component*, so divide by 3,
233 // and round down, since the spec says to use the smallest when the
234 // color components differ.
235 depth /= 3;
236 aResult.SetIntValue(int32_t(depth), eCSSUnit_Integer);
237 return NS_OK;
240 static nsresult
241 GetColorIndex(nsPresContext* aPresContext, const nsMediaFeature*,
242 nsCSSValue& aResult)
244 // We should return zero if the device does not use a color lookup
245 // table. Stuart says that our handling of displays with 8-bit
246 // color is bad enough that we never change the lookup table to
247 // match what we're trying to display, so perhaps we should always
248 // return zero. Given that there isn't any better information
249 // exposed, we don't have much other choice.
250 aResult.SetIntValue(0, eCSSUnit_Integer);
251 return NS_OK;
254 static nsresult
255 GetMonochrome(nsPresContext* aPresContext, const nsMediaFeature*,
256 nsCSSValue& aResult)
258 // For color devices we should return 0.
259 // FIXME: On a monochrome device, return the actual color depth, not
260 // 0!
261 aResult.SetIntValue(0, eCSSUnit_Integer);
262 return NS_OK;
265 static nsresult
266 GetResolution(nsPresContext* aPresContext, const nsMediaFeature*,
267 nsCSSValue& aResult)
269 // Resolution measures device pixels per CSS (inch/cm/pixel). We
270 // return it in device pixels per CSS inches.
271 float dpi = float(nsPresContext::AppUnitsPerCSSInch()) /
272 float(aPresContext->AppUnitsPerDevPixel());
273 aResult.SetFloatValue(dpi, eCSSUnit_Inch);
274 return NS_OK;
277 static nsresult
278 GetScan(nsPresContext* aPresContext, const nsMediaFeature*,
279 nsCSSValue& aResult)
281 // Since Gecko doesn't support the 'tv' media type, the 'scan'
282 // feature is never present.
283 aResult.Reset();
284 return NS_OK;
287 static nsresult
288 GetGrid(nsPresContext* aPresContext, const nsMediaFeature*,
289 nsCSSValue& aResult)
291 // Gecko doesn't support grid devices (e.g., ttys), so the 'grid'
292 // feature is always 0.
293 aResult.SetIntValue(0, eCSSUnit_Integer);
294 return NS_OK;
297 static nsresult
298 GetDevicePixelRatio(nsPresContext* aPresContext, const nsMediaFeature*,
299 nsCSSValue& aResult)
301 float ratio = aPresContext->CSSPixelsToDevPixels(1.0f);
302 aResult.SetFloatValue(ratio, eCSSUnit_Number);
303 return NS_OK;
306 static nsresult
307 GetSystemMetric(nsPresContext* aPresContext, const nsMediaFeature* aFeature,
308 nsCSSValue& aResult)
310 NS_ABORT_IF_FALSE(aFeature->mValueType == nsMediaFeature::eBoolInteger,
311 "unexpected type");
312 nsIAtom *metricAtom = *aFeature->mData.mMetric;
313 bool hasMetric = nsCSSRuleProcessor::HasSystemMetric(metricAtom);
314 aResult.SetIntValue(hasMetric ? 1 : 0, eCSSUnit_Integer);
315 return NS_OK;
318 static nsresult
319 GetWindowsTheme(nsPresContext* aPresContext, const nsMediaFeature* aFeature,
320 nsCSSValue& aResult)
322 aResult.Reset();
323 #ifdef XP_WIN
324 uint8_t windowsThemeId =
325 nsCSSRuleProcessor::GetWindowsThemeIdentifier();
327 // Classic mode should fail to match.
328 if (windowsThemeId == LookAndFeel::eWindowsTheme_Classic)
329 return NS_OK;
331 // Look up the appropriate theme string
332 for (size_t i = 0; i < ArrayLength(themeStrings); ++i) {
333 if (windowsThemeId == themeStrings[i].id) {
334 aResult.SetStringValue(nsDependentString(themeStrings[i].name),
335 eCSSUnit_Ident);
336 break;
339 #endif
340 return NS_OK;
343 static nsresult
344 GetOperatinSystemVersion(nsPresContext* aPresContext, const nsMediaFeature* aFeature,
345 nsCSSValue& aResult)
347 aResult.Reset();
348 #ifdef XP_WIN
349 int32_t metricResult;
350 if (NS_SUCCEEDED(
351 LookAndFeel::GetInt(LookAndFeel::eIntID_OperatingSystemVersionIdentifier,
352 &metricResult))) {
353 for (size_t i = 0; i < ArrayLength(osVersionStrings); ++i) {
354 if (metricResult == osVersionStrings[i].id) {
355 aResult.SetStringValue(nsDependentString(osVersionStrings[i].name),
356 eCSSUnit_Ident);
357 break;
361 #endif
362 return NS_OK;
365 static nsresult
366 GetIsGlyph(nsPresContext* aPresContext, const nsMediaFeature* aFeature,
367 nsCSSValue& aResult)
369 aResult.SetIntValue(aPresContext->IsGlyph() ? 1 : 0, eCSSUnit_Integer);
370 return NS_OK;
374 * Adding new media features requires (1) adding the new feature to this
375 * array, with appropriate entries (and potentially any new code needed
376 * to support new types in these entries and (2) ensuring that either
377 * nsPresContext::MediaFeatureValuesChanged or
378 * nsPresContext::PostMediaFeatureValuesChangedEvent is called when the
379 * value that would be returned by the entry's mGetter changes.
382 /* static */ const nsMediaFeature
383 nsMediaFeatures::features[] = {
385 &nsGkAtoms::width,
386 nsMediaFeature::eMinMaxAllowed,
387 nsMediaFeature::eLength,
388 { nullptr },
389 GetWidth
392 &nsGkAtoms::height,
393 nsMediaFeature::eMinMaxAllowed,
394 nsMediaFeature::eLength,
395 { nullptr },
396 GetHeight
399 &nsGkAtoms::deviceWidth,
400 nsMediaFeature::eMinMaxAllowed,
401 nsMediaFeature::eLength,
402 { nullptr },
403 GetDeviceWidth
406 &nsGkAtoms::deviceHeight,
407 nsMediaFeature::eMinMaxAllowed,
408 nsMediaFeature::eLength,
409 { nullptr },
410 GetDeviceHeight
413 &nsGkAtoms::orientation,
414 nsMediaFeature::eMinMaxNotAllowed,
415 nsMediaFeature::eEnumerated,
416 { kOrientationKeywords },
417 GetOrientation
420 &nsGkAtoms::aspectRatio,
421 nsMediaFeature::eMinMaxAllowed,
422 nsMediaFeature::eIntRatio,
423 { nullptr },
424 GetAspectRatio
427 &nsGkAtoms::deviceAspectRatio,
428 nsMediaFeature::eMinMaxAllowed,
429 nsMediaFeature::eIntRatio,
430 { nullptr },
431 GetDeviceAspectRatio
434 &nsGkAtoms::color,
435 nsMediaFeature::eMinMaxAllowed,
436 nsMediaFeature::eInteger,
437 { nullptr },
438 GetColor
441 &nsGkAtoms::colorIndex,
442 nsMediaFeature::eMinMaxAllowed,
443 nsMediaFeature::eInteger,
444 { nullptr },
445 GetColorIndex
448 &nsGkAtoms::monochrome,
449 nsMediaFeature::eMinMaxAllowed,
450 nsMediaFeature::eInteger,
451 { nullptr },
452 GetMonochrome
455 &nsGkAtoms::resolution,
456 nsMediaFeature::eMinMaxAllowed,
457 nsMediaFeature::eResolution,
458 { nullptr },
459 GetResolution
462 &nsGkAtoms::scan,
463 nsMediaFeature::eMinMaxNotAllowed,
464 nsMediaFeature::eEnumerated,
465 { kScanKeywords },
466 GetScan
469 &nsGkAtoms::grid,
470 nsMediaFeature::eMinMaxNotAllowed,
471 nsMediaFeature::eBoolInteger,
472 { nullptr },
473 GetGrid
476 // Mozilla extensions
478 &nsGkAtoms::_moz_device_pixel_ratio,
479 nsMediaFeature::eMinMaxAllowed,
480 nsMediaFeature::eFloat,
481 { nullptr },
482 GetDevicePixelRatio
485 &nsGkAtoms::_moz_device_orientation,
486 nsMediaFeature::eMinMaxNotAllowed,
487 nsMediaFeature::eEnumerated,
488 { kOrientationKeywords },
489 GetDeviceOrientation
492 &nsGkAtoms::_moz_is_resource_document,
493 nsMediaFeature::eMinMaxNotAllowed,
494 nsMediaFeature::eBoolInteger,
495 { nullptr },
496 GetIsResourceDocument
499 &nsGkAtoms::_moz_color_picker_available,
500 nsMediaFeature::eMinMaxNotAllowed,
501 nsMediaFeature::eBoolInteger,
502 { &nsGkAtoms::color_picker_available },
503 GetSystemMetric
506 &nsGkAtoms::_moz_scrollbar_start_backward,
507 nsMediaFeature::eMinMaxNotAllowed,
508 nsMediaFeature::eBoolInteger,
509 { &nsGkAtoms::scrollbar_start_backward },
510 GetSystemMetric
513 &nsGkAtoms::_moz_scrollbar_start_forward,
514 nsMediaFeature::eMinMaxNotAllowed,
515 nsMediaFeature::eBoolInteger,
516 { &nsGkAtoms::scrollbar_start_forward },
517 GetSystemMetric
520 &nsGkAtoms::_moz_scrollbar_end_backward,
521 nsMediaFeature::eMinMaxNotAllowed,
522 nsMediaFeature::eBoolInteger,
523 { &nsGkAtoms::scrollbar_end_backward },
524 GetSystemMetric
527 &nsGkAtoms::_moz_scrollbar_end_forward,
528 nsMediaFeature::eMinMaxNotAllowed,
529 nsMediaFeature::eBoolInteger,
530 { &nsGkAtoms::scrollbar_end_forward },
531 GetSystemMetric
534 &nsGkAtoms::_moz_scrollbar_thumb_proportional,
535 nsMediaFeature::eMinMaxNotAllowed,
536 nsMediaFeature::eBoolInteger,
537 { &nsGkAtoms::scrollbar_thumb_proportional },
538 GetSystemMetric
541 &nsGkAtoms::_moz_images_in_menus,
542 nsMediaFeature::eMinMaxNotAllowed,
543 nsMediaFeature::eBoolInteger,
544 { &nsGkAtoms::images_in_menus },
545 GetSystemMetric
548 &nsGkAtoms::_moz_images_in_buttons,
549 nsMediaFeature::eMinMaxNotAllowed,
550 nsMediaFeature::eBoolInteger,
551 { &nsGkAtoms::images_in_buttons },
552 GetSystemMetric
555 &nsGkAtoms::_moz_overlay_scrollbars,
556 nsMediaFeature::eMinMaxNotAllowed,
557 nsMediaFeature::eBoolInteger,
558 { &nsGkAtoms::overlay_scrollbars },
559 GetSystemMetric
562 &nsGkAtoms::_moz_windows_default_theme,
563 nsMediaFeature::eMinMaxNotAllowed,
564 nsMediaFeature::eBoolInteger,
565 { &nsGkAtoms::windows_default_theme },
566 GetSystemMetric
569 &nsGkAtoms::_moz_mac_graphite_theme,
570 nsMediaFeature::eMinMaxNotAllowed,
571 nsMediaFeature::eBoolInteger,
572 { &nsGkAtoms::mac_graphite_theme },
573 GetSystemMetric
576 &nsGkAtoms::_moz_mac_lion_theme,
577 nsMediaFeature::eMinMaxNotAllowed,
578 nsMediaFeature::eBoolInteger,
579 { &nsGkAtoms::mac_lion_theme },
580 GetSystemMetric
583 &nsGkAtoms::_moz_mac_yosemite_theme,
584 nsMediaFeature::eMinMaxNotAllowed,
585 nsMediaFeature::eBoolInteger,
586 { &nsGkAtoms::mac_yosemite_theme },
587 GetSystemMetric
590 &nsGkAtoms::_moz_windows_compositor,
591 nsMediaFeature::eMinMaxNotAllowed,
592 nsMediaFeature::eBoolInteger,
593 { &nsGkAtoms::windows_compositor },
594 GetSystemMetric
597 &nsGkAtoms::_moz_windows_classic,
598 nsMediaFeature::eMinMaxNotAllowed,
599 nsMediaFeature::eBoolInteger,
600 { &nsGkAtoms::windows_classic },
601 GetSystemMetric
604 &nsGkAtoms::_moz_windows_glass,
605 nsMediaFeature::eMinMaxNotAllowed,
606 nsMediaFeature::eBoolInteger,
607 { &nsGkAtoms::windows_glass },
608 GetSystemMetric
611 &nsGkAtoms::_moz_touch_enabled,
612 nsMediaFeature::eMinMaxNotAllowed,
613 nsMediaFeature::eBoolInteger,
614 { &nsGkAtoms::touch_enabled },
615 GetSystemMetric
618 &nsGkAtoms::_moz_menubar_drag,
619 nsMediaFeature::eMinMaxNotAllowed,
620 nsMediaFeature::eBoolInteger,
621 { &nsGkAtoms::menubar_drag },
622 GetSystemMetric
625 &nsGkAtoms::_moz_windows_theme,
626 nsMediaFeature::eMinMaxNotAllowed,
627 nsMediaFeature::eIdent,
628 { nullptr },
629 GetWindowsTheme
632 &nsGkAtoms::_moz_os_version,
633 nsMediaFeature::eMinMaxNotAllowed,
634 nsMediaFeature::eIdent,
635 { nullptr },
636 GetOperatinSystemVersion
640 &nsGkAtoms::_moz_swipe_animation_enabled,
641 nsMediaFeature::eMinMaxNotAllowed,
642 nsMediaFeature::eBoolInteger,
643 { &nsGkAtoms::swipe_animation_enabled },
644 GetSystemMetric
648 &nsGkAtoms::_moz_physical_home_button,
649 nsMediaFeature::eMinMaxNotAllowed,
650 nsMediaFeature::eBoolInteger,
651 { &nsGkAtoms::physical_home_button },
652 GetSystemMetric
655 // Internal -moz-is-glyph media feature: applies only inside SVG glyphs.
656 // Internal because it is really only useful in the user agent anyway
657 // and therefore not worth standardizing.
659 &nsGkAtoms::_moz_is_glyph,
660 nsMediaFeature::eMinMaxNotAllowed,
661 nsMediaFeature::eBoolInteger,
662 { nullptr },
663 GetIsGlyph
665 // Null-mName terminator:
667 nullptr,
668 nsMediaFeature::eMinMaxAllowed,
669 nsMediaFeature::eInteger,
670 { nullptr },
671 nullptr