Atlas - SDL_emscriptenevents.c
Home / ext / SDL2 / src / video / emscripten Lines: 1 | Size: 26031 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)][FILE BEGIN]1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2018 Sam Lantinga <[email protected]> 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 42https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent 43https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode 44*/ 45static 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_VOLUMEDOWN, /*IE, Chrome*/ 221 /* 175 */ SDL_SCANCODE_VOLUMEUP, /*IE, Chrome*/ 222 /* 176 */ SDL_SCANCODE_AUDIONEXT, /*IE, Chrome*/ 223 /* 177 */ SDL_SCANCODE_AUDIOPREV, /*IE, Chrome*/ 224 /* 178 */ SDL_SCANCODE_UNKNOWN, 225 /* 179 */ SDL_SCANCODE_AUDIOPLAY, /*IE, Chrome*/ 226 /* 180 */ SDL_SCANCODE_UNKNOWN, 227 /* 181 */ SDL_SCANCODE_AUDIOMUTE, /*FX*/ 228 /* 182 */ SDL_SCANCODE_VOLUMEDOWN, /*FX*/ 229 /* 183 */ SDL_SCANCODE_VOLUMEUP, /*FX*/ 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 */ 273static int 274Emscripten_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 300static EM_BOOL 301Emscripten_HandlePointerLockChange(int eventType, const EmscriptenPointerlockChangeEvent *changeEvent, void *userData) 302{ 303 SDL_WindowData *window_data = (SDL_WindowData *) userData; 304 /* keep track of lock losses, so we can regrab if/when appropriate. */ 305 window_data->has_pointer_lock = changeEvent->isActive; 306 return 0; 307} 308 309 310static EM_BOOL 311Emscripten_HandleMouseMove(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData) 312{ 313 SDL_WindowData *window_data = userData; 314 const int isPointerLocked = window_data->has_pointer_lock; 315 int mx, my; 316 static double residualx = 0, residualy = 0; 317 318 /* rescale (in case canvas is being scaled)*/ 319 double client_w, client_h, xscale, yscale; 320 emscripten_get_element_css_size(NULL, &client_w, &client_h); 321 xscale = window_data->window->w / client_w; 322 yscale = window_data->window->h / client_h; 323 324 if (isPointerLocked) { 325 residualx += mouseEvent->movementX * xscale; 326 residualy += mouseEvent->movementY * yscale; 327 /* Let slow sub-pixel motion accumulate. Don't lose it. */ 328 mx = residualx; 329 residualx -= mx; 330 my = residualy; 331 residualy -= my; 332 } else { 333 mx = mouseEvent->canvasX * xscale; 334 my = mouseEvent->canvasY * yscale; 335 } 336 337 SDL_SendMouseMotion(window_data->window, 0, isPointerLocked, mx, my); 338 return 0; 339} 340 341static EM_BOOL 342Emscripten_HandleMouseButton(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData) 343{ 344 SDL_WindowData *window_data = userData; 345 Uint8 sdl_button; 346 Uint8 sdl_button_state; 347 SDL_EventType sdl_event_type; 348 349 switch (mouseEvent->button) { 350 case 0: 351 sdl_button = SDL_BUTTON_LEFT; 352 break; 353 case 1: 354 sdl_button = SDL_BUTTON_MIDDLE; 355 break; 356 case 2: 357 sdl_button = SDL_BUTTON_RIGHT; 358 break; 359 default: 360 return 0; 361 } 362 363 if (eventType == EMSCRIPTEN_EVENT_MOUSEDOWN) { 364 if (SDL_GetMouse()->relative_mode && !window_data->has_pointer_lock) { 365 emscripten_request_pointerlock(NULL, 0); /* try to regrab lost pointer lock. */ 366 } 367 sdl_button_state = SDL_PRESSED; 368 sdl_event_type = SDL_MOUSEBUTTONDOWN; 369 } else { 370 sdl_button_state = SDL_RELEASED; 371 sdl_event_type = SDL_MOUSEBUTTONUP; 372 } 373 SDL_SendMouseButton(window_data->window, 0, sdl_button_state, sdl_button); 374 return SDL_GetEventState(sdl_event_type) == SDL_ENABLE; 375} 376 377static EM_BOOL 378Emscripten_HandleMouseFocus(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData) 379{ 380 SDL_WindowData *window_data = userData; 381 382 int mx = mouseEvent->canvasX, my = mouseEvent->canvasY; 383 const int isPointerLocked = window_data->has_pointer_lock; 384 385 if (!isPointerLocked) { 386 /* rescale (in case canvas is being scaled)*/ 387 double client_w, client_h; 388 emscripten_get_element_css_size(NULL, &client_w, &client_h); 389 390 mx = mx * (window_data->window->w / client_w); 391 my = my * (window_data->window->h / client_h); 392 SDL_SendMouseMotion(window_data->window, 0, isPointerLocked, mx, my); 393 } 394 395 SDL_SetMouseFocus(eventType == EMSCRIPTEN_EVENT_MOUSEENTER ? window_data->window : NULL); 396 return SDL_GetEventState(SDL_WINDOWEVENT) == SDL_ENABLE; 397} 398 399static EM_BOOL 400Emscripten_HandleWheel(int eventType, const EmscriptenWheelEvent *wheelEvent, void *userData) 401{ 402 SDL_WindowData *window_data = userData; 403 SDL_SendMouseWheel(window_data->window, 0, (float)wheelEvent->deltaX, (float)-wheelEvent->deltaY, SDL_MOUSEWHEEL_NORMAL); 404 return SDL_GetEventState(SDL_MOUSEWHEEL) == SDL_ENABLE; 405} 406 407static EM_BOOL 408Emscripten_HandleFocus(int eventType, const EmscriptenFocusEvent *wheelEvent, void *userData) 409{ 410 SDL_WindowData *window_data = userData; 411 /* If the user switches away while keys are pressed (such as 412 * via Alt+Tab), key release events won't be received. */ 413 if (eventType == EMSCRIPTEN_EVENT_BLUR) { 414 SDL_ResetKeyboard(); 415 } 416 417 418 SDL_SendWindowEvent(window_data->window, eventType == EMSCRIPTEN_EVENT_FOCUS ? SDL_WINDOWEVENT_FOCUS_GAINED : SDL_WINDOWEVENT_FOCUS_LOST, 0, 0); 419 return SDL_GetEventState(SDL_WINDOWEVENT) == SDL_ENABLE; 420} 421 422static EM_BOOL 423Emscripten_HandleTouch(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData) 424{ 425 SDL_WindowData *window_data = userData; 426 int i; 427 double client_w, client_h; 428 int preventDefault = 0; 429 430 SDL_TouchID deviceId = 1; 431 if (SDL_AddTouch(deviceId, "") < 0) { 432 return 0; 433 } 434 435 emscripten_get_element_css_size(NULL, &client_w, &client_h); 436 437 for (i = 0; i < touchEvent->numTouches; i++) { 438 SDL_FingerID id; 439 float x, y; 440 int mx, my; 441 442 if (!touchEvent->touches[i].isChanged) 443 continue; 444 445 id = touchEvent->touches[i].identifier; 446 x = touchEvent->touches[i].canvasX / client_w; 447 y = touchEvent->touches[i].canvasY / client_h; 448 449 mx = x * window_data->window->w; 450 my = y * window_data->window->h; 451 452 if (eventType == EMSCRIPTEN_EVENT_TOUCHSTART) { 453 if (!window_data->finger_touching) { 454 window_data->finger_touching = SDL_TRUE; 455 window_data->first_finger = id; 456 SDL_SendMouseMotion(window_data->window, SDL_TOUCH_MOUSEID, 0, mx, my); 457 SDL_SendMouseButton(window_data->window, SDL_TOUCH_MOUSEID, SDL_PRESSED, SDL_BUTTON_LEFT); 458 } 459 SDL_SendTouch(deviceId, id, SDL_TRUE, x, y, 1.0f); 460 461 if (!preventDefault && SDL_GetEventState(SDL_FINGERDOWN) == SDL_ENABLE) { 462 preventDefault = 1; 463 } 464 } else if (eventType == EMSCRIPTEN_EVENT_TOUCHMOVE) { 465 if ((window_data->finger_touching) && (window_data->first_finger == id)) { 466 SDL_SendMouseMotion(window_data->window, SDL_TOUCH_MOUSEID, 0, mx, my); 467 } 468 SDL_SendTouchMotion(deviceId, id, x, y, 1.0f); 469 470 if (!preventDefault && SDL_GetEventState(SDL_FINGERMOTION) == SDL_ENABLE) { 471 preventDefault = 1; 472 } 473 } else { 474 if ((window_data->finger_touching) && (window_data->first_finger == id)) { 475 SDL_SendMouseButton(window_data->window, SDL_TOUCH_MOUSEID, SDL_RELEASED, SDL_BUTTON_LEFT); 476 window_data->finger_touching = SDL_FALSE; 477 } 478 SDL_SendTouch(deviceId, id, SDL_FALSE, x, y, 1.0f); 479 480 if (!preventDefault && SDL_GetEventState(SDL_FINGERUP) == SDL_ENABLE) { 481 preventDefault = 1; 482 } 483 } 484 } 485 486 return preventDefault; 487} 488 489static EM_BOOL 490Emscripten_HandleKey(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData) 491{ 492 Uint32 scancode; 493 SDL_bool prevent_default; 494 SDL_bool is_nav_key; 495 496 /* .keyCode is deprecated, but still the most reliable way to get keys */ 497 if (keyEvent->keyCode < SDL_arraysize(emscripten_scancode_table)) { 498 scancode = emscripten_scancode_table[keyEvent->keyCode]; 499 500 if (scancode != SDL_SCANCODE_UNKNOWN) { 501 502 if (keyEvent->location == DOM_KEY_LOCATION_RIGHT) { 503 switch (scancode) { 504 case SDL_SCANCODE_LSHIFT: 505 scancode = SDL_SCANCODE_RSHIFT; 506 break; 507 case SDL_SCANCODE_LCTRL: 508 scancode = SDL_SCANCODE_RCTRL; 509 break; 510 case SDL_SCANCODE_LALT: 511 scancode = SDL_SCANCODE_RALT; 512 break; 513 case SDL_SCANCODE_LGUI: 514 scancode = SDL_SCANCODE_RGUI; 515 break; 516 } 517 } 518 SDL_SendKeyboardKey(eventType == EMSCRIPTEN_EVENT_KEYDOWN ? SDL_PRESSED : SDL_RELEASED, scancode); 519 } 520 } 521 522 prevent_default = SDL_GetEventState(eventType == EMSCRIPTEN_EVENT_KEYDOWN ? SDL_KEYDOWN : SDL_KEYUP) == SDL_ENABLE; 523 524 /* if TEXTINPUT events are enabled we can't prevent keydown or we won't get keypress 525 * we need to ALWAYS prevent backspace and tab otherwise chrome takes action and does bad navigation UX 526 */ 527 is_nav_key = keyEvent->keyCode == 8 /* backspace */ || 528 keyEvent->keyCode == 9 /* tab */ || 529 keyEvent->keyCode == 37 /* left */ || 530 keyEvent->keyCode == 38 /* up */ || 531 keyEvent->keyCode == 39 /* right */ || 532 keyEvent->keyCode == 40 /* down */; 533 534 if (eventType == EMSCRIPTEN_EVENT_KEYDOWN && SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE && !is_nav_key) 535 prevent_default = SDL_FALSE; 536 537 return prevent_default; 538} 539 540static EM_BOOL 541Emscripten_HandleKeyPress(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData) 542{ 543 char text[5]; 544 if (Emscripten_ConvertUTF32toUTF8(keyEvent->charCode, text)) { 545 SDL_SendKeyboardText(text); 546 } 547 return SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE; 548} 549 550static EM_BOOL 551Emscripten_HandleFullscreenChange(int eventType, const EmscriptenFullscreenChangeEvent *fullscreenChangeEvent, void *userData) 552{ 553 SDL_WindowData *window_data = userData; 554 if(fullscreenChangeEvent->isFullscreen) 555 { 556 window_data->window->flags |= window_data->requested_fullscreen_mode; 557 558 window_data->requested_fullscreen_mode = 0; 559 560 if(!window_data->requested_fullscreen_mode) 561 window_data->window->flags |= SDL_WINDOW_FULLSCREEN; /*we didn't reqest fullscreen*/ 562 } 563 else 564 { 565 window_data->window->flags &= ~FULLSCREEN_MASK; 566 } 567 568 return 0; 569} 570 571static EM_BOOL 572Emscripten_HandleResize(int eventType, const EmscriptenUiEvent *uiEvent, void *userData) 573{ 574 SDL_WindowData *window_data = userData; 575 576 /* update pixel ratio */ 577 if (window_data->window->flags & SDL_WINDOW_ALLOW_HIGHDPI) { 578 window_data->pixel_ratio = emscripten_get_device_pixel_ratio(); 579 } 580 581 if(!(window_data->window->flags & FULLSCREEN_MASK)) 582 { 583 /* this will only work if the canvas size is set through css */ 584 if(window_data->window->flags & SDL_WINDOW_RESIZABLE) 585 { 586 double w = window_data->window->w; 587 double h = window_data->window->h; 588 589 if(window_data->external_size) { 590 emscripten_get_element_css_size(NULL, &w, &h); 591 } 592 593 emscripten_set_canvas_size(w * window_data->pixel_ratio, h * window_data->pixel_ratio); 594 595 /* set_canvas_size unsets this */ 596 if (!window_data->external_size && window_data->pixel_ratio != 1.0f) { 597 emscripten_set_element_css_size(NULL, w, h); 598 } 599 600 SDL_SendWindowEvent(window_data->window, SDL_WINDOWEVENT_RESIZED, w, h); 601 } 602 } 603 604 return 0; 605} 606 607EM_BOOL 608Emscripten_HandleCanvasResize(int eventType, const void *reserved, void *userData) 609{ 610 /*this is used during fullscreen changes*/ 611 SDL_WindowData *window_data = userData; 612 613 if(window_data->fullscreen_resize) 614 { 615 double css_w, css_h; 616 emscripten_get_element_css_size(NULL, &css_w, &css_h); 617 SDL_SendWindowEvent(window_data->window, SDL_WINDOWEVENT_RESIZED, css_w, css_h); 618 } 619 620 return 0; 621} 622 623static EM_BOOL 624Emscripten_HandleVisibilityChange(int eventType, const EmscriptenVisibilityChangeEvent *visEvent, void *userData) 625{ 626 SDL_WindowData *window_data = userData; 627 SDL_SendWindowEvent(window_data->window, visEvent->hidden ? SDL_WINDOWEVENT_HIDDEN : SDL_WINDOWEVENT_SHOWN, 0, 0); 628 return 0; 629} 630 631void 632Emscripten_RegisterEventHandlers(SDL_WindowData *data) 633{ 634 const char *keyElement; 635 636 /* There is only one window and that window is the canvas */ 637 emscripten_set_mousemove_callback("#canvas", data, 0, Emscripten_HandleMouseMove); 638 639 emscripten_set_mousedown_callback("#canvas", data, 0, Emscripten_HandleMouseButton); 640 emscripten_set_mouseup_callback("#document", data, 0, Emscripten_HandleMouseButton); 641 642 emscripten_set_mouseenter_callback("#canvas", data, 0, Emscripten_HandleMouseFocus); 643 emscripten_set_mouseleave_callback("#canvas", data, 0, Emscripten_HandleMouseFocus); 644 645 emscripten_set_wheel_callback("#canvas", data, 0, Emscripten_HandleWheel); 646 647 emscripten_set_focus_callback("#window", data, 0, Emscripten_HandleFocus); 648 emscripten_set_blur_callback("#window", data, 0, Emscripten_HandleFocus); 649 650 emscripten_set_touchstart_callback("#canvas", data, 0, Emscripten_HandleTouch); 651 emscripten_set_touchend_callback("#canvas", data, 0, Emscripten_HandleTouch); 652 emscripten_set_touchmove_callback("#canvas", data, 0, Emscripten_HandleTouch); 653 emscripten_set_touchcancel_callback("#canvas", data, 0, Emscripten_HandleTouch); 654 655 emscripten_set_pointerlockchange_callback("#document", data, 0, Emscripten_HandlePointerLockChange); 656 657 /* Keyboard events are awkward */ 658 keyElement = SDL_GetHint(SDL_HINT_EMSCRIPTEN_KEYBOARD_ELEMENT); 659 if (!keyElement) keyElement = "#window"; 660 661 emscripten_set_keydown_callback(keyElement, data, 0, Emscripten_HandleKey); 662 emscripten_set_keyup_callback(keyElement, data, 0, Emscripten_HandleKey); 663 emscripten_set_keypress_callback(keyElement, data, 0, Emscripten_HandleKeyPress); 664 665 emscripten_set_fullscreenchange_callback("#document", data, 0, Emscripten_HandleFullscreenChange); 666 667 emscripten_set_resize_callback("#window", data, 0, Emscripten_HandleResize); 668 669 emscripten_set_visibilitychange_callback(data, 0, Emscripten_HandleVisibilityChange); 670} 671 672void 673Emscripten_UnregisterEventHandlers(SDL_WindowData *data) 674{ 675 const char *target; 676 677 /* only works due to having one window */ 678 emscripten_set_mousemove_callback("#canvas", NULL, 0, NULL); 679 680 emscripten_set_mousedown_callback("#canvas", NULL, 0, NULL); 681 emscripten_set_mouseup_callback("#document", NULL, 0, NULL); 682 683 emscripten_set_mouseenter_callback("#canvas", NULL, 0, NULL); 684 emscripten_set_mouseleave_callback("#canvas", NULL, 0, NULL); 685 686 emscripten_set_wheel_callback("#canvas", NULL, 0, NULL); 687 688 emscripten_set_focus_callback("#window", NULL, 0, NULL); 689 emscripten_set_blur_callback("#window", NULL, 0, NULL); 690 691 emscripten_set_touchstart_callback("#canvas", NULL, 0, NULL); 692 emscripten_set_touchend_callback("#canvas", NULL, 0, NULL); 693 emscripten_set_touchmove_callback("#canvas", NULL, 0, NULL); 694 emscripten_set_touchcancel_callback("#canvas", NULL, 0, NULL); 695 696 emscripten_set_pointerlockchange_callback("#document", NULL, 0, NULL); 697 698 target = SDL_GetHint(SDL_HINT_EMSCRIPTEN_KEYBOARD_ELEMENT); 699 if (!target) { 700 target = "#window"; 701 } 702 703 emscripten_set_keydown_callback(target, NULL, 0, NULL); 704 emscripten_set_keyup_callback(target, NULL, 0, NULL); 705 emscripten_set_keypress_callback(target, NULL, 0, NULL); 706 707 emscripten_set_fullscreenchange_callback("#document", NULL, 0, NULL); 708 709 emscripten_set_resize_callback("#window", NULL, 0, NULL); 710 711 emscripten_set_visibilitychange_callback(NULL, 0, NULL); 712} 713 714#endif /* SDL_VIDEO_DRIVER_EMSCRIPTEN */ 715 716/* vi: set ts=4 sw=4 expandtab: */ 717[FILE END](C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.