Skip to content
This repository has been archived by the owner on Feb 17, 2022. It is now read-only.

Implement multi-window support #55

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 79 additions & 30 deletions src/video/emscripten/SDL_emscriptenevents.c
Original file line number Diff line number Diff line change
Expand Up @@ -297,10 +297,22 @@ Emscripten_ConvertUTF32toUTF8(Uint32 codepoint, char * text)
return SDL_TRUE;
}

static SDL_WindowData *wdata;
static SDL_WindowData *GetCurrentWindowData(void) {
#ifdef EMSCRIPTEN_HAS_WINDOW_SELECTOR
// Use wdata as a fallback in case Emscripten does support window selector
// but custom HTML shell does not
SDL_WindowData *result = emscripten_get_current_window_data();
return result ? result : wdata;
#else
return wdata;
#endif
}

EM_BOOL
Emscripten_HandleMouseMove(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData)
{
SDL_WindowData *window_data = userData;
SDL_WindowData *window_data = GetCurrentWindowData();
int mx, my;
static double residualx = 0, residualy = 0;
EmscriptenPointerlockChangeEvent pointerlock_status;
Expand Down Expand Up @@ -335,7 +347,7 @@ Emscripten_HandleMouseMove(int eventType, const EmscriptenMouseEvent *mouseEvent
EM_BOOL
Emscripten_HandleMouseButton(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData)
{
SDL_WindowData *window_data = userData;
SDL_WindowData *window_data = GetCurrentWindowData();
uint32_t sdl_button;
switch (mouseEvent->button) {
case 0:
Expand All @@ -359,7 +371,7 @@ Emscripten_HandleMouseButton(int eventType, const EmscriptenMouseEvent *mouseEve
EM_BOOL
Emscripten_HandleMouseFocus(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData)
{
SDL_WindowData *window_data = userData;
SDL_WindowData *window_data = GetCurrentWindowData();

int mx = mouseEvent->canvasX, my = mouseEvent->canvasY;
EmscriptenPointerlockChangeEvent pointerlock_status;
Expand All @@ -385,15 +397,15 @@ Emscripten_HandleMouseFocus(int eventType, const EmscriptenMouseEvent *mouseEven
EM_BOOL
Emscripten_HandleWheel(int eventType, const EmscriptenWheelEvent *wheelEvent, void *userData)
{
SDL_WindowData *window_data = userData;
SDL_WindowData *window_data = GetCurrentWindowData();
SDL_SendMouseWheel(window_data->window, 0, wheelEvent->deltaX, -wheelEvent->deltaY, SDL_MOUSEWHEEL_NORMAL);
return SDL_GetEventState(SDL_MOUSEWHEEL) == SDL_ENABLE;
}

EM_BOOL
Emscripten_HandleFocus(int eventType, const EmscriptenFocusEvent *wheelEvent, void *userData)
{
SDL_WindowData *window_data = userData;
SDL_WindowData *window_data = GetCurrentWindowData();
/* If the user switches away while keys are pressed (such as
* via Alt+Tab), key release events won't be received. */
if (eventType == EMSCRIPTEN_EVENT_BLUR) {
Expand All @@ -408,7 +420,7 @@ Emscripten_HandleFocus(int eventType, const EmscriptenFocusEvent *wheelEvent, vo
EM_BOOL
Emscripten_HandleTouch(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData)
{
SDL_WindowData *window_data = userData;
SDL_WindowData *window_data = GetCurrentWindowData();
int i;
double client_w, client_h;
int preventDefault = 0;
Expand Down Expand Up @@ -534,7 +546,7 @@ Emscripten_HandleKeyPress(int eventType, const EmscriptenKeyboardEvent *keyEvent
EM_BOOL
Emscripten_HandleFullscreenChange(int eventType, const EmscriptenFullscreenChangeEvent *fullscreenChangeEvent, void *userData)
{
SDL_WindowData *window_data = userData;
SDL_WindowData *window_data = GetCurrentWindowData();
if(fullscreenChangeEvent->isFullscreen)
{
window_data->window->flags |= window_data->requested_fullscreen_mode;
Expand All @@ -555,7 +567,7 @@ Emscripten_HandleFullscreenChange(int eventType, const EmscriptenFullscreenChang
EM_BOOL
Emscripten_HandleResize(int eventType, const EmscriptenUiEvent *uiEvent, void *userData)
{
SDL_WindowData *window_data = userData;
SDL_WindowData *window_data = GetCurrentWindowData();

/* update pixel ratio */
if (window_data->window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
Expand Down Expand Up @@ -592,7 +604,7 @@ EM_BOOL
Emscripten_HandleCanvasResize(int eventType, const void *reserved, void *userData)
{
/*this is used during fullscreen changes*/
SDL_WindowData *window_data = userData;
SDL_WindowData *window_data = GetCurrentWindowData();

if(window_data->fullscreen_resize)
{
Expand All @@ -604,49 +616,82 @@ Emscripten_HandleCanvasResize(int eventType, const void *reserved, void *userDat
return 0;
}

static int canvas_is_hidden;
static SDL_WindowData *previous_selected_window;

static void
SendHiddenStatus(SDL_WindowData *window_data)
{
int hidden = canvas_is_hidden || !window_data->selected;
SDL_SendWindowEvent(window_data->window, hidden ? SDL_WINDOWEVENT_HIDDEN : SDL_WINDOWEVENT_SHOWN, 0, 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);
SDL_WindowData *window_data = GetCurrentWindowData();
canvas_is_hidden = visEvent->hidden;
SendHiddenStatus(window_data);
return 0;
}

static void
Emscripten_HandleWindowSelectorChange(void) {
SDL_WindowData *window_data = GetCurrentWindowData();
if (previous_selected_window == window_data) {
return;
}
if (previous_selected_window) {
previous_selected_window->selected = 0;
SendHiddenStatus(previous_selected_window);
}
window_data->selected = 1;
SendHiddenStatus(window_data);
previous_selected_window = window_data;
}

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);
/* There is either only one window and that window is the canvas or multiple windows mapped to the single canvas */
wdata = data;
emscripten_set_mousemove_callback("#canvas", NULL, 0, Emscripten_HandleMouseMove);

emscripten_set_mousedown_callback("#canvas", data, 0, Emscripten_HandleMouseButton);
emscripten_set_mouseup_callback("#document", data, 0, Emscripten_HandleMouseButton);
emscripten_set_mousedown_callback("#canvas", NULL, 0, Emscripten_HandleMouseButton);
emscripten_set_mouseup_callback("#document", NULL, 0, Emscripten_HandleMouseButton);

emscripten_set_mouseenter_callback("#canvas", data, 0, Emscripten_HandleMouseFocus);
emscripten_set_mouseleave_callback("#canvas", data, 0, Emscripten_HandleMouseFocus);
emscripten_set_mouseenter_callback("#canvas", NULL, 0, Emscripten_HandleMouseFocus);
emscripten_set_mouseleave_callback("#canvas", NULL, 0, Emscripten_HandleMouseFocus);

emscripten_set_wheel_callback("#canvas", data, 0, Emscripten_HandleWheel);
emscripten_set_wheel_callback("#canvas", NULL, 0, Emscripten_HandleWheel);

emscripten_set_focus_callback("#window", data, 0, Emscripten_HandleFocus);
emscripten_set_blur_callback("#window", data, 0, Emscripten_HandleFocus);
emscripten_set_focus_callback("#window", NULL, 0, Emscripten_HandleFocus);
emscripten_set_blur_callback("#window", NULL, 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);
emscripten_set_touchstart_callback("#canvas", NULL, 0, Emscripten_HandleTouch);
emscripten_set_touchend_callback("#canvas", NULL, 0, Emscripten_HandleTouch);
emscripten_set_touchmove_callback("#canvas", NULL, 0, Emscripten_HandleTouch);
emscripten_set_touchcancel_callback("#canvas", NULL, 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_keydown_callback(keyElement, NULL, 0, Emscripten_HandleKey);
emscripten_set_keyup_callback(keyElement, NULL, 0, Emscripten_HandleKey);
emscripten_set_keypress_callback(keyElement, NULL, 0, Emscripten_HandleKeyPress);

emscripten_set_fullscreenchange_callback("#document", NULL, 0, Emscripten_HandleFullscreenChange);

emscripten_set_fullscreenchange_callback("#document", data, 0, Emscripten_HandleFullscreenChange);
emscripten_set_resize_callback("#window", NULL, 0, Emscripten_HandleResize);

emscripten_set_resize_callback("#window", data, 0, Emscripten_HandleResize);
emscripten_set_visibilitychange_callback(NULL, 0, Emscripten_HandleVisibilityChange);

emscripten_set_visibilitychange_callback(data, 0, Emscripten_HandleVisibilityChange);
#ifdef EMSCRIPTEN_HAS_WINDOW_SELECTOR
emscripten_set_selected_window_change_callback(Emscripten_HandleWindowSelectorChange);
#else
Emscripten_HandleWindowSelectorChange();
#endif
}

void
Expand Down Expand Up @@ -686,6 +731,10 @@ Emscripten_UnregisterEventHandlers(SDL_WindowData *data)
emscripten_set_resize_callback("#window", NULL, 0, NULL);

emscripten_set_visibilitychange_callback(NULL, 0, NULL);

#ifdef EMSCRIPTEN_HAS_WINDOW_SELECTOR
emscripten_set_selected_window_change_callback(NULL);
#endif
}

#endif /* SDL_VIDEO_DRIVER_EMSCRIPTEN */
Expand Down
5 changes: 5 additions & 0 deletions src/video/emscripten/SDL_emscriptenframebuffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ int Emscripten_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rec
SDL_Surface *surface;

SDL_WindowData *data = (SDL_WindowData *) window->driverdata;

if (!data->selected) {
return 0;
}

surface = data->surface;
if (!surface) {
return SDL_SetError("Couldn't find framebuffer surface for window");
Expand Down
Loading