src/video/emscripten/SDL_emscriptenevents.c
author Philipp Wiesemann <philipp.wiesemann@arcor.de>
Sun, 15 Feb 2015 21:44:36 +0100
changeset 9352 2cbf791a601c
parent 9278 8900afb78a19
child 9377 4c29dc2baaa8
permissions -rw-r--r--
Emscripten: Changed return type of callback implementations from int to EM_BOOL.

The prototypes are declared with EM_BOOL (which is currently an int) in html5.h.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 
    22 
    23 #include "../../SDL_internal.h"
    24 
    25 #if SDL_VIDEO_DRIVER_EMSCRIPTEN
    26 
    27 #include <emscripten/html5.h>
    28 
    29 #include "../../events/SDL_events_c.h"
    30 #include "../../events/SDL_keyboard_c.h"
    31 #include "../../events/SDL_touch_c.h"
    32 
    33 #include "SDL_emscriptenevents.h"
    34 #include "SDL_emscriptenvideo.h"
    35 
    36 #include "SDL_hints.h"
    37 
    38 #define FULLSCREEN_MASK ( SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_FULLSCREEN )
    39 
    40 /*
    41 .which to scancode
    42 https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Constants
    43 */
    44 static const SDL_Scancode emscripten_scancode_table[] = {
    45     /*  0 */    SDL_SCANCODE_UNKNOWN,
    46     /*  1 */    SDL_SCANCODE_UNKNOWN,
    47     /*  2 */    SDL_SCANCODE_UNKNOWN,
    48     /*  3 */    SDL_SCANCODE_CANCEL,
    49     /*  4 */    SDL_SCANCODE_UNKNOWN,
    50     /*  5 */    SDL_SCANCODE_UNKNOWN,
    51     /*  6 */    SDL_SCANCODE_HELP,
    52     /*  7 */    SDL_SCANCODE_UNKNOWN,
    53     /*  8 */    SDL_SCANCODE_BACKSPACE,
    54     /*  9 */    SDL_SCANCODE_TAB,
    55     /*  10 */   SDL_SCANCODE_UNKNOWN,
    56     /*  11 */   SDL_SCANCODE_UNKNOWN,
    57     /*  12 */   SDL_SCANCODE_UNKNOWN,
    58     /*  13 */   SDL_SCANCODE_RETURN,
    59     /*  14 */   SDL_SCANCODE_UNKNOWN,
    60     /*  15 */   SDL_SCANCODE_UNKNOWN,
    61     /*  16 */   SDL_SCANCODE_LSHIFT,
    62     /*  17 */   SDL_SCANCODE_LCTRL,
    63     /*  18 */   SDL_SCANCODE_LALT,
    64     /*  19 */   SDL_SCANCODE_PAUSE,
    65     /*  20 */   SDL_SCANCODE_CAPSLOCK,
    66     /*  21 */   SDL_SCANCODE_UNKNOWN,
    67     /*  22 */   SDL_SCANCODE_UNKNOWN,
    68     /*  23 */   SDL_SCANCODE_UNKNOWN,
    69     /*  24 */   SDL_SCANCODE_UNKNOWN,
    70     /*  25 */   SDL_SCANCODE_UNKNOWN,
    71     /*  26 */   SDL_SCANCODE_UNKNOWN,
    72     /*  27 */   SDL_SCANCODE_ESCAPE,
    73     /*  28 */   SDL_SCANCODE_UNKNOWN,
    74     /*  29 */   SDL_SCANCODE_UNKNOWN,
    75     /*  30 */   SDL_SCANCODE_UNKNOWN,
    76     /*  31 */   SDL_SCANCODE_UNKNOWN,
    77     /*  32 */   SDL_SCANCODE_SPACE,
    78     /*  33 */   SDL_SCANCODE_PAGEUP,
    79     /*  34 */   SDL_SCANCODE_PAGEDOWN,
    80     /*  35 */   SDL_SCANCODE_END,
    81     /*  36 */   SDL_SCANCODE_HOME,
    82     /*  37 */   SDL_SCANCODE_LEFT,
    83     /*  38 */   SDL_SCANCODE_UP,
    84     /*  39 */   SDL_SCANCODE_RIGHT,
    85     /*  40 */   SDL_SCANCODE_DOWN,
    86     /*  41 */   SDL_SCANCODE_UNKNOWN,
    87     /*  42 */   SDL_SCANCODE_UNKNOWN,
    88     /*  43 */   SDL_SCANCODE_UNKNOWN,
    89     /*  44 */   SDL_SCANCODE_UNKNOWN,
    90     /*  45 */   SDL_SCANCODE_INSERT,
    91     /*  46 */   SDL_SCANCODE_DELETE,
    92     /*  47 */   SDL_SCANCODE_UNKNOWN,
    93     /*  48 */   SDL_SCANCODE_0,
    94     /*  49 */   SDL_SCANCODE_1,
    95     /*  50 */   SDL_SCANCODE_2,
    96     /*  51 */   SDL_SCANCODE_3,
    97     /*  52 */   SDL_SCANCODE_4,
    98     /*  53 */   SDL_SCANCODE_5,
    99     /*  54 */   SDL_SCANCODE_6,
   100     /*  55 */   SDL_SCANCODE_7,
   101     /*  56 */   SDL_SCANCODE_8,
   102     /*  57 */   SDL_SCANCODE_9,
   103     /*  58 */   SDL_SCANCODE_UNKNOWN,
   104     /*  59 */   SDL_SCANCODE_SEMICOLON,
   105     /*  60 */   SDL_SCANCODE_UNKNOWN,
   106     /*  61 */   SDL_SCANCODE_EQUALS,
   107     /*  62 */   SDL_SCANCODE_UNKNOWN,
   108     /*  63 */   SDL_SCANCODE_UNKNOWN,
   109     /*  64 */   SDL_SCANCODE_UNKNOWN,
   110     /*  65 */   SDL_SCANCODE_A,
   111     /*  66 */   SDL_SCANCODE_B,
   112     /*  67 */   SDL_SCANCODE_C,
   113     /*  68 */   SDL_SCANCODE_D,
   114     /*  69 */   SDL_SCANCODE_E,
   115     /*  70 */   SDL_SCANCODE_F,
   116     /*  71 */   SDL_SCANCODE_G,
   117     /*  72 */   SDL_SCANCODE_H,
   118     /*  73 */   SDL_SCANCODE_I,
   119     /*  74 */   SDL_SCANCODE_J,
   120     /*  75 */   SDL_SCANCODE_K,
   121     /*  76 */   SDL_SCANCODE_L,
   122     /*  77 */   SDL_SCANCODE_M,
   123     /*  78 */   SDL_SCANCODE_N,
   124     /*  79 */   SDL_SCANCODE_O,
   125     /*  80 */   SDL_SCANCODE_P,
   126     /*  81 */   SDL_SCANCODE_Q,
   127     /*  82 */   SDL_SCANCODE_R,
   128     /*  83 */   SDL_SCANCODE_S,
   129     /*  84 */   SDL_SCANCODE_T,
   130     /*  85 */   SDL_SCANCODE_U,
   131     /*  86 */   SDL_SCANCODE_V,
   132     /*  87 */   SDL_SCANCODE_W,
   133     /*  88 */   SDL_SCANCODE_X,
   134     /*  89 */   SDL_SCANCODE_Y,
   135     /*  90 */   SDL_SCANCODE_Z,
   136     /*  91 */   SDL_SCANCODE_LGUI,
   137     /*  92 */   SDL_SCANCODE_UNKNOWN,
   138     /*  93 */   SDL_SCANCODE_APPLICATION,
   139     /*  94 */   SDL_SCANCODE_UNKNOWN,
   140     /*  95 */   SDL_SCANCODE_UNKNOWN,
   141     /*  96 */   SDL_SCANCODE_KP_0,
   142     /*  97 */   SDL_SCANCODE_KP_1,
   143     /*  98 */   SDL_SCANCODE_KP_2,
   144     /*  99 */   SDL_SCANCODE_KP_3,
   145     /* 100 */   SDL_SCANCODE_KP_4,
   146     /* 101 */   SDL_SCANCODE_KP_5,
   147     /* 102 */   SDL_SCANCODE_KP_6,
   148     /* 103 */   SDL_SCANCODE_KP_7,
   149     /* 104 */   SDL_SCANCODE_KP_8,
   150     /* 105 */   SDL_SCANCODE_KP_9,
   151     /* 106 */   SDL_SCANCODE_KP_MULTIPLY,
   152     /* 107 */   SDL_SCANCODE_KP_PLUS,
   153     /* 108 */   SDL_SCANCODE_UNKNOWN,
   154     /* 109 */   SDL_SCANCODE_KP_MINUS,
   155     /* 110 */   SDL_SCANCODE_KP_PERIOD,
   156     /* 111 */   SDL_SCANCODE_KP_DIVIDE,
   157     /* 112 */   SDL_SCANCODE_F1,
   158     /* 113 */   SDL_SCANCODE_F2,
   159     /* 114 */   SDL_SCANCODE_F3,
   160     /* 115 */   SDL_SCANCODE_F4,
   161     /* 116 */   SDL_SCANCODE_F5,
   162     /* 117 */   SDL_SCANCODE_F6,
   163     /* 118 */   SDL_SCANCODE_F7,
   164     /* 119 */   SDL_SCANCODE_F8,
   165     /* 120 */   SDL_SCANCODE_F9,
   166     /* 121 */   SDL_SCANCODE_F10,
   167     /* 122 */   SDL_SCANCODE_F11,
   168     /* 123 */   SDL_SCANCODE_F12,
   169     /* 124 */   SDL_SCANCODE_F13,
   170     /* 125 */   SDL_SCANCODE_F14,
   171     /* 126 */   SDL_SCANCODE_F15,
   172     /* 127 */   SDL_SCANCODE_F16,
   173     /* 128 */   SDL_SCANCODE_F17,
   174     /* 129 */   SDL_SCANCODE_F18,
   175     /* 130 */   SDL_SCANCODE_F19,
   176     /* 131 */   SDL_SCANCODE_F20,
   177     /* 132 */   SDL_SCANCODE_F21,
   178     /* 133 */   SDL_SCANCODE_F22,
   179     /* 134 */   SDL_SCANCODE_F23,
   180     /* 135 */   SDL_SCANCODE_F24,
   181     /* 136 */   SDL_SCANCODE_UNKNOWN,
   182     /* 137 */   SDL_SCANCODE_UNKNOWN,
   183     /* 138 */   SDL_SCANCODE_UNKNOWN,
   184     /* 139 */   SDL_SCANCODE_UNKNOWN,
   185     /* 140 */   SDL_SCANCODE_UNKNOWN,
   186     /* 141 */   SDL_SCANCODE_UNKNOWN,
   187     /* 142 */   SDL_SCANCODE_UNKNOWN,
   188     /* 143 */   SDL_SCANCODE_UNKNOWN,
   189     /* 144 */   SDL_SCANCODE_NUMLOCKCLEAR,
   190     /* 145 */   SDL_SCANCODE_SCROLLLOCK,
   191     /* 146 */   SDL_SCANCODE_UNKNOWN,
   192     /* 147 */   SDL_SCANCODE_UNKNOWN,
   193     /* 148 */   SDL_SCANCODE_UNKNOWN,
   194     /* 149 */   SDL_SCANCODE_UNKNOWN,
   195     /* 150 */   SDL_SCANCODE_UNKNOWN,
   196     /* 151 */   SDL_SCANCODE_UNKNOWN,
   197     /* 152 */   SDL_SCANCODE_UNKNOWN,
   198     /* 153 */   SDL_SCANCODE_UNKNOWN,
   199     /* 154 */   SDL_SCANCODE_UNKNOWN,
   200     /* 155 */   SDL_SCANCODE_UNKNOWN,
   201     /* 156 */   SDL_SCANCODE_UNKNOWN,
   202     /* 157 */   SDL_SCANCODE_UNKNOWN,
   203     /* 158 */   SDL_SCANCODE_UNKNOWN,
   204     /* 159 */   SDL_SCANCODE_UNKNOWN,
   205     /* 160 */   SDL_SCANCODE_UNKNOWN,
   206     /* 161 */   SDL_SCANCODE_UNKNOWN,
   207     /* 162 */   SDL_SCANCODE_UNKNOWN,
   208     /* 163 */   SDL_SCANCODE_UNKNOWN,
   209     /* 164 */   SDL_SCANCODE_UNKNOWN,
   210     /* 165 */   SDL_SCANCODE_UNKNOWN,
   211     /* 166 */   SDL_SCANCODE_UNKNOWN,
   212     /* 167 */   SDL_SCANCODE_UNKNOWN,
   213     /* 168 */   SDL_SCANCODE_UNKNOWN,
   214     /* 169 */   SDL_SCANCODE_UNKNOWN,
   215     /* 170 */   SDL_SCANCODE_UNKNOWN,
   216     /* 171 */   SDL_SCANCODE_UNKNOWN,
   217     /* 172 */   SDL_SCANCODE_UNKNOWN,
   218     /* 173 */   SDL_SCANCODE_MINUS, /*FX*/
   219     /* 174 */   SDL_SCANCODE_UNKNOWN,
   220     /* 175 */   SDL_SCANCODE_UNKNOWN,
   221     /* 176 */   SDL_SCANCODE_UNKNOWN,
   222     /* 177 */   SDL_SCANCODE_UNKNOWN,
   223     /* 178 */   SDL_SCANCODE_UNKNOWN,
   224     /* 179 */   SDL_SCANCODE_UNKNOWN,
   225     /* 180 */   SDL_SCANCODE_UNKNOWN,
   226     /* 181 */   SDL_SCANCODE_UNKNOWN,
   227     /* 182 */   SDL_SCANCODE_UNKNOWN,
   228     /* 183 */   SDL_SCANCODE_UNKNOWN,
   229     /* 184 */   SDL_SCANCODE_UNKNOWN,
   230     /* 185 */   SDL_SCANCODE_UNKNOWN,
   231     /* 186 */   SDL_SCANCODE_SEMICOLON, /*IE, Chrome, D3E legacy*/
   232     /* 187 */   SDL_SCANCODE_EQUALS, /*IE, Chrome, D3E legacy*/
   233     /* 188 */   SDL_SCANCODE_COMMA,
   234     /* 189 */   SDL_SCANCODE_MINUS, /*IE, Chrome, D3E legacy*/
   235     /* 190 */   SDL_SCANCODE_PERIOD,
   236     /* 191 */   SDL_SCANCODE_SLASH,
   237     /* 192 */   SDL_SCANCODE_GRAVE, /*FX, D3E legacy (SDL_SCANCODE_APOSTROPHE in IE/Chrome)*/
   238     /* 193 */   SDL_SCANCODE_UNKNOWN,
   239     /* 194 */   SDL_SCANCODE_UNKNOWN,
   240     /* 195 */   SDL_SCANCODE_UNKNOWN,
   241     /* 196 */   SDL_SCANCODE_UNKNOWN,
   242     /* 197 */   SDL_SCANCODE_UNKNOWN,
   243     /* 198 */   SDL_SCANCODE_UNKNOWN,
   244     /* 199 */   SDL_SCANCODE_UNKNOWN,
   245     /* 200 */   SDL_SCANCODE_UNKNOWN,
   246     /* 201 */   SDL_SCANCODE_UNKNOWN,
   247     /* 202 */   SDL_SCANCODE_UNKNOWN,
   248     /* 203 */   SDL_SCANCODE_UNKNOWN,
   249     /* 204 */   SDL_SCANCODE_UNKNOWN,
   250     /* 205 */   SDL_SCANCODE_UNKNOWN,
   251     /* 206 */   SDL_SCANCODE_UNKNOWN,
   252     /* 207 */   SDL_SCANCODE_UNKNOWN,
   253     /* 208 */   SDL_SCANCODE_UNKNOWN,
   254     /* 209 */   SDL_SCANCODE_UNKNOWN,
   255     /* 210 */   SDL_SCANCODE_UNKNOWN,
   256     /* 211 */   SDL_SCANCODE_UNKNOWN,
   257     /* 212 */   SDL_SCANCODE_UNKNOWN,
   258     /* 213 */   SDL_SCANCODE_UNKNOWN,
   259     /* 214 */   SDL_SCANCODE_UNKNOWN,
   260     /* 215 */   SDL_SCANCODE_UNKNOWN,
   261     /* 216 */   SDL_SCANCODE_UNKNOWN,
   262     /* 217 */   SDL_SCANCODE_UNKNOWN,
   263     /* 218 */   SDL_SCANCODE_UNKNOWN,
   264     /* 219 */   SDL_SCANCODE_LEFTBRACKET,
   265     /* 220 */   SDL_SCANCODE_BACKSLASH,
   266     /* 221 */   SDL_SCANCODE_RIGHTBRACKET,
   267     /* 222 */   SDL_SCANCODE_APOSTROPHE, /*FX, D3E legacy*/
   268 };
   269 
   270 
   271 /* "borrowed" from SDL_windowsevents.c */
   272 int
   273 Emscripten_ConvertUTF32toUTF8(Uint32 codepoint, char * text)
   274 {
   275     if (codepoint <= 0x7F) {
   276         text[0] = (char) codepoint;
   277         text[1] = '\0';
   278     } else if (codepoint <= 0x7FF) {
   279         text[0] = 0xC0 | (char) ((codepoint >> 6) & 0x1F);
   280         text[1] = 0x80 | (char) (codepoint & 0x3F);
   281         text[2] = '\0';
   282     } else if (codepoint <= 0xFFFF) {
   283         text[0] = 0xE0 | (char) ((codepoint >> 12) & 0x0F);
   284         text[1] = 0x80 | (char) ((codepoint >> 6) & 0x3F);
   285         text[2] = 0x80 | (char) (codepoint & 0x3F);
   286         text[3] = '\0';
   287     } else if (codepoint <= 0x10FFFF) {
   288         text[0] = 0xF0 | (char) ((codepoint >> 18) & 0x0F);
   289         text[1] = 0x80 | (char) ((codepoint >> 12) & 0x3F);
   290         text[2] = 0x80 | (char) ((codepoint >> 6) & 0x3F);
   291         text[3] = 0x80 | (char) (codepoint & 0x3F);
   292         text[4] = '\0';
   293     } else {
   294         return SDL_FALSE;
   295     }
   296     return SDL_TRUE;
   297 }
   298 
   299 EM_BOOL
   300 Emscripten_HandleMouseMove(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData)
   301 {
   302     SDL_WindowData *window_data = userData;
   303     int mx = mouseEvent->canvasX, my = mouseEvent->canvasY;
   304     EmscriptenPointerlockChangeEvent pointerlock_status;
   305 
   306     /* check for pointer lock */
   307     emscripten_get_pointerlock_status(&pointerlock_status);
   308 
   309     if (pointerlock_status.isActive) {
   310         mx = mouseEvent->movementX;
   311         my = mouseEvent->movementY;
   312     }
   313 
   314     /* rescale (in case canvas is being scaled)*/
   315     double client_w, client_h;
   316     emscripten_get_element_css_size(NULL, &client_w, &client_h);
   317 
   318     mx = mx * (window_data->window->w / (client_w * window_data->pixel_ratio));
   319     my = my * (window_data->window->h / (client_h * window_data->pixel_ratio));
   320 
   321     SDL_SendMouseMotion(window_data->window, 0, pointerlock_status.isActive, mx, my);
   322     return 0;
   323 }
   324 
   325 EM_BOOL
   326 Emscripten_HandleMouseButton(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData)
   327 {
   328     SDL_WindowData *window_data = userData;
   329     uint32_t sdl_button;
   330     switch (mouseEvent->button) {
   331         case 0:
   332             sdl_button = SDL_BUTTON_LEFT;
   333             break;
   334         case 1:
   335             sdl_button = SDL_BUTTON_MIDDLE;
   336             break;
   337         case 2:
   338             sdl_button = SDL_BUTTON_RIGHT;
   339             break;
   340         default:
   341             return 0;
   342     }
   343     SDL_SendMouseButton(window_data->window, 0, eventType == EMSCRIPTEN_EVENT_MOUSEDOWN ? SDL_PRESSED : SDL_RELEASED, sdl_button);
   344     return 1;
   345 }
   346 
   347 EM_BOOL
   348 Emscripten_HandleMouseFocus(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData)
   349 {
   350     SDL_WindowData *window_data = userData;
   351     SDL_SendWindowEvent(window_data->window, eventType == EMSCRIPTEN_EVENT_MOUSEENTER ? SDL_WINDOWEVENT_ENTER : SDL_WINDOWEVENT_LEAVE, 0, 0);
   352     return 1;
   353 }
   354 
   355 EM_BOOL
   356 Emscripten_HandleWheel(int eventType, const EmscriptenWheelEvent *wheelEvent, void *userData)
   357 {
   358     SDL_WindowData *window_data = userData;
   359     SDL_SendMouseWheel(window_data->window, 0, wheelEvent->deltaX, -wheelEvent->deltaY, SDL_MOUSEWHEEL_NORMAL);
   360     return 1;
   361 }
   362 
   363 EM_BOOL
   364 Emscripten_HandleFocus(int eventType, const EmscriptenFocusEvent *wheelEvent, void *userData)
   365 {
   366     SDL_WindowData *window_data = userData;
   367     SDL_SendWindowEvent(window_data->window, eventType == EMSCRIPTEN_EVENT_FOCUS ? SDL_WINDOWEVENT_FOCUS_GAINED : SDL_WINDOWEVENT_FOCUS_LOST, 0, 0);
   368     return 1;
   369 }
   370 
   371 EM_BOOL
   372 Emscripten_HandleTouch(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData)
   373 {
   374     /*SDL_WindowData *window_data = userData;*/
   375     int i;
   376 
   377     SDL_TouchID deviceId = 0;
   378     if (!SDL_GetTouch(deviceId)) {
   379         if (SDL_AddTouch(deviceId, "") < 0) {
   380              return 0;
   381         }
   382     }
   383 
   384     for (i = 0; i < touchEvent->numTouches; i++) {
   385         long x, y, id;
   386 
   387         if (!touchEvent->touches[i].isChanged)
   388             continue;
   389 
   390         id = touchEvent->touches[i].identifier;
   391         x = touchEvent->touches[i].canvasX;
   392         y = touchEvent->touches[i].canvasY;
   393 
   394         if (eventType == EMSCRIPTEN_EVENT_TOUCHMOVE) {
   395             SDL_SendTouchMotion(deviceId, id, x, y, 1.0f);
   396         } else if (eventType == EMSCRIPTEN_EVENT_TOUCHSTART) {
   397             SDL_SendTouch(deviceId, id, SDL_TRUE, x, y, 1.0f);
   398         } else {
   399             SDL_SendTouch(deviceId, id, SDL_FALSE, x, y, 1.0f);
   400         }
   401     }
   402 
   403 
   404     return 1;
   405 }
   406 
   407 EM_BOOL
   408 Emscripten_HandleKey(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData)
   409 {
   410     Uint32 scancode;
   411 
   412     /* .keyCode is deprecated, but still the most reliable way to get keys */
   413     if (keyEvent->keyCode < SDL_arraysize(emscripten_scancode_table)) {
   414         scancode = emscripten_scancode_table[keyEvent->keyCode];
   415 
   416         if (scancode != SDL_SCANCODE_UNKNOWN) {
   417 
   418             if (keyEvent->location == DOM_KEY_LOCATION_RIGHT) {
   419                 switch (scancode) {
   420                     case SDL_SCANCODE_LSHIFT:
   421                         scancode = SDL_SCANCODE_RSHIFT;
   422                         break;
   423                     case SDL_SCANCODE_LCTRL:
   424                         scancode = SDL_SCANCODE_RCTRL;
   425                         break;
   426                     case SDL_SCANCODE_LALT:
   427                         scancode = SDL_SCANCODE_RALT;
   428                         break;
   429                     case SDL_SCANCODE_LGUI:
   430                         scancode = SDL_SCANCODE_RGUI;
   431                         break;
   432                 }
   433             }
   434             SDL_SendKeyboardKey(eventType == EMSCRIPTEN_EVENT_KEYDOWN ?
   435                                 SDL_PRESSED : SDL_RELEASED, scancode);
   436         }
   437     }
   438 
   439     /* if we prevent keydown, we won't get keypress
   440      * also we need to ALWAYS prevent backspace and tab otherwise chrome takes action and does bad navigation UX
   441      */
   442     return SDL_GetEventState(SDL_TEXTINPUT) != SDL_ENABLE || eventType != EMSCRIPTEN_EVENT_KEYDOWN
   443             || keyEvent->keyCode == 8 /* backspace */ || keyEvent->keyCode == 9 /* tab */;
   444 }
   445 
   446 EM_BOOL
   447 Emscripten_HandleKeyPress(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData)
   448 {
   449     char text[5];
   450     Emscripten_ConvertUTF32toUTF8(keyEvent->charCode, text);
   451     SDL_SendKeyboardText(text);
   452     return 1;
   453 }
   454 
   455 EM_BOOL
   456 Emscripten_HandleFullscreenChange(int eventType, const EmscriptenFullscreenChangeEvent *fullscreenChangeEvent, void *userData)
   457 {
   458     /*make sure this is actually our element going fullscreen*/
   459     if(SDL_strcmp(fullscreenChangeEvent->id, "SDLFullscreenElement") != 0)
   460         return 0;
   461 
   462     SDL_WindowData *window_data = userData;
   463     if(fullscreenChangeEvent->isFullscreen)
   464     {
   465         SDL_bool is_desktop_fullscreen;
   466         window_data->window->flags |= window_data->requested_fullscreen_mode;
   467 
   468         if(!window_data->requested_fullscreen_mode)
   469             window_data->window->flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; /*we didn't reqest fullscreen*/
   470 
   471         window_data->requested_fullscreen_mode = 0;
   472 
   473         is_desktop_fullscreen = (window_data->window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP;
   474 
   475         /*update size*/
   476         if(window_data->window->flags & SDL_WINDOW_RESIZABLE || is_desktop_fullscreen)
   477         {
   478             emscripten_set_canvas_size(fullscreenChangeEvent->screenWidth, fullscreenChangeEvent->screenHeight);
   479             SDL_SendWindowEvent(window_data->window, SDL_WINDOWEVENT_RESIZED, fullscreenChangeEvent->screenWidth, fullscreenChangeEvent->screenHeight);
   480         }
   481         else
   482         {
   483             /*preserve ratio*/
   484             double w = window_data->window->w;
   485             double h = window_data->window->h;
   486             double factor = SDL_min(fullscreenChangeEvent->screenWidth / w, fullscreenChangeEvent->screenHeight / h);
   487             emscripten_set_element_css_size(NULL, w * factor, h * factor);
   488         }
   489     }
   490     else
   491     {
   492         EM_ASM({
   493             //un-reparent canvas (similar to Module.requestFullscreen)
   494             var canvas = Module['canvas'];
   495             if(canvas.parentNode.id == "SDLFullscreenElement") {
   496                 var canvasContainer = canvas.parentNode;
   497                 canvasContainer.parentNode.insertBefore(canvas, canvasContainer);
   498                 canvasContainer.parentNode.removeChild(canvasContainer);
   499             }
   500         });
   501         double unscaled_w = window_data->windowed_width / window_data->pixel_ratio;
   502         double unscaled_h = window_data->windowed_height / window_data->pixel_ratio;
   503         emscripten_set_canvas_size(window_data->windowed_width, window_data->windowed_height);
   504 
   505         if (!window_data->external_size && window_data->pixel_ratio != 1.0f) {
   506             emscripten_set_element_css_size(NULL, unscaled_w, unscaled_h);
   507         }
   508 
   509         SDL_SendWindowEvent(window_data->window, SDL_WINDOWEVENT_RESIZED, unscaled_w, unscaled_h);
   510 
   511         window_data->window->flags &= ~FULLSCREEN_MASK;
   512     }
   513 
   514     return 0;
   515 }
   516 
   517 EM_BOOL
   518 Emscripten_HandleResize(int eventType, const EmscriptenUiEvent *uiEvent, void *userData)
   519 {
   520     SDL_WindowData *window_data = userData;
   521     if(window_data->window->flags & FULLSCREEN_MASK)
   522     {
   523         SDL_bool is_desktop_fullscreen = (window_data->window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP;
   524 
   525         if(window_data->window->flags & SDL_WINDOW_RESIZABLE || is_desktop_fullscreen)
   526         {
   527             emscripten_set_canvas_size(uiEvent->windowInnerWidth * window_data->pixel_ratio, uiEvent->windowInnerHeight * window_data->pixel_ratio);
   528             SDL_SendWindowEvent(window_data->window, SDL_WINDOWEVENT_RESIZED, uiEvent->windowInnerWidth, uiEvent->windowInnerHeight);
   529         }
   530     }
   531     else
   532     {
   533         /* this will only work if the canvas size is set through css */
   534         if(window_data->window->flags & SDL_WINDOW_RESIZABLE)
   535         {
   536             double w = window_data->window->w;
   537             double h = window_data->window->h;
   538 
   539             if(window_data->external_size) {
   540                 emscripten_get_element_css_size(NULL, &w, &h);
   541             }
   542 
   543             emscripten_set_canvas_size(w * window_data->pixel_ratio, h * window_data->pixel_ratio);
   544 
   545             /* set_canvas_size unsets this */
   546             if (!window_data->external_size && window_data->pixel_ratio != 1.0f) {
   547                 emscripten_set_element_css_size(NULL, w, h);
   548             }
   549 
   550             SDL_SendWindowEvent(window_data->window, SDL_WINDOWEVENT_RESIZED, w, h);
   551         }
   552     }
   553 
   554     return 0;
   555 }
   556 
   557 EM_BOOL
   558 Emscripten_HandleVisibilityChange(int eventType, const EmscriptenVisibilityChangeEvent *visEvent, void *userData)
   559 {
   560     SDL_WindowData *window_data = userData;
   561     SDL_SendWindowEvent(window_data->window, visEvent->hidden ? SDL_WINDOWEVENT_HIDDEN : SDL_WINDOWEVENT_SHOWN, 0, 0);
   562     return 0;
   563 }
   564 
   565 void
   566 Emscripten_RegisterEventHandlers(SDL_WindowData *data)
   567 {
   568     /* There is only one window and that window is the canvas */
   569     emscripten_set_mousemove_callback("#canvas", data, 0, Emscripten_HandleMouseMove);
   570 
   571     emscripten_set_mousedown_callback("#canvas", data, 0, Emscripten_HandleMouseButton);
   572     emscripten_set_mouseup_callback("#canvas", data, 0, Emscripten_HandleMouseButton);
   573 
   574     emscripten_set_mouseenter_callback("#canvas", data, 0, Emscripten_HandleMouseFocus);
   575     emscripten_set_mouseleave_callback("#canvas", data, 0, Emscripten_HandleMouseFocus);
   576 
   577     emscripten_set_wheel_callback("#canvas", data, 0, Emscripten_HandleWheel);
   578 
   579     emscripten_set_focus_callback("#canvas", data, 0, Emscripten_HandleFocus);
   580     emscripten_set_blur_callback("#canvas", data, 0, Emscripten_HandleFocus);
   581 
   582     emscripten_set_touchstart_callback("#canvas", data, 0, Emscripten_HandleTouch);
   583     emscripten_set_touchend_callback("#canvas", data, 0, Emscripten_HandleTouch);
   584     emscripten_set_touchmove_callback("#canvas", data, 0, Emscripten_HandleTouch);
   585     emscripten_set_touchcancel_callback("#canvas", data, 0, Emscripten_HandleTouch);
   586 
   587     /* Keyboard events are awkward */
   588     const char *keyElement = SDL_GetHint(SDL_HINT_EMSCRIPTEN_KEYBOARD_ELEMENT);
   589     if (!keyElement) keyElement = "#window";
   590 
   591     emscripten_set_keydown_callback(keyElement, data, 0, Emscripten_HandleKey);
   592     emscripten_set_keyup_callback(keyElement, data, 0, Emscripten_HandleKey);
   593     emscripten_set_keypress_callback(keyElement, data, 0, Emscripten_HandleKeyPress);
   594 
   595     emscripten_set_fullscreenchange_callback("#document", data, 0, Emscripten_HandleFullscreenChange);
   596 
   597     emscripten_set_resize_callback("#window", data, 0, Emscripten_HandleResize);
   598 
   599     emscripten_set_visibilitychange_callback(data, 0, Emscripten_HandleVisibilityChange);
   600 }
   601 
   602 void
   603 Emscripten_UnregisterEventHandlers(SDL_WindowData *data)
   604 {
   605     /* only works due to having one window */
   606     emscripten_set_mousemove_callback("#canvas", NULL, 0, NULL);
   607 
   608     emscripten_set_mousedown_callback("#canvas", NULL, 0, NULL);
   609     emscripten_set_mouseup_callback("#canvas", NULL, 0, NULL);
   610 
   611     emscripten_set_mouseenter_callback("#canvas", NULL, 0, NULL);
   612     emscripten_set_mouseleave_callback("#canvas", NULL, 0, NULL);
   613 
   614     emscripten_set_wheel_callback("#canvas", NULL, 0, NULL);
   615 
   616     emscripten_set_focus_callback("#canvas", NULL, 0, NULL);
   617     emscripten_set_blur_callback("#canvas", NULL, 0, NULL);
   618 
   619     emscripten_set_touchstart_callback("#canvas", NULL, 0, NULL);
   620     emscripten_set_touchend_callback("#canvas", NULL, 0, NULL);
   621     emscripten_set_touchmove_callback("#canvas", NULL, 0, NULL);
   622     emscripten_set_touchcancel_callback("#canvas", NULL, 0, NULL);
   623 
   624     emscripten_set_keydown_callback("#window", NULL, 0, NULL);
   625     emscripten_set_keyup_callback("#window", NULL, 0, NULL);
   626 
   627     emscripten_set_keypress_callback("#window", NULL, 0, NULL);
   628 
   629     emscripten_set_fullscreenchange_callback("#document", NULL, 0, NULL);
   630 
   631     emscripten_set_resize_callback("#window", NULL, 0, NULL);
   632 
   633     emscripten_set_visibilitychange_callback(NULL, 0, NULL);
   634 }
   635 
   636 #endif /* SDL_VIDEO_DRIVER_EMSCRIPTEN */
   637 
   638 /* vi: set ts=4 sw=4 expandtab: */