Skip to content

Conversation

nondebug
Copy link
Collaborator

@nondebug nondebug commented Jun 12, 2025

Closes #???

The following tasks have been completed:

  • Modified Web platform tests (link to pull request)

Implementation commitment:


Preview | Diff

Update webdriver CDDL type definitions.
Move all bounds information into SimulateGamepadParams.
Remove vendor/product/name parameters.
Remove "flush" action and move its functionality to "pause".
Add steps for processing and dispatching actions.
@nondebug nondebug added TPAC2025 Topics for discussion at TPAC 2025 and removed TPAC2025 Topics for discussion at TPAC 2025 labels Aug 27, 2025
Co-authored-by: Marcos Cáceres <[email protected]>
</p>
<p>
An [=input value=] may have an associated <dfn>HID usage identifier</dfn>, a 32-bit value that identifies the type of data represented by the input value.
A HID usage does not precisely describe the [=input control layout=], but by convention many [=gamepads=] with similar layouts use similar usages.
Copy link

@sadym-chromium sadym-chromium Sep 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

by convention many [=gamepads=] with similar layouts use similar usages

It would be great to link a resource with the list of conventional HID usage identifiers. Even if it is not strictly standardizes, it would be helpful to have such a list for reference.

time. A [=touch point=] has a <dfn>touch x coordinate</dfn>
and a <dfn>touch y coordinate</dfn> representing the position in the [=touch surface=]'s coordinate system.
If a [=touch surface=] is on the top, bottom, front, or back side of the [=gamepad=] then the [=touch x coordinate=] is measured along the left-right axis, otherwise it is measured along the top-bottom axis.
The [=touch y coordinate=] is measured along the perpendicular axis.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIT: should we define the specific orientation of the the perpendicular axis?

</p>
<ol>
<li>
Return 2 (|value| − |minimum|) / (|maximum| − |minimum|) − 1.
Copy link

@sadym-chromium sadym-chromium Sep 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would expect the normalized output of input with min 1, max 5 and val 3 to be 1/2:

Suggested change
Return 2 (|value| − |minimum|) / (|maximum| − |minimum|) − 1.
Return (|value| − |minimum|) / (|maximum| − |minimum|).

Comment on lines 809 to 810
To <dfn>map and normalize axes</dfn> for |gamepad:Gamepad|, run the
following steps:
Copy link

@sadym-chromium sadym-chromium Sep 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIT: The definition below now can be formulated in strict terms introduced previously: input values #dfn-input-values and axis list #dfn-axis-list

<li>Let |axisValues:list| be a [=list=] of {{unsigned long}} values
representing the most recent logical axis input values for each axis
input of the device represented by |gamepad|.
</li>```

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also mappedIndex is not used, so probably it can be omitted.

Comment on lines 1361 to +1589
<li>[=Issue a haptic effect=] to the actuator with |type|,
|params|, and the |playEffectTimestamp|.
</li>
<li>If |this|'s [=gamepad=] is a [=simulated gamepad=], run the steps to [=vibrate a simulated gamepad=] for |this|'s [=gamepad=] with |params|.
</li>
Copy link

@sadym-chromium sadym-chromium Sep 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume we should do only one of these steps:

Suggested change
<li>[=Issue a haptic effect=] to the actuator with |type|,
|params|, and the |playEffectTimestamp|.
</li>
<li>If |this|'s [=gamepad=] is a [=simulated gamepad=], run the steps to [=vibrate a simulated gamepad=] for |this|'s [=gamepad=] with |params|.
</li>
<li>If |this|'s [=gamepad=] is a [=simulated gamepad=], run the steps to [=vibrate a simulated gamepad=] for |this|'s [=gamepad=] with |params|.
</li>
<li>Otherwise, [=issue a haptic effect=] to the actuator with |type|,
|params|, and the |playEffectTimestamp|.
</li>

</h3>
<p>
When a gamepad becomes available on the system, run the following
<dfn>When a gamepad becomes available on the system</dfn>, run the following

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe it's more correct to split this into a trigger and a process.

Suggested change
<dfn>When a gamepad becomes available on the system</dfn>, run the following
When a [=gamepad=] <var>gamepad</var> becomes available on the system,
[=emit `gamepadconnected` event=] for <var>gamepad</var>.
</p>
<p>
To <dfn>emit `gamepadconnected` event</dfn> for given [=gamepad=] <var>gamepad</var>, run the following

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also I believe the [=current global object=] is ambiguous, especially in case of simulated devices.

</h3>
<p>
When a gamepad becomes unavailable on the system, run the following
<dfn>When a gamepad becomes unavailable on the system</dfn>, run the following

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same issue as with When a gamepad becomes available on the system.

It is OPTIONAL for a [=user agent=] to support them.
</p>
<p>
Each [=top-level traversable=] has a <dfn>simulated gamepad map</dfn> which is an [=ordered map=] of [=version 4 UUIDs=] to [=gamepad input sources=].
Copy link

@sadym-chromium sadym-chromium Sep 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the UUID key it sufficient and we don't need to have it ordered map.

Suggested change
Each [=top-level traversable=] has a <dfn>simulated gamepad map</dfn> which is an [=ordered map=] of [=version 4 UUIDs=] to [=gamepad input sources=].
Each [=top-level traversable=] has a <dfn>simulated gamepad map</dfn> which is a [=map=] of [=version 4 UUID=] and [=gamepad input source=].

It is OPTIONAL for a [=user agent=] to support them.
</p>
<p>
Each [=top-level traversable=] has a <dfn>simulated gamepad map</dfn> which is an [=ordered map=] of [=version 4 UUIDs=] to [=gamepad input sources=].

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps it's simulated gamepad, not gamepad input source:

Suggested change
Each [=top-level traversable=] has a <dfn>simulated gamepad map</dfn> which is an [=ordered map=] of [=version 4 UUIDs=] to [=gamepad input sources=].
Each [=top-level traversable=] has a <dfn>simulated gamepad map</dfn> which is an [=ordered map=] of [=version 4 UUIDs=] to [=simulated gamepad=].

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the UUID version is important only when it is generated:

Suggested change
Each [=top-level traversable=] has a <dfn>simulated gamepad map</dfn> which is an [=ordered map=] of [=version 4 UUIDs=] to [=gamepad input sources=].
Each [=top-level traversable=] has a <dfn>simulated gamepad map</dfn> which is an [=ordered map=] of [=UUID=] to [=gamepad input sources=].

<pre class="cddl">
emulation.GamepadBounds = {
max: float64,
? min: float64,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can define .default in CDDL like this:

Suggested change
? min: float64,
? min: float64 .default 0.0,

<pre class="cddl">
emulation.SimulateGamepadParams = {
type: "gamepad",
context: browsingContext.BrowsingContext,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IDK if we can cross-reference CDDL to BiDi spec, so let's use text the same way Bluetooth spec does.

Suggested change
context: browsingContext.BrowsingContext,
context: text,

Let |simulatedGamepads| be the [=simulated gamepad map=].
</li>
<li>
If |simulatedGamepads|[|params|.|deviceId|] does not [=map/exist=], abort these steps.
Copy link

@sadym-chromium sadym-chromium Sep 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. We should return a error if there is no such an simulated device.
  2. params is a map, so |params|["<code>deviceId</code>"] is the correct way to access it's values by keys.
Suggested change
If |simulatedGamepads|[|params|.|deviceId|] does not [=map/exist=], abort these steps.
If |simulatedGamepads|[|params|["<code>deviceId</code>"]] does not [=map/exist=], return [=error=]
with [=error code=] [=invalid argument=].

If |simulatedGamepads|[|params|.|deviceId|] does not [=map/exist=], abort these steps.
</li>
<li>
Let |gamepad| be |simulatedGamepads|[|params|.|deviceId|].

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Let |gamepad| be |simulatedGamepads|[|params|.|deviceId|].
Let |gamepad| be |simulatedGamepads|[|params|["<code>deviceId</code>"]].

Run the steps [=when a gamepad becomes unavailable on the system=] with |gamepad|.
</li>
<li>
[=map/Remove=] |simulatedGamepads|[|params|.|deviceId|].

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
[=map/Remove=] |simulatedGamepads|[|params|.|deviceId|].
[=map/Remove=] |simulatedGamepads|[|params|["<code>deviceId</code>"]].

}
</pre>
<p>
To get <dfn>the identifier for a simulated gamepad</dfn> |gamepad|:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optionally, we can also extend the definition of "simulated gamepad" as "Simulated gamepad has an associated [=UUID=] simulated gamepad identifier".

Let |deviceId:string| be [=the identifier for a simulated gamepad=] |gamepad|.
</li>
<li>
If |deviceId| is `null`, abort these steps.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we want to notify the user that the given gamepad is removed by throwing an exception?

Let |channels| be the [=list=] « `"strongMagnitude"`, `"weakMagnitude"`, `"leftTrigger"`, `"rightTrigger"` ».
</li>
<li>
[=list/For each=] |channel| of |channels|:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It means that we ignore all other potential values. IDK if this is correct, and how extensible it is.

Let |body| be a [=map=] matching the `emulation.SimulatedDeviceEvent` production with the `params` field set to |eventParams|.
</li>
<li>
Let |relatedNavigables| be a [=set=] containing |navigable|.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: this means that even if the event was initiated from an iframe, the event will be emitted only on the top-level navigable. I believe this is fine.

Gamepad Input Source
</h4>
<p>
A <dfn>gamepad input source</dfn> is an [=input source=] that is associated with a [=gamepad=]-like device.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need the gamepad input source instance? Cannot it be a simulated gamepad?

</dl>
</section>
<p>
Extend the dispatch action algorithm table in [=dispatch tick actions=] with the following table:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add reference to the WebDriver Classic spec, where dispatch tick actions is defined:

spec: WEBDRIVER; urlPrefix: https://w3c.github.io/webdriver/
    text: dispatch tick actions; url: dfn-dispatch-tick-actions

Let |simulated gamepads| be the [=simulated gamepad map=].
</li>
<li>
If |simulated gamepads|[|device id|] does not [=map/exist=], abort these steps.
Copy link

@sadym-chromium sadym-chromium Sep 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Return a error with "invalid argument" or a new error like "no such simulated gamepad"

<p>
A [=gamepad input source=] has the following items:
</p>
<table>
Copy link

@sadym-chromium sadym-chromium Sep 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider defining the gamepad input source (or simulated gamepad) as a [=struct=] with [=struct/item=] (example). That would allow for referencing the items with the links to it's definitions and search for references (example).

Let |action| be an [=action object=] constructed with arguments |id|, `"gamepad"`, and |subtype|.
</li>
<li>
If |subtype| is `"pause"`, let |result| be the result of [=trying=] to [=process a pause action=] with arguments |action item| and |action|, and return |result|.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This and other calls can be simplified:

Suggested change
If |subtype| is `"pause"`, let |result| be the result of [=trying=] to [=process a pause action=] with arguments |action item| and |action|, and return |result|.
If |subtype| is `"pause"`, return the result of [=trying=] to [=process a pause action=] |action item| and |action|.

Comment on lines +3269 to +3271
<li>
Return [=success=] with data |action|.
</li>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should not it be an "invalid argument" error, as the actions is unknown?

Actions
</h4>
<p>
To <dfn>process a gamepad action</dfn> given |id| and |action item|:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like this part is not finished yet. Please let me know if I can help with it.

Co-authored-by: Maksim Sadym <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants