mirror of
https://github.com/encounter/SDL.git
synced 2025-12-19 01:46:22 +00:00
Fixed crash if initialization of EGL failed but was tried again later.
The internal function SDL_EGL_LoadLibrary() did not delete and remove a mostly uninitialized data structure if loading the library first failed. A later try to use EGL then skipped initialization and assumed it was previously successful because the data structure now already existed. This led to at least one crash in the internal function SDL_EGL_ChooseConfig() because a NULL pointer was dereferenced to make a call to eglBindAPI().
This commit is contained in:
644
src/video/emscripten/SDL_emscriptenevents.c
Normal file
644
src/video/emscripten/SDL_emscriptenevents.c
Normal file
@@ -0,0 +1,644 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#if SDL_VIDEO_DRIVER_EMSCRIPTEN
|
||||
|
||||
#include <emscripten/html5.h>
|
||||
|
||||
#include "../../events/SDL_events_c.h"
|
||||
#include "../../events/SDL_keyboard_c.h"
|
||||
#include "../../events/SDL_touch_c.h"
|
||||
|
||||
#include "SDL_emscriptenevents.h"
|
||||
#include "SDL_emscriptenvideo.h"
|
||||
|
||||
#include "SDL_hints.h"
|
||||
|
||||
#define FULLSCREEN_MASK ( SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_FULLSCREEN )
|
||||
|
||||
/*
|
||||
.keyCode to scancode
|
||||
https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent
|
||||
https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode
|
||||
*/
|
||||
static const SDL_Scancode emscripten_scancode_table[] = {
|
||||
/* 0 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 1 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 2 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 3 */ SDL_SCANCODE_CANCEL,
|
||||
/* 4 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 5 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 6 */ SDL_SCANCODE_HELP,
|
||||
/* 7 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 8 */ SDL_SCANCODE_BACKSPACE,
|
||||
/* 9 */ SDL_SCANCODE_TAB,
|
||||
/* 10 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 11 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 12 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 13 */ SDL_SCANCODE_RETURN,
|
||||
/* 14 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 15 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 16 */ SDL_SCANCODE_LSHIFT,
|
||||
/* 17 */ SDL_SCANCODE_LCTRL,
|
||||
/* 18 */ SDL_SCANCODE_LALT,
|
||||
/* 19 */ SDL_SCANCODE_PAUSE,
|
||||
/* 20 */ SDL_SCANCODE_CAPSLOCK,
|
||||
/* 21 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 22 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 23 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 24 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 25 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 26 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 27 */ SDL_SCANCODE_ESCAPE,
|
||||
/* 28 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 29 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 30 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 31 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 32 */ SDL_SCANCODE_SPACE,
|
||||
/* 33 */ SDL_SCANCODE_PAGEUP,
|
||||
/* 34 */ SDL_SCANCODE_PAGEDOWN,
|
||||
/* 35 */ SDL_SCANCODE_END,
|
||||
/* 36 */ SDL_SCANCODE_HOME,
|
||||
/* 37 */ SDL_SCANCODE_LEFT,
|
||||
/* 38 */ SDL_SCANCODE_UP,
|
||||
/* 39 */ SDL_SCANCODE_RIGHT,
|
||||
/* 40 */ SDL_SCANCODE_DOWN,
|
||||
/* 41 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 42 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 43 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 44 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 45 */ SDL_SCANCODE_INSERT,
|
||||
/* 46 */ SDL_SCANCODE_DELETE,
|
||||
/* 47 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 48 */ SDL_SCANCODE_0,
|
||||
/* 49 */ SDL_SCANCODE_1,
|
||||
/* 50 */ SDL_SCANCODE_2,
|
||||
/* 51 */ SDL_SCANCODE_3,
|
||||
/* 52 */ SDL_SCANCODE_4,
|
||||
/* 53 */ SDL_SCANCODE_5,
|
||||
/* 54 */ SDL_SCANCODE_6,
|
||||
/* 55 */ SDL_SCANCODE_7,
|
||||
/* 56 */ SDL_SCANCODE_8,
|
||||
/* 57 */ SDL_SCANCODE_9,
|
||||
/* 58 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 59 */ SDL_SCANCODE_SEMICOLON,
|
||||
/* 60 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 61 */ SDL_SCANCODE_EQUALS,
|
||||
/* 62 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 63 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 64 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 65 */ SDL_SCANCODE_A,
|
||||
/* 66 */ SDL_SCANCODE_B,
|
||||
/* 67 */ SDL_SCANCODE_C,
|
||||
/* 68 */ SDL_SCANCODE_D,
|
||||
/* 69 */ SDL_SCANCODE_E,
|
||||
/* 70 */ SDL_SCANCODE_F,
|
||||
/* 71 */ SDL_SCANCODE_G,
|
||||
/* 72 */ SDL_SCANCODE_H,
|
||||
/* 73 */ SDL_SCANCODE_I,
|
||||
/* 74 */ SDL_SCANCODE_J,
|
||||
/* 75 */ SDL_SCANCODE_K,
|
||||
/* 76 */ SDL_SCANCODE_L,
|
||||
/* 77 */ SDL_SCANCODE_M,
|
||||
/* 78 */ SDL_SCANCODE_N,
|
||||
/* 79 */ SDL_SCANCODE_O,
|
||||
/* 80 */ SDL_SCANCODE_P,
|
||||
/* 81 */ SDL_SCANCODE_Q,
|
||||
/* 82 */ SDL_SCANCODE_R,
|
||||
/* 83 */ SDL_SCANCODE_S,
|
||||
/* 84 */ SDL_SCANCODE_T,
|
||||
/* 85 */ SDL_SCANCODE_U,
|
||||
/* 86 */ SDL_SCANCODE_V,
|
||||
/* 87 */ SDL_SCANCODE_W,
|
||||
/* 88 */ SDL_SCANCODE_X,
|
||||
/* 89 */ SDL_SCANCODE_Y,
|
||||
/* 90 */ SDL_SCANCODE_Z,
|
||||
/* 91 */ SDL_SCANCODE_LGUI,
|
||||
/* 92 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 93 */ SDL_SCANCODE_APPLICATION,
|
||||
/* 94 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 95 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 96 */ SDL_SCANCODE_KP_0,
|
||||
/* 97 */ SDL_SCANCODE_KP_1,
|
||||
/* 98 */ SDL_SCANCODE_KP_2,
|
||||
/* 99 */ SDL_SCANCODE_KP_3,
|
||||
/* 100 */ SDL_SCANCODE_KP_4,
|
||||
/* 101 */ SDL_SCANCODE_KP_5,
|
||||
/* 102 */ SDL_SCANCODE_KP_6,
|
||||
/* 103 */ SDL_SCANCODE_KP_7,
|
||||
/* 104 */ SDL_SCANCODE_KP_8,
|
||||
/* 105 */ SDL_SCANCODE_KP_9,
|
||||
/* 106 */ SDL_SCANCODE_KP_MULTIPLY,
|
||||
/* 107 */ SDL_SCANCODE_KP_PLUS,
|
||||
/* 108 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 109 */ SDL_SCANCODE_KP_MINUS,
|
||||
/* 110 */ SDL_SCANCODE_KP_PERIOD,
|
||||
/* 111 */ SDL_SCANCODE_KP_DIVIDE,
|
||||
/* 112 */ SDL_SCANCODE_F1,
|
||||
/* 113 */ SDL_SCANCODE_F2,
|
||||
/* 114 */ SDL_SCANCODE_F3,
|
||||
/* 115 */ SDL_SCANCODE_F4,
|
||||
/* 116 */ SDL_SCANCODE_F5,
|
||||
/* 117 */ SDL_SCANCODE_F6,
|
||||
/* 118 */ SDL_SCANCODE_F7,
|
||||
/* 119 */ SDL_SCANCODE_F8,
|
||||
/* 120 */ SDL_SCANCODE_F9,
|
||||
/* 121 */ SDL_SCANCODE_F10,
|
||||
/* 122 */ SDL_SCANCODE_F11,
|
||||
/* 123 */ SDL_SCANCODE_F12,
|
||||
/* 124 */ SDL_SCANCODE_F13,
|
||||
/* 125 */ SDL_SCANCODE_F14,
|
||||
/* 126 */ SDL_SCANCODE_F15,
|
||||
/* 127 */ SDL_SCANCODE_F16,
|
||||
/* 128 */ SDL_SCANCODE_F17,
|
||||
/* 129 */ SDL_SCANCODE_F18,
|
||||
/* 130 */ SDL_SCANCODE_F19,
|
||||
/* 131 */ SDL_SCANCODE_F20,
|
||||
/* 132 */ SDL_SCANCODE_F21,
|
||||
/* 133 */ SDL_SCANCODE_F22,
|
||||
/* 134 */ SDL_SCANCODE_F23,
|
||||
/* 135 */ SDL_SCANCODE_F24,
|
||||
/* 136 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 137 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 138 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 139 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 140 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 141 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 142 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 143 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 144 */ SDL_SCANCODE_NUMLOCKCLEAR,
|
||||
/* 145 */ SDL_SCANCODE_SCROLLLOCK,
|
||||
/* 146 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 147 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 148 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 149 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 150 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 151 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 152 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 153 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 154 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 155 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 156 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 157 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 158 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 159 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 160 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 161 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 162 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 163 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 164 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 165 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 166 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 167 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 168 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 169 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 170 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 171 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 172 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 173 */ SDL_SCANCODE_MINUS, /*FX*/
|
||||
/* 174 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 175 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 176 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 177 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 178 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 179 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 180 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 181 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 182 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 183 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 184 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 185 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 186 */ SDL_SCANCODE_SEMICOLON, /*IE, Chrome, D3E legacy*/
|
||||
/* 187 */ SDL_SCANCODE_EQUALS, /*IE, Chrome, D3E legacy*/
|
||||
/* 188 */ SDL_SCANCODE_COMMA,
|
||||
/* 189 */ SDL_SCANCODE_MINUS, /*IE, Chrome, D3E legacy*/
|
||||
/* 190 */ SDL_SCANCODE_PERIOD,
|
||||
/* 191 */ SDL_SCANCODE_SLASH,
|
||||
/* 192 */ SDL_SCANCODE_GRAVE, /*FX, D3E legacy (SDL_SCANCODE_APOSTROPHE in IE/Chrome)*/
|
||||
/* 193 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 194 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 195 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 196 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 197 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 198 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 199 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 200 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 201 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 202 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 203 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 204 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 205 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 206 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 207 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 208 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 209 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 210 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 211 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 212 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 213 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 214 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 215 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 216 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 217 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 218 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 219 */ SDL_SCANCODE_LEFTBRACKET,
|
||||
/* 220 */ SDL_SCANCODE_BACKSLASH,
|
||||
/* 221 */ SDL_SCANCODE_RIGHTBRACKET,
|
||||
/* 222 */ SDL_SCANCODE_APOSTROPHE, /*FX, D3E legacy*/
|
||||
};
|
||||
|
||||
|
||||
/* "borrowed" from SDL_windowsevents.c */
|
||||
int
|
||||
Emscripten_ConvertUTF32toUTF8(Uint32 codepoint, char * text)
|
||||
{
|
||||
if (codepoint <= 0x7F) {
|
||||
text[0] = (char) codepoint;
|
||||
text[1] = '\0';
|
||||
} else if (codepoint <= 0x7FF) {
|
||||
text[0] = 0xC0 | (char) ((codepoint >> 6) & 0x1F);
|
||||
text[1] = 0x80 | (char) (codepoint & 0x3F);
|
||||
text[2] = '\0';
|
||||
} else if (codepoint <= 0xFFFF) {
|
||||
text[0] = 0xE0 | (char) ((codepoint >> 12) & 0x0F);
|
||||
text[1] = 0x80 | (char) ((codepoint >> 6) & 0x3F);
|
||||
text[2] = 0x80 | (char) (codepoint & 0x3F);
|
||||
text[3] = '\0';
|
||||
} else if (codepoint <= 0x10FFFF) {
|
||||
text[0] = 0xF0 | (char) ((codepoint >> 18) & 0x0F);
|
||||
text[1] = 0x80 | (char) ((codepoint >> 12) & 0x3F);
|
||||
text[2] = 0x80 | (char) ((codepoint >> 6) & 0x3F);
|
||||
text[3] = 0x80 | (char) (codepoint & 0x3F);
|
||||
text[4] = '\0';
|
||||
} else {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
EM_BOOL
|
||||
Emscripten_HandleMouseMove(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData)
|
||||
{
|
||||
SDL_WindowData *window_data = userData;
|
||||
int mx = mouseEvent->canvasX, my = mouseEvent->canvasY;
|
||||
EmscriptenPointerlockChangeEvent pointerlock_status;
|
||||
|
||||
/* check for pointer lock */
|
||||
emscripten_get_pointerlock_status(&pointerlock_status);
|
||||
|
||||
if (pointerlock_status.isActive) {
|
||||
mx = mouseEvent->movementX;
|
||||
my = mouseEvent->movementY;
|
||||
}
|
||||
|
||||
/* rescale (in case canvas is being scaled)*/
|
||||
double client_w, client_h;
|
||||
emscripten_get_element_css_size(NULL, &client_w, &client_h);
|
||||
|
||||
mx = mx * (window_data->window->w / (client_w * window_data->pixel_ratio));
|
||||
my = my * (window_data->window->h / (client_h * window_data->pixel_ratio));
|
||||
|
||||
SDL_SendMouseMotion(window_data->window, 0, pointerlock_status.isActive, mx, my);
|
||||
return 0;
|
||||
}
|
||||
|
||||
EM_BOOL
|
||||
Emscripten_HandleMouseButton(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData)
|
||||
{
|
||||
SDL_WindowData *window_data = userData;
|
||||
uint32_t sdl_button;
|
||||
switch (mouseEvent->button) {
|
||||
case 0:
|
||||
sdl_button = SDL_BUTTON_LEFT;
|
||||
break;
|
||||
case 1:
|
||||
sdl_button = SDL_BUTTON_MIDDLE;
|
||||
break;
|
||||
case 2:
|
||||
sdl_button = SDL_BUTTON_RIGHT;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
SDL_SendMouseButton(window_data->window, 0, eventType == EMSCRIPTEN_EVENT_MOUSEDOWN ? SDL_PRESSED : SDL_RELEASED, sdl_button);
|
||||
return 1;
|
||||
}
|
||||
|
||||
EM_BOOL
|
||||
Emscripten_HandleMouseFocus(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData)
|
||||
{
|
||||
SDL_WindowData *window_data = userData;
|
||||
SDL_SendWindowEvent(window_data->window, eventType == EMSCRIPTEN_EVENT_MOUSEENTER ? SDL_WINDOWEVENT_ENTER : SDL_WINDOWEVENT_LEAVE, 0, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
EM_BOOL
|
||||
Emscripten_HandleWheel(int eventType, const EmscriptenWheelEvent *wheelEvent, void *userData)
|
||||
{
|
||||
SDL_WindowData *window_data = userData;
|
||||
SDL_SendMouseWheel(window_data->window, 0, wheelEvent->deltaX, -wheelEvent->deltaY, SDL_MOUSEWHEEL_NORMAL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
EM_BOOL
|
||||
Emscripten_HandleFocus(int eventType, const EmscriptenFocusEvent *wheelEvent, void *userData)
|
||||
{
|
||||
SDL_WindowData *window_data = userData;
|
||||
SDL_SendWindowEvent(window_data->window, eventType == EMSCRIPTEN_EVENT_FOCUS ? SDL_WINDOWEVENT_FOCUS_GAINED : SDL_WINDOWEVENT_FOCUS_LOST, 0, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
EM_BOOL
|
||||
Emscripten_HandleTouch(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData)
|
||||
{
|
||||
SDL_WindowData *window_data = userData;
|
||||
int i;
|
||||
|
||||
SDL_TouchID deviceId = 1;
|
||||
if (SDL_AddTouch(deviceId, "") < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < touchEvent->numTouches; i++) {
|
||||
SDL_FingerID id;
|
||||
float x, y;
|
||||
|
||||
if (!touchEvent->touches[i].isChanged)
|
||||
continue;
|
||||
|
||||
id = touchEvent->touches[i].identifier;
|
||||
x = touchEvent->touches[i].canvasX / (float)window_data->windowed_width;
|
||||
y = touchEvent->touches[i].canvasY / (float)window_data->windowed_height;
|
||||
|
||||
if (eventType == EMSCRIPTEN_EVENT_TOUCHMOVE) {
|
||||
SDL_SendTouchMotion(deviceId, id, x, y, 1.0f);
|
||||
} else if (eventType == EMSCRIPTEN_EVENT_TOUCHSTART) {
|
||||
SDL_SendTouch(deviceId, id, SDL_TRUE, x, y, 1.0f);
|
||||
} else {
|
||||
SDL_SendTouch(deviceId, id, SDL_FALSE, x, y, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
EM_BOOL
|
||||
Emscripten_HandleKey(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData)
|
||||
{
|
||||
Uint32 scancode;
|
||||
|
||||
/* .keyCode is deprecated, but still the most reliable way to get keys */
|
||||
if (keyEvent->keyCode < SDL_arraysize(emscripten_scancode_table)) {
|
||||
scancode = emscripten_scancode_table[keyEvent->keyCode];
|
||||
|
||||
if (scancode != SDL_SCANCODE_UNKNOWN) {
|
||||
|
||||
if (keyEvent->location == DOM_KEY_LOCATION_RIGHT) {
|
||||
switch (scancode) {
|
||||
case SDL_SCANCODE_LSHIFT:
|
||||
scancode = SDL_SCANCODE_RSHIFT;
|
||||
break;
|
||||
case SDL_SCANCODE_LCTRL:
|
||||
scancode = SDL_SCANCODE_RCTRL;
|
||||
break;
|
||||
case SDL_SCANCODE_LALT:
|
||||
scancode = SDL_SCANCODE_RALT;
|
||||
break;
|
||||
case SDL_SCANCODE_LGUI:
|
||||
scancode = SDL_SCANCODE_RGUI;
|
||||
break;
|
||||
}
|
||||
}
|
||||
SDL_SendKeyboardKey(eventType == EMSCRIPTEN_EVENT_KEYDOWN ?
|
||||
SDL_PRESSED : SDL_RELEASED, scancode);
|
||||
}
|
||||
}
|
||||
|
||||
/* if we prevent keydown, we won't get keypress
|
||||
* also we need to ALWAYS prevent backspace and tab otherwise chrome takes action and does bad navigation UX
|
||||
*/
|
||||
return SDL_GetEventState(SDL_TEXTINPUT) != SDL_ENABLE || eventType != EMSCRIPTEN_EVENT_KEYDOWN
|
||||
|| keyEvent->keyCode == 8 /* backspace */ || keyEvent->keyCode == 9 /* tab */;
|
||||
}
|
||||
|
||||
EM_BOOL
|
||||
Emscripten_HandleKeyPress(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData)
|
||||
{
|
||||
char text[5];
|
||||
if (Emscripten_ConvertUTF32toUTF8(keyEvent->charCode, text)) {
|
||||
SDL_SendKeyboardText(text);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
EM_BOOL
|
||||
Emscripten_HandleFullscreenChange(int eventType, const EmscriptenFullscreenChangeEvent *fullscreenChangeEvent, void *userData)
|
||||
{
|
||||
/*make sure this is actually our element going fullscreen*/
|
||||
if(SDL_strcmp(fullscreenChangeEvent->id, "SDLFullscreenElement") != 0)
|
||||
return 0;
|
||||
|
||||
SDL_WindowData *window_data = userData;
|
||||
if(fullscreenChangeEvent->isFullscreen)
|
||||
{
|
||||
SDL_bool is_desktop_fullscreen;
|
||||
window_data->window->flags |= window_data->requested_fullscreen_mode;
|
||||
|
||||
if(!window_data->requested_fullscreen_mode)
|
||||
window_data->window->flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; /*we didn't reqest fullscreen*/
|
||||
|
||||
window_data->requested_fullscreen_mode = 0;
|
||||
|
||||
is_desktop_fullscreen = (window_data->window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||
|
||||
/*update size*/
|
||||
if(window_data->window->flags & SDL_WINDOW_RESIZABLE || is_desktop_fullscreen)
|
||||
{
|
||||
emscripten_set_canvas_size(fullscreenChangeEvent->screenWidth, fullscreenChangeEvent->screenHeight);
|
||||
SDL_SendWindowEvent(window_data->window, SDL_WINDOWEVENT_RESIZED, fullscreenChangeEvent->screenWidth, fullscreenChangeEvent->screenHeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*preserve ratio*/
|
||||
double w = window_data->window->w;
|
||||
double h = window_data->window->h;
|
||||
double factor = SDL_min(fullscreenChangeEvent->screenWidth / w, fullscreenChangeEvent->screenHeight / h);
|
||||
emscripten_set_element_css_size(NULL, w * factor, h * factor);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EM_ASM({
|
||||
//un-reparent canvas (similar to Module.requestFullscreen)
|
||||
var canvas = Module['canvas'];
|
||||
if(canvas.parentNode.id == "SDLFullscreenElement") {
|
||||
var canvasContainer = canvas.parentNode;
|
||||
canvasContainer.parentNode.insertBefore(canvas, canvasContainer);
|
||||
canvasContainer.parentNode.removeChild(canvasContainer);
|
||||
}
|
||||
});
|
||||
double unscaled_w = window_data->windowed_width / window_data->pixel_ratio;
|
||||
double unscaled_h = window_data->windowed_height / window_data->pixel_ratio;
|
||||
emscripten_set_canvas_size(window_data->windowed_width, window_data->windowed_height);
|
||||
|
||||
if (!window_data->external_size && window_data->pixel_ratio != 1.0f) {
|
||||
emscripten_set_element_css_size(NULL, unscaled_w, unscaled_h);
|
||||
}
|
||||
|
||||
SDL_SendWindowEvent(window_data->window, SDL_WINDOWEVENT_RESIZED, unscaled_w, unscaled_h);
|
||||
|
||||
window_data->window->flags &= ~FULLSCREEN_MASK;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EM_BOOL
|
||||
Emscripten_HandleResize(int eventType, const EmscriptenUiEvent *uiEvent, void *userData)
|
||||
{
|
||||
SDL_WindowData *window_data = userData;
|
||||
if(window_data->window->flags & FULLSCREEN_MASK)
|
||||
{
|
||||
SDL_bool is_desktop_fullscreen = (window_data->window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||
|
||||
if(window_data->window->flags & SDL_WINDOW_RESIZABLE || is_desktop_fullscreen)
|
||||
{
|
||||
emscripten_set_canvas_size(uiEvent->windowInnerWidth * window_data->pixel_ratio, uiEvent->windowInnerHeight * window_data->pixel_ratio);
|
||||
SDL_SendWindowEvent(window_data->window, SDL_WINDOWEVENT_RESIZED, uiEvent->windowInnerWidth, uiEvent->windowInnerHeight);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* this will only work if the canvas size is set through css */
|
||||
if(window_data->window->flags & SDL_WINDOW_RESIZABLE)
|
||||
{
|
||||
double w = window_data->window->w;
|
||||
double h = window_data->window->h;
|
||||
|
||||
if(window_data->external_size) {
|
||||
emscripten_get_element_css_size(NULL, &w, &h);
|
||||
}
|
||||
|
||||
emscripten_set_canvas_size(w * window_data->pixel_ratio, h * window_data->pixel_ratio);
|
||||
|
||||
/* set_canvas_size unsets this */
|
||||
if (!window_data->external_size && window_data->pixel_ratio != 1.0f) {
|
||||
emscripten_set_element_css_size(NULL, w, h);
|
||||
}
|
||||
|
||||
SDL_SendWindowEvent(window_data->window, SDL_WINDOWEVENT_RESIZED, w, h);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EM_BOOL
|
||||
Emscripten_HandleVisibilityChange(int eventType, const EmscriptenVisibilityChangeEvent *visEvent, void *userData)
|
||||
{
|
||||
SDL_WindowData *window_data = userData;
|
||||
SDL_SendWindowEvent(window_data->window, visEvent->hidden ? SDL_WINDOWEVENT_HIDDEN : SDL_WINDOWEVENT_SHOWN, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
Emscripten_RegisterEventHandlers(SDL_WindowData *data)
|
||||
{
|
||||
/* There is only one window and that window is the canvas */
|
||||
emscripten_set_mousemove_callback("#canvas", data, 0, Emscripten_HandleMouseMove);
|
||||
|
||||
emscripten_set_mousedown_callback("#canvas", data, 0, Emscripten_HandleMouseButton);
|
||||
emscripten_set_mouseup_callback("#canvas", data, 0, Emscripten_HandleMouseButton);
|
||||
|
||||
emscripten_set_mouseenter_callback("#canvas", data, 0, Emscripten_HandleMouseFocus);
|
||||
emscripten_set_mouseleave_callback("#canvas", data, 0, Emscripten_HandleMouseFocus);
|
||||
|
||||
emscripten_set_wheel_callback("#canvas", data, 0, Emscripten_HandleWheel);
|
||||
|
||||
emscripten_set_focus_callback("#canvas", data, 0, Emscripten_HandleFocus);
|
||||
emscripten_set_blur_callback("#canvas", data, 0, Emscripten_HandleFocus);
|
||||
|
||||
emscripten_set_touchstart_callback("#canvas", data, 0, Emscripten_HandleTouch);
|
||||
emscripten_set_touchend_callback("#canvas", data, 0, Emscripten_HandleTouch);
|
||||
emscripten_set_touchmove_callback("#canvas", data, 0, Emscripten_HandleTouch);
|
||||
emscripten_set_touchcancel_callback("#canvas", data, 0, Emscripten_HandleTouch);
|
||||
|
||||
/* Keyboard events are awkward */
|
||||
const char *keyElement = SDL_GetHint(SDL_HINT_EMSCRIPTEN_KEYBOARD_ELEMENT);
|
||||
if (!keyElement) keyElement = "#window";
|
||||
|
||||
emscripten_set_keydown_callback(keyElement, data, 0, Emscripten_HandleKey);
|
||||
emscripten_set_keyup_callback(keyElement, data, 0, Emscripten_HandleKey);
|
||||
emscripten_set_keypress_callback(keyElement, data, 0, Emscripten_HandleKeyPress);
|
||||
|
||||
emscripten_set_fullscreenchange_callback("#document", data, 0, Emscripten_HandleFullscreenChange);
|
||||
|
||||
emscripten_set_resize_callback("#window", data, 0, Emscripten_HandleResize);
|
||||
|
||||
emscripten_set_visibilitychange_callback(data, 0, Emscripten_HandleVisibilityChange);
|
||||
}
|
||||
|
||||
void
|
||||
Emscripten_UnregisterEventHandlers(SDL_WindowData *data)
|
||||
{
|
||||
/* only works due to having one window */
|
||||
emscripten_set_mousemove_callback("#canvas", NULL, 0, NULL);
|
||||
|
||||
emscripten_set_mousedown_callback("#canvas", NULL, 0, NULL);
|
||||
emscripten_set_mouseup_callback("#canvas", NULL, 0, NULL);
|
||||
|
||||
emscripten_set_mouseenter_callback("#canvas", NULL, 0, NULL);
|
||||
emscripten_set_mouseleave_callback("#canvas", NULL, 0, NULL);
|
||||
|
||||
emscripten_set_wheel_callback("#canvas", NULL, 0, NULL);
|
||||
|
||||
emscripten_set_focus_callback("#canvas", NULL, 0, NULL);
|
||||
emscripten_set_blur_callback("#canvas", NULL, 0, NULL);
|
||||
|
||||
emscripten_set_touchstart_callback("#canvas", NULL, 0, NULL);
|
||||
emscripten_set_touchend_callback("#canvas", NULL, 0, NULL);
|
||||
emscripten_set_touchmove_callback("#canvas", NULL, 0, NULL);
|
||||
emscripten_set_touchcancel_callback("#canvas", NULL, 0, NULL);
|
||||
|
||||
const char *target = SDL_GetHint(SDL_HINT_EMSCRIPTEN_KEYBOARD_ELEMENT);
|
||||
if (!target) {
|
||||
target = "#window";
|
||||
}
|
||||
|
||||
emscripten_set_keydown_callback(target, NULL, 0, NULL);
|
||||
emscripten_set_keyup_callback(target, NULL, 0, NULL);
|
||||
|
||||
emscripten_set_keypress_callback(target, NULL, 0, NULL);
|
||||
|
||||
emscripten_set_fullscreenchange_callback("#document", NULL, 0, NULL);
|
||||
|
||||
emscripten_set_resize_callback("#window", NULL, 0, NULL);
|
||||
|
||||
emscripten_set_visibilitychange_callback(NULL, 0, NULL);
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_EMSCRIPTEN */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
36
src/video/emscripten/SDL_emscriptenevents.h
Normal file
36
src/video/emscripten/SDL_emscriptenevents.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _SDL_emscriptenevents_h
|
||||
#define _SDL_emscriptenevents_h
|
||||
|
||||
#include "SDL_emscriptenvideo.h"
|
||||
|
||||
extern void
|
||||
Emscripten_RegisterEventHandlers(SDL_WindowData *data);
|
||||
|
||||
extern void
|
||||
Emscripten_UnregisterEventHandlers(SDL_WindowData *data);
|
||||
#endif /* _SDL_emscriptenevents_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
136
src/video/emscripten/SDL_emscriptenframebuffer.c
Normal file
136
src/video/emscripten/SDL_emscriptenframebuffer.c
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#if SDL_VIDEO_DRIVER_EMSCRIPTEN
|
||||
|
||||
#include "SDL_emscriptenvideo.h"
|
||||
#include "SDL_emscriptenframebuffer.h"
|
||||
|
||||
|
||||
int Emscripten_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch)
|
||||
{
|
||||
SDL_Surface *surface;
|
||||
const Uint32 surface_format = SDL_PIXELFORMAT_BGR888;
|
||||
int w, h;
|
||||
int bpp;
|
||||
Uint32 Rmask, Gmask, Bmask, Amask;
|
||||
|
||||
/* Free the old framebuffer surface */
|
||||
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
||||
surface = data->surface;
|
||||
SDL_FreeSurface(surface);
|
||||
|
||||
/* Create a new one */
|
||||
SDL_PixelFormatEnumToMasks(surface_format, &bpp, &Rmask, &Gmask, &Bmask, &Amask);
|
||||
SDL_GetWindowSize(window, &w, &h);
|
||||
|
||||
surface = SDL_CreateRGBSurface(0, w, h, bpp, Rmask, Gmask, Bmask, Amask);
|
||||
if (!surface) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Save the info and return! */
|
||||
data->surface = surface;
|
||||
*format = surface_format;
|
||||
*pixels = surface->pixels;
|
||||
*pitch = surface->pitch;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Emscripten_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects)
|
||||
{
|
||||
SDL_Surface *surface;
|
||||
|
||||
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
||||
surface = data->surface;
|
||||
if (!surface) {
|
||||
return SDL_SetError("Couldn't find framebuffer surface for window");
|
||||
}
|
||||
|
||||
/* Send the data to the display */
|
||||
|
||||
EM_ASM_INT({
|
||||
//TODO: don't create context every update
|
||||
var ctx = Module['canvas'].getContext('2d');
|
||||
|
||||
//library_sdl.js SDL_UnlockSurface
|
||||
var image = ctx.createImageData($0, $1);
|
||||
var data = image.data;
|
||||
var src = $2 >> 2;
|
||||
var dst = 0;
|
||||
var isScreen = true;
|
||||
var num;
|
||||
if (typeof CanvasPixelArray !== 'undefined' && data instanceof CanvasPixelArray) {
|
||||
// IE10/IE11: ImageData objects are backed by the deprecated CanvasPixelArray,
|
||||
// not UInt8ClampedArray. These don't have buffers, so we need to revert
|
||||
// to copying a byte at a time. We do the undefined check because modern
|
||||
// browsers do not define CanvasPixelArray anymore.
|
||||
num = data.length;
|
||||
while (dst < num) {
|
||||
var val = HEAP32[src]; // This is optimized. Instead, we could do {{{ makeGetValue('buffer', 'dst', 'i32') }}};
|
||||
data[dst ] = val & 0xff;
|
||||
data[dst+1] = (val >> 8) & 0xff;
|
||||
data[dst+2] = (val >> 16) & 0xff;
|
||||
data[dst+3] = isScreen ? 0xff : ((val >> 24) & 0xff);
|
||||
src++;
|
||||
dst += 4;
|
||||
}
|
||||
} else {
|
||||
var data32 = new Uint32Array(data.buffer);
|
||||
num = data32.length;
|
||||
if (isScreen) {
|
||||
while (dst < num) {
|
||||
// HEAP32[src++] is an optimization. Instead, we could do {{{ makeGetValue('buffer', 'dst', 'i32') }}};
|
||||
data32[dst++] = HEAP32[src++] | 0xff000000;
|
||||
}
|
||||
} else {
|
||||
while (dst < num) {
|
||||
data32[dst++] = HEAP32[src++];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx.putImageData(image, 0, 0);
|
||||
return 0;
|
||||
}, surface->w, surface->h, surface->pixels);
|
||||
|
||||
/*if (SDL_getenv("SDL_VIDEO_Emscripten_SAVE_FRAMES")) {
|
||||
static int frame_number = 0;
|
||||
char file[128];
|
||||
SDL_snprintf(file, sizeof(file), "SDL_window%d-%8.8d.bmp",
|
||||
SDL_GetWindowID(window), ++frame_number);
|
||||
SDL_SaveBMP(surface, file);
|
||||
}*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Emscripten_DestroyWindowFramebuffer(_THIS, SDL_Window * window)
|
||||
{
|
||||
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
||||
|
||||
SDL_FreeSurface(data->surface);
|
||||
data->surface = NULL;
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_EMSCRIPTEN */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
32
src/video/emscripten/SDL_emscriptenframebuffer.h
Normal file
32
src/video/emscripten/SDL_emscriptenframebuffer.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifndef _SDL_emscriptenframebuffer_h
|
||||
#define _SDL_emscriptenframebuffer_h
|
||||
|
||||
extern int Emscripten_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch);
|
||||
extern int Emscripten_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects);
|
||||
extern void Emscripten_DestroyWindowFramebuffer(_THIS, SDL_Window * window);
|
||||
|
||||
#endif /* _SDL_emscriptenframebuffer_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
232
src/video/emscripten/SDL_emscriptenmouse.c
Normal file
232
src/video/emscripten/SDL_emscriptenmouse.c
Normal file
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#if SDL_VIDEO_DRIVER_EMSCRIPTEN
|
||||
|
||||
#include <emscripten/emscripten.h>
|
||||
#include <emscripten/html5.h>
|
||||
|
||||
#include "SDL_emscriptenmouse.h"
|
||||
|
||||
#include "../../events/SDL_mouse_c.h"
|
||||
#include "SDL_assert.h"
|
||||
|
||||
|
||||
static SDL_Cursor*
|
||||
Emscripten_CreateDefaultCursor()
|
||||
{
|
||||
SDL_Cursor* cursor;
|
||||
Emscripten_CursorData *curdata;
|
||||
|
||||
cursor = SDL_calloc(1, sizeof(SDL_Cursor));
|
||||
if (cursor) {
|
||||
curdata = (Emscripten_CursorData *) SDL_calloc(1, sizeof(*curdata));
|
||||
if (!curdata) {
|
||||
SDL_OutOfMemory();
|
||||
SDL_free(cursor);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
curdata->system_cursor = "default";
|
||||
cursor->driverdata = curdata;
|
||||
}
|
||||
else {
|
||||
SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
return cursor;
|
||||
}
|
||||
|
||||
static SDL_Cursor*
|
||||
Emscripten_CreateCursor(SDL_Surface* sruface, int hot_x, int hot_y)
|
||||
{
|
||||
return Emscripten_CreateDefaultCursor();
|
||||
}
|
||||
|
||||
static SDL_Cursor*
|
||||
Emscripten_CreateSystemCursor(SDL_SystemCursor id)
|
||||
{
|
||||
SDL_Cursor *cursor;
|
||||
Emscripten_CursorData *curdata;
|
||||
const char *cursor_name = NULL;
|
||||
|
||||
switch(id) {
|
||||
case SDL_SYSTEM_CURSOR_ARROW:
|
||||
cursor_name = "default";
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_IBEAM:
|
||||
cursor_name = "text";
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_WAIT:
|
||||
cursor_name = "wait";
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_CROSSHAIR:
|
||||
cursor_name = "crosshair";
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_WAITARROW:
|
||||
cursor_name = "progress";
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_SIZENWSE:
|
||||
cursor_name = "nwse-resize";
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_SIZENESW:
|
||||
cursor_name = "nesw-resize";
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_SIZEWE:
|
||||
cursor_name = "ew-resize";
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_SIZENS:
|
||||
cursor_name = "ns-resize";
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_SIZEALL:
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_NO:
|
||||
cursor_name = "not-allowed";
|
||||
break;
|
||||
case SDL_SYSTEM_CURSOR_HAND:
|
||||
cursor_name = "pointer";
|
||||
break;
|
||||
default:
|
||||
SDL_assert(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cursor = (SDL_Cursor *) SDL_calloc(1, sizeof(*cursor));
|
||||
if (!cursor) {
|
||||
SDL_OutOfMemory();
|
||||
return NULL;
|
||||
}
|
||||
curdata = (Emscripten_CursorData *) SDL_calloc(1, sizeof(*curdata));
|
||||
if (!curdata) {
|
||||
SDL_OutOfMemory();
|
||||
SDL_free(cursor);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
curdata->system_cursor = cursor_name;
|
||||
cursor->driverdata = curdata;
|
||||
|
||||
return cursor;
|
||||
}
|
||||
|
||||
static void
|
||||
Emscripten_FreeCursor(SDL_Cursor* cursor)
|
||||
{
|
||||
Emscripten_CursorData *curdata;
|
||||
if (cursor) {
|
||||
curdata = (Emscripten_CursorData *) cursor->driverdata;
|
||||
|
||||
if (curdata != NULL) {
|
||||
SDL_free(cursor->driverdata);
|
||||
}
|
||||
|
||||
SDL_free(cursor);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
Emscripten_ShowCursor(SDL_Cursor* cursor)
|
||||
{
|
||||
Emscripten_CursorData *curdata;
|
||||
if (SDL_GetMouseFocus() != NULL) {
|
||||
if(cursor && cursor->driverdata) {
|
||||
curdata = (Emscripten_CursorData *) cursor->driverdata;
|
||||
|
||||
if(curdata->system_cursor) {
|
||||
EM_ASM_INT({
|
||||
if (Module['canvas']) {
|
||||
Module['canvas'].style['cursor'] = Module['Pointer_stringify']($0);
|
||||
}
|
||||
return 0;
|
||||
}, curdata->system_cursor);
|
||||
}
|
||||
}
|
||||
else {
|
||||
EM_ASM(
|
||||
if (Module['canvas']) {
|
||||
Module['canvas'].style['cursor'] = 'none';
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
Emscripten_WarpMouse(SDL_Window* window, int x, int y)
|
||||
{
|
||||
SDL_Unsupported();
|
||||
}
|
||||
|
||||
static int
|
||||
Emscripten_SetRelativeMouseMode(SDL_bool enabled)
|
||||
{
|
||||
/* TODO: pointer lock isn't actually enabled yet */
|
||||
if(enabled) {
|
||||
if(emscripten_request_pointerlock(NULL, 1) >= EMSCRIPTEN_RESULT_SUCCESS) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if(emscripten_exit_pointerlock() >= EMSCRIPTEN_RESULT_SUCCESS) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
Emscripten_InitMouse()
|
||||
{
|
||||
SDL_Mouse* mouse = SDL_GetMouse();
|
||||
|
||||
mouse->CreateCursor = Emscripten_CreateCursor;
|
||||
mouse->ShowCursor = Emscripten_ShowCursor;
|
||||
mouse->FreeCursor = Emscripten_FreeCursor;
|
||||
mouse->WarpMouse = Emscripten_WarpMouse;
|
||||
mouse->CreateSystemCursor = Emscripten_CreateSystemCursor;
|
||||
mouse->SetRelativeMouseMode = Emscripten_SetRelativeMouseMode;
|
||||
|
||||
SDL_SetDefaultCursor(Emscripten_CreateDefaultCursor());
|
||||
}
|
||||
|
||||
void
|
||||
Emscripten_FiniMouse()
|
||||
{
|
||||
SDL_Mouse* mouse = SDL_GetMouse();
|
||||
|
||||
Emscripten_FreeCursor(mouse->def_cursor);
|
||||
mouse->def_cursor = NULL;
|
||||
|
||||
mouse->CreateCursor = NULL;
|
||||
mouse->ShowCursor = NULL;
|
||||
mouse->FreeCursor = NULL;
|
||||
mouse->WarpMouse = NULL;
|
||||
mouse->CreateSystemCursor = NULL;
|
||||
mouse->SetRelativeMouseMode = NULL;
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_EMSCRIPTEN */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
39
src/video/emscripten/SDL_emscriptenmouse.h
Normal file
39
src/video/emscripten/SDL_emscriptenmouse.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _SDL_emscriptenmouse_h
|
||||
#define _SDL_emscriptenmouse_h
|
||||
|
||||
typedef struct _Emscripten_CursorData
|
||||
{
|
||||
const char *system_cursor;
|
||||
} Emscripten_CursorData;
|
||||
|
||||
extern void
|
||||
Emscripten_InitMouse();
|
||||
|
||||
extern void
|
||||
Emscripten_FiniMouse();
|
||||
|
||||
#endif /* _SDL_emscriptenmouse_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
117
src/video/emscripten/SDL_emscriptenopengles.c
Normal file
117
src/video/emscripten/SDL_emscriptenopengles.c
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#if SDL_VIDEO_DRIVER_EMSCRIPTEN && SDL_VIDEO_OPENGL_EGL
|
||||
|
||||
#include <emscripten/emscripten.h>
|
||||
#include <GLES2/gl2.h>
|
||||
|
||||
#include "SDL_emscriptenvideo.h"
|
||||
#include "SDL_emscriptenopengles.h"
|
||||
|
||||
#define LOAD_FUNC(NAME) _this->egl_data->NAME = NAME;
|
||||
|
||||
/* EGL implementation of SDL OpenGL support */
|
||||
|
||||
int
|
||||
Emscripten_GLES_LoadLibrary(_THIS, const char *path) {
|
||||
/*we can't load EGL dynamically*/
|
||||
_this->egl_data = (struct SDL_EGL_VideoData *) SDL_calloc(1, sizeof(SDL_EGL_VideoData));
|
||||
if (!_this->egl_data) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
LOAD_FUNC(eglGetDisplay);
|
||||
LOAD_FUNC(eglInitialize);
|
||||
LOAD_FUNC(eglTerminate);
|
||||
LOAD_FUNC(eglGetProcAddress);
|
||||
LOAD_FUNC(eglChooseConfig);
|
||||
LOAD_FUNC(eglGetConfigAttrib);
|
||||
LOAD_FUNC(eglCreateContext);
|
||||
LOAD_FUNC(eglDestroyContext);
|
||||
LOAD_FUNC(eglCreateWindowSurface);
|
||||
LOAD_FUNC(eglDestroySurface);
|
||||
LOAD_FUNC(eglMakeCurrent);
|
||||
LOAD_FUNC(eglSwapBuffers);
|
||||
LOAD_FUNC(eglSwapInterval);
|
||||
LOAD_FUNC(eglWaitNative);
|
||||
LOAD_FUNC(eglWaitGL);
|
||||
LOAD_FUNC(eglBindAPI);
|
||||
|
||||
_this->egl_data->egl_display = _this->egl_data->eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
if (!_this->egl_data->egl_display) {
|
||||
return SDL_SetError("Could not get EGL display");
|
||||
}
|
||||
|
||||
if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) {
|
||||
return SDL_SetError("Could not initialize EGL");
|
||||
}
|
||||
|
||||
_this->gl_config.driver_loaded = 1;
|
||||
|
||||
if (path) {
|
||||
SDL_strlcpy(_this->gl_config.driver_path, path, sizeof(_this->gl_config.driver_path) - 1);
|
||||
} else {
|
||||
*_this->gl_config.driver_path = '\0';
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
Emscripten_GLES_DeleteContext(_THIS, SDL_GLContext context)
|
||||
{
|
||||
/*
|
||||
WebGL contexts can't actually be deleted, so we need to reset it.
|
||||
ES2 renderer resets state on init anyway, clearing the canvas should be enough
|
||||
*/
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
SDL_EGL_DeleteContext(_this, context);
|
||||
}
|
||||
|
||||
SDL_EGL_CreateContext_impl(Emscripten)
|
||||
SDL_EGL_SwapWindow_impl(Emscripten)
|
||||
SDL_EGL_MakeCurrent_impl(Emscripten)
|
||||
|
||||
void
|
||||
Emscripten_GLES_GetDrawableSize(_THIS, SDL_Window * window, int * w, int * h)
|
||||
{
|
||||
SDL_WindowData *data;
|
||||
if (window->driverdata) {
|
||||
data = (SDL_WindowData *) window->driverdata;
|
||||
|
||||
if (w) {
|
||||
*w = window->w * data->pixel_ratio;
|
||||
}
|
||||
|
||||
if (h) {
|
||||
*h = window->h * data->pixel_ratio;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_EMSCRIPTEN && SDL_VIDEO_OPENGL_EGL */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
49
src/video/emscripten/SDL_emscriptenopengles.h
Normal file
49
src/video/emscripten/SDL_emscriptenopengles.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifndef _SDL_emscriptenopengles_h
|
||||
#define _SDL_emscriptenopengles_h
|
||||
|
||||
#if SDL_VIDEO_DRIVER_EMSCRIPTEN && SDL_VIDEO_OPENGL_EGL
|
||||
|
||||
#include "../SDL_sysvideo.h"
|
||||
#include "../SDL_egl_c.h"
|
||||
|
||||
/* OpenGLES functions */
|
||||
#define Emscripten_GLES_GetAttribute SDL_EGL_GetAttribute
|
||||
#define Emscripten_GLES_GetProcAddress SDL_EGL_GetProcAddress
|
||||
#define Emscripten_GLES_UnloadLibrary SDL_EGL_UnloadLibrary
|
||||
#define Emscripten_GLES_SetSwapInterval SDL_EGL_SetSwapInterval
|
||||
#define Emscripten_GLES_GetSwapInterval SDL_EGL_GetSwapInterval
|
||||
|
||||
extern int Emscripten_GLES_LoadLibrary(_THIS, const char *path);
|
||||
extern void Emscripten_GLES_DeleteContext(_THIS, SDL_GLContext context);
|
||||
extern SDL_GLContext Emscripten_GLES_CreateContext(_THIS, SDL_Window * window);
|
||||
extern void Emscripten_GLES_SwapWindow(_THIS, SDL_Window * window);
|
||||
extern int Emscripten_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context);
|
||||
extern void Emscripten_GLES_GetDrawableSize(_THIS, SDL_Window * window, int * w, int * h);
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_EMSCRIPTEN && SDL_VIDEO_OPENGL_EGL */
|
||||
|
||||
#endif /* _SDL_emscriptenopengles_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
319
src/video/emscripten/SDL_emscriptenvideo.c
Normal file
319
src/video/emscripten/SDL_emscriptenvideo.c
Normal file
@@ -0,0 +1,319 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#if SDL_VIDEO_DRIVER_EMSCRIPTEN
|
||||
|
||||
#include "SDL_video.h"
|
||||
#include "SDL_mouse.h"
|
||||
#include "../SDL_sysvideo.h"
|
||||
#include "../SDL_pixels_c.h"
|
||||
#include "../SDL_egl_c.h"
|
||||
#include "../../events/SDL_events_c.h"
|
||||
|
||||
#include "SDL_emscriptenvideo.h"
|
||||
#include "SDL_emscriptenopengles.h"
|
||||
#include "SDL_emscriptenframebuffer.h"
|
||||
#include "SDL_emscriptenevents.h"
|
||||
#include "SDL_emscriptenmouse.h"
|
||||
|
||||
#define EMSCRIPTENVID_DRIVER_NAME "emscripten"
|
||||
|
||||
/* Initialization/Query functions */
|
||||
static int Emscripten_VideoInit(_THIS);
|
||||
static int Emscripten_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode);
|
||||
static void Emscripten_VideoQuit(_THIS);
|
||||
|
||||
static int Emscripten_CreateWindow(_THIS, SDL_Window * window);
|
||||
static void Emscripten_SetWindowSize(_THIS, SDL_Window * window);
|
||||
static void Emscripten_DestroyWindow(_THIS, SDL_Window * window);
|
||||
static void Emscripten_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen);
|
||||
static void Emscripten_PumpEvents(_THIS);
|
||||
|
||||
|
||||
/* Emscripten driver bootstrap functions */
|
||||
|
||||
static int
|
||||
Emscripten_Available(void)
|
||||
{
|
||||
return (1);
|
||||
}
|
||||
|
||||
static void
|
||||
Emscripten_DeleteDevice(SDL_VideoDevice * device)
|
||||
{
|
||||
SDL_free(device);
|
||||
}
|
||||
|
||||
static SDL_VideoDevice *
|
||||
Emscripten_CreateDevice(int devindex)
|
||||
{
|
||||
SDL_VideoDevice *device;
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
|
||||
if (!device) {
|
||||
SDL_OutOfMemory();
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Set the function pointers */
|
||||
device->VideoInit = Emscripten_VideoInit;
|
||||
device->VideoQuit = Emscripten_VideoQuit;
|
||||
device->SetDisplayMode = Emscripten_SetDisplayMode;
|
||||
|
||||
|
||||
device->PumpEvents = Emscripten_PumpEvents;
|
||||
|
||||
device->CreateWindow = Emscripten_CreateWindow;
|
||||
/*device->CreateWindowFrom = Emscripten_CreateWindowFrom;
|
||||
device->SetWindowTitle = Emscripten_SetWindowTitle;
|
||||
device->SetWindowIcon = Emscripten_SetWindowIcon;
|
||||
device->SetWindowPosition = Emscripten_SetWindowPosition;*/
|
||||
device->SetWindowSize = Emscripten_SetWindowSize;
|
||||
/*device->ShowWindow = Emscripten_ShowWindow;
|
||||
device->HideWindow = Emscripten_HideWindow;
|
||||
device->RaiseWindow = Emscripten_RaiseWindow;
|
||||
device->MaximizeWindow = Emscripten_MaximizeWindow;
|
||||
device->MinimizeWindow = Emscripten_MinimizeWindow;
|
||||
device->RestoreWindow = Emscripten_RestoreWindow;
|
||||
device->SetWindowGrab = Emscripten_SetWindowGrab;*/
|
||||
device->DestroyWindow = Emscripten_DestroyWindow;
|
||||
device->SetWindowFullscreen = Emscripten_SetWindowFullscreen;
|
||||
|
||||
device->CreateWindowFramebuffer = Emscripten_CreateWindowFramebuffer;
|
||||
device->UpdateWindowFramebuffer = Emscripten_UpdateWindowFramebuffer;
|
||||
device->DestroyWindowFramebuffer = Emscripten_DestroyWindowFramebuffer;
|
||||
|
||||
device->GL_LoadLibrary = Emscripten_GLES_LoadLibrary;
|
||||
device->GL_GetProcAddress = Emscripten_GLES_GetProcAddress;
|
||||
device->GL_UnloadLibrary = Emscripten_GLES_UnloadLibrary;
|
||||
device->GL_CreateContext = Emscripten_GLES_CreateContext;
|
||||
device->GL_MakeCurrent = Emscripten_GLES_MakeCurrent;
|
||||
device->GL_SetSwapInterval = Emscripten_GLES_SetSwapInterval;
|
||||
device->GL_GetSwapInterval = Emscripten_GLES_GetSwapInterval;
|
||||
device->GL_SwapWindow = Emscripten_GLES_SwapWindow;
|
||||
device->GL_DeleteContext = Emscripten_GLES_DeleteContext;
|
||||
device->GL_GetDrawableSize = Emscripten_GLES_GetDrawableSize;
|
||||
|
||||
device->free = Emscripten_DeleteDevice;
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
VideoBootStrap Emscripten_bootstrap = {
|
||||
EMSCRIPTENVID_DRIVER_NAME, "SDL emscripten video driver",
|
||||
Emscripten_Available, Emscripten_CreateDevice
|
||||
};
|
||||
|
||||
|
||||
int
|
||||
Emscripten_VideoInit(_THIS)
|
||||
{
|
||||
SDL_DisplayMode mode;
|
||||
double css_w, css_h;
|
||||
|
||||
/* Use a fake 32-bpp desktop mode */
|
||||
mode.format = SDL_PIXELFORMAT_RGB888;
|
||||
|
||||
emscripten_get_element_css_size(NULL, &css_w, &css_h);
|
||||
|
||||
mode.w = css_w;
|
||||
mode.h = css_h;
|
||||
|
||||
mode.refresh_rate = 0;
|
||||
mode.driverdata = NULL;
|
||||
if (SDL_AddBasicVideoDisplay(&mode) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_zero(mode);
|
||||
SDL_AddDisplayMode(&_this->displays[0], &mode);
|
||||
|
||||
Emscripten_InitMouse();
|
||||
|
||||
/* We're done! */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
Emscripten_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
|
||||
{
|
||||
/* can't do this */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
Emscripten_VideoQuit(_THIS)
|
||||
{
|
||||
Emscripten_FiniMouse();
|
||||
}
|
||||
|
||||
static void
|
||||
Emscripten_PumpEvents(_THIS)
|
||||
{
|
||||
/* do nothing. */
|
||||
}
|
||||
|
||||
static int
|
||||
Emscripten_CreateWindow(_THIS, SDL_Window * window)
|
||||
{
|
||||
SDL_WindowData *wdata;
|
||||
double scaled_w, scaled_h;
|
||||
double css_w, css_h;
|
||||
|
||||
/* Allocate window internal data */
|
||||
wdata = (SDL_WindowData *) SDL_calloc(1, sizeof(SDL_WindowData));
|
||||
if (wdata == NULL) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
|
||||
if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
|
||||
wdata->pixel_ratio = emscripten_get_device_pixel_ratio();
|
||||
} else {
|
||||
wdata->pixel_ratio = 1.0f;
|
||||
}
|
||||
|
||||
scaled_w = SDL_floor(window->w * wdata->pixel_ratio);
|
||||
scaled_h = SDL_floor(window->h * wdata->pixel_ratio);
|
||||
|
||||
emscripten_set_canvas_size(scaled_w, scaled_h);
|
||||
|
||||
emscripten_get_element_css_size(NULL, &css_w, &css_h);
|
||||
|
||||
wdata->external_size = css_w != scaled_w || css_h != scaled_h;
|
||||
|
||||
if ((window->flags & SDL_WINDOW_RESIZABLE) && wdata->external_size) {
|
||||
/* external css has resized us */
|
||||
scaled_w = css_w * wdata->pixel_ratio;
|
||||
scaled_h = css_h * wdata->pixel_ratio;
|
||||
|
||||
emscripten_set_canvas_size(scaled_w, scaled_h);
|
||||
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, css_w, css_h);
|
||||
}
|
||||
|
||||
/* if the size is not being controlled by css, we need to scale down for hidpi */
|
||||
if (!wdata->external_size) {
|
||||
if (wdata->pixel_ratio != 1.0f) {
|
||||
/*scale canvas down*/
|
||||
emscripten_set_element_css_size(NULL, window->w, window->h);
|
||||
}
|
||||
}
|
||||
|
||||
wdata->windowed_width = scaled_w;
|
||||
wdata->windowed_height = scaled_h;
|
||||
|
||||
if (window->flags & SDL_WINDOW_OPENGL) {
|
||||
if (!_this->egl_data) {
|
||||
if (SDL_GL_LoadLibrary(NULL) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
wdata->egl_surface = SDL_EGL_CreateSurface(_this, 0);
|
||||
|
||||
if (wdata->egl_surface == EGL_NO_SURFACE) {
|
||||
return SDL_SetError("Could not create GLES window surface");
|
||||
}
|
||||
}
|
||||
|
||||
wdata->window = window;
|
||||
|
||||
/* Setup driver data for this window */
|
||||
window->driverdata = wdata;
|
||||
|
||||
/* One window, it always has focus */
|
||||
SDL_SetMouseFocus(window);
|
||||
SDL_SetKeyboardFocus(window);
|
||||
|
||||
Emscripten_RegisterEventHandlers(wdata);
|
||||
|
||||
/* Window has been successfully created */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void Emscripten_SetWindowSize(_THIS, SDL_Window * window)
|
||||
{
|
||||
SDL_WindowData *data;
|
||||
|
||||
if (window->driverdata) {
|
||||
data = (SDL_WindowData *) window->driverdata;
|
||||
emscripten_set_canvas_size(window->w * data->pixel_ratio, window->h * data->pixel_ratio);
|
||||
|
||||
/*scale canvas down*/
|
||||
if (!data->external_size && data->pixel_ratio != 1.0f) {
|
||||
emscripten_set_element_css_size(NULL, window->w, window->h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
Emscripten_DestroyWindow(_THIS, SDL_Window * window)
|
||||
{
|
||||
SDL_WindowData *data;
|
||||
|
||||
if(window->driverdata) {
|
||||
data = (SDL_WindowData *) window->driverdata;
|
||||
|
||||
Emscripten_UnregisterEventHandlers(data);
|
||||
if (data->egl_surface != EGL_NO_SURFACE) {
|
||||
SDL_EGL_DestroySurface(_this, data->egl_surface);
|
||||
data->egl_surface = EGL_NO_SURFACE;
|
||||
}
|
||||
SDL_free(window->driverdata);
|
||||
window->driverdata = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
Emscripten_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
|
||||
{
|
||||
SDL_WindowData *data;
|
||||
if(window->driverdata) {
|
||||
data = (SDL_WindowData *) window->driverdata;
|
||||
|
||||
if(fullscreen) {
|
||||
data->requested_fullscreen_mode = window->flags & (SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_FULLSCREEN);
|
||||
/*unset the fullscreen flags as we're not actually fullscreen yet*/
|
||||
window->flags &= ~(SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_FULLSCREEN);
|
||||
|
||||
EM_ASM({
|
||||
//reparent canvas (similar to Module.requestFullscreen)
|
||||
var canvas = Module['canvas'];
|
||||
if(canvas.parentNode.id != "SDLFullscreenElement") {
|
||||
var canvasContainer = document.createElement("div");
|
||||
canvasContainer.id = "SDLFullscreenElement";
|
||||
canvas.parentNode.insertBefore(canvasContainer, canvas);
|
||||
canvasContainer.appendChild(canvas);
|
||||
}
|
||||
});
|
||||
|
||||
int is_fullscreen;
|
||||
emscripten_get_canvas_size(&data->windowed_width, &data->windowed_height, &is_fullscreen);
|
||||
emscripten_request_fullscreen("SDLFullscreenElement", 1);
|
||||
}
|
||||
else
|
||||
emscripten_exit_fullscreen();
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_EMSCRIPTEN */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
52
src/video/emscripten/SDL_emscriptenvideo.h
Normal file
52
src/video/emscripten/SDL_emscriptenvideo.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifndef _SDL_emscriptenvideo_h
|
||||
#define _SDL_emscriptenvideo_h
|
||||
|
||||
#include "../SDL_sysvideo.h"
|
||||
#include <emscripten/emscripten.h>
|
||||
#include <emscripten/html5.h>
|
||||
|
||||
#include <EGL/egl.h>
|
||||
|
||||
typedef struct SDL_WindowData
|
||||
{
|
||||
#if SDL_VIDEO_OPENGL_EGL
|
||||
EGLSurface egl_surface;
|
||||
#endif
|
||||
SDL_Window *window;
|
||||
SDL_Surface *surface;
|
||||
|
||||
int windowed_width;
|
||||
int windowed_height;
|
||||
|
||||
float pixel_ratio;
|
||||
|
||||
SDL_bool external_size;
|
||||
|
||||
int requested_fullscreen_mode;
|
||||
} SDL_WindowData;
|
||||
|
||||
#endif /* _SDL_emscriptenvideo_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
Reference in New Issue
Block a user