Diff
Modified: trunk/LayoutTests/ChangeLog (238569 => 238570)
--- trunk/LayoutTests/ChangeLog 2018-11-27 21:06:52 UTC (rev 238569)
+++ trunk/LayoutTests/ChangeLog 2018-11-27 21:16:07 UTC (rev 238570)
@@ -1,3 +1,16 @@
+2018-11-27 Timothy Hatcher <timo...@apple.com>
+
+ Web Inspector: Add support for forcing color scheme appearance in DOM tree.
+ https://bugs.webkit.org/show_bug.cgi?id=191820
+ rdar://problem/46153172
+
+ Reviewed by Devin Rousso.
+
+ * TestExpectations: Skip dark mode tests on other platforms.
+ * inspector/css/force-page-appearance-expected.txt: Added.
+ * inspector/css/force-page-appearance.html: Added.
+ * platform/mac/TestExpectations: Expect dark mode tests to pass on Mojave and later.
+
2018-11-27 Tim Horton <timothy_hor...@apple.com>
Serialize and deserialize editable image strokes
Modified: trunk/LayoutTests/TestExpectations (238569 => 238570)
--- trunk/LayoutTests/TestExpectations 2018-11-27 21:06:52 UTC (rev 238569)
+++ trunk/LayoutTests/TestExpectations 2018-11-27 21:16:07 UTC (rev 238570)
@@ -74,7 +74,9 @@
fast/xmlhttprequest/set-dangerous-headers-in-dashboard.html [ WontFix ]
# Only applicable on macOS
+css-dark-mode [ Skip ]
fast/css/apple-system-control-colors.html [ Skip ]
+inspector/css/force-page-appearance.html [ Skip ]
# Only Mac supports force tests.
fast/events/cancelled-force-click-link-navigation.html [ Skip ]
Added: trunk/LayoutTests/inspector/css/force-page-appearance-expected.txt (0 => 238570)
--- trunk/LayoutTests/inspector/css/force-page-appearance-expected.txt (rev 0)
+++ trunk/LayoutTests/inspector/css/force-page-appearance-expected.txt 2018-11-27 21:16:07 UTC (rev 238570)
@@ -0,0 +1,38 @@
+Testing the default appearance and forced appearance features.
+
+
+== Running test suite: ForcePageAppearance
+-- Running test case: Default appearance should be light
+PASS: WI.cssManager.defaultAppearance should be Light.
+PASS: WI.cssManager.forcedAppearance should be null.
+PASS: expectEqual("150px", "150px")
+PASS: expectEqual("rgb(0, 0, 0)", "rgb(0, 0, 0)")
+
+-- Running test case: Force appearance to Dark
+PASS: WI.cssManager.defaultAppearance should be Light.
+PASS: WI.cssManager.forcedAppearance should be Dark.
+PASS: DOMNodeStyles should need refresh.
+PASS: expectEqual("200px", "200px")
+PASS: expectEqual("rgb(255, 255, 255)", "rgb(255, 255, 255)")
+
+-- Running test case: Switch to Dark appearance by default
+PASS: WI.cssManager.defaultAppearance should be Dark.
+PASS: WI.cssManager.forcedAppearance should be Dark.
+PASS: DOMNodeStyles should need refresh.
+PASS: expectEqual("200px", "200px")
+PASS: expectEqual("rgb(255, 255, 255)", "rgb(255, 255, 255)")
+
+-- Running test case: Force appearance to Light
+PASS: WI.cssManager.defaultAppearance should be Dark.
+PASS: WI.cssManager.forcedAppearance should be Light.
+PASS: DOMNodeStyles should need refresh.
+PASS: expectEqual("150px", "150px")
+PASS: expectEqual("rgb(0, 0, 0)", "rgb(0, 0, 0)")
+
+-- Running test case: Disable forced appearance
+PASS: WI.cssManager.defaultAppearance should be Dark.
+PASS: WI.cssManager.forcedAppearance should be null.
+PASS: DOMNodeStyles should need refresh.
+PASS: expectEqual("200px", "200px")
+PASS: expectEqual("rgb(255, 255, 255)", "rgb(255, 255, 255)")
+
Added: trunk/LayoutTests/inspector/css/force-page-appearance.html (0 => 238570)
--- trunk/LayoutTests/inspector/css/force-page-appearance.html (rev 0)
+++ trunk/LayoutTests/inspector/css/force-page-appearance.html 2018-11-27 21:16:07 UTC (rev 238570)
@@ -0,0 +1,166 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+<script>
+function switchToDarkAppearance() {
+ if (window.internals)
+ internals.settings.setUseDarkAppearance(true);
+}
+
+function test() {
+ let nodeStyles = null;
+ let suite = InspectorTest.createAsyncSuite("ForcePageAppearance");
+
+ let getProperty = (propertyName) => {
+ let styleDeclaration = nodeStyles.computedStyle;
+ for (let property of styleDeclaration.properties) {
+ if (property.name === propertyName)
+ return property;
+ }
+ };
+
+ suite.addTestCase({
+ name: "Default appearance should be light",
+ test(resolve, reject) {
+ InspectorTest.expectEqual(WI.cssManager.defaultAppearance, WI.CSSManager.Appearance.Light, `WI.cssManager.defaultAppearance should be Light.`);
+ InspectorTest.expectNull(WI.cssManager.forcedAppearance, `WI.cssManager.forcedAppearance should be null.`);
+
+ InspectorTest.expectEqual(getProperty("width").rawValue, "150px");
+ InspectorTest.expectEqual(getProperty("color").rawValue, "rgb(0, 0, 0)");
+
+ resolve();
+ }
+ });
+
+ suite.addTestCase({
+ name: "Force appearance to Dark",
+ test(resolve, reject) {
+ // Styles should referesh when dark apeparance is forced.
+ WI.cssManager.awaitEvent(WI.CSSManager.Event.ForcedAppearanceDidChange).then((event) => {
+ InspectorTest.expectEqual(nodeStyles.needsRefresh, true, `DOMNodeStyles should need refresh.`);
+ nodeStyles.refresh();
+
+ return nodeStyles.computedStyle.awaitEvent(WI.CSSStyleDeclaration.Event.PropertiesChanged).then((event) => {
+ InspectorTest.expectEqual(getProperty("width").rawValue, "200px");
+ InspectorTest.expectEqual(getProperty("color").rawValue, "rgb(255, 255, 255)");
+ });
+ }).then(resolve, reject);
+
+ WI.cssManager.forcedAppearance = WI.CSSManager.Appearance.Dark;
+
+ InspectorTest.expectEqual(WI.cssManager.defaultAppearance, WI.CSSManager.Appearance.Light, `WI.cssManager.defaultAppearance should be Light.`);
+ InspectorTest.expectEqual(WI.cssManager.forcedAppearance, WI.CSSManager.Appearance.Dark, `WI.cssManager.forcedAppearance should be Dark.`);
+ }
+ });
+
+ suite.addTestCase({
+ name: "Switch to Dark appearance by default",
+ test(resolve, reject) {
+ InspectorTest.evaluateInPage(`switchToDarkAppearance()`);
+
+ WI.cssManager.awaitEvent(WI.CSSManager.Event.DefaultAppearanceDidChange).then((event) => {
+ InspectorTest.expectEqual(WI.cssManager.defaultAppearance, WI.CSSManager.Appearance.Dark, `WI.cssManager.defaultAppearance should be Dark.`);
+ InspectorTest.expectEqual(WI.cssManager.forcedAppearance, WI.CSSManager.Appearance.Dark, `WI.cssManager.forcedAppearance should be Dark.`);
+ InspectorTest.expectEqual(nodeStyles.needsRefresh, true, `DOMNodeStyles should need refresh.`);
+ nodeStyles.refresh();
+
+ return nodeStyles.computedStyle.awaitEvent(WI.CSSStyleDeclaration.Event.PropertiesChanged).then((event) => {
+ InspectorTest.expectEqual(getProperty("width").rawValue, "200px");
+ InspectorTest.expectEqual(getProperty("color").rawValue, "rgb(255, 255, 255)");
+ });
+ }).then(resolve, reject);
+ }
+ });
+
+ suite.addTestCase({
+ name: "Force appearance to Light",
+ test(resolve, reject) {
+ // Styles should referesh when light apeparance is forced.
+ WI.cssManager.awaitEvent(WI.CSSManager.Event.ForcedAppearanceDidChange).then((event) => {
+ InspectorTest.expectEqual(nodeStyles.needsRefresh, true, `DOMNodeStyles should need refresh.`);
+ nodeStyles.refresh();
+
+ return nodeStyles.computedStyle.awaitEvent(WI.CSSStyleDeclaration.Event.PropertiesChanged).then((event) => {
+ InspectorTest.expectEqual(getProperty("width").rawValue, "150px");
+ InspectorTest.expectEqual(getProperty("color").rawValue, "rgb(0, 0, 0)");
+ });
+ }).then(resolve, reject);
+
+ WI.cssManager.forcedAppearance = WI.CSSManager.Appearance.Light;
+
+ InspectorTest.expectEqual(WI.cssManager.defaultAppearance, WI.CSSManager.Appearance.Dark, `WI.cssManager.defaultAppearance should be Dark.`);
+ InspectorTest.expectEqual(WI.cssManager.forcedAppearance, WI.CSSManager.Appearance.Light, `WI.cssManager.forcedAppearance should be Light.`);
+ }
+ });
+
+ suite.addTestCase({
+ name: "Disable forced appearance",
+ test(resolve, reject) {
+ // Styles should referesh when forced apeparance is disabled.
+ WI.cssManager.awaitEvent(WI.CSSManager.Event.ForcedAppearanceDidChange).then((event) => {
+ InspectorTest.expectEqual(nodeStyles.needsRefresh, true, `DOMNodeStyles should need refresh.`);
+ nodeStyles.refresh();
+
+ return nodeStyles.computedStyle.awaitEvent(WI.CSSStyleDeclaration.Event.PropertiesChanged).then((event) => {
+ InspectorTest.expectEqual(getProperty("width").rawValue, "200px");
+ InspectorTest.expectEqual(getProperty("color").rawValue, "rgb(255, 255, 255)");
+ });
+ }).then(resolve, reject);
+
+ WI.cssManager.forcedAppearance = null;
+
+ InspectorTest.expectEqual(WI.cssManager.defaultAppearance, WI.CSSManager.Appearance.Dark, `WI.cssManager.defaultAppearance should be Dark.`);
+ InspectorTest.expectNull(WI.cssManager.forcedAppearance, `WI.cssManager.forcedAppearance should be null.`);
+ }
+ });
+
+ WI.domManager.requestDocument((documentNode) => {
+ WI.domManager.querySelector(documentNode.id, "#x", (contentNodeId) => {
+ if (contentNodeId) {
+ let domNode = WI.domManager.nodeForId(contentNodeId);
+ nodeStyles = WI.cssManager.stylesForNode(domNode);
+
+ if (nodeStyles.needsRefresh) {
+ nodeStyles.singleFireEventListener(WI.DOMNodeStyles.Event.Refreshed, (event) => {
+ suite.runTestCasesAndFinish()
+ });
+ } else
+ suite.runTestCasesAndFinish();
+ } else {
+ InspectorTest.fail("DOM node not found.");
+ InspectorTest.completeTest();
+ }
+ });
+ });
+}
+</script>
+</head>
+<body _onload_="runTest()">
+ <p>Testing the default appearance and forced appearance features.</p>
+
+ <style>
+ :root {
+ supported-color-schemes: light dark;
+ }
+
+ .test-node {
+ width: 100px;
+ }
+
+ @media (prefers-color-scheme: light) {
+ .test-node {
+ width: 150px;
+ }
+ }
+
+ @media (prefers-color-scheme: dark) {
+ .test-node {
+ width: 200px;
+ }
+ }
+ </style>
+
+ <div id="x" class="test-node"></div>
+</body>
+</html>
Modified: trunk/LayoutTests/platform/mac/TestExpectations (238569 => 238570)
--- trunk/LayoutTests/platform/mac/TestExpectations 2018-11-27 21:06:52 UTC (rev 238569)
+++ trunk/LayoutTests/platform/mac/TestExpectations 2018-11-27 21:16:07 UTC (rev 238570)
@@ -1768,7 +1768,8 @@
[ Mojave+ ] fast/gradients/conic-two-hints.html [ Pass ]
# Dark Mode is Mojave and later.
-[ Sierra HighSierra ] css-dark-mode [ Skip ]
+[ Mojave+ ] css-dark-mode [ Pass ]
+[ Mojave+ ] inspector/css/force-page-appearance.html [ Pass ]
webkit.org/b/185651 legacy-animation-engine/animations/play-state-in-shorthand.html [ Pass Failure ]
Modified: trunk/Source/_javascript_Core/ChangeLog (238569 => 238570)
--- trunk/Source/_javascript_Core/ChangeLog 2018-11-27 21:06:52 UTC (rev 238569)
+++ trunk/Source/_javascript_Core/ChangeLog 2018-11-27 21:16:07 UTC (rev 238570)
@@ -1,3 +1,14 @@
+2018-11-27 Timothy Hatcher <timo...@apple.com>
+
+ Web Inspector: Add support for forcing color scheme appearance in DOM tree.
+ https://bugs.webkit.org/show_bug.cgi?id=191820
+ rdar://problem/46153172
+
+ Reviewed by Devin Rousso.
+
+ * inspector/protocol/Page.json: Added setForcedAppearance.
+ Also added the defaultAppearanceDidChange event and Appearance enum.
+
2018-11-27 Ryan Haddad <ryanhad...@apple.com>
Unreviewed, rolling out r238509.
Modified: trunk/Source/_javascript_Core/inspector/protocol/Page.json (238569 => 238570)
--- trunk/Source/_javascript_Core/inspector/protocol/Page.json 2018-11-27 21:06:52 UTC (rev 238569)
+++ trunk/Source/_javascript_Core/inspector/protocol/Page.json 2018-11-27 21:16:07 UTC (rev 238570)
@@ -22,6 +22,12 @@
"description": "Same-Site policy of a cookie."
},
{
+ "id": "Appearance",
+ "type": "string",
+ "enum": ["Light", "Dark"],
+ "description": "Page appearance name."
+ },
+ {
"id": "Frame",
"type": "object",
"description": "Information about the Frame on the page.",
@@ -194,6 +200,13 @@
]
},
{
+ "name": "setForcedAppearance",
+ "description": "Forces the given appearance for the page.",
+ "parameters": [
+ { "name": "appearance", "$ref": "Appearance", "description": "Appearance name to force. Empty string disables the override." }
+ ]
+ },
+ {
"name": "getCompositingBordersVisible",
"description": "Indicates the visibility of compositing borders.",
"returns": [
@@ -294,6 +307,13 @@
"parameters": [
{ "name": "frameId", "$ref": "Network.FrameId", "description": "Id of the frame that has cleared its scheduled navigation." }
]
+ },
+ {
+ "name": "defaultAppearanceDidChange",
+ "description": "Fired when page's default appearance changes, even if there is a forced appearance.",
+ "parameters": [
+ { "name": "appearance", "$ref": "Appearance", "description": "Name of the appearance that is active (not considering any forced appearance.)" }
+ ]
}
]
}
Modified: trunk/Source/WebCore/ChangeLog (238569 => 238570)
--- trunk/Source/WebCore/ChangeLog 2018-11-27 21:06:52 UTC (rev 238569)
+++ trunk/Source/WebCore/ChangeLog 2018-11-27 21:16:07 UTC (rev 238570)
@@ -1,3 +1,30 @@
+2018-11-27 Timothy Hatcher <timo...@apple.com>
+
+ Web Inspector: Add support for forcing color scheme appearance in DOM tree.
+ https://bugs.webkit.org/show_bug.cgi?id=191820
+ rdar://problem/46153172
+
+ Reviewed by Devin Rousso.
+
+ Test: inspector/css/force-page-appearance.html
+
+ * inspector/InspectorInstrumentation.cpp:
+ (WebCore::InspectorInstrumentation::defaultAppearanceDidChangeImpl):
+ * inspector/InspectorInstrumentation.h:
+ (WebCore::InspectorInstrumentation::defaultAppearanceDidChange):
+ * inspector/agents/InspectorPageAgent.cpp:
+ (WebCore::InspectorPageAgent::enable): Fire defaultAppearanceDidChange() on macOS Majave.
+ (WebCore::InspectorPageAgent::disable): Call setForcedAppearance() with empty string.
+ (WebCore::InspectorPageAgent::defaultAppearanceDidChange): Added.
+ (WebCore::InspectorPageAgent::setForcedAppearance): Added.
+ * inspector/agents/InspectorPageAgent.h:
+ * page/Page.cpp:
+ (WebCore::Page::setUseDarkAppearance): Call InspectorInstrumentation::defaultAppearanceDidChange().
+ (WebCore::Page::useDarkAppearance const): Return override value if not nullopt.
+ (WebCore::Page::setUseDarkAppearanceOverride): Added.
+ * page/Page.h:
+ (WebCore::Page::defaultUseDarkAppearance const): Added.
+
2018-11-27 Tim Horton <timothy_hor...@apple.com>
Serialize and deserialize editable image strokes
Modified: trunk/Source/WebCore/inspector/InspectorInstrumentation.cpp (238569 => 238570)
--- trunk/Source/WebCore/inspector/InspectorInstrumentation.cpp 2018-11-27 21:06:52 UTC (rev 238569)
+++ trunk/Source/WebCore/inspector/InspectorInstrumentation.cpp 2018-11-27 21:16:07 UTC (rev 238570)
@@ -782,6 +782,12 @@
inspectorPageAgent->frameClearedScheduledNavigation(frame);
}
+void InspectorInstrumentation::defaultAppearanceDidChangeImpl(InstrumentingAgents& instrumentingAgents, bool useDarkAppearance)
+{
+ if (InspectorPageAgent* inspectorPageAgent = instrumentingAgents.inspectorPageAgent())
+ inspectorPageAgent->defaultAppearanceDidChange(useDarkAppearance);
+}
+
void InspectorInstrumentation::willDestroyCachedResourceImpl(CachedResource& cachedResource)
{
if (!s_instrumentingAgentsSet)
Modified: trunk/Source/WebCore/inspector/InspectorInstrumentation.h (238569 => 238570)
--- trunk/Source/WebCore/inspector/InspectorInstrumentation.h 2018-11-27 21:06:52 UTC (rev 238569)
+++ trunk/Source/WebCore/inspector/InspectorInstrumentation.h 2018-11-27 21:16:07 UTC (rev 238570)
@@ -213,6 +213,7 @@
static void frameStoppedLoading(Frame&);
static void frameScheduledNavigation(Frame&, Seconds delay);
static void frameClearedScheduledNavigation(Frame&);
+ static void defaultAppearanceDidChange(Page&, bool useDarkAppearance);
static void willDestroyCachedResource(CachedResource&);
static void addMessageToConsole(Page&, std::unique_ptr<Inspector::ConsoleMessage>);
@@ -386,6 +387,7 @@
static void frameStoppedLoadingImpl(InstrumentingAgents&, Frame&);
static void frameScheduledNavigationImpl(InstrumentingAgents&, Frame&, Seconds delay);
static void frameClearedScheduledNavigationImpl(InstrumentingAgents&, Frame&);
+ static void defaultAppearanceDidChangeImpl(InstrumentingAgents&, bool useDarkAppearance);
static void willDestroyCachedResourceImpl(CachedResource&);
static void addMessageToConsoleImpl(InstrumentingAgents&, std::unique_ptr<Inspector::ConsoleMessage>);
@@ -1135,6 +1137,12 @@
frameClearedScheduledNavigationImpl(*instrumentingAgents, frame);
}
+inline void InspectorInstrumentation::defaultAppearanceDidChange(Page& page, bool useDarkAppearance)
+{
+ FAST_RETURN_IF_NO_FRONTENDS(void());
+ defaultAppearanceDidChangeImpl(instrumentingAgentsForPage(page), useDarkAppearance);
+}
+
inline void InspectorInstrumentation::willDestroyCachedResource(CachedResource& cachedResource)
{
FAST_RETURN_IF_NO_FRONTENDS(void());
Modified: trunk/Source/WebCore/inspector/agents/InspectorPageAgent.cpp (238569 => 238570)
--- trunk/Source/WebCore/inspector/agents/InspectorPageAgent.cpp 2018-11-27 21:06:52 UTC (rev 238569)
+++ trunk/Source/WebCore/inspector/agents/InspectorPageAgent.cpp 2018-11-27 21:16:07 UTC (rev 238570)
@@ -300,6 +300,10 @@
auto stopwatch = m_environment.executionStopwatch();
stopwatch->reset();
stopwatch->start();
+
+#if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
+ defaultAppearanceDidChange(m_page.defaultUseDarkAppearance());
+#endif
}
void InspectorPageAgent::disable(ErrorString&)
@@ -310,6 +314,7 @@
ErrorString unused;
setShowPaintRects(unused, false);
setEmulatedMedia(unused, emptyString());
+ setForcedAppearance(unused, emptyString());
}
void InspectorPageAgent::reload(ErrorString&, const bool* optionalReloadFromOrigin, const bool* optionalRevalidateAllResources)
@@ -685,6 +690,11 @@
m_frontendDispatcher->frameClearedScheduledNavigation(frameId(&frame));
}
+void InspectorPageAgent::defaultAppearanceDidChange(bool useDarkAppearance)
+{
+ m_frontendDispatcher->defaultAppearanceDidChange(useDarkAppearance ? Inspector::Protocol::Page::Appearance::Dark : Inspector::Protocol::Page::Appearance::Light);
+}
+
void InspectorPageAgent::didPaint(RenderObject& renderer, const LayoutRect& rect)
{
if (!m_enabled || !m_showPaintRects)
@@ -808,6 +818,21 @@
document->updateLayout();
}
+void InspectorPageAgent::setForcedAppearance(ErrorString&, const String& appearance)
+{
+ if (appearance == m_forcedAppearance)
+ return;
+
+ m_forcedAppearance = appearance;
+
+ if (appearance == "Light"_s)
+ m_page.setUseDarkAppearanceOverride(false);
+ else if (appearance == "Dark"_s)
+ m_page.setUseDarkAppearanceOverride(true);
+ else
+ m_page.setUseDarkAppearanceOverride(std::nullopt);
+}
+
void InspectorPageAgent::applyEmulatedMedia(String& media)
{
if (!m_emulatedMedia.isEmpty())
Modified: trunk/Source/WebCore/inspector/agents/InspectorPageAgent.h (238569 => 238570)
--- trunk/Source/WebCore/inspector/agents/InspectorPageAgent.h 2018-11-27 21:06:52 UTC (rev 238569)
+++ trunk/Source/WebCore/inspector/agents/InspectorPageAgent.h 2018-11-27 21:16:07 UTC (rev 238570)
@@ -100,6 +100,7 @@
void setShowRulers(ErrorString&, bool) final;
void setShowPaintRects(ErrorString&, bool show) final;
void setEmulatedMedia(ErrorString&, const String&) final;
+ void setForcedAppearance(ErrorString&, const String&) final;
void getCompositingBordersVisible(ErrorString&, bool* out_param) final;
void setCompositingBordersVisible(ErrorString&, bool) final;
void snapshotNode(ErrorString&, int nodeId, String* outDataURL) final;
@@ -116,6 +117,7 @@
void frameStoppedLoading(Frame&);
void frameScheduledNavigation(Frame&, Seconds delay);
void frameClearedScheduledNavigation(Frame&);
+ void defaultAppearanceDidChange(bool useDarkAppearance);
void applyEmulatedMedia(String&);
void didPaint(RenderObject&, const LayoutRect&);
void didLayout();
@@ -160,6 +162,7 @@
bool m_isFirstLayoutAfterOnLoad { false };
bool m_showPaintRects { false };
String m_emulatedMedia;
+ String m_forcedAppearance;
};
} // namespace WebCore
Modified: trunk/Source/WebCore/page/Page.cpp (238569 => 238570)
--- trunk/Source/WebCore/page/Page.cpp 2018-11-27 21:06:52 UTC (rev 238569)
+++ trunk/Source/WebCore/page/Page.cpp 2018-11-27 21:16:07 UTC (rev 238570)
@@ -2632,6 +2632,8 @@
m_useDarkAppearance = value;
+ InspectorInstrumentation::defaultAppearanceDidChange(*this, value);
+
appearanceDidChange();
}
@@ -2640,9 +2642,21 @@
FrameView* view = mainFrame().view();
if (!view || !equalLettersIgnoringASCIICase(view->mediaType(), "screen"))
return false;
+ if (m_useDarkAppearanceOverride)
+ return m_useDarkAppearanceOverride.value();
return m_useDarkAppearance;
}
+void Page::setUseDarkAppearanceOverride(std::optional<bool> valueOverride)
+{
+ if (valueOverride == m_useDarkAppearanceOverride)
+ return;
+
+ m_useDarkAppearanceOverride = valueOverride;
+
+ appearanceDidChange();
+}
+
void Page::setFullscreenInsets(const FloatBoxExtent& insets)
{
if (insets == m_fullscreenInsets)
Modified: trunk/Source/WebCore/page/Page.h (238569 => 238570)
--- trunk/Source/WebCore/page/Page.h 2018-11-27 21:06:52 UTC (rev 238569)
+++ trunk/Source/WebCore/page/Page.h 2018-11-27 21:16:07 UTC (rev 238570)
@@ -360,6 +360,8 @@
WEBCORE_EXPORT bool useDarkAppearance() const;
WEBCORE_EXPORT void setUseDarkAppearance(bool);
+ bool defaultUseDarkAppearance() const { return m_useDarkAppearance; }
+ void setUseDarkAppearanceOverride(std::optional<bool>);
#if ENABLE(TEXT_AUTOSIZING)
float textAutosizingWidth() const { return m_textAutosizingWidth; }
@@ -793,6 +795,7 @@
bool m_useSystemAppearance { false };
bool m_useDarkAppearance { false };
+ std::optional<bool> m_useDarkAppearanceOverride;
#if ENABLE(TEXT_AUTOSIZING)
float m_textAutosizingWidth { 0 };
Modified: trunk/Source/WebInspectorUI/ChangeLog (238569 => 238570)
--- trunk/Source/WebInspectorUI/ChangeLog 2018-11-27 21:06:52 UTC (rev 238569)
+++ trunk/Source/WebInspectorUI/ChangeLog 2018-11-27 21:16:07 UTC (rev 238570)
@@ -1,3 +1,28 @@
+2018-11-27 Timothy Hatcher <timo...@apple.com>
+
+ Web Inspector: Add support for forcing color scheme appearance in DOM tree.
+ https://bugs.webkit.org/show_bug.cgi?id=191820
+ rdar://problem/46153172
+
+ Reviewed by Devin Rousso.
+
+ * Localizations/en.lproj/localizedStrings.js: Updated.
+ * UserInterface/Controllers/CSSManager.js:
+ (WI.CSSManager):
+ (WI.CSSManager.prototype.get defaultAppearance): Added.
+ (WI.CSSManager.prototype.get forcedAppearance): Added.
+ (WI.CSSManager.prototype.set forcedAppearance): Added.
+ (WI.CSSManager.prototype.canForceAppearance): Added.
+ (WI.CSSManager.prototype.defaultAppearanceDidChange): Added.
+ * UserInterface/Images/Appearance.svg: Added.
+ * UserInterface/Protocol/PageObserver.js:
+ (WI.PageObserver.prototype.defaultAppearanceChanged): Added.
+ * UserInterface/Views/DOMTreeContentView.js:
+ (WI.DOMTreeContentView):
+ (WI.DOMTreeContentView.prototype.get navigationItems):
+ (WI.DOMTreeContentView.prototype._defaultAppearanceDidChange): Added.
+ (WI.DOMTreeContentView.prototype._toggleAppearance): Added.
+
2018-11-27 Matt Baker <mattba...@apple.com>
Web Inspector: Cookies table needs copy keyboard shortcut and context menu support
Modified: trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js (238569 => 238570)
--- trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js 2018-11-27 21:06:52 UTC (rev 238569)
+++ trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js 2018-11-27 21:16:07 UTC (rev 238570)
@@ -418,6 +418,8 @@
localizedStrings["Focused"] = "Focused";
localizedStrings["Font"] = "Font";
localizedStrings["Fonts"] = "Fonts";
+localizedStrings["Force Dark Appearance"] = "Force Dark Appearance";
+localizedStrings["Force Light Appearance"] = "Force Light Appearance";
localizedStrings["Force Print Media Styles"] = "Force Print Media Styles";
localizedStrings["Forced Layout"] = "Forced Layout";
localizedStrings["Forced Pseudo-Classes"] = "Forced Pseudo-Classes";
@@ -981,6 +983,7 @@
localizedStrings["Unsupported property name"] = "Unsupported property name";
localizedStrings["Unsupported property value"] = "Unsupported property value";
localizedStrings["Untitled"] = "Untitled";
+localizedStrings["Use Default Appearance"] = "Use Default Appearance";
localizedStrings["Use Default Media Styles"] = "Use Default Media Styles";
localizedStrings["Use the resource cache when loading resources"] = "Use the resource cache when loading resources";
localizedStrings["User Agent"] = "User Agent";
Modified: trunk/Source/WebInspectorUI/UserInterface/Controllers/CSSManager.js (238569 => 238570)
--- trunk/Source/WebInspectorUI/UserInterface/Controllers/CSSManager.js 2018-11-27 21:06:52 UTC (rev 238569)
+++ trunk/Source/WebInspectorUI/UserInterface/Controllers/CSSManager.js 2018-11-27 21:16:07 UTC (rev 238570)
@@ -45,6 +45,8 @@
this._styleSheetIdentifierMap = new Map;
this._styleSheetFrameURLMap = new Map;
this._nodeStylesMap = {};
+ this._defaultAppearance = null;
+ this._forcedAppearance = null;
// COMPATIBILITY (iOS 9): Legacy backends did not send stylesheet
// added/removed events and must be fetched manually.
@@ -107,6 +109,56 @@
return [...this._styleSheetIdentifierMap.values()];
}
+ get defaultAppearance()
+ {
+ return this._defaultAppearance;
+ }
+
+ get forcedAppearance()
+ {
+ return this._forcedAppearance;
+ }
+
+ set forcedAppearance(name)
+ {
+ if (!this.canForceAppearance())
+ return;
+
+ let protocolName = "";
+
+ switch (name) {
+ case WI.CSSManager.Appearance.Light:
+ protocolName = PageAgent.Appearance.Light;
+ break;
+
+ case WI.CSSManager.Appearance.Dark:
+ protocolName = PageAgent.Appearance.Dark;
+ break;
+
+ case null:
+ case undefined:
+ case "":
+ protocolName = "";
+ break;
+
+ default:
+ // Abort for unknown values.
+ return;
+ }
+
+ this._forcedAppearance = name || null;
+
+ PageAgent.setForcedAppearance(protocolName).then(() => {
+ this.mediaQueryResultChanged();
+ this.dispatchEventToListeners(WI.CSSManager.Event.ForcedAppearanceDidChange, {appearance: this._forcedAppearance});
+ });
+ }
+
+ canForceAppearance()
+ {
+ return window.PageAgent && !!PageAgent.setForcedAppearance && this._defaultAppearance;
+ }
+
canForcePseudoClasses()
{
return window.CSSAgent && !!CSSAgent.forcePseudoState;
@@ -269,6 +321,33 @@
this.mediaQueryResultChanged();
}
+ defaultAppearanceDidChange(protocolName)
+ {
+ // Called from WI.PageObserver.
+
+ let appearance = null;
+
+ switch (protocolName) {
+ case PageAgent.Appearance.Light:
+ appearance = WI.CSSManager.Appearance.Light;
+ break;
+
+ case PageAgent.Appearance.Dark:
+ appearance = WI.CSSManager.Appearance.Dark;
+ break;
+
+ default:
+ console.error("Unknown default appearance name:", protocolName);
+ break;
+ }
+
+ this._defaultAppearance = appearance;
+
+ this.mediaQueryResultChanged();
+
+ this.dispatchEventToListeners(WI.CSSManager.Event.DefaultAppearanceDidChange, {appearance});
+ }
+
// Protected
mediaQueryResultChanged()
@@ -561,8 +640,15 @@
WI.CSSManager.Event = {
StyleSheetAdded: "css-manager-style-sheet-added",
StyleSheetRemoved: "css-manager-style-sheet-removed",
+ DefaultAppearanceDidChange: "css-manager-default-appearance-did-change",
+ ForcedAppearanceDidChange: "css-manager-forced-appearance-did-change",
};
+WI.CSSManager.Appearance = {
+ Light: Symbol("light"),
+ Dark: Symbol("dark"),
+};
+
WI.CSSManager.PseudoElementNames = ["before", "after"];
WI.CSSManager.ForceablePseudoClasses = ["active", "focus", "hover", "visited"];
WI.CSSManager.PreferredInspectorStyleSheetSymbol = Symbol("css-manager-preferred-inspector-stylesheet");
Added: trunk/Source/WebInspectorUI/UserInterface/Images/Appearance.svg (0 => 238570)
--- trunk/Source/WebInspectorUI/UserInterface/Images/Appearance.svg (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Images/Appearance.svg 2018-11-27 21:16:07 UTC (rev 238570)
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright © 2018 Apple Inc. All rights reserved. -->
+<svg xmlns="http://www.w3.org/2000/svg" id="root" version="1.1" viewBox="0 0 16 16">
+ <path fill="currentColor" fill-rule="evenodd" d="M 3.99119893 1 L 12.0087973 1 C 13.048904 1 13.4260733 1.10829467 13.8063227 1.31165867 C 14.1865627 1.51501333 14.4849867 1.81343733 14.6883413 2.19367733 C 14.8917053 2.57392667 15 2.951096 15 3.99120267 L 15 12.0088011 C 15 13.0489059 14.8917053 13.4260733 14.6883413 13.8063199 C 14.4849867 14.1865669 14.1865627 14.4849869 13.8063227 14.6883452 C 13.4260733 14.8917035 13.048904 15 12.0087973 15 L 3.99119893 15 C 2.95109413 15 2.57392667 14.8917035 2.19368013 14.6883452 C 1.81343313 14.4849869 1.51501305 14.1865669 1.31165484 13.8063199 C 1.10829653 13.4260733 1 13.0489059 1 12.0088011 L 1 3.99120267 C 1 2.951096 1.10829653 2.57392667 1.31165484 2.19367733 C 1.51501305 1.81343733 1.81343313 1.51501333 2.19368013 1.31165867 C 2.57392667 1.10829467 2.95109413 1 3.99119893 1 Z M 3.5 4 L 12.5 4 C 13.3284271 4 14 4.67157288 14 5.5 L 14 12.5 C 14 13.3284271 13.3284271 14 12.5 14 L 3.5 14 C 2.67157288 14 2 1
3.3284271 2 12.5 L 2 5.5 C 2 4.67157288 2.67157288 4 3.5 4 Z M 4.1 5 L 11.9 5 C 12.5075132 5 13 5.49248678 13 6.1 L 13 11.9 C 13 12.5075132 12.5075132 13 11.9 13 L 4.1 13 C 3.49248678 13 3 12.5075132 3 11.9 L 3 6.1 C 3 5.49248678 3.49248678 5 4.1 5 Z M 3 2 L 4 2 L 4 3 L 3 3 L 3 2 Z M 5 2 L 6 2 L 6 3 L 5 3 L 5 2 Z M 7 2 L 8 2 L 8 3 L 7 3 L 7 2 Z"/>
+</svg>
Modified: trunk/Source/WebInspectorUI/UserInterface/Protocol/PageObserver.js (238569 => 238570)
--- trunk/Source/WebInspectorUI/UserInterface/Protocol/PageObserver.js 2018-11-27 21:06:52 UTC (rev 238569)
+++ trunk/Source/WebInspectorUI/UserInterface/Protocol/PageObserver.js 2018-11-27 21:16:07 UTC (rev 238570)
@@ -47,6 +47,11 @@
WI.networkManager.frameDidDetach(frameId);
}
+ defaultAppearanceDidChange(appearance)
+ {
+ WI.cssManager.defaultAppearanceDidChange(appearance);
+ }
+
frameStartedLoading(frameId)
{
// Not handled yet.
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/DOMTreeContentView.js (238569 => 238570)
--- trunk/Source/WebInspectorUI/UserInterface/Views/DOMTreeContentView.js 2018-11-27 21:06:52 UTC (rev 238569)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/DOMTreeContentView.js 2018-11-27 21:16:07 UTC (rev 238570)
@@ -74,6 +74,8 @@
WI.domManager.addEventListener(WI.DOMManager.Event.AttributeRemoved, this._domNodeChanged, this);
WI.domManager.addEventListener(WI.DOMManager.Event.CharacterDataModified, this._domNodeChanged, this);
+ WI.cssManager.addEventListener(WI.CSSManager.Event.DefaultAppearanceDidChange, this._defaultAppearanceDidChange, this);
+
this._lastSelectedNodePathSetting = new WI.Setting("last-selected-node-path", null);
this._numberOfSearchResults = null;
@@ -81,6 +83,9 @@
this._breakpointGutterEnabled = false;
this._pendingBreakpointNodeIdentifiers = new Set;
+ if (WI.cssManager.canForceAppearance())
+ this._defaultAppearanceDidChange();
+
if (WI.domDebuggerManager.supported) {
WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.BreakpointsEnabledDidChange, this._breakpointsEnabledDidChange, this);
@@ -100,6 +105,9 @@
{
let items = [this._showPrintStylesButtonNavigationItem, this._showsShadowDOMButtonNavigationItem];
+ if (this._forceAppearanceButtonNavigationItem)
+ items.unshift(this._forceAppearanceButtonNavigationItem);
+
// COMPATIBILITY (iOS 11.3)
if (window.PageAgent && PageAgent.setShowRulers)
items.unshift(this._showRulersButtonNavigationItem);
@@ -582,6 +590,71 @@
this._showPrintStylesChanged();
}
+ _defaultAppearanceDidChange()
+ {
+ let defaultAppearance = WI.cssManager.defaultAppearance;
+ if (!defaultAppearance) {
+ this._lastKnownDefaultAppearance = null;
+ this._forceAppearanceButtonNavigationItem = null;
+ this.dispatchEventToListeners(WI.ContentView.Event.NavigationItemsDidChange);
+ return;
+ }
+
+ // Don't update the navigation item if there is currently a forced appearance.
+ // The user will need to toggle it off to update it based on the new default appearance.
+ if (WI.cssManager.forcedAppearance && this._forceAppearanceButtonNavigationItem)
+ return;
+
+ this._forceAppearanceButtonNavigationItem = null;
+
+ switch (defaultAppearance) {
+ case WI.CSSManager.Appearance.Light:
+ this._forceAppearanceButtonNavigationItem = new WI.ActivateButtonNavigationItem("appearance", WI.UIString("Force Dark Appearance"), WI.UIString("Use Default Appearance"), "Images/Appearance.svg", 16, 16);
+ break;
+ case WI.CSSManager.Appearance.Dark:
+ this._forceAppearanceButtonNavigationItem = new WI.ActivateButtonNavigationItem("appearance", WI.UIString("Force Light Appearance"), WI.UIString("Use Default Appearance"), "Images/Appearance.svg", 16, 16);
+ break;
+ }
+
+ if (!this._forceAppearanceButtonNavigationItem) {
+ console.error("Unknown default appearance name:", defaultAppearance);
+ this.dispatchEventToListeners(WI.ContentView.Event.NavigationItemsDidChange);
+ return;
+ }
+
+ this._lastKnownDefaultAppearance = defaultAppearance;
+
+ this._forceAppearanceButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._toggleAppearance, this);
+ this._forceAppearanceButtonNavigationItem.visibilityPriority = WI.NavigationItem.VisibilityPriority.Low;
+ this._forceAppearanceButtonNavigationItem.activated = !!WI.cssManager.forcedAppearance;
+
+ this.dispatchEventToListeners(WI.ContentView.Event.NavigationItemsDidChange);
+ }
+
+ _toggleAppearance(event)
+ {
+ // Use the last known default appearance, since that is the appearance this navigation item was generated for.
+ let appearanceToForce = null;
+ switch (this._lastKnownDefaultAppearance) {
+ case WI.CSSManager.Appearance.Light:
+ appearanceToForce = WI.CSSManager.Appearance.Dark;
+ break;
+ case WI.CSSManager.Appearance.Dark:
+ appearanceToForce = WI.CSSManager.Appearance.Light;
+ break;
+ }
+
+ console.assert(appearanceToForce);
+ WI.cssManager.forcedAppearance = WI.cssManager.forcedAppearance == appearanceToForce ? null : appearanceToForce;
+
+ // When no longer forcing an appearance, if the last known default appearance is different than the current
+ // default appearance, then update the navigation button now. Otherwise just toggle the activated state.
+ if (!WI.cssManager.forcedAppearance && this._lastKnownDefaultAppearance !== WI.cssManager.defaultAppearance)
+ this._defaultAppearanceDidChange();
+ else
+ this._forceAppearanceButtonNavigationItem.activated = !!WI.cssManager.forcedAppearance;
+ }
+
_showRulersChanged()
{
this._showRulersButtonNavigationItem.activated = WI.settings.showRulers.value;