[Mac] Support "inverted-colors" and "monochrome" media feature.
authordino@apple.com <dino@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 20 Oct 2014 19:37:40 +0000 (19:37 +0000)
committerdino@apple.com <dino@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 20 Oct 2014 19:37:40 +0000 (19:37 +0000)
https://bugs.webkit.org/show_bug.cgi?id=137535
<rdar://problem/18586398>

Reviewed by Brent Fulgham.

Source/WebCore:

Add a new media query from CSS Level 4, "inverted-colors", and
implement the Apple backends for the "monochrome" media query.

The platform code went into PlatformScreenMac, which already
had a screenIsMonochrome method. This now calls into Core
Graphics via SPI. I added a screenHasInvertedColors
method which tests for inversion. On iOS, there is public API
for both queries. On Windows, we try to use CoreGraphics.

At the moment neither of these media queries re-evaluate
automatically if the user changes their mode. The page will
need to be reloaded. It is possible to detect a change on iOS,
but not OS X.
https://bugs.webkit.org/show_bug.cgi?id=137868

I decided to not add an ENABLE flag for this, mostly because it
is such an isolated feature and seems very unlikely to be
controversial. I don't expect the syntax to change. (I'm sure
this comment will come back to haunt me.)

Testing this automatically is slightly tricky. We'd need
to expose SPI to invert the user's screen, but then we get
inverted images from our testing which could interfere with concurrent
operations. Instead I've included some tests that exercise
the "false" parts of the media query, with explanations as
to why they would fail if the display is inverted.

Tests: fast/media/mq-inverted-colors.html
       fast/media/mq-monochrome.html

* css/CSSValueKeywords.in: Add the "inverted" keyword for "inverted-colors".
* css/MediaFeatureNames.h: Add the "inverted-colors" feature name.
* css/MediaQueryEvaluator.cpp:
(WebCore::inverted_colorsMediaFeatureEval): Implementation of the new media query.
* css/MediaQueryExp.cpp:
(WebCore::featureWithCSSValueID): The new query takes an id...
(WebCore::featureWithoutValue): ... or no value.
* platform/PlatformScreen.h: Add "screenHasInvertedColors".
* platform/efl/PlatformScreenEfl.cpp:
(WebCore::screenHasInvertedColors): Stub implementation.
* platform/gtk/PlatformScreenGtk.cpp:
(WebCore::screenHasInvertedColors): Ditto.
* platform/ios/PlatformScreenIOS.mm:
(WebCore::screenHasInvertedColors): Call into the platform accessibility API.
(WebCore::screenIsMonochrome): Ditto.
* platform/mac/PlatformScreenMac.mm:
(WebCore::screenIsMonochrome): Call into the CoreGraphics SPI.
(WebCore::screenHasInvertedColors): Call into the CoreGraphics SPI.
* platform/win/PlatformScreenWin.cpp:
(WebCore::screenHasInvertedColors): Call into CoreGraphics if we're using it.

LayoutTests:

Add tests for the new "inverted-colors" media feature, and
another test for the "monochrome" feature. Note that these
tests don't actually exercise the positive values of the
query, since that requires the screen to be changed and would
interfere with concurrent tests.

* fast/media/mq-inverted-colors.html: Added.
* fast/media/mq-monochrome.html: Added.
* fast/media/mq-inverted-colors-expected.html: Added.
* fast/media/mq-monochrome-expected.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@174901 268f45cc-cd09-0410-ab3c-d52691b4dbfc

16 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/media/mq-inverted-colors-expected.html [new file with mode: 0644]
LayoutTests/fast/media/mq-inverted-colors.html [new file with mode: 0644]
LayoutTests/fast/media/mq-monochrome-expected.html [new file with mode: 0644]
LayoutTests/fast/media/mq-monochrome.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/css/CSSValueKeywords.in
Source/WebCore/css/MediaFeatureNames.h
Source/WebCore/css/MediaQueryEvaluator.cpp
Source/WebCore/css/MediaQueryExp.cpp
Source/WebCore/platform/PlatformScreen.h
Source/WebCore/platform/efl/PlatformScreenEfl.cpp
Source/WebCore/platform/gtk/PlatformScreenGtk.cpp
Source/WebCore/platform/ios/PlatformScreenIOS.mm
Source/WebCore/platform/mac/PlatformScreenMac.mm
Source/WebCore/platform/win/PlatformScreenWin.cpp

index 7c3868e..ad6b96d 100644 (file)
@@ -1,3 +1,22 @@
+2014-10-20  Dean Jackson  <dino@apple.com>
+
+        [Mac] Support "inverted-colors" and "monochrome" media feature.
+        https://bugs.webkit.org/show_bug.cgi?id=137535
+        <rdar://problem/18586398>
+
+        Reviewed by Brent Fulgham.
+
+        Add tests for the new "inverted-colors" media feature, and
+        another test for the "monochrome" feature. Note that these
+        tests don't actually exercise the positive values of the
+        query, since that requires the screen to be changed and would
+        interfere with concurrent tests.
+
+        * fast/media/mq-inverted-colors.html: Added.
+        * fast/media/mq-monochrome.html: Added.
+        * fast/media/mq-inverted-colors-expected.html: Added.
+        * fast/media/mq-monochrome-expected.html: Added.
+
 2014-10-20  Alexey Proskuryakov  <ap@apple.com>
 
         Eight transitions tests are very flaky, frequently failing all at once
diff --git a/LayoutTests/fast/media/mq-inverted-colors-expected.html b/LayoutTests/fast/media/mq-inverted-colors-expected.html
new file mode 100644 (file)
index 0000000..0d635c2
--- /dev/null
@@ -0,0 +1,18 @@
+<html>
+<head>
+<title>CSS4 media query test: inverted-colors.</title>
+<style type="text/css">
+#a { color: green; }
+#b { color: black; }
+#c { color: green; }
+#d { color: black; }
+</style>
+</head>
+<body>
+  <p id="a">This text should be inverted black (white) if the screen is inverted. Green otherwise.</p>
+  <p id="b">This text should be inverted green (puplish) if the screen is inverted. Black otherwise.</p>
+  <p id="c">This text should be inverted black (white) if the screen is inverted. Green otherwise.</p>
+  <p id="d">This text should be inverted green (purplish) if the screen is inverted. Black otherwise.</p>
+  <p>Note that the expected results of this test assume a non-inverted display.</p>
+</body>
+</html>
diff --git a/LayoutTests/fast/media/mq-inverted-colors.html b/LayoutTests/fast/media/mq-inverted-colors.html
new file mode 100644 (file)
index 0000000..e40710f
--- /dev/null
@@ -0,0 +1,31 @@
+<html>
+<head>
+<title>CSS4 media query test: inverted-colors.</title>
+<style type="text/css">
+#a { color: green; }
+#b { color: black; }
+#c { color: black; }
+#d { color: black; }
+
+@media (inverted-colors) {
+#a { color: black; }
+#b { color: green; }
+}
+
+@media (inverted-colors: none) {
+#c { color: green; }
+}
+
+@media (inverted-colors: inverted) {
+#d { color: green; }
+}
+</style>
+</head>
+<body>
+  <p id="a">This text should be inverted black (white) if the screen is inverted. Green otherwise.</p>
+  <p id="b">This text should be inverted green (puplish) if the screen is inverted. Black otherwise.</p>
+  <p id="c">This text should be inverted black (white) if the screen is inverted. Green otherwise.</p>
+  <p id="d">This text should be inverted green (purplish) if the screen is inverted. Black otherwise.</p>
+  <p>Note that the expected results of this test assume a non-inverted display.</p>
+</body>
+</html>
diff --git a/LayoutTests/fast/media/mq-monochrome-expected.html b/LayoutTests/fast/media/mq-monochrome-expected.html
new file mode 100644 (file)
index 0000000..e26b08d
--- /dev/null
@@ -0,0 +1,14 @@
+<html>
+<head>
+<title>CSS4 media query test: monochrome.</title>
+<style type="text/css">
+#a { color: black; }
+#b { color: #888; }
+</style>
+</head>
+<body>
+  <p id="a">This text should be middle grey if the screen is monochrome. Black otherwise.</p>
+  <p id="b">This text should be black if the screen is monochrome. Middle grey otherwise.</p>
+  <p>Note that the expected results of this test assume a non-monochrome display.</p>
+</body>
+</html>
diff --git a/LayoutTests/fast/media/mq-monochrome.html b/LayoutTests/fast/media/mq-monochrome.html
new file mode 100644 (file)
index 0000000..c34f528
--- /dev/null
@@ -0,0 +1,20 @@
+<html>
+<head>
+<title>CSS4 media query test: monochrome.</title>
+<style type="text/css">
+#a { color: black; }
+#b { color: #888; }
+
+@media (monochrome) {
+#a { color: #888; }
+#b { color: black; }
+}
+
+</style>
+</head>
+<body>
+  <p id="a">This text should be middle grey if the screen is monochrome. Black otherwise.</p>
+  <p id="b">This text should be black if the screen is monochrome. Middle grey otherwise.</p>
+  <p>Note that the expected results of this test assume a non-monochrome display.</p>
+</body>
+</html>
index f251710..47af988 100644 (file)
@@ -1,3 +1,62 @@
+2014-10-20  Dean Jackson  <dino@apple.com>
+
+        [Mac] Support "inverted-colors" and "monochrome" media feature.
+        https://bugs.webkit.org/show_bug.cgi?id=137535
+        <rdar://problem/18586398>
+
+        Reviewed by Brent Fulgham.
+
+        Add a new media query from CSS Level 4, "inverted-colors", and
+        implement the Apple backends for the "monochrome" media query.
+
+        The platform code went into PlatformScreenMac, which already
+        had a screenIsMonochrome method. This now calls into Core
+        Graphics via SPI. I added a screenHasInvertedColors
+        method which tests for inversion. On iOS, there is public API
+        for both queries. On Windows, we try to use CoreGraphics.
+
+        At the moment neither of these media queries re-evaluate
+        automatically if the user changes their mode. The page will
+        need to be reloaded. It is possible to detect a change on iOS,
+        but not OS X.
+        https://bugs.webkit.org/show_bug.cgi?id=137868
+
+        I decided to not add an ENABLE flag for this, mostly because it
+        is such an isolated feature and seems very unlikely to be
+        controversial. I don't expect the syntax to change. (I'm sure
+        this comment will come back to haunt me.)
+
+        Testing this automatically is slightly tricky. We'd need
+        to expose SPI to invert the user's screen, but then we get
+        inverted images from our testing which could interfere with concurrent
+        operations. Instead I've included some tests that exercise
+        the "false" parts of the media query, with explanations as
+        to why they would fail if the display is inverted.
+
+        Tests: fast/media/mq-inverted-colors.html
+               fast/media/mq-monochrome.html
+
+        * css/CSSValueKeywords.in: Add the "inverted" keyword for "inverted-colors".
+        * css/MediaFeatureNames.h: Add the "inverted-colors" feature name.
+        * css/MediaQueryEvaluator.cpp:
+        (WebCore::inverted_colorsMediaFeatureEval): Implementation of the new media query.
+        * css/MediaQueryExp.cpp:
+        (WebCore::featureWithCSSValueID): The new query takes an id...
+        (WebCore::featureWithoutValue): ... or no value.
+        * platform/PlatformScreen.h: Add "screenHasInvertedColors".
+        * platform/efl/PlatformScreenEfl.cpp:
+        (WebCore::screenHasInvertedColors): Stub implementation.
+        * platform/gtk/PlatformScreenGtk.cpp:
+        (WebCore::screenHasInvertedColors): Ditto.
+        * platform/ios/PlatformScreenIOS.mm:
+        (WebCore::screenHasInvertedColors): Call into the platform accessibility API.
+        (WebCore::screenIsMonochrome): Ditto.
+        * platform/mac/PlatformScreenMac.mm:
+        (WebCore::screenIsMonochrome): Call into the CoreGraphics SPI.
+        (WebCore::screenHasInvertedColors): Call into the CoreGraphics SPI.
+        * platform/win/PlatformScreenWin.cpp:
+        (WebCore::screenHasInvertedColors): Call into CoreGraphics if we're using it.
+
 2014-10-20  Chris Dumez  <cdumez@apple.com>
 
         Use is<>() / downcast<>() for Accessibility objects
index 2bb1f5d..66dfd38 100644 (file)
@@ -455,6 +455,7 @@ hand
 hide
 higher
 invert
+inverted
 -webkit-isolate
 -webkit-isolate-override
 -webkit-plaintext
index 1c9ef00..514790b 100644 (file)
@@ -45,6 +45,7 @@ namespace WebCore {
     macro(device_pixel_ratio, "-webkit-device-pixel-ratio") \
     macro(device_height, "device-height") \
     macro(device_width, "device-width") \
+    macro(inverted_colors, "inverted-colors") \
     macro(max_color, "max-color") \
     macro(max_color_index, "max-color-index") \
     macro(max_aspect_ratio, "max-aspect-ratio") \
index 38ed30b..5bfb41f 100644 (file)
@@ -237,6 +237,17 @@ static bool monochromeMediaFeatureEval(CSSValue* value, const CSSToLengthConvers
     return colorMediaFeatureEval(value, conversionData, frame, op);
 }
 
+static bool inverted_colorsMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData&, Frame*, MediaFeaturePrefix)
+{
+    bool isInverted = screenHasInvertedColors();
+
+    if (!value)
+        return isInverted;
+
+    const CSSValueID id = downcast<CSSPrimitiveValue>(*value).getValueID();
+    return (isInverted && id == CSSValueInverted) || (!isInverted && id == CSSValueNone);
+}
+
 static bool orientationMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData&, Frame* frame, MediaFeaturePrefix)
 {
     FrameView* view = frame->view();
index abb4d40..37bed75 100644 (file)
@@ -47,6 +47,7 @@ static inline bool featureWithCSSValueID(const AtomicString& mediaFeature, const
 #if ENABLE(VIEW_MODE_CSS_MEDIA)
         || mediaFeature == MediaFeatureNames::view_modeMediaFeature
 #endif // ENABLE(VIEW_MODE_CSS_MEDIA)
+        || mediaFeature == MediaFeatureNames::inverted_colorsMediaFeature
         || mediaFeature == MediaFeatureNames::pointerMediaFeature;
 }
 
@@ -146,6 +147,7 @@ static inline bool featureWithoutValue(const AtomicString& mediaFeature)
         || mediaFeature == MediaFeatureNames::transform_3dMediaFeature
         || mediaFeature == MediaFeatureNames::transitionMediaFeature
         || mediaFeature == MediaFeatureNames::animationMediaFeature
+        || mediaFeature == MediaFeatureNames::inverted_colorsMediaFeature
 #if ENABLE(VIEW_MODE_CSS_MEDIA)
         || mediaFeature == MediaFeatureNames::view_modeMediaFeature
 #endif // ENABLE(VIEW_MODE_CSS_MEDIA)
index a8d09a4..e4cae10 100644 (file)
@@ -53,6 +53,8 @@ namespace WebCore {
     int screenDepthPerComponent(Widget*);
     bool screenIsMonochrome(Widget*);
 
+    bool screenHasInvertedColors();
+
     FloatRect screenRect(Widget*);
     FloatRect screenAvailableRect(Widget*);
 
index fdc23b8..4d449f4 100644 (file)
@@ -83,6 +83,11 @@ bool screenIsMonochrome(Widget* widget)
     return screenDepth(widget) < 2;
 }
 
+bool screenHasInvertedColors()
+{
+    return false;
+}
+
 FloatRect screenRect(Widget* widget)
 {
 #ifdef HAVE_ECORE_X
index fec08a5..be2b9c9 100644 (file)
@@ -83,6 +83,10 @@ bool screenIsMonochrome(Widget* widget)
     return screenDepth(widget) < 2;
 }
 
+bool screenHasInvertedColors()
+{
+    return false;
+}
 
 static GdkScreen* getScreen(GtkWidget* widget)
 {
index ef25f24..7389f27 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006 Apple Inc.  All rights reserved.
+ * Copyright (C) 2006, 2014 Apple Inc.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #import "FrameView.h"
 #import "HostWindow.h"
 #import "IntRect.h"
+#import "SoftLinking.h"
 #import "WAKWindow.h"
 #import "WebCoreSystemInterface.h"
 #import "Widget.h"
 #import <MobileGestalt.h>
 
+SOFT_LINK_FRAMEWORK(UIKit)
+SOFT_LINK(UIKit, UIAccessibilityIsGrayscaleEnabled, bool, (void), ())
+SOFT_LINK(UIKit, UIAccessibilityIsInvertColorsEnabled, bool, (void), ())
+
 namespace WebCore {
 
 int screenDepth(Widget*)
@@ -51,7 +56,12 @@ int screenDepthPerComponent(Widget*)
 
 bool screenIsMonochrome(Widget*)
 {
-    return false;
+    return UIAccessibilityIsGrayscaleEnabled();
+}
+
+bool screenHasInvertedColors()
+{
+    return UIAccessibilityIsInvertColorsEnabled();
 }
 
 // These functions scale between screen and page coordinates because JavaScript/DOM operations
index 66fa291..8a43129 100644 (file)
 #import "FrameView.h"
 #import "HostWindow.h"
 
+extern "C" {
+bool CGDisplayUsesInvertedPolarity(void);
+bool CGDisplayUsesForceToGray(void);
+}
+
 namespace WebCore {
 
 static PlatformDisplayID displayIDFromScreen(NSScreen *screen)
@@ -58,10 +63,15 @@ int screenDepthPerComponent(Widget*)
 
 bool screenIsMonochrome(Widget*)
 {
-    return false;
+    return CGDisplayUsesForceToGray();
+}
+
+bool screenHasInvertedColors()
+{
+    return CGDisplayUsesInvertedPolarity();
 }
 
-// These functions scale between screen and page coordinates because JavaScript/DOM operations 
+// These functions scale between screen and page coordinates because JavaScript/DOM operations
 // assume that the screen and the page share the same coordinate system.
 
 static PlatformDisplayID displayFromWidget(Widget* widget)
index dea954f..892db82 100644 (file)
 #include "Page.h"
 #include <windows.h>
 
+#if USE(CG)
+extern "C" {
+bool CGDisplayUsesInvertedPolarity(void);
+}
+#endif
+
 namespace WebCore {
 
 // Returns info for the default monitor if widget is NULL
@@ -84,6 +90,15 @@ bool screenIsMonochrome(Widget* widget)
     return deviceInfo.dmColor == DMCOLOR_MONOCHROME;
 }
 
+bool screenHasInvertedColors()
+{
+#if USE(CG)
+    return CGDisplayUsesInvertedPolarity();
+#else
+    return false;
+#endif
+}
+
 FloatRect screenRect(Widget* widget)
 {
     MONITORINFOEX monitorInfo = monitorInfoForWidget(widget);