From 793eb176a0c777d91941cb17386de0f5da981bac Mon Sep 17 00:00:00 2001 From: Jukka Jylänki Date: Wed, 26 Feb 2014 12:05:13 +0200 Subject: Add new fields to EmscriptenFullscreenChangeEvent structure that report the new pixel sizes of the fullscreen element, as well as the whole screen size. These can be used to read and adjust the rendering canvas size appropriately when transitioning between fullscreen modes. Thanks to Joel Croteau for the suggestion at https://groups.google.com/forum/#!topic/emscripten-discuss/qaTrOXWv1Oc . Bump version to 1.12.3 to update the cache after change to struct_info.json. --- src/library_html5.js | 18 ++++++- src/struct_info.json | 6 ++- system/include/emscripten/html5.h | 7 +++ tests/test_browser.py | 3 ++ tests/test_html5.c | 4 +- tests/test_html5_fullscreen.c | 107 ++++++++++++++++++++++++++++++++++++++ tools/shared.py | 2 +- 7 files changed, 141 insertions(+), 6 deletions(-) create mode 100644 tests/test_html5_fullscreen.c diff --git a/src/library_html5.js b/src/library_html5.js index 63a4dff7..b17a0d4d 100644 --- a/src/library_html5.js +++ b/src/library_html5.js @@ -13,6 +13,10 @@ 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, + // 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, @@ -484,10 +488,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) { diff --git a/src/struct_info.json b/src/struct_info.json index 2aeffc9c..2a2b4c64 100644 --- a/src/struct_info.json +++ b/src/struct_info.json @@ -1207,7 +1207,11 @@ "isFullscreen", "fullscreenEnabled", "nodeName", - "id" + "id", + "elementWidth", + "elementHeight", + "screenWidth", + "screenHeight" ], "EmscriptenPointerlockChangeEvent": [ "isActive", diff --git a/system/include/emscripten/html5.h b/system/include/emscripten/html5.h index 06c647bf..6109d87f 100644 --- a/system/include/emscripten/html5.h +++ b/system/include/emscripten/html5.h @@ -388,9 +388,16 @@ typedef struct EmscriptenFullscreenChangeEvent { // Specifies if the current page has the ability to display elements fullscreen. EM_BOOL fullscreenEnabled; // The nodeName of the target HTML Element that is in full screen mode. See https://developer.mozilla.org/en-US/docs/Web/API/Node.nodeName + // If isFullscreen is false, then nodeName, id and elementWidth/Height specify information about the element that just exited fullscreen mode. EM_UTF8 nodeName[128]; // The HTML Element ID of the target HTML element that is in full screen mode. EM_UTF8 id[128]; + // The new pixel size of the element that changed fullscreen status. + int elementWidth; + int elementHeight; + // The size of the whole screen, in pixels. + int screenWidth; + int screenHeight; } EmscriptenFullscreenChangeEvent; /* diff --git a/tests/test_browser.py b/tests/test_browser.py index f2e17ea0..62d3f257 100644 --- a/tests/test_browser.py +++ b/tests/test_browser.py @@ -1846,6 +1846,9 @@ Module["preRun"].push(function () { def test_html5(self): self.btest(path_from_root('tests', 'test_html5.c'), expected='0') + def test_html5_fullscreen(self): + self.btest(path_from_root('tests', 'test_html5_fullscreen.c'), expected='0') + def test_codemods(self): for opt_level in [0, 2]: print 'opt level', opt_level diff --git a/tests/test_html5.c b/tests/test_html5.c index 77ddea98..fec46035 100644 --- a/tests/test_html5.c +++ b/tests/test_html5.c @@ -145,8 +145,8 @@ EM_BOOL orientationchange_callback(int eventType, const EmscriptenOrientationCha EM_BOOL fullscreenchange_callback(int eventType, const EmscriptenFullscreenChangeEvent *e, void *userData) { - printf("%s, isFullscreen: %d, fullscreenEnabled: %d, fs element nodeName: \"%s\", fs element id: \"%s\"\n", - emscripten_event_type_to_string(eventType), e->isFullscreen, e->fullscreenEnabled, e->nodeName, e->id); + printf("%s, isFullscreen: %d, fullscreenEnabled: %d, fs element nodeName: \"%s\", fs element id: \"%s\". New size: %dx%d pixels. Screen size: %dx%d pixels.\n", + emscripten_event_type_to_string(eventType), e->isFullscreen, e->fullscreenEnabled, e->nodeName, e->id, e->elementWidth, e->elementHeight, e->screenWidth, e->screenHeight); return 0; } diff --git a/tests/test_html5_fullscreen.c b/tests/test_html5_fullscreen.c new file mode 100644 index 00000000..9a284b09 --- /dev/null +++ b/tests/test_html5_fullscreen.c @@ -0,0 +1,107 @@ +#include +#include +#include +#include + +#ifdef REPORT_RESULT +void report_result(int result) +{ + if (result == 0) { + printf("Test successful!\n"); + } else { + printf("Test failed!\n"); + } + REPORT_RESULT(); +} +#endif + +static inline const char *emscripten_event_type_to_string(int eventType) { + const char *events[] = { "(invalid)", "(none)", "keypress", "keydown", "keyup", "click", "mousedown", "mouseup", "dblclick", "mousemove", "wheel", "resize", + "scroll", "blur", "focus", "focusin", "focusout", "deviceorientation", "devicemotion", "orientationchange", "fullscreenchange", "pointerlockchange", + "visibilitychange", "touchstart", "touchend", "touchmove", "touchcancel", "gamepadconnected", "gamepaddisconnected", "beforeunload", + "batterychargingchange", "batterylevelchange", "webglcontextlost", "webglcontextrestored", "(invalid)" }; + ++eventType; + if (eventType < 0) eventType = 0; + if (eventType >= sizeof(events)/sizeof(events[0])) eventType = sizeof(events)/sizeof(events[0])-1; + return events[eventType]; +} + +const char *emscripten_result_to_string(EMSCRIPTEN_RESULT result) { + if (result == EMSCRIPTEN_RESULT_SUCCESS) return "EMSCRIPTEN_RESULT_SUCCESS"; + if (result == EMSCRIPTEN_RESULT_DEFERRED) return "EMSCRIPTEN_RESULT_DEFERRED"; + if (result == EMSCRIPTEN_RESULT_NOT_SUPPORTED) return "EMSCRIPTEN_RESULT_NOT_SUPPORTED"; + if (result == EMSCRIPTEN_RESULT_FAILED_NOT_DEFERRED) return "EMSCRIPTEN_RESULT_FAILED_NOT_DEFERRED"; + if (result == EMSCRIPTEN_RESULT_INVALID_TARGET) return "EMSCRIPTEN_RESULT_INVALID_TARGET"; + if (result == EMSCRIPTEN_RESULT_UNKNOWN_TARGET) return "EMSCRIPTEN_RESULT_UNKNOWN_TARGET"; + if (result == EMSCRIPTEN_RESULT_INVALID_PARAM) return "EMSCRIPTEN_RESULT_INVALID_PARAM"; + if (result == EMSCRIPTEN_RESULT_FAILED) return "EMSCRIPTEN_RESULT_FAILED"; + if (result == EMSCRIPTEN_RESULT_NO_DATA) return "EMSCRIPTEN_RESULT_NO_DATA"; + return "Unknown EMSCRIPTEN_RESULT!"; +} + +#define TEST_RESULT(x) if (ret != EMSCRIPTEN_RESULT_SUCCESS) printf("%s returned %s.\n", #x, emscripten_result_to_string(ret)); + +// The event handler functions can return 1 to suppress the event and disable the default action. That calls event.preventDefault(); +// Returning 0 signals that the event was not consumed by the code, and will allow the event to pass on and bubble up normally. +EM_BOOL key_callback(int eventType, const EmscriptenKeyboardEvent *e, void *userData) +{ + if (eventType == EMSCRIPTEN_EVENT_KEYPRESS && (!strcmp(e->key, "f") || e->which == 102)) { + EmscriptenFullscreenChangeEvent fsce; + EMSCRIPTEN_RESULT ret = emscripten_get_fullscreen_status(&fsce); + TEST_RESULT(emscripten_get_fullscreen_status); + if (!fsce.isFullscreen) { + printf("Requesting fullscreen..\n"); + ret = emscripten_request_fullscreen(0, 1); + TEST_RESULT(emscripten_request_fullscreen); + } else { + printf("Exiting fullscreen..\n"); + ret = emscripten_exit_fullscreen(); + TEST_RESULT(emscripten_exit_fullscreen); + ret = emscripten_get_fullscreen_status(&fsce); + TEST_RESULT(emscripten_get_fullscreen_status); + if (fsce.isFullscreen) { + fprintf(stderr, "Fullscreen exit did not work!\n"); + } + } + } + + return 0; +} + +int callCount = 0; + +EM_BOOL fullscreenchange_callback(int eventType, const EmscriptenFullscreenChangeEvent *e, void *userData) +{ + printf("%s, isFullscreen: %d, fullscreenEnabled: %d, fs element nodeName: \"%s\", fs element id: \"%s\". New size: %dx%d pixels. Screen size: %dx%d pixels.\n", + emscripten_event_type_to_string(eventType), e->isFullscreen, e->fullscreenEnabled, e->nodeName, e->id, e->elementWidth, e->elementHeight, e->screenWidth, e->screenHeight); + + ++callCount; + if (callCount == 1) { // Transitioned to fullscreen. + if (!e->isFullscreen) { + report_result(1); + } + } else if (callCount == 2) { // Transitioned to windowed, we must be back to the default pixel size 300x150. + if (e->isFullscreen || e->elementWidth != 300 || e->elementHeight != 150) { + report_result(1); + } else { + report_result(0); + } + } + return 0; +} + +int main() +{ + EMSCRIPTEN_RESULT ret = emscripten_set_keypress_callback(0, 0, 1, key_callback); + TEST_RESULT(emscripten_set_keypress_callback); + + ret = emscripten_set_fullscreenchange_callback(0, 0, 1, fullscreenchange_callback); + TEST_RESULT(emscripten_set_fullscreenchange_callback); + + printf("To finish this test, press f to enter fullscreen mode, and then exit it.\n"); + + /* For the events to function, one must either call emscripten_set_main_loop or enable Module.noExitRuntime by some other means. + Otherwise the application will exit after leaving main(), and the atexit handlers will clean up all event hooks (by design). */ + EM_ASM(Module['noExitRuntime'] = true); + return 0; +} diff --git a/tools/shared.py b/tools/shared.py index b7a186fc..a413a932 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -361,7 +361,7 @@ def find_temp_directory(): # we re-check sanity when the settings are changed) # We also re-check sanity and clear the cache when the version changes -EMSCRIPTEN_VERSION = '1.12.2' +EMSCRIPTEN_VERSION = '1.12.3' def generate_sanity(): return EMSCRIPTEN_VERSION + '|' + get_llvm_target() + '|' + LLVM_ROOT + '|' + get_clang_version() -- cgit v1.2.3-18-g5258