/src/library_glfw.js

http://github.com/kripken/emscripten · JavaScript · 1794 lines · 1384 code · 309 blank · 101 comment · 214 complexity · 86c0dbbd592a612214c8f3f14e9ce62d MD5 · raw file

  1. /**
  2. * @license
  3. * Copyright 2013 The Emscripten Authors
  4. * SPDX-License-Identifier: MIT
  5. */
  6. /*
  7. * EMSCRIPTEN GLFW 2.x-3.x emulation.
  8. * It tries to emulate the behavior described in
  9. * http://www.glfw.org/docs/latest/
  10. *
  11. * This also implements parts of GLFW 2.x on top of GLFW 3.x.
  12. *
  13. * What it does:
  14. * - Creates a GL context.
  15. * - Manage keyboard and mouse events.
  16. * - GL Extensions support.
  17. *
  18. * What it does not but should probably do:
  19. * - Transmit events when glfwPollEvents, glfwWaitEvents or glfwSwapBuffers is
  20. * called. Events callbacks are called as soon as event are received.
  21. * - Input modes.
  22. * - Gamma ramps.
  23. * - Video modes.
  24. * - Monitors.
  25. * - Clipboard (not possible from javascript?).
  26. * - Multiple windows.
  27. * - Error codes && messages through callback.
  28. * - Thread emulation. (removed in GLFW3).
  29. * - Image/Texture I/O support (removed in GLFW 3).
  30. *
  31. * Authors:
  32. * - Jari Vetoniemi <mailroxas@gmail.com>
  33. * - Éloi Rivard <eloi.rivard@gmail.com>
  34. * - Thomas Borsos <thomasborsos@gmail.com>
  35. */
  36. var LibraryGLFW = {
  37. $GLFW_Window__docs: '/** @constructor */',
  38. $GLFW_Window: function(id, width, height, title, monitor, share) {
  39. this.id = id;
  40. this.x = 0;
  41. this.y = 0;
  42. this.fullscreen = false; // Used to determine if app in fullscreen mode
  43. this.storedX = 0; // Used to store X before fullscreen
  44. this.storedY = 0; // Used to store Y before fullscreen
  45. this.width = width;
  46. this.height = height;
  47. this.storedWidth = width; // Used to store width before fullscreen
  48. this.storedHeight = height; // Used to store height before fullscreen
  49. this.title = title;
  50. this.monitor = monitor;
  51. this.share = share;
  52. this.attributes = GLFW.hints;
  53. this.inputModes = {
  54. 0x00033001:0x00034001, // GLFW_CURSOR (GLFW_CURSOR_NORMAL)
  55. 0x00033002:0, // GLFW_STICKY_KEYS
  56. 0x00033003:0, // GLFW_STICKY_MOUSE_BUTTONS
  57. };
  58. this.buttons = 0;
  59. this.keys = new Array();
  60. this.domKeys = new Array();
  61. this.shouldClose = 0;
  62. this.title = null;
  63. this.windowPosFunc = null; // GLFWwindowposfun
  64. this.windowSizeFunc = null; // GLFWwindowsizefun
  65. this.windowCloseFunc = null; // GLFWwindowclosefun
  66. this.windowRefreshFunc = null; // GLFWwindowrefreshfun
  67. this.windowFocusFunc = null; // GLFWwindowfocusfun
  68. this.windowIconifyFunc = null; // GLFWwindowiconifyfun
  69. this.framebufferSizeFunc = null; // GLFWframebuffersizefun
  70. this.mouseButtonFunc = null; // GLFWmousebuttonfun
  71. this.cursorPosFunc = null; // GLFWcursorposfun
  72. this.cursorEnterFunc = null; // GLFWcursorenterfun
  73. this.scrollFunc = null; // GLFWscrollfun
  74. this.dropFunc = null; // GLFWdropfun
  75. this.keyFunc = null; // GLFWkeyfun
  76. this.charFunc = null; // GLFWcharfun
  77. this.userptr = null;
  78. },
  79. $GLFW__deps: ['emscripten_get_now', '$GL', '$Browser', '$GLFW_Window',
  80. #if FILESYSTEM
  81. , '$FS'
  82. #endif
  83. ],
  84. $GLFW: {
  85. WindowFromId: function(id) {
  86. if (id <= 0 || !GLFW.windows) return null;
  87. return GLFW.windows[id - 1];
  88. },
  89. joystickFunc: null, // GLFWjoystickfun
  90. errorFunc: null, // GLFWerrorfun
  91. monitorFunc: null, // GLFWmonitorfun
  92. active: null, // active window
  93. windows: null,
  94. monitors: null,
  95. monitorString: null,
  96. versionString: null,
  97. initialTime: null,
  98. extensions: null,
  99. hints: null,
  100. defaultHints: {
  101. 0x00020001:0, // GLFW_FOCUSED
  102. 0x00020002:0, // GLFW_ICONIFIED
  103. 0x00020003:1, // GLFW_RESIZABLE
  104. 0x00020004:1, // GLFW_VISIBLE
  105. 0x00020005:1, // GLFW_DECORATED
  106. 0x00021001:8, // GLFW_RED_BITS
  107. 0x00021002:8, // GLFW_GREEN_BITS
  108. 0x00021003:8, // GLFW_BLUE_BITS
  109. 0x00021004:8, // GLFW_ALPHA_BITS
  110. 0x00021005:24, // GLFW_DEPTH_BITS
  111. 0x00021006:8, // GLFW_STENCIL_BITS
  112. 0x00021007:0, // GLFW_ACCUM_RED_BITS
  113. 0x00021008:0, // GLFW_ACCUM_GREEN_BITS
  114. 0x00021009:0, // GLFW_ACCUM_BLUE_BITS
  115. 0x0002100A:0, // GLFW_ACCUM_ALPHA_BITS
  116. 0x0002100B:0, // GLFW_AUX_BUFFERS
  117. 0x0002100C:0, // GLFW_STEREO
  118. 0x0002100D:0, // GLFW_SAMPLES
  119. 0x0002100E:0, // GLFW_SRGB_CAPABLE
  120. 0x0002100F:0, // GLFW_REFRESH_RATE
  121. 0x00022001:0x00030001, // GLFW_CLIENT_API (GLFW_OPENGL_API)
  122. 0x00022002:1, // GLFW_CONTEXT_VERSION_MAJOR
  123. 0x00022003:0, // GLFW_CONTEXT_VERSION_MINOR
  124. 0x00022004:0, // GLFW_CONTEXT_REVISION
  125. 0x00022005:0, // GLFW_CONTEXT_ROBUSTNESS
  126. 0x00022006:0, // GLFW_OPENGL_FORWARD_COMPAT
  127. 0x00022007:0, // GLFW_OPENGL_DEBUG_CONTEXT
  128. 0x00022008:0, // GLFW_OPENGL_PROFILE
  129. },
  130. /*******************************************************************************
  131. * DOM EVENT CALLBACKS
  132. ******************************************************************************/
  133. /* https://developer.mozilla.org/en/Document_Object_Model_%28DOM%29/KeyboardEvent and GLFW/glfw3.h */
  134. DOMToGLFWKeyCode: function(keycode) {
  135. switch (keycode) {
  136. // these keycodes are only defined for GLFW3, assume they are the same for GLFW2
  137. case 0x20:return 32; // DOM_VK_SPACE -> GLFW_KEY_SPACE
  138. case 0xDE:return 39; // DOM_VK_QUOTE -> GLFW_KEY_APOSTROPHE
  139. case 0xBC:return 44; // DOM_VK_COMMA -> GLFW_KEY_COMMA
  140. case 0xAD:return 45; // DOM_VK_HYPHEN_MINUS -> GLFW_KEY_MINUS
  141. case 0xBD:return 45; // DOM_VK_MINUS -> GLFW_KEY_MINUS
  142. case 0xBE:return 46; // DOM_VK_PERIOD -> GLFW_KEY_PERIOD
  143. case 0xBF:return 47; // DOM_VK_SLASH -> GLFW_KEY_SLASH
  144. case 0x30:return 48; // DOM_VK_0 -> GLFW_KEY_0
  145. case 0x31:return 49; // DOM_VK_1 -> GLFW_KEY_1
  146. case 0x32:return 50; // DOM_VK_2 -> GLFW_KEY_2
  147. case 0x33:return 51; // DOM_VK_3 -> GLFW_KEY_3
  148. case 0x34:return 52; // DOM_VK_4 -> GLFW_KEY_4
  149. case 0x35:return 53; // DOM_VK_5 -> GLFW_KEY_5
  150. case 0x36:return 54; // DOM_VK_6 -> GLFW_KEY_6
  151. case 0x37:return 55; // DOM_VK_7 -> GLFW_KEY_7
  152. case 0x38:return 56; // DOM_VK_8 -> GLFW_KEY_8
  153. case 0x39:return 57; // DOM_VK_9 -> GLFW_KEY_9
  154. case 0x3B:return 59; // DOM_VK_SEMICOLON -> GLFW_KEY_SEMICOLON
  155. case 0x3D:return 61; // DOM_VK_EQUALS -> GLFW_KEY_EQUAL
  156. case 0xBB:return 61; // DOM_VK_EQUALS -> GLFW_KEY_EQUAL
  157. case 0x41:return 65; // DOM_VK_A -> GLFW_KEY_A
  158. case 0x42:return 66; // DOM_VK_B -> GLFW_KEY_B
  159. case 0x43:return 67; // DOM_VK_C -> GLFW_KEY_C
  160. case 0x44:return 68; // DOM_VK_D -> GLFW_KEY_D
  161. case 0x45:return 69; // DOM_VK_E -> GLFW_KEY_E
  162. case 0x46:return 70; // DOM_VK_F -> GLFW_KEY_F
  163. case 0x47:return 71; // DOM_VK_G -> GLFW_KEY_G
  164. case 0x48:return 72; // DOM_VK_H -> GLFW_KEY_H
  165. case 0x49:return 73; // DOM_VK_I -> GLFW_KEY_I
  166. case 0x4A:return 74; // DOM_VK_J -> GLFW_KEY_J
  167. case 0x4B:return 75; // DOM_VK_K -> GLFW_KEY_K
  168. case 0x4C:return 76; // DOM_VK_L -> GLFW_KEY_L
  169. case 0x4D:return 77; // DOM_VK_M -> GLFW_KEY_M
  170. case 0x4E:return 78; // DOM_VK_N -> GLFW_KEY_N
  171. case 0x4F:return 79; // DOM_VK_O -> GLFW_KEY_O
  172. case 0x50:return 80; // DOM_VK_P -> GLFW_KEY_P
  173. case 0x51:return 81; // DOM_VK_Q -> GLFW_KEY_Q
  174. case 0x52:return 82; // DOM_VK_R -> GLFW_KEY_R
  175. case 0x53:return 83; // DOM_VK_S -> GLFW_KEY_S
  176. case 0x54:return 84; // DOM_VK_T -> GLFW_KEY_T
  177. case 0x55:return 85; // DOM_VK_U -> GLFW_KEY_U
  178. case 0x56:return 86; // DOM_VK_V -> GLFW_KEY_V
  179. case 0x57:return 87; // DOM_VK_W -> GLFW_KEY_W
  180. case 0x58:return 88; // DOM_VK_X -> GLFW_KEY_X
  181. case 0x59:return 89; // DOM_VK_Y -> GLFW_KEY_Y
  182. case 0x5a:return 90; // DOM_VK_Z -> GLFW_KEY_Z
  183. case 0xDB:return 91; // DOM_VK_OPEN_BRACKET -> GLFW_KEY_LEFT_BRACKET
  184. case 0xDC:return 92; // DOM_VK_BACKSLASH -> GLFW_KEY_BACKSLASH
  185. case 0xDD:return 93; // DOM_VK_CLOSE_BRACKET -> GLFW_KEY_RIGHT_BRACKET
  186. case 0xC0:return 94; // DOM_VK_BACK_QUOTE -> GLFW_KEY_GRAVE_ACCENT
  187. #if USE_GLFW == 2
  188. //#define GLFW_KEY_SPECIAL 256
  189. case 0x1B:return (256+1); // DOM_VK_ESCAPE -> GLFW_KEY_ESC
  190. case 0x70:return (256+2); // DOM_VK_F1 -> GLFW_KEY_F1
  191. case 0x71:return (256+3); // DOM_VK_F2 -> GLFW_KEY_F2
  192. case 0x72:return (256+4); // DOM_VK_F3 -> GLFW_KEY_F3
  193. case 0x73:return (256+5); // DOM_VK_F4 -> GLFW_KEY_F4
  194. case 0x74:return (256+6); // DOM_VK_F5 -> GLFW_KEY_F5
  195. case 0x75:return (256+7); // DOM_VK_F6 -> GLFW_KEY_F6
  196. case 0x76:return (256+8); // DOM_VK_F7 -> GLFW_KEY_F7
  197. case 0x77:return (256+9); // DOM_VK_F8 -> GLFW_KEY_F8
  198. case 0x78:return (256+10); // DOM_VK_F9 -> GLFW_KEY_F9
  199. case 0x79:return (256+11); // DOM_VK_F10 -> GLFW_KEY_F10
  200. case 0x7A:return (256+12); // DOM_VK_F11 -> GLFW_KEY_F11
  201. case 0x7B:return (256+13); // DOM_VK_F12 -> GLFW_KEY_F12
  202. case 0x7C:return (256+14); // DOM_VK_F13 -> GLFW_KEY_F13
  203. case 0x7D:return (256+15); // DOM_VK_F14 -> GLFW_KEY_F14
  204. case 0x7E:return (256+16); // DOM_VK_F15 -> GLFW_KEY_F15
  205. case 0x7F:return (256+17); // DOM_VK_F16 -> GLFW_KEY_F16
  206. case 0x80:return (256+18); // DOM_VK_F17 -> GLFW_KEY_F17
  207. case 0x81:return (256+19); // DOM_VK_F18 -> GLFW_KEY_F18
  208. case 0x82:return (256+20); // DOM_VK_F19 -> GLFW_KEY_F19
  209. case 0x83:return (256+21); // DOM_VK_F20 -> GLFW_KEY_F20
  210. case 0x84:return (256+22); // DOM_VK_F21 -> GLFW_KEY_F21
  211. case 0x85:return (256+23); // DOM_VK_F22 -> GLFW_KEY_F22
  212. case 0x86:return (256+24); // DOM_VK_F23 -> GLFW_KEY_F23
  213. case 0x87:return (256+25); // DOM_VK_F24 -> GLFW_KEY_F24
  214. case 0x88:return (256+26); // 0x88 (not used?) -> GLFW_KEY_F25
  215. case 0x27:return (256+30); // DOM_VK_RIGHT -> GLFW_KEY_RIGHT
  216. case 0x25:return (256+29); // DOM_VK_LEFT -> GLFW_KEY_LEFT
  217. case 0x28:return (256+28); // DOM_VK_DOWN -> GLFW_KEY_DOWN
  218. case 0x26:return (256+27); // DOM_VK_UP -> GLFW_KEY_UP
  219. case 0x10:return (256+31); // DOM_VK_SHIFT -> GLFW_KEY_LSHIFT
  220. // #define GLFW_KEY_RSHIFT (GLFW_KEY_SPECIAL+32)
  221. case 0x11:return (256+33); // DOM_VK_CONTROL -> GLFW_KEY_LCTRL
  222. // #define GLFW_KEY_RCTRL (GLFW_KEY_SPECIAL+34)
  223. case 0x12:return (256+35); // DOM_VK_ALT -> GLFW_KEY_LALT
  224. // #define GLFW_KEY_RALT (GLFW_KEY_SPECIAL+36)
  225. case 0x09:return (256+37); // DOM_VK_TAB -> GLFW_KEY_TAB
  226. case 0x0D:return (256+38); // DOM_VK_RETURN -> GLFW_KEY_ENTER
  227. case 0x08:return (256+39); // DOM_VK_BACK -> GLFW_KEY_BACKSPACE
  228. case 0x2D:return (256+40); // DOM_VK_INSERT -> GLFW_KEY_INSERT
  229. case 0x2E:return (256+41); // DOM_VK_DELETE -> GLFW_KEY_DEL
  230. case 0x21:return (256+42); // DOM_VK_PAGE_UP -> GLFW_KEY_PAGEUP
  231. case 0x22:return (256+43); // DOM_VK_PAGE_DOWN -> GLFW_KEY_PAGEDOWN
  232. case 0x24:return (256+44); // DOM_VK_HOME -> GLFW_KEY_HOME
  233. case 0x23:return (256+45); // DOM_VK_END -> GLFW_KEY_END
  234. case 0x60:return (256+46); // DOM_VK_NUMPAD0 -> GLFW_KEY_KP_0
  235. case 0x61:return (256+47); // DOM_VK_NUMPAD1 -> GLFW_KEY_KP_1
  236. case 0x62:return (256+48); // DOM_VK_NUMPAD2 -> GLFW_KEY_KP_2
  237. case 0x63:return (256+49); // DOM_VK_NUMPAD3 -> GLFW_KEY_KP_3
  238. case 0x64:return (256+50); // DOM_VK_NUMPAD4 -> GLFW_KEY_KP_4
  239. case 0x65:return (256+51); // DOM_VK_NUMPAD5 -> GLFW_KEY_KP_5
  240. case 0x66:return (256+52); // DOM_VK_NUMPAD6 -> GLFW_KEY_KP_6
  241. case 0x67:return (256+53); // DOM_VK_NUMPAD7 -> GLFW_KEY_KP_7
  242. case 0x68:return (256+54); // DOM_VK_NUMPAD8 -> GLFW_KEY_KP_8
  243. case 0x69:return (256+55); // DOM_VK_NUMPAD9 -> GLFW_KEY_KP_9
  244. case 0x6F:return (256+56); // DOM_VK_DIVIDE -> GLFW_KEY_KP_DIVIDE
  245. case 0x6A:return (256+57); // DOM_VK_MULTIPLY -> GLFW_KEY_KP_MULTIPLY
  246. case 0x6D:return (256+58); // DOM_VK_SUBTRACT -> GLFW_KEY_KP_SUBTRACT
  247. case 0x6B:return (256+59); // DOM_VK_ADD -> GLFW_KEY_KP_ADD
  248. case 0x6E:return (256+60); // DOM_VK_DECIMAL -> GLFW_KEY_KP_DECIMAL
  249. // #define GLFW_KEY_KP_EQUAL (GLFW_KEY_SPECIAL+61)
  250. // #define GLFW_KEY_KP_ENTER (GLFW_KEY_SPECIAL+62)
  251. case 0x90:return (256+63); // DOM_VK_NUM_LOCK -> GLFW_KEY_KP_NUM_LOCK
  252. case 0x14:return (256+64); // DOM_VK_CAPS_LOCK -> GLFW_KEY_CAPS_LOCK
  253. case 0x91:return (256+65); // DOM_VK_SCROLL_LOCK -> GLFW_KEY_SCROLL_LOCK
  254. case 0x13:return (256+66); // DOM_VK_PAUSE -> GLFW_KEY_PAUSE
  255. case 0x5B:return (256+67); // DOM_VK_WIN -> GLFW_KEY_LSUPER
  256. // #define GLFW_KEY_RSUPER (GLFW_KEY_SPECIAL+68)
  257. case 0x5D:return (256+69); // DOM_VK_CONTEXT_MENU -> GLFW_KEY_MENU
  258. #endif
  259. #if USE_GLFW == 3
  260. case 0x1B:return 256; // DOM_VK_ESCAPE -> GLFW_KEY_ESCAPE
  261. case 0x0D:return 257; // DOM_VK_RETURN -> GLFW_KEY_ENTER
  262. case 0x09:return 258; // DOM_VK_TAB -> GLFW_KEY_TAB
  263. case 0x08:return 259; // DOM_VK_BACK -> GLFW_KEY_BACKSPACE
  264. case 0x2D:return 260; // DOM_VK_INSERT -> GLFW_KEY_INSERT
  265. case 0x2E:return 261; // DOM_VK_DELETE -> GLFW_KEY_DELETE
  266. case 0x27:return 262; // DOM_VK_RIGHT -> GLFW_KEY_RIGHT
  267. case 0x25:return 263; // DOM_VK_LEFT -> GLFW_KEY_LEFT
  268. case 0x28:return 264; // DOM_VK_DOWN -> GLFW_KEY_DOWN
  269. case 0x26:return 265; // DOM_VK_UP -> GLFW_KEY_UP
  270. case 0x21:return 266; // DOM_VK_PAGE_UP -> GLFW_KEY_PAGE_UP
  271. case 0x22:return 267; // DOM_VK_PAGE_DOWN -> GLFW_KEY_PAGE_DOWN
  272. case 0x24:return 268; // DOM_VK_HOME -> GLFW_KEY_HOME
  273. case 0x23:return 269; // DOM_VK_END -> GLFW_KEY_END
  274. case 0x14:return 280; // DOM_VK_CAPS_LOCK -> GLFW_KEY_CAPS_LOCK
  275. case 0x91:return 281; // DOM_VK_SCROLL_LOCK -> GLFW_KEY_SCROLL_LOCK
  276. case 0x90:return 282; // DOM_VK_NUM_LOCK -> GLFW_KEY_NUM_LOCK
  277. case 0x2C:return 283; // DOM_VK_SNAPSHOT -> GLFW_KEY_PRINT_SCREEN
  278. case 0x13:return 284; // DOM_VK_PAUSE -> GLFW_KEY_PAUSE
  279. case 0x70:return 290; // DOM_VK_F1 -> GLFW_KEY_F1
  280. case 0x71:return 291; // DOM_VK_F2 -> GLFW_KEY_F2
  281. case 0x72:return 292; // DOM_VK_F3 -> GLFW_KEY_F3
  282. case 0x73:return 293; // DOM_VK_F4 -> GLFW_KEY_F4
  283. case 0x74:return 294; // DOM_VK_F5 -> GLFW_KEY_F5
  284. case 0x75:return 295; // DOM_VK_F6 -> GLFW_KEY_F6
  285. case 0x76:return 296; // DOM_VK_F7 -> GLFW_KEY_F7
  286. case 0x77:return 297; // DOM_VK_F8 -> GLFW_KEY_F8
  287. case 0x78:return 298; // DOM_VK_F9 -> GLFW_KEY_F9
  288. case 0x79:return 299; // DOM_VK_F10 -> GLFW_KEY_F10
  289. case 0x7A:return 300; // DOM_VK_F11 -> GLFW_KEY_F11
  290. case 0x7B:return 301; // DOM_VK_F12 -> GLFW_KEY_F12
  291. case 0x7C:return 302; // DOM_VK_F13 -> GLFW_KEY_F13
  292. case 0x7D:return 303; // DOM_VK_F14 -> GLFW_KEY_F14
  293. case 0x7E:return 304; // DOM_VK_F15 -> GLFW_KEY_F15
  294. case 0x7F:return 305; // DOM_VK_F16 -> GLFW_KEY_F16
  295. case 0x80:return 306; // DOM_VK_F17 -> GLFW_KEY_F17
  296. case 0x81:return 307; // DOM_VK_F18 -> GLFW_KEY_F18
  297. case 0x82:return 308; // DOM_VK_F19 -> GLFW_KEY_F19
  298. case 0x83:return 309; // DOM_VK_F20 -> GLFW_KEY_F20
  299. case 0x84:return 310; // DOM_VK_F21 -> GLFW_KEY_F21
  300. case 0x85:return 311; // DOM_VK_F22 -> GLFW_KEY_F22
  301. case 0x86:return 312; // DOM_VK_F23 -> GLFW_KEY_F23
  302. case 0x87:return 313; // DOM_VK_F24 -> GLFW_KEY_F24
  303. case 0x88:return 314; // 0x88 (not used?) -> GLFW_KEY_F25
  304. case 0x60:return 320; // DOM_VK_NUMPAD0 -> GLFW_KEY_KP_0
  305. case 0x61:return 321; // DOM_VK_NUMPAD1 -> GLFW_KEY_KP_1
  306. case 0x62:return 322; // DOM_VK_NUMPAD2 -> GLFW_KEY_KP_2
  307. case 0x63:return 323; // DOM_VK_NUMPAD3 -> GLFW_KEY_KP_3
  308. case 0x64:return 324; // DOM_VK_NUMPAD4 -> GLFW_KEY_KP_4
  309. case 0x65:return 325; // DOM_VK_NUMPAD5 -> GLFW_KEY_KP_5
  310. case 0x66:return 326; // DOM_VK_NUMPAD6 -> GLFW_KEY_KP_6
  311. case 0x67:return 327; // DOM_VK_NUMPAD7 -> GLFW_KEY_KP_7
  312. case 0x68:return 328; // DOM_VK_NUMPAD8 -> GLFW_KEY_KP_8
  313. case 0x69:return 329; // DOM_VK_NUMPAD9 -> GLFW_KEY_KP_9
  314. case 0x6E:return 330; // DOM_VK_DECIMAL -> GLFW_KEY_KP_DECIMAL
  315. case 0x6F:return 331; // DOM_VK_DIVIDE -> GLFW_KEY_KP_DIVIDE
  316. case 0x6A:return 332; // DOM_VK_MULTIPLY -> GLFW_KEY_KP_MULTIPLY
  317. case 0x6D:return 333; // DOM_VK_SUBTRACT -> GLFW_KEY_KP_SUBTRACT
  318. case 0x6B:return 334; // DOM_VK_ADD -> GLFW_KEY_KP_ADD
  319. // case 0x0D:return 335; // DOM_VK_RETURN -> GLFW_KEY_KP_ENTER (DOM_KEY_LOCATION_RIGHT)
  320. // case 0x61:return 336; // DOM_VK_EQUALS -> GLFW_KEY_KP_EQUAL (DOM_KEY_LOCATION_RIGHT)
  321. case 0x10:return 340; // DOM_VK_SHIFT -> GLFW_KEY_LEFT_SHIFT
  322. case 0x11:return 341; // DOM_VK_CONTROL -> GLFW_KEY_LEFT_CONTROL
  323. case 0x12:return 342; // DOM_VK_ALT -> GLFW_KEY_LEFT_ALT
  324. case 0x5B:return 343; // DOM_VK_WIN -> GLFW_KEY_LEFT_SUPER
  325. // case 0x10:return 344; // DOM_VK_SHIFT -> GLFW_KEY_RIGHT_SHIFT (DOM_KEY_LOCATION_RIGHT)
  326. // case 0x11:return 345; // DOM_VK_CONTROL -> GLFW_KEY_RIGHT_CONTROL (DOM_KEY_LOCATION_RIGHT)
  327. // case 0x12:return 346; // DOM_VK_ALT -> GLFW_KEY_RIGHT_ALT (DOM_KEY_LOCATION_RIGHT)
  328. // case 0x5B:return 347; // DOM_VK_WIN -> GLFW_KEY_RIGHT_SUPER (DOM_KEY_LOCATION_RIGHT)
  329. case 0x5D:return 348; // DOM_VK_CONTEXT_MENU -> GLFW_KEY_MENU
  330. // XXX: GLFW_KEY_WORLD_1, GLFW_KEY_WORLD_2 what are these?
  331. #endif
  332. default:return -1; // GLFW_KEY_UNKNOWN
  333. };
  334. },
  335. getModBits: function(win) {
  336. var mod = 0;
  337. if (win.keys[340]) mod |= 0x0001; // GLFW_MOD_SHIFT
  338. if (win.keys[341]) mod |= 0x0002; // GLFW_MOD_CONTROL
  339. if (win.keys[342]) mod |= 0x0004; // GLFW_MOD_ALT
  340. if (win.keys[343]) mod |= 0x0008; // GLFW_MOD_SUPER
  341. return mod;
  342. },
  343. onKeyPress: function(event) {
  344. if (!GLFW.active || !GLFW.active.charFunc) return;
  345. if (event.ctrlKey || event.metaKey) return;
  346. // correct unicode charCode is only available with onKeyPress event
  347. var charCode = event.charCode;
  348. if (charCode == 0 || (charCode >= 0x00 && charCode <= 0x1F)) return;
  349. #if USE_GLFW == 2
  350. {{{ makeDynCall('vii') }}}(GLFW.active.charFunc, charCode, 1);
  351. #endif
  352. #if USE_GLFW == 3
  353. {{{ makeDynCall('vii') }}}(GLFW.active.charFunc, GLFW.active.id, charCode);
  354. #endif
  355. },
  356. onKeyChanged: function(keyCode, status) {
  357. if (!GLFW.active) return;
  358. var key = GLFW.DOMToGLFWKeyCode(keyCode);
  359. if (key == -1) return;
  360. #if USE_GLFW == 3
  361. var repeat = status && GLFW.active.keys[key];
  362. #endif
  363. GLFW.active.keys[key] = status;
  364. GLFW.active.domKeys[keyCode] = status;
  365. if (!GLFW.active.keyFunc) return;
  366. #if USE_GLFW == 2
  367. {{{ makeDynCall('vii') }}}(GLFW.active.keyFunc, key, status);
  368. #endif
  369. #if USE_GLFW == 3
  370. if (repeat) status = 2; // GLFW_REPEAT
  371. {{{ makeDynCall('viiiii') }}}(GLFW.active.keyFunc, GLFW.active.id, key, keyCode, status, GLFW.getModBits(GLFW.active));
  372. #endif
  373. },
  374. onGamepadConnected: function(event) {
  375. GLFW.refreshJoysticks();
  376. },
  377. onGamepadDisconnected: function(event) {
  378. GLFW.refreshJoysticks();
  379. },
  380. onKeydown: function(event) {
  381. GLFW.onKeyChanged(event.keyCode, 1); // GLFW_PRESS or GLFW_REPEAT
  382. // This logic comes directly from the sdl implementation. We cannot
  383. // call preventDefault on all keydown events otherwise onKeyPress will
  384. // not get called
  385. if (event.keyCode === 8 /* backspace */ || event.keyCode === 9 /* tab */) {
  386. event.preventDefault();
  387. }
  388. },
  389. onKeyup: function(event) {
  390. GLFW.onKeyChanged(event.keyCode, 0); // GLFW_RELEASE
  391. },
  392. onBlur: function(event) {
  393. if (!GLFW.active) return;
  394. for (var i = 0; i < GLFW.active.domKeys.length; ++i) {
  395. if (GLFW.active.domKeys[i]) {
  396. GLFW.onKeyChanged(i, 0); // GLFW_RELEASE
  397. }
  398. }
  399. },
  400. onMousemove: function(event) {
  401. if (!GLFW.active) return;
  402. Browser.calculateMouseEvent(event);
  403. if (event.target != Module["canvas"] || !GLFW.active.cursorPosFunc) return;
  404. #if USE_GLFW == 2
  405. {{{ makeDynCall('vii') }}}(GLFW.active.cursorPosFunc, Browser.mouseX, Browser.mouseY);
  406. #endif
  407. #if USE_GLFW == 3
  408. {{{ makeDynCall('vidd') }}}(GLFW.active.cursorPosFunc, GLFW.active.id, Browser.mouseX, Browser.mouseY);
  409. #endif
  410. },
  411. DOMToGLFWMouseButton: function(event) {
  412. // DOM and glfw have different button codes.
  413. // See http://www.w3schools.com/jsref/event_button.asp.
  414. var eventButton = event['button'];
  415. if (eventButton > 0) {
  416. if (eventButton == 1) {
  417. eventButton = 2;
  418. } else {
  419. eventButton = 1;
  420. }
  421. }
  422. return eventButton;
  423. },
  424. onMouseenter: function(event) {
  425. if (!GLFW.active) return;
  426. if (event.target != Module["canvas"] || !GLFW.active.cursorEnterFunc) return;
  427. #if USE_GLFW == 3
  428. {{{ makeDynCall('vii') }}}(GLFW.active.cursorEnterFunc, GLFW.active.id, 1);
  429. #endif
  430. },
  431. onMouseleave: function(event) {
  432. if (!GLFW.active) return;
  433. if (event.target != Module["canvas"] || !GLFW.active.cursorEnterFunc) return;
  434. #if USE_GLFW == 3
  435. {{{ makeDynCall('vii') }}}(GLFW.active.cursorEnterFunc, GLFW.active.id, 0);
  436. #endif
  437. },
  438. onMouseButtonChanged: function(event, status) {
  439. if (!GLFW.active) return;
  440. Browser.calculateMouseEvent(event);
  441. if (event.target != Module["canvas"]) return;
  442. var eventButton = GLFW.DOMToGLFWMouseButton(event);
  443. if (status == 1) { // GLFW_PRESS
  444. GLFW.active.buttons |= (1 << eventButton);
  445. try {
  446. event.target.setCapture();
  447. } catch (e) {}
  448. } else { // GLFW_RELEASE
  449. GLFW.active.buttons &= ~(1 << eventButton);
  450. }
  451. if (!GLFW.active.mouseButtonFunc) return;
  452. #if USE_GLFW == 2
  453. {{{ makeDynCall('vii') }}}(GLFW.active.mouseButtonFunc, eventButton, status);
  454. #endif
  455. #if USE_GLFW == 3
  456. {{{ makeDynCall('viiii') }}}(GLFW.active.mouseButtonFunc, GLFW.active.id, eventButton, status, GLFW.getModBits(GLFW.active));
  457. #endif
  458. },
  459. onMouseButtonDown: function(event) {
  460. if (!GLFW.active) return;
  461. GLFW.onMouseButtonChanged(event, 1); // GLFW_PRESS
  462. },
  463. onMouseButtonUp: function(event) {
  464. if (!GLFW.active) return;
  465. GLFW.onMouseButtonChanged(event, 0); // GLFW_RELEASE
  466. },
  467. onMouseWheel: function(event) {
  468. // Note the minus sign that flips browser wheel direction (positive direction scrolls page down) to native wheel direction (positive direction is mouse wheel up)
  469. var delta = -Browser.getMouseWheelDelta(event);
  470. delta = (delta == 0) ? 0 : (delta > 0 ? Math.max(delta, 1) : Math.min(delta, -1)); // Quantize to integer so that minimum scroll is at least +/- 1.
  471. GLFW.wheelPos += delta;
  472. if (!GLFW.active || !GLFW.active.scrollFunc || event.target != Module['canvas']) return;
  473. #if USE_GLFW == 2
  474. {{{ makeDynCall('vi') }}}(GLFW.active.scrollFunc, GLFW.wheelPos);
  475. #endif
  476. #if USE_GLFW == 3
  477. var sx = 0;
  478. var sy = 0;
  479. if (event.type == 'mousewheel') {
  480. sx = event.wheelDeltaX;
  481. sy = event.wheelDeltaY;
  482. } else {
  483. sx = event.deltaX;
  484. sy = event.deltaY;
  485. }
  486. {{{ makeDynCall('vidd') }}}(GLFW.active.scrollFunc, GLFW.active.id, sx, sy);
  487. #endif
  488. event.preventDefault();
  489. },
  490. onCanvasResize: function(width, height) {
  491. if (!GLFW.active) return;
  492. var resizeNeeded = true;
  493. // If the client is requesting fullscreen mode
  494. if (document["fullscreen"] || document["fullScreen"] || document["mozFullScreen"] || document["webkitIsFullScreen"]) {
  495. GLFW.active.storedX = GLFW.active.x;
  496. GLFW.active.storedY = GLFW.active.y;
  497. GLFW.active.storedWidth = GLFW.active.width;
  498. GLFW.active.storedHeight = GLFW.active.height;
  499. GLFW.active.x = GLFW.active.y = 0;
  500. GLFW.active.width = screen.width;
  501. GLFW.active.height = screen.height;
  502. GLFW.active.fullscreen = true;
  503. // If the client is reverting from fullscreen mode
  504. } else if (GLFW.active.fullscreen == true) {
  505. GLFW.active.x = GLFW.active.storedX;
  506. GLFW.active.y = GLFW.active.storedY;
  507. GLFW.active.width = GLFW.active.storedWidth;
  508. GLFW.active.height = GLFW.active.storedHeight;
  509. GLFW.active.fullscreen = false;
  510. // If the width/height values do not match current active window sizes
  511. } else if (GLFW.active.width != width || GLFW.active.height != height) {
  512. GLFW.active.width = width;
  513. GLFW.active.height = height;
  514. } else {
  515. resizeNeeded = false;
  516. }
  517. // If any of the above conditions were true, we need to resize the canvas
  518. if (resizeNeeded) {
  519. // resets the canvas size to counter the aspect preservation of Browser.updateCanvasDimensions
  520. Browser.setCanvasSize(GLFW.active.width, GLFW.active.height, true);
  521. // TODO: Client dimensions (clientWidth/clientHeight) vs pixel dimensions (width/height) of
  522. // the canvas should drive window and framebuffer size respectfully.
  523. GLFW.onWindowSizeChanged();
  524. GLFW.onFramebufferSizeChanged();
  525. }
  526. },
  527. onWindowSizeChanged: function() {
  528. if (!GLFW.active) return;
  529. if (!GLFW.active.windowSizeFunc) return;
  530. #if USE_GLFW == 2
  531. {{{ makeDynCall('vii') }}}(GLFW.active.windowSizeFunc, GLFW.active.width, GLFW.active.height);
  532. #endif
  533. #if USE_GLFW == 3
  534. {{{ makeDynCall('viii') }}}(GLFW.active.windowSizeFunc, GLFW.active.id, GLFW.active.width, GLFW.active.height);
  535. #endif
  536. },
  537. onFramebufferSizeChanged: function() {
  538. if (!GLFW.active) return;
  539. if (!GLFW.active.framebufferSizeFunc) return;
  540. #if USE_GLFW == 3
  541. {{{ makeDynCall('viii') }}}(GLFW.active.framebufferSizeFunc, GLFW.active.id, GLFW.active.width, GLFW.active.height);
  542. #endif
  543. },
  544. getTime: function() {
  545. return _emscripten_get_now() / 1000;
  546. },
  547. /* GLFW2 wrapping */
  548. setWindowTitle: function(winid, title) {
  549. var win = GLFW.WindowFromId(winid);
  550. if (!win) return;
  551. win.title = UTF8ToString(title);
  552. if (GLFW.active.id == win.id) {
  553. document.title = win.title;
  554. }
  555. },
  556. setJoystickCallback: function(cbfun) {
  557. GLFW.joystickFunc = cbfun;
  558. GLFW.refreshJoysticks();
  559. },
  560. joys: {}, // glfw joystick data
  561. lastGamepadState: null,
  562. lastGamepadStateFrame: null, // The integer value of Browser.mainLoop.currentFrameNumber of when the last gamepad state was produced.
  563. refreshJoysticks: function() {
  564. // Produce a new Gamepad API sample if we are ticking a new game frame, or if not using emscripten_set_main_loop() at all to drive animation.
  565. if (Browser.mainLoop.currentFrameNumber !== GLFW.lastGamepadStateFrame || !Browser.mainLoop.currentFrameNumber) {
  566. GLFW.lastGamepadState = navigator.getGamepads ? navigator.getGamepads() : (navigator.webkitGetGamepads ? navigator.webkitGetGamepads : null);
  567. GLFW.lastGamepadStateFrame = Browser.mainLoop.currentFrameNumber;
  568. for (var joy = 0; joy < GLFW.lastGamepadState.length; ++joy) {
  569. var gamepad = GLFW.lastGamepadState[joy];
  570. if (gamepad) {
  571. if (!GLFW.joys[joy]) {
  572. console.log('glfw joystick connected:',joy);
  573. GLFW.joys[joy] = {
  574. id: allocate(intArrayFromString(gamepad.id), 'i8', ALLOC_NORMAL),
  575. buttonsCount: gamepad.buttons.length,
  576. axesCount: gamepad.axes.length,
  577. buttons: allocate(new Array(gamepad.buttons.length), 'i8', ALLOC_NORMAL),
  578. axes: allocate(new Array(gamepad.axes.length*4), 'float', ALLOC_NORMAL)
  579. };
  580. if (GLFW.joystickFunc) {
  581. {{{ makeDynCall('vii') }}}(GLFW.joystickFunc, joy, 0x00040001); // GLFW_CONNECTED
  582. }
  583. }
  584. var data = GLFW.joys[joy];
  585. for (var i = 0; i < gamepad.buttons.length; ++i) {
  586. setValue(data.buttons + i, gamepad.buttons[i].pressed, 'i8');
  587. }
  588. for (var i = 0; i < gamepad.axes.length; ++i) {
  589. setValue(data.axes + i*4, gamepad.axes[i], 'float');
  590. }
  591. } else {
  592. if (GLFW.joys[joy]) {
  593. console.log('glfw joystick disconnected',joy);
  594. if (GLFW.joystickFunc) {
  595. {{{ makeDynCall('vii') }}}(GLFW.joystickFunc, joy, 0x00040002); // GLFW_DISCONNECTED
  596. }
  597. _free(GLFW.joys[joy].id);
  598. _free(GLFW.joys[joy].buttons);
  599. _free(GLFW.joys[joy].axes);
  600. delete GLFW.joys[joy];
  601. }
  602. }
  603. }
  604. }
  605. },
  606. setKeyCallback: function(winid, cbfun) {
  607. var win = GLFW.WindowFromId(winid);
  608. if (!win) return null;
  609. var prevcbfun = win.keyFunc;
  610. win.keyFunc = cbfun;
  611. return prevcbfun;
  612. },
  613. setCharCallback: function(winid, cbfun) {
  614. var win = GLFW.WindowFromId(winid);
  615. if (!win) return null;
  616. var prevcbfun = win.charFunc;
  617. win.charFunc = cbfun;
  618. return prevcbfun;
  619. },
  620. setMouseButtonCallback: function(winid, cbfun) {
  621. var win = GLFW.WindowFromId(winid);
  622. if (!win) return null;
  623. var prevcbfun = win.mouseButtonFunc;
  624. win.mouseButtonFunc = cbfun;
  625. return prevcbfun;
  626. },
  627. setCursorPosCallback: function(winid, cbfun) {
  628. var win = GLFW.WindowFromId(winid);
  629. if (!win) return null;
  630. var prevcbfun = win.cursorPosFunc;
  631. win.cursorPosFunc = cbfun;
  632. return prevcbfun;
  633. },
  634. setScrollCallback: function(winid, cbfun) {
  635. var win = GLFW.WindowFromId(winid);
  636. if (!win) return null;
  637. var prevcbfun = win.scrollFunc;
  638. win.scrollFunc = cbfun;
  639. return prevcbfun;
  640. },
  641. setDropCallback: function(winid, cbfun) {
  642. var win = GLFW.WindowFromId(winid);
  643. if (!win) return null;
  644. var prevcbfun = win.dropFunc;
  645. win.dropFunc = cbfun;
  646. return prevcbfun;
  647. },
  648. onDrop: function(event) {
  649. if (!GLFW.active || !GLFW.active.dropFunc) return;
  650. if (!event.dataTransfer || !event.dataTransfer.files || event.dataTransfer.files.length == 0) return;
  651. event.preventDefault();
  652. #if FILESYSTEM
  653. var filenames = allocate(new Array(event.dataTransfer.files.length*4), 'i8*', ALLOC_NORMAL);
  654. var filenamesArray = [];
  655. var count = event.dataTransfer.files.length;
  656. // Read and save the files to emscripten's FS
  657. var written = 0;
  658. var drop_dir = '.glfw_dropped_files';
  659. FS.createPath('/', drop_dir);
  660. function save(file) {
  661. var path = '/' + drop_dir + '/' + file.name.replace(/\//g, '_');
  662. var reader = new FileReader();
  663. reader.onloadend = function(e) {
  664. if (reader.readyState != 2) { // not DONE
  665. ++written;
  666. console.log('failed to read dropped file: '+file.name+': '+reader.error);
  667. return;
  668. }
  669. var data = e.target.result;
  670. FS.writeFile(path, new Uint8Array(data));
  671. if (++written === count) {
  672. {{{ makeDynCall('viii') }}}(GLFW.active.dropFunc, GLFW.active.id, count, filenames);
  673. for (var i = 0; i < filenamesArray.length; ++i) {
  674. _free(filenamesArray[i]);
  675. }
  676. _free(filenames);
  677. }
  678. };
  679. reader.readAsArrayBuffer(file);
  680. var filename = allocate(intArrayFromString(path), 'i8', ALLOC_NORMAL);
  681. filenamesArray.push(filename);
  682. setValue(filenames + i*4, filename, 'i8*');
  683. }
  684. for (var i = 0; i < count; ++i) {
  685. save(event.dataTransfer.files[i]);
  686. }
  687. #endif // FILESYSTEM
  688. return false;
  689. },
  690. onDragover: function(event) {
  691. if (!GLFW.active || !GLFW.active.dropFunc) return;
  692. event.preventDefault();
  693. return false;
  694. },
  695. setWindowSizeCallback: function(winid, cbfun) {
  696. var win = GLFW.WindowFromId(winid);
  697. if (!win) return null;
  698. var prevcbfun = win.windowSizeFunc;
  699. win.windowSizeFunc = cbfun;
  700. #if USE_GLFW == 2
  701. // As documented in GLFW2 API (http://www.glfw.org/GLFWReference27.pdf#page=22), when size
  702. // callback function is set, it will be called with the current window size before this
  703. // function returns.
  704. // GLFW3 on the over hand doesn't have this behavior (https://github.com/glfw/glfw/issues/62).
  705. if (!win.windowSizeFunc) return null;
  706. {{{ makeDynCall('vii') }}}(win.windowSizeFunc, win.width, win.height);
  707. #endif
  708. return prevcbfun;
  709. },
  710. setWindowCloseCallback: function(winid, cbfun) {
  711. var win = GLFW.WindowFromId(winid);
  712. if (!win) return null;
  713. var prevcbfun = win.windowCloseFunc;
  714. win.windowCloseFunc = cbfun;
  715. return prevcbfun;
  716. },
  717. setWindowRefreshCallback: function(winid, cbfun) {
  718. var win = GLFW.WindowFromId(winid);
  719. if (!win) return null;
  720. var prevcbfun = win.windowRefreshFunc;
  721. win.windowRefreshFunc = cbfun;
  722. return prevcbfun;
  723. },
  724. onClickRequestPointerLock: function(e) {
  725. if (!Browser.pointerLock && Module['canvas'].requestPointerLock) {
  726. Module['canvas'].requestPointerLock();
  727. e.preventDefault();
  728. }
  729. },
  730. setInputMode: function(winid, mode, value) {
  731. var win = GLFW.WindowFromId(winid);
  732. if (!win) return;
  733. switch(mode) {
  734. case 0x00033001: { // GLFW_CURSOR
  735. switch(value) {
  736. case 0x00034001: { // GLFW_CURSOR_NORMAL
  737. win.inputModes[mode] = value;
  738. Module['canvas'].removeEventListener('click', GLFW.onClickRequestPointerLock, true);
  739. Module['canvas'].exitPointerLock();
  740. break;
  741. }
  742. case 0x00034002: { // GLFW_CURSOR_HIDDEN
  743. console.log("glfwSetInputMode called with GLFW_CURSOR_HIDDEN value not implemented.");
  744. break;
  745. }
  746. case 0x00034003: { // GLFW_CURSOR_DISABLED
  747. win.inputModes[mode] = value;
  748. Module['canvas'].addEventListener('click', GLFW.onClickRequestPointerLock, true);
  749. Module['canvas'].requestPointerLock();
  750. break;
  751. }
  752. default: {
  753. console.log("glfwSetInputMode called with unknown value parameter value: " + value + ".");
  754. break;
  755. }
  756. }
  757. break;
  758. }
  759. case 0x00033002: { // GLFW_STICKY_KEYS
  760. console.log("glfwSetInputMode called with GLFW_STICKY_KEYS mode not implemented.");
  761. break;
  762. }
  763. case 0x00033003: { // GLFW_STICKY_MOUSE_BUTTONS
  764. console.log("glfwSetInputMode called with GLFW_STICKY_MOUSE_BUTTONS mode not implemented.");
  765. break;
  766. }
  767. default: {
  768. console.log("glfwSetInputMode called with unknown mode parameter value: " + mode + ".");
  769. break;
  770. }
  771. }
  772. },
  773. getKey: function(winid, key) {
  774. var win = GLFW.WindowFromId(winid);
  775. if (!win) return 0;
  776. return win.keys[key];
  777. },
  778. getMouseButton: function(winid, button) {
  779. var win = GLFW.WindowFromId(winid);
  780. if (!win) return 0;
  781. return (win.buttons & (1 << button)) > 0;
  782. },
  783. getCursorPos: function(winid, x, y) {
  784. setValue(x, Browser.mouseX, 'double');
  785. setValue(y, Browser.mouseY, 'double');
  786. },
  787. getMousePos: function(winid, x, y) {
  788. setValue(x, Browser.mouseX, 'i32');
  789. setValue(y, Browser.mouseY, 'i32');
  790. },
  791. setCursorPos: function(winid, x, y) {
  792. },
  793. getWindowPos: function(winid, x, y) {
  794. var wx = 0;
  795. var wy = 0;
  796. var win = GLFW.WindowFromId(winid);
  797. if (win) {
  798. wx = win.x;
  799. wy = win.y;
  800. }
  801. setValue(x, wx, 'i32');
  802. setValue(y, wy, 'i32');
  803. },
  804. setWindowPos: function(winid, x, y) {
  805. var win = GLFW.WindowFromId(winid);
  806. if (!win) return;
  807. win.x = x;
  808. win.y = y;
  809. },
  810. getWindowSize: function(winid, width, height) {
  811. var ww = 0;
  812. var wh = 0;
  813. var win = GLFW.WindowFromId(winid);
  814. if (win) {
  815. ww = win.width;
  816. wh = win.height;
  817. }
  818. setValue(width, ww, 'i32');
  819. setValue(height, wh, 'i32');
  820. },
  821. setWindowSize: function(winid, width, height) {
  822. var win = GLFW.WindowFromId(winid);
  823. if (!win) return;
  824. if (GLFW.active.id == win.id) {
  825. if (width == screen.width && height == screen.height) {
  826. Browser.requestFullscreen();
  827. } else {
  828. Browser.exitFullscreen();
  829. Browser.setCanvasSize(width, height);
  830. win.width = width;
  831. win.height = height;
  832. }
  833. }
  834. if (!win.windowSizeFunc) return;
  835. #if USE_GLFW == 2
  836. {{{ makeDynCall('vii') }}}(win.windowSizeFunc, width, height);
  837. #endif
  838. #if USE_GLFW == 3
  839. {{{ makeDynCall('viii') }}}(win.windowSizeFunc, win.id, width, height);
  840. #endif
  841. },
  842. createWindow: function(width, height, title, monitor, share) {
  843. var i, id;
  844. for (i = 0; i < GLFW.windows.length && GLFW.windows[i] !== null; i++) {
  845. // no-op
  846. }
  847. if (i > 0) throw "glfwCreateWindow only supports one window at time currently";
  848. // id for window
  849. id = i + 1;
  850. // not valid
  851. if (width <= 0 || height <= 0) return 0;
  852. if (monitor) {
  853. Browser.requestFullscreen();
  854. } else {
  855. Browser.setCanvasSize(width, height);
  856. }
  857. // Create context when there are no existing alive windows
  858. for (i = 0; i < GLFW.windows.length && GLFW.windows[i] == null; i++) {
  859. // no-op
  860. }
  861. if (i == GLFW.windows.length) {
  862. var contextAttributes = {
  863. antialias: (GLFW.hints[0x0002100D] > 1), // GLFW_SAMPLES
  864. depth: (GLFW.hints[0x00021005] > 0), // GLFW_DEPTH_BITS
  865. stencil: (GLFW.hints[0x00021006] > 0), // GLFW_STENCIL_BITS
  866. alpha: (GLFW.hints[0x00021004] > 0) // GLFW_ALPHA_BITS
  867. }
  868. #if OFFSCREEN_FRAMEBUFFER
  869. // TODO: Make GLFW explicitly aware of whether it is being proxied or not, and set these to true only when proxying is being performed.
  870. GL.enableOffscreenFramebufferAttributes(contextAttributes);
  871. #endif
  872. Module.ctx = Browser.createContext(Module['canvas'], true, true, contextAttributes);
  873. }
  874. // If context creation failed, do not return a valid window
  875. if (!Module.ctx) return 0;
  876. // Get non alive id
  877. var win = new GLFW_Window(id, width, height, title, monitor, share);
  878. // Set window to array
  879. if (id - 1 == GLFW.windows.length) {
  880. GLFW.windows.push(win);
  881. } else {
  882. GLFW.windows[id - 1] = win;
  883. }
  884. GLFW.active = win;
  885. return win.id;
  886. },
  887. destroyWindow: function(winid) {
  888. var win = GLFW.WindowFromId(winid);
  889. if (!win) return;
  890. #if USE_GLFW == 3
  891. if (win.windowCloseFunc)
  892. {{{ makeDynCall('vi') }}}(win.windowCloseFunc, win.id);
  893. #endif
  894. GLFW.windows[win.id - 1] = null;
  895. if (GLFW.active.id == win.id)
  896. GLFW.active = null;
  897. // Destroy context when no alive windows
  898. for (var i = 0; i < GLFW.windows.length; i++)
  899. if (GLFW.windows[i] !== null) return;
  900. Module.ctx = Browser.destroyContext(Module['canvas'], true, true);
  901. },
  902. swapBuffers: function(winid) {
  903. },
  904. GLFW2ParamToGLFW3Param: function(param) {
  905. var table = {
  906. 0x00030001:0, // GLFW_MOUSE_CURSOR
  907. 0x00030002:0, // GLFW_STICKY_KEYS
  908. 0x00030003:0, // GLFW_STICKY_MOUSE_BUTTONS
  909. 0x00030004:0, // GLFW_SYSTEM_KEYS
  910. 0x00030005:0, // GLFW_KEY_REPEAT
  911. 0x00030006:0, // GLFW_AUTO_POLL_EVENTS
  912. 0x00020001:0, // GLFW_OPENED
  913. 0x00020002:0, // GLFW_ACTIVE
  914. 0x00020003:0, // GLFW_ICONIFIED
  915. 0x00020004:0, // GLFW_ACCELERATED
  916. 0x00020005:0x00021001, // GLFW_RED_BITS
  917. 0x00020006:0x00021002, // GLFW_GREEN_BITS
  918. 0x00020007:0x00021003, // GLFW_BLUE_BITS
  919. 0x00020008:0x00021004, // GLFW_ALPHA_BITS
  920. 0x00020009:0x00021005, // GLFW_DEPTH_BITS
  921. 0x0002000A:0x00021006, // GLFW_STENCIL_BITS
  922. 0x0002000B:0x0002100F, // GLFW_REFRESH_RATE
  923. 0x0002000C:0x00021007, // GLFW_ACCUM_RED_BITS
  924. 0x0002000D:0x00021008, // GLFW_ACCUM_GREEN_BITS
  925. 0x0002000E:0x00021009, // GLFW_ACCUM_BLUE_BITS
  926. 0x0002000F:0x0002100A, // GLFW_ACCUM_ALPHA_BITS
  927. 0x00020010:0x0002100B, // GLFW_AUX_BUFFERS
  928. 0x00020011:0x0002100C, // GLFW_STEREO
  929. 0x00020012:0, // GLFW_WINDOW_NO_RESIZE
  930. 0x00020013:0x0002100D, // GLFW_FSAA_SAMPLES
  931. 0x00020014:0x00022002, // GLFW_OPENGL_VERSION_MAJOR
  932. 0x00020015:0x00022003, // GLFW_OPENGL_VERSION_MINOR
  933. 0x00020016:0x00022006, // GLFW_OPENGL_FORWARD_COMPAT
  934. 0x00020017:0x00022007, // GLFW_OPENGL_DEBUG_CONTEXT
  935. 0x00020018:0x00022008, // GLFW_OPENGL_PROFILE
  936. };
  937. return table[param];
  938. }
  939. },
  940. /*******************************************************************************
  941. * GLFW FUNCTIONS
  942. ******************************************************************************/
  943. glfwInit: function() {
  944. if (GLFW.windows) return 1; // GL_TRUE
  945. GLFW.initialTime = GLFW.getTime();
  946. GLFW.hints = GLFW.defaultHints;
  947. GLFW.windows = new Array()
  948. GLFW.active = null;
  949. window.addEventListener("gamepadconnected", GLFW.onGamepadConnected, true);
  950. window.addEventListener("gamepaddisconnected", GLFW.onGamepadDisconnected, true);
  951. window.addEventListener("keydown", GLFW.onKeydown, true);
  952. window.addEventListener("keypress", GLFW.onKeyPress, true);
  953. window.addEventListener("keyup", GLFW.onKeyup, true);
  954. window.addEventListener("blur", GLFW.onBlur, true);
  955. Module["canvas"].addEventListener("touchmove", GLFW.onMousemove, true);
  956. Module["canvas"].addEventListener("touchstart", GLFW.onMouseButtonDown, true);
  957. Module["canvas"].addEventListener("touchcancel", GLFW.onMouseButtonUp, true);
  958. Module["canvas"].addEventListener("touchend", GLFW.onMouseButtonUp, true);
  959. Module["canvas"].addEventListener("mousemove", GLFW.onMousemove, true);
  960. Module["canvas"].addEventListener("mousedown", GLFW.onMouseButtonDown, true);
  961. Module["canvas"].addEventListener("mouseup", GLFW.onMouseButtonUp, true);
  962. Module["canvas"].addEventListener('wheel', GLFW.onMouseWheel, true);
  963. Module["canvas"].addEventListener('mousewheel', GLFW.onMouseWheel, true);
  964. Module["canvas"].addEventListener('mouseenter', GLFW.onMouseenter, true);
  965. Module["canvas"].addEventListener('mouseleave', GLFW.onMouseleave, true);
  966. Module["canvas"].addEventListener('drop', GLFW.onDrop, true);
  967. Module["canvas"].addEventListener('dragover', GLFW.onDragover, true);
  968. Browser.resizeListeners.push(function(width, height) {
  969. GLFW.onCanvasResize(width, height);
  970. });
  971. return 1; // GL_TRUE
  972. },
  973. glfwTerminate: function() {
  974. window.removeEventListener("gamepadconnected", GLFW.onGamepadConnected, true);
  975. window.removeEventListener("gamepaddisconnected", GLFW.onGamepadDisconnected, true);
  976. window.removeEventListener("keydown", GLFW.onKeydown, true);
  977. window.removeEventListener("keypress", GLFW.onKeyPress, true);
  978. window.removeEventListener("keyup", GLFW.onKeyup, true);
  979. window.removeEventListener("blur", GLFW.onBlur, true);
  980. Module["canvas"].removeEventListener("touchmove", GLFW.onMousemove, true);
  981. Module["canvas"].removeEventListener("touchstart", GLFW.onMouseButtonDown, true);
  982. Module["canvas"].removeEventListener("touchcancel", GLFW.onMouseButtonUp, true);
  983. Module["canvas"].removeEventListener("touchend", GLFW.onMouseButtonUp, true);
  984. Module["canvas"].removeEventListener("mousemove", GLFW.onMousemove, true);
  985. Module["canvas"].removeEventListener("mousedown", GLFW.onMouseButtonDown, true);
  986. Module["canvas"].removeEventListener("mouseup", GLFW.onMouseButtonUp, true);
  987. Module["canvas"].removeEventListener('wheel', GLFW.onMouseWheel, true);
  988. Module["canvas"].removeEventListener('mousewheel', GLFW.onMouseWheel, true);
  989. Module["canvas"].removeEventListener('mouseenter', GLFW.onMouseenter, true);
  990. Module["canvas"].removeEventListener('mouseleave', GLFW.onMouseleave, true);
  991. Module["canvas"].removeEventListener('drop', GLFW.onDrop, true);
  992. Module["canvas"].removeEventListener('dragover', GLFW.onDragover, true);
  993. Module["canvas"].width = Module["canvas"].height = 1;
  994. GLFW.windows = null;
  995. GLFW.active = null;
  996. },
  997. glfwGetVersion: function(major, minor, rev) {
  998. #if USE_GLFW == 2
  999. setValue(major, 2, 'i32');
  1000. setValue(minor, 7, 'i32');
  1001. setValue(rev, 7, 'i32');
  1002. #endif
  1003. #if USE_GLFW == 3
  1004. setValue(major, 3, 'i32');
  1005. setValue(minor, 2, 'i32');
  1006. setValue(rev, 1, 'i32');
  1007. #endif
  1008. },
  1009. glfwPollEvents: function() {},
  1010. glfwWaitEvents: function() {},
  1011. glfwGetTime: function() {
  1012. return GLFW.getTime() - GLFW.initialTime;
  1013. },
  1014. glfwSetTime: function(time) {
  1015. GLFW.initialTime = GLFW.getTime() - time;
  1016. },
  1017. glfwExtensionSupported__deps: ['glGetString'],
  1018. glfwExtensionSupported: function(extension) {
  1019. if (!GLFW.extensions) {
  1020. GLFW.extensions = UTF8ToString(_glGetString(0x1F03)).split(' ');
  1021. }
  1022. if (GLFW.extensions.indexOf(extension) != -1) return 1;
  1023. // extensions from GLEmulations do not come unprefixed
  1024. // so, try with prefix
  1025. return (GLFW.extensions.indexOf("GL_" + extension) != -1);
  1026. },
  1027. glfwGetProcAddress__deps: ['emscripten_GetProcAddress'],
  1028. glfwGetProcAddress: function(procname) {
  1029. return _emscripten_GetProcAddress(procname);
  1030. },
  1031. glfwSwapInterval__deps: ['emscripten_set_main_loop_timing'],
  1032. glfwSwapInterval: function(interval) {
  1033. interval = Math.abs(interval); // GLFW uses negative values to enable GLX_EXT_swap_control_tear, which we don't have, so just treat negative and positive the same.
  1034. if (interval == 0) _emscripten_set_main_loop_timing(0/*EM_TIMING_SETTIMEOUT*/, 0);
  1035. else _emscripten_set_main_loop_timing(1/*EM_TIMING_RAF*/, interval);
  1036. },
  1037. #if USE_GLFW == 3
  1038. glfwGetVersionString: function() {
  1039. if (!GLFW.versionString) {
  1040. GLFW.versionString = allocate(intArrayFromString("3.2.1 JS WebGL Emscripten"), 'i8', ALLOC_NORMAL);
  1041. }
  1042. return GLFW.versionString;
  1043. },
  1044. glfwSetErrorCallback: function(cbfun) {
  1045. var prevcbfun = GLFW.errorFunc;
  1046. GLFW.errorFunc = cbfun;
  1047. return prevcbfun;
  1048. },
  1049. glfwWaitEventsTimeout: function(timeout) {},
  1050. glfwPostEmptyEvent: function() {},
  1051. glfwGetMonitors: function(count) {
  1052. setValue(count, 1, 'i32');
  1053. if (!GLFW.monitors) {
  1054. GLFW.monitors = allocate([1, 0, 0, 0], 'i32', ALLOC_NORMAL);
  1055. }
  1056. return GLFW.monitors;
  1057. },
  1058. glfwGetPrimaryMonitor: function() {
  1059. return 1;
  1060. },
  1061. glfwGetMonitorPos: function(monitor, x, y) {
  1062. setValue(x, 0, 'i32');
  1063. setValue(y, 0, 'i32');
  1064. },
  1065. glfwGetMonitorPhysicalSize: function(monitor, width, height) {
  1066. // AFAIK there is no way to do this in javascript
  1067. // Maybe with platform specific ccalls?
  1068. //
  1069. // Lets report 0 now which is wrong as it can get for end user.
  1070. setValue(width, 0, 'i32');
  1071. setValue(height, 0, 'i32');
  1072. },
  1073. glfwGetMonitorName: function(mon) {
  1074. if (!GLFW.monitorString) {
  1075. GLFW.monitorString = allocate(intArrayFromString("HTML5 WebGL Canvas"), 'i8', ALLOC_NORMAL);
  1076. }
  1077. return GLFW.monitorString;
  1078. },
  1079. glfwSetMonitorCallback: function(cbfun) {
  1080. var prevcbfun = GLFW.monitorFunc;
  1081. GLFW.monitorFunc = cbfun;
  1082. return prevcbfun;
  1083. },
  1084. // TODO: implement
  1085. glfwGetVideoModes: function(monitor, count) {
  1086. setValue(count, 0, 'i32');
  1087. return 0;
  1088. },
  1089. // TODO: implement
  1090. glfwGetVideoMode: function(monitor) { return 0; },
  1091. // TODO: implement
  1092. glfwSetGamma: function(monitor, gamma) { },
  1093. glfwGetGammaRamp: function(monitor) {
  1094. throw "glfwGetGammaRamp not implemented.";
  1095. },
  1096. glfwSetGammaRamp: function(monitor, ramp) {
  1097. throw "glfwSetGammaRamp not implemented.";
  1098. },
  1099. glfwDefaultWindowHints: function() {
  1100. GLFW.hints = GLFW.defaultHints;
  1101. },
  1102. glfwWindowHint: function(target, hint) {
  1103. GLFW.hints[target] = hint;
  1104. },
  1105. glfwCreateWindow: function(width, height, title, monitor, share) {
  1106. return GLFW.createWindow(width, height, title, monitor, share);
  1107. },
  1108. glfwDestroyWindow: function(winid) {
  1109. return GLFW.destroyWindow(winid);
  1110. },
  1111. glfwWindowShouldClose: function(winid) {
  1112. var win = GLFW.WindowFromId(winid);
  1113. if (!win) return 0;
  1114. return win.shouldClose;
  1115. },
  1116. glfwSetWindowShouldClose: function(winid, value) {
  1117. var win = GLFW.WindowFromId(winid);
  1118. if (!win) return;
  1119. win.shouldClose = value;
  1120. },
  1121. glfwSetWindowTitle: function(winid, title) {
  1122. GLFW.setWindowTitle(winid, title);
  1123. },
  1124. glfwGetWindowPos: function(winid, x, y) {
  1125. GLFW.getWindowPos(winid, x, y);
  1126. },
  1127. glfwSetWindowPos: function(winid, x, y) {
  1128. GLFW.setWindowPos(winid, x, y);
  1129. },
  1130. glfwGetWindowSize: function(winid, width, height) {
  1131. GLFW.getWindowSize(winid, width, height);
  1132. },
  1133. glfwSetWindowSize: function(winid, width, height) {
  1134. GLFW.setWindowSize(winid, width, height);
  1135. },
  1136. glfwGetFramebufferSize: function(winid, width, height) {
  1137. var ww = 0;
  1138. var wh = 0;
  1139. var win = GLFW.WindowFromId(winid);
  1140. if (win) {
  1141. ww = win.width;
  1142. wh = win.height;
  1143. }
  1144. setValue(width, ww, 'i32');
  1145. setValue(height, wh, 'i32');
  1146. },
  1147. glfwIconifyWindow: function(winid) {
  1148. #if ASSERTIONS
  1149. warnOnce('glfwIconifyWindow is not implemented');
  1150. #endif
  1151. },
  1152. glfwRestoreWindow: function(winid) {
  1153. #if ASSERTIONS
  1154. warnOnce('glfwRestoreWindow is not implemented');
  1155. #endif
  1156. },
  1157. glfwShowWindow: function(winid) {},
  1158. glfwHideWindow: function(winid) {},
  1159. glfwGetWindowMonitor: function(winid) {
  1160. var win = GLFW.WindowFromId(winid);
  1161. if (!win) return 0;
  1162. return win.monitor;
  1163. },
  1164. glfwGetWindowAttrib: function(winid, attrib) {
  1165. var win = GLFW.WindowFromId(winid);
  1166. if (!win) return 0;
  1167. return win.attributes[attrib];
  1168. },
  1169. glfwSetWindowUserPointer: function(winid, ptr) {
  1170. var win = GLFW.WindowFromId(winid);
  1171. if (!win) return;
  1172. win.userptr = ptr;
  1173. },
  1174. glfwGetWindowUserPointer: function(winid) {
  1175. var win = GLFW.WindowFromId(winid);
  1176. if (!win) return 0;
  1177. return win.userptr;
  1178. },
  1179. glfwSetWindowPosCallback: function(winid, cbfun) {
  1180. var win = GLFW.WindowFromId(winid);
  1181. if (!win) return null;
  1182. var prevcbfun = win.windowPosFunc;
  1183. win.windowPosFunc = cbfun;
  1184. return prevcbfun;
  1185. },
  1186. glfwSetWindowSizeCallback: function(winid, cbfun) {
  1187. return GLFW.setWindowSizeCallback(winid, cbfun);
  1188. },
  1189. glfwSetWindowCloseCallback: function(winid, cbfun) {
  1190. return GLFW.setWindowCloseCallback(winid, cbfun);
  1191. },
  1192. glfwSetWindowRefreshCallback: function(winid, cbfun) {
  1193. return GLFW.setWindowRefreshCallback(winid, cbfun);
  1194. },
  1195. glfwSetWindowFocusCallback: function(winid, cbfun) {
  1196. var win = GLFW.WindowFromId(winid);
  1197. if (!win) return null;
  1198. var prevcbfun = win.windowFocusFunc;
  1199. win.windowFocusFunc = cbfun;
  1200. return prevcbfun;
  1201. },
  1202. glfwSetWindowIconifyCallback: function(winid, cbfun) {
  1203. var win = GLFW.WindowFromId(winid);
  1204. if (!win) return null;
  1205. var prevcbfun = win.windowIconifyFunc;
  1206. win.windowIconifyFunc = cbfun;
  1207. return prevcbfun;
  1208. },
  1209. glfwSetWindowIcon: function(winid, count, images) {},
  1210. glfwSetWindowSizeLimits: function(winid, minwidth, minheight, maxwidth, maxheight) {},
  1211. glfwSetWindowAspectRatio: function(winid, numer, denom) {},
  1212. glfwGetWindowFrameSize: function(winid, left, top, right, bottom) { throw "glfwGetWindowFrameSize not implemented."; },
  1213. glfwMaximizeWindow: function(winid) {},
  1214. glfwFocusWindow: function(winid) {},
  1215. glfwSetWindowMonitor: function(winid, monitor, xpos, ypos, width, height, refreshRate) { throw "glfwSetWindowMonitor not implemented."; },
  1216. glfwCreateCursor: function(image, xhot, yhot) {},
  1217. glfwCreateStandardCursor: function(shape) {},
  1218. glfwDestroyCursor: function(cursor) {},
  1219. glfwSetCursor: function(winid, cursor) {},
  1220. glfwSetFramebufferSizeCallback: function(winid, cbfun) {
  1221. var win = GLFW.WindowFromId(winid);
  1222. if (!win) return null;
  1223. var prevcbfun = win.framebufferSizeFunc;
  1224. win.framebufferSizeFunc = cbfun;
  1225. return prevcbfun;
  1226. },
  1227. glfwGetInputMode: function(winid, mode) {
  1228. var win = GLFW.WindowFromId(winid);
  1229. if (!win) return;
  1230. switch (mode) {
  1231. case 0x00033001: { // GLFW_CURSOR
  1232. if (Browser.pointerLock) {
  1233. win.inputModes[mode] = 0x00034003; // GLFW_CURSOR_DISABLED
  1234. } else {
  1235. win.inputModes[mode] = 0x00034001; // GLFW_CURSOR_NORMAL
  1236. }
  1237. }
  1238. }
  1239. return win.inputModes[mode];
  1240. },
  1241. glfwSetInputMode: function(winid, mode, value) {
  1242. GLFW.setInputMode(winid, mode, value);
  1243. },
  1244. glfwGetKey: function(winid, key) {
  1245. return GLFW.getKey(winid, key);
  1246. },
  1247. glfwGetKeyName: function(key, scancode) { throw "glfwGetKeyName not implemented."; },
  1248. glfwGetMouseButton: function(winid, button) {
  1249. return GLFW.getMouseButton(winid, button);
  1250. },
  1251. glfwGetCursorPos: function(winid, x, y) {
  1252. GLFW.getCursorPos(winid, x, y);
  1253. },
  1254. // I believe it is not possible to move the mouse with javascript
  1255. glfwSetCursorPos: function(winid, x, y) {
  1256. GLFW.setCursorPos(winid, x, y);
  1257. },
  1258. glfwSetKeyCallback: function(winid, cbfun) {
  1259. return GLFW.setKeyCallback(winid, cbfun);
  1260. },
  1261. glfwSetCharCallback: function(winid, cbfun) {
  1262. return GLFW.setCharCallback(winid, cbfun);
  1263. },
  1264. glfwSetCharModsCallback: function(winid, cbfun) { throw "glfwSetCharModsCallback not implemented."; },
  1265. glfwSetMouseButtonCallback: function(winid, cbfun) {
  1266. return GLFW.setMouseButtonCallback(winid, cbfun);
  1267. },
  1268. glfwSetCursorPosCallback: function(winid, cbfun) {
  1269. return GLFW.setCursorPosCallback(winid, cbfun);
  1270. },
  1271. glfwSetCursorEnterCallback: function(winid, cbfun) {
  1272. var win = GLFW.WindowFromId(winid);
  1273. if (!win) return null;
  1274. var prevcbfun = win.cursorEnterFunc;
  1275. win.cursorEnterFunc = cbfun;
  1276. return prevcbfun;
  1277. },
  1278. glfwSetScrollCallback: function(winid, cbfun) {
  1279. return GLFW.setScrollCallback(winid, cbfun);
  1280. },
  1281. glfwVulkanSupported: function() {
  1282. return 0;
  1283. },
  1284. glfwSetDropCallback: function(winid, cbfun) {
  1285. return GLFW.setDropCallback(winid, cbfun);
  1286. },
  1287. glfwGetTimerValue: function() { throw "glfwGetTimerValue is not implemented."; },
  1288. glfwGetTimerFrequency: function() { throw "glfwGetTimerFrequency is not implemented."; },
  1289. glfwGetRequiredInstanceExtensions: function(count) { throw "glfwGetRequiredInstanceExtensions is not implemented."; },
  1290. glfwGetInstanceProcAddress: function(instance, procname) { throw "glfwGetInstanceProcAddress is not implemented."; },
  1291. glfwGetPhysicalDevicePresentationSupport: function(instance, device, queuefamily) { throw "glfwGetPhysicalDevicePresentationSupport is not implemented"; },
  1292. glfwCreateWindowSurface: function(instance, winid, allocator, surface) { throw "glfwCreateWindowSurface is not implemented."; },
  1293. glfwJoystickPresent: function(joy) {
  1294. GLFW.refreshJoysticks();
  1295. return GLFW.joys[joy] !== undefined;
  1296. },
  1297. glfwGetJoystickAxes: function(joy, count) {
  1298. GLFW.refreshJoysticks();
  1299. var state = GLFW.joys[joy];
  1300. if (!state || !state.axes) {
  1301. setValue(count, 0, 'i32');
  1302. return;
  1303. }
  1304. setValue(count, state.axesCount, 'i32');
  1305. return state.axes;
  1306. },
  1307. glfwGetJoystickButtons: function(joy, count) {
  1308. GLFW.refreshJoysticks();
  1309. var state = GLFW.joys[joy];
  1310. if (!state || !state.buttons) {
  1311. setValue(count, 0, 'i32');
  1312. return;
  1313. }
  1314. setValue(count, state.buttonsCount, 'i32');
  1315. return state.buttons;
  1316. },
  1317. glfwGetJoystickName: function(joy) {
  1318. if (GLFW.joys[joy]) {
  1319. return GLFW.joys[joy].id;
  1320. } else {
  1321. return 0;
  1322. }
  1323. },
  1324. glfwSetJoystickCallback: function(cbfun) {
  1325. GLFW.setJoystickCallback(cbfun);
  1326. },
  1327. glfwSetClipboardString: function(win, string) {},
  1328. glfwGetClipboardString: function(win) {},
  1329. glfwMakeContextCurrent: function(winid) {},
  1330. glfwGetCurrentContext: function() {
  1331. return GLFW.active ? GLFW.active.id : 0;
  1332. },
  1333. glfwSwapBuffers: function(winid) {
  1334. GLFW.swapBuffers(winid);
  1335. },
  1336. #endif // GLFW 3
  1337. #if USE_GLFW == 2
  1338. glfwOpenWindow: function(width, height, redbits, greenbits, bluebits, alphabits, depthbits, stencilbits, mode) {
  1339. GLFW.hints[0x00021001] = redbits; // GLFW_RED_BITS
  1340. GLFW.hints[0x00021002] = greenbits; // GLFW_GREEN_BITS
  1341. GLFW.hints[0x00021003] = bluebits; // GLFW_BLUE_BITS
  1342. GLFW.hints[0x00021004] = alphabits; // GLFW_ALPHA_BITS
  1343. GLFW.hints[0x00021005] = depthbits; // GLFW_DEPTH_BITS
  1344. GLFW.hints[0x00021006] = stencilbits; // GLFW_STENCIL_BITS
  1345. GLFW.createWindow(width, height, "GLFW2 Window", 0, 0);
  1346. return 1; // GL_TRUE
  1347. },
  1348. glfwCloseWindow: function() {
  1349. GLFW.destroyWindow(GLFW.active.id);
  1350. },
  1351. glfwOpenWindowHint: function(target, hint) {
  1352. target = GLFW.GLFW2ParamToGLFW3Param(target);
  1353. GLFW.hints[target] = hint;
  1354. },
  1355. glfwGetWindowSize: function(width, height) {
  1356. GLFW.getWindowSize(GLFW.active.id, width, height);
  1357. },
  1358. glfwSetWindowSize: function(width, height) {
  1359. GLFW.setWindowSize(GLFW.active.id, width, height);
  1360. },
  1361. glfwGetWindowPos: function(x, y) {
  1362. GLFW.getWindowPos(GLFW.active.id, x, y);
  1363. },
  1364. glfwSetWindowPos: function(x, y) {
  1365. GLFW.setWindowPos(GLFW.active.id, x, y);
  1366. },
  1367. glfwSetWindowTitle: function(title) {
  1368. GLFW.setWindowTitle(GLFW.active.id, title);
  1369. },
  1370. glfwIconifyWindow: function() {
  1371. #if ASSERTIONS
  1372. warnOnce('glfwIconifyWindow is not implemented');
  1373. #endif
  1374. },
  1375. glfwRestoreWindow: function() {
  1376. #if ASSERTIONS
  1377. warnOnce('glfwRestoreWindow is not implemented');
  1378. #endif
  1379. },
  1380. glfwSwapBuffers: function() {
  1381. GLFW.swapBuffers(GLFW.active.id);
  1382. },
  1383. glfwGetWindowParam: function(param) {
  1384. param = GLFW.GLFW2ParamToGLFW3Param(param);
  1385. return GLFW.hints[param];
  1386. },
  1387. glfwSetWindowSizeCallback: function(cbfun) {
  1388. GLFW.setWindowSizeCallback(GLFW.active.id, cbfun);
  1389. },
  1390. glfwSetWindowCloseCallback: function(cbfun) {
  1391. GLFW.setWindowCloseCallback(GLFW.active.id, cbfun);
  1392. },
  1393. glfwSetWindowRefreshCallback: function(cbfun) {
  1394. GLFW.setWindowRefreshCallback(GLFW.active.id, cbfun);
  1395. },
  1396. glfwGetKey: function(key) {
  1397. return GLFW.getKey(GLFW.active.id, key);
  1398. },
  1399. glfwGetMouseButton: function(button) {
  1400. return GLFW.getMouseButton(GLFW.active.id, button);
  1401. },
  1402. glfwGetMousePos: function(x, y) {
  1403. GLFW.getMousePos(GLFW.active.id, x, y);
  1404. },
  1405. glfwSetMousePos: function(x, y) {
  1406. GLFW.setCursorPos(GLFW.active.id, x, y);
  1407. },
  1408. glfwGetMouseWheel: function() {
  1409. return 0;
  1410. },
  1411. glfwSetMouseWheel: function(pos) {
  1412. },
  1413. glfwSetKeyCallback: function(cbfun) {
  1414. GLFW.setKeyCallback(GLFW.active.id, cbfun);
  1415. },
  1416. glfwSetCharCallback: function(cbfun) {
  1417. GLFW.setCharCallback(GLFW.active.id, cbfun);
  1418. },
  1419. glfwSetMouseButtonCallback: function(cbfun) {
  1420. GLFW.setMouseButtonCallback(GLFW.active.id, cbfun);
  1421. },
  1422. glfwSetMousePosCallback: function(cbfun) {
  1423. GLFW.setCursorPosCallback(GLFW.active.id, cbfun);
  1424. },
  1425. glfwSetMouseWheelCallback: function(cbfun) {
  1426. GLFW.setScrollCallback(GLFW.active.id, cbfun);
  1427. },
  1428. glfwGetDesktopMode: function(mode) {
  1429. throw "glfwGetDesktopMode is not implemented.";
  1430. },
  1431. glfwSleep__deps: ['sleep'],
  1432. glfwSleep: function(time) {
  1433. _sleep(time);
  1434. },
  1435. glfwEnable: function(target) {
  1436. target = GLFW.GLFW2ParamToGLFW3Param(target);
  1437. GLFW.hints[target] = false;
  1438. },
  1439. glfwDisable: function(target) {
  1440. target = GLFW.GLFW2ParamToGLFW3Param(target);
  1441. GLFW.hints[target] = true;
  1442. },
  1443. glfwGetGLVersion: function(major, minor, rev) {
  1444. setValue(major, 0, 'i32');
  1445. setValue(minor, 0, 'i32');
  1446. setValue(rev, 1, 'i32');
  1447. },
  1448. glfwCreateThread: function(fun, arg) {
  1449. var str = 'v';
  1450. for (var i in arg) {
  1451. str += 'i';
  1452. }
  1453. dynCall(str, fun, arg);
  1454. // One single thread
  1455. return 0;
  1456. },
  1457. glfwDestroyThread: function(ID) {},
  1458. glfwWaitThread: function(ID, waitmode) {},
  1459. glfwGetThreadID: function() {
  1460. // One single thread
  1461. return 0;
  1462. },
  1463. glfwCreateMutex: function() { throw "glfwCreateMutex is not implemented."; },
  1464. glfwDestroyMutex: function(mutex) { throw "glfwDestroyMutex is not implemented."; },
  1465. glfwLockMutex: function(mutex) { throw "glfwLockMutex is not implemented."; },
  1466. glfwUnlockMutex: function(mutex) { throw "glfwUnlockMutex is not implemented."; },
  1467. glfwCreateCond: function() { throw "glfwCreateCond is not implemented."; },
  1468. glfwDestroyCond: function(cond) { throw "glfwDestroyCond is not implemented."; },
  1469. glfwWaitCond: function(cond, mutex, timeout) { throw "glfwWaitCond is not implemented."; },
  1470. glfwSignalCond: function(cond) { throw "glfwSignalCond is not implemented."; },
  1471. glfwBroadcastCond: function(cond) { throw "glfwBroadcastCond is not implemented."; },
  1472. glfwGetNumberOfProcessors: function() {
  1473. // Threads are disabled anyway…
  1474. return 1;
  1475. },
  1476. glfwReadImage: function(name, img, flags) { throw "glfwReadImage is not implemented."; },
  1477. glfwReadMemoryImage: function(data, size, img, flags) { throw "glfwReadMemoryImage is not implemented."; },
  1478. glfwFreeImage: function(img) { throw "glfwFreeImage is not implemented."; },
  1479. glfwLoadTexture2D: function(name, flags) { throw "glfwLoadTexture2D is not implemented."; },
  1480. glfwLoadMemoryTexture2D: function(data, size, flags) { throw "glfwLoadMemoryTexture2D is not implemented."; },
  1481. glfwLoadTextureImage2D: function(img, flags) { throw "glfwLoadTextureImage2D is not implemented."; },
  1482. #endif // GLFW2
  1483. };
  1484. autoAddDeps(LibraryGLFW, '$GLFW');
  1485. mergeInto(LibraryManager.library, LibraryGLFW);