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
bdb176a271
commit
e5bb046a11
@ -59,6 +59,7 @@ const (
|
|||||||
_DIPH_BYID = 2
|
_DIPH_BYID = 2
|
||||||
|
|
||||||
_DIPROP_AXISMODE = 2
|
_DIPROP_AXISMODE = 2
|
||||||
|
_DIPROP_GUIDANDPATH = 12
|
||||||
_DIPROP_RANGE = 4
|
_DIPROP_RANGE = 4
|
||||||
|
|
||||||
_DIPROPAXISMODE_ABS = 0
|
_DIPROPAXISMODE_ABS = 0
|
||||||
@ -280,6 +281,12 @@ type _DIPROPDWORD struct {
|
|||||||
dwData uint32
|
dwData uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type _DIPROPGUIDANDPATH struct {
|
||||||
|
diph _DIPROPHEADER
|
||||||
|
guidClass windows.GUID
|
||||||
|
wszPath [_MAX_PATH]uint16
|
||||||
|
}
|
||||||
|
|
||||||
type _DIPROPHEADER struct {
|
type _DIPROPHEADER struct {
|
||||||
dwSize uint32
|
dwSize uint32
|
||||||
dwHeaderSize uint32
|
dwHeaderSize uint32
|
||||||
@ -409,6 +416,14 @@ func (d *_IDirectInputDevice8W) GetDeviceState(cbData uint32, lpvData unsafe.Poi
|
|||||||
return nil
|
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 {
|
func (d *_IDirectInputDevice8W) Poll() error {
|
||||||
r, _, _ := syscall.Syscall(d.vtbl.Poll, 1, uintptr(unsafe.Pointer(d)), 0, 0)
|
r, _, _ := syscall.Syscall(d.vtbl.Poll, 1, uintptr(unsafe.Pointer(d)), 0, 0)
|
||||||
if uint32(r) != _DI_OK && uint32(r) != _DI_NOEFFECT {
|
if uint32(r) != _DI_OK && uint32(r) != _DI_NOEFFECT {
|
||||||
|
@ -294,12 +294,6 @@ func (g *nativeGamepadsDesktop) dinput8EnumDevicesCallback(lpddi *_DIDEVICEINSTA
|
|||||||
return _DIENUM_STOP
|
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)
|
s, err := supportsXInput(lpddi.guidProduct)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
g.err = err
|
g.err = err
|
||||||
@ -315,6 +309,42 @@ func (g *nativeGamepadsDesktop) dinput8EnumDevicesCallback(lpddi *_DIDEVICEINSTA
|
|||||||
return _DIENUM_STOP
|
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{
|
dataFormat := _DIDATAFORMAT{
|
||||||
dwSize: uint32(unsafe.Sizeof(_DIDATAFORMAT{})),
|
dwSize: uint32(unsafe.Sizeof(_DIDATAFORMAT{})),
|
||||||
dwObjSize: uint32(unsafe.Sizeof(_DIOBJECTDATAFORMAT{})),
|
dwObjSize: uint32(unsafe.Sizeof(_DIOBJECTDATAFORMAT{})),
|
||||||
@ -395,7 +425,7 @@ func (g *nativeGamepadsDesktop) dinput8EnumDevicesCallback(lpddi *_DIDEVICEINSTA
|
|||||||
gp.native = &nativeGamepadDesktop{
|
gp.native = &nativeGamepadDesktop{
|
||||||
dinputDevice: device,
|
dinputDevice: device,
|
||||||
dinputObjects: ctx.objects,
|
dinputObjects: ctx.objects,
|
||||||
dinputGUID: lpddi.guidInstance,
|
dinputPath: dinputPath,
|
||||||
dinputAxes: make([]float64, ctx.axisCount+ctx.sliderCount),
|
dinputAxes: make([]float64, ctx.axisCount+ctx.sliderCount),
|
||||||
dinputButtons: make([]bool, ctx.buttonCount),
|
dinputButtons: make([]bool, ctx.buttonCount),
|
||||||
dinputHats: make([]int, ctx.povCount),
|
dinputHats: make([]int, ctx.povCount),
|
||||||
@ -562,7 +592,7 @@ func (g *nativeGamepadsDesktop) setNativeWindow(nativeWindow uintptr) {
|
|||||||
type nativeGamepadDesktop struct {
|
type nativeGamepadDesktop struct {
|
||||||
dinputDevice *_IDirectInputDevice8W
|
dinputDevice *_IDirectInputDevice8W
|
||||||
dinputObjects []dinputObject
|
dinputObjects []dinputObject
|
||||||
dinputGUID windows.GUID
|
dinputPath string
|
||||||
dinputAxes []float64
|
dinputAxes []float64
|
||||||
dinputButtons []bool
|
dinputButtons []bool
|
||||||
dinputHats []int
|
dinputHats []int
|
||||||
|
Loading…
Reference in New Issue
Block a user