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