1 /* vim: set shiftwidth=4 tabstop=8 autoindent cindent expandtab: */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is nsMediaFeatures.
17 * The Initial Developer of the Original Code is the Mozilla Foundation.
18 * Portions created by the Initial Developer are Copyright (C) 2008
19 * the Initial Developer. All Rights Reserved.
22 * L. David Baron <dbaron@dbaron.org>, Mozilla Corporation (original author)
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 /* the features that media queries can test */
40 #include "nsMediaFeatures.h"
41 #include "nsGkAtoms.h"
42 #include "nsCSSKeywords.h"
43 #include "nsStyleConsts.h"
44 #include "nsPresContext.h"
45 #include "nsIDeviceContext.h"
46 #include "nsCSSValue.h"
47 #include "nsIDocShell.h"
48 #include "nsLayoutUtils.h"
49 #include "nsILookAndFeel.h"
50 #include "nsCSSRuleProcessor.h"
52 static const PRInt32 kOrientationKeywords
[] = {
53 eCSSKeyword_portrait
, NS_STYLE_ORIENTATION_PORTRAIT
,
54 eCSSKeyword_landscape
, NS_STYLE_ORIENTATION_LANDSCAPE
,
55 eCSSKeyword_UNKNOWN
, -1
58 static const PRInt32 kScanKeywords
[] = {
59 eCSSKeyword_progressive
, NS_STYLE_SCAN_PROGRESSIVE
,
60 eCSSKeyword_interlace
, NS_STYLE_SCAN_INTERLACE
,
61 eCSSKeyword_UNKNOWN
, -1
65 struct WindowsThemeName
{
66 nsILookAndFeel::WindowsThemeIdentifier id
;
70 // Windows theme identities used in the -moz-windows-theme media query.
71 const WindowsThemeName themeStrings
[] = {
72 { nsILookAndFeel::eWindowsTheme_Aero
, L
"aero" },
73 { nsILookAndFeel::eWindowsTheme_LunaBlue
, L
"luna-blue" },
74 { nsILookAndFeel::eWindowsTheme_LunaOlive
, L
"luna-olive" },
75 { nsILookAndFeel::eWindowsTheme_LunaSilver
, L
"luna-silver" },
76 { nsILookAndFeel::eWindowsTheme_Royale
, L
"royale" },
77 { nsILookAndFeel::eWindowsTheme_Zune
, L
"zune" },
78 { nsILookAndFeel::eWindowsTheme_Generic
, L
"generic" }
82 // A helper for four features below
84 GetSize(nsPresContext
* aPresContext
)
87 if (aPresContext
->IsRootPaginatedDocument())
88 // We want the page size, including unprintable areas and margins.
89 size
= aPresContext
->GetPageSize();
91 size
= aPresContext
->GetVisibleArea().Size();
96 GetWidth(nsPresContext
* aPresContext
, const nsMediaFeature
*,
99 nsSize size
= GetSize(aPresContext
);
100 float pixelWidth
= aPresContext
->AppUnitsToFloatCSSPixels(size
.width
);
101 aResult
.SetFloatValue(pixelWidth
, eCSSUnit_Pixel
);
106 GetHeight(nsPresContext
* aPresContext
, const nsMediaFeature
*,
109 nsSize size
= GetSize(aPresContext
);
110 float pixelHeight
= aPresContext
->AppUnitsToFloatCSSPixels(size
.height
);
111 aResult
.SetFloatValue(pixelHeight
, eCSSUnit_Pixel
);
115 inline static nsIDeviceContext
*
116 GetDeviceContextFor(nsPresContext
* aPresContext
)
118 // It would be nice to call
119 // nsLayoutUtils::GetDeviceContextForScreenInfo here, except for two
120 // things: (1) it can flush, and flushing is bad here, and (2) it
121 // doesn't really get us consistency in multi-monitor situations
123 return aPresContext
->DeviceContext();
126 // A helper for three features below.
128 GetDeviceSize(nsPresContext
* aPresContext
)
131 if (aPresContext
->IsRootPaginatedDocument())
132 // We want the page size, including unprintable areas and margins.
133 // XXX The spec actually says we want the "page sheet size", but
134 // how is that different?
135 size
= aPresContext
->GetPageSize();
137 GetDeviceContextFor(aPresContext
)->
138 GetDeviceSurfaceDimensions(size
.width
, size
.height
);
143 GetDeviceWidth(nsPresContext
* aPresContext
, const nsMediaFeature
*,
146 nsSize size
= GetDeviceSize(aPresContext
);
147 float pixelWidth
= aPresContext
->AppUnitsToFloatCSSPixels(size
.width
);
148 aResult
.SetFloatValue(pixelWidth
, eCSSUnit_Pixel
);
153 GetDeviceHeight(nsPresContext
* aPresContext
, const nsMediaFeature
*,
156 nsSize size
= GetDeviceSize(aPresContext
);
157 float pixelHeight
= aPresContext
->AppUnitsToFloatCSSPixels(size
.height
);
158 aResult
.SetFloatValue(pixelHeight
, eCSSUnit_Pixel
);
163 GetOrientation(nsPresContext
* aPresContext
, const nsMediaFeature
*,
166 nsSize size
= GetSize(aPresContext
);
168 if (size
.width
> size
.height
) {
169 orientation
= NS_STYLE_ORIENTATION_LANDSCAPE
;
171 // Per spec, square viewports should be 'portrait'
172 orientation
= NS_STYLE_ORIENTATION_PORTRAIT
;
175 aResult
.SetIntValue(orientation
, eCSSUnit_Enumerated
);
179 // Helper for two features below
181 MakeArray(const nsSize
& aSize
, nsCSSValue
& aResult
)
183 nsRefPtr
<nsCSSValue::Array
> a
= nsCSSValue::Array::Create(2);
185 a
->Item(0).SetIntValue(aSize
.width
, eCSSUnit_Integer
);
186 a
->Item(1).SetIntValue(aSize
.height
, eCSSUnit_Integer
);
188 aResult
.SetArrayValue(a
, eCSSUnit_Array
);
193 GetAspectRatio(nsPresContext
* aPresContext
, const nsMediaFeature
*,
196 return MakeArray(GetSize(aPresContext
), aResult
);
200 GetDeviceAspectRatio(nsPresContext
* aPresContext
, const nsMediaFeature
*,
203 return MakeArray(GetDeviceSize(aPresContext
), aResult
);
207 GetColor(nsPresContext
* aPresContext
, const nsMediaFeature
*,
210 // FIXME: This implementation is bogus. nsThebesDeviceContext
211 // doesn't provide reliable information (should be fixed in bug
213 // FIXME: On a monochrome device, return 0!
214 nsIDeviceContext
*dx
= GetDeviceContextFor(aPresContext
);
217 // The spec says to use bits *per color component*, so divide by 3,
218 // and round down, since the spec says to use the smallest when the
219 // color components differ.
221 aResult
.SetIntValue(PRInt32(depth
), eCSSUnit_Integer
);
226 GetColorIndex(nsPresContext
* aPresContext
, const nsMediaFeature
*,
229 // We should return zero if the device does not use a color lookup
230 // table. Stuart says that our handling of displays with 8-bit
231 // color is bad enough that we never change the lookup table to
232 // match what we're trying to display, so perhaps we should always
233 // return zero. Given that there isn't any better information
234 // exposed, we don't have much other choice.
235 aResult
.SetIntValue(0, eCSSUnit_Integer
);
240 GetMonochrome(nsPresContext
* aPresContext
, const nsMediaFeature
*,
243 // For color devices we should return 0.
244 // FIXME: On a monochrome device, return the actual color depth, not
246 aResult
.SetIntValue(0, eCSSUnit_Integer
);
251 GetResolution(nsPresContext
* aPresContext
, const nsMediaFeature
*,
254 // Resolution values are in device pixels, not CSS pixels.
255 nsIDeviceContext
*dx
= GetDeviceContextFor(aPresContext
);
256 float dpi
= float(dx
->AppUnitsPerPhysicalInch()) / float(dx
->AppUnitsPerDevPixel());
257 aResult
.SetFloatValue(dpi
, eCSSUnit_Inch
);
262 GetScan(nsPresContext
* aPresContext
, const nsMediaFeature
*,
265 // Since Gecko doesn't support the 'tv' media type, the 'scan'
266 // feature is never present.
272 GetGrid(nsPresContext
* aPresContext
, const nsMediaFeature
*,
275 // Gecko doesn't support grid devices (e.g., ttys), so the 'grid'
276 // feature is always 0.
277 aResult
.SetIntValue(0, eCSSUnit_Integer
);
282 GetDevicePixelRatio(nsPresContext
* aPresContext
, const nsMediaFeature
*,
285 float ratio
= aPresContext
->CSSPixelsToDevPixels(1.0f
);
286 aResult
.SetFloatValue(ratio
, eCSSUnit_Number
);
291 GetSystemMetric(nsPresContext
* aPresContext
, const nsMediaFeature
* aFeature
,
294 NS_ABORT_IF_FALSE(aFeature
->mValueType
== nsMediaFeature::eBoolInteger
,
296 nsIAtom
*metricAtom
= *aFeature
->mData
.mMetric
;
297 PRBool hasMetric
= nsCSSRuleProcessor::HasSystemMetric(metricAtom
);
298 aResult
.SetIntValue(hasMetric
? 1 : 0, eCSSUnit_Integer
);
303 GetWindowsTheme(nsPresContext
* aPresContext
, const nsMediaFeature
* aFeature
,
308 PRUint8 windowsThemeId
=
309 nsCSSRuleProcessor::GetWindowsThemeIdentifier();
311 // Classic mode should fail to match.
312 if (windowsThemeId
== nsILookAndFeel::eWindowsTheme_Classic
)
315 // Look up the appropriate theme string
316 for (size_t i
= 0; i
< NS_ARRAY_LENGTH(themeStrings
); ++i
) {
317 if (windowsThemeId
== themeStrings
[i
].id
) {
318 aResult
.SetStringValue(nsDependentString(themeStrings
[i
].name
),
328 * Adding new media features requires (1) adding the new feature to this
329 * array, with appropriate entries (and potentially any new code needed
330 * to support new types in these entries and (2) ensuring that either
331 * nsPresContext::MediaFeatureValuesChanged or
332 * nsPresContext::PostMediaFeatureValuesChangedEvent is called when the
333 * value that would be returned by the entry's mGetter changes.
336 /* static */ const nsMediaFeature
337 nsMediaFeatures::features
[] = {
340 nsMediaFeature::eMinMaxAllowed
,
341 nsMediaFeature::eLength
,
347 nsMediaFeature::eMinMaxAllowed
,
348 nsMediaFeature::eLength
,
353 &nsGkAtoms::deviceWidth
,
354 nsMediaFeature::eMinMaxAllowed
,
355 nsMediaFeature::eLength
,
360 &nsGkAtoms::deviceHeight
,
361 nsMediaFeature::eMinMaxAllowed
,
362 nsMediaFeature::eLength
,
367 &nsGkAtoms::orientation
,
368 nsMediaFeature::eMinMaxNotAllowed
,
369 nsMediaFeature::eEnumerated
,
370 { kOrientationKeywords
},
374 &nsGkAtoms::aspectRatio
,
375 nsMediaFeature::eMinMaxAllowed
,
376 nsMediaFeature::eIntRatio
,
381 &nsGkAtoms::deviceAspectRatio
,
382 nsMediaFeature::eMinMaxAllowed
,
383 nsMediaFeature::eIntRatio
,
389 nsMediaFeature::eMinMaxAllowed
,
390 nsMediaFeature::eInteger
,
395 &nsGkAtoms::colorIndex
,
396 nsMediaFeature::eMinMaxAllowed
,
397 nsMediaFeature::eInteger
,
402 &nsGkAtoms::monochrome
,
403 nsMediaFeature::eMinMaxAllowed
,
404 nsMediaFeature::eInteger
,
409 &nsGkAtoms::resolution
,
410 nsMediaFeature::eMinMaxAllowed
,
411 nsMediaFeature::eResolution
,
417 nsMediaFeature::eMinMaxNotAllowed
,
418 nsMediaFeature::eEnumerated
,
424 nsMediaFeature::eMinMaxNotAllowed
,
425 nsMediaFeature::eBoolInteger
,
430 // Mozilla extensions
432 &nsGkAtoms::_moz_device_pixel_ratio
,
433 nsMediaFeature::eMinMaxAllowed
,
434 nsMediaFeature::eFloat
,
439 &nsGkAtoms::_moz_scrollbar_start_backward
,
440 nsMediaFeature::eMinMaxNotAllowed
,
441 nsMediaFeature::eBoolInteger
,
442 { &nsGkAtoms::scrollbar_start_backward
},
446 &nsGkAtoms::_moz_scrollbar_start_forward
,
447 nsMediaFeature::eMinMaxNotAllowed
,
448 nsMediaFeature::eBoolInteger
,
449 { &nsGkAtoms::scrollbar_start_forward
},
453 &nsGkAtoms::_moz_scrollbar_end_backward
,
454 nsMediaFeature::eMinMaxNotAllowed
,
455 nsMediaFeature::eBoolInteger
,
456 { &nsGkAtoms::scrollbar_end_backward
},
460 &nsGkAtoms::_moz_scrollbar_end_forward
,
461 nsMediaFeature::eMinMaxNotAllowed
,
462 nsMediaFeature::eBoolInteger
,
463 { &nsGkAtoms::scrollbar_end_forward
},
467 &nsGkAtoms::_moz_scrollbar_thumb_proportional
,
468 nsMediaFeature::eMinMaxNotAllowed
,
469 nsMediaFeature::eBoolInteger
,
470 { &nsGkAtoms::scrollbar_thumb_proportional
},
474 &nsGkAtoms::_moz_images_in_menus
,
475 nsMediaFeature::eMinMaxNotAllowed
,
476 nsMediaFeature::eBoolInteger
,
477 { &nsGkAtoms::images_in_menus
},
481 &nsGkAtoms::_moz_images_in_buttons
,
482 nsMediaFeature::eMinMaxNotAllowed
,
483 nsMediaFeature::eBoolInteger
,
484 { &nsGkAtoms::images_in_buttons
},
488 &nsGkAtoms::_moz_windows_default_theme
,
489 nsMediaFeature::eMinMaxNotAllowed
,
490 nsMediaFeature::eBoolInteger
,
491 { &nsGkAtoms::windows_default_theme
},
495 &nsGkAtoms::_moz_mac_graphite_theme
,
496 nsMediaFeature::eMinMaxNotAllowed
,
497 nsMediaFeature::eBoolInteger
,
498 { &nsGkAtoms::mac_graphite_theme
},
502 &nsGkAtoms::_moz_windows_compositor
,
503 nsMediaFeature::eMinMaxNotAllowed
,
504 nsMediaFeature::eBoolInteger
,
505 { &nsGkAtoms::windows_compositor
},
509 &nsGkAtoms::_moz_windows_classic
,
510 nsMediaFeature::eMinMaxNotAllowed
,
511 nsMediaFeature::eBoolInteger
,
512 { &nsGkAtoms::windows_classic
},
516 &nsGkAtoms::_moz_touch_enabled
,
517 nsMediaFeature::eMinMaxNotAllowed
,
518 nsMediaFeature::eBoolInteger
,
519 { &nsGkAtoms::touch_enabled
},
523 &nsGkAtoms::_moz_maemo_classic
,
524 nsMediaFeature::eMinMaxNotAllowed
,
525 nsMediaFeature::eBoolInteger
,
526 { &nsGkAtoms::maemo_classic
},
530 &nsGkAtoms::_moz_menubar_drag
,
531 nsMediaFeature::eMinMaxNotAllowed
,
532 nsMediaFeature::eBoolInteger
,
533 { &nsGkAtoms::menubar_drag
},
537 &nsGkAtoms::_moz_windows_theme
,
538 nsMediaFeature::eMinMaxNotAllowed
,
539 nsMediaFeature::eIdent
,
543 // Null-mName terminator:
546 nsMediaFeature::eMinMaxAllowed
,
547 nsMediaFeature::eInteger
,