canvas.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663
  1. // Copyright 2016 The G3N Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. //go:build wasm
  5. // +build wasm
  6. package window
  7. import (
  8. "fmt"
  9. "github.com/g3n/engine/core"
  10. "github.com/g3n/engine/gls"
  11. "github.com/g3n/engine/util/wasm"
  12. _ "image/png"
  13. "syscall/js"
  14. )
  15. // Keycodes
  16. const (
  17. KeyUnknown = Key(iota)
  18. KeySpace
  19. KeyApostrophe
  20. KeyComma
  21. KeyMinus
  22. KeyPeriod
  23. KeySlash
  24. Key0
  25. Key1
  26. Key2
  27. Key3
  28. Key4
  29. Key5
  30. Key6
  31. Key7
  32. Key8
  33. Key9
  34. KeySemicolon
  35. KeyEqual
  36. KeyA
  37. KeyB
  38. KeyC
  39. KeyD
  40. KeyE
  41. KeyF
  42. KeyG
  43. KeyH
  44. KeyI
  45. KeyJ
  46. KeyK
  47. KeyL
  48. KeyM
  49. KeyN
  50. KeyO
  51. KeyP
  52. KeyQ
  53. KeyR
  54. KeyS
  55. KeyT
  56. KeyU
  57. KeyV
  58. KeyW
  59. KeyX
  60. KeyY
  61. KeyZ
  62. KeyLeftBracket
  63. KeyBackslash
  64. KeyRightBracket
  65. KeyGraveAccent
  66. KeyWorld1
  67. KeyWorld2
  68. KeyEscape
  69. KeyEnter
  70. KeyTab
  71. KeyBackspace
  72. KeyInsert
  73. KeyDelete
  74. KeyRight
  75. KeyLeft
  76. KeyDown
  77. KeyUp
  78. KeyPageUp
  79. KeyPageDown
  80. KeyHome
  81. KeyEnd
  82. KeyCapsLock
  83. KeyScrollLock
  84. KeyNumLock
  85. KeyPrintScreen
  86. KeyPause
  87. KeyF1
  88. KeyF2
  89. KeyF3
  90. KeyF4
  91. KeyF5
  92. KeyF6
  93. KeyF7
  94. KeyF8
  95. KeyF9
  96. KeyF10
  97. KeyF11
  98. KeyF12
  99. KeyF13
  100. KeyF14
  101. KeyF15
  102. KeyF16
  103. KeyF17
  104. KeyF18
  105. KeyF19
  106. KeyF20
  107. KeyF21
  108. KeyF22
  109. KeyF23
  110. KeyF24
  111. KeyF25
  112. KeyKP0
  113. KeyKP1
  114. KeyKP2
  115. KeyKP3
  116. KeyKP4
  117. KeyKP5
  118. KeyKP6
  119. KeyKP7
  120. KeyKP8
  121. KeyKP9
  122. KeyKPDecimal
  123. KeyKPDivide
  124. KeyKPMultiply
  125. KeyKPSubtract
  126. KeyKPAdd
  127. KeyKPEnter
  128. KeyKPEqual
  129. KeyLeftShift
  130. KeyLeftControl
  131. KeyLeftAlt
  132. KeyLeftSuper // Meta in Javascript
  133. KeyRightShift
  134. KeyRightControl
  135. KeyRightAlt
  136. KeyRightSuper
  137. KeyMenu
  138. KeyLast
  139. )
  140. var keyMap = map[string]Key{
  141. //"KeyUnknown": KeyUnknown, TODO emit when key is not in map
  142. "Space": KeySpace,
  143. "Quote": KeyApostrophe,
  144. "Comma": KeyComma,
  145. "Minus": KeyMinus,
  146. "Period": KeyPeriod,
  147. "Slash": KeySlash,
  148. "Digit0": Key0,
  149. "Digit1": Key1,
  150. "Digit2": Key2,
  151. "Digit3": Key3,
  152. "Digit4": Key4,
  153. "Digit5": Key5,
  154. "Digit6": Key6,
  155. "Digit7": Key7,
  156. "Digit8": Key8,
  157. "Digit9": Key9,
  158. "Semicolon": KeySemicolon,
  159. "Equal": KeyEqual,
  160. "KeyA": KeyA,
  161. "KeyB": KeyB,
  162. "KeyC": KeyC,
  163. "KeyD": KeyD,
  164. "KeyE": KeyE,
  165. "KeyF": KeyF,
  166. "KeyG": KeyG,
  167. "KeyH": KeyH,
  168. "KeyI": KeyI,
  169. "KeyJ": KeyJ,
  170. "KeyK": KeyK,
  171. "KeyL": KeyL,
  172. "KeyM": KeyM,
  173. "KeyN": KeyN,
  174. "KeyO": KeyO,
  175. "KeyP": KeyP,
  176. "KeyQ": KeyQ,
  177. "KeyR": KeyR,
  178. "KeyS": KeyS,
  179. "KeyT": KeyT,
  180. "KeyU": KeyU,
  181. "KeyV": KeyV,
  182. "KeyW": KeyW,
  183. "KeyX": KeyX,
  184. "KeyY": KeyY,
  185. "KeyZ": KeyZ,
  186. "BracketLeft": KeyLeftBracket,
  187. "Backslash": KeyBackslash,
  188. "BracketRight": KeyRightBracket,
  189. "Backquote": KeyGraveAccent,
  190. //"KeyWorld1": KeyWorld1,
  191. //"KeyWorld2": KeyWorld2,
  192. "Escape": KeyEscape,
  193. "Enter": KeyEnter,
  194. "Tab": KeyTab,
  195. "Backspace": KeyBackspace,
  196. "Insert": KeyInsert,
  197. "Delete": KeyDelete,
  198. "ArrowRight": KeyRight,
  199. "ArrowLeft": KeyLeft,
  200. "ArrowDown": KeyDown,
  201. "ArrowUp": KeyUp,
  202. "PageUp": KeyPageUp,
  203. "PageDown": KeyPageDown,
  204. "Home": KeyHome,
  205. "End": KeyEnd,
  206. "CapsLock": KeyCapsLock,
  207. "ScrollLock": KeyScrollLock,
  208. "NumLock": KeyNumLock,
  209. "PrintScreen": KeyPrintScreen,
  210. "Pause": KeyPause,
  211. "F1": KeyF1,
  212. "F2": KeyF2,
  213. "F3": KeyF3,
  214. "F4": KeyF4,
  215. "F5": KeyF5,
  216. "F6": KeyF6,
  217. "F7": KeyF7,
  218. "F8": KeyF8,
  219. "F9": KeyF9,
  220. "F10": KeyF10,
  221. "F11": KeyF11,
  222. "F12": KeyF12,
  223. "F13": KeyF13,
  224. "F14": KeyF14,
  225. "F15": KeyF15,
  226. "F16": KeyF16,
  227. "F17": KeyF17,
  228. "F18": KeyF18,
  229. "F19": KeyF19,
  230. "F20": KeyF20,
  231. "F21": KeyF21,
  232. "F22": KeyF22,
  233. "F23": KeyF23,
  234. "F24": KeyF24,
  235. "F25": KeyF25,
  236. "Numpad0": KeyKP0,
  237. "Numpad1": KeyKP1,
  238. "Numpad2": KeyKP2,
  239. "Numpad3": KeyKP3,
  240. "Numpad4": KeyKP4,
  241. "Numpad5": KeyKP5,
  242. "Numpad6": KeyKP6,
  243. "Numpad7": KeyKP7,
  244. "Numpad8": KeyKP8,
  245. "Numpad9": KeyKP9,
  246. "NumpadDecimal": KeyKPDecimal,
  247. "NumpadDivide": KeyKPDivide,
  248. "NumpadMultiply": KeyKPMultiply,
  249. "NumpadSubtract": KeyKPSubtract,
  250. "NumpadAdd": KeyKPAdd,
  251. "NumpadEnter": KeyKPEnter,
  252. "NumpadEqual": KeyKPEqual,
  253. "ShiftLeft": KeyLeftShift,
  254. "ControlLeft": KeyLeftControl,
  255. "AltLeft": KeyLeftAlt,
  256. "MetaLeft": KeyLeftSuper,
  257. "ShiftRight": KeyRightShift,
  258. "ControlRight": KeyRightControl,
  259. "AltRight": KeyRightAlt,
  260. "MetaRight": KeyRightSuper,
  261. "Menu": KeyMenu,
  262. }
  263. // Modifier keys
  264. const (
  265. ModShift = ModifierKey(1 << iota) // Bitmask
  266. ModControl
  267. ModAlt
  268. ModSuper // Meta in Javascript
  269. )
  270. // Mouse buttons
  271. const (
  272. //MouseButton1 = MouseButton(0)
  273. //MouseButton2 = MouseButton(0)
  274. //MouseButton3 = MouseButton(0)
  275. //MouseButton4 = MouseButton(0)
  276. //MouseButton5 = MouseButton(0)
  277. //MouseButton6 = MouseButton(0)
  278. //MouseButton7 = MouseButton(0)
  279. //MouseButton8 = MouseButton(0)
  280. //MouseButtonLast = MouseButton(0)
  281. MouseButtonLeft = MouseButton(0)
  282. MouseButtonRight = MouseButton(2)
  283. MouseButtonMiddle = MouseButton(1)
  284. )
  285. // Input modes
  286. const (
  287. CursorInputMode = InputMode(iota) // See Cursor mode values
  288. StickyKeysInputMode // Value can be either 1 or 0
  289. StickyMouseButtonsInputMode // Value can be either 1 or 0
  290. )
  291. // Cursor mode values
  292. const (
  293. CursorNormal = CursorMode(iota)
  294. CursorHidden
  295. CursorDisabled
  296. )
  297. // WebGlCanvas is a browser-based WebGL canvas.
  298. type WebGlCanvas struct {
  299. core.Dispatcher // Embedded event dispatcher
  300. canvas js.Value // Associated WebGL canvas
  301. gls *gls.GLS // Associated WebGL state
  302. // Events
  303. keyEv KeyEvent
  304. charEv CharEvent
  305. mouseEv MouseEvent
  306. posEv PosEvent
  307. sizeEv SizeEvent
  308. cursorEv CursorEvent
  309. scrollEv ScrollEvent
  310. focusEv FocusEvent
  311. lockEv LockEvent
  312. // Callbacks
  313. onCtxMenu js.Func
  314. keyDown js.Func
  315. keyUp js.Func
  316. mouseDown js.Func
  317. mouseUp js.Func
  318. mouseMove js.Func
  319. mouseWheel js.Func
  320. winResize js.Func
  321. winFocus js.Func
  322. winBlur js.Func
  323. pointerLock js.Func
  324. }
  325. // Init initializes the WebGlCanvas singleton.
  326. // If canvasId is provided, the pre-existing WebGlCanvas with that id is used.
  327. // If canvasId is the empty string then it creates a new WebGL canvas.
  328. func Init(canvasId string) error {
  329. // Panic if already created
  330. if win != nil {
  331. panic(fmt.Errorf("can only call window.Init() once"))
  332. }
  333. // Create wrapper window with dispatcher
  334. w := new(WebGlCanvas)
  335. w.Dispatcher.Initialize()
  336. // Create or get WebGlCanvas
  337. doc := js.Global().Get("document")
  338. if canvasId == "" {
  339. w.canvas = doc.Call("createElement", "WebGlCanvas")
  340. } else {
  341. w.canvas = doc.Call("getElementById", canvasId)
  342. if wasm.Equal(w.canvas, js.Null()) {
  343. panic(fmt.Sprintf("Cannot find canvas with provided id: %s", canvasId))
  344. }
  345. }
  346. // Get reference to WebGL context
  347. webglCtx := w.canvas.Call("getContext", "webgl2")
  348. if wasm.Equal(webglCtx, js.Undefined()) {
  349. return fmt.Errorf("Browser doesn't support WebGL2")
  350. }
  351. // Create WebGL state
  352. gl, err := gls.New(webglCtx)
  353. if err != nil {
  354. return err
  355. }
  356. w.gls = gl
  357. // Disable right-click context menu on the canvas
  358. w.onCtxMenu = js.FuncOf(func(this js.Value, args []js.Value) interface{} { return false })
  359. w.canvas.Set("oncontextmenu", w.onCtxMenu)
  360. // TODO scaling/hidpi (device pixel ratio)
  361. w.pointerLock = js.FuncOf(func(this js.Value, args []js.Value) interface{} {
  362. w.lockEv.Locked = doc.Get("pointerLockElement").Equal(w.canvas)
  363. w.Dispatch(OnLockChange, &w.lockEv)
  364. return nil
  365. })
  366. doc.Call("addEventListener", "pointerlockchange", w.pointerLock)
  367. // Set up key down callback to dispatch event
  368. w.keyDown = js.FuncOf(func(this js.Value, args []js.Value) interface{} {
  369. event := args[0]
  370. eventCode := event.Get("code").String()
  371. w.keyEv.Key = Key(keyMap[eventCode])
  372. w.keyEv.Mods = getModifiers(event)
  373. w.Dispatch(OnKeyDown, &w.keyEv)
  374. return nil
  375. })
  376. js.Global().Call("addEventListener", "keydown", w.keyDown)
  377. // Set up key up callback to dispatch event
  378. w.keyUp = js.FuncOf(func(this js.Value, args []js.Value) interface{} {
  379. event := args[0]
  380. eventCode := event.Get("code").String()
  381. w.keyEv.Key = Key(keyMap[eventCode])
  382. w.keyEv.Mods = getModifiers(event)
  383. w.Dispatch(OnKeyUp, &w.keyEv)
  384. return nil
  385. })
  386. js.Global().Call("addEventListener", "keyup", w.keyUp)
  387. // Set up mouse down callback to dispatch event
  388. w.mouseDown = js.FuncOf(func(this js.Value, args []js.Value) interface{} {
  389. event := args[0]
  390. w.mouseEv.Button = MouseButton(event.Get("button").Int())
  391. w.mouseEv.Xpos = float32(event.Get("offsetX").Int()) //* float32(w.scaleX) TODO
  392. w.mouseEv.Ypos = float32(event.Get("offsetY").Int()) //* float32(w.scaleY)
  393. w.mouseEv.Mods = getModifiers(event)
  394. w.Dispatch(OnMouseDown, &w.mouseEv)
  395. return nil
  396. })
  397. w.canvas.Call("addEventListener", "mousedown", w.mouseDown)
  398. // Set up mouse down callback to dispatch event
  399. w.mouseUp = js.FuncOf(func(this js.Value, args []js.Value) interface{} {
  400. event := args[0]
  401. w.mouseEv.Button = MouseButton(event.Get("button").Int())
  402. w.mouseEv.Xpos = float32(event.Get("offsetX").Float()) //* float32(w.scaleX) TODO
  403. w.mouseEv.Ypos = float32(event.Get("offsetY").Float()) //* float32(w.scaleY)
  404. w.mouseEv.Mods = getModifiers(event)
  405. w.Dispatch(OnMouseUp, &w.mouseEv)
  406. return nil
  407. })
  408. w.canvas.Call("addEventListener", "mouseup", w.mouseUp)
  409. // Set up mouse move callback to dispatch event
  410. w.mouseMove = js.FuncOf(func(this js.Value, args []js.Value) interface{} {
  411. event := args[0]
  412. if w.lockEv.Locked {
  413. w.cursorEv.Xpos += float32(event.Get("movementX").Float())
  414. w.cursorEv.Ypos += float32(event.Get("movementY").Float())
  415. } else {
  416. w.cursorEv.Xpos = float32(event.Get("offsetX").Float()) //* float32(w.scaleX) TODO
  417. w.cursorEv.Ypos = float32(event.Get("offsetY").Float()) //* float32(w.scaleY)
  418. }
  419. w.cursorEv.Mods = getModifiers(event)
  420. w.Dispatch(OnCursor, &w.cursorEv)
  421. return nil
  422. })
  423. w.canvas.Call("addEventListener", "mousemove", w.mouseMove)
  424. // Set up mouse wheel callback to dispatch event
  425. w.mouseWheel = js.FuncOf(func(this js.Value, args []js.Value) interface{} {
  426. event := args[0]
  427. event.Call("preventDefault")
  428. w.scrollEv.Xoffset = -float32(event.Get("deltaX").Float()) / 100.0
  429. w.scrollEv.Yoffset = -float32(event.Get("deltaY").Float()) / 100.0
  430. w.scrollEv.Mods = getModifiers(event)
  431. w.Dispatch(OnScroll, &w.scrollEv)
  432. return nil
  433. })
  434. w.canvas.Call("addEventListener", "wheel", w.mouseWheel)
  435. // Set up window resize callback to dispatch event
  436. w.winResize = js.FuncOf(func(this js.Value, args []js.Value) interface{} {
  437. w.sizeEv.Width = w.canvas.Get("width").Int()
  438. w.sizeEv.Height = w.canvas.Get("height").Int()
  439. // TODO device pixel ratio
  440. //fbw, fbh := x.GetFramebufferSize()
  441. //w.scaleX = float64(fbw) / float64(width)
  442. //w.scaleY = float64(fbh) / float64(height)
  443. w.Dispatch(OnWindowSize, &w.sizeEv)
  444. return nil
  445. })
  446. js.Global().Get("window").Call("addEventListener", "resize", w.winResize)
  447. // Set up window focus callback to dispatch event
  448. w.winFocus = js.FuncOf(func(this js.Value, args []js.Value) interface{} {
  449. w.focusEv.Focused = true
  450. w.Dispatch(OnWindowFocus, &w.focusEv)
  451. return nil
  452. })
  453. w.winBlur = js.FuncOf(func(this js.Value, args []js.Value) interface{} {
  454. w.focusEv.Focused = false
  455. w.Dispatch(OnWindowFocus, &w.focusEv)
  456. return nil
  457. })
  458. js.Global().Get("window").Call("addEventListener", "onfocus", w.winFocus)
  459. js.Global().Get("window").Call("addEventListener", "onblur", w.winBlur)
  460. //// Set up char callback to dispatch event TODO
  461. //w.SetCharModsCallback(func(x *glfw.Window, char rune, mods glfw.ModifierKey) { //
  462. // w.charEv.Char = char
  463. // w.charEv.Mods = ModifierKey(mods)
  464. // w.Dispatch(OnChar, &w.charEv)
  465. //})
  466. win = w // Set singleton
  467. return nil
  468. }
  469. // getModifiers extracts a ModifierKey bitmask from a Javascript event object.
  470. func getModifiers(event js.Value) ModifierKey {
  471. shiftKey := event.Get("shiftKey").Bool()
  472. ctrlKey := event.Get("ctrlKey").Bool()
  473. altKey := event.Get("altKey").Bool()
  474. metaKey := event.Get("metaKey").Bool()
  475. var mods ModifierKey
  476. if shiftKey {
  477. mods = mods | ModShift
  478. }
  479. if ctrlKey {
  480. mods = mods | ModControl
  481. }
  482. if altKey {
  483. mods = mods | ModAlt
  484. }
  485. if metaKey {
  486. mods = mods | ModSuper
  487. }
  488. return mods
  489. }
  490. // Canvas returns the associated WebGL WebGlCanvas.
  491. func (w *WebGlCanvas) Canvas() js.Value {
  492. return w.canvas
  493. }
  494. // Gls returns the associated OpenGL state
  495. func (w *WebGlCanvas) Gls() *gls.GLS {
  496. return w.gls
  497. }
  498. // FullScreen returns whether this canvas is fullscreen
  499. func (w *WebGlCanvas) FullScreen() bool {
  500. // TODO
  501. return false
  502. }
  503. // SetFullScreen sets this window full screen state for the primary monitor
  504. func (w *WebGlCanvas) SetFullScreen(full bool) {
  505. // TODO
  506. // Make it so that the first user interaction (e.g. click) should set the canvas as fullscreen.
  507. }
  508. // Destroy destroys the WebGL canvas and removes all event listeners.
  509. func (w *WebGlCanvas) Destroy() {
  510. // Remove event listeners
  511. w.canvas.Set("oncontextmenu", js.Null())
  512. js.Global().Call("removeEventListener", "keydown", w.keyDown)
  513. js.Global().Call("removeEventListener", "keyup", w.keyUp)
  514. w.canvas.Call("removeEventListener", "mousedown", w.mouseDown)
  515. w.canvas.Call("removeEventListener", "mouseup", w.mouseUp)
  516. w.canvas.Call("removeEventListener", "mousemove", w.mouseMove)
  517. w.canvas.Call("removeEventListener", "wheel", w.mouseWheel)
  518. js.Global().Get("window").Call("removeEventListener", "resize", w.winResize)
  519. js.Global().Get("window").Call("removeEventListener", "onfocus", w.winFocus)
  520. js.Global().Get("window").Call("removeEventListener", "onfocus", w.winBlur)
  521. js.Global().Get("document").Call("removeEventListener", "pointerlockchange", w.pointerLock)
  522. // Release callbacks
  523. w.onCtxMenu.Release()
  524. w.keyDown.Release()
  525. w.keyUp.Release()
  526. w.mouseDown.Release()
  527. w.mouseUp.Release()
  528. w.mouseMove.Release()
  529. w.mouseWheel.Release()
  530. w.winResize.Release()
  531. w.winFocus.Release()
  532. w.winBlur.Release()
  533. w.pointerLock.Release()
  534. }
  535. // GetFramebufferSize returns the framebuffer size.
  536. func (w *WebGlCanvas) GetFramebufferSize() (width int, height int) {
  537. // TODO device pixel ratio
  538. return w.canvas.Get("width").Int(), w.canvas.Get("height").Int()
  539. }
  540. // GetSize returns this window's size in screen coordinates.
  541. func (w *WebGlCanvas) GetSize() (width int, height int) {
  542. return w.canvas.Get("width").Int(), w.canvas.Get("height").Int()
  543. }
  544. // SetSize sets the size, in screen coordinates, of the canvas.
  545. func (w *WebGlCanvas) SetSize(width int, height int) {
  546. w.canvas.Set("width", width)
  547. w.canvas.Set("height", height)
  548. }
  549. // Scale returns this window's DPI scale factor (FramebufferSize / Size)
  550. func (w *WebGlCanvas) GetScale() (x float64, y float64) {
  551. // TODO device pixel ratio
  552. return 1, 1
  553. }
  554. // CreateCursor creates a new custom cursor and returns an int handle.
  555. func (w *WebGlCanvas) CreateCursor(imgFile string, xhot, yhot int) (Cursor, error) {
  556. // TODO
  557. return 0, nil
  558. }
  559. // SetCursor sets the window's cursor to a standard one
  560. func (w *WebGlCanvas) SetCursor(cursor Cursor) {
  561. // TODO
  562. }
  563. // SetCursorMode sets the window's cursor mode.
  564. // More info: https://developer.mozilla.org/en-US/docs/Web/API/Pointer_Lock_API
  565. func (w *WebGlCanvas) SetCursorMode(mode CursorMode) {
  566. switch mode {
  567. case CursorNormal:
  568. js.Global().Get("document").Call("exitPointerLock")
  569. case CursorHidden:
  570. case CursorDisabled:
  571. promise := w.Canvas().Call("requestPointerLock", map[string]interface{}{"unadjustedMovement": true})
  572. if promise.IsUndefined() {
  573. w.Canvas().Call("requestPointerLock")
  574. } else {
  575. promise.Call("catch", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
  576. if len(args) > 0 && args[0].Get("name").Equal(js.ValueOf("NotSupportedError")) {
  577. w.Canvas().Call("requestPointerLock")
  578. }
  579. return nil
  580. }))
  581. }
  582. }
  583. }
  584. // DisposeAllCursors deletes all existing custom cursors.
  585. func (w *WebGlCanvas) DisposeAllCustomCursors() {
  586. // TODO
  587. }
  588. // SetInputMode changes specified input to specified state
  589. //func (w *WebGlCanvas) SetInputMode(mode InputMode, state int) {
  590. //
  591. // // TODO
  592. // // Hide cursor etc
  593. //}