Skip to content

Commit

Permalink
Fullscreen/unfullscreen ASAP; fire events in animation frame tasks
Browse files Browse the repository at this point in the history
This means that changes to document.fullscreenElement and other state
will be observable as soon as the resize itself is (e.g. via
window.innerWidth) and before resize or scroll events are fired.

The fullscreenchange event is still delayed to animation frame timing.

This also includes a slight change when /resize/ is true in "exit
fullscreen". By changing /doc/ to /topLevelDoc/ in this case, we can
make sure that we always fully unfullscreen all documents in this case.
This makes a "fully exit fullscreen" corner case unnecessary.

Fixes #74.
  • Loading branch information
foolip committed May 31, 2017
1 parent c186c6e commit f86c078
Showing 1 changed file with 76 additions and 88 deletions.
164 changes: 76 additions & 88 deletions fullscreen.bs
Original file line number Diff line number Diff line change
Expand Up @@ -247,68 +247,65 @@ these steps:
<!-- cross-process -->

<li>
<p>As part of the next <a>animation frame task</a>, run these substeps:

<ol>
<li>
<p>If any of the following conditions are false, then set <var>error</var> to true:

<ul>
<li><p><var>pending</var>'s <a>node document</a> is <var>pendingDoc</var>.
<p>If any of the following conditions are false, then set <var>error</var> to true:

<li><p>The <a>fullscreen element ready check</a> for <var>pending</var> returns true.
<!-- cross-process; check is only needed on pending as it is recursive already -->
</ul>
<ul>
<li><p><var>pending</var>'s <a>node document</a> is <var>pendingDoc</var>.

<li><p>If <var>error</var> is true, <a>fire a fullscreen event</a> named
<code>fullscreenerror</code> for (<var>pending</var>, <var>pendingDoc</var>), reject
<var>promise</var> with a <code>TypeError</code> exception, and terminate these steps.
<li><p>The <a>fullscreen element ready check</a> for <var>pending</var> returns true.
<!-- cross-process; check is only needed on pending as it is recursive already -->
</ul>

<li><p>Let <var>fullscreenElements</var> be an <a>ordered set</a> initially consisting of
<var>pending</var>.
<li>
<p>If <var>error</var> is true:

<li><p><a>While</a> the first element in <var>fullscreenElements</var> is in a
<a>nested browsing context</a>: <a for=set>prepend</a> its <a>browsing context container</a> to
<var>fullscreenElements</var>.
<!-- cross-process -->
<ol>
<li><p><a>Queue an animation frame task</a> for <var>pendingDoc</var> to
<a>fire a fullscreen event</a> named <code>fullscreenerror</code> for (<var>pending</var>,
<var>pendingDoc</var>).

<li><p>Let <var>eventPairs</var> be a new <a>ordered set</a>.
<li><p>Reject <var>promise</var> with a <code>TypeError</code> exception and terminate these
steps.
</ol>

<li>
<p><a>For each</a> <var>element</var> in <var>fullscreenElements</var>:
<li><p>Let <var>fullscreenElements</var> be an <a>ordered set</a> initially consisting of
<var>pending</var>.

<ol>
<li><p>Let <var>doc</var> be <var>element</var>'s <a>node document</a>.
<li><p><a>While</a> the first element in <var>fullscreenElements</var> is in a
<a>nested browsing context</a>: <a for=set>append</a> its <a>browsing context container</a> to
<var>fullscreenElements</var>.
<!-- cross-process -->

<li>
<p>If <var>element</var> is <var>doc</var>'s <a>fullscreen element</a>, <a>continue</a>.
<li>
<p><a>For each</a> <var>element</var> in <var>fullscreenElements</var>:

<p class=note>No need to notify observers when nothing has changed.
<ol>
<li><p>Let <var>doc</var> be <var>element</var>'s <a>node document</a>.

<li><p>Otherwise, <a for=set>append</a> (<var>element</var>, <var>doc</var>) to
<var>eventPairs</var>.
<li>
<p>If <var>element</var> is <var>doc</var>'s <a>fullscreen element</a>, <a>continue</a>.

<li><p>If <var>element</var> is <var>pending</var> and <var>pending</var> is an <{iframe}>
<a>element</a>, then set <var>element</var>'s <a>iframe fullscreen flag</a>.
<p class=note>No need to notify observers when nothing has changed.

<li><p><a lt="fullscreen an element">Fullscreen <var>element</var></a> within <var>doc</var>.
</ol>
<li><p>If <var>element</var> is <var>pending</var> and <var>pending</var> is an <{iframe}>
<a>element</a>, then set <var>element</var>'s <a>iframe fullscreen flag</a>.

<li><p><a>For each</a> (<var>element</var>, <var>document</var>) in <var>eventPairs</var>:
<a>fire a fullscreen event</a> named <code>fullscreenchange</code> for (<var>element</var>,
<var>document</var>).
</ol>
<li><p><a lt="fullscreen an element">Fullscreen <var>element</var></a> within <var>doc</var>.

<li><p>Resolve <var>promise</var> with undefined.
<li><p><a>Queue an animation frame task</a> for <var>doc</var> to <a>fire a fullscreen event</a>
named <code>fullscreenchange</code> for (<var>element</var>, <var>document</var>).
</ol>

<p class=XXX><dfn>Animation frame task</dfn> is not really defined yet, including relative order
within that task, see <a href=https://www.w3.org/Bugs/Public/show_bug.cgi?id=26440>bug 26440</a>.
<p class=note>The order in which elements are <a lt="fullscreen an element">fullscreened</a>
and animation frame tasks are queued is not observable, because the animation frame tasks will run
in <a>tree order</a>.

<p class=note>Implementations with out-of-process <a for=/>browsing contexts</a> are left as an
exercise to the reader. Input welcome on potential improvements.
<li><p>Resolve <var>promise</var> with undefined.
</ol>

<p class=note>Implementations with out-of-process <a for=/>browsing contexts</a> are left as an
exercise to the reader. Input welcome on potential improvements.

<p>The <dfn attribute for=Document><code>fullscreenEnabled</code></dfn> attribute's getter must
return true if the <a>context object</a> is <a>allowed to use</a> the feature indicated by attribute
name <code>allowfullscreen</code> and <a>fullscreen is supported</a>, and false otherwise.
Expand Down Expand Up @@ -394,66 +391,57 @@ could be an open <{dialog}> element.
<!-- cross-process -->

<li><p>If <var>topLevelDoc</var> is in <var>docs</var>, and it is a
<a>simple fullscreen document</a>, then set <var>resize</var> to true.
<a>simple fullscreen document</a>, then set <var>doc</var> to <var>topLevelDoc</var> and
<var>resize</var> to true.

<li><p>Return <var>promise</var>, and run the remaining steps <a>in parallel</a>.

<li><p>If <var>resize</var> is true, resize <var>topLevelDoc</var>'s viewport to its "normal"
dimensions.
<li><p>If <var>resize</var> is true, resize <var>doc</var>'s viewport to its "normal" dimensions.

<li>
<p>As part of the next <a>animation frame task</a>, run these substeps:

<ol>
<li><p>If <var>doc</var>'s <a>fullscreen element</a> is null, then resolve <var>promise</var>
with undefined and terminate these steps.

<li><p>Let <var>exitDocs</var> be the result of
<a lt="collect documents to unfullscreen">collecting documents to unfullscreen</a> given
<var>doc</var>.
<!-- cross-process -->

<li><p>If <var>resize</var> is true and <var>topLevelDoc</var> is either not in
<var>exitDocs</var>, or not a <a>simple fullscreen document</a>,
<a>fully exit fullscreen</a> <var>topLevelDoc</var>, reject <var>promise</var> with a
<code>TypeError</code> exception, and terminate these steps.
<!-- cross-process -->
<li><p>If <var>doc</var>'s <a>fullscreen element</a> is null, then resolve <var>promise</var> with
undefined and terminate these steps.

<li><p>Let <var>eventPairs</var> be a new <a>ordered set</a>.

<li><p>Let <var>descendantDocs</var> be an <a>ordered set</a> consisting of <var>doc</var>'s
<a>descendant browsing contexts</a>' <a>active documents</a> whose <a>fullscreen element</a> is
non-null, if any, in <em>reverse</em> <a>tree order</a>.
<!-- cross-process -->
<li><p>Let <var>exitDocs</var> be the result of
<a lt="collect documents to unfullscreen">collecting documents to unfullscreen</a> given
<var>doc</var>.
<!-- cross-process -->

<li>
<p><a>For each</a> <var>descendantDoc</var> in <var>descendantDocs</var>:
<li><p>Let <var>descendantDocs</var> be an <a>ordered set</a> consisting of <var>doc</var>'s
<a>descendant browsing contexts</a>' <a>active documents</a> whose <a>fullscreen element</a> is
non-null, if any, in <a>tree order</a>.
<!-- cross-process -->

<ol>
<li><p><a for=set>Append</a> (<var>descendantDoc</var>'s <a>fullscreen element</a>,
<var>descendantDoc</var>) to <var>eventPairs</var>.
<li>
<p><a>For each</a> <var>exitDoc</var> in <var>exitDocs</var>:

<li><p><a lt="unfullscreen a document">Unfullscreen <var>descendantDoc</var></a>.
</ol>
<ol>
<li><p><a>Queue an animation frame task</a> for <var>exitDoc</var> to
<a>fire a fullscreen event</a> named <code>fullscreenchange</code> for
(<var>exitDoc</var>'s <a>fullscreen element</a>, <var>exitDoc</var>).

<li>
<p><a>For each</a> <var>exitDoc</var> in <var>exitDocs</var>:
<li><p>If <var>resize</var> is true, <a lt="unfullscreen a document">unfullscreen
<var>exitDoc</var></a>.

<ol>
<li><p><a for=set>Append</a> (<var>exitDoc</var>'s <a>fullscreen element</a>,
<var>exitDoc</var>) to <var>eventPairs</var>.
<li><p>Otherwise, <a lt="unfullscreen an element">unfullscreen</a> <var>exitDoc</var>'s
<a>fullscreen element</a>.
</ol>

<li><p><a lt="unfullscreen an element">Unfullscreen</a> <var>exitDoc</var>'s <a>fullscreen element</a>.
</ol>
<li>
<p><a>For each</a> <var>descendantDoc</var> in <var>descendantDocs</var>:

<li><p><a>For each</a> (<var>element</var>, <var>document</var>) in <var>eventPairs</var>:
<a>fire a fullscreen event</a> named <code>fullscreenchange</code> for (<var>element</var>,
<var>document</var>).
<ol>
<li><p><a>Queue an animation frame task</a> for <var>descendantDoc</var> to
<a>fire a fullscreen event</a> named <code>fullscreenchange</code> for
(<var>descendantDoc</var>'s <a>fullscreen element</a>, <var>descendantDoc</var>).

<li><p>Resolve <var>promise</var> with undefined.
<li><p><a lt="unfullscreen a document">Unfullscreen <var>descendantDoc</var></a>.
</ol>

<p class=note>This results in events being fired from the innermost to the outermost document.
<p class=note>The order in which documents are <a lt="unfullscreen a document">unfullscreened</a>
and animation frame tasks are queued is not observable, because the animation frame tasks will run
in <a>tree order</a>.

<li><p>Resolve <var>promise</var> with undefined.
</ol>

<p>The <dfn method for=Document><code>exitFullscreen()</code></dfn> method, when invoked, must
Expand Down

0 comments on commit f86c078

Please sign in to comment.