diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-11-28 08:17:10 +0200 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-11-28 08:17:10 +0200 |
commit | 95a6963112f430dfae63ee6b801b36985482a541 (patch) | |
tree | 0c1265a9b93468d1bde8c3c3deba462ea9fc2c82 | |
parent | 3b0e44cc32f4d45e37912d52fc2f2cd98f12da75 (diff) |
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
-rw-r--r-- | src/app.c | 10 | ||||
-rw-r--r-- | src/ui/window.c | 20 | ||||
-rw-r--r-- | src/ui/window.h | 1 |
3 files changed, 25 insertions, 6 deletions
@@ -566,10 +566,20 @@ static void runTickers_App_(iApp *d) { | |||
566 | } | 566 | } |
567 | } | 567 | } |
568 | 568 | ||
569 | static int resizeWatcher_(void *user, SDL_Event *event) { | ||
570 | iApp *d = user; | ||
571 | if (event->type == SDL_WINDOWEVENT && event->window.event == SDL_WINDOWEVENT_SIZE_CHANGED) { | ||
572 | const SDL_WindowEvent *winev = &event->window; | ||
573 | drawWhileResizing_Window(d->window, winev->data1, winev->data2); | ||
574 | } | ||
575 | return 0; | ||
576 | } | ||
577 | |||
569 | static int run_App_(iApp *d) { | 578 | static int run_App_(iApp *d) { |
570 | arrange_Widget(findWidget_App("root")); | 579 | arrange_Widget(findWidget_App("root")); |
571 | d->running = iTrue; | 580 | d->running = iTrue; |
572 | SDL_EventState(SDL_DROPFILE, SDL_ENABLE); /* open files via drag'n'drop */ | 581 | SDL_EventState(SDL_DROPFILE, SDL_ENABLE); /* open files via drag'n'drop */ |
582 | SDL_AddEventWatch(resizeWatcher_, d); | ||
573 | while (d->running) { | 583 | while (d->running) { |
574 | processEvents_App(waitForNewEvents_AppEventMode); | 584 | processEvents_App(waitForNewEvents_AppEventMode); |
575 | runTickers_App_(d); | 585 | 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) { | |||
514 | } | 514 | } |
515 | } | 515 | } |
516 | 516 | ||
517 | static void updateRootSize_Window_(iWindow *d) { | 517 | static void updateRootSize_Window_(iWindow *d, iBool notifyAlways) { |
518 | iInt2 *size = &d->root->rect.size; | 518 | iInt2 *size = &d->root->rect.size; |
519 | const iInt2 oldSize = *size; | 519 | const iInt2 oldSize = *size; |
520 | SDL_GetRendererOutputSize(d->render, &size->x, &size->y); | 520 | SDL_GetRendererOutputSize(d->render, &size->x, &size->y); |
521 | if (!isEqual_I2(oldSize, *size)) { | 521 | if (notifyAlways || !isEqual_I2(oldSize, *size)) { |
522 | arrange_Widget(d->root); | 522 | arrange_Widget(d->root); |
523 | postCommandf_App("window.resized width:%d height:%d", size->x, size->y); | 523 | postCommandf_App("window.resized width:%d height:%d", size->x, size->y); |
524 | postRefresh_App(); | 524 | postRefresh_App(); |
525 | } | 525 | } |
526 | } | 526 | } |
527 | 527 | ||
528 | void drawWhileResizing_Window(iWindow *d, int w, int h) { | ||
529 | /* This is called while a window resize is in progress, so we can be pretty confident | ||
530 | the size has actually changed. */ | ||
531 | d->root->rect.size = mulf_I2(init_I2(w, h), d->pixelRatio); | ||
532 | arrange_Widget(d->root); | ||
533 | draw_Window(d); | ||
534 | } | ||
535 | |||
528 | static float pixelRatio_Window_(const iWindow *d) { | 536 | static float pixelRatio_Window_(const iWindow *d) { |
529 | #if defined (iPlatformMsys) | 537 | #if defined (iPlatformMsys) |
530 | iUnused(d); | 538 | iUnused(d); |
@@ -631,7 +639,7 @@ void init_Window(iWindow *d, iRect rect) { | |||
631 | init_Text(d->render); | 639 | init_Text(d->render); |
632 | setupUserInterface_Window(d); | 640 | setupUserInterface_Window(d); |
633 | postCommand_App("bindings.changed"); /* update from bindings */ | 641 | postCommand_App("bindings.changed"); /* update from bindings */ |
634 | updateRootSize_Window_(d); | 642 | updateRootSize_Window_(d, iFalse); |
635 | } | 643 | } |
636 | 644 | ||
637 | void deinit_Window(iWindow *d) { | 645 | void deinit_Window(iWindow *d) { |
@@ -692,11 +700,11 @@ static iBool handleWindowEvent_Window_(iWindow *d, const SDL_WindowEvent *ev) { | |||
692 | return iTrue; | 700 | return iTrue; |
693 | } | 701 | } |
694 | case SDL_WINDOWEVENT_RESIZED: | 702 | case SDL_WINDOWEVENT_RESIZED: |
695 | case SDL_WINDOWEVENT_SIZE_CHANGED: | 703 | // case SDL_WINDOWEVENT_SIZE_CHANGED: |
696 | if (!isMaximized_Window_(d) && !d->isDrawFrozen) { | 704 | if (!isMaximized_Window_(d) && !d->isDrawFrozen) { |
697 | d->lastRect.size = init_I2(ev->data1, ev->data2); | 705 | d->lastRect.size = init_I2(ev->data1, ev->data2); |
698 | } | 706 | } |
699 | updateRootSize_Window_(d); | 707 | updateRootSize_Window_(d, iTrue /* we were already redrawing during the resize */); |
700 | return iTrue; | 708 | return iTrue; |
701 | case SDL_WINDOWEVENT_LEAVE: | 709 | case SDL_WINDOWEVENT_LEAVE: |
702 | unhover_Widget(); | 710 | unhover_Widget(); |
@@ -836,7 +844,7 @@ void draw_Window(iWindow *d) { | |||
836 | 844 | ||
837 | void resize_Window(iWindow *d, int w, int h) { | 845 | void resize_Window(iWindow *d, int w, int h) { |
838 | SDL_SetWindowSize(d->win, w, h); | 846 | SDL_SetWindowSize(d->win, w, h); |
839 | updateRootSize_Window_(d); | 847 | updateRootSize_Window_(d, iFalse); |
840 | } | 848 | } |
841 | 849 | ||
842 | void setTitle_Window(iWindow *d, const iString *title) { | 850 | 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 { | |||
51 | 51 | ||
52 | iBool processEvent_Window (iWindow *, const SDL_Event *); | 52 | iBool processEvent_Window (iWindow *, const SDL_Event *); |
53 | void draw_Window (iWindow *); | 53 | void draw_Window (iWindow *); |
54 | void drawWhileResizing_Window(iWindow *d, int w, int h); /* workaround for SDL bug */ | ||
54 | void resize_Window (iWindow *, int w, int h); | 55 | void resize_Window (iWindow *, int w, int h); |
55 | void setTitle_Window (iWindow *, const iString *title); | 56 | void setTitle_Window (iWindow *, const iString *title); |
56 | void setUiScale_Window (iWindow *, float uiScale); | 57 | void setUiScale_Window (iWindow *, float uiScale); |