From 95a6963112f430dfae63ee6b801b36985482a541 Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Sat, 28 Nov 2020 08:17:10 +0200 Subject: Workaround for SDL window resize issue Rearrange and draw window contents with an event watcher during window resizing because SDL is blocking the main thread. Tested on macOS so far, may need a build option. In reference to SDL bug: https://bugzilla.libsdl.org/show_bug.cgi?id=2077 --- src/app.c | 10 ++++++++++ src/ui/window.c | 20 ++++++++++++++------ src/ui/window.h | 1 + 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/app.c b/src/app.c index 57fa3318..419c5619 100644 --- a/src/app.c +++ b/src/app.c @@ -566,10 +566,20 @@ static void runTickers_App_(iApp *d) { } } +static int resizeWatcher_(void *user, SDL_Event *event) { + iApp *d = user; + if (event->type == SDL_WINDOWEVENT && event->window.event == SDL_WINDOWEVENT_SIZE_CHANGED) { + const SDL_WindowEvent *winev = &event->window; + drawWhileResizing_Window(d->window, winev->data1, winev->data2); + } + return 0; +} + static int run_App_(iApp *d) { arrange_Widget(findWidget_App("root")); d->running = iTrue; SDL_EventState(SDL_DROPFILE, SDL_ENABLE); /* open files via drag'n'drop */ + SDL_AddEventWatch(resizeWatcher_, d); while (d->running) { processEvents_App(waitForNewEvents_AppEventMode); runTickers_App_(d); diff --git a/src/ui/window.c b/src/ui/window.c index cdb122be..dd9181ad 100644 --- a/src/ui/window.c +++ b/src/ui/window.c @@ -514,17 +514,25 @@ static void setupUserInterface_Window(iWindow *d) { } } -static void updateRootSize_Window_(iWindow *d) { +static void updateRootSize_Window_(iWindow *d, iBool notifyAlways) { iInt2 *size = &d->root->rect.size; const iInt2 oldSize = *size; SDL_GetRendererOutputSize(d->render, &size->x, &size->y); - if (!isEqual_I2(oldSize, *size)) { + if (notifyAlways || !isEqual_I2(oldSize, *size)) { arrange_Widget(d->root); postCommandf_App("window.resized width:%d height:%d", size->x, size->y); postRefresh_App(); } } +void drawWhileResizing_Window(iWindow *d, int w, int h) { + /* This is called while a window resize is in progress, so we can be pretty confident + the size has actually changed. */ + d->root->rect.size = mulf_I2(init_I2(w, h), d->pixelRatio); + arrange_Widget(d->root); + draw_Window(d); +} + static float pixelRatio_Window_(const iWindow *d) { #if defined (iPlatformMsys) iUnused(d); @@ -631,7 +639,7 @@ void init_Window(iWindow *d, iRect rect) { init_Text(d->render); setupUserInterface_Window(d); postCommand_App("bindings.changed"); /* update from bindings */ - updateRootSize_Window_(d); + updateRootSize_Window_(d, iFalse); } void deinit_Window(iWindow *d) { @@ -692,11 +700,11 @@ static iBool handleWindowEvent_Window_(iWindow *d, const SDL_WindowEvent *ev) { return iTrue; } case SDL_WINDOWEVENT_RESIZED: - case SDL_WINDOWEVENT_SIZE_CHANGED: +// case SDL_WINDOWEVENT_SIZE_CHANGED: if (!isMaximized_Window_(d) && !d->isDrawFrozen) { d->lastRect.size = init_I2(ev->data1, ev->data2); } - updateRootSize_Window_(d); + updateRootSize_Window_(d, iTrue /* we were already redrawing during the resize */); return iTrue; case SDL_WINDOWEVENT_LEAVE: unhover_Widget(); @@ -836,7 +844,7 @@ void draw_Window(iWindow *d) { void resize_Window(iWindow *d, int w, int h) { SDL_SetWindowSize(d->win, w, h); - updateRootSize_Window_(d); + updateRootSize_Window_(d, iFalse); } void setTitle_Window(iWindow *d, const iString *title) { diff --git a/src/ui/window.h b/src/ui/window.h index 18df0cf9..2b68d7aa 100644 --- a/src/ui/window.h +++ b/src/ui/window.h @@ -51,6 +51,7 @@ struct Impl_Window { iBool processEvent_Window (iWindow *, const SDL_Event *); void draw_Window (iWindow *); +void drawWhileResizing_Window(iWindow *d, int w, int h); /* workaround for SDL bug */ void resize_Window (iWindow *, int w, int h); void setTitle_Window (iWindow *, const iString *title); void setUiScale_Window (iWindow *, float uiScale); -- cgit v1.2.3