emscripten: Move fill-document from hint/property to a window flag.

Fixes #14617.
This commit is contained in:
Ryan C. Gordon
2025-12-07 14:42:18 -05:00
parent 19988c5faa
commit 9918d6cb5e
10 changed files with 87 additions and 77 deletions

View File

@@ -1270,6 +1270,7 @@ SDL3_0.0.0 {
SDL_RotateSurface;
SDL_LoadSurface_IO;
SDL_LoadSurface;
SDL_SetWindowFillDocument;
# extra symbols go here (don't modify this line)
local: *;
};

View File

@@ -1296,3 +1296,4 @@
#define SDL_RotateSurface SDL_RotateSurface_REAL
#define SDL_LoadSurface_IO SDL_LoadSurface_IO_REAL
#define SDL_LoadSurface SDL_LoadSurface_REAL
#define SDL_SetWindowFillDocument SDL_SetWindowFillDocument_REAL

View File

@@ -1304,3 +1304,4 @@ SDL_DYNAPI_PROC(SDL_Cursor*,SDL_CreateAnimatedCursor,(SDL_CursorFrameInfo *a,int
SDL_DYNAPI_PROC(SDL_Surface*,SDL_RotateSurface,(SDL_Surface *a,float b),(a,b),return)
SDL_DYNAPI_PROC(SDL_Surface*,SDL_LoadSurface_IO,(SDL_IOStream *a,bool b),(a,b),return)
SDL_DYNAPI_PROC(SDL_Surface*,SDL_LoadSurface,(const char *a),(a),return)
SDL_DYNAPI_PROC(bool,SDL_SetWindowFillDocument,(SDL_Window *a,bool b),(a,b),return)

View File

@@ -2497,6 +2497,15 @@ SDL_AppResult SDLTest_CommonEventMainCallbacks(SDLTest_CommonState *state, const
}
}
break;
case SDLK_D:
if (withControl) {
/* Ctrl-D toggle fill-document */
SDL_Window *window = SDL_GetWindowFromEvent(event);
if (window) {
SDL_SetWindowFillDocument(window, !((SDL_GetWindowFlags(window) & SDL_WINDOW_FILL_DOCUMENT) != 0));
}
}
break;
case SDLK_P:
if (withAlt) {
/* Alt-P cycle through progress states */

View File

@@ -312,6 +312,7 @@ struct SDL_VideoDevice
bool (*FlashWindow)(SDL_VideoDevice *_this, SDL_Window *window, SDL_FlashOperation operation);
bool (*ApplyWindowProgress)(SDL_VideoDevice *_this, SDL_Window *window);
bool (*SetWindowFocusable)(SDL_VideoDevice *_this, SDL_Window *window, bool focusable);
bool (*SetWindowFillDocument)(SDL_VideoDevice *_this, SDL_Window *window, bool fill);
bool (*SyncWindow)(SDL_VideoDevice *_this, SDL_Window *window);
bool (*ReconfigureWindow)(SDL_VideoDevice *_this, SDL_Window *window, SDL_WindowFlags flags);

View File

@@ -2199,7 +2199,7 @@ SDL_PixelFormat SDL_GetWindowPixelFormat(SDL_Window *window)
}
#define CREATE_FLAGS \
(SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY | SDL_WINDOW_ALWAYS_ON_TOP | SDL_WINDOW_POPUP_MENU | SDL_WINDOW_UTILITY | SDL_WINDOW_TOOLTIP | SDL_WINDOW_VULKAN | SDL_WINDOW_MINIMIZED | SDL_WINDOW_METAL | SDL_WINDOW_TRANSPARENT | SDL_WINDOW_NOT_FOCUSABLE)
(SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY | SDL_WINDOW_ALWAYS_ON_TOP | SDL_WINDOW_POPUP_MENU | SDL_WINDOW_UTILITY | SDL_WINDOW_TOOLTIP | SDL_WINDOW_VULKAN | SDL_WINDOW_MINIMIZED | SDL_WINDOW_METAL | SDL_WINDOW_TRANSPARENT | SDL_WINDOW_NOT_FOCUSABLE | SDL_WINDOW_FILL_DOCUMENT)
static SDL_INLINE bool IsAcceptingDragAndDrop(void)
{
@@ -2557,6 +2557,10 @@ SDL_Window *SDL_CreateWindowWithProperties(SDL_PropertiesID props)
window->external_graphics_context = external_graphics_context;
window->constrain_popup = SDL_GetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_CONSTRAIN_POPUP_BOOLEAN, true);
if (!_this->SetWindowFillDocument) {
window->flags &= ~SDL_WINDOW_FILL_DOCUMENT; // not an error, just unsupported here, so remove the flag.
}
if (_this->windows) {
_this->windows->prev = window;
}
@@ -3914,6 +3918,25 @@ bool SDL_SetWindowFocusable(SDL_Window *window, bool focusable)
return true;
}
bool SDL_SetWindowFillDocument(SDL_Window *window, bool fill)
{
CHECK_WINDOW_MAGIC(window, false);
const bool want = (fill != false); // normalize the flag.
const bool have = ((window->flags & SDL_WINDOW_FILL_DOCUMENT) != 0);
if ((want != have) && (_this->SetWindowFillDocument)) {
if (!_this->SetWindowFillDocument(_this, window, want)) {
return false;
} else if (want) {
window->flags |= SDL_WINDOW_FILL_DOCUMENT;
} else {
window->flags &= ~SDL_WINDOW_FILL_DOCUMENT;
}
}
return true;
}
void SDL_UpdateWindowGrab(SDL_Window *window)
{
bool keyboard_grabbed, mouse_grabbed;

View File

@@ -50,6 +50,7 @@ static SDL_FullscreenResult Emscripten_SetWindowFullscreen(SDL_VideoDevice *_thi
static void Emscripten_PumpEvents(SDL_VideoDevice *_this);
static void Emscripten_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window);
static bool Emscripten_SetWindowIcon(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surface *icon);
static bool Emscripten_SetWindowFillDocument(SDL_VideoDevice *_this, SDL_Window *window, bool fill);
SDL_Window *Emscripten_fill_document_window = NULL;
@@ -58,11 +59,8 @@ static int pending_swap_interval = -1;
// Emscripten driver bootstrap functions
static void SDLCALL Emscripten_FillDocHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint);
static void Emscripten_DeleteDevice(SDL_VideoDevice *device)
{
SDL_RemoveHintCallback(SDL_HINT_EMSCRIPTEN_FILL_DOCUMENT, Emscripten_FillDocHintChanged, device);
SDL_free(device);
}
@@ -177,6 +175,7 @@ static SDL_VideoDevice *Emscripten_CreateDevice(void)
device->GetWindowSizeInPixels = Emscripten_GetWindowSizeInPixels;
device->DestroyWindow = Emscripten_DestroyWindow;
device->SetWindowFullscreen = Emscripten_SetWindowFullscreen;
device->SetWindowFillDocument = Emscripten_SetWindowFillDocument;
device->CreateWindowFramebuffer = Emscripten_CreateWindowFramebuffer;
device->UpdateWindowFramebuffer = Emscripten_UpdateWindowFramebuffer;
@@ -197,8 +196,6 @@ static SDL_VideoDevice *Emscripten_CreateDevice(void)
Emscripten_ListenSystemTheme();
device->system_theme = Emscripten_GetSystemTheme();
SDL_AddHintCallback(SDL_HINT_EMSCRIPTEN_FILL_DOCUMENT, Emscripten_FillDocHintChanged, device);
return device;
}
@@ -463,14 +460,16 @@ EMSCRIPTEN_KEEPALIVE void requestFullscreenThroughSDL(SDL_Window *window)
SDL_SetWindowFullscreen(window, true);
}
static void Emscripten_SetWindowFillDocState(SDL_Window *window, bool enable)
static bool Emscripten_SetWindowFillDocument(SDL_VideoDevice *_this, SDL_Window *window, bool fill)
{
SDL_WindowData *wdata = window->internal;
SDL_assert(!Emscripten_fill_document_window || !enable); // one at a time, sorry.
if (fill && Emscripten_fill_document_window && (Emscripten_fill_document_window != window)) {
return SDL_SetError("Only one fill-document window allowed at a time.");
}
// fill_document takes up the entire page and resizes as the browser window resizes.
if (enable) {
if (fill) {
Emscripten_fill_document_window = window;
const int w = MAIN_THREAD_EM_ASM_INT({ return window.innerWidth; });
@@ -558,20 +557,8 @@ static void Emscripten_SetWindowFillDocState(SDL_Window *window, bool enable)
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESIZED, wdata->non_fill_document_width, wdata->non_fill_document_height);
}
}
}
static void SDLCALL Emscripten_FillDocHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
{
const bool enabled = SDL_GetStringBoolean(hint, false);
if (Emscripten_fill_document_window && !enabled) {
Emscripten_SetWindowFillDocState(Emscripten_fill_document_window, false);
} else if (!Emscripten_fill_document_window && enabled) {
/// there's currently only ever one canvas, but if this changes later, we can choose the one with keyboard focus or something.
SDL_VideoDevice *device = (SDL_VideoDevice *) userdata;
if (device && device->windows) { // take first window in the list for now.
Emscripten_SetWindowFillDocState(device->windows, true);
}
}
return true;
}
static bool Emscripten_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID props)
@@ -580,6 +567,12 @@ static bool Emscripten_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window,
double css_w, css_h;
const char *selector;
bool fill_document = ((window->flags & SDL_WINDOW_FILL_DOCUMENT) != 0);
if (fill_document && Emscripten_fill_document_window) {
fill_document = false; // only one allowed at a time.
window->flags &= ~SDL_WINDOW_FILL_DOCUMENT; // !!! FIXME: should this fail instead?
}
// Allocate window internal data
wdata = (SDL_WindowData *)SDL_calloc(1, sizeof(SDL_WindowData));
if (!wdata) {
@@ -598,15 +591,6 @@ static bool Emscripten_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window,
}
wdata->keyboard_element = SDL_strdup(selector);
bool fill_document;
if (Emscripten_fill_document_window) {
fill_document = false; // only one allowed at a time.
} else if (SDL_GetHint(SDL_HINT_EMSCRIPTEN_FILL_DOCUMENT)) {
fill_document = SDL_GetHintBoolean(SDL_HINT_EMSCRIPTEN_FILL_DOCUMENT, false);
} else {
fill_document = SDL_GetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_EMSCRIPTEN_FILL_DOCUMENT_BOOLEAN, false);
}
if (window->flags & SDL_WINDOW_HIGH_PIXEL_DENSITY) {
wdata->pixel_ratio = emscripten_get_device_pixel_ratio();
} else {
@@ -629,7 +613,7 @@ static bool Emscripten_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window,
wdata->non_fill_document_width = window->w;
wdata->non_fill_document_height = window->h;
Emscripten_SetWindowFillDocState(window, fill_document);
Emscripten_SetWindowFillDocument(_this, window, fill_document);
// One window, it always has focus
SDL_SetMouseFocus(window);
@@ -647,7 +631,6 @@ static bool Emscripten_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window,
// Ensure various things are added to the window's properties
SDL_SetStringProperty(window->props, SDL_PROP_WINDOW_EMSCRIPTEN_CANVAS_ID_STRING, wdata->canvas_id);
SDL_SetStringProperty(window->props, SDL_PROP_WINDOW_EMSCRIPTEN_KEYBOARD_ELEMENT_STRING, wdata->keyboard_element);
SDL_SetBooleanProperty(window->props, SDL_PROP_WINDOW_EMSCRIPTEN_FILL_DOCUMENT_BOOLEAN, fill_document);
// Window has been successfully created
return true;
@@ -695,9 +678,7 @@ static void Emscripten_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window)
{
SDL_WindowData *data;
if (Emscripten_fill_document_window == window) {
Emscripten_SetWindowFillDocState(window, false);
}
Emscripten_SetWindowFillDocument(_this, window, false);
if (window->internal) {
data = window->internal;