Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

It is not defined what the value of Gamepad.index should be after disconnecting the gamepad #5

Closed
luser opened this issue Apr 24, 2015 · 2 comments

Comments

@luser
Copy link
Contributor

luser commented Apr 24, 2015

Originally filed as https://www.w3.org/Bugs/Public/show_bug.cgi?id=17309:

Olli Pettay 2012-06-04 14:10:27 UTC

It is not defined what the value of Gamepad.index should be after disconnecting the gamepad. If the index is not changed, then it lies, since the gamepad
isn't anymore in navigator.gamepads.
Perhaps index should become -1 ?

Comment 1 Ted Mielczarek [:ted] 2012-06-04 17:00:01 UTC

Hm. This is a good point. I guess leaving it unchanged would be bad, because if you plugged in a different gamepad, it could reuse the same index, so you could get bad data.

Since this is JS, and we're writing WebIDL, I guess we could just make this a nullable type, and say that it must be set to null when the gamepad is disconnected. Does that sound reasonable?

Comment 2 Olli Pettay 2012-06-04 17:02:56 UTC

Uh, nullable Number values sound pretty horrible.

Comment 3 Ted Mielczarek [:ted] 2012-06-04 17:04:02 UTC

Why? How is that any worse than using -1 as a sigil for "not connected"? null seems like a saner choice in that regard. Either way, the point is just that writing navigator.gamepads[gamepad.index] will throw.

Comment 4 Olli Pettay 2012-06-04 17:10:52 UTC

well, javascript arrays work with number values.
(new Array()).indexOf("anything") == -1

Comment 5 Ted Mielczarek [:ted] 2012-06-04 20:47:08 UTC

I still don't see how that example makes any difference. You can pass anything as the array index, you'll just get back undefined:
a = ['a','b','c']

a[0]
a

a[null] == undefined
true

Comment 6 Olli Pettay 2012-06-04 20:53:19 UTC

I mean, the index of something not in the array is -1, not null.

Comment 7 Ted Mielczarek [:ted] 2013-03-22 15:17:28 UTC

So, the spec currently says "When multiple gamepads are connected to a user agent, indices MUST be assigned on a first-come, first-serve basis, starting at zero. If a gamepad is disconnected, previously assigned indices MUST NOT be reassigned to gamepads that continue to be connected. However, if a gamepad is disconnected, and subsequently the same or a different gamepad is then connected, index entries MUST be reused."

Given that, perhaps we should just leave .index alone, since if you reconnect the same gamepad the spec says the index should be reused?

I suppose the followup question there is "should navigator.getGamepads()[] return the gamepad object with .connected == false, or should it return null?

Comment 8 Scott Graham 2013-03-22 15:52:45 UTC

The important part here is that unplugging #0 doesn't change the index on #1 when 1 continues to be connected.

When 0 is reinserted, it should just find the first empty slot, meaning that if you had 0,1,2 plugged in, unplugged 0 and 1 and then replugged 1 first, it'd be OK for that to become 0 (rather than resuming being 1). If there's some reason for it to stay 1, that's OK too (e.g. the Xbox 360 indicator thingy has the user still assigned as player 1)

Given that, I'm fine with whatever value as a sigil, but it probably makes sense to lose its .index.

Comment 9 Scott Graham 2013-03-22 15:55:06 UTC

(In reply to comment #7)

I suppose the followup question there is "should
navigator.getGamepads()[] return the
gamepad object with .connected == false, or should it return null?

Hmm, good question. When there's no devices at all, I'm just returning undefined which made the most sense at the time. Creating disconnected objects for indices to infinity seems a bit strange.

Stepping back a bit... In the polling model, I'd honestly been thinking of them as "values", not references to be held on to. So, the model was more that you'd get data via navigator.getGamepads()[N], consume it, and then do the same next time you wanted refreshed data. In that model, there wasn't even a connected attribute required because you either got data or undefined in the array. I'm not sure if that model helps though, given the other approach of onconnected events and hanging on to the gamepad objects indefinitely.

Comment 10 Ted Mielczarek [:ted] 2013-03-22 17:32:39 UTC

(In reply to comment #8)

The important part here is that unplugging #0 doesn't change the index on #1
when 1 continues to be connected.

When 0 is reinserted, it should just find the first empty slot, meaning that
if you had 0,1,2 plugged in, unplugged 0 and 1 and then replugged 1 first,
it'd be OK for that to become 0 (rather than resuming being 1). If there's
some reason for it to stay 1, that's OK too (e.g. the Xbox 360 indicator
thingy has the user still assigned as player 1)

Should we loosen up the spec language then? Something like "If a gamepad is disconnected, previously assigned indices MUST NOT be reassigned to gamepads that continue to be connected. However, if a gamepad is disconnected, and subsequently the same or a different gamepad is then connected, index entries MAY be reused. It is RECOMMENDED that when the same gamepad is disconnected and subsequently reconnected that the index value be reused."

(In reply to comment #9)

Hmm, good question. When there's no devices at all, I'm just returning
undefined which made the most sense at the time. Creating disconnected
objects for indices to infinity seems a bit strange.

Sure, that seems sensible, I wasn't proposing having mock objects for all indices. I simply meant "for an index that used to contain a gamepad object that is now disconnected". Should we return undefined after it's disconnected, or should we return the (now-useless) gamepad object?

Stepping back a bit... In the polling model, I'd honestly been thinking of
them as "values", not references to be held on to. So, the model was more
that you'd get data via navigator.getGamepads()[N], consume it, and then do
the same next time you wanted refreshed data. In that model, there wasn't
even a connected attribute required because you either got data or undefined
in the array. I'm not sure if that model helps though, given the other
approach of onconnected events and hanging on to the gamepad objects
indefinitely.

I don't think this is going to fly, because content can stash these objects in arbitrary slots, and will probably expect things to work. I can imagine someone doing something like:
function Player() {} var p = Player(); p.input = navigator.getGamepads()[0];
// ... poll p.input ...

I can also imagine scenarios where someone has implemented a mock Gamepad object (say to abstract away keyboard vs. gamepad input).

(Also note that the "grab the object from the onconnected event" is mostly just a hackaround for my implementation lacking navigator.getGamepads.)

Comment 11 Ted Mielczarek [:ted] 2013-03-29 13:38:58 UTC

Filed bug 21434 to handle spec'ing the "liveness" of Gamepad objects, since that seems to be the root of our confusion here.

@sgraham
Copy link
Contributor

sgraham commented Feb 14, 2018

The liveness seems like the bigger problem here, but the loosened language seems like an OK change.

@sgraham
Copy link
Contributor

sgraham commented Feb 14, 2018

I think given that we've converged on snapshots (?) the index isn't relevant for disconnected any more. Either it's connected and has an index and is in the list, or it's not, and getGamepads() has returned a null, rather than an empty object. Closing based on that, feel free to reopen.

@sgraham sgraham closed this as completed Feb 14, 2018
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

No branches or pull requests

2 participants