<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[214386] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/214386">214386</a></dd>
<dt>Author</dt> <dd>graouts@webkit.org</dd>
<dt>Date</dt> <dd>2017-03-24 16:32:14 -0700 (Fri, 24 Mar 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>[Modern Media Controls] Remove placard icon if height is compressed
https://bugs.webkit.org/show_bug.cgi?id=167935
&lt;rdar://problem/30397128&gt;

Reviewed by Dean Jackson.

Source/WebCore:

We make the addition of certain Placard children conditional on the placard's metrics. Whenever the
media controls metrics changes, the placard, if any, is set to have the same metrics and layout() is
called where we ensure that there is enough space, per designs, to have the icon, description and even
the title visible. We also make some CSS improvements to guarantee that the description is laid out on
two lines at most and that both text labels are trimmed elegantly with an ellipsis shold the width be
insufficient to display the whole text.

Since we would have needed to have more width/height setter overrides to trigger layout, we now make
LayoutNode trigger layout() directly and remove the need for subclasses to do this on a per-class basis.
We also make layout() a method that can be called safely anytime as it's now no longer part of the DOM
commit step, a new commit() method is used instead of that.

Tests: media/modern-media-controls/layout-node/node-made-dirty-during-commit.html
       media/modern-media-controls/media-controls/media-controls-placard-compressed-metrics.html

* Modules/modern-media-controls/controls/layout-node.js:
(LayoutNode.prototype.set width):
(LayoutNode.prototype.set height):
Trigger a call to layout() anytime &quot;width&quot; or &quot;height&quot; is set on any LayoutNode.

(LayoutNode.prototype.layout):
(LayoutNode.prototype.commit):
(performScheduledLayout):
Make layout() an empty method that subclasses can override easily outside of the DOM commit cycle,
its previous implementation is now called &quot;commit()&quot; which is a more accurate name.

* Modules/modern-media-controls/controls/media-controls.js:
(MediaControls.prototype.get placard):
(MediaControls.prototype.get showsPlacard):
(MediaControls.prototype.showPlacard):
(MediaControls.prototype.hidePlacard):
(MediaControls.prototype.layout):
(MediaControls.prototype.get width): Deleted.
(MediaControls.prototype.set width): Deleted.
Add a &quot;placard&quot; property to make it simpler to reference the placard instead of making assumptions in
several places in that class on the children order. Anytime we run a layout or show the placard, ensure
that the placard metrics are synced with the media controls metrics.

* Modules/modern-media-controls/controls/placard.css:
(.placard .container):
(.placard .title,):
(.placard .description):
We now ensure that both the title and description are trimmed with an ellipsis when we run out of space
to display them fully.

* Modules/modern-media-controls/controls/placard.js:
(Placard.):
(Placard.prototype.layout):
We add new constraints to only show the icon, title and description if the placard is tall and wide enough.

* Modules/modern-media-controls/controls/slider.js:
(Slider.prototype.get width): Deleted.
(Slider.prototype.set width): Deleted.
Removed custom &quot;width&quot; getters and setters now we can just override layout() in case node metrics change.

* Modules/modern-media-controls/controls/time-control.js:
(TimeControl.prototype.set useSixDigitsForTimeLabels):
(TimeControl.prototype.layout):
(TimeControl.prototype.get width): Deleted.
(TimeControl.prototype.set width): Deleted.
(TimeControl.prototype._availableWidthHasChanged): Deleted.
Removed custom &quot;width&quot; getters and setters now we can just override layout() in case node metrics change.

* Modules/modern-media-controls/media/media-controller.js:
(MediaController):
Ensure we flush pending updates at construction time so that we match the size of the media controls right
at the first media layout.

LayoutTests:

We add a new test to check that the various designed constraints to toggle display of a placard's
icon, title and description are honored. Also, due to the old layout() method now being called
&quot;commit()&quot;, we refactor a relevant test.

* media/modern-media-controls/layout-node/node-made-dirty-during-commit-expected.txt: Added.
* media/modern-media-controls/layout-node/node-made-dirty-during-commit.html: Added.
* media/modern-media-controls/media-controls/media-controls-placard-compressed-metrics-expected.txt: Added.
* media/modern-media-controls/media-controls/media-controls-placard-compressed-metrics.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreModulesmodernmediacontrolscontrolslayoutnodejs">trunk/Source/WebCore/Modules/modern-media-controls/controls/layout-node.js</a></li>
<li><a href="#trunkSourceWebCoreModulesmodernmediacontrolscontrolsmediacontrolsjs">trunk/Source/WebCore/Modules/modern-media-controls/controls/media-controls.js</a></li>
<li><a href="#trunkSourceWebCoreModulesmodernmediacontrolscontrolsplacardcss">trunk/Source/WebCore/Modules/modern-media-controls/controls/placard.css</a></li>
<li><a href="#trunkSourceWebCoreModulesmodernmediacontrolscontrolsplacardjs">trunk/Source/WebCore/Modules/modern-media-controls/controls/placard.js</a></li>
<li><a href="#trunkSourceWebCoreModulesmodernmediacontrolscontrolssliderjs">trunk/Source/WebCore/Modules/modern-media-controls/controls/slider.js</a></li>
<li><a href="#trunkSourceWebCoreModulesmodernmediacontrolscontrolstimecontroljs">trunk/Source/WebCore/Modules/modern-media-controls/controls/time-control.js</a></li>
<li><a href="#trunkSourceWebCoreModulesmodernmediacontrolsmediamediacontrollerjs">trunk/Source/WebCore/Modules/modern-media-controls/media/media-controller.js</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsmediamodernmediacontrolslayoutnodenodemadedirtyduringcommitexpectedtxt">trunk/LayoutTests/media/modern-media-controls/layout-node/node-made-dirty-during-commit-expected.txt</a></li>
<li><a href="#trunkLayoutTestsmediamodernmediacontrolslayoutnodenodemadedirtyduringcommithtml">trunk/LayoutTests/media/modern-media-controls/layout-node/node-made-dirty-during-commit.html</a></li>
<li><a href="#trunkLayoutTestsmediamodernmediacontrolsmediacontrolsmediacontrolsplacardcompressedmetricsexpectedtxt">trunk/LayoutTests/media/modern-media-controls/media-controls/media-controls-placard-compressed-metrics-expected.txt</a></li>
<li><a href="#trunkLayoutTestsmediamodernmediacontrolsmediacontrolsmediacontrolsplacardcompressedmetricshtml">trunk/LayoutTests/media/modern-media-controls/media-controls/media-controls-placard-compressed-metrics.html</a></li>
</ul>

<h3>Removed Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsmediamodernmediacontrolslayoutnodenodemadedirtyduringlayoutexpectedtxt">trunk/LayoutTests/media/modern-media-controls/layout-node/node-made-dirty-during-layout-expected.txt</a></li>
<li><a href="#trunkLayoutTestsmediamodernmediacontrolslayoutnodenodemadedirtyduringlayouthtml">trunk/LayoutTests/media/modern-media-controls/layout-node/node-made-dirty-during-layout.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (214385 => 214386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2017-03-24 23:27:14 UTC (rev 214385)
+++ trunk/LayoutTests/ChangeLog        2017-03-24 23:32:14 UTC (rev 214386)
</span><span class="lines">@@ -1,3 +1,20 @@
</span><ins>+2017-03-24  Antoine Quint  &lt;graouts@webkit.org&gt;
+
+        [Modern Media Controls] Remove placard icon if height is compressed
+        https://bugs.webkit.org/show_bug.cgi?id=167935
+        &lt;rdar://problem/30397128&gt;
+
+        Reviewed by Dean Jackson.
+
+        We add a new test to check that the various designed constraints to toggle display of a placard's
+        icon, title and description are honored. Also, due to the old layout() method now being called
+        &quot;commit()&quot;, we refactor a relevant test.
+
+        * media/modern-media-controls/layout-node/node-made-dirty-during-commit-expected.txt: Added.
+        * media/modern-media-controls/layout-node/node-made-dirty-during-commit.html: Added.
+        * media/modern-media-controls/media-controls/media-controls-placard-compressed-metrics-expected.txt: Added.
+        * media/modern-media-controls/media-controls/media-controls-placard-compressed-metrics.html: Added.
+
</ins><span class="cx"> 2017-03-24  Eric Carlson  &lt;eric.carlson@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [MediaStream] &quot;ideal&quot; constraints passed to getUserMedia should affect fitness score
</span></span></pre></div>
<a id="trunkLayoutTestsmediamodernmediacontrolslayoutnodenodemadedirtyduringcommitexpectedtxtfromrev214385trunkLayoutTestsmediamodernmediacontrolslayoutnodenodemadedirtyduringlayoutexpectedtxt"></a>
<div class="copfile"><h4>Copied: trunk/LayoutTests/media/modern-media-controls/layout-node/node-made-dirty-during-commit-expected.txt (from rev 214385, trunk/LayoutTests/media/modern-media-controls/layout-node/node-made-dirty-during-layout-expected.txt) (0 => 214386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/media/modern-media-controls/layout-node/node-made-dirty-during-commit-expected.txt                                (rev 0)
+++ trunk/LayoutTests/media/modern-media-controls/layout-node/node-made-dirty-during-commit-expected.txt        2017-03-24 23:32:14 UTC (rev 214386)
</span><span class="lines">@@ -0,0 +1,11 @@
</span><ins>+Making a node dirty again during a commit.
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+PASS node.element.style.left is &quot;20px&quot;
+PASS node.element.style.left is &quot;10px&quot;
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsmediamodernmediacontrolslayoutnodenodemadedirtyduringcommithtmlfromrev214385trunkLayoutTestsmediamodernmediacontrolslayoutnodenodemadedirtyduringlayouthtml"></a>
<div class="copfile"><h4>Copied: trunk/LayoutTests/media/modern-media-controls/layout-node/node-made-dirty-during-commit.html (from rev 214385, trunk/LayoutTests/media/modern-media-controls/layout-node/node-made-dirty-during-layout.html) (0 => 214386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/media/modern-media-controls/layout-node/node-made-dirty-during-commit.html                                (rev 0)
+++ trunk/LayoutTests/media/modern-media-controls/layout-node/node-made-dirty-during-commit.html        2017-03-24 23:32:14 UTC (rev 214386)
</span><span class="lines">@@ -0,0 +1,40 @@
</span><ins>+&lt;script src=&quot;../../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../../../Source/WebCore/Modules/modern-media-controls/controls/scheduler.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../../../Source/WebCore/Modules/modern-media-controls/controls/layout-node.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../resources/media-controls-utils.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
+
+&lt;script type=&quot;text/javascript&quot;&gt;
+
+description(&quot;Making a node dirty again during a commit.&quot;);
+
+window.jsTestIsAsync = true;
+
+class CustomNode extends LayoutNode
+{
+    
+    commit()
+    {
+        super.commit();
+
+        this.x = 10;
+    }
+    
+}
+
+const node = new CustomNode;
+node.x = 20;
+
+let numberOfFrames = 0;
+scheduler.frameDidFire = function()
+{
+    numberOfFrames++;
+    if (numberOfFrames == 1)
+        shouldBeEqualToString(&quot;node.element.style.left&quot;, &quot;20px&quot;);
+    else if (numberOfFrames == 2) {
+        shouldBeEqualToString(&quot;node.element.style.left&quot;, &quot;10px&quot;);
+        finishMediaControlsTest();
+    }
+};
+
+&lt;/script&gt;
+&lt;script src=&quot;../../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsmediamodernmediacontrolslayoutnodenodemadedirtyduringlayoutexpectedtxt"></a>
<div class="delfile"><h4>Deleted: trunk/LayoutTests/media/modern-media-controls/layout-node/node-made-dirty-during-layout-expected.txt (214385 => 214386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/media/modern-media-controls/layout-node/node-made-dirty-during-layout-expected.txt        2017-03-24 23:27:14 UTC (rev 214385)
+++ trunk/LayoutTests/media/modern-media-controls/layout-node/node-made-dirty-during-layout-expected.txt        2017-03-24 23:32:14 UTC (rev 214386)
</span><span class="lines">@@ -1,11 +0,0 @@
</span><del>-Testing the LayoutNode.y property.
-
-On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
-
-
-PASS node.element.style.left is &quot;20px&quot;
-PASS node.element.style.left is &quot;10px&quot;
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
</del></span></pre></div>
<a id="trunkLayoutTestsmediamodernmediacontrolslayoutnodenodemadedirtyduringlayouthtml"></a>
<div class="delfile"><h4>Deleted: trunk/LayoutTests/media/modern-media-controls/layout-node/node-made-dirty-during-layout.html (214385 => 214386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/media/modern-media-controls/layout-node/node-made-dirty-during-layout.html        2017-03-24 23:27:14 UTC (rev 214385)
+++ trunk/LayoutTests/media/modern-media-controls/layout-node/node-made-dirty-during-layout.html        2017-03-24 23:32:14 UTC (rev 214386)
</span><span class="lines">@@ -1,40 +0,0 @@
</span><del>-&lt;script src=&quot;../../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
-&lt;script src=&quot;../../../../Source/WebCore/Modules/modern-media-controls/controls/scheduler.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
-&lt;script src=&quot;../../../../Source/WebCore/Modules/modern-media-controls/controls/layout-node.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
-&lt;script src=&quot;../resources/media-controls-utils.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
-
-&lt;script type=&quot;text/javascript&quot;&gt;
-
-description(&quot;Testing the &lt;code&gt;LayoutNode.y&lt;/code&gt; property.&quot;);
-
-window.jsTestIsAsync = true;
-
-class CustomNode extends LayoutNode
-{
-    
-    layout()
-    {
-        super.layout();
-
-        this.x = 10;
-    }
-    
-}
-
-const node = new CustomNode;
-node.x = 20;
-
-let numberOfFrames = 0;
-scheduler.frameDidFire = function()
-{
-    numberOfFrames++;
-    if (numberOfFrames == 1)
-        shouldBeEqualToString(&quot;node.element.style.left&quot;, &quot;20px&quot;);
-    else if (numberOfFrames == 2) {
-        shouldBeEqualToString(&quot;node.element.style.left&quot;, &quot;10px&quot;);
-        finishMediaControlsTest();
-    }
-};
-
-&lt;/script&gt;
-&lt;script src=&quot;../../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
</del></span></pre></div>
<a id="trunkLayoutTestsmediamodernmediacontrolsmediacontrolsmediacontrolsplacardcompressedmetricsexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/media/modern-media-controls/media-controls/media-controls-placard-compressed-metrics-expected.txt (0 => 214386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/media/modern-media-controls/media-controls/media-controls-placard-compressed-metrics-expected.txt                                (rev 0)
+++ trunk/LayoutTests/media/modern-media-controls/media-controls/media-controls-placard-compressed-metrics-expected.txt        2017-03-24 23:32:14 UTC (rev 214386)
</span><span class="lines">@@ -0,0 +1,48 @@
</span><ins>+Testing placard metrics constraints.
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+mediaControls.showPlacard(mediaControls.airplayPlacard)
+PASS placardContainer.children.length is 3
+PASS placardContainer.children[0] instanceof IconButton is true
+PASS placardContainer.children[1].element.className is &quot;title&quot;
+PASS placardContainer.children[2].element.className is &quot;description&quot;
+
+mediaControls.height = 169
+PASS placardContainer.children.length is 2
+PASS placardContainer.children[0].element.className is &quot;title&quot;
+PASS placardContainer.children[1].element.className is &quot;description&quot;
+
+mediaControls.height = 100
+PASS placardContainer.children.length is 2
+PASS placardContainer.children[0].element.className is &quot;title&quot;
+PASS placardContainer.children[1].element.className is &quot;description&quot;
+
+mediaControls.height = 99
+PASS placardContainer.children.length is 1
+PASS placardContainer.children[0].element.className is &quot;title&quot;
+
+mediaControls.height = 40
+PASS placardContainer.children.length is 1
+PASS placardContainer.children[0].element.className is &quot;title&quot;
+
+mediaControls.height = 39
+PASS placardContainer.children.length is 0
+
+mediaControls.width = 170
+mediaControls.height = 170
+PASS placardContainer.children.length is 3
+PASS placardContainer.children[0] instanceof IconButton is true
+PASS placardContainer.children[1].element.className is &quot;title&quot;
+PASS placardContainer.children[2].element.className is &quot;description&quot;
+
+mediaControls.width = 169
+PASS placardContainer.children.length is 2
+PASS placardContainer.children[0].element.className is &quot;title&quot;
+PASS placardContainer.children[1].element.className is &quot;description&quot;
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsmediamodernmediacontrolsmediacontrolsmediacontrolsplacardcompressedmetricshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/media/modern-media-controls/media-controls/media-controls-placard-compressed-metrics.html (0 => 214386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/media/modern-media-controls/media-controls/media-controls-placard-compressed-metrics.html                                (rev 0)
+++ trunk/LayoutTests/media/modern-media-controls/media-controls/media-controls-placard-compressed-metrics.html        2017-03-24 23:32:14 UTC (rev 214386)
</span><span class="lines">@@ -0,0 +1,70 @@
</span><ins>+&lt;script src=&quot;../../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../resources/media-controls-loader.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
+&lt;body&gt;
+&lt;script type=&quot;text/javascript&quot;&gt;
+
+description(&quot;Testing placard metrics constraints.&quot;);
+
+const mediaControls = new MediaControls({ layoutTraits: LayoutTraits.macOS, width: 400, height: 300 });
+
+mediaControls.showPlacard(mediaControls.airplayPlacard);
+const placardContainer = mediaControls.placard.children[0];
+debug(&quot;mediaControls.showPlacard(mediaControls.airplayPlacard)&quot;);
+shouldBe(&quot;placardContainer.children.length&quot;, &quot;3&quot;);
+shouldBeTrue(&quot;placardContainer.children[0] instanceof IconButton&quot;);
+shouldBeEqualToString(&quot;placardContainer.children[1].element.className&quot;, &quot;title&quot;);
+shouldBeEqualToString(&quot;placardContainer.children[2].element.className&quot;, &quot;description&quot;);
+
+debug(&quot;&quot;);
+debug(&quot;mediaControls.height = 169&quot;);
+mediaControls.height = 169;
+shouldBe(&quot;placardContainer.children.length&quot;, &quot;2&quot;);
+shouldBeEqualToString(&quot;placardContainer.children[0].element.className&quot;, &quot;title&quot;);
+shouldBeEqualToString(&quot;placardContainer.children[1].element.className&quot;, &quot;description&quot;);
+
+debug(&quot;&quot;);
+debug(&quot;mediaControls.height = 100&quot;);
+mediaControls.height = 100;
+shouldBe(&quot;placardContainer.children.length&quot;, &quot;2&quot;);
+shouldBeEqualToString(&quot;placardContainer.children[0].element.className&quot;, &quot;title&quot;);
+shouldBeEqualToString(&quot;placardContainer.children[1].element.className&quot;, &quot;description&quot;);
+
+debug(&quot;&quot;);
+debug(&quot;mediaControls.height = 99&quot;);
+mediaControls.height = 99;
+shouldBe(&quot;placardContainer.children.length&quot;, &quot;1&quot;);
+shouldBeEqualToString(&quot;placardContainer.children[0].element.className&quot;, &quot;title&quot;);
+
+debug(&quot;&quot;);
+debug(&quot;mediaControls.height = 40&quot;);
+mediaControls.height = 40;
+shouldBe(&quot;placardContainer.children.length&quot;, &quot;1&quot;);
+shouldBeEqualToString(&quot;placardContainer.children[0].element.className&quot;, &quot;title&quot;);
+
+debug(&quot;&quot;);
+debug(&quot;mediaControls.height = 39&quot;);
+mediaControls.height = 39;
+shouldBe(&quot;placardContainer.children.length&quot;, &quot;0&quot;);
+
+debug(&quot;&quot;);
+debug(&quot;mediaControls.width = 170&quot;);
+debug(&quot;mediaControls.height = 170&quot;);
+mediaControls.width = 170;
+mediaControls.height = 170;
+shouldBe(&quot;placardContainer.children.length&quot;, &quot;3&quot;);
+shouldBeTrue(&quot;placardContainer.children[0] instanceof IconButton&quot;);
+shouldBeEqualToString(&quot;placardContainer.children[1].element.className&quot;, &quot;title&quot;);
+shouldBeEqualToString(&quot;placardContainer.children[2].element.className&quot;, &quot;description&quot;);
+
+debug(&quot;&quot;);
+debug(&quot;mediaControls.width = 169&quot;);
+mediaControls.width = 169;
+shouldBe(&quot;placardContainer.children.length&quot;, &quot;2&quot;);
+shouldBeEqualToString(&quot;placardContainer.children[0].element.className&quot;, &quot;title&quot;);
+shouldBeEqualToString(&quot;placardContainer.children[1].element.className&quot;, &quot;description&quot;);
+
+debug(&quot;&quot;);
+
+&lt;/script&gt;
+&lt;script src=&quot;../../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
</ins></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (214385 => 214386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2017-03-24 23:27:14 UTC (rev 214385)
+++ trunk/Source/WebCore/ChangeLog        2017-03-24 23:32:14 UTC (rev 214386)
</span><span class="lines">@@ -1,3 +1,79 @@
</span><ins>+2017-03-24  Antoine Quint  &lt;graouts@webkit.org&gt;
+
+        [Modern Media Controls] Remove placard icon if height is compressed
+        https://bugs.webkit.org/show_bug.cgi?id=167935
+        &lt;rdar://problem/30397128&gt;
+
+        Reviewed by Dean Jackson.
+
+        We make the addition of certain Placard children conditional on the placard's metrics. Whenever the
+        media controls metrics changes, the placard, if any, is set to have the same metrics and layout() is
+        called where we ensure that there is enough space, per designs, to have the icon, description and even
+        the title visible. We also make some CSS improvements to guarantee that the description is laid out on
+        two lines at most and that both text labels are trimmed elegantly with an ellipsis shold the width be
+        insufficient to display the whole text.
+
+        Since we would have needed to have more width/height setter overrides to trigger layout, we now make
+        LayoutNode trigger layout() directly and remove the need for subclasses to do this on a per-class basis.
+        We also make layout() a method that can be called safely anytime as it's now no longer part of the DOM
+        commit step, a new commit() method is used instead of that.
+
+        Tests: media/modern-media-controls/layout-node/node-made-dirty-during-commit.html
+               media/modern-media-controls/media-controls/media-controls-placard-compressed-metrics.html
+
+        * Modules/modern-media-controls/controls/layout-node.js:
+        (LayoutNode.prototype.set width):
+        (LayoutNode.prototype.set height):
+        Trigger a call to layout() anytime &quot;width&quot; or &quot;height&quot; is set on any LayoutNode.
+
+        (LayoutNode.prototype.layout):
+        (LayoutNode.prototype.commit):
+        (performScheduledLayout):
+        Make layout() an empty method that subclasses can override easily outside of the DOM commit cycle,
+        its previous implementation is now called &quot;commit()&quot; which is a more accurate name.
+
+        * Modules/modern-media-controls/controls/media-controls.js:
+        (MediaControls.prototype.get placard):
+        (MediaControls.prototype.get showsPlacard):
+        (MediaControls.prototype.showPlacard):
+        (MediaControls.prototype.hidePlacard):
+        (MediaControls.prototype.layout):
+        (MediaControls.prototype.get width): Deleted.
+        (MediaControls.prototype.set width): Deleted.
+        Add a &quot;placard&quot; property to make it simpler to reference the placard instead of making assumptions in
+        several places in that class on the children order. Anytime we run a layout or show the placard, ensure
+        that the placard metrics are synced with the media controls metrics.
+
+        * Modules/modern-media-controls/controls/placard.css:
+        (.placard .container):
+        (.placard .title,):
+        (.placard .description):
+        We now ensure that both the title and description are trimmed with an ellipsis when we run out of space
+        to display them fully.
+
+        * Modules/modern-media-controls/controls/placard.js:
+        (Placard.):
+        (Placard.prototype.layout):
+        We add new constraints to only show the icon, title and description if the placard is tall and wide enough.
+
+        * Modules/modern-media-controls/controls/slider.js:
+        (Slider.prototype.get width): Deleted.
+        (Slider.prototype.set width): Deleted.
+        Removed custom &quot;width&quot; getters and setters now we can just override layout() in case node metrics change.
+
+        * Modules/modern-media-controls/controls/time-control.js:
+        (TimeControl.prototype.set useSixDigitsForTimeLabels):
+        (TimeControl.prototype.layout):
+        (TimeControl.prototype.get width): Deleted.
+        (TimeControl.prototype.set width): Deleted.
+        (TimeControl.prototype._availableWidthHasChanged): Deleted.
+        Removed custom &quot;width&quot; getters and setters now we can just override layout() in case node metrics change.
+
+        * Modules/modern-media-controls/media/media-controller.js:
+        (MediaController):
+        Ensure we flush pending updates at construction time so that we match the size of the media controls right
+        at the first media layout.
+
</ins><span class="cx"> 2017-03-24  Eric Carlson  &lt;eric.carlson@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [MediaStream] &quot;ideal&quot; constraints passed to getUserMedia should affect fitness score
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmodernmediacontrolscontrolslayoutnodejs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/modern-media-controls/controls/layout-node.js (214385 => 214386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/modern-media-controls/controls/layout-node.js        2017-03-24 23:27:14 UTC (rev 214385)
+++ trunk/Source/WebCore/Modules/modern-media-controls/controls/layout-node.js        2017-03-24 23:32:14 UTC (rev 214386)
</span><span class="lines">@@ -30,6 +30,8 @@
</span><span class="cx">         this._pendingDOMManipulation = LayoutNode.DOMManipulation.None;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    // Public
+
</ins><span class="cx">     get x()
</span><span class="cx">     {
</span><span class="cx">         return this._x;
</span><span class="lines">@@ -70,6 +72,7 @@
</span><span class="cx"> 
</span><span class="cx">         this._width = width;
</span><span class="cx">         this.markDirtyProperty(&quot;width&quot;);
</span><ins>+        this.layout();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     get height()
</span><span class="lines">@@ -84,6 +87,7 @@
</span><span class="cx"> 
</span><span class="cx">         this._height = height;
</span><span class="cx">         this.markDirtyProperty(&quot;height&quot;);
</span><ins>+        this.layout();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     get visible()
</span><span class="lines">@@ -213,6 +217,30 @@
</span><span class="cx">             this._updateDirtyState();
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    // Protected
+
+    layout()
+    {
+        // Implemented by subclasses.
+    }
+
+    commit()
+    {
+        if (this._pendingDOMManipulation === LayoutNode.DOMManipulation.Removal) {
+            const parent = this.element.parentNode;
+            if (parent)
+                parent.removeChild(this.element);
+        }
+    
+        for (let propertyName of this._dirtyProperties)
+            this.commitProperty(propertyName);
+
+        this._dirtyProperties.clear();
+
+        if (this._pendingDOMManipulation === LayoutNode.DOMManipulation.Addition)
+            nodesRequiringChildrenUpdate.add(this.parent);
+    }
+
</ins><span class="cx">     commitProperty(propertyName)
</span><span class="cx">     {
</span><span class="cx">         const style = this.element.style;
</span><span class="lines">@@ -236,23 +264,6 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    layout()
-    {
-        if (this._pendingDOMManipulation === LayoutNode.DOMManipulation.Removal) {
-            const parent = this.element.parentNode;
-            if (parent)
-                parent.removeChild(this.element);
-        }
-    
-        for (let propertyName of this._dirtyProperties)
-            this.commitProperty(propertyName);
-
-        this._dirtyProperties.clear();
-
-        if (this._pendingDOMManipulation === LayoutNode.DOMManipulation.Addition)
-            nodesRequiringChildrenUpdate.add(this.parent);
-    }
-
</del><span class="cx">     // Private
</span><span class="cx"> 
</span><span class="cx">     _markNodeManipulation(manipulation)
</span><span class="lines">@@ -305,6 +316,7 @@
</span><span class="cx">     previousDirtyNodes.forEach(node =&gt; {
</span><span class="cx">         node._needsLayout = false;
</span><span class="cx">         node.layout();
</span><ins>+        node.commit();
</ins><span class="cx">     });
</span><span class="cx"> 
</span><span class="cx">     nodesRequiringChildrenUpdate.forEach(node =&gt; node._updateChildren());
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmodernmediacontrolscontrolsmediacontrolsjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/modern-media-controls/controls/media-controls.js (214385 => 214386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/modern-media-controls/controls/media-controls.js        2017-03-24 23:27:14 UTC (rev 214385)
+++ trunk/Source/WebCore/Modules/modern-media-controls/controls/media-controls.js        2017-03-24 23:32:14 UTC (rev 214386)
</span><span class="lines">@@ -59,20 +59,6 @@
</span><span class="cx"> 
</span><span class="cx">     // Public
</span><span class="cx"> 
</span><del>-    get width()
-    {
-        return super.width;
-    }
-
-    set width(width)
-    {
-        if (width === this.width)
-            return;
-
-        super.width = width;
-        this.layout();
-    }
-
</del><span class="cx">     get layoutTraits()
</span><span class="cx">     {
</span><span class="cx">         return this._layoutTraits;
</span><span class="lines">@@ -139,9 +125,14 @@
</span><span class="cx">         this.markDirtyProperty(&quot;scaleFactor&quot;);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    get placard()
+    {
+        return this.children[0] instanceof Placard ? this.children[0] : null;
+    }
+
</ins><span class="cx">     get showsPlacard()
</span><span class="cx">     {
</span><del>-        return this.children[0] instanceof Placard;
</del><ins>+        return !!this.placard;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     showPlacard(placard)
</span><span class="lines">@@ -151,12 +142,13 @@
</span><span class="cx">             children.push(this.controlsBar);
</span><span class="cx"> 
</span><span class="cx">         this.children = children;
</span><ins>+        this.layout();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     hidePlacard()
</span><span class="cx">     {
</span><span class="cx">         if (this.showsPlacard)
</span><del>-            this.children[0].remove();
</del><ins>+            this.placard.remove();
</ins><span class="cx">         this._invalidateChildren();
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -196,6 +188,16 @@
</span><span class="cx">         // Implemented by subclasses as needed.
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    layout()
+    {
+        super.layout();
+
+        if (this.showsPlacard) {
+            this.placard.width = this.width;
+            this.placard.height = this.height;
+        }
+    }
+
</ins><span class="cx">     // Private
</span><span class="cx"> 
</span><span class="cx">     _invalidateChildren()
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmodernmediacontrolscontrolsplacardcss"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/modern-media-controls/controls/placard.css (214385 => 214386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/modern-media-controls/controls/placard.css        2017-03-24 23:27:14 UTC (rev 214385)
+++ trunk/Source/WebCore/Modules/modern-media-controls/controls/placard.css        2017-03-24 23:32:14 UTC (rev 214386)
</span><span class="lines">@@ -39,6 +39,7 @@
</span><span class="cx">     left: 50%;
</span><span class="cx">     top: 50%;
</span><span class="cx">     max-width: 402px;
</span><ins>+    width: 100%;
</ins><span class="cx"> 
</span><span class="cx">     transform: translate(-50%, -50%);
</span><span class="cx"> }
</span><span class="lines">@@ -58,7 +59,10 @@
</span><span class="cx"> 
</span><span class="cx"> .placard .title,
</span><span class="cx"> .placard .description {
</span><ins>+    padding: 0 10px;
</ins><span class="cx">     text-align: center;
</span><ins>+    text-overflow: ellipsis;
+    overflow: hidden;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> .placard .title {
</span><span class="lines">@@ -67,4 +71,8 @@
</span><span class="cx"> 
</span><span class="cx"> .placard .description {
</span><span class="cx">     font-size: 13px;
</span><ins>+    white-space: initial;
+    display: -webkit-box;
+    -webkit-box-orient: vertical;
+    -webkit-line-clamp: 2;
</ins><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmodernmediacontrolscontrolsplacardjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/modern-media-controls/controls/placard.js (214385 => 214386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/modern-media-controls/controls/placard.js        2017-03-24 23:27:14 UTC (rev 214385)
+++ trunk/Source/WebCore/Modules/modern-media-controls/controls/placard.js        2017-03-24 23:32:14 UTC (rev 214386)
</span><span class="lines">@@ -23,10 +23,15 @@
</span><span class="cx">  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</span><span class="cx">  */
</span><span class="cx"> 
</span><ins>+const MinWidthToDisplayIcon = 170;
+const MinHeightToDisplayIcon = 170;
+const MinHeightToDisplayDescription = 100;
+const MinHeightToDisplayTitle = 40;
+
</ins><span class="cx"> class Placard extends LayoutItem
</span><span class="cx"> {
</span><span class="cx"> 
</span><del>-    constructor({ iconName = null, title = &quot;&quot;, description = &quot;&quot;, layoutDelegate = null } = {})
</del><ins>+    constructor({ iconName = null, title = &quot;&quot;, description = &quot;&quot;, width = 400, height = 300, layoutDelegate = null } = {})
</ins><span class="cx">     {
</span><span class="cx">         super({
</span><span class="cx">             element: `&lt;div class=&quot;placard&quot;&gt;&lt;/div&gt;`,
</span><span class="lines">@@ -33,16 +38,41 @@
</span><span class="cx">             layoutDelegate
</span><span class="cx">         });
</span><span class="cx"> 
</span><del>-        const container = this.addChild(new LayoutNode(`&lt;div class=&quot;container&quot;&gt;&lt;/div&gt;`));
</del><ins>+        this._container = this.addChild(new LayoutNode(`&lt;div class=&quot;container&quot;&gt;&lt;/div&gt;`));
</ins><span class="cx">         
</span><del>-        if (iconName)
-            container.addChild(new IconButton(this)).iconName = iconName;
</del><ins>+        if (iconName) {
+            this._iconButton = new IconButton(this);
+            this._iconButton.iconName = iconName;
+        }
</ins><span class="cx"> 
</span><span class="cx">         if (!!title)
</span><del>-            container.addChild(new LayoutNode(`&lt;div class=&quot;title&quot;&gt;${title}&lt;/div&gt;`));
</del><ins>+            this._titleNode = new LayoutNode(`&lt;div class=&quot;title&quot;&gt;${title}&lt;/div&gt;`);
</ins><span class="cx"> 
</span><span class="cx">         if (!!description)
</span><del>-            container.addChild(new LayoutNode(`&lt;div class=&quot;description&quot;&gt;${description}&lt;/div&gt;`));
</del><ins>+            this._descriptionNode = new LayoutNode(`&lt;div class=&quot;description&quot;&gt;${description}&lt;/div&gt;`);
+
+        this.width = width;
+        this.height = height;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    // Protected
+
+    layout()
+    {
+        super.layout();
+
+        const children = [];
+
+        if (this._iconButton &amp;&amp; this.width &gt;= MinWidthToDisplayIcon &amp;&amp; this.height &gt;= MinHeightToDisplayIcon)
+            children.push(this._iconButton);
+
+        if (this._titleNode &amp;&amp; this.height &gt;= MinHeightToDisplayTitle)
+            children.push(this._titleNode);
+
+        if (this._descriptionNode &amp;&amp; this.height &gt;= MinHeightToDisplayDescription)
+            children.push(this._descriptionNode);
+
+        this._container.children = children;
+    }
+
</ins><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmodernmediacontrolscontrolssliderjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/modern-media-controls/controls/slider.js (214385 => 214386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/modern-media-controls/controls/slider.js        2017-03-24 23:27:14 UTC (rev 214385)
+++ trunk/Source/WebCore/Modules/modern-media-controls/controls/slider.js        2017-03-24 23:32:14 UTC (rev 214386)
</span><span class="lines">@@ -64,17 +64,6 @@
</span><span class="cx">         this.needsLayout = true;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    get width()
-    {
-        return super.width;
-    }
-
-    set width(width)
-    {
-        super.width = width;
-        this.needsLayout = true;
-    }
-
</del><span class="cx">     // Protected
</span><span class="cx"> 
</span><span class="cx">     handleEvent(event)
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmodernmediacontrolscontrolstimecontroljs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/modern-media-controls/controls/time-control.js (214385 => 214386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/modern-media-controls/controls/time-control.js        2017-03-24 23:27:14 UTC (rev 214385)
+++ trunk/Source/WebCore/Modules/modern-media-controls/controls/time-control.js        2017-03-24 23:32:14 UTC (rev 214386)
</span><span class="lines">@@ -63,20 +63,9 @@
</span><span class="cx">             return;
</span><span class="cx"> 
</span><span class="cx">         this._useSixDigitsForTimeLabels = flag;
</span><del>-        this._availableWidthHasChanged();
</del><ins>+        this.layout();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    get width()
-    {
-        return super.width;
-    }
-
-    set width(width)
-    {
-        super.width = width;
-        this._availableWidthHasChanged();
-    }
-
</del><span class="cx">     get isSufficientlyWide()
</span><span class="cx">     {
</span><span class="cx">         return this.scrubber.width &gt;= ((this.layoutTraits &amp; LayoutTraits.Compact) ? MinimumScrubberWidthCompact : MinimumScrubberWidthDefault);
</span><span class="lines">@@ -84,8 +73,10 @@
</span><span class="cx"> 
</span><span class="cx">     // Protected
</span><span class="cx"> 
</span><del>-    _availableWidthHasChanged()
</del><ins>+    layout()
</ins><span class="cx">     {
</span><ins>+        super.layout();
+
</ins><span class="cx">         const extraWidth = this._useSixDigitsForTimeLabels ? AdditionalTimeLabelWidthOverAnHour : 0;
</span><span class="cx">         const elapsedTimeLabelWidth = ElapsedTimeLabelWidth + extraWidth;
</span><span class="cx">         const remainingTimeLabelWidth = RemainingTimeLabelWidth + extraWidth;
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesmodernmediacontrolsmediamediacontrollerjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/modern-media-controls/media/media-controller.js (214385 => 214386)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/modern-media-controls/media/media-controller.js        2017-03-24 23:27:14 UTC (rev 214385)
+++ trunk/Source/WebCore/Modules/modern-media-controls/media/media-controller.js        2017-03-24 23:32:14 UTC (rev 214386)
</span><span class="lines">@@ -44,6 +44,7 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         this._updateControlsIfNeeded();
</span><ins>+        scheduler.flushScheduledLayoutCallbacks();
</ins><span class="cx"> 
</span><span class="cx">         shadowRoot.addEventListener(&quot;resize&quot;, this);
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>