@@ -119,6 +124,22 @@ property for the first <BODY> element of
an HTML or XHTML document. For other document types, it is the
computed 'direction' for the root element.
+
Display feature definition
+A display feature is a hardware feature that acts as a divider
+and creates logically separate region of the viewport called {{segments}}.
+It can be a fold area of a device with a foldable screen or a physical
+split occupying a logical space within the viewport for example some dual
+screen models.
+
+Below is an illustration describing the concept of display features and how
+they divide the viewport in {{segments}}:
+
+
+
+
@@ -554,10 +575,12 @@ Each {{DOMRect}} contains the geometry of the segment (x, y, width, height) in C
Additonal details about the definition of a viewport segment can be found here: [[css-env-1#viewport-segments]].
-The {{segments}} attribute must run these steps:
+The {{segments}} attribute getter steps are:
1. If the {{Viewport}}'s associated {{Document}} is not fully active, return null.
-2. Returns null if there is only a single viewport segment and abort these steps.
-3. Otherwise, return the {{Viewport}}'s [[css-env-1#viewport-segments|segments]] array.
+2. Let |topLevelTraversable| be |document|'s [=relevant global object=]'s [=/navigable=]'s [=browsing context/top-level traversable=].
+3. If |topLevelTraversable|.[=[[DisplayFeaturesOverride]]=] is non-null, return {{Viewport}}'s [[css-env-1#viewport-segments|segments]] array calculated from |topLevelTraversable|.[=[[DisplayFeaturesOverride]]=].
+4. Returns null if there is only a single viewport segment and abort these steps.
+5. Otherwise, return the {{Viewport}}'s [[css-env-1#viewport-segments|segments]] array calculated from the hardware features.
This section is not normative.
@@ -572,6 +595,188 @@ If a viewport of 400px by 400px is split horizontally into two side-by-side segm
+
Automation
+The {{segments}} property poses a challenge to test authors, as exercising this property
+requires access to specific hardware devices. To address this challenge this document defines
+[[WEBDRIVER2]] [=extension commands=] that allow users to control how the viewport is split by
+one or more [=display feature| display features=] (such as a fold or a hinge between two separate displays).
+
+A display feature override is a [=struct=] encapsulating the result of a single display feature.
+It has a orientation (a string that is either "vertical" or "horizontal"),
+a mask length (a positive number describing the length of the feature in CSS ''/px''), and
+an offset (which describe the distance from the origin of the viewport in CSS ''/px'').
+
+
Internal slots
+To support the [=extension commands=] below and their integration with
+the {{segments}} attribute getter steps, [=browsing context/top-level traversables=] must have the following
+internal slots:
+
+
+
+
+ Internal slot
+
+
+ Description
+
+
+
+
+
+
+ \[[DisplayFeaturesOverride]]
+
+
+ List of [=display feature override=] that overrides those provided by the hardware, or null.
+
+
+
+
+
+
Extensions Commands
+
+
Set display features
+
+
+
+ HTTP Method
+
+
+ [=extension command URI Template|URI Template=]
+
+
+
+
+ POST
+
+
+ /session/{session id}/displayfeatures
+
+
+
+
+This [=extension command=] creates a setup that emulates a set of [=display feature override=] by taking a list of display features as
+parameter.
+
+
+ This section is not normative.
+
+ This section exists because the input format is not trivial. Here is a pseudo IDL example on
+ how a [=display feature override=] is defined:
+
+
+ Below is an illustration showing the various properties of a display feature:
+
+
+
+
+
+ To create a [=[[DisplayFeaturesOverride]]=] in the current browsing context of the [=session=] with ID 23,
+ the [=local end=] would POST to `/session/23/displayfeatures` with the body:
+
+ Considering a viewport of 400px by 400px the command will result of a {{segments}} property with the following content:
+ [DOMRect(0, 0, 400, 190), DOMRect(0, 210, 400, 190)]
+
+
+
+
+The [=remote end steps=] are:
+
+
+
Let |features| be the result of invoking getting a property "features" from
+ |parameters|.
+
+
If |features| is not a {{Array}}, return [=error=] with [=error
+ code|WebDriver error code=] [=invalid argument=].
+
+
Let |parsedFeatures| be a new list of [=display feature override=].
+
For each |feature item| in |features|:
+
+
If |feature item| is not an {{Object}}, return [=error=] with [=error code|WebDriver error code=] [=invalid argument=].
+
Let |mask length| be the result of invoking getting a property "maskLength" from |feature item|.
+
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=].
+
Let |offset| be the result of invoking getting a property "offset" from |feature item|.
+
If |offset| is not a {{Number}} or its value is {{Number/NaN}}, +∞, −∞, or negative return [=error=] with [=error code|WebDriver error code=] [=invalid argument=].
+
Let |orientation| be the result of invoking getting a property "orientation" from |feature item|.
+
If |orientation| is not a {{string}}, return [=error=] with [=error code|WebDriver error code=] [=invalid argument=].
+
If |orientation| is neither "vertical" or "vertical", return [=error=] with [=error code|WebDriver error code=] [=invalid argument=].
+
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=].
+
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=].
+
Let |override| be a new [=display feature override=].
+
Set |override|'s [=mask length=] to |mask length|.
+
Set |override|'s [=orientation=] to |orientation|.
+
Set |override|'s [=offset=] to |offset|.
+
[=list/Append=] |override| to |parsedFeatures|.
+
+
+
Let |topLevelTraversable| be the current browsing context's
+ [=browsing context/top-level traversable=].
+
+
Set |topLevelTraversable|.[=[[DisplayFeaturesOverride]]=] to |parsedFeatures|.
+
+
Return [=success=] with data null.
+
+
+
+
Clear display features
+
+
+
+ HTTP Method
+
+
+ [=extension command URI Template|URI Template=]
+
+
+
+
+ DELETE
+
+
+ /session/{session id}/displayfeatures
+
+
+
+
+ This [=extension command=] removes the display features override and returns
+ control back to hardware.
+
+
+ The [=remote end steps=] are:
+
+
+
Let |topLevelTraversable| be the current browsing context's
+ [=browsing context/top-level traversable=].
+
+
Set |topLevelTraversable|. [=[[DisplayFeaturesOverride]]=] to null.
+
+
Return [=success=] with data null.
+
+
+
Appendix A. Changes
This appendix is informative.
diff --git a/css-viewport-1/display_features.svg b/css-viewport-1/display_features.svg
new file mode 100644
index 00000000000..a88e94c87e1
--- /dev/null
+++ b/css-viewport-1/display_features.svg
@@ -0,0 +1,379 @@
+
+
diff --git a/css-viewport-1/display_features_general.svg b/css-viewport-1/display_features_general.svg
new file mode 100644
index 00000000000..a85dd8c8885
--- /dev/null
+++ b/css-viewport-1/display_features_general.svg
@@ -0,0 +1,391 @@
+
+