internal/uidriver/js: Implement CursorModeCaptured

Closes #1572
This commit is contained in:
Hajime Hoshi 2021-04-16 02:26:10 +09:00
parent 3c1226a227
commit ead84553a0
2 changed files with 59 additions and 31 deletions

View File

@ -74,6 +74,8 @@ type Input struct {
mouseButtonPressed map[int]bool
cursorX int
cursorY int
origCursorX int
origCursorY int
wheelX float64
wheelY float64
gamepads map[driver.GamepadID]gamepad
@ -284,10 +286,6 @@ func (i *Input) mouseUp(code int) {
i.mouseButtonPressed[code] = false
}
func (i *Input) setMouseCursor(x, y int) {
i.cursorX, i.cursorY = x, y
}
func (i *Input) updateGamepads() {
nav := js.Global().Get("navigator")
if !nav.Truthy() {
@ -401,8 +399,22 @@ func (i *Input) updateFromEvent(e js.Value) {
}
func (i *Input) setMouseCursorFromEvent(e js.Value) {
if i.ui.cursorMode == driver.CursorModeCaptured {
x, y := e.Get("clientX").Int(), e.Get("clientY").Int()
i.setMouseCursor(x, y)
i.origCursorX, i.origCursorY = x, y
dx, dy := e.Get("movementX").Int(), e.Get("movementY").Int()
i.cursorX += dx
i.cursorY += dy
return
}
x, y := e.Get("clientX").Int(), e.Get("clientY").Int()
i.cursorX, i.cursorY = x, y
i.origCursorX, i.origCursorY = x, y
}
func (i *Input) recoverCursorPosition() {
i.cursorX, i.cursorY = i.origCursorX, i.origCursorY
}
func (in *Input) updateTouchesFromEvent(e js.Value) {

View File

@ -50,7 +50,8 @@ type UserInterface struct {
vsync bool
running bool
initFocused bool
cursorHidden bool
cursorMode driver.CursorMode
cursorPrevMode driver.CursorMode
cursorShape driver.CursorShape
sizeChanged bool
@ -122,38 +123,34 @@ func (u *UserInterface) CursorMode() driver.CursorMode {
if !canvas.Truthy() {
return driver.CursorModeHidden
}
if u.cursorHidden {
return driver.CursorModeHidden
}
return driver.CursorModeVisible
return u.cursorMode
}
func (u *UserInterface) SetCursorMode(mode driver.CursorMode) {
if !canvas.Truthy() {
return
}
if u.cursorMode == mode {
return
}
// Remember the previous cursor mode in the case when the pointer lock exit by pressing ESC.
u.cursorPrevMode = u.cursorMode
if u.cursorMode == driver.CursorModeCaptured {
document.Call("exitPointerLock")
}
u.cursorMode = mode
switch mode {
case driver.CursorModeVisible:
if !u.cursorHidden {
return
}
u.cursorHidden = false
canvas.Get("style").Set("cursor", driverCursorShapeToCSSCursor(u.cursorShape))
case driver.CursorModeHidden:
if u.cursorHidden {
return
canvas.Get("style").Set("cursor", stringNone)
case driver.CursorModeCaptured:
canvas.Call("requestPointerLock")
}
u.cursorHidden = true
default:
return
}
if u.cursorHidden {
canvas.Get("style").Set("cursor", stringNone)
} else {
canvas.Get("style").Set("cursor", driverCursorShapeToCSSCursor(u.cursorShape))
}
func (u *UserInterface) recoverCursorMode() {
u.SetCursorMode(u.cursorPrevMode)
}
func (u *UserInterface) CursorShape() driver.CursorShape {
@ -170,8 +167,9 @@ func (u *UserInterface) SetCursorShape(shape driver.CursorShape) {
if u.cursorShape == shape {
return
}
u.cursorShape = shape
if !u.cursorHidden {
if u.cursorMode == driver.CursorModeVisible {
canvas.Get("style").Set("cursor", driverCursorShapeToCSSCursor(u.cursorShape))
}
}
@ -380,6 +378,24 @@ func init() {
canvas.Get("style").Set("outline", "none")
setCanvasEventHandlers(canvas)
// Pointer Lock
document.Call("addEventListener", "pointerlockchange", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
if document.Get("pointerLockElement").Truthy() {
return nil
}
// Recover the state correctly when exiting from the pointer lock.
// A user can exit the pointer lock by pressing ESC. In this case, sync the cursor mode state.
if theUI.cursorMode == driver.CursorModeCaptured {
if theUI.cursorPrevMode == driver.CursorModeCaptured {
panic("js: cursorPrevMode must not be driver.CursorModeCaptured")
}
theUI.recoverCursorMode()
}
theUI.input.recoverCursorPosition()
return nil
}))
}
func setWindowEventHandlers(v js.Value) {
@ -473,7 +489,7 @@ func setCanvasEventHandlers(v js.Value) {
return nil
}))
// Gamepad
// Context menu
v.Call("addEventListener", "contextmenu", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
e := args[0]
e.Call("preventDefault")