mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-11-10 04:57:26 +01:00
internal/gamepad: bug fix: GUID was not reliable as a unique identifier
Use a HID path as a gamepad unique identifier instead. Closes #3046
This commit is contained in:
parent
3a6aaac5ac
commit
122877c265
@ -58,8 +58,9 @@ const (
|
||||
_DIPH_DEVICE = 0
|
||||
_DIPH_BYID = 2
|
||||
|
||||
_DIPROP_AXISMODE = 2
|
||||
_DIPROP_RANGE = 4
|
||||
_DIPROP_AXISMODE = 2
|
||||
_DIPROP_GUIDANDPATH = 12
|
||||
_DIPROP_RANGE = 4
|
||||
|
||||
_DIPROPAXISMODE_ABS = 0
|
||||
|
||||
@ -280,6 +281,12 @@ type _DIPROPDWORD struct {
|
||||
dwData uint32
|
||||
}
|
||||
|
||||
type _DIPROPGUIDANDPATH struct {
|
||||
diph _DIPROPHEADER
|
||||
guidClass windows.GUID
|
||||
wszPath [_MAX_PATH]uint16
|
||||
}
|
||||
|
||||
type _DIPROPHEADER struct {
|
||||
dwSize uint32
|
||||
dwHeaderSize uint32
|
||||
@ -409,6 +416,14 @@ func (d *_IDirectInputDevice8W) GetDeviceState(cbData uint32, lpvData unsafe.Poi
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *_IDirectInputDevice8W) GetProperty(rguidProp uintptr, pdiph *_DIPROPHEADER) error {
|
||||
r, _, _ := syscall.Syscall(d.vtbl.GetProperty, 3, uintptr(unsafe.Pointer(d)), rguidProp, uintptr(unsafe.Pointer(pdiph)))
|
||||
if uint32(r) != _DI_OK {
|
||||
return fmt.Errorf("gamepad: IDirectInputDevice8::GetProperty failed: %w", handleError(windows.Handle(uint32(r))))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *_IDirectInputDevice8W) Poll() error {
|
||||
r, _, _ := syscall.Syscall(d.vtbl.Poll, 1, uintptr(unsafe.Pointer(d)), 0, 0)
|
||||
if uint32(r) != _DI_OK && uint32(r) != _DI_NOEFFECT {
|
||||
|
@ -294,12 +294,6 @@ func (g *nativeGamepadsDesktop) dinput8EnumDevicesCallback(lpddi *_DIDEVICEINSTA
|
||||
return _DIENUM_STOP
|
||||
}
|
||||
|
||||
if gamepads.find(func(g *Gamepad) bool {
|
||||
return g.native.(*nativeGamepadDesktop).dinputGUID == lpddi.guidInstance
|
||||
}) != nil {
|
||||
return _DIENUM_CONTINUE
|
||||
}
|
||||
|
||||
s, err := supportsXInput(lpddi.guidProduct)
|
||||
if err != nil {
|
||||
g.err = err
|
||||
@ -315,6 +309,42 @@ func (g *nativeGamepadsDesktop) dinput8EnumDevicesCallback(lpddi *_DIDEVICEINSTA
|
||||
return _DIENUM_STOP
|
||||
}
|
||||
|
||||
// lpddi.guidInstance is not relialable as a unique identity when the same multiple devices are connected (#3046).
|
||||
// Use HID Path instead.
|
||||
getDInputPath := func(device *_IDirectInputDevice8W) (string, error) {
|
||||
var prop _DIPROPGUIDANDPATH
|
||||
prop.diph.dwHeaderSize = uint32(unsafe.Sizeof(_DIPROPHEADER{}))
|
||||
prop.diph.dwSize = uint32(unsafe.Sizeof(_DIPROPGUIDANDPATH{}))
|
||||
if err := device.GetProperty(_DIPROP_GUIDANDPATH, &prop.diph); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return windows.UTF16ToString(prop.wszPath[:]), nil
|
||||
}
|
||||
dinputPath, err := getDInputPath(device)
|
||||
if err != nil {
|
||||
g.err = err
|
||||
device.Release()
|
||||
return _DIENUM_STOP
|
||||
}
|
||||
|
||||
var findErr error
|
||||
if gamepads.find(func(g *Gamepad) bool {
|
||||
path, err := getDInputPath(g.native.(*nativeGamepadDesktop).dinputDevice)
|
||||
if err != nil {
|
||||
findErr = err
|
||||
return true
|
||||
}
|
||||
return path == dinputPath
|
||||
}) != nil {
|
||||
if findErr != nil {
|
||||
g.err = findErr
|
||||
device.Release()
|
||||
return _DIENUM_STOP
|
||||
}
|
||||
device.Release()
|
||||
return _DIENUM_CONTINUE
|
||||
}
|
||||
|
||||
dataFormat := _DIDATAFORMAT{
|
||||
dwSize: uint32(unsafe.Sizeof(_DIDATAFORMAT{})),
|
||||
dwObjSize: uint32(unsafe.Sizeof(_DIOBJECTDATAFORMAT{})),
|
||||
@ -395,7 +425,7 @@ func (g *nativeGamepadsDesktop) dinput8EnumDevicesCallback(lpddi *_DIDEVICEINSTA
|
||||
gp.native = &nativeGamepadDesktop{
|
||||
dinputDevice: device,
|
||||
dinputObjects: ctx.objects,
|
||||
dinputGUID: lpddi.guidInstance,
|
||||
dinputPath: dinputPath,
|
||||
dinputAxes: make([]float64, ctx.axisCount+ctx.sliderCount),
|
||||
dinputButtons: make([]bool, ctx.buttonCount),
|
||||
dinputHats: make([]int, ctx.povCount),
|
||||
@ -562,7 +592,7 @@ func (g *nativeGamepadsDesktop) setNativeWindow(nativeWindow uintptr) {
|
||||
type nativeGamepadDesktop struct {
|
||||
dinputDevice *_IDirectInputDevice8W
|
||||
dinputObjects []dinputObject
|
||||
dinputGUID windows.GUID
|
||||
dinputPath string
|
||||
dinputAxes []float64
|
||||
dinputButtons []bool
|
||||
dinputHats []int
|
||||
|
Loading…
Reference in New Issue
Block a user