Skip to content

Commit 8f2c2fb

Browse files
darktearsemilio
authored andcommitted
[css-viewport-1] Add automation support for viewport segments
This commits define ways to emulate display features of a device. A display feature is a hardware feature that acts as a divider and creates logically separate regions of the viewport. Using WebDriver developers and user agents will have the opportunity to test or emulate several types of devices.
1 parent 7d73877 commit 8f2c2fb

File tree

3 files changed

+980
-5
lines changed

3 files changed

+980
-5
lines changed

css-viewport-1/Overview.bs

Lines changed: 210 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ spec: fenced-frames; urlPrefix: https://wicg.github.io/fenced-frame/
3232
type: interface; text: FencedFrames
3333
</pre>
3434

35+
<pre class=link-defaults>
36+
spec:webdriver2; type:dfn; text:remote end steps
37+
spec:webdriver2; type:dfn; text:error
38+
</pre>
39+
3540
<h2 id="intro">
3641
Introduction</h2>
3742

@@ -119,6 +124,22 @@ property for the first <code class=html>&lt;BODY&gt;</code> element of
119124
an HTML or XHTML document. For other document types, it is the
120125
computed 'direction' for the root element.
121126

127+
<h3 id="display-feature"><dfn>Display feature</dfn> definition</h3>
128+
A display feature is a hardware feature that acts as a divider
129+
and creates logically separate region of the viewport called {{segments}}.
130+
It can be a fold area of a device with a foldable screen or a physical
131+
split occupying a logical space within the viewport for example some dual
132+
screen models.
133+
134+
Below is an illustration describing the concept of display features and how
135+
they divide the viewport in {{segments}}:
136+
137+
<img src="display_features_general.svg" alt="Two images,
138+
showing two display feature configurations and the respective segments.
139+
One image is showing an vertical display feature, the other is showing
140+
an horizontal display feature" style="width: 70%;height: auto; margin:auto; display: flex;">
141+
142+
122143
<h2 id="viewport-meta">
123144
Viewport <code class=html>&lt;meta&gt;</code> element</h2>
124145

@@ -524,7 +545,6 @@ The <dfn export>unscaled</dfn> value of a CSS length relative to an element is t
524545
and not be divided by the zoom of the element.
525546

526547
The {{Window/devicePixelRatio}} of a frame is multiplied by the [=effective zoom=] inherited by its parent frame.
527-
</h3>
528548

529549
<h2 id=extensions-to-the-window-interface>Extensions to the {{Window}} Interface</h2>
530550

@@ -541,7 +561,7 @@ partial interface Window {
541561
<pre class=idl>
542562
[Exposed=Window]
543563
interface Viewport {
544-
readonly attribute FrozenArray&lt;DOMRect>? segments;
564+
readonly attribute FrozenArray&lt;DOMRect>? segments;
545565
};
546566
</pre>
547567

@@ -554,10 +574,12 @@ Each {{DOMRect}} contains the geometry of the segment (x, y, width, height) in C
554574

555575
Additonal details about the definition of a viewport segment can be found here: [[css-env-1#viewport-segments]].
556576

557-
The {{segments}} attribute must run these steps:
577+
The {{segments}} attribute getter steps are:
558578
1. If the {{Viewport}}'s associated {{Document}} is not <a>fully active</a>, return null.
559-
2. Returns null if there is only a single viewport segment and abort these steps.
560-
3. Otherwise, return the {{Viewport}}'s [[css-env-1#viewport-segments|segments]] array.
579+
2. Let |topLevelTraversable| be |document|'s [=relevant global object=]'s [=/navigable=]'s [=browsing context/top-level traversable=].
580+
3. If |topLevelTraversable|.[=[[DisplayFeaturesOverride]]=] is non-null, return {{Viewport}}'s [[css-env-1#viewport-segments|segments]] array calculated from |topLevelTraversable|.[=[[DisplayFeaturesOverride]]=].
581+
4. Returns null if there is only a single viewport segment and abort these steps.
582+
5. Otherwise, return the {{Viewport}}'s [[css-env-1#viewport-segments|segments]] array calculated from the hardware features.
561583

562584
<div class=non-normative>
563585
<em>This section is not normative.</em>
@@ -608,3 +630,186 @@ This appendix is <em>informative</em>.
608630
<li>Extend [[!CSS3-CONDITIONAL]] rather than CSS21 for nesting in @media.
609631
<li>Removed @viewport
610632
</ul>
633+
634+
<h2 class="no-num" id="automation">Appendix B. Automation</h2>
635+
636+
<h3>Automation of the {{segments}} property</h3>
637+
The {{segments}} property poses a challenge to test authors, as exercising this property
638+
requires access to specific hardware devices. To address this challenge this document defines
639+
[[WEBDRIVER2]] [=extension commands=] that allow users to control how the viewport is split by
640+
one or more [=display feature| display features=] (such as a fold or a hinge between two separate displays).
641+
642+
A <dfn>display feature override</dfn> is a [=struct=] encapsulating the result of a single display feature.
643+
It has a <dfn data-dfn-for="display feature override">orientation</dfn> (a string that is either "vertical" or "horizontal"),
644+
a <dfn data-dfn-for="display feature override">mask length</dfn> (a positive number describing the length of the feature in CSS ''<length>/px''), and
645+
an <dfn data-dfn-for="display feature override">offset</dfn> (which describe the distance from the origin of the viewport in CSS ''<length>/px'').
646+
647+
<h4 id="internal-slots">Internal slots</h4>
648+
To support the [=extension commands=] below and their integration with
649+
the {{segments}} attribute getter steps, [=browsing context/top-level traversables=] must have the following
650+
internal slots:
651+
<table class="def">
652+
<thead>
653+
<tr>
654+
<th>
655+
Internal slot
656+
</th>
657+
<th>
658+
Description
659+
</th>
660+
</tr>
661+
</thead>
662+
<tbody>
663+
<tr>
664+
<td>
665+
<dfn data-dfn-for="top-level traversable">\[[DisplayFeaturesOverride]]</dfn>
666+
</td>
667+
<td>
668+
List of [=display feature override=] that overrides those provided by the hardware, or <code>null</code>.
669+
</td>
670+
</tr>
671+
</tbody>
672+
</table>
673+
674+
<h4 id="extension-commands">Extensions Commands</h4>
675+
676+
<h5 id="set-display-features">Set display features</h5>
677+
<table class="def">
678+
<tr>
679+
<th>
680+
HTTP Method
681+
</th>
682+
<th>
683+
[=extension command URI Template|URI Template=]
684+
</th>
685+
</tr>
686+
<tr>
687+
<td>
688+
POST
689+
</td>
690+
<td>
691+
/session/{session id}/displayfeatures
692+
</td>
693+
</tr>
694+
</table>
695+
696+
This [=extension command=] creates a setup that emulates a set of [=display feature override=] by taking a list of display features as
697+
parameter.
698+
699+
<div class=non-normative>
700+
<em>This section is not normative.</em>
701+
702+
This section exists because the input format is not trivial. Here is a pseudo IDL example on
703+
how a [=display feature override=] is defined:
704+
<pre class="idl">
705+
enum OrientationType {
706+
"vertical",
707+
"horizontal"
708+
};
709+
710+
interface DisplayFeature {
711+
readonly attribute OrientationType orientation;
712+
readonly attribute double offset;
713+
readonly attribute double maskLength;
714+
};
715+
</pre>
716+
717+
Below is an illustration showing the various properties of a display feature:
718+
719+
<img src="display_features.svg" alt="Two images,
720+
showing the meaning of each display feature attributes. One image is showing an
721+
vertical display feature, the other is showing an horizontal display feature" style="width: 70%;height: auto; margin:auto; display: flex;">
722+
723+
<div class="example">
724+
To create a [=[[DisplayFeaturesOverride]]=] in the <a spec="WEBDRIVER2">current browsing context</a> of the [=session=] with ID 23,
725+
the [=local end=] would POST to `/session/23/displayfeatures` with the body:
726+
<pre class="lang-json">
727+
{
728+
"features": [
729+
{
730+
"orientation": "horizontal",
731+
"offset": 190,
732+
"maskLength": 20
733+
}
734+
]
735+
}
736+
</pre>
737+
Considering a viewport of 400px by 400px the command will result of a {{segments}} property with the following content:
738+
<code highlight=javascript>[DOMRect(0, 0, 400, 190), DOMRect(0, 210, 400, 190)]</code>
739+
</div>
740+
</div>
741+
742+
<div>
743+
The [=remote end steps=] are:
744+
</div>
745+
<ol>
746+
<li>Let |features| be the result of invoking <a spec="WEBDRIVER2">getting a property</a> "features" from
747+
|parameters|.
748+
</li>
749+
<li>If |features| is not a {{Array}}, return [=error=] with [=error
750+
code|WebDriver error code=] [=invalid argument=].
751+
</li>
752+
<li>Let |parsedFeatures| be a new <a spec=infra>list</a> of [=display feature override=].</li>
753+
<li>For each |feature item| in |features|:
754+
<ol>
755+
<li>If |feature item| is not an {{Object}}, return [=error=] with [=error code|WebDriver error code=] [=invalid argument=].</li>
756+
<li>Let |mask length| be the result of invoking <a spec="WEBDRIVER2">getting a property</a> "maskLength" from |feature item|.</li>
757+
<li>If |mask length| is not a {{Number}} or its value is {{Number/NaN}}, +∞, −∞, or negative return [=error=] with [=error code|WebDriver error code=] [=invalid argument=].
758+
<li>Let |offset| be the result of invoking <a spec="WEBDRIVER2">getting a property</a> "offset" from |feature item|.</li>
759+
<li>If |offset| is not a {{Number}} or its value is {{Number/NaN}}, +∞, −∞, or negative return [=error=] with [=error code|WebDriver error code=] [=invalid argument=].
760+
<li>Let |orientation| be the result of invoking <a spec="WEBDRIVER2">getting a property</a> "orientation" from |feature item|.</li>
761+
<li>If |orientation| is not a {{string}}, return [=error=] with [=error code|WebDriver error code=] [=invalid argument=].</li>
762+
<li>If |orientation| is neither "vertical" or "vertical", return [=error=] with [=error code|WebDriver error code=] [=invalid argument=].
763+
<li>If |orientation| is "vertical" and |mask length| + |offset| is greater than viewport width including the size of the rendered scrollbar, return [=error=] with [=error code|WebDriver error code=] [=invalid argument=].</li>
764+
<li>If |orientation| is "vertical" and |mask length| + |offset| is greater than viewport height including the size of the rendered scrollbar, return [=error=] with [=error code|WebDriver error code=] [=invalid argument=].</li>
765+
<li>Let |override| be a new [=display feature override=].</li>
766+
<li>Set |override|'s [=mask length=] to |mask length|.</li>
767+
<li>Set |override|'s [=orientation=] to |orientation|.</li>
768+
<li>Set |override|'s [=offset=] to |offset|.</li>
769+
<li>[=list/Append=] |override| to |parsedFeatures|.</li>
770+
</ol>
771+
</li>
772+
<li>Let |topLevelTraversable| be the <a spec="WEBDRIVER2">current browsing context</a>'s
773+
[=browsing context/top-level traversable=].
774+
</li>
775+
<li>Set |topLevelTraversable|.[=[[DisplayFeaturesOverride]]=] to |parsedFeatures|.
776+
</li>
777+
<li>Return [=success=] with data <code>null</code>.
778+
</li>
779+
</ol>
780+
781+
<h5 id="clear-display-features">Clear display features</h5>
782+
<table class="def">
783+
<tr>
784+
<th>
785+
HTTP Method
786+
</th>
787+
<th>
788+
[=extension command URI Template|URI Template=]
789+
</th>
790+
</tr>
791+
<tr>
792+
<td>
793+
DELETE
794+
</td>
795+
<td>
796+
/session/{session id}/displayfeatures
797+
</td>
798+
</tr>
799+
</table>
800+
<div>
801+
This [=extension command=] removes the display features override and returns
802+
control back to hardware.
803+
</div>
804+
<div>
805+
The [=remote end steps=] are:
806+
</div>
807+
<ol>
808+
<li>Let |topLevelTraversable| be the <a spec="WEBDRIVER2">current browsing context</a>'s
809+
[=browsing context/top-level traversable=].
810+
</li>
811+
<li>Set |topLevelTraversable|. [=[[DisplayFeaturesOverride]]=] to <code>null</code>.
812+
</li>
813+
<li>Return [=success=] with data <code>null</code>.
814+
</li>
815+
</ol>

0 commit comments

Comments
 (0)