diff options
Diffstat (limited to 'src/library_html5.js')
-rw-r--r-- | src/library_html5.js | 79 |
1 files changed, 63 insertions, 16 deletions
diff --git a/src/library_html5.js b/src/library_html5.js index 63a4dff7..d9376c2a 100644 --- a/src/library_html5.js +++ b/src/library_html5.js @@ -13,6 +13,15 @@ var LibraryJSEvents = { visibilityChangeEvent: 0, touchEvent: 0, + // When we transition from fullscreen to windowed mode, we remember here the element that was just in fullscreen mode + // so that we can report information about that element in the event message. + previousFullscreenElement: null, + + // Remember the current mouse coordinates in case we need to emulate movementXY generation for browsers that don't support it. + // Some browsers (e.g. Safari 6.0.5) only give movementXY when Pointerlock is active. + previousScreenX: null, + previousScreenY: null, + // When the C runtime exits via exit(), we unregister all event handlers added by this library to be nice and clean. // Track in this field whether we have yet registered that __ATEXIT__ handler. removeEventListenersRegistered: false, @@ -114,8 +123,11 @@ var LibraryJSEvents = { // Stores objects representing each currently registered JS event handler. eventHandlers: [], + isInternetExplorer: function() { return navigator.userAgent.indexOf('MSIE') !== -1 || navigator.appVersion.indexOf('Trident/') > 0; }, + _removeHandler: function(i) { - JSEvents.eventHandlers[i].target.removeEventListener(JSEvents.eventHandlers[i].eventTypeString, JSEvents.eventHandlers[i].handlerFunc, true); + var h = JSEvents.eventHandlers[i]; + h.target.removeEventListener(h.eventTypeString, h.eventListenerFunc, h.useCapture); JSEvents.eventHandlers.splice(i, 1); }, @@ -135,6 +147,7 @@ var LibraryJSEvents = { } if (eventHandler.callbackfunc) { + eventHandler.eventListenerFunc = jsEventHandler; eventHandler.target.addEventListener(eventHandler.eventTypeString, jsEventHandler, eventHandler.useCapture); JSEvents.eventHandlers.push(eventHandler); JSEvents.registerRemoveEventListeners(); @@ -173,11 +186,9 @@ var LibraryJSEvents = { } }; - var isInternetExplorer = (navigator.userAgent.indexOf('MSIE') !== -1 || navigator.appVersion.indexOf('Trident/') > 0); - var eventHandler = { target: JSEvents.findEventTarget(target), - allowsDeferredCalls: isInternetExplorer ? false : true, // MSIE doesn't allow fullscreen and pointerlock requests from key handlers, others do. + allowsDeferredCalls: JSEvents.isInternetExplorer() ? false : true, // MSIE doesn't allow fullscreen and pointerlock requests from key handlers, others do. eventTypeString: eventTypeString, callbackfunc: callbackfunc, handlerFunc: handlerFunc, @@ -199,10 +210,12 @@ var LibraryJSEvents = { {{{ makeSetValue('eventStruct', C_STRUCTS.EmscriptenMouseEvent.metaKey, 'e.metaKey', 'i32') }}}; {{{ makeSetValue('eventStruct', C_STRUCTS.EmscriptenMouseEvent.button, 'e.button', 'i16') }}}; {{{ makeSetValue('eventStruct', C_STRUCTS.EmscriptenMouseEvent.buttons, 'e.buttons', 'i16') }}}; - {{{ makeSetValue('eventStruct', C_STRUCTS.EmscriptenMouseEvent.movementX, 'e.movementX || e.mozMovementX || e.webkitMovementX', 'i32') }}}; - {{{ makeSetValue('eventStruct', C_STRUCTS.EmscriptenMouseEvent.movementY, 'e.movementY || e.mozMovementY || e.webkitMovementY', 'i32') }}}; + {{{ makeSetValue('eventStruct', C_STRUCTS.EmscriptenMouseEvent.movementX, 'e["movementX"] || e["mozMovementX"] || e["webkitMovementX"] || (e.screenX-JSEvents.previousScreenX)', 'i32') }}}; + {{{ makeSetValue('eventStruct', C_STRUCTS.EmscriptenMouseEvent.movementY, 'e["movementY"] || e["mozMovementY"] || e["webkitMovementY"] || (e.screenY-JSEvents.previousScreenY)', 'i32') }}}; {{{ makeSetValue('eventStruct', C_STRUCTS.EmscriptenMouseEvent.canvasX, 'e.clientX - rect.left', 'i32') }}}; {{{ makeSetValue('eventStruct', C_STRUCTS.EmscriptenMouseEvent.canvasY, 'e.clientY - rect.top', 'i32') }}}; + JSEvents.previousScreenX = e.screenX; + JSEvents.previousScreenY = e.screenY; }, registerMouseEventCallback: function(target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString) { @@ -226,6 +239,8 @@ var LibraryJSEvents = { handlerFunc: handlerFunc, useCapture: useCapture }; + // In IE, mousedown events don't either allow deferred calls to be run! + if (JSEvents.isInternetExplorer() && eventTypeString == 'mousedown') eventHandler.allowsDeferredCalls = false; JSEvents.registerOrRemoveHandler(eventHandler); }, @@ -233,13 +248,27 @@ var LibraryJSEvents = { if (!JSEvents.wheelEvent) { JSEvents.wheelEvent = _malloc( {{{ C_STRUCTS.EmscriptenWheelEvent.__size__ }}} ); } - var handlerFunc = function(event) { + // The DOM Level 3 events spec event 'wheel' + var wheelHandlerFunc = function(event) { var e = event || window.event; JSEvents.fillMouseEventData(JSEvents.wheelEvent, e); - {{{ makeSetValue('JSEvents.wheelEvent', C_STRUCTS.EmscriptenWheelEvent.deltaX, 'e.deltaX', 'double') }}}; - {{{ makeSetValue('JSEvents.wheelEvent', C_STRUCTS.EmscriptenWheelEvent.deltaY, 'e.deltaY', 'double') }}}; - {{{ makeSetValue('JSEvents.wheelEvent', C_STRUCTS.EmscriptenWheelEvent.deltaZ, 'e.deltaZ', 'double') }}}; - {{{ makeSetValue('JSEvents.wheelEvent', C_STRUCTS.EmscriptenWheelEvent.deltaMode, 'e.deltaMode', 'i32') }}}; + {{{ makeSetValue('JSEvents.wheelEvent', C_STRUCTS.EmscriptenWheelEvent.deltaX, 'e["deltaX"]', 'double') }}}; + {{{ makeSetValue('JSEvents.wheelEvent', C_STRUCTS.EmscriptenWheelEvent.deltaY, 'e["deltaY"]', 'double') }}}; + {{{ makeSetValue('JSEvents.wheelEvent', C_STRUCTS.EmscriptenWheelEvent.deltaZ, 'e["deltaZ"]', 'double') }}}; + {{{ makeSetValue('JSEvents.wheelEvent', C_STRUCTS.EmscriptenWheelEvent.deltaMode, 'e["deltaMode"]', 'i32') }}}; + var shouldCancel = Runtime.dynCall('iiii', callbackfunc, [eventTypeId, JSEvents.wheelEvent, userData]); + if (shouldCancel) { + e.preventDefault(); + } + }; + // The 'mousewheel' event as implemented in Safari 6.0.5 + var mouseWheelHandlerFunc = function(event) { + var e = event || window.event; + JSEvents.fillMouseEventData(JSEvents.wheelEvent, e); + {{{ makeSetValue('JSEvents.wheelEvent', C_STRUCTS.EmscriptenWheelEvent.deltaX, 'e["wheelDeltaX"]', 'double') }}}; + {{{ makeSetValue('JSEvents.wheelEvent', C_STRUCTS.EmscriptenWheelEvent.deltaY, '-e["wheelDeltaY"] /* Invert to unify direction with the DOM Level 3 wheel event. */', 'double') }}}; + {{{ makeSetValue('JSEvents.wheelEvent', C_STRUCTS.EmscriptenWheelEvent.deltaZ, '0 /* Not available */', 'double') }}}; + {{{ makeSetValue('JSEvents.wheelEvent', C_STRUCTS.EmscriptenWheelEvent.deltaMode, '0 /* DOM_DELTA_PIXEL */', 'i32') }}}; var shouldCancel = Runtime.dynCall('iiii', callbackfunc, [eventTypeId, JSEvents.wheelEvent, userData]); if (shouldCancel) { e.preventDefault(); @@ -251,7 +280,7 @@ var LibraryJSEvents = { allowsDeferredCalls: true, eventTypeString: eventTypeString, callbackfunc: callbackfunc, - handlerFunc: handlerFunc, + handlerFunc: (eventTypeString == 'wheel') ? wheelHandlerFunc : mouseWheelHandlerFunc, useCapture: useCapture }; JSEvents.registerOrRemoveHandler(eventHandler); @@ -484,10 +513,20 @@ var LibraryJSEvents = { var isFullscreen = !!fullscreenElement; {{{ makeSetValue('eventStruct', C_STRUCTS.EmscriptenFullscreenChangeEvent.isFullscreen, 'isFullscreen', 'i32') }}}; {{{ makeSetValue('eventStruct', C_STRUCTS.EmscriptenFullscreenChangeEvent.fullscreenEnabled, 'JSEvents.fullscreenEnabled()', 'i32') }}}; - var nodeName = JSEvents.getNodeNameForTarget(fullscreenElement); - var id = (fullscreenElement && fullscreenElement.id) ? fullscreenElement.id : ''; + // If transitioning to fullscreen, report info about the element that is now fullscreen. + // If transitioning to windowed mode, report info about the element that just was fullscreen. + var reportedElement = isFullscreen ? fullscreenElement : JSEvents.previousFullscreenElement; + var nodeName = JSEvents.getNodeNameForTarget(reportedElement); + var id = (reportedElement && reportedElement.id) ? reportedElement.id : ''; writeStringToMemory(nodeName, eventStruct + {{{ C_STRUCTS.EmscriptenFullscreenChangeEvent.nodeName }}} ); writeStringToMemory(id, eventStruct + {{{ C_STRUCTS.EmscriptenFullscreenChangeEvent.id }}} ); + {{{ makeSetValue('eventStruct', C_STRUCTS.EmscriptenFullscreenChangeEvent.elementWidth, 'reportedElement ? reportedElement.clientWidth : 0', 'i32') }}}; + {{{ makeSetValue('eventStruct', C_STRUCTS.EmscriptenFullscreenChangeEvent.elementHeight, 'reportedElement ? reportedElement.clientHeight : 0', 'i32') }}}; + {{{ makeSetValue('eventStruct', C_STRUCTS.EmscriptenFullscreenChangeEvent.screenWidth, 'screen.width', 'i32') }}}; + {{{ makeSetValue('eventStruct', C_STRUCTS.EmscriptenFullscreenChangeEvent.screenHeight, 'screen.height', 'i32') }}}; + if (isFullscreen) { + JSEvents.previousFullscreenElement = fullscreenElement; + } }, registerFullscreenChangeEventCallback: function(target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString) { @@ -904,8 +943,16 @@ var LibraryJSEvents = { }, emscripten_set_wheel_callback: function(target, userData, useCapture, callbackfunc) { - JSEvents.registerWheelEventCallback(target, userData, useCapture, callbackfunc, {{{ cDefine('EMSCRIPTEN_EVENT_WHEEL') }}}, "wheel"); - return {{{ cDefine('EMSCRIPTEN_RESULT_SUCCESS') }}}; + target = JSEvents.findEventTarget(target); + if (typeof target.onwheel !== 'undefined') { + JSEvents.registerWheelEventCallback(target, userData, useCapture, callbackfunc, {{{ cDefine('EMSCRIPTEN_EVENT_WHEEL') }}}, "wheel"); + return {{{ cDefine('EMSCRIPTEN_RESULT_SUCCESS') }}}; + } else if (typeof target.onmousewheel !== 'undefined') { + JSEvents.registerWheelEventCallback(target, userData, useCapture, callbackfunc, {{{ cDefine('EMSCRIPTEN_EVENT_WHEEL') }}}, "mousewheel"); + return {{{ cDefine('EMSCRIPTEN_RESULT_SUCCESS') }}}; + } else { + return {{{ cDefine('EMSCRIPTEN_RESULT_NOT_SUPPORTED') }}}; + } }, emscripten_set_resize_callback: function(target, userData, useCapture, callbackfunc) { |