aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/library_glfw.js457
-rw-r--r--tests/glfw/Makefile5
-rw-r--r--tests/glfw/glfwsample.c375
3 files changed, 587 insertions, 250 deletions
diff --git a/src/library_glfw.js b/src/library_glfw.js
index 23dea5fc..6a000252 100644
--- a/src/library_glfw.js
+++ b/src/library_glfw.js
@@ -1,51 +1,140 @@
+/*******************************************************************************
+ * EMSCRIPTEN GLFW 2.7.7 emulation.
+ * It tries to copy the behavior described in
+ * http://www.glfw.org/GLFWReference277.pdf
+ *
+ * What it does:
+ * - Creates a GL context.
+ * - Manage keyboard and mouse events.
+ *
+ * What it does not but should do:
+ * - Transmit events when glfwPollEvents, glfwWaitEvents or glfwSwapBuffers is
+ * called. Events callbacks are called as soon as event are received.
+ * - Correctly handle unicode characters
+ * - Thread emulation.
+ * - Joystick support.
+ * - Image/Texture I/O support.
+ * - GL Extensions support.
+ * - Video modes.
+ *
+ ******************************************************************************/
var LibraryGLFW = {
$GLFW: {
- keyboardFunc: null,
- charFunc: null,
- mouseButtonFunc: null,
- mousePosFunc: null,
- mouseWheelFunc: null,
+ keyFunc: null,
+ charFunc: null,
+ mouseButtonFunc: null,
+ mousePosFunc: null,
+ mouseWheelFunc: null,
resizeFunc: null,
- closeFunc: null,
- refreshFunc: null,
+ closeFunc: null,
+ refreshFunc: null,
mouseFunc: null,
- params: null,
+ params: null,
initTime: null,
+ wheelPos: 0,
lastX: 0,
lastY: 0,
buttons: 0,
- modifiers: 0,
+ keys: 0,
initWindowWidth: 640,
initWindowHeight: 480,
-/*******************************************************************************
- * DOM EVENT CALLBACKS
- ******************************************************************************/
-
-/*
// Set when going fullscreen
windowX: 0,
windowY: 0,
windowWidth: 0,
windowHeight: 0,
-*/
+
+/*******************************************************************************
+ * DOM EVENT CALLBACKS
+ ******************************************************************************/
+
savePosition: function(event) {
/* TODO maybe loop here ala http://www.quirksmode.org/js/findpos.html */
GLFW.lastX = event['clientX'] - Module['canvas'].offsetLeft;
GLFW.lastY = event['clientY'] - Module['canvas'].offsetTop;
},
- saveModifiers: function(event) {
-/*
- GLFW.modifiers = 0;
- if (event['shiftKey'])
- GLFW.modifiers += 1; // GLFW_ACTIVE_SHIFT
- if (event['ctrlKey'])
- GLFW.modifiers += 2; // GLFW_ACTIVE_CTRL
- if (event['altKey'])
- GLFW.modifiers += 4; // GLFW_ACTIVE_ALT
-*/
+ DOMToGLFWKeyCode: function(keycode) {
+ switch (keycode) {
+ case 0x09 : return 295 ; //DOM_VK_TAB -> GLFW_KEY_TAB
+ case 0x1B : return 255 ; //DOM_VK_ESCAPE -> GLFW_KEY_ESC
+ case 0x6A : return 313 ; //DOM_VK_MULTIPLY -> GLFW_KEY_KP_MULTIPLY
+ case 0x6B : return 315 ; //DOM_VK_ADD -> GLFW_KEY_KP_ADD
+ case 0x6D : return 314 ; //DOM_VK_SUBTRACT -> GLFW_KEY_KP_SUBTRACT
+ case 0x6E : return 316 ; //DOM_VK_DECIMAL -> GLFW_KEY_KP_DECIMAL
+ case 0x6F : return 312 ; //DOM_VK_DIVIDE -> GLFW_KEY_KP_DIVIDE
+ case 0x70 : return 258 ; //DOM_VK_F1 -> GLFW_KEY_F1
+ case 0x71 : return 259 ; //DOM_VK_F2 -> GLFW_KEY_F2
+ case 0x72 : return 260 ; //DOM_VK_F3 -> GLFW_KEY_F3
+ case 0x73 : return 261 ; //DOM_VK_F4 -> GLFW_KEY_F4
+ case 0x74 : return 262 ; //DOM_VK_F5 -> GLFW_KEY_F5
+ case 0x75 : return 263 ; //DOM_VK_F6 -> GLFW_KEY_F6
+ case 0x76 : return 264 ; //DOM_VK_F7 -> GLFW_KEY_F7
+ case 0x77 : return 265 ; //DOM_VK_F8 -> GLFW_KEY_F8
+ case 0x78 : return 266 ; //DOM_VK_F9 -> GLFW_KEY_F9
+ case 0x79 : return 267 ; //DOM_VK_F10 -> GLFW_KEY_F10
+ case 0x7a : return 268 ; //DOM_VK_F11 -> GLFW_KEY_F11
+ case 0x7b : return 269 ; //DOM_VK_F12 -> GLFW_KEY_F12
+ case 0x25 : return 285 ; //DOM_VK_LEFT -> GLFW_KEY_LEFT
+ case 0x26 : return 283 ; //DOM_VK_UP -> GLFW_KEY_UP
+ case 0x27 : return 286 ; //DOM_VK_RIGHT -> GLFW_KEY_RIGHT
+ case 0x28 : return 284 ; //DOM_VK_DOWN -> GLFW_KEY_DOWN
+ case 0x21 : return 298 ; //DOM_VK_PAGE_UP -> GLFW_KEY_PAGEUP
+ case 0x22 : return 299 ; //DOM_VK_PAGE_DOWN -> GLFW_KEY_PAGEDOWN
+ case 0x24 : return 300 ; //DOM_VK_HOME -> GLFW_KEY_HOME
+ case 0x23 : return 301 ; //DOM_VK_END -> GLFW_KEY_END
+ case 0x2d : return 296 ; //DOM_VK_INSERT -> GLFW_KEY_INSERT
+ case 16 : return 287 ; //DOM_VK_SHIFT -> GLFW_KEY_LSHIFT
+ case 0x05 : return 287 ; //DOM_VK_LEFT_SHIFT -> GLFW_KEY_LSHIFT
+ case 0x06 : return 288 ; //DOM_VK_RIGHT_SHIFT -> GLFW_KEY_RSHIFT
+ case 17 : return 289 ; //DOM_VK_CONTROL -> GLFW_KEY_LCTRL
+ case 0x03 : return 289 ; //DOM_VK_LEFT_CONTROL -> GLFW_KEY_LCTRL
+ case 0x04 : return 290 ; //DOM_VK_RIGHT_CONTROL -> GLFW_KEY_RCTRL
+ case 18 : return 291 ; //DOM_VK_ALT -> GLFW_KEY_LALT
+ case 0x02 : return 291 ; //DOM_VK_LEFT_ALT -> GLFW_KEY_LALT
+ case 0x01 : return 292 ; //DOM_VK_RIGHT_ALT -> GLFW_KEY_RALT
+ case 96 : return 302 ; //GLFW_KEY_KP_0
+ case 97 : return 303 ; //GLFW_KEY_KP_1
+ case 98 : return 304 ; //GLFW_KEY_KP_2
+ case 99 : return 305 ; //GLFW_KEY_KP_3
+ case 100 : return 306 ; //GLFW_KEY_KP_4
+ case 101 : return 307 ; //GLFW_KEY_KP_5
+ case 102 : return 308 ; //GLFW_KEY_KP_6
+ case 103 : return 309 ; //GLFW_KEY_KP_7
+ case 104 : return 310 ; //GLFW_KEY_KP_8
+ case 105 : return 311 ; //GLFW_KEY_KP_9
+ default : return keycode;
+ };
+ },
+
+ getUnicodeKey: function(event) {
+ //TODO: return the correct Unicode ISO 10646 character
+ return event['keyCode'];
+ },
+
+ onKeyChanged: function(event, status){
+ var key = GLFW.DOMToGLFWKeyCode(event['keyCode']);
+ if(key && GLFW.keyFunc) {
+ GLFW.keys[key] = status;
+ event.preventDefault();
+ Runtime.dynCall('vii', GLFW.keyFunc, [key, status]);
+ }
+
+ var char = GLFW.getUnicodeKey(event);
+ if( char !== null && GLFW.charFunc ) {
+ event.preventDefault();
+ Runtime.dynCall('vii', GLFW.charFunc, [char, status]);
+ }
+ },
+
+ onKeydown: function(event) {
+ GLFW.onKeyChanged(event, 1);//GLFW_PRESS
+ },
+
+ onKeyup: function(event) {
+ GLFW.onKeyChanged(event, 0);//GLFW_RELEASE
},
onMousemove: function(event) {
@@ -59,207 +148,55 @@ var LibraryGLFW = {
return;
GLFW.savePosition(event);
-/*
- if (GLFW.buttons == 0 && event.target == Module["canvas"] && GLFW.passiveMotionFunc) {
+
+ if (event.target == Module["canvas"] && GLFW.mousePosFunc) {
event.preventDefault();
- GLFW.saveModifiers(event);
- Runtime.dynCall('vii', GLFW.passiveMotionFunc, [GLFW.lastX, GLFW.lastY]);
- } else if (GLFW.buttons != 0 && GLFW.motionFunc) {
- event.preventDefault();
- GLFW.saveModifiers(event);
- Runtime.dynCall('vii', GLFW.motionFunc, [GLFW.lastX, GLFW.lastY]);
- }
-*/
+ Runtime.dynCall('vii', GLFW.mousePosFunc, [GLFW.lastX, GLFW.lastY]);
+ }
},
- getSpecialKey: function(keycode) {
- var key = null;
-/*
- switch (keycode) {
- case 0x70 : //DOM_VK_F1
- key = 1 ;//GLUT_KEY_F1
- break;
- case 0x71 : //DOM_VK_F2
- key = 2 ;//GLUT_KEY_F2
- break;
- case 0x72 : //DOM_VK_F3
- key = 3 ;//GLUT_KEY_F3
- break;
- case 0x73 : //DOM_VK_F4
- key = 4 ;//GLUT_KEY_F4
- break;
- case 0x74 : //DOM_VK_F5
- key = 5 ;//GLUT_KEY_F5
- break;
- case 0x75 : //DOM_VK_F6
- key = 6 ;//GLUT_KEY_F6
- break;
- case 0x76 : //DOM_VK_F7
- key = 7 ;//GLUT_KEY_F7
- break;
- case 0x77 : //DOM_VK_F8
- key = 8 ;//GLUT_KEY_F8
- break;
- case 0x78 : //DOM_VK_F9
- key = 9 ;//GLUT_KEY_F9
- break;
- case 0x79 : //DOM_VK_F10
- key = 10 ;//GLUT_KEY_F10
- break;
- case 0x7a : //DOM_VK_F11
- key = 11 ;//GLUT_KEY_F11
- break;
- case 0x7b : //DOM_VK_F12
- key = 12 ;//GLUT_KEY_F12
- break;
- case 0x25 : //DOM_VK_LEFT
- key = 100 ;//GLUT_KEY_LEFT
- break;
- case 0x26 : //DOM_VK_UP
- key = 101 ;//GLUT_KEY_UP
- break;
- case 0x27 : //DOM_VK_RIGHT
- key = 102 ;//GLUT_KEY_RIGHT
- break;
- case 0x28 : //DOM_VK_DOWN
- key = 103 ;//GLUT_KEY_DOWN
- break;
- case 0x21 : //DOM_VK_PAGE_UP
- key = 104 ;//GLUT_KEY_PAGE_UP
- break;
- case 0x22 : //DOM_VK_PAGE_DOWN
- key = 105 ;//GLUT_KEY_PAGE_DOWN
- break;
- case 0x24 : //DOM_VK_HOME
- key = 106 ;//GLUT_KEY_HOME
- break;
- case 0x23 : //DOM_VK_END
- key = 107 ;//GLUT_KEY_END
- break;
- case 0x2d : //DOM_VK_INSERT
- key = 108 ;//GLUT_KEY_INSERT
- break;
- case 16 : //DOM_VK_SHIFT
- case 0x05 : //DOM_VK_LEFT_SHIFT
- key = 112 ;//GLUT_KEY_SHIFT_L
- break;
- case 0x06 : //DOM_VK_RIGHT_SHIFT
- key = 113 ;//GLUT_KEY_SHIFT_R
- break;
- case 17 : //DOM_VK_CONTROL
- case 0x03 : //DOM_VK_LEFT_CONTROL
- key = 114 ;//GLUT_KEY_CONTROL_L
- break;
- case 0x04 : //DOM_VK_RIGHT_CONTROL
- key = 115 ;//GLUT_KEY_CONTROL_R
- break;
- case 18 : //DOM_VK_ALT
- case 0x02 : //DOM_VK_LEFT_ALT
- key = 116 ;//GLUT_KEY_ALT_L
- break;
- case 0x01 : //DOM_VK_RIGHT_ALT
- key = 117 ;//GLUT_KEY_ALT_R
- break;
- };
-*/
- return key;
- },
-
- getASCIIKey: function(event) {
- if (event['ctrlKey'] || event['altKey'] || event['metaKey']) return null;
-/*
- var keycode = event['keyCode'];
- if (48 <= keycode && keycode <= 57)
- return keycode; // numeric TODO handle shift?
- if (65 <= keycode && keycode <= 90)
- return event['shiftKey'] ? keycode : keycode + 32;
- if (106 <= keycode && keycode <= 111)
- return keycode - 106 + 42; // *,+-./ TODO handle shift?
-
- switch (keycode) {
- case 27: // escape
- case 32: // space
- case 61: // equal
- return keycode;
- }
-
- var s = event['shiftKey'];
- switch (keycode) {
- case 186: return s ? 58 : 59; // colon / semi-colon
- case 187: return s ? 43 : 61; // add / equal (these two may be wrong)
- case 188: return s ? 60 : 44; // less-than / comma
- case 189: return s ? 95 : 45; // dash
- case 190: return s ? 62 : 46; // greater-than / period
- case 191: return s ? 63 : 47; // forward slash
- case 219: return s ? 123 : 91; // open bracket
- case 220: return s ? 124 : 47; // back slash
- case 221: return s ? 125 : 93; // close braket
- case 222: return s ? 34 : 39; // single quote
- }
-*/
- return null;
- },
-
- onKeyChanged: function(event, status){
- if (GLFW.charFunc || GLFW.keyboardFunc) {
- var key = GLFW.getSpecialKey(event['keyCode']);
- if (key !== null) {
- if( GLFW.keyboardFunc ) {
- event.preventDefault();
- GLFW.saveModifiers(event);
- Runtime.dynCall('vii', GLFW.keyboardFunc, [key, status]);
- }
- }
-
- key = GLFW.getASCIIKey(event);
- if( key !== null && GLFW.charFunc ) {
- event.preventDefault();
- GLFW.saveModifiers(event);
- Runtime.dynCall('vii', GLFW.charFunc, [key, status]);
- }
- }
- },
-
- onKeydown: function(event) {
- GLFW.onKeyChanged(event, 1);//GLFW_PRESS
- },
-
- onKeyup: function(event) {
- GLFW.onKeyChanged(event, 0);//GLFW_RELEASE
- },
-
- onMouseButtonChanged: function(event, status){
- if(GLFW.mouseButtonFunc == null)
- return;
+ onMouseButtonChanged: function(event, status){
+ if(GLFW.mouseButtonFunc == null)
+ return;
GLFW.savePosition(event);
if(event.target == Module["canvas"] || status == 0){//GLFW_RELEASE
- if(status == 1){//GLFW_PRESS
+ if(status == 1){//GLFW_PRESS
try {
event.target.setCapture();
} catch (e) {}
- }
+ }
event.preventDefault();
- GLFW.saveModifiers(event);
- //DOM and glfw have the same button codes
- Runtime.dynCall('vii', GLFW.mouseFunc, [event['button'], status]);
- }
- },
+ //DOM and glfw have the same button codes
+ Runtime.dynCall('vii', GLFW.mouseButtonFunc, [event['button'], status]);
+ }
+ },
onMouseButtonDown: function(event){
GLFW.buttons |= (1 << event['button']);
- GLFW.onMouseButtonChanged(event, 1);//GLFW_PRESS
- },
-
- onMouseButtonUp: function(event){
- GLFW.buttons &= ~(1 << event['button']);
- GLFW.onMouseButtonChanged(event, 0);//GLFW_RELEASE
- },
+ GLFW.onMouseButtonChanged(event, 1);//GLFW_PRESS
+ },
+
+ onMouseButtonUp: function(event){
+ GLFW.buttons &= ~(1 << event['button']);
+ GLFW.onMouseButtonChanged(event, 0);//GLFW_RELEASE
+ },
+
+ onMouseWheel: function(event){
+ if(event.detail > 0)
+ GLFW.wheelPos++;
+ if(event.detail < 0)
+ GLFW.wheelPos--;
+
+ if(GLFW.mouseWheelFunc && event.target == Module["canvas"]){
+ Runtime.dynCall('vi', GLFW.mouseWheelFunc, [GLFW.wheelPos]);
+ event.preventDefault();
+ }
+ },
// TODO add fullscreen API ala:
// http://johndyer.name/native-fullscreen-javascript-api-plus-jquery-plugin/
onFullScreenEventChange: function(event){
-/*
var width;
var height;
if (document["fullScreen"] || document["mozFullScreen"] || document["webkitIsFullScreen"]) {
@@ -274,13 +211,10 @@ var LibraryGLFW = {
document.removeEventListener('webkitfullscreenchange', GLFW.onFullScreenEventChange, true);
}
Browser.setCanvasSize(width, height);
- // Can't call _glfwReshapeWindow as that requests cancelling fullscreen.
- if (GLFW.resizeFunc) {
- // console.log("GLFW.resizeFunc (from FS): " + width + ", " + height);
+
+ if (GLFW.resizeFunc){
Runtime.dynCall('vii', GLFW.resizeFunc, [width, height]);
}
- _glfwPostRedisplay();
-*/
},
requestFullScreen: function() {
@@ -315,6 +249,8 @@ var LibraryGLFW = {
window.addEventListener("mousemove", GLFW.onMousemove, true);
window.addEventListener("mousedown", GLFW.onMouseButtonDown, true);
window.addEventListener("mouseup", GLFW.onMouseButtonUp, true);
+ window.addEventListener('DOMMouseScroll', GLFW.onMouseWheel, true);
+ window.addEventListener('mousewheel', GLFW.onMouseWheel, true);
__ATEXIT__.push({ func: function() {
window.removeEventListener("keydown", GLFW.onKeydown, true);
@@ -322,6 +258,8 @@ var LibraryGLFW = {
window.removeEventListener("mousemove", GLFW.onMousemove, true);
window.removeEventListener("mousedown", GLFW.onMouseButtonDown, true);
window.removeEventListener("mouseup", GLFW.onMouseButtonUp, true);
+ window.removeEventListener('DOMMouseScroll', GLFW.onMouseWheel, true);
+ window.removeEventListener('mousewheel', GLFW.onMouseWheel, true);
Module["canvas"].width = Module["canvas"].height = 1;
} });
@@ -333,29 +271,31 @@ var LibraryGLFW = {
GLFW.params[0x00030005] = false; //GLFW_KEY_REPEAT
GLFW.params[0x00030006] = true; //GLFW_AUTO_POLL_EVENTS
GLFW.params[0x00020001] = true; //GLFW_OPENED
- GLFW.params[0x00020002] = true; //GLFW_ACTIVE
- GLFW.params[0x00020003] = false; //GLFW_ICONIFIED
- GLFW.params[0x00020004] = true; //GLFW_ACCELERATED
- GLFW.params[0x00020005] = 0; //GLFW_RED_BITS
- GLFW.params[0x00020006] = 0; //GLFW_GREEN_BITS
- GLFW.params[0x00020007] = 0; //GLFW_BLUE_BITS
- GLFW.params[0x00020008] = 0; //GLFW_ALPHA_BITS
- GLFW.params[0x00020009] = 0; //GLFW_DEPTH_BITS
- GLFW.params[0x0002000A] = 0; //GLFW_STENCIL_BITS
- GLFW.params[0x0002000B] = 0; //GLFW_REFRESH_RATE
- GLFW.params[0x0002000C] = 0; //GLFW_ACCUM_RED_BITS
- GLFW.params[0x0002000D] = 0; //GLFW_ACCUM_GREEN_BITS
- GLFW.params[0x0002000E] = 0; //GLFW_ACCUM_BLUE_BITS
- GLFW.params[0x0002000F] = 0; //GLFW_ACCUM_ALPHA_BITS
- GLFW.params[0x00020010] = 0; //GLFW_AUX_BUFFERS
- GLFW.params[0x00020011] = 0; //GLFW_STEREO
- GLFW.params[0x00020012] = 0; //GLFW_WINDOW_NO_RESIZE
- GLFW.params[0x00020013] = 0; //GLFW_FSAA_SAMPLES
- GLFW.params[0x00020014] = 0; //GLFW_OPENGL_VERSION_MAJOR
- GLFW.params[0x00020015] = 0; //GLFW_OPENGL_VERSION_MINOR
- GLFW.params[0x00020016] = 0; //GLFW_OPENGL_FORWARD_COMPAT
- GLFW.params[0x00020017] = 0; //GLFW_OPENGL_DEBUG_CONTEXT
- GLFW.params[0x00020018] = 0; //GLFW_OPENGL_PROFILE
+ GLFW.params[0x00020002] = true; //GLFW_ACTIVE
+ GLFW.params[0x00020003] = false; //GLFW_ICONIFIED
+ GLFW.params[0x00020004] = true; //GLFW_ACCELERATED
+ GLFW.params[0x00020005] = 0; //GLFW_RED_BITS
+ GLFW.params[0x00020006] = 0; //GLFW_GREEN_BITS
+ GLFW.params[0x00020007] = 0; //GLFW_BLUE_BITS
+ GLFW.params[0x00020008] = 0; //GLFW_ALPHA_BITS
+ GLFW.params[0x00020009] = 0; //GLFW_DEPTH_BITS
+ GLFW.params[0x0002000A] = 0; //GLFW_STENCIL_BITS
+ GLFW.params[0x0002000B] = 0; //GLFW_REFRESH_RATE
+ GLFW.params[0x0002000C] = 0; //GLFW_ACCUM_RED_BITS
+ GLFW.params[0x0002000D] = 0; //GLFW_ACCUM_GREEN_BITS
+ GLFW.params[0x0002000E] = 0; //GLFW_ACCUM_BLUE_BITS
+ GLFW.params[0x0002000F] = 0; //GLFW_ACCUM_ALPHA_BITS
+ GLFW.params[0x00020010] = 0; //GLFW_AUX_BUFFERS
+ GLFW.params[0x00020011] = 0; //GLFW_STEREO
+ GLFW.params[0x00020012] = 0; //GLFW_WINDOW_NO_RESIZE
+ GLFW.params[0x00020013] = 0; //GLFW_FSAA_SAMPLES
+ GLFW.params[0x00020014] = 0; //GLFW_OPENGL_VERSION_MAJOR
+ GLFW.params[0x00020015] = 0; //GLFW_OPENGL_VERSION_MINOR
+ GLFW.params[0x00020016] = 0; //GLFW_OPENGL_FORWARD_COMPAT
+ GLFW.params[0x00020017] = 0; //GLFW_OPENGL_DEBUG_CONTEXT
+ GLFW.params[0x00020018] = 0; //GLFW_OPENGL_PROFILE
+
+ GLFW.keys = new Array();
return 1; //GL_TRUE
},
@@ -389,6 +329,7 @@ var LibraryGLFW = {
GLFW.params[0x00030003] = true; //GLFW_STICKY_MOUSE_BUTTONS
}
else if(mode == 0x00010002){//GLFW_FULLSCREEN
+ GLFW.requestFullScreen();
GLFW.params[0x00030003] = false; //GLFW_STICKY_MOUSE_BUTTONS
}
else{
@@ -428,9 +369,11 @@ var LibraryGLFW = {
}
},
- glfwSetWindowPos : function( x, y ) { throw "glfwSetWindowPos is not implemented yet."; },
- glfwIconifyWindow : function() { throw "glfwIconifyWindow is not implemented yet."; },
- glfwRestoreWindow : function() { throw "glfwRestoreWindow is not implemented yet."; },
+ glfwSetWindowPos : function( x, y ) {},
+
+ glfwIconifyWindow : function() {},
+
+ glfwRestoreWindow : function() {},
glfwSwapBuffers : function() {},
@@ -461,12 +404,11 @@ var LibraryGLFW = {
glfwWaitEvents : function() { throw "glfwWaitEvents is not implemented yet."; },
glfwGetKey : function( key ) {
- //TODO, actually something
- return 0;//GLFW_RELEASE
+ return GLFW.keys[key];
},
glfwGetMouseButton : function( button ) {
- return GLUT.buttons & button;
+ return GLFW.buttons & button;
},
glfwGetMousePos : function( xpos, ypos ) {
@@ -475,8 +417,14 @@ var LibraryGLFW = {
},
glfwSetMousePos : function( xpos, ypos ) { throw "glfwSetMousePos is not implemented yet."; },
- glfwGetMouseWheel : function() { throw "glfwGetMouseWheel is not implemented yet."; },
- glfwSetMouseWheel : function( pos ) { throw "glfwSetMouseWheel is not implemented yet."; },
+
+ glfwGetMouseWheel : function() {
+ return GLFW.wheelPos;
+ },
+
+ glfwSetMouseWheel : function( pos ) {
+ GLFW.wheelPos = pos;
+ },
glfwSetKeyCallback : function( cbfun ) {
GLFW.keyFunc = cbfun;
@@ -515,9 +463,16 @@ var LibraryGLFW = {
glfwSleep : function( time ) { throw "glfwSleep is not implemented yet."; },
/* Extension support */
- glfwExtensionSupported : function( extension ) { throw "glfwExtensionSupported is not implemented yet."; },
- glfwGetProcAddress : function( procname ) { throw "glfwGetProcAddress is not implemented yet."; },
- glfwGetGLVersion : function( major, minor, rev ) { throw "glfwGetGLVersion is not implemented yet."; },
+ glfwExtensionSupported : function( extension ) { return 1; /*throw "glfwExtensionSupported is not implemented yet.";*/ },
+ glfwGetProcAddress : function( procname ) { return null; /*throw "glfwGetProcAddress is not implemented yet.";*/ },
+
+ glfwGetGLVersion : function( major, minor, rev ) {
+ //TODO: Find something better here.
+ Module.printErr("Fake GL version");
+ setValue(major, 4, 'i32');
+ setValue(minor, 2, 'i32');
+ setValue(rev, 0, 'i32');
+ },
/* Threading support */
glfwCreateThread : function( fun, arg ) { throw "glfwCreateThread is not implemented yet."; },
@@ -533,7 +488,11 @@ var LibraryGLFW = {
glfwWaitCond : function( cond, mutex, timeout ) { throw "glfwWaitCond is not implemented yet."; },
glfwSignalCond : function( cond ) { throw "glfwSignalCond is not implemented yet."; },
glfwBroadcastCond : function( cond ) { throw "glfwBroadcastCond is not implemented yet."; },
- glfwGetNumberOfProcessors : function() { throw "glfwGetNumberOfProcessors is not implemented yet."; },
+
+ glfwGetNumberOfProcessors : function() {
+ //Threads are disabled anyway…
+ return 1;
+ },
/* Enable/disable functions */
glfwEnable : function( token ) {
diff --git a/tests/glfw/Makefile b/tests/glfw/Makefile
index 85b9067c..9bf06d80 100644
--- a/tests/glfw/Makefile
+++ b/tests/glfw/Makefile
@@ -11,7 +11,7 @@ SO_LFLAGS = $(SOLIB)
EXT = html
BINARIES = triangle listmodes mthello pong3d mtbench particles splitview \
- mipmaps gears boing heightmap
+ mipmaps gears boing heightmap glfwsample
## wave
all: $(BINARIES)
@@ -51,6 +51,9 @@ wave: wave.c
heightmap: heightmap.c
$(CC) $(CFLAGS) heightmap.c $(LFLAGS) -o $@.$(EXT)
+
+glfwsample: glfwsample.c
+ $(CC) $(CFLAGS) glfwsample.c $(LFLAGS) -o $@.$(EXT)
clean:
rm -f $(BINARIES)
diff --git a/tests/glfw/glfwsample.c b/tests/glfw/glfwsample.c
new file mode 100644
index 00000000..38b37cea
--- /dev/null
+++ b/tests/glfw/glfwsample.c
@@ -0,0 +1,375 @@
+#include <stdlib.h>
+#include <GL/glfw.h>
+#include <stdio.h>
+
+#ifdef EMSCRIPTEN
+#include <emscripten/emscripten.h>
+#endif
+
+void Init(void);
+void Shut_Down(int return_code);
+int Iteration(void);
+void Draw_Square(float red, float green, float blue);
+void Draw(void);
+void OnKeyPressed( int key, int action );
+void OnCharPressed( int character, int action );
+char* GetKeyName(int key);
+char* GetParamName(int param);
+int OnClose();
+void OnResize( int width, int height );
+void OnRefresh();
+void OnMouseClick( int button, int action );
+void OnMouseMove( int x, int y );
+void OnMouseWheel( int pos );
+void PullInfo();
+void Iteration_void();
+
+int params[] = {GLFW_OPENED, GLFW_ACTIVE, GLFW_ICONIFIED, GLFW_ACCELERATED, GLFW_RED_BITS, GLFW_GREEN_BITS, GLFW_BLUE_BITS, GLFW_ALPHA_BITS, GLFW_DEPTH_BITS, GLFW_STENCIL_BITS, GLFW_REFRESH_RATE, GLFW_ACCUM_RED_BITS, GLFW_ACCUM_GREEN_BITS, GLFW_ACCUM_BLUE_BITS, GLFW_ACCUM_ALPHA_BITS, GLFW_AUX_BUFFERS, GLFW_STEREO, GLFW_WINDOW_NO_RESIZE, GLFW_FSAA_SAMPLES, GLFW_OPENGL_VERSION_MAJOR, GLFW_OPENGL_VERSION_MINOR, GLFW_OPENGL_FORWARD_COMPAT, GLFW_OPENGL_DEBUG_CONTEXT, GLFW_OPENGL_PROFILE};
+unsigned int nb_params = sizeof(params) / sizeof(int);
+
+int features[] = {GLFW_MOUSE_CURSOR, GLFW_STICKY_KEYS, GLFW_STICKY_MOUSE_BUTTONS, GLFW_SYSTEM_KEYS, GLFW_KEY_REPEAT, GLFW_AUTO_POLL_EVENTS};
+unsigned int nb_features = sizeof(features) / sizeof(int);
+
+float rotate_y = 0,
+ rotate_z = 0;
+const float rotations_per_tick = .2;
+// the time of the previous frame
+double old_time;
+
+int main(void)
+{
+ Init();
+ old_time = glfwGetTime();
+#ifdef EMSCRIPTEN
+ emscripten_set_main_loop (Iteration_void, 0, 1);
+#else
+ while(Iteration());
+#endif
+ Shut_Down(0);
+}
+
+void Init()
+{
+ const int window_width = 800,
+ window_height = 600;
+
+ if (glfwInit() != GL_TRUE)
+ Shut_Down(1);
+ // 800 x 600, 16 bit color, no depth, alpha or stencil buffers, windowed
+ if (glfwOpenWindow(window_width, window_height, 5, 6, 5,
+ 0, 0, 0, GLFW_WINDOW) != GL_TRUE)
+ Shut_Down(1);
+ glfwSetWindowTitle("The GLFW Window");
+
+ glfwSetKeyCallback( OnKeyPressed );
+ glfwSetCharCallback( OnCharPressed );
+ glfwSetWindowCloseCallback(OnClose);
+ glfwSetWindowSizeCallback(OnResize);
+ glfwSetWindowRefreshCallback(OnRefresh);
+ glfwSetMouseWheelCallback(OnMouseWheel);
+ glfwSetMousePosCallback(OnMouseMove);
+ glfwSetMouseButtonCallback(OnMouseClick);
+
+ // set the projection matrix to a normal frustum with a max depth of 50
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ float aspect_ratio = ((float)window_height) / window_width;
+ glFrustum(.5, -.5, -.5 * aspect_ratio, .5 * aspect_ratio, 1, 50);
+ glMatrixMode(GL_MODELVIEW);
+
+ PullInfo();
+}
+
+void Shut_Down(int return_code)
+{
+ glfwTerminate();
+ exit(return_code);
+}
+
+int Iteration()
+{
+ // calculate time elapsed, and the amount by which stuff rotates
+ double current_time = glfwGetTime(),
+ delta_rotate = (current_time - old_time) * rotations_per_tick * 360;
+ old_time = current_time;
+ // escape to quit, arrow keys to rotate view
+ if (glfwGetKey(GLFW_KEY_ESC) == GLFW_PRESS) return 0;
+ if (glfwGetKey(GLFW_KEY_LEFT) == GLFW_PRESS)
+ rotate_y += delta_rotate;
+ if (glfwGetKey(GLFW_KEY_RIGHT) == GLFW_PRESS)
+ rotate_y -= delta_rotate;
+ // z axis always rotates
+ rotate_z += delta_rotate;
+
+ // clear the buffer
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ // draw the figure
+ Draw();
+ // swap back and front buffers
+ glfwSwapBuffers();
+ return 1;
+}
+
+void Iteration_void(){
+ Iteration();
+}
+
+void Draw_Square(float red, float green, float blue)
+{
+#ifndef EMSCRIPTEN
+ // Draws a square with a gradient color at coordinates 0, 10
+ glBegin(GL_QUADS);
+ {
+ glColor3f(red, green, blue);
+ glVertex2i(1, 11);
+ glColor3f(red * .8, green * .8, blue * .8);
+ glVertex2i(-1, 11);
+ glColor3f(red * .5, green * .5, blue * .5);
+ glVertex2i(-1, 9);
+ glColor3f(red * .8, green * .8, blue * .8);
+ glVertex2i(1, 9);
+ }
+ glEnd();
+#endif
+}
+
+void Draw(void)
+{
+ // reset view matrix
+ glLoadIdentity();
+ // move view back a bit
+ glTranslatef(0, 0, -30);
+ // apply the current rotation
+ glRotatef(rotate_y, 0, 1, 0);
+ glRotatef(rotate_z, 0, 0, 1);
+ // by repeatedly rotating the view matrix during drawing, the
+ // squares end up in a circle
+ int i = 0, squares = 15;
+ float red = 0, blue = 1;
+ for (; i < squares; ++i){
+ glRotatef(360.0/squares, 0, 0, 1);
+ // colors change for each square
+ red += 1.0/12;
+ blue -= 1.0/12;
+ Draw_Square(red, .6, blue);
+ }
+}
+
+void OnCharPressed( int character, int action ){
+ if(action == GLFW_PRESS)
+ printf("'%c' is pressed\n", character);
+ if(action == GLFW_RELEASE)
+ printf("'%c' is released\n", character);
+}
+
+char* GetKeyName(int key){
+ switch(key){
+ case GLFW_KEY_UNKNOWN: return "unknown";
+ case GLFW_KEY_SPACE: return "space";
+ case GLFW_KEY_SPECIAL: return "special";
+ case GLFW_KEY_ESC: return "escape";
+ case GLFW_KEY_F1 : return "F1";
+ case GLFW_KEY_F2 : return "F2";
+ case GLFW_KEY_F3 : return "F3";
+ case GLFW_KEY_F4 : return "F4";
+ case GLFW_KEY_F5 : return "F5";
+ case GLFW_KEY_F6 : return "F6";
+ case GLFW_KEY_F7 : return "F7";
+ case GLFW_KEY_F8 : return "F8";
+ case GLFW_KEY_F9 : return "F9";
+ case GLFW_KEY_F10: return "F10";
+ case GLFW_KEY_F11: return "F11";
+ case GLFW_KEY_F12: return "F12";
+ case GLFW_KEY_F13: return "F13";
+ case GLFW_KEY_F14: return "F14";
+ case GLFW_KEY_F15: return "F15";
+ case GLFW_KEY_F16: return "F16";
+ case GLFW_KEY_F17: return "F17";
+ case GLFW_KEY_F18: return "F18";
+ case GLFW_KEY_F19: return "F19";
+ case GLFW_KEY_F20: return "F20";
+ case GLFW_KEY_F21: return "F21";
+ case GLFW_KEY_F22: return "F22";
+ case GLFW_KEY_F23: return "F23";
+ case GLFW_KEY_F24: return "F24";
+ case GLFW_KEY_F25: return "F25";
+ case GLFW_KEY_UP : return "up";
+ case GLFW_KEY_DOWN: return "down";
+ case GLFW_KEY_LEFT: return "left";
+ case GLFW_KEY_RIGHT: return "right";
+ case GLFW_KEY_LSHIFT: return "left shift";
+ case GLFW_KEY_RSHIFT: return "right shift";
+ case GLFW_KEY_LCTRL: return "left ctrl";
+ case GLFW_KEY_RCTRL: return "right ctrl";
+ case GLFW_KEY_LALT: return "left alt";
+ case GLFW_KEY_RALT: return "right alt";
+ case GLFW_KEY_TAB: return "tab";
+ case GLFW_KEY_ENTER: return "enter";
+ case GLFW_KEY_BACKSPACE: return "backspace";
+ case GLFW_KEY_INSERT: return "insertr";
+ case GLFW_KEY_DEL: return "del";
+ case GLFW_KEY_PAGEUP: return "page up";
+ case GLFW_KEY_PAGEDOWN: return "page down";
+ case GLFW_KEY_HOME: return "home";
+ case GLFW_KEY_END: return "end";
+ case GLFW_KEY_KP_0: return "0";
+ case GLFW_KEY_KP_1: return "1";
+ case GLFW_KEY_KP_2: return "2";
+ case GLFW_KEY_KP_3: return "3";
+ case GLFW_KEY_KP_4: return "4";
+ case GLFW_KEY_KP_5: return "5";
+ case GLFW_KEY_KP_6: return "6";
+ case GLFW_KEY_KP_7: return "7";
+ case GLFW_KEY_KP_8: return "8";
+ case GLFW_KEY_KP_9: return "9";
+ case GLFW_KEY_KP_DIVIDE: return "/";
+ case GLFW_KEY_KP_MULTIPLY: return "*";
+ case GLFW_KEY_KP_SUBTRACT: return "-";
+ case GLFW_KEY_KP_ADD: return "+";
+ case GLFW_KEY_KP_DECIMAL: return ".";
+ case GLFW_KEY_KP_EQUAL: return "=";
+ case GLFW_KEY_KP_ENTER: return "enter";
+ case GLFW_KEY_KP_NUM_LOCK: return "num lock";
+ case GLFW_KEY_CAPS_LOCK: return "caps lock";
+ case GLFW_KEY_SCROLL_LOCK: return "scroll lock";
+ case GLFW_KEY_PAUSE: return "pause";
+ case GLFW_KEY_LSUPER: return "left super";
+ case GLFW_KEY_RSUPER: return "right super";
+ case GLFW_KEY_MENU: return "menu";
+ }
+ char* chr = malloc(2*sizeof(char));
+ chr[0] = key;
+ chr[1] = '\0';
+ return chr;
+}
+
+char* GetParamName(int param){
+ switch(param){
+ case GLFW_WINDOW : return "GLFW_WINDOW";
+ case GLFW_FULLSCREEN : return "GLFW_FULLSCREEN";
+ case GLFW_OPENED : return "GLFW_OPENED";
+ case GLFW_ACTIVE : return "GLFW_ACTIVE";
+ case GLFW_ICONIFIED : return "GLFW_ICONIFIED";
+ case GLFW_ACCELERATED : return "GLFW_ACCELERATED";
+ case GLFW_RED_BITS : return "GLFW_RED_BITS";
+ case GLFW_GREEN_BITS : return "GLFW_GREEN_BITS";
+ case GLFW_BLUE_BITS : return "GLFW_BLUE_BITS";
+ case GLFW_ALPHA_BITS : return "GLFW_ALPHA_BITS";
+ case GLFW_DEPTH_BITS : return "GLFW_DEPTH_BITS";
+ case GLFW_STENCIL_BITS : return "GLFW_STENCIL_BITS";
+ case GLFW_REFRESH_RATE : return "GLFW_REFRESH_RATE";
+ case GLFW_ACCUM_RED_BITS : return "GLFW_ACCUM_RED_BITS";
+ case GLFW_ACCUM_GREEN_BITS : return "GLFW_ACCUM_GREEN_BITS";
+ case GLFW_ACCUM_BLUE_BITS : return "GLFW_BLUE_BITS";
+ case GLFW_ACCUM_ALPHA_BITS : return "GLFW_ALPHA_BITS";
+ case GLFW_AUX_BUFFERS : return "GLFW_AUX_BUFFERS";
+ case GLFW_STEREO : return "GLFW_STEREO";
+ case GLFW_WINDOW_NO_RESIZE : return "GLFW_WINDOW_NO_RESIZE";
+ case GLFW_FSAA_SAMPLES : return "GLFW_FSAA_SAMPLES";
+ case GLFW_OPENGL_VERSION_MAJOR : return "GLFW_OPENGL_VERSION_MAJOR";
+ case GLFW_OPENGL_VERSION_MINOR : return "GLFW_OPENGL_VERSION_MINOR";
+ case GLFW_OPENGL_FORWARD_COMPAT : return "GLFW_OPENGL_FORWARD_COMPAT";
+ case GLFW_OPENGL_DEBUG_CONTEXT : return "GLFW_OPENGL_DEBUG_CONTEXT";
+ case GLFW_OPENGL_PROFILE : return "GLFW_OPENGL_PROFILE";
+ case GLFW_OPENGL_CORE_PROFILE : return "GLFW_OPENGL_CORE_PROFILE | GLFW_PRESENT";
+ case GLFW_OPENGL_COMPAT_PROFILE : return "GLFW_OPENGL_COMPAT_PROFILE | GLFW_AXES";
+ case GLFW_MOUSE_CURSOR : return "GLFW_MOUSE_CURSOR";
+ case GLFW_STICKY_KEYS : return "GLFW_STICKY_KEYS";
+ case GLFW_STICKY_MOUSE_BUTTONS : return "GLFW_STICKY_MOUSE_BUTTONS";
+ case GLFW_SYSTEM_KEYS : return "GLFW_SYSTEM_KEYS";
+ case GLFW_KEY_REPEAT : return "GLFW_KEY_REPEAT";
+ case GLFW_AUTO_POLL_EVENTS : return "GLFW_AUTO_POLL_EVENTS";
+ case GLFW_WAIT : return "GLFW_WAIT";
+ case GLFW_NOWAIT : return "GLFW_NOWAIT";
+ case GLFW_BUTTONS : return "GLFW_BUTTONS";
+ case GLFW_NO_RESCALE_BIT : return "GLFW_NO_RESCALE_BIT";
+ case GLFW_ORIGIN_UL_BIT : return "GLFW_ORIGIN_UL_BIT";
+ case GLFW_BUILD_MIPMAPS_BIT : return "GLFW_BUILD_MIPMAPS_BIT";
+ case GLFW_ALPHA_MAP_BIT : return "GLFW_ALPHA_MAP_BIT";
+ default : return "Invalid param";
+ }
+}
+void OnKeyPressed( int key, int action ){
+ const char* key_name = GetKeyName(key);
+ if(key_name == 0)
+ return;
+ if(action == GLFW_PRESS)
+ printf("%s (%i) is pressed\n", key_name, key);
+ if(action == GLFW_RELEASE)
+ printf("%s (%i) is released\n", key_name, key);
+ if(action == GLFW_RELEASE && key == GLFW_KEY_ENTER)
+ PullInfo();
+}
+
+int OnClose(){
+ printf("Closed\n");
+ return 0;
+}
+
+void OnRefresh(){
+ printf("Refresh\n");
+}
+
+void OnResize( int width, int height ){
+ printf("Resizing to %i %i\n", width, height);
+}
+
+void OnMouseClick( int button, int action ){
+ if(action == GLFW_PRESS)
+ printf("Mouse button %i has been pressed\n", button);
+ if(action == GLFW_RELEASE)
+ printf("Mouse button %i has been released\n", button);
+}
+
+void OnMouseMove( int x, int y ){
+ printf("Mouse has been moved to %i %i\n", x, y);
+}
+
+void OnMouseWheel( int pos ){
+ printf("Mouse wheel has been moved to %i\n", pos);
+}
+
+void PullInfo(){
+ printf("================================================================================\n");
+ int major, minor, rev;
+ glfwGetVersion(&major, &minor, &rev);
+ printf("GLFW version is %i.%i.%i\n", major, minor, rev);
+
+ int width, height;
+ glfwGetWindowSize(&width, &height);
+ printf("Window size is %i %i\n", width, height);
+
+ int status = glfwGetKey(GLFW_KEY_LCTRL);
+ if(status == GLFW_PRESS)
+ printf("Left control is pressed\n");
+ else
+ printf("Left control is released\n");
+
+ status = glfwGetMouseButton(GLFW_MOUSE_BUTTON_1);
+ if(status == GLFW_PRESS)
+ printf("Mouse button 1 is pressed\n");
+ else
+ printf("Mouse button 1 is released\n");
+
+ int x, y;
+ glfwGetMousePos(&x, &y);
+ printf("Mouse position is %i %i\n", x, y);
+
+ int wheel = glfwGetMouseWheel();
+ printf("Mouse wheel pos is %i\n", wheel);
+
+ double time = glfwGetTime();
+ printf("Time is %f\n", time);
+
+ glfwGetGLVersion(&major, &minor, &rev);
+ printf("GL version is %i.%i.%i\n", major, minor, rev);
+
+ int proc = glfwGetNumberOfProcessors();
+ printf("%i processors are available\n", proc);
+
+ unsigned int i;
+ for(i = 0; i<nb_params; i++)
+ printf(" - %-27s : %i\n", GetParamName(params[i]), glfwGetWindowParam(params[i]));
+
+ printf("================================================================================\n");
+}