mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 02:38:53 +01:00
internal/ui: bug fix: need to delay to capture a cursor
From the spec https://w3c.github.io/pointerlock/#extensions-to-the-element-interface, capturing a cursor might require a cooltime. This change adds a delay to capture a cursor just after escaping from a capture. Closes #2693
This commit is contained in:
parent
d0b6d2c41a
commit
7a7d4fd91f
@ -80,8 +80,10 @@ type userInterfaceImpl struct {
|
||||
running bool
|
||||
cursorMode CursorMode
|
||||
cursorPrevMode CursorMode
|
||||
captureCursorLater bool
|
||||
cursorShape CursorShape
|
||||
onceUpdateCalled bool
|
||||
lastCaptureExitTime time.Time
|
||||
|
||||
lastDeviceScaleFactor float64
|
||||
|
||||
@ -189,6 +191,16 @@ func (u *userInterfaceImpl) CursorMode() CursorMode {
|
||||
}
|
||||
|
||||
func (u *userInterfaceImpl) SetCursorMode(mode CursorMode) {
|
||||
if mode == CursorModeCaptured && !u.canCaptureCursor() {
|
||||
u.captureCursorLater = true
|
||||
return
|
||||
}
|
||||
u.setCursorMode(mode)
|
||||
}
|
||||
|
||||
func (u *userInterfaceImpl) setCursorMode(mode CursorMode) {
|
||||
u.captureCursorLater = false
|
||||
|
||||
if !canvas.Truthy() {
|
||||
return
|
||||
}
|
||||
@ -199,6 +211,7 @@ func (u *userInterfaceImpl) SetCursorMode(mode CursorMode) {
|
||||
u.cursorPrevMode = u.cursorMode
|
||||
if u.cursorMode == CursorModeCaptured {
|
||||
document.Call("exitPointerLock")
|
||||
u.lastCaptureExitTime = time.Now()
|
||||
}
|
||||
u.cursorMode = mode
|
||||
switch mode {
|
||||
@ -272,7 +285,25 @@ func (u *userInterfaceImpl) isFocused() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// canCaptureCursor reports whether a cursor can be captured or not now.
|
||||
// Just after escaping from a capture, a browser might not be able to capture a cursor (#2693).
|
||||
// If it is too early to capture a cursor, Ebitengine tries to delay it.
|
||||
//
|
||||
// See also https://w3c.github.io/pointerlock/#extensions-to-the-element-interface
|
||||
//
|
||||
// > Pointer lock is a transient activation-gated API, therefore a requestPointerLock() call
|
||||
// > MUST fail if the relevant global object of this does not have transient activation.
|
||||
// > This prevents locking upon initial navigation or re-acquiring lock without user's attention.
|
||||
func (u *userInterfaceImpl) canCaptureCursor() bool {
|
||||
// 1.5 [sec] seems enough in the real world.
|
||||
return time.Now().Sub(u.lastCaptureExitTime) >= 1500*time.Millisecond
|
||||
}
|
||||
|
||||
func (u *userInterfaceImpl) update() error {
|
||||
if u.captureCursorLater && u.canCaptureCursor() {
|
||||
u.setCursorMode(CursorModeCaptured)
|
||||
}
|
||||
|
||||
if u.suspended() {
|
||||
return hooks.SuspendAudio()
|
||||
}
|
||||
|
1
run.go
1
run.go
@ -353,6 +353,7 @@ func CursorMode() CursorModeType {
|
||||
// CursorModeCaptured also works on browsers.
|
||||
// When the user exits the captured mode not by SetCursorMode but by the UI (e.g., pressing ESC),
|
||||
// the previous cursor mode is set automatically.
|
||||
// On browsers, setting CursorModeCaptured might be delayed especially just after escaping from a capture.
|
||||
//
|
||||
// SetCursorMode does nothing on mobiles.
|
||||
//
|
||||
|
Loading…
Reference in New Issue
Block a user