Bug 596094 - fix a race condition w/ipc disabled in focus related event handling...
[mozilla-central.git] / layout / style / nsMediaFeatures.cpp
blobf055a0286480fec96d3812a2dc53a4009dca4b74
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
13 * License.
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.
21 * Contributor(s):
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
64 #ifdef XP_WIN
65 struct WindowsThemeName {
66 nsILookAndFeel::WindowsThemeIdentifier id;
67 const wchar_t* name;
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" }
80 #endif
82 // A helper for four features below
83 static nsSize
84 GetSize(nsPresContext* aPresContext)
86 nsSize size;
87 if (aPresContext->IsRootPaginatedDocument())
88 // We want the page size, including unprintable areas and margins.
89 size = aPresContext->GetPageSize();
90 else
91 size = aPresContext->GetVisibleArea().Size();
92 return size;
95 static nsresult
96 GetWidth(nsPresContext* aPresContext, const nsMediaFeature*,
97 nsCSSValue& aResult)
99 nsSize size = GetSize(aPresContext);
100 float pixelWidth = aPresContext->AppUnitsToFloatCSSPixels(size.width);
101 aResult.SetFloatValue(pixelWidth, eCSSUnit_Pixel);
102 return NS_OK;
105 static nsresult
106 GetHeight(nsPresContext* aPresContext, const nsMediaFeature*,
107 nsCSSValue& aResult)
109 nsSize size = GetSize(aPresContext);
110 float pixelHeight = aPresContext->AppUnitsToFloatCSSPixels(size.height);
111 aResult.SetFloatValue(pixelHeight, eCSSUnit_Pixel);
112 return NS_OK;
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
122 // *anyway*.
123 return aPresContext->DeviceContext();
126 // A helper for three features below.
127 static nsSize
128 GetDeviceSize(nsPresContext* aPresContext)
130 nsSize size;
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();
136 else
137 GetDeviceContextFor(aPresContext)->
138 GetDeviceSurfaceDimensions(size.width, size.height);
139 return size;
142 static nsresult
143 GetDeviceWidth(nsPresContext* aPresContext, const nsMediaFeature*,
144 nsCSSValue& aResult)
146 nsSize size = GetDeviceSize(aPresContext);
147 float pixelWidth = aPresContext->AppUnitsToFloatCSSPixels(size.width);
148 aResult.SetFloatValue(pixelWidth, eCSSUnit_Pixel);
149 return NS_OK;
152 static nsresult
153 GetDeviceHeight(nsPresContext* aPresContext, const nsMediaFeature*,
154 nsCSSValue& aResult)
156 nsSize size = GetDeviceSize(aPresContext);
157 float pixelHeight = aPresContext->AppUnitsToFloatCSSPixels(size.height);
158 aResult.SetFloatValue(pixelHeight, eCSSUnit_Pixel);
159 return NS_OK;
162 static nsresult
163 GetOrientation(nsPresContext* aPresContext, const nsMediaFeature*,
164 nsCSSValue& aResult)
166 nsSize size = GetSize(aPresContext);
167 PRInt32 orientation;
168 if (size.width > size.height) {
169 orientation = NS_STYLE_ORIENTATION_LANDSCAPE;
170 } else {
171 // Per spec, square viewports should be 'portrait'
172 orientation = NS_STYLE_ORIENTATION_PORTRAIT;
175 aResult.SetIntValue(orientation, eCSSUnit_Enumerated);
176 return NS_OK;
179 // Helper for two features below
180 static nsresult
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);
189 return NS_OK;
192 static nsresult
193 GetAspectRatio(nsPresContext* aPresContext, const nsMediaFeature*,
194 nsCSSValue& aResult)
196 return MakeArray(GetSize(aPresContext), aResult);
199 static nsresult
200 GetDeviceAspectRatio(nsPresContext* aPresContext, const nsMediaFeature*,
201 nsCSSValue& aResult)
203 return MakeArray(GetDeviceSize(aPresContext), aResult);
206 static nsresult
207 GetColor(nsPresContext* aPresContext, const nsMediaFeature*,
208 nsCSSValue& aResult)
210 // FIXME: This implementation is bogus. nsThebesDeviceContext
211 // doesn't provide reliable information (should be fixed in bug
212 // 424386).
213 // FIXME: On a monochrome device, return 0!
214 nsIDeviceContext *dx = GetDeviceContextFor(aPresContext);
215 PRUint32 depth;
216 dx->GetDepth(depth);
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.
220 depth /= 3;
221 aResult.SetIntValue(PRInt32(depth), eCSSUnit_Integer);
222 return NS_OK;
225 static nsresult
226 GetColorIndex(nsPresContext* aPresContext, const nsMediaFeature*,
227 nsCSSValue& aResult)
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);
236 return NS_OK;
239 static nsresult
240 GetMonochrome(nsPresContext* aPresContext, const nsMediaFeature*,
241 nsCSSValue& aResult)
243 // For color devices we should return 0.
244 // FIXME: On a monochrome device, return the actual color depth, not
245 // 0!
246 aResult.SetIntValue(0, eCSSUnit_Integer);
247 return NS_OK;
250 static nsresult
251 GetResolution(nsPresContext* aPresContext, const nsMediaFeature*,
252 nsCSSValue& aResult)
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);
258 return NS_OK;
261 static nsresult
262 GetScan(nsPresContext* aPresContext, const nsMediaFeature*,
263 nsCSSValue& aResult)
265 // Since Gecko doesn't support the 'tv' media type, the 'scan'
266 // feature is never present.
267 aResult.Reset();
268 return NS_OK;
271 static nsresult
272 GetGrid(nsPresContext* aPresContext, const nsMediaFeature*,
273 nsCSSValue& aResult)
275 // Gecko doesn't support grid devices (e.g., ttys), so the 'grid'
276 // feature is always 0.
277 aResult.SetIntValue(0, eCSSUnit_Integer);
278 return NS_OK;
281 static nsresult
282 GetDevicePixelRatio(nsPresContext* aPresContext, const nsMediaFeature*,
283 nsCSSValue& aResult)
285 float ratio = aPresContext->CSSPixelsToDevPixels(1.0f);
286 aResult.SetFloatValue(ratio, eCSSUnit_Number);
287 return NS_OK;
290 static nsresult
291 GetSystemMetric(nsPresContext* aPresContext, const nsMediaFeature* aFeature,
292 nsCSSValue& aResult)
294 NS_ABORT_IF_FALSE(aFeature->mValueType == nsMediaFeature::eBoolInteger,
295 "unexpected type");
296 nsIAtom *metricAtom = *aFeature->mData.mMetric;
297 PRBool hasMetric = nsCSSRuleProcessor::HasSystemMetric(metricAtom);
298 aResult.SetIntValue(hasMetric ? 1 : 0, eCSSUnit_Integer);
299 return NS_OK;
302 static nsresult
303 GetWindowsTheme(nsPresContext* aPresContext, const nsMediaFeature* aFeature,
304 nsCSSValue& aResult)
306 aResult.Reset();
307 #ifdef XP_WIN
308 PRUint8 windowsThemeId =
309 nsCSSRuleProcessor::GetWindowsThemeIdentifier();
311 // Classic mode should fail to match.
312 if (windowsThemeId == nsILookAndFeel::eWindowsTheme_Classic)
313 return NS_OK;
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),
319 eCSSUnit_Ident);
320 break;
323 #endif
324 return NS_OK;
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[] = {
339 &nsGkAtoms::width,
340 nsMediaFeature::eMinMaxAllowed,
341 nsMediaFeature::eLength,
342 { nsnull },
343 GetWidth
346 &nsGkAtoms::height,
347 nsMediaFeature::eMinMaxAllowed,
348 nsMediaFeature::eLength,
349 { nsnull },
350 GetHeight
353 &nsGkAtoms::deviceWidth,
354 nsMediaFeature::eMinMaxAllowed,
355 nsMediaFeature::eLength,
356 { nsnull },
357 GetDeviceWidth
360 &nsGkAtoms::deviceHeight,
361 nsMediaFeature::eMinMaxAllowed,
362 nsMediaFeature::eLength,
363 { nsnull },
364 GetDeviceHeight
367 &nsGkAtoms::orientation,
368 nsMediaFeature::eMinMaxNotAllowed,
369 nsMediaFeature::eEnumerated,
370 { kOrientationKeywords },
371 GetOrientation
374 &nsGkAtoms::aspectRatio,
375 nsMediaFeature::eMinMaxAllowed,
376 nsMediaFeature::eIntRatio,
377 { nsnull },
378 GetAspectRatio
381 &nsGkAtoms::deviceAspectRatio,
382 nsMediaFeature::eMinMaxAllowed,
383 nsMediaFeature::eIntRatio,
384 { nsnull },
385 GetDeviceAspectRatio
388 &nsGkAtoms::color,
389 nsMediaFeature::eMinMaxAllowed,
390 nsMediaFeature::eInteger,
391 { nsnull },
392 GetColor
395 &nsGkAtoms::colorIndex,
396 nsMediaFeature::eMinMaxAllowed,
397 nsMediaFeature::eInteger,
398 { nsnull },
399 GetColorIndex
402 &nsGkAtoms::monochrome,
403 nsMediaFeature::eMinMaxAllowed,
404 nsMediaFeature::eInteger,
405 { nsnull },
406 GetMonochrome
409 &nsGkAtoms::resolution,
410 nsMediaFeature::eMinMaxAllowed,
411 nsMediaFeature::eResolution,
412 { nsnull },
413 GetResolution
416 &nsGkAtoms::scan,
417 nsMediaFeature::eMinMaxNotAllowed,
418 nsMediaFeature::eEnumerated,
419 { kScanKeywords },
420 GetScan
423 &nsGkAtoms::grid,
424 nsMediaFeature::eMinMaxNotAllowed,
425 nsMediaFeature::eBoolInteger,
426 { nsnull },
427 GetGrid
430 // Mozilla extensions
432 &nsGkAtoms::_moz_device_pixel_ratio,
433 nsMediaFeature::eMinMaxAllowed,
434 nsMediaFeature::eFloat,
435 { nsnull },
436 GetDevicePixelRatio
439 &nsGkAtoms::_moz_scrollbar_start_backward,
440 nsMediaFeature::eMinMaxNotAllowed,
441 nsMediaFeature::eBoolInteger,
442 { &nsGkAtoms::scrollbar_start_backward },
443 GetSystemMetric
446 &nsGkAtoms::_moz_scrollbar_start_forward,
447 nsMediaFeature::eMinMaxNotAllowed,
448 nsMediaFeature::eBoolInteger,
449 { &nsGkAtoms::scrollbar_start_forward },
450 GetSystemMetric
453 &nsGkAtoms::_moz_scrollbar_end_backward,
454 nsMediaFeature::eMinMaxNotAllowed,
455 nsMediaFeature::eBoolInteger,
456 { &nsGkAtoms::scrollbar_end_backward },
457 GetSystemMetric
460 &nsGkAtoms::_moz_scrollbar_end_forward,
461 nsMediaFeature::eMinMaxNotAllowed,
462 nsMediaFeature::eBoolInteger,
463 { &nsGkAtoms::scrollbar_end_forward },
464 GetSystemMetric
467 &nsGkAtoms::_moz_scrollbar_thumb_proportional,
468 nsMediaFeature::eMinMaxNotAllowed,
469 nsMediaFeature::eBoolInteger,
470 { &nsGkAtoms::scrollbar_thumb_proportional },
471 GetSystemMetric
474 &nsGkAtoms::_moz_images_in_menus,
475 nsMediaFeature::eMinMaxNotAllowed,
476 nsMediaFeature::eBoolInteger,
477 { &nsGkAtoms::images_in_menus },
478 GetSystemMetric
481 &nsGkAtoms::_moz_images_in_buttons,
482 nsMediaFeature::eMinMaxNotAllowed,
483 nsMediaFeature::eBoolInteger,
484 { &nsGkAtoms::images_in_buttons },
485 GetSystemMetric
488 &nsGkAtoms::_moz_windows_default_theme,
489 nsMediaFeature::eMinMaxNotAllowed,
490 nsMediaFeature::eBoolInteger,
491 { &nsGkAtoms::windows_default_theme },
492 GetSystemMetric
495 &nsGkAtoms::_moz_mac_graphite_theme,
496 nsMediaFeature::eMinMaxNotAllowed,
497 nsMediaFeature::eBoolInteger,
498 { &nsGkAtoms::mac_graphite_theme },
499 GetSystemMetric
502 &nsGkAtoms::_moz_windows_compositor,
503 nsMediaFeature::eMinMaxNotAllowed,
504 nsMediaFeature::eBoolInteger,
505 { &nsGkAtoms::windows_compositor },
506 GetSystemMetric
509 &nsGkAtoms::_moz_windows_classic,
510 nsMediaFeature::eMinMaxNotAllowed,
511 nsMediaFeature::eBoolInteger,
512 { &nsGkAtoms::windows_classic },
513 GetSystemMetric
516 &nsGkAtoms::_moz_touch_enabled,
517 nsMediaFeature::eMinMaxNotAllowed,
518 nsMediaFeature::eBoolInteger,
519 { &nsGkAtoms::touch_enabled },
520 GetSystemMetric
523 &nsGkAtoms::_moz_maemo_classic,
524 nsMediaFeature::eMinMaxNotAllowed,
525 nsMediaFeature::eBoolInteger,
526 { &nsGkAtoms::maemo_classic },
527 GetSystemMetric
530 &nsGkAtoms::_moz_menubar_drag,
531 nsMediaFeature::eMinMaxNotAllowed,
532 nsMediaFeature::eBoolInteger,
533 { &nsGkAtoms::menubar_drag },
534 GetSystemMetric
537 &nsGkAtoms::_moz_windows_theme,
538 nsMediaFeature::eMinMaxNotAllowed,
539 nsMediaFeature::eIdent,
540 { nsnull },
541 GetWindowsTheme
543 // Null-mName terminator:
545 nsnull,
546 nsMediaFeature::eMinMaxAllowed,
547 nsMediaFeature::eInteger,
548 { nsnull },
549 nsnull