diff options
-rw-r--r-- | src/library_sdl.js | 48 | ||||
-rw-r--r-- | system/include/SDL/SDL_events.h | 8 | ||||
-rw-r--r-- | tests/sdl_key.c | 93 | ||||
-rw-r--r-- | tests/test_browser.py | 49 |
4 files changed, 123 insertions, 75 deletions
diff --git a/src/library_sdl.js b/src/library_sdl.js index 7145a7ba..0cd1d27d 100644 --- a/src/library_sdl.js +++ b/src/library_sdl.js @@ -84,6 +84,9 @@ var LibrarySDL = { TOUCH_DEFAULT_ID: 0, // Our default deviceID for touch events (we get nothing from the browser) + eventHandler: null, + eventHandlerContext: null, + keyCodes: { // DOM code ==> SDL code. See https://developer.mozilla.org/en/Document_Object_Model_%28DOM%29/KeyboardEvent and SDL_keycode.h // For keys that don't have unicode value, we map DOM codes with the corresponding scan codes + 1024 (using "| 1 << 10") 16: 225 | 1<<10, // shift @@ -699,6 +702,9 @@ var LibrarySDL = { Module.printErr('SDL event queue full, dropping events'); SDL.events = SDL.events.slice(0, 10000); } + // If we have a handler installed, this will push the events to the app + // instead of the app polling for them. + SDL.flushEventsToHandler(); return; }, @@ -750,6 +756,30 @@ var LibrarySDL = { } }, + flushEventsToHandler: function() { + if (!SDL.eventHandler) return; + + // All SDLEvents take the same amount of memory + var sdlEventPtr = allocate({{{ C_STRUCTS.SDL_KeyboardEvent.__size__ }}}, "i8", ALLOC_STACK); + + while (SDL.pollEvent(sdlEventPtr)) { + Runtime.dynCall('iii', SDL.eventHandler, [SDL.eventHandlerContext, sdlEventPtr]); + } + }, + + pollEvent: function(ptr) { + if (SDL.initFlags & 0x200 && SDL.joystickEventState) { + // If SDL_INIT_JOYSTICK was supplied AND the joystick system is configured + // to automatically query for events, query for joystick events. + SDL.queryJoysticks(); + } + if (SDL.events.length === 0) return 0; + if (ptr) { + SDL.makeCEvent(SDL.events.shift(), ptr); + } + return 1; + }, + makeCEvent: function(event, ptr) { if (typeof event === 'number') { // This is a pointer to a native C event that was SDL_PushEvent'ed @@ -1709,16 +1739,7 @@ var LibrarySDL = { }, SDL_PollEvent: function(ptr) { - if (SDL.initFlags & 0x200 && SDL.joystickEventState) { - // If SDL_INIT_JOYSTICK was supplied AND the joystick system is configured - // to automatically query for events, query for joystick events. - SDL.queryJoysticks(); - } - if (SDL.events.length === 0) return 0; - if (ptr) { - SDL.makeCEvent(SDL.events.shift(), ptr); - } - return 1; + return SDL.pollEvent(ptr); }, SDL_PushEvent: function(ptr) { @@ -1758,6 +1779,13 @@ var LibrarySDL = { SDL.handleEvent(event); }); }, + + // An Emscripten-specific extension to SDL: Some browser APIs require that they are called from within an event handler function. + // Allow recording a callback that will be called for each received event. + emscripten_SDL_SetEventHandler: function(handler, userdata) { + SDL.eventHandler = handler; + SDL.eventHandlerContext = userdata; + }, SDL_SetColors: function(surf, colors, firstColor, nColors) { var surfData = SDL.surfaces[surf]; diff --git a/system/include/SDL/SDL_events.h b/system/include/SDL/SDL_events.h index 183ea4b2..66f5c82f 100644 --- a/system/include/SDL/SDL_events.h +++ b/system/include/SDL/SDL_events.h @@ -615,6 +615,14 @@ extern DECLSPEC void SDLCALL SDL_DelEventWatch(SDL_EventFilter filter, extern DECLSPEC void SDLCALL SDL_FilterEvents(SDL_EventFilter filter, void *userdata); +/** + * An Emscripten-specific extension to SDL: Some browser APIs require that they are called from within an event handler function. + * Allow recording a callback that will be called for each received event. This is used in place of SDL_PollEvent. + * Your application will be called whenever there are events available. + */ +extern DECLSPEC void SDLCALL emscripten_SDL_SetEventHandler(SDL_EventFilter handler, + void *userdata); + /*@{*/ #define SDL_QUERY -1 #define SDL_IGNORE 0 diff --git a/tests/sdl_key.c b/tests/sdl_key.c index 7a304fc1..9c78694b 100644 --- a/tests/sdl_key.c +++ b/tests/sdl_key.c @@ -5,55 +5,68 @@ int result = 1; +int SDLCALL EventHandler(void *userdata, SDL_Event *event) { + switch(event->type) { + case SDL_KEYDOWN: + break; + case SDL_KEYUP: + // don't handle the modifier key events + if (event->key.keysym.sym == SDLK_LCTRL || + event->key.keysym.sym == SDLK_LSHIFT || + event->key.keysym.sym == SDLK_LALT) { + return 0; + } + if ((event->key.keysym.mod & KMOD_LCTRL) || (event->key.keysym.mod & KMOD_RCTRL)) { + result *= 2; + } + if ((event->key.keysym.mod & KMOD_LSHIFT) || (event->key.keysym.mod & KMOD_RSHIFT)) { + result *= 3; + } + if ((event->key.keysym.mod & KMOD_LALT) || (event->key.keysym.mod & KMOD_RALT)) { + result *= 5; + } + switch (event->key.keysym.sym) { + case SDLK_RIGHT: printf("right\n"); result *= 7; break; + case SDLK_LEFT: printf("left\n"); result *= 11; break; + case SDLK_DOWN: printf("down\n"); result *= 13; break; + case SDLK_UP: printf("up\n"); result *= 17; break; + case SDLK_a: printf("a\n"); result *= 19; break; + default: { + if (event->key.keysym.scancode == SDL_SCANCODE_B) { + printf("b scancode\n"); result *= 23; break; + } + printf("unknown key: sym %d scancode %d\n", event->key.keysym.sym, event->key.keysym.scancode); + REPORT_RESULT(); + emscripten_run_script("throw 'done'"); // comment this out to leave event handling active. Use the following to log DOM keys: + // addEventListener('keyup', function(event) { console.log(event->keyCode) }, true) + } + } + break; + default: /* Report an unhandled event */ + printf("I don't know what this event is (type=%d)!\n", event->type); + } + return 0; +} + void one() { +#ifndef TEST_EMSCRIPTEN_SDL_SETEVENTHANDLER SDL_Event event; while (SDL_PollEvent(&event)) { - switch(event.type) { - case SDL_KEYDOWN: - break; - case SDL_KEYUP: - // don't handle the modifier key events - if (event.key.keysym.sym == SDLK_LCTRL || - event.key.keysym.sym == SDLK_LSHIFT || - event.key.keysym.sym == SDLK_LALT) { - return; - } - if ((event.key.keysym.mod & KMOD_LCTRL) || (event.key.keysym.mod & KMOD_RCTRL)) { - result *= 2; - } - if ((event.key.keysym.mod & KMOD_LSHIFT) || (event.key.keysym.mod & KMOD_RSHIFT)) { - result *= 3; - } - if ((event.key.keysym.mod & KMOD_LALT) || (event.key.keysym.mod & KMOD_RALT)) { - result *= 5; - } - switch (event.key.keysym.sym) { - case SDLK_RIGHT: printf("right\n"); result *= 7; break; - case SDLK_LEFT: printf("left\n"); result *= 11; break; - case SDLK_DOWN: printf("down\n"); result *= 13; break; - case SDLK_UP: printf("up\n"); result *= 17; break; - case SDLK_a: printf("a\n"); result *= 19; break; - default: { - if (event.key.keysym.scancode == SDL_SCANCODE_B) { - printf("b scancode\n"); result *= 23; break; - } - printf("unknown key: sym %d scancode %d\n", event.key.keysym.sym, event.key.keysym.scancode); - REPORT_RESULT(); - emscripten_run_script("throw 'done'"); // comment this out to leave event handling active. Use the following to log DOM keys: - // addEventListener('keyup', function(event) { console.log(event.keyCode) }, true) - } - } - break; - default: /* Report an unhandled event */ - printf("I don't know what this event is!\n"); - } + EventHandler(0, &event); } +#endif } int main(int argc, char **argv) { SDL_Init(SDL_INIT_VIDEO); SDL_Surface *screen = SDL_SetVideoMode(600, 450, 32, SDL_HWSURFACE); +#ifdef TEST_EMSCRIPTEN_SDL_SETEVENTHANDLER + emscripten_SDL_SetEventHandler(EventHandler, 0); +#else + if (argc == 1337) one(); // keep it alive +#endif + emscripten_run_script("keydown(1250);keydown(38);keyup(38);keyup(1250);"); // alt, up emscripten_run_script("keydown(1248);keydown(1249);keydown(40);keyup(40);keyup(1249);keyup(1248);"); // ctrl, shift, down emscripten_run_script("keydown(37);keyup(37);"); // left @@ -62,8 +75,6 @@ int main(int argc, char **argv) { emscripten_run_script("keydown(66);keyup(66);"); // b emscripten_run_script("keydown(100);keyup(100);"); // trigger the end - if (argc == 1337) one(); // keep it alive - return 0; } diff --git a/tests/test_browser.py b/tests/test_browser.py index 0771cb1b..42a1c0a0 100644 --- a/tests/test_browser.py +++ b/tests/test_browser.py @@ -748,35 +748,36 @@ window.close = function() { self.btest('sdl_canvas_alpha.c', reference='sdl_canvas_alpha.png', reference_slack=9) def test_sdl_key(self): - open(os.path.join(self.get_dir(), 'pre.js'), 'w').write(''' - Module.postRun = function() { - function doOne() { - Module._one(); + for defines in [[], ['-DTEST_EMSCRIPTEN_SDL_SETEVENTHANDLER']]: + open(os.path.join(self.get_dir(), 'pre.js'), 'w').write(''' + Module.postRun = function() { + function doOne() { + Module._one(); + setTimeout(doOne, 1000/60); + } setTimeout(doOne, 1000/60); } - setTimeout(doOne, 1000/60); - } - function keydown(c) { - var event = document.createEvent("KeyboardEvent"); - event.initKeyEvent("keydown", true, true, window, - 0, 0, 0, 0, - c, c); - document.dispatchEvent(event); - } + function keydown(c) { + var event = document.createEvent("KeyboardEvent"); + event.initKeyEvent("keydown", true, true, window, + 0, 0, 0, 0, + c, c); + document.dispatchEvent(event); + } - function keyup(c) { - var event = document.createEvent("KeyboardEvent"); - event.initKeyEvent("keyup", true, true, window, - 0, 0, 0, 0, - c, c); - document.dispatchEvent(event); - } - ''') - open(os.path.join(self.get_dir(), 'sdl_key.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl_key.c')).read())) + function keyup(c) { + var event = document.createEvent("KeyboardEvent"); + event.initKeyEvent("keyup", true, true, window, + 0, 0, 0, 0, + c, c); + document.dispatchEvent(event); + } + ''') + open(os.path.join(self.get_dir(), 'sdl_key.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl_key.c')).read())) - Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'sdl_key.c'), '-o', 'page.html', '--pre-js', 'pre.js', '-s', '''EXPORTED_FUNCTIONS=['_main', '_one']''', '-s', 'NO_EXIT_RUNTIME=1']).communicate() - self.run_browser('page.html', '', '/report_result?223092870') + Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'sdl_key.c'), '-o', 'page.html'] + defines + ['--pre-js', 'pre.js', '-s', '''EXPORTED_FUNCTIONS=['_main', '_one']''', '-s', 'NO_EXIT_RUNTIME=1']).communicate() + self.run_browser('page.html', '', '/report_result?223092870') def test_sdl_key_proxy(self): open(os.path.join(self.get_dir(), 'pre.js'), 'w').write(''' |