Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[Modern Media Controls] Controls size lags behind media size
https://bugs.webkit.org/show_bug.cgi?id=169962
<rdar://problem/30340293>

Patch by Antoine Quint <graouts@apple.com> on 2017-03-22
Reviewed by Dean Jackson.

Source/WebCore:

We used to dispatch the "resize" event to the shadow root on a timer and commit changes to the DOM
when handling it inside of a requestAnimationFrame() callback. We now dispatch the "resize" event
as a post-layout task and commit to the DOM right away which ensures immediate size changes of the
controls.

* Modules/modern-media-controls/controls/ios-inline-media-controls.js:
(IOSInlineMediaControls.prototype.layout):
* Modules/modern-media-controls/controls/macos-fullscreen-media-controls.js:
(MacOSFullscreenMediaControls.prototype.layout):
* Modules/modern-media-controls/controls/macos-inline-media-controls.js:
(MacOSInlineMediaControls.prototype.layout):
Making some layout() safer by returning early in case they're called during the object construction
phase, due to the LayoutNode "width" setter now calling that method.

* Modules/modern-media-controls/controls/media-controls.js:
(MediaControls.prototype.get width):
(MediaControls.prototype.set width):
Calling layout() in the "width" setter to ensure that the inline controls layout is invalidated as
soon as the controls width changes instead of waiting on the next rAF to update the layout.

* Modules/modern-media-controls/controls/scheduler.js:
(const.scheduler.new.prototype.flushScheduledLayoutCallbacks):
Add a new method to immediately call queued layouts.

* Modules/modern-media-controls/media/media-controller.js:
(MediaController.prototype.handleEvent):
Flush all queued layouts when handling a "resize" event.

* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::layoutSizeChanged):
Queue the "resize" event as a post-layout task.

(WebCore::HTMLMediaElement::contextDestroyed):
* html/HTMLMediaElement.h:
Remove the queue we no longer use.

LayoutTests:

Updating an existing test to use a "resize" event handler to check that a size change
on the element is reflected on the shadow root. This would have failed prior to this
patch. Also rebaselining a test which now reports correct values.

* media/modern-media-controls/media-controller/media-controller-resize-expected.txt:
* media/modern-media-controls/media-controller/media-controller-resize.html:
* media/modern-media-controls/media-controller/media-controller-scale-factor-audio-expected.txt:
* media/modern-media-controls/media-controller/media-controller-scale-factor-audio.html:

Canonical link: https://commits.webkit.org/186909@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@214282 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
graouts authored and webkit-commit-queue committed Mar 22, 2017
1 parent 2fc3128 commit 166445e
Show file tree
Hide file tree
Showing 14 changed files with 109 additions and 22 deletions.
17 changes: 17 additions & 0 deletions LayoutTests/ChangeLog
@@ -1,3 +1,20 @@
2017-03-22 Antoine Quint <graouts@apple.com>

[Modern Media Controls] Controls size lags behind media size
https://bugs.webkit.org/show_bug.cgi?id=169962
<rdar://problem/30340293>

Reviewed by Dean Jackson.

Updating an existing test to use a "resize" event handler to check that a size change
on the element is reflected on the shadow root. This would have failed prior to this
patch. Also rebaselining a test which now reports correct values.

* media/modern-media-controls/media-controller/media-controller-resize-expected.txt:
* media/modern-media-controls/media-controller/media-controller-resize.html:
* media/modern-media-controls/media-controller/media-controller-scale-factor-audio-expected.txt:
* media/modern-media-controls/media-controller/media-controller-scale-factor-audio.html:

2017-03-22 Youenn Fablet <youenn@apple.com>

Activate remaining webrtc tests
Expand Down
Expand Up @@ -8,8 +8,8 @@ PASS mediaControls.style.width is "320px"
PASS mediaControls.style.height is "240px"

Resizing to 400x300
PASS mediaControls.style.width became "400px"
PASS mediaControls.style.height became "300px"
PASS mediaControls.style.width is "400px"
PASS mediaControls.style.height is "300px"

PASS successfullyParsed is true

Expand Down
Expand Up @@ -16,19 +16,21 @@
shouldBeEqualToString("mediaControls.style.width", "320px");
shouldBeEqualToString("mediaControls.style.height", "240px");

debug("");
debug("Resizing to 400x300");
media.style.width = "400px";
media.style.height = "300px";

shouldBecomeEqualToString("mediaControls.style.width", "400px", () => {
shouldBecomeEqualToString("mediaControls.style.height", "300px", () => {
shadowRoot.addEventListener("resize", () => {
shouldBeEqualToString("mediaControls.style.width", "400px");
shouldBeEqualToString("mediaControls.style.height", "300px");
setTimeout(() => {
debug("");
media.remove();
finishJSTest();
});
});

debug("");
debug("Resizing to 400x300");
media.style.width = "400px";
media.style.height = "300px";

</script>
<script src="../../../resources/js-test-post.js"></script>
</body>
Expand Up @@ -6,7 +6,7 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
PASS shadowRoot.querySelector('.media-controls').style.width is "800px"
PASS shadowRoot.querySelector('.media-controls').style.height is "100px"
PASS shadowRoot.querySelector('.media-controls').style.zoom is "0.5"
PASS shadowRoot.querySelector('.media-controls').style.top is "-25px"
PASS shadowRoot.querySelector('.media-controls').style.top is "-12.5px"

PASS successfullyParsed is true

Expand Down
Expand Up @@ -16,7 +16,7 @@
shouldBeEqualToString("shadowRoot.querySelector('.media-controls').style.width", "800px");
shouldBeEqualToString("shadowRoot.querySelector('.media-controls').style.height", "100px");
shouldBeEqualToString("shadowRoot.querySelector('.media-controls').style.zoom", "0.5");
shouldBeEqualToString("shadowRoot.querySelector('.media-controls').style.top", "-25px");
shouldBeEqualToString("shadowRoot.querySelector('.media-controls').style.top", "-12.5px");

debug("");
media.remove();
Expand Down
44 changes: 44 additions & 0 deletions Source/WebCore/ChangeLog
@@ -1,3 +1,47 @@
2017-03-22 Antoine Quint <graouts@apple.com>

[Modern Media Controls] Controls size lags behind media size
https://bugs.webkit.org/show_bug.cgi?id=169962
<rdar://problem/30340293>

Reviewed by Dean Jackson.

We used to dispatch the "resize" event to the shadow root on a timer and commit changes to the DOM
when handling it inside of a requestAnimationFrame() callback. We now dispatch the "resize" event
as a post-layout task and commit to the DOM right away which ensures immediate size changes of the
controls.

* Modules/modern-media-controls/controls/ios-inline-media-controls.js:
(IOSInlineMediaControls.prototype.layout):
* Modules/modern-media-controls/controls/macos-fullscreen-media-controls.js:
(MacOSFullscreenMediaControls.prototype.layout):
* Modules/modern-media-controls/controls/macos-inline-media-controls.js:
(MacOSInlineMediaControls.prototype.layout):
Making some layout() safer by returning early in case they're called during the object construction
phase, due to the LayoutNode "width" setter now calling that method.

* Modules/modern-media-controls/controls/media-controls.js:
(MediaControls.prototype.get width):
(MediaControls.prototype.set width):
Calling layout() in the "width" setter to ensure that the inline controls layout is invalidated as
soon as the controls width changes instead of waiting on the next rAF to update the layout.

* Modules/modern-media-controls/controls/scheduler.js:
(const.scheduler.new.prototype.flushScheduledLayoutCallbacks):
Add a new method to immediately call queued layouts.

* Modules/modern-media-controls/media/media-controller.js:
(MediaController.prototype.handleEvent):
Flush all queued layouts when handling a "resize" event.

* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::layoutSizeChanged):
Queue the "resize" event as a post-layout task.

(WebCore::HTMLMediaElement::contextDestroyed):
* html/HTMLMediaElement.h:
Remove the queue we no longer use.

2017-03-22 Andy Estes <aestes@apple.com>

Try to fix the Mac CMake build after r214266.
Expand Down
Expand Up @@ -74,7 +74,7 @@ class IOSInlineMediaControls extends MediaControls
{
super.layout();

if (this.controlsBar.visible)
if (this.controlsBar && this.controlsBar.visible)
this.controlsBar.children = this._inlineLayoutSupport.childrenAfterPerformingLayout();
}

Expand Down
Expand Up @@ -94,6 +94,9 @@ class MacOSFullscreenMediaControls extends MacOSMediaControls
{
super.layout();

if (!this._rightContainer)
return;

const numberOfEnabledButtons = this._rightContainer.buttons.filter(button => button.enabled).length;

let buttonMargin = ButtonMarginForFiveButtons;
Expand Down
Expand Up @@ -67,7 +67,7 @@ class MacOSInlineMediaControls extends MacOSMediaControls
{
super.layout();

if (!this.controlsBar.visible)
if (!this.controlsBar || !this.controlsBar.visible)
return;

const children = this._inlineLayoutSupport.childrenAfterPerformingLayout();
Expand Down
Expand Up @@ -59,6 +59,20 @@ class MediaControls extends LayoutNode

// Public

get width()
{
return super.width;
}

set width(width)
{
if (width === this.width)
return;

super.width = width;
this.layout();
}

get layoutTraits()
{
return this._layoutTraits;
Expand Down
Expand Up @@ -43,6 +43,11 @@ const scheduler = new class
this.debug("unscheduleLayout() - end");
}

flushScheduledLayoutCallbacks()
{
this._frameDidFire();
}

// Private

_requestFrameIfNeeded()
Expand Down
Expand Up @@ -113,9 +113,11 @@ class MediaController
{
if (event instanceof TrackEvent && event.currentTarget === this.media.videoTracks)
this._updateControlsIfNeeded();
else if (event.type === "resize" && event.currentTarget === this.shadowRoot)
else if (event.type === "resize" && event.currentTarget === this.shadowRoot) {
this._updateControlsIfNeeded();
else if (event.type === "click" && event.currentTarget === this.container)
// We must immediately perform layouts so that we don't lag behind the media layout size.
scheduler.flushScheduledLayoutCallbacks();
} else if (event.type === "click" && event.currentTarget === this.container)
this._containerWasClicked(event);
else if (event.currentTarget === this.media) {
this._updateControlsIfNeeded();
Expand Down
13 changes: 7 additions & 6 deletions Source/WebCore/html/HTMLMediaElement.cpp
Expand Up @@ -4049,11 +4049,13 @@ void HTMLMediaElement::updateCaptionContainer()
void HTMLMediaElement::layoutSizeChanged()
{
#if ENABLE(MEDIA_CONTROLS_SCRIPT)
auto task = [this, protectedThis = makeRef(*this)] {
if (ShadowRoot* root = userAgentShadowRoot())
root->dispatchEvent(Event::create("resize", false, false));
};
m_resizeTaskQueue.enqueueTask(WTFMove(task));
if (auto* frameView = document().view()) {
auto task = [this, protectedThis = makeRef(*this)] {
if (ShadowRoot* root = userAgentShadowRoot())
root->dispatchEvent(Event::create("resize", false, false));
};
frameView->queuePostLayoutCallback(WTFMove(task));
}
#endif

if (!m_receivedLayoutSizeChanged) {
Expand Down Expand Up @@ -5231,7 +5233,6 @@ void HTMLMediaElement::stopWithoutDestroyingMediaPlayer()
void HTMLMediaElement::contextDestroyed()
{
m_seekTaskQueue.close();
m_resizeTaskQueue.close();
m_shadowDOMTaskQueue.close();
m_promiseTaskQueue.close();
m_pauseAfterDetachedTaskQueue.close();
Expand Down
1 change: 0 additions & 1 deletion Source/WebCore/html/HTMLMediaElement.h
Expand Up @@ -838,7 +838,6 @@ class HTMLMediaElement
Timer m_playbackControlsManagerBehaviorRestrictionsTimer;
Timer m_seekToPlaybackPositionEndedTimer;
GenericTaskQueue<Timer> m_seekTaskQueue;
GenericTaskQueue<Timer> m_resizeTaskQueue;
GenericTaskQueue<Timer> m_shadowDOMTaskQueue;
GenericTaskQueue<Timer> m_promiseTaskQueue;
GenericTaskQueue<Timer> m_pauseAfterDetachedTaskQueue;
Expand Down

0 comments on commit 166445e

Please sign in to comment.