Skip to content

Commit 245a2f4

Browse files
jgrahamsadym-chromiumwhimboo
committed
Add an input module with performActions and releaseActions commands (#175)
This adds support for user input, exactly following the actions model from classic WebDriver. The user sends a list of input devices, and the state change (if any) of each device in each time period ("tick"). The implementation then converts this into a list of ticks and performs the relevant state updates in each time period. By supporting multiple devices acting simultaneously it's possible to model complex multi-device interactions e.g. multitouch gestures combined with different key input states. Compared with classic WebDriver, the main difference is that it's possible to target the actions at any browsing context, not just the active browsing context. Co-authored-by: Maksim Sadym <[email protected]> Co-authored-by: Henrik Skupin <[email protected]>
1 parent 80bae9a commit 245a2f4

File tree

1 file changed

+318
-0
lines changed

1 file changed

+318
-0
lines changed

index.bs

Lines changed: 318 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,23 +35,31 @@ spec: RFC8610; urlPrefix: https://tools.ietf.org/html/rfc8610
3535
spec: WEBDRIVER; urlPrefix: https://w3c.github.io/webdriver/
3636
type: dfn
3737
text: WebDriver new session algorithm; url: dfn-webdriver-new-session-algorithm
38+
text: actions options; url: dfn-actions-options
3839
text: active sessions; url: dfn-active-session
3940
text: additional WebDriver capability; url: dfn-additional-webdriver-capability
4041
text: additional capability deserialization algorithm; url: dfn-additional-capability-deserialization-algorithm
4142
text: capability name; url: dfn-capability-name
4243
text: create a session; url: dfn-create-a-session
44+
text: dispatch actions; url: dfn-dispatch-actions
45+
text: dispatch tick actions; url: dfn-dispatch-tick-actions
4346
text: draw a bounding box from the framebuffer; url: dfn-draw-a-bounding-box-from-the-framebuffer
4447
text: encode a canvas as Base64; url: dfn-encoding-a-canvas-as-base64
4548
text: endpoint node; url: dfn-endpoint-node
4649
text: error code; url: dfn-error-code
4750
text: error; url: dfn-errors
51+
text: extract an action sequence; url: dfn-extract-an-action-sequence
4852
text: get a node; url: dfn-get-a-node
4953
text: get or create a node reference; url: dfn-get-or-create-a-node-reference
5054
text: getting a property; url: dfn-get-a-property
55+
text: get element origin; url: dfn-get-element-origin
56+
text: get the input state; url: dfn-get-the-input-state
5157
text: http session; url: dfn-http-session
58+
text: input cancel list; url: dfn-input-cancel-list
5259
text: intermediary node; url: dfn-intermediary-node
5360
text: invalid argument; url: dfn-invalid-argument
5461
text: invalid session id; url: dfn-invalid-session-id
62+
text: is element origin; url: dfn-is-element-origin
5563
text: local end; url: dfn-local-ends
5664
text: matched capability serialization algorithm; url: dfn-matched-capability-serialization-algorithm
5765
text: maximum active sessions; url: dfn-maximum-active-sessions
@@ -63,6 +71,7 @@ spec: WEBDRIVER; urlPrefix: https://w3c.github.io/webdriver/
6371
text: readiness state; url: dfn-readiness-state
6472
text: remote end steps; url: dfn-remote-end-steps
6573
text: remote end; url: dfn-remote-ends
74+
text: reset the input state; url: dfn-reset-the-input-state
6675
text: session ID; url: dfn-session-id
6776
text: session not created; url: dfn-session-not-created
6877
text: session; url: dfn-sessions
@@ -261,6 +270,7 @@ Command = {
261270

262271
CommandData = (
263272
BrowsingContextCommand //
273+
InputCommand //
264274
ScriptCommand //
265275
SessionCommand
266276
)
@@ -321,6 +331,7 @@ EventData = (
321331
<pre class="cddl remote-cddl local-cddl">
322332
Extensible = (*text => any)
323333

334+
js-int = -9007199254740991..9007199254740991
324335
js-uint = 0..9007199254740991
325336
</pre>
326337

@@ -5755,6 +5766,313 @@ The [=remote end subscribe steps=], with [=subscribe priority=] 10, given
57555766

57565767
</div>
57575768

5769+
## Input ## {#module-input}
5770+
5771+
The <dfn export for=modules>input</dfn> module contains functionality for
5772+
simulated user input.
5773+
5774+
### Definition ### {#module-input-definition}
5775+
5776+
[=remote end definition=]
5777+
5778+
<pre class="cddl remote-cddl">
5779+
5780+
InputCommand = (
5781+
input.PerformActions //
5782+
input.ReleaseActions
5783+
)
5784+
</pre>
5785+
5786+
### Types ### {#module-input-types}
5787+
5788+
#### input.ElementOrigin #### {#type-input-origin}
5789+
5790+
The <code>input.ElementOrigin</code> type represents an {{Element}} that will
5791+
be used as a coordinate origin.
5792+
5793+
<pre class="cddl remote-cddl">
5794+
input.ElementOrigin = {
5795+
type: "element",
5796+
element: SharedReference
5797+
}
5798+
</pre>
5799+
5800+
<div algorithm>
5801+
The <dfn>is <code>input.ElementOrigin</code></dfn> steps given |object| are:
5802+
5803+
1. If |object| is a [=/map=] matching the <code>input.ElementOrigin</code>
5804+
production, return true.
5805+
5806+
1. Return false.
5807+
5808+
</div>
5809+
5810+
<div algorithm>To <dfn>get Element from <code>input.ElementOrigin</code>
5811+
steps</dfn> given |session|:
5812+
5813+
1. Return the following steps, given |origin| and |context|:
5814+
5815+
1. Assert: |origin| matches <code>input.ElementOrigin</code>.
5816+
5817+
<!-- converting to realm here is kind of silly since we immediately convert back
5818+
in [=deserialize remote reference=] -->
5819+
1. Let |document| be |context|'s [=active document=].
5820+
5821+
1. Let |reference| be |origin|["<code>element</code>"]
5822+
5823+
1. Let |environment settings| be the [=environment settings object=] whose
5824+
[=relevant global object=]'s <a>associated <code>Document</code></a> is
5825+
|document|.
5826+
5827+
1. Let |realm| be |environment settings|' [=realm execution context=]'s
5828+
Realm component.
5829+
5830+
1. Let |element| be the result of [=trying=] to [=deserialize remote reference=]
5831+
with |reference|, |realm|, and |session|.
5832+
5833+
1. If |element| doesn't implement {{Element}} return [=error=] with [=error code=]
5834+
[=no such element=].
5835+
5836+
1. Return [=success=] with data |element|.
5837+
5838+
</div>
5839+
5840+
### Commands ### {#module-input-commands}
5841+
5842+
#### The input.performActions Command #### {#command-input-performActions}
5843+
5844+
The <dfn export for=commands>input.performActions</dfn> command performs a
5845+
specified sequence of user input actions.
5846+
5847+
<dl>
5848+
<dt>Command Type</dt>
5849+
<dd>
5850+
<pre class="cddl remote-cddl">
5851+
input.PerformActions = {
5852+
method: "input.performActions",
5853+
params: input.PerformActionsParameters
5854+
};
5855+
5856+
input.PerformActionsParameters = {
5857+
context: browsingContext.BrowsingContext,
5858+
actions: [*input.SourceActions]
5859+
}
5860+
5861+
input.SourceActions = (
5862+
input.NoneSourceActions //
5863+
input.KeySourceActions //
5864+
input.PointerSourceActions //
5865+
input.WheelSourceActions
5866+
)
5867+
5868+
input.NoneSourceActions = {
5869+
type: "none",
5870+
actions: [*input.NoneSourceAction]
5871+
}
5872+
5873+
input.NoneSourceAction = input.PauseAction
5874+
5875+
input.KeySourceActions = {
5876+
type: "key",
5877+
actions: [*input.KeySourceAction]
5878+
}
5879+
5880+
input.KeySourceAction = (
5881+
input.PauseAction //
5882+
input.KeyDownAction //
5883+
input.KeyUpAction
5884+
)
5885+
5886+
input.PointerSourceActions = {
5887+
type: "pointer",
5888+
? parameters: input.PointerParameters,
5889+
actions: [*input.PointerSourceAction]
5890+
}
5891+
5892+
input.PointerType = "mouse" / "pen" / "touch"
5893+
5894+
input.PointerParameters = {
5895+
?pointerType: input.PointerType .default "mouse"
5896+
}
5897+
5898+
input.PointerSourceAction = (
5899+
input.PauseAction //
5900+
input.PointerDownAction //
5901+
input.PointerUpAction //
5902+
input.PointerMoveAction
5903+
)
5904+
5905+
input.WheelSourceActions = {
5906+
type: "wheel",
5907+
actions: [*input.WheelSourceAction]
5908+
}
5909+
5910+
input.WheelSourceAction = (
5911+
input.PauseAction //
5912+
input.WheelScrollAction
5913+
)
5914+
5915+
input.PauseAction = {
5916+
type: "pause",
5917+
? duration: js-uint
5918+
}
5919+
5920+
input.KeyDownAction = {
5921+
type: "keyDown",
5922+
value: text
5923+
}
5924+
5925+
input.KeyUpAction = {
5926+
type: "keyUp",
5927+
value: text
5928+
}
5929+
5930+
input.PointerUpAction = {
5931+
type: "pointerUp",
5932+
button: js-uint,
5933+
input.PointerCommonProperties
5934+
}
5935+
5936+
input.PointerDownAction = {
5937+
type: "pointerDown",
5938+
button: js-uint,
5939+
input.PointerCommonProperties
5940+
}
5941+
5942+
input.PointerMoveAction = {
5943+
type: "pointerMove",
5944+
x: js-uint,
5945+
y: js-uint,
5946+
? duration: js-uint,
5947+
? origin: input.Origin,
5948+
input.PointerCommonProperties
5949+
}
5950+
5951+
input.WheelScrollAction = {
5952+
type: "scroll",
5953+
x: js-uint,
5954+
y: js-uint,
5955+
deltaX: js-int,
5956+
deltaY: js-int,
5957+
? duration: js-uint,
5958+
? origin: input.Origin .default "viewport",
5959+
}
5960+
5961+
input.PointerCommonProperties = (
5962+
? width: js-uint .default 1,
5963+
? height: js-uint .default 1,
5964+
? pressure: float .default 0.0,
5965+
? tangentialPressure: float .default 0.0,
5966+
? twist: 0..359 .default 0,
5967+
(input.TiltProperties // input.AngleProperties)
5968+
)
5969+
5970+
input.AngleProperties = (
5971+
? altitudeAngle: float .default 0.0,
5972+
? azimuthAngle: float .default 0.0,
5973+
)
5974+
5975+
input.TiltProperties = (
5976+
? tiltX: -90..90 .default 0,
5977+
? tiltY: -90..90 .default 0,
5978+
)
5979+
5980+
input.Origin = "viewport" / "pointer" / input.ElementOrigin
5981+
</pre>
5982+
</dd>
5983+
<dt>Return Type</dt>
5984+
<dd>
5985+
<pre class="cddl">
5986+
EmptyResult
5987+
</pre>
5988+
</dd>
5989+
</dl>
5990+
5991+
<div algorithm="remote end steps for input.performActions">
5992+
5993+
The [=remote end steps=] with |session| and |command parameters| are:
5994+
5995+
1. Let |context id| be the value of the <code>context</code> field of
5996+
|command parameters|.
5997+
5998+
1. Let |context| be the result of [=trying=] to [=get a browsing context=]
5999+
with |context id|.
6000+
6001+
1. Let |input state| be [=get the input state=] with |session| and |context|'s
6002+
[=top-level browsing context=].
6003+
6004+
1. Let |actions options| be a new [=actions options=] with the [=is element
6005+
origin=] steps set to [=is input.ElementOrigin=], and the
6006+
[=get element origin=] steps set to the result of [=get Element from
6007+
input.ElementOrigin steps=] given |session|.
6008+
6009+
1. Let |actions by tick| be the result of trying to [=extract an action
6010+
sequence=] with |input state|, |command parameters|, and |actions options|.
6011+
6012+
1. [=Try=] to [=dispatch actions=] with |input state|, |actions by tick|,
6013+
|context|, and |actions options|.
6014+
6015+
1. Return [=success=] with data null.
6016+
6017+
</div>
6018+
6019+
#### The input.releaseActions Command #### {#command-input-releaseActions}
6020+
6021+
The <dfn export for=commands>input.releaseActions</dfn> command resets the input
6022+
state associated with the current session.
6023+
6024+
<dl>
6025+
<dt>Command Type</dt>
6026+
<dd>
6027+
<pre class="cddl remote-cddl">
6028+
input.ReleaseActions = {
6029+
method: "input.releaseActions",
6030+
params: input.ReleaseActionsParameters
6031+
};
6032+
6033+
input.ReleaseActionsParameters = {
6034+
context: browsingContext.BrowsingContext,
6035+
}
6036+
</pre>
6037+
</dd>
6038+
<dt>Return Type</dt>
6039+
<dd>
6040+
<pre class="cddl">
6041+
EmptyResult
6042+
</pre>
6043+
</dd>
6044+
</dl>
6045+
6046+
<div algorithm="remote end steps for input.releaseActions">
6047+
6048+
The [=remote end steps=] given |session|, and |command parameters| are:
6049+
6050+
1. Let |context id| be the value of the <code>context</code> field of
6051+
|command parameters|.
6052+
6053+
1. Let |context| be the result of [=trying=] to [=get a browsing context=]
6054+
with |context id|.
6055+
6056+
1. Let |top-level context| be |context|'s [=top-level browsing context=].
6057+
6058+
1. Let |input state| be [=get the input state=] with |session| and |top-level context|.
6059+
6060+
1. Let |actions options| be a new [=actions options=] with the [=is element
6061+
origin=] steps set to [=is input.ElementOrigin=], and the
6062+
[=get element origin=] steps set to [=get Element from
6063+
input.ElementOrigin steps=] given |session|.
6064+
6065+
1. Let |undo actions| be |input state|’s [=input cancel list=] in reverse order.
6066+
6067+
1. [=Try=] to [=dispatch tick actions=] with |undo actions|, 0, |context|, and
6068+
|actions options|.
6069+
6070+
1. [=Reset the input state=] with |session| and |top-level context|.
6071+
6072+
1. Return [=success=] with data null.
6073+
6074+
</div>
6075+
57586076
# Patches to Other Specifications # {#patches}
57596077

57606078
This specification requires some changes to external specifications to provide the necessary

0 commit comments

Comments
 (0)