This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.

Bug 17309 - It is not defined what the value of Gamepad.index should be after disconnecting the gamepad
Summary: It is not defined what the value of Gamepad.index should be after disconnecti...
Status: RESOLVED MOVED
Alias: None
Product: WebAppsWG
Classification: Unclassified
Component: HISTORICAL - Gamepad (show other bugs)
Version: unspecified
Hardware: PC Linux
: P2 normal
Target Milestone: ---
Assignee: Ted Mielczarek [:ted]
QA Contact: public-webapps-bugzilla
URL:
Whiteboard:
Keywords:
Depends on: 21434
Blocks:
  Show dependency treegraph
 
Reported: 2012-06-04 14:10 UTC by Olli Pettay
Modified: 2015-04-24 10:47 UTC (History)
4 users (show)

See Also:


Attachments

Description 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()[<index of a disconnected gamepad>] 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()[<index of a disconnected gamepad>] 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.
Comment 12 Ted Mielczarek [:ted] 2015-04-24 10:47:56 UTC
Moved to https://github.com/w3c/gamepad/issues/5