ecere:gui:drivers:EmscriptenInterface: add early keyboard and mouse support.
authorRejean Loyer <redj@ecere.com>
Sun, 7 Dec 2014 00:18:18 +0000 (19:18 -0500)
committerRejean Loyer <redj@ecere.com>
Mon, 16 Mar 2015 05:31:59 +0000 (01:31 -0400)
ecere/src/gui/GuiApplication.ec
ecere/src/gui/drivers/EmscriptenInterface.ec

index a74e8d8..38f13a8 100644 (file)
@@ -1,11 +1,8 @@
 namespace gui;
 
-#ifdef __EMSCRIPTEN__
-#include <emscripten.h>
-#endif
-
-#ifdef __EMSCRIPTEN__
+#if defined(__EMSCRIPTEN__)
 #include <emscripten.h>
+#include <emscripten/html5.h>
 #endif
 
 #if (defined(__unix__) || defined(__APPLE__)) && !defined(__ANDROID__) && !defined(__EMSCRIPTEN__) && !defined(__pnacl__)
@@ -706,8 +703,8 @@ public:
             }
          }
 
-#ifdef __EMSCRIPTEN__
-      emscripten_set_main_loop(emscripten_main_loop_callback, 1/*60*/, 1);
+#if defined(__EMSCRIPTEN__)
+      emscripten_set_main_loop(em_main_loop_callback, 0/*1*//*60*/, 1);
 #endif
 
          if(desktop)
@@ -1531,8 +1528,9 @@ public:
    };
 };
 
-#ifdef __EMSCRIPTEN__
-private void emscripten_main_loop_callback()
+#if defined(__EMSCRIPTEN__)
+default:
+private void em_main_loop_callback()
 {
    guiApp.ProcessInput(false);
    guiApp.Cycle(false);
index 9df8751..d5d425a 100644 (file)
@@ -24,10 +24,714 @@ public import "ecere"
 //#include <GLES2/gl2.h>
 #include <GL/glfw.h>
 #include <emscripten/emscripten.h>
+#include <emscripten/html5.h>
 
 #undef property
 #undef uint
 
+static canvasX;
+static canvasY;
+
+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", "mouseenter", "mouseleave", "mouseover", "mouseout", "(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!";
+}
+
+default:
+
+/*
+public enum KeyCode : Key
+{
+   escape            = 0x01,
+   // Characters
+   k1                = 0x02,
+   bang              = 0x02,
+   k2                = 0x03,
+   commercial        = 0x03,
+   k3                = 0x04,
+   pound             = 0x04,
+   k4                = 0x05,
+   dollar            = 0x05,
+   k5                = 0x06,
+   percent           = 0x06,
+   k6                = 0x07,
+   circumflex        = 0x07,
+   k7                = 0x08,
+   ampersand         = 0x08,
+   k8                = 0x09,
+   star              = 0x09,
+   k9                = 0x0A,
+   leftParanthesis   = 0x0A,
+   k0                = 0x0B,
+   rightParanthesis  = 0x0A,
+   minus             = 0x0C,
+   underscore        = 0x0C,
+   equal             = 0x0D,
+   plus              = 0x0D,
+   backSpace         = 0x0E,
+   tab               = 0x0F,
+   q                 = 0x10,
+   w                 = 0x11,
+   e                 = 0x12,
+   r                 = 0x13,
+   t                 = 0x14,
+   y                 = 0x15,
+   u                 = 0x16,
+   i                 = 0x17,
+   o                 = 0x18,
+   p                 = 0x19,
+   leftBracket       = 0x1A,
+   rightBracket      = 0x1B,
+   enter             = 0x1C,
+   leftControl       = 0x1D,
+   a                 = 0x1E,
+   s                 = 0x1F,
+   d                 = 0x20,
+   f                 = 0x21,
+   g                 = 0x22,
+   h                 = 0x23,
+   j                 = 0x24,
+   k                 = 0x25,
+   l                 = 0x26,
+   semicolon         = 0x27,
+   colon             = 0x27,
+   quote             = 0x28,
+   doubleQuote       = 0x28,
+   tilde             = 0x29,
+   backQuote         = 0x29,
+   leftShift         = 0x2A,
+   backSlash         = 0x2B,
+   pipe              = 0x2B,
+   z                 = 0x2C,
+   x                 = 0x2D,
+   c                 = 0x2E,
+   v                 = 0x2F,
+   b                 = 0x30,
+   n                 = 0x31,
+   m                 = 0x32,
+   comma             = 0x33,
+   smallerThan       = 0x33,
+   period            = 0x34,
+   greaterThan       = 0x34,
+   slash             = 0x35,
+   questionMark      = 0x35,
+
+   rightShift        = 0x36,
+   keyPadStar        = 0x37,
+   leftAlt           = 0x38,
+   space             = 0x39,
+
+   capsLock          = 0x3A,
+
+   // Function keys 1-10
+   f1                = 0x3B,
+   f2                = 0x3C,
+   f3                = 0x3D,
+   f4                = 0x3E,
+   f5                = 0x3F,
+   f6                = 0x40,
+   f7                = 0x41,
+   f8                = 0x42,
+   f9                = 0x43,
+   f10               = 0x44,
+
+   // Num Pad
+   numLock           = 0x45,
+   scrollLock        = 0x46,
+   keyPadHome        = 0x47,
+   keyPad7           = 0x47,
+   keyPadUp          = 0x48,
+   keyPad8           = 0x48,
+   keyPadPageUp      = 0x49,
+   keyPad9           = 0x49,
+   keyPadMinus       = 0x4A,
+   keyPadLeft        = 0x4B,
+   keyPad4           = 0x4B,
+   keyPad5           = 0x4C,
+   keyPadRight       = 0x4D,
+   keyPad6           = 0x4D,
+   keyPadPlus        = 0x4E,
+   keyPadEnd         = 0x4F,
+   keyPad1           = 0x4F,
+   keyPadDown        = 0x50,
+   keyPad2           = 0x50,
+   keyPadPageDown    = 0x51,
+   keyPad3           = 0x51,
+   keyPadInsert      = 0x52,
+   keyPad0           = 0x52,
+   keyPadDelete      = 0x53,
+   // KeyPadLess        = 0x56,
+
+   // F11-F12
+   f11               = 0x57,
+   f12               = 0x58,
+
+   keyPadEnter       = 0x60,
+   rightControl      = 0x61,
+   keyPadSlash       = 0x62,
+   printScreen       = 0x63,
+   rightAlt          = 0x64,
+   pauseBreak        = 0x65,
+
+   // Function Pad
+   home              = 0x66,
+   up                = 0x67,
+   pageUp            = 0x68,
+   left              = 0x69,
+   right             = 0x6A,
+   end               = 0x6B,
+   down              = 0x6C,
+   pageDown          = 0x6D,
+   insert            = 0x6E,
+   del               = 0x6F,
+
+   // Pseudo keys
+   shift             = 0x100,
+   alt               = 0x101,
+   control           = 0x102,
+   wheelUp           = 0x103,
+   wheelDown         = 0x104,
+   hotKey            = 0x105,
+   defaultKey        = 0x106,
+   capsState         = 0x107,
+   numState          = 0x108,
+   scrollState       = 0x109,
+
+   // Remote Control Buttons
+   play              = 0x201,
+   record            = 0x202,
+   pause             = 0x203,
+   rewind            = 0x204,
+   fastForward       = 0x205,
+   previousTrack     = 0x206,
+   nextTrack         = 0x207,
+   stop              = 0x208,
+   eject             = 0x209,
+   volumeUp          = 0x20A,
+   volumeDown        = 0x20B,
+   mute              = 0x20C,
+   remoteHome        = 0x213,
+   back              = f1,
+   menu1             = f2,
+   menu2             = f3,
+   menu3             = f4,
+   menu4             = f5,
+   select            = enter
+};
+*/
+
+static KeyCode keys[256] =
+{
+   0,                //                            0x00
+   0,                //                            0x01
+   0,                //                            0x02
+   0,                // DOM_VK_CANCEL              0x03 (  3) Cancel key.
+   0,                //                            0x
+   0,                //                            0x
+   0,                // DOM_VK_HELP                0x06 (  6) Help key.
+   0,                //                            0x
+   backSpace,        // DOM_VK_BACK_SPACE          0x08 (  8) Backspace key.
+   tab,              // DOM_VK_TAB                 0x09 (  9) Tab key.
+   0,                //                            0x
+   0,                //                            0x
+   0,                // DOM_VK_CLEAR               0x0C ( 12) "5" key on Numpad when NumLock is unlocked. Or on Mac, clear key which is positioned at NumLock key.
+   enter,            // DOM_VK_RETURN              0x0D ( 13) Return/enter key on the main keyboard.
+   0,                // DOM_VK_ENTER               0x0E ( 14) Reserved, but not used. Obsolete since Gecko 30 (Dropped, see bug 969247.)
+   0,                //                            0x
+   shift,            // DOM_VK_SHIFT               0x10 ( 16) Shift key.
+   control,          // DOM_VK_CONTROL             0x11 ( 17) Control key.
+   alt,              // DOM_VK_ALT                 0x12 ( 18) Alt (Option on Mac) key.
+   pauseBreak,       // DOM_VK_PAUSE               0x13 ( 19) Pause key.
+   0,                // DOM_VK_CAPS_LOCK           0x14 ( 20) Caps lock.
+   0,                // DOM_VK_KANA                0x15 ( 21) Linux support for this keycode was added in Gecko 4.0. //0,                // DOM_VK_HANGUL  0x15 (21) Linux support for this keycode was added in Gecko 4.0.
+   0,                // DOM_VK_EISU                0x16 ( 22) "英数" key on Japanese Mac keyboard.
+   0,                // DOM_VK_JUNJA               0x17 ( 23) Linux support for this keycode was added in Gecko 4.0.
+   0,                // DOM_VK_FINAL               0x18 ( 24) Linux support for this keycode was added in Gecko 4.0.
+   0,                // DOM_VK_HANJA               0x19 ( 25) Linux support for this keycode was added in Gecko 4.0. //0,                // DOM_VK_KANJI   0x19 (25) Linux support for this keycode was added in Gecko 4.0.
+   0,                //                            0x
+   escape,           // DOM_VK_ESCAPE              0x1B ( 27) Escape key.
+   0,                // DOM_VK_CONVERT             0x1C ( 28) Linux support for this keycode was added in Gecko 4.0.
+   0,                // DOM_VK_NONCONVERT          0x1D ( 29) Linux support for this keycode was added in Gecko 4.0.
+   0,                // DOM_VK_ACCEPT              0x1E ( 30) Linux support for this keycode was added in Gecko 4.0.
+   0,                // DOM_VK_MODECHANGE          0x1F ( 31) Linux support for this keycode was added in Gecko 4.0.
+   0,                // DOM_VK_SPACE               0x20 ( 32) Space bar.
+   pageUp,           // DOM_VK_PAGE_UP             0x21 ( 33) Page Up key.
+   pageDown,         // DOM_VK_PAGE_DOWN           0x22 ( 34) Page Down key.
+   end,              // DOM_VK_END                 0x23 ( 35) End key.
+   home,             // DOM_VK_HOME                0x24 ( 36) Home key.
+   left,             // DOM_VK_LEFT                0x25 ( 37) Left arrow.
+   up,               // DOM_VK_UP                  0x26 ( 38) Up arrow.
+   right,            // DOM_VK_RIGHT               0x27 ( 39) Right arrow.
+   down,             // DOM_VK_DOWN                0x28 ( 40) Down arrow.
+   0,                // DOM_VK_SELECT              0x29 ( 41) Linux support for this keycode was added in Gecko 4.0.
+   0,                // DOM_VK_PRINT               0x2A ( 42) Linux support for this keycode was added in Gecko 4.0.
+   0,                // DOM_VK_EXECUTE             0x2B ( 43) Linux support for this keycode was added in Gecko 4.0.
+   printScreen,      // DOM_VK_PRINTSCREEN         0x2C ( 44) Print Screen key.
+   insert,           // DOM_VK_INSERT              0x2D ( 45) Ins(ert) key.
+   del,              // DOM_VK_DELETE              0x2E ( 46) Del(ete) key.
+   0,                //                            0x
+   k0,               // DOM_VK_0                   0x30 ( 48) "0" key in standard key location.
+   k1,               // DOM_VK_1                   0x31 ( 49) "1" key in standard key location.
+   k2,               // DOM_VK_2                   0x32 ( 50) "2" key in standard key location.
+   k3,               // DOM_VK_3                   0x33 ( 51) "3" key in standard key location.
+   k4,               // DOM_VK_4                   0x34 ( 52) "4" key in standard key location.
+   k5,               // DOM_VK_5                   0x35 ( 53) "5" key in standard key location.
+   k6,               // DOM_VK_6                   0x36 ( 54) "6" key in standard key location.
+   k7,               // DOM_VK_7                   0x37 ( 55) "7" key in standard key location.
+   k8,               // DOM_VK_8                   0x38 ( 56) "8" key in standard key location.
+   k9,               // DOM_VK_9                   0x39 ( 57) "9" key in standard key location.
+   colon,            // DOM_VK_COLON               0x3A ( 58) Colon (":") key.
+   semicolon,        // DOM_VK_SEMICOLON           0x3B ( 59) Semicolon (";") key.
+   smallerThan,      // DOM_VK_LESS_THAN           0x3C ( 60) Less-than ("<") key.
+   equal,            // DOM_VK_EQUALS              0x3D ( 61) Equals ("=") key.
+   greaterThan,      // DOM_VK_GREATER_THAN        0x3E ( 62) Greater-than (">") key.
+   questionMark,     // DOM_VK_QUESTION_MARK       0x3F ( 63) Question mark ("?") key.
+   0,                // DOM_VK_AT                  0x40 ( 64) Atmark ("@") key.
+   a,                // DOM_VK_A                   0x41 ( 65) "A" key.
+   b,                // DOM_VK_B                   0x42 ( 66) "B" key.
+   c,                // DOM_VK_C                   0x43 ( 67) "C" key.
+   d,                // DOM_VK_D                   0x44 ( 68) "D" key.
+   e,                // DOM_VK_E                   0x45 ( 69) "E" key.
+   f,                // DOM_VK_F                   0x46 ( 70) "F" key.
+   g,                // DOM_VK_G                   0x47 ( 71) "G" key.
+   h,                // DOM_VK_H                   0x48 ( 72) "H" key.
+   i,                // DOM_VK_I                   0x49 ( 73) "I" key.
+   j,                // DOM_VK_J                   0x4A ( 74) "J" key.
+   k,                // DOM_VK_K                   0x4B ( 75) "K" key.
+   l,                // DOM_VK_L                   0x4C ( 76) "L" key.
+   m,                // DOM_VK_M                   0x4D ( 77) "M" key.
+   n,                // DOM_VK_N                   0x4E ( 78) "N" key.
+   o,                // DOM_VK_O                   0x4F ( 79) "O" key.
+   p,                // DOM_VK_P                   0x50 ( 80) "P" key.
+   q,                // DOM_VK_Q                   0x51 ( 81) "Q" key.
+   r,                // DOM_VK_R                   0x52 ( 82) "R" key.
+   s,                // DOM_VK_S                   0x53 ( 83) "S" key.
+   t,                // DOM_VK_T                   0x54 ( 84) "T" key.
+   u,                // DOM_VK_U                   0x55 ( 85) "U" key.
+   v,                // DOM_VK_V                   0x56 ( 86) "V" key.
+   w,                // DOM_VK_W                   0x57 ( 87) "W" key.
+   x,                // DOM_VK_X                   0x58 ( 88) "X" key.
+   y,                // DOM_VK_Y                   0x59 ( 89) "Y" key.
+   z,                // DOM_VK_Z                   0x5A ( 90) "Z" key.
+   0,                // DOM_VK_WIN                 0x5B ( 91) Windows logo key on Windows. Or Super or Hyper key on Linux.
+   0,                //                            0x
+   0,                // DOM_VK_CONTEXT_MENU        0x5D ( 93) Opening context menu key.
+   0,                //                            0x
+   0,                // DOM_VK_SLEEP               0x5F ( 95) Linux support for this keycode was added in Gecko 4.0.
+   keyPad0,          // DOM_VK_NUMPAD0             0x60 ( 96) "0" on the numeric keypad.
+   keyPad1,          // DOM_VK_NUMPAD1             0x61 ( 97) "1" on the numeric keypad.
+   keyPad2,          // DOM_VK_NUMPAD2             0x62 ( 98) "2" on the numeric keypad.
+   keyPad3,          // DOM_VK_NUMPAD3             0x63 ( 99) "3" on the numeric keypad.
+   keyPad4,          // DOM_VK_NUMPAD4             0x64 (100) "4" on the numeric keypad.
+   keyPad5,          // DOM_VK_NUMPAD5             0x65 (101) "5" on the numeric keypad.
+   keyPad6,          // DOM_VK_NUMPAD6             0x66 (102) "6" on the numeric keypad.
+   keyPad7,          // DOM_VK_NUMPAD7             0x67 (103) "7" on the numeric keypad.
+   keyPad8,          // DOM_VK_NUMPAD8             0x68 (104) "8" on the numeric keypad.
+   keyPad9,          // DOM_VK_NUMPAD9             0x69 (105) "9" on the numeric keypad.
+   keyPadStar,       // DOM_VK_MULTIPLY            0x6A (106) "*" on the numeric keypad.
+   keyPadPlus,       // DOM_VK_ADD                 0x6B (107) "+" on the numeric keypad.
+   0,                // DOM_VK_SEPARATOR           0x6C (108)
+   keyPadMinus,      // DOM_VK_SUBTRACT            0x6D (109) "-" on the numeric keypad.
+   0,                // DOM_VK_DECIMAL             0x6E (110) Decimal point on the numeric keypad.
+   keyPadSlash,      // DOM_VK_DIVIDE              0x6F (111) "/" on the numeric keypad.
+   f1,               // DOM_VK_F1                  0x70 (112) F1 key.
+   f2,               // DOM_VK_F2                  0x71 (113) F2 key.
+   f3,               // DOM_VK_F3                  0x72 (114) F3 key.
+   f4,               // DOM_VK_F4                  0x73 (115) F4 key.
+   f5,               // DOM_VK_F5                  0x74 (116) F5 key.
+   f6,               // DOM_VK_F6                  0x75 (117) F6 key.
+   f7,               // DOM_VK_F7                  0x76 (118) F7 key.
+   f8,               // DOM_VK_F8                  0x77 (119) F8 key.
+   f9,               // DOM_VK_F9                  0x78 (120) F9 key.
+   f10,              // DOM_VK_F10                 0x79 (121) F10 key.
+   f11,              // DOM_VK_F11                 0x7A (122) F11 key.
+   f12,              // DOM_VK_F12                 0x7B (123) F12 key.
+   0,                // DOM_VK_F13                 0x7C (124) F13 key.
+   0,                // DOM_VK_F14                 0x7D (125) F14 key.
+   0,                // DOM_VK_F15                 0x7E (126) F15 key.
+   0,                // DOM_VK_F16                 0x7F (127) F16 key.
+   0,                // DOM_VK_F17                 0x80 (128) F17 key.
+   0,                // DOM_VK_F18                 0x81 (129) F18 key.
+   0,                // DOM_VK_F19                 0x82 (130) F19 key.
+   0,                // DOM_VK_F20                 0x83 (131) F20 key.
+   0,                // DOM_VK_F21                 0x84 (132) F21 key.
+   0,                // DOM_VK_F22                 0x85 (133) F22 key.
+   0,                // DOM_VK_F23                 0x86 (134) F23 key.
+   0,                // DOM_VK_F24                 0x87 (135) F24 key.
+   0,                //                            0x
+   0,                //                            0x
+   0,                //                            0x
+   0,                //                            0x
+   0,                //                            0x
+   0,                //                            0x
+   0,                //                            0x
+   0,                //                            0x
+   numLock,          // DOM_VK_NUM_LOCK            0x90 (144) Num Lock key.
+   scrollLock,       // DOM_VK_SCROLL_LOCK         0x91 (145) Scroll Lock key.
+   0,                // DOM_VK_WIN_OEM_FJ_JISHO    0x92 (146) An OEM specific key on Windows. This was used for "Dictionary" key on Fujitsu OASYS.
+   0,                // DOM_VK_WIN_OEM_FJ_MASSHOU  0x93 (147) An OEM specific key on Windows. This was used for "Unregister word" key on Fujitsu OASYS.
+   0,                // DOM_VK_WIN_OEM_FJ_TOUROKU  0x94 (148) An OEM specific key on Windows. This was used for "Register word" key on Fujitsu OASYS.
+   0,                // DOM_VK_WIN_OEM_FJ_LOYA     0x95 (149) An OEM specific key on Windows. This was used for "Left OYAYUBI" key on Fujitsu OASYS.
+   0,                // DOM_VK_WIN_OEM_FJ_ROYA     0x96 (150) An OEM specific key on Windows. This was used for "Right OYAYUBI" key on Fujitsu OASYS.
+   0,                //                            0x
+   0,                //                            0x
+   0,                //                            0x
+   0,                //                            0x
+   0,                //                            0x
+   0,                //                            0x
+   0,                //                            0x
+   0,                //                            0x
+   0,                //                            0x
+   circumflex,       // DOM_VK_CIRCUMFLEX          0xA0 (160) Circumflex ("^") key.
+   bang,             // DOM_VK_EXCLAMATION         0xA1 (161) Exclamation ("!") key.
+   doubleQuote,      // DOM_VK_DOUBLE_QUOTE        0xA3 (162) Double quote (""") key.
+   pound,            // DOM_VK_HASH                0xA3 (163) Hash ("#") key.
+   dollar,           // DOM_VK_DOLLAR              0xA4 (164) Dollar sign ("$") key.
+   percent,          // DOM_VK_PERCENT             0xA5 (165) Percent ("%") key.
+   ampersand,        // DOM_VK_AMPERSAND           0xA6 (166) Ampersand ("&") key.
+   underscore,       // DOM_VK_UNDERSCORE          0xA7 (167) Underscore ("_") key.
+   leftParanthesis,  // DOM_VK_OPEN_PAREN          0xA8 (168) Open parenthesis ("(") key.
+   rightParanthesis, // DOM_VK_CLOSE_PAREN         0xA9 (169) Close parenthesis (")") key.
+   star,             // DOM_VK_ASTERISK            0xAA (170) Asterisk ("*") key.
+   plus,             // DOM_VK_PLUS                0xAB (171) Plus ("+") key.
+   pipe,             // DOM_VK_PIPE                0xAC (172) Pipe ("|") key.
+   minus,            // DOM_VK_HYPHEN_MINUS        0xAD (173) Hyphen-US/docs/Minus ("-") key.
+   0,                // DOM_VK_OPEN_CURLY_BRACKET  0xAE (174) Open curly bracket ("{") key.
+   0,                // DOM_VK_CLOSE_CURLY_BRACKET 0xAF (175) Close curly bracket ("}") key.
+   tilde,            // DOM_VK_TILDE               0xB0 (176) Tilde ("~") key.
+   0,                //                            0x
+   0,                //                            0x
+   0,                //                            0x
+   0,                //                            0x
+   mute,             // DOM_VK_VOLUME_MUTE         0xB5 (181) Audio mute key.
+   volumeDown,       // DOM_VK_VOLUME_DOWN         0xB6 (182) Audio volume down key
+   volumeUp,         // DOM_VK_VOLUME_UP           0xB7 (183) Audio volume up key
+   0,                //                            0x
+   0,                //                            0x
+   0,                //                            0x
+   0,                //                            0x
+   comma,            // DOM_VK_COMMA               0xBC (188) Comma (",") key.
+   0,                //                            0x
+   period,           // DOM_VK_PERIOD              0xBE (190) Period (".") key.
+   slash,            // DOM_VK_SLASH               0xBF (191) Slash ("/") key.
+   backQuote,        // DOM_VK_BACK_QUOTE          0xC0 (192) Back tick ("`") key.
+   0,                //                            0x
+   0,                //                            0x
+   0,                //                            0x
+   0,                //                            0x
+   0,                //                            0x
+   0,                //                            0x
+   0,                //                            0x
+   0,                //                            0x
+   0,                //                            0x
+   0,                //                            0x
+   0,                //                            0x
+   0,                //                            0x
+   0,                //                            0x
+   0,                //                            0x
+   0,                //                            0x
+   0,                //                            0x
+   0,                //                            0x
+   0,                //                            0x
+   0,                //                            0x
+   0,                //                            0x
+   0,                //                            0x
+   0,                //                            0x
+   0,                //                            0x
+   0,                //                            0x
+   0,                //                            0x
+   0,                //                            0x
+   leftBracket,      // DOM_VK_OPEN_BRACKET        0xDB (219) Open square bracket ("[") key.
+   backSlash,        // DOM_VK_BACK_SLASH          0xDC (220) Back slash ("\") key.
+   rightBracket,     // DOM_VK_CLOSE_BRACKET       0xDD (221) Close square bracket ("]") key.
+   quote,            // DOM_VK_QUOTE               0xDE (222) Quote (''') key.
+   0,                //                            0x
+   0,                // DOM_VK_META                0xE0 (224) Meta key on Linux, Command key on Mac.
+   0,                // DOM_VK_ALTGR               0xE1 (225) AltGr key (Level 3 Shift key or Level 5 Shift key) on Linux.
+   0,                //                            0x
+   0,                // DOM_VK_WIN_ICO_HELP        0xE3 (227) An OEM specific key on Windows. This is (was?) used for Olivetti ICO keyboard.
+   0,                // DOM_VK_WIN_ICO_00          0xE4 (228) An OEM specific key on Windows. This is (was?) used for Olivetti ICO keyboard.
+   0,                //                            0x
+   0,                // DOM_VK_WIN_ICO_CLEAR       0xE6 (230) An OEM specific key on Windows. This is (was?) used for Olivetti ICO keyboard.
+   0,                //                            0x
+   0,                //                            0x
+   0,                // DOM_VK_WIN_OEM_RESET       0xE9 (233) An OEM specific key on Windows. This was used for Nokia/Ericsson's device.
+   0,                // DOM_VK_WIN_OEM_JUMP        0xEA (234) An OEM specific key on Windows. This was used for Nokia/Ericsson's device.
+   0,                // DOM_VK_WIN_OEM_PA1         0xEB (235) An OEM specific key on Windows. This was used for Nokia/Ericsson's device.
+   0,                // DOM_VK_WIN_OEM_PA2         0xEC (236) An OEM specific key on Windows. This was used for Nokia/Ericsson's device.
+   0,                // DOM_VK_WIN_OEM_PA3         0xED (237) An OEM specific key on Windows. This was used for Nokia/Ericsson's device.
+   0,                // DOM_VK_WIN_OEM_WSCTRL      0xEE (238) An OEM specific key on Windows. This was used for Nokia/Ericsson's device.
+   0,                // DOM_VK_WIN_OEM_CUSEL       0xEF (239) An OEM specific key on Windows. This was used for Nokia/Ericsson's device.
+   0,                // DOM_VK_WIN_OEM_ATTN        0xF0 (240) An OEM specific key on Windows. This was used for Nokia/Ericsson's device.
+   0,                // DOM_VK_WIN_OEM_FINISH      0xF1 (241) An OEM specific key on Windows. This was used for Nokia/Ericsson's device.
+   0,                // DOM_VK_WIN_OEM_COPY        0xF2 (242) An OEM specific key on Windows. This was used for Nokia/Ericsson's device.
+   0,                // DOM_VK_WIN_OEM_AUTO        0xF3 (243) An OEM specific key on Windows. This was used for Nokia/Ericsson's device.
+   0,                // DOM_VK_WIN_OEM_ENLW        0xF4 (244) An OEM specific key on Windows. This was used for Nokia/Ericsson's device.
+   0,                // DOM_VK_WIN_OEM_BACKTAB     0xF5 (245) An OEM specific key on Windows. This was used for Nokia/Ericsson's device.
+   0,                // DOM_VK_ATTN                0xF6 (246) Attn (Attention) key of IBM midrange computers, e.g., AS/400.
+   0,                // DOM_VK_CRSEL               0xF7 (247) CrSel (Cursor Selection) key of IBM 3270 keyboard layout.
+   0,                // DOM_VK_EXSEL               0xF8 (248) ExSel (Extend Selection) key of IBM 3270 keyboard layout.
+   0,                // DOM_VK_EREOF               0xF9 (249) Erase EOF key of IBM 3270 keyboard layout.
+   0,                // DOM_VK_PLAY                0xFA (250) Play key of IBM 3270 keyboard layout.
+   0,                // DOM_VK_ZOOM                0xFB (251) Zoom key.
+   0,                //                            0x
+   0,                // DOM_VK_PA1                 0xFD (253) PA1 key of IBM 3270 keyboard layout.
+   0,                // DOM_VK_WIN_OEM_CLEAR       0xFE (254) Clear key, but we're not sure the meaning difference from DOM_VK_CLEAR.
+   0
+};
+
+private EM_BOOL em_key_callback(int eventType, const EmscriptenKeyboardEvent *e, void *userData)
+{
+   uint method;
+   Key key = keys[e->keyCode ? e->keyCode : e->which];
+   unichar character = e->charCode ? e->charCode : e->which;
+   PrintLn(key, " | ", character);
+
+   printf("%s, key: \"%s\", code: \"%s\", location: %lu,%s%s%s%s repeat: %d, locale: \"%s\", char: \"%s\", charCode: %lu, keyCode: %lu, which: %lu\n",
+         emscripten_event_type_to_string(eventType), e->key, e->code, e->location,
+         e->ctrlKey ? " CTRL" : "", e->shiftKey ? " SHIFT" : "", e->altKey ? " ALT" : "", e->metaKey ? " META" : "",
+         e->repeat, e->locale, e->charValue, e->charCode, e->keyCode, e->which);
+
+   switch(eventType)
+   {
+      case EMSCRIPTEN_EVENT_KEYPRESS: method = __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit;  break;
+      case EMSCRIPTEN_EVENT_KEYDOWN:  method = __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown; break;
+      case EMSCRIPTEN_EVENT_KEYUP:    method = __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp;   break;
+      default:                        method = 0;
+   }
+
+   if(method)
+      /*result = */guiApp.desktop.KeyMessage(method, key, character);
+   return 0;
+}
+
+private EM_BOOL em_mouse_callback(int eventType, const EmscriptenMouseEvent *e, void *userData)
+{
+   uint method;
+   Modifiers mods = 0;
+   bool consequential = false;
+   bool activate = false;
+
+   canvasX = e->canvasX;
+   canvasY = e->canvasY;
+
+   printf("%s, screen: (%ld,%ld), client: (%ld,%ld),%s%s%s%s button: %hu, buttons: %hu, movement: (%ld,%ld), canvas: (%ld,%ld)\n",
+         emscripten_event_type_to_string(eventType), e->screenX, e->screenY, e->clientX, e->clientY,
+         e->ctrlKey ? " CTRL" : "", e->shiftKey ? " SHIFT" : "", e->altKey ? " ALT" : "", e->metaKey ? " META" : "",
+         e->button, e->buttons, e->movementX, e->movementY, e->canvasX, e->canvasY);
+
+   if(e->shiftKey) mods.shift = true;
+   if(e->ctrlKey) mods.ctrl = true;
+   if(e->altKey) mods.alt = true;
+   //if(e->metaKey) mods.meta = true;
+
+   // e->buttons
+   switch(eventType)
+   {
+      //case EMSCRIPTEN_EVENT_CLICK:      method = 0; break;
+      case EMSCRIPTEN_EVENT_MOUSEDOWN:
+         switch(e->button)
+         {
+            case 0: mods.left = true;   method = __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonDown;    break;
+            case 1: mods.middle = true; method = __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonDown;  break;
+            case 2: mods.right = true;  method = __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonDown;   break;
+            default:                    method = 0;
+         }
+         break;
+      case EMSCRIPTEN_EVENT_MOUSEUP:
+         switch(e->button)
+         {
+            case 0: mods.left = true;   method = __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonUp;      break;
+            case 1: mods.middle = true; method = __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonUp;    break;
+            case 2: mods.right = true;  method = __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonUp;     break;
+            default:                    method = 0;
+         }
+         break;
+      case EMSCRIPTEN_EVENT_DBLCLICK:
+         switch(e->button)
+         {
+            case 0: mods.left = true;   method = __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftDoubleClick;   break;
+            case 1: mods.middle = true; method = __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleDoubleClick; break;
+            case 2: mods.right = true;  method = __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightDoubleClick;  break;
+            default:                    method = 0;
+         }
+         break;
+      case EMSCRIPTEN_EVENT_MOUSEMOVE:  method = __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMouseMove;         break;
+      //case EMSCRIPTEN_EVENT_MOUSEENTER: method = 0; break;
+      //case EMSCRIPTEN_EVENT_MOUSELEAVE: method = 0; break;
+      case EMSCRIPTEN_EVENT_MOUSEOVER:  method = __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMouseMove;         break;
+      //case EMSCRIPTEN_EVENT_MOUSEOUT:   method = 0; break;
+      default:                          method = 0;
+   }
+
+   if(method)
+      // e->screenX, e->screenY, e->clientX, e->clientY, e->movementX, e->movementY
+      guiApp.desktop.MouseMessage(method, e->canvasX, e->canvasY, &mods, consequential, true);
+   return 0;
+}
+
+private EM_BOOL em_wheel_callback(int eventType, const EmscriptenWheelEvent *e, void *userData)
+{
+   printf("%s, screen: (%ld,%ld), client: (%ld,%ld),%s%s%s%s button: %hu, buttons: %hu, canvas: (%ld,%ld), delta:(%g,%g,%g), deltaMode:%lu\n",
+         emscripten_event_type_to_string(eventType), e->mouse.screenX, e->mouse.screenY, e->mouse.clientX, e->mouse.clientY,
+         e->mouse.ctrlKey ? " CTRL" : "", e->mouse.shiftKey ? " SHIFT" : "", e->mouse.altKey ? " ALT" : "", e->mouse.metaKey ? " META" : "",
+         e->mouse.button, e->mouse.buttons, e->mouse.canvasX, e->mouse.canvasY,
+         (float)e->deltaX, (float)e->deltaY, (float)e->deltaZ, e->deltaMode);
+   return 0;
+}
+
+private EM_BOOL em_uievent_callback(int eventType, const EmscriptenUiEvent *e, void *userData)
+{
+   printf("%s, detail: %ld, document.body.client size: (%d,%d), window.inner size: (%d,%d), scrollPos: (%d, %d)\n",
+         emscripten_event_type_to_string(eventType), e->detail, e->documentBodyClientWidth, e->documentBodyClientHeight,
+         e->windowInnerWidth, e->windowInnerHeight, e->scrollTop, e->scrollLeft);
+   return 0;
+}
+
+private EM_BOOL em_focusevent_callback(int eventType, const EmscriptenFocusEvent *e, void *userData)
+{
+   printf("%s, nodeName: \"%s\", id: \"%s\"\n", emscripten_event_type_to_string(eventType), e->nodeName, e->id[0] == '\0' ? "(empty string)" : e->id);
+   return 0;
+}
+
+private EM_BOOL em_deviceorientation_callback(int eventType, const EmscriptenDeviceOrientationEvent *e, void *userData)
+{
+   printf("%s, (%g, %g, %g)\n", emscripten_event_type_to_string(eventType), e->alpha, e->beta, e->gamma);
+   return 0;
+}
+
+private EM_BOOL em_devicemotion_callback(int eventType, const EmscriptenDeviceMotionEvent *e, void *userData)
+{
+   printf("%s, accel: (%g, %g, %g), accelInclGravity: (%g, %g, %g), rotationRate: (%g, %g, %g)\n",
+   emscripten_event_type_to_string(eventType),
+   e->accelerationX, e->accelerationY, e->accelerationZ,
+   e->accelerationIncludingGravityX, e->accelerationIncludingGravityY, e->accelerationIncludingGravityZ,
+   e->rotationRateAlpha, e->rotationRateBeta, e->rotationRateGamma);
+   return 0;
+}
+
+private EM_BOOL em_orientationchange_callback(int eventType, const EmscriptenOrientationChangeEvent *e, void *userData)
+{
+   printf("%s, orientationAngle: %d, orientationIndex: %d\n", emscripten_event_type_to_string(eventType), e->orientationAngle, e->orientationIndex);
+   return 0;
+}
+
+private EM_BOOL em_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);
+   return 0;
+}
+
+private EM_BOOL em_pointerlockchange_callback(int eventType, const EmscriptenPointerlockChangeEvent *e, void *userData)
+{
+   printf("%s, isActive: %d, pointerlock element nodeName: \"%s\", id: \"%s\"\n",
+   emscripten_event_type_to_string(eventType), e->isActive, e->nodeName, e->id);
+   return 0;
+}
+
+private EM_BOOL em_visibilitychange_callback(int eventType, const EmscriptenVisibilityChangeEvent *e, void *userData)
+{
+   printf("%s, hidden: %d, visibilityState: %d\n", emscripten_event_type_to_string(eventType), e->hidden, e->visibilityState);
+   return 0;
+}
+
+#if 0
+private EM_BOOL em_touch_callback(int eventType, const EmscriptenTouchEvent *e, void *userData)
+{
+   printf("%s, numTouches: %d %s%s%s%s\n",
+   emscripten_event_type_to_string(eventType), e->numTouches,
+   e->ctrlKey ? " CTRL" : "", e->shiftKey ? " SHIFT" : "", e->altKey ? " ALT" : "", e->metaKey ? " META" : "");
+   for(int i = 0; i < e->numTouches; ++i)
+   {
+   const EmscriptenTouchPoint *t = &e->touches[i];
+   printf("  %ld: screen: (%ld,%ld), client: (%ld,%ld), page: (%ld,%ld), isChanged: %d, onTarget: %d, canvas: (%ld, %ld)\n",
+   t->identifier, t->screenX, t->screenY, t->clientX, t->clientY, t->pageX, t->pageY, t->isChanged, t->onTarget, t->canvasX, t->canvasY);
+}
+
+return 0;
+}
+
+private EM_BOOL em_gamepad_callback(int eventType, const EmscriptenGamepadEvent *e, void *userData)
+{
+   printf("%s: timeStamp: %g, connected: %d, index: %ld, numAxes: %d, numButtons: %d, id: \"%s\", mapping: \"%s\"\n",
+   eventType != 0 ? emscripten_event_type_to_string(eventType) : "Gamepad state", e->timestamp, e->connected, e->index,
+   e->numAxes, e->numButtons, e->id, e->mapping);
+
+   if (e->connected)
+   {
+      for(int i = 0; i < e->numAxes; ++i)
+         printf("Axis %d: %g\n", i, e->axis[i]);
+      for(int i = 0; i < e->numButtons; ++i)
+         printf("Button %d: Digital: %d, Analog: %g\n", i, e->digitalButton[i], e->analogButton[i]);
+   }
+   return 0;
+}
+
+const char *beforeunload_callback(int eventType, const void *reserved, void *userData)
+{
+   #ifdef REPORT_RESULT
+   return ""; // For test harness, don't show a confirmation dialog to not block and keep the test runner automated.
+   #else
+   return "Do you really want to leave the page?";
+   #endif
+}
+
+private EM_BOOL em_battery_callback(int eventType, const EmscriptenBatteryEvent *e, void *userData)
+{
+   char t1[64];
+   formatTime(t1, (int)e->chargingTime);
+   char t2[64];
+   formatTime(t2, (int)e->dischargingTime);
+   printf("%s: chargingTime: %s, dischargingTime: %s, level: %g%%, charging: %d\n",
+   emscripten_event_type_to_string(eventType), t1, t2, e->level*100, e->charging);
+   return 0;
+}
+
+private EM_BOOL em_webglcontext_callback(int eventType, const void *reserved, void *userData)
+{
+   printf("%s.\n", emscripten_event_type_to_string(eventType));
+   return 0;
+}
+#endif
+
+default:
+extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit;
+extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp;
+extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown;
+extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit;
+extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMouseMove;
+extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftDoubleClick;
+extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonDown;
+extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonUp;
+extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleDoubleClick;
+extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonDown;
+extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonUp;
+extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightDoubleClick;
+extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonDown;
+extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonUp;
+private:
 
 class EmscriptenInterface : Interface
 {
@@ -39,7 +743,191 @@ class EmscriptenInterface : Interface
    bool ::Initialize()
    {
       sflnprintf("class(EmscriptenInterface) ::Initialize [STUB!]\n");
-      guiApp.desktop.ExternalPosition(0,0, 640, 480);
+      guiApp.desktop.ExternalPosition(0,0, 800, 240);
+
+#ifdef __EMSCRIPTEN__
+
+      {
+      EMSCRIPTEN_RESULT ret;
+
+      ret = emscripten_set_keypress_callback(0, 0, 1, em_key_callback);
+      //TEST_RESULT(emscripten_set_keypress_callback);
+      ret = emscripten_set_keydown_callback(0, 0, 1, em_key_callback);
+      //TEST_RESULT(emscripten_set_keydown_callback);
+      ret = emscripten_set_keyup_callback(0, 0, 1, em_key_callback);
+      //TEST_RESULT(emscripten_set_keyup_callback);
+
+      //ret = emscripten_set_click_callback(0, 0, 1, em_mouse_callback);
+      //TEST_RESULT(emscripten_set_click_callback);
+      ret = emscripten_set_mousedown_callback(0, 0, 1, em_mouse_callback);
+      //TEST_RESULT(emscripten_set_mousedown_callback);
+      ret = emscripten_set_mouseup_callback(0, 0, 1, em_mouse_callback);
+      //TEST_RESULT(emscripten_set_mouseup_callback);
+      ret = emscripten_set_dblclick_callback(0, 0, 1, em_mouse_callback);
+      //TEST_RESULT(emscripten_set_dblclick_callback);
+      ret = emscripten_set_mousemove_callback(0, 0, 1, em_mouse_callback);
+      //TEST_RESULT(emscripten_set_mousemove_callback);
+      ret = emscripten_set_mouseenter_callback(0, 0, 1, em_mouse_callback);
+      //TEST_RESULT(emscripten_set_mouseenter_callback);
+      ret = emscripten_set_mouseleave_callback(0, 0, 1, em_mouse_callback);
+      //TEST_RESULT(emscripten_set_mouseleave_callback);
+      ret = emscripten_set_mouseover_callback(0, 0, 1, em_mouse_callback);
+      //TEST_RESULT(emscripten_set_mouseover_callback);
+      ret = emscripten_set_mouseout_callback(0, 0, 1, em_mouse_callback);
+      //TEST_RESULT(emscripten_set_mouseout_callback);
+
+      ret = emscripten_set_wheel_callback(0, 0, 1, em_wheel_callback);
+      //TEST_RESULT(emscripten_set_wheel_callback);
+
+      ret = emscripten_set_resize_callback(0, 0, 1, em_uievent_callback);
+      //TEST_RESULT(emscripten_set_resize_callback);
+      ret = emscripten_set_scroll_callback(0, 0, 1, em_uievent_callback);
+      //TEST_RESULT(emscripten_set_scroll_callback);
+
+      ret = emscripten_set_blur_callback(0, 0, 1, em_focusevent_callback);
+      //TEST_RESULT(emscripten_set_blur_callback);
+      ret = emscripten_set_focus_callback(0, 0, 1, em_focusevent_callback);
+      //TEST_RESULT(emscripten_set_focus_callback);
+      ret = emscripten_set_focusin_callback(0, 0, 1, em_focusevent_callback);
+      //TEST_RESULT(emscripten_set_focusin_callback);
+      ret = emscripten_set_focusout_callback(0, 0, 1, em_focusevent_callback);
+      //TEST_RESULT(emscripten_set_focusout_callback);
+
+      ret = emscripten_set_deviceorientation_callback(0, 1, em_deviceorientation_callback);
+      //TEST_RESULT(emscripten_set_deviceorientation_callback);
+      ret = emscripten_set_devicemotion_callback(0, 1, em_devicemotion_callback);
+      //TEST_RESULT(emscripten_set_devicemotion_callback);
+
+      ret = emscripten_set_orientationchange_callback(0, 1, em_orientationchange_callback);
+      //TEST_RESULT(emscripten_set_orientationchange_callback);
+
+#if 0
+      // Test the polling of orientation.
+      EmscriptenOrientationChangeEvent oce;
+      ret = emscripten_get_orientation_status(&oce);
+      //TEST_RESULT(emscripten_get_orientation_status);
+      if (ret == EMSCRIPTEN_RESULT_SUCCESS) {
+      printf("The current orientation is:\n");
+      orientationchange_callback(EMSCRIPTEN_EVENT_ORIENTATIONCHANGE, &oce, 0);
+      }
+
+      int newOrientation = (oce.orientationIndex == EMSCRIPTEN_ORIENTATION_PORTRAIT_PRIMARY
+      || oce.orientationIndex == EMSCRIPTEN_ORIENTATION_PORTRAIT_SECONDARY) ? EMSCRIPTEN_ORIENTATION_LANDSCAPE_PRIMARY : EMSCRIPTEN_ORIENTATION_PORTRAIT_PRIMARY;
+      // Test locking of orientation.
+      ret = emscripten_lock_orientation(newOrientation);
+      //TEST_RESULT(emscripten_lock_orientation);
+      if (ret == EMSCRIPTEN_RESULT_SUCCESS) {
+      printf("Locked orientation to state %d.\n", newOrientation);
+      }
+
+      ret = emscripten_get_orientation_status(&oce);
+      //TEST_RESULT(emscripten_get_orientation_status);
+      if (ret == EMSCRIPTEN_RESULT_SUCCESS) {
+      printf("The current orientation is after locking:\n");
+      orientationchange_callback(18, &oce, 0);
+      }
+
+      ret = emscripten_unlock_orientation();
+      //TEST_RESULT(emscripten_unlock_orientation);
+      if (ret == EMSCRIPTEN_RESULT_SUCCESS) {
+      printf("Unlocked orientation.\n");
+      }
+
+      EmscriptenFullscreenChangeEvent fsce;
+      ret = emscripten_get_fullscreen_status(&fsce);
+      //TEST_RESULT(emscripten_get_fullscreen_status);
+      if (ret == EMSCRIPTEN_RESULT_SUCCESS) {
+      printf("The current fullscreen status is:\n");
+      fullscreenchange_callback(EMSCRIPTEN_EVENT_FULLSCREENCHANGE, &fsce, 0);
+      }
+
+      ret = emscripten_set_fullscreenchange_callback(0, 0, 1, em_fullscreenchange_callback);
+      //TEST_RESULT(emscripten_set_fullscreenchange_callback);
+
+      // These won't do anything, since fullscreen must be requested in an event handler,
+      // but call these anyways to confirm that they don't crash in an exception in the test suite.
+      ret = emscripten_request_fullscreen(0, 1);
+      //TEST_RESULT(emscripten_request_fullscreen);
+      ret = emscripten_exit_fullscreen();
+      //TEST_RESULT(emscripten_exit_fullscreen);
+
+      EmscriptenPointerlockChangeEvent plce;
+      ret = emscripten_get_pointerlock_status(&plce);
+      //TEST_RESULT(emscripten_get_pointerlock_status);
+      if (ret == EMSCRIPTEN_RESULT_SUCCESS) {
+      printf("The current pointerlock status is:\n");
+      pointerlockchange_callback(EMSCRIPTEN_EVENT_POINTERLOCKCHANGE, &plce, 0);
+      }
+
+      ret = emscripten_set_pointerlockchange_callback(0, 0, 1, em_pointerlockchange_callback);
+      //TEST_RESULT(emscripten_set_pointerlockchange_callback);
+
+      // These won't do anything, since pointer lock must be requested in an event handler,
+      // but call these anyways to confirm that they don't crash in an exception in the test suite.
+      ret = emscripten_request_pointerlock(0, 1);
+      //TEST_RESULT(emscripten_request_pointerlock);
+      ret = emscripten_exit_pointerlock();
+      //TEST_RESULT(emscripten_exit_pointerlock);
+
+      int vibratePattern[] = {
+      150, 500,
+      300, 500,
+      450
+      };
+      ret = emscripten_vibrate_pattern(vibratePattern, sizeof(vibratePattern)/sizeof(vibratePattern[0]));
+      //TEST_RESULT(emscripten_vibrate_pattern);
+
+      EmscriptenVisibilityChangeEvent vce;
+      ret = emscripten_get_visibility_status(&vce);
+      //TEST_RESULT(emscripten_get_visibility_status);
+      if (ret == EMSCRIPTEN_RESULT_SUCCESS) {
+      printf("Current visibility status:\n");
+      visibilitychange_callback(EMSCRIPTEN_EVENT_VISIBILITYCHANGE, &vce, 0);
+      }
+
+      ret = emscripten_set_visibilitychange_callback(0, 1, visibilitychange_callback);
+      //TEST_RESULT(emscripten_set_visibilitychange_callback);
+
+      ret = emscripten_set_touchstart_callback(0, 0, 1, em_touch_callback);
+      //TEST_RESULT(emscripten_set_touchstart_callback);
+      ret = emscripten_set_touchend_callback(0, 0, 1, em_touch_callback);
+      //TEST_RESULT(emscripten_set_touchend_callback);
+      ret = emscripten_set_touchmove_callback(0, 0, 1, em_touch_callback);
+      //TEST_RESULT(emscripten_set_touchmove_callback);
+      ret = emscripten_set_touchcancel_callback(0, 0, 1, em_touch_callback);
+      //TEST_RESULT(emscripten_set_touchcancel_callback);
+
+      ret = emscripten_set_gamepadconnected_callback(0, 1, gamepad_callback);
+      //TEST_RESULT(emscripten_set_gamepadconnected_callback);
+      ret = emscripten_set_gamepaddisconnected_callback(0, 1, gamepad_callback);
+      //TEST_RESULT(emscripten_set_gamepaddisconnected_callback);
+
+      emscripten_set_main_loop(mainloop, 10, 0);
+
+      ret = emscripten_set_beforeunload_callback(0, beforeunload_callback);
+      //TEST_RESULT(emscripten_set_beforeunload_callback);
+
+      ret = emscripten_set_batterychargingchange_callback(0, battery_callback);
+      //TEST_RESULT(emscripten_set_batterychargingchange_callback);
+      ret = emscripten_set_batterylevelchange_callback(0, battery_callback);
+      //TEST_RESULT(emscripten_set_batterylevelchange_callback);
+
+      EmscriptenBatteryEvent bs;
+      ret = emscripten_get_battery_status(&bs);
+      //TEST_RESULT(emscripten_get_battery_status);
+      if (ret == EMSCRIPTEN_RESULT_SUCCESS) {
+      printf("Current battery status:\n");
+      battery_callback(EMSCRIPTEN_EVENT_BATTERYLEVELCHANGE, &bs, 0);
+      }
+
+      ret = emscripten_set_webglcontextlost_callback(0, 0, 1, em_webglcontext_callback);
+      //TEST_RESULT(emscripten_set_webglcontextlost_callback);
+      ret = emscripten_set_webglcontextrestored_callback(0, 0, 1, em_webglcontext_callback);
+      //TEST_RESULT(emscripten_set_webglcontextrestored_callback);
+#endif
+      }
+#endif
+
       return true;
    }
 
@@ -50,7 +938,7 @@ class EmscriptenInterface : Interface
 
    bool ::ProcessInput(bool processAll)
    {
-      sflnprintf("class(EmscriptenInterface) ::ProcessInput [STUB!]\n");
+      //sflnprintf("class(EmscriptenInterface) ::ProcessInput [STUB!]\n");
       return false;
    }
 
@@ -129,7 +1017,7 @@ class EmscriptenInterface : Interface
 
    void ::OffsetWindow(Window window, int * x, int * y)
    {
-      sflnprintf("class(EmscriptenInterface) ::OffsetWindow [STUB!]\n");
+      //sflnprintf("class(EmscriptenInterface) ::OffsetWindow [STUB!]\n");
    }
 
    void ::UpdateRootWindow(Window window)
@@ -180,7 +1068,8 @@ class EmscriptenInterface : Interface
 
    void ::GetMousePosition(int *x, int *y)
    {
-      sflnprintf("class(EmscriptenInterface) ::GetMousePosition [STUB!]\n");
+      *x = canvasX;
+      *y = canvasY;
    }
 
    void ::SetMousePosition(int x, int y)