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 mouseButtonPressed map[int]bool
cursorX int cursorX int
cursorY int cursorY int
origCursorX int
origCursorY int
wheelX float64 wheelX float64
wheelY float64 wheelY float64
gamepads map[driver.GamepadID]gamepad gamepads map[driver.GamepadID]gamepad
@ -284,10 +286,6 @@ func (i *Input) mouseUp(code int) {
i.mouseButtonPressed[code] = false i.mouseButtonPressed[code] = false
} }
func (i *Input) setMouseCursor(x, y int) {
i.cursorX, i.cursorY = x, y
}
func (i *Input) updateGamepads() { func (i *Input) updateGamepads() {
nav := js.Global().Get("navigator") nav := js.Global().Get("navigator")
if !nav.Truthy() { if !nav.Truthy() {
@ -401,8 +399,22 @@ func (i *Input) updateFromEvent(e js.Value) {
} }
func (i *Input) setMouseCursorFromEvent(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() 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) { func (in *Input) updateTouchesFromEvent(e js.Value) {

View File

@ -50,7 +50,8 @@ type UserInterface struct {
vsync bool vsync bool
running bool running bool
initFocused bool initFocused bool
cursorHidden bool cursorMode driver.CursorMode
cursorPrevMode driver.CursorMode
cursorShape driver.CursorShape cursorShape driver.CursorShape
sizeChanged bool sizeChanged bool
@ -122,38 +123,34 @@ func (u *UserInterface) CursorMode() driver.CursorMode {
if !canvas.Truthy() { if !canvas.Truthy() {
return driver.CursorModeHidden return driver.CursorModeHidden
} }
return u.cursorMode
if u.cursorHidden {
return driver.CursorModeHidden
}
return driver.CursorModeVisible
} }
func (u *UserInterface) SetCursorMode(mode driver.CursorMode) { func (u *UserInterface) SetCursorMode(mode driver.CursorMode) {
if !canvas.Truthy() { if !canvas.Truthy() {
return 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 { switch mode {
case driver.CursorModeVisible: case driver.CursorModeVisible:
if !u.cursorHidden { canvas.Get("style").Set("cursor", driverCursorShapeToCSSCursor(u.cursorShape))
return
}
u.cursorHidden = false
case driver.CursorModeHidden: case driver.CursorModeHidden:
if u.cursorHidden { canvas.Get("style").Set("cursor", stringNone)
return case driver.CursorModeCaptured:
canvas.Call("requestPointerLock")
} }
u.cursorHidden = true
default:
return
} }
if u.cursorHidden { func (u *UserInterface) recoverCursorMode() {
canvas.Get("style").Set("cursor", stringNone) u.SetCursorMode(u.cursorPrevMode)
} else {
canvas.Get("style").Set("cursor", driverCursorShapeToCSSCursor(u.cursorShape))
}
} }
func (u *UserInterface) CursorShape() driver.CursorShape { func (u *UserInterface) CursorShape() driver.CursorShape {
@ -170,8 +167,9 @@ func (u *UserInterface) SetCursorShape(shape driver.CursorShape) {
if u.cursorShape == shape { if u.cursorShape == shape {
return return
} }
u.cursorShape = shape u.cursorShape = shape
if !u.cursorHidden { if u.cursorMode == driver.CursorModeVisible {
canvas.Get("style").Set("cursor", driverCursorShapeToCSSCursor(u.cursorShape)) canvas.Get("style").Set("cursor", driverCursorShapeToCSSCursor(u.cursorShape))
} }
} }
@ -380,6 +378,24 @@ func init() {
canvas.Get("style").Set("outline", "none") canvas.Get("style").Set("outline", "none")
setCanvasEventHandlers(canvas) 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) { func setWindowEventHandlers(v js.Value) {
@ -473,7 +489,7 @@ func setCanvasEventHandlers(v js.Value) {
return nil return nil
})) }))
// Gamepad // Context menu
v.Call("addEventListener", "contextmenu", js.FuncOf(func(this js.Value, args []js.Value) interface{} { v.Call("addEventListener", "contextmenu", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
e := args[0] e := args[0]
e.Call("preventDefault") e.Call("preventDefault")