From 509c70c6982b6927f5a8d4fb32f9319cbaf0c2ef Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 8 Nov 2023 14:01:00 -0800 Subject: [PATCH] Allow the application to draw while Windows is in a modal move/resize loop SDL will send an SDL_EVENT_WINDOW_EXPOSED event for your window during the modal interaction and you can use an event watcher to redraw your window directly from the callback. Fixes https://github.com/libsdl-org/SDL/issues/1059 Closes https://github.com/libsdl-org/SDL/pull/4836 --- src/video/windows/SDL_windowsevents.c | 26 +++++++++++++++++++++ test/testsprite2.c | 33 +++++++++++++++++++++------ 2 files changed, 52 insertions(+), 7 deletions(-) diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index 180c1a8eb..66aa8b0b3 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -110,6 +110,10 @@ #define IS_SURROGATE_PAIR(h, l) (IS_HIGH_SURROGATE(h) && IS_LOW_SURROGATE(l)) #endif +#ifndef USER_TIMER_MINIMUM +#define USER_TIMER_MINIMUM 0x0000000A +#endif + static SDL_Scancode VKeytoScancodeFallback(WPARAM vkey) { switch (vkey) { @@ -675,6 +679,7 @@ WIN_KeyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam) LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { + static SDL_bool s_ModalMoveResizeLoop; SDL_WindowData *data; LRESULT returnCode = -1; @@ -1253,6 +1258,27 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) } } break; + case WM_ENTERSIZEMOVE: + case WM_ENTERMENULOOP: + { + SetTimer(hwnd, (UINT_PTR)&s_ModalMoveResizeLoop, USER_TIMER_MINIMUM, NULL); + } break; + + case WM_TIMER: + { + if (wParam == (UINT_PTR)&s_ModalMoveResizeLoop) { + // Send an expose event so the application can redraw + SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_EXPOSED, 0, 0); + return 0; + } + } break; + + case WM_EXITSIZEMOVE: + case WM_EXITMENULOOP: + { + KillTimer(hwnd, (UINT_PTR)&s_ModalMoveResizeLoop); + } break; + case WM_SIZE: { switch (wParam) { diff --git a/test/testsprite2.c b/test/testsprite2.c index 89037fd09..01c614883 100644 --- a/test/testsprite2.c +++ b/test/testsprite2.c @@ -392,22 +392,30 @@ void MoveSprites(SDL_Renderer *renderer, SDL_Texture *sprite) SDL_RenderPresent(renderer); } -void loop() +static void MoveAllSprites() { - Uint32 now; int i; - SDL_Event event; - /* Check for events */ - while (SDL_PollEvent(&event)) { - SDLTest_CommonEvent(state, &event, &done); - } for (i = 0; i < state->num_windows; ++i) { if (state->windows[i] == NULL) { continue; } MoveSprites(state->renderers[i], sprites[i]); } +} + +void loop() +{ + Uint32 now; + SDL_Event event; + + /* Check for events */ + while (SDL_PollEvent(&event)) { + SDLTest_CommonEvent(state, &event, &done); + } + + MoveAllSprites(); + #ifdef __EMSCRIPTEN__ if (done) { emscripten_cancel_main_loop(); @@ -426,6 +434,14 @@ void loop() } } +static int SDLCALL ExposeEventWatcher(void *userdata, SDL_Event *event) +{ + if (event->type == SDL_WINDOWEVENT && event->window.event == SDL_WINDOWEVENT_EXPOSED) { + MoveAllSprites(); + } + return 0; +} + int main(int argc, char *argv[]) { int i; @@ -568,6 +584,9 @@ int main(int argc, char *argv[]) } } + /* Add an event watcher to redraw from within modal window resize/move loops */ + SDL_AddEventWatch(ExposeEventWatcher, NULL); + /* Main render loop */ frames = 0; next_fps_check = SDL_GetTicks() + fps_check_delay;