From c7a65c93136e9f74b8bbca7db149b30b7b55365c Mon Sep 17 00:00:00 2001 From: zicodxx Date: Thu, 3 Feb 2011 11:48:27 +0100 Subject: [PATCH] Included new window structure flag w_closing_state and let window_close() set this flag - after drawing all windows, check them again and call window_do_close() which then actually closes the window(s) marked to. Solving all sorts of problems when windows close while being drawn (network error messageboxes, game_leave_menus(), etc.) --- CHANGELOG.txt | 1 + arch/include/window.h | 1 + arch/sdl/event.c | 15 +++++++++------ arch/sdl/window.c | 20 +++++++++++++++++--- 4 files changed, 28 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 8af070359..5c1da85b8 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -4,6 +4,7 @@ D2X-Rebirth Changelog -------- main/automap.c, main/gamecntl.c: Little fixes for recent kconfig/event overhaul: Automap inputs read by kconfig should be processed by input rather than idle and automap frame calculations should be done while drawing; Fixed drop_bomb_count which could roll over to 255 dropping bombs without end main/gauges: Corrected values for gr_ubox while drawing a window_view to not mess up at some widescreen resolutions +arch/include/window.h, arch/sdl/event.c, arch/sdl/window.c: Included new window structure flag w_closing_state and let window_close() set this flag - after drawing all windows, check them again and call window_do_close() which then actually closes the window(s) marked to. Solving all sorts of problems when windows close while being drawn (network error messageboxes, game_leave_menus(), etc.) 20110202 -------- diff --git a/arch/include/window.h b/arch/include/window.h index f6bf26af0..4122721c0 100644 --- a/arch/include/window.h +++ b/arch/include/window.h @@ -19,6 +19,7 @@ typedef struct window window; extern window *window_create(grs_canvas *src, int x, int y, int w, int h, int (*event_callback)(window *wind, d_event *event, void *data), void *data); extern int window_close(window *wind); +extern int window_do_close(window *wind); extern int window_exists(window *wind); extern window *window_get_front(void); extern window *window_get_first(void); diff --git a/arch/sdl/event.c b/arch/sdl/event.c index de0f95b26..229e562d4 100644 --- a/arch/sdl/event.c +++ b/arch/sdl/event.c @@ -152,16 +152,19 @@ void event_process(void) return; event.type = EVENT_WINDOW_DRAW; // then draw all visible windows - wind = window_get_first(); - while (wind != NULL) - { - window *next_wind = window_get_next(wind); // check this in now in case this window closes during EVENT_WINDOW_DRAW + for (wind = window_get_first(); wind != NULL; wind = window_get_next(wind)) if (window_is_visible(wind)) window_send_event(wind, &event); - wind = next_wind; - } gr_flip(); + + wind = window_get_first(); + while (wind != NULL) // go through all windows and actually close them if they want to + { + window *next_wind = window_get_next(wind); + window_do_close(wind); + wind = next_wind; + } } void event_toggle_focus(int activate_focus) diff --git a/arch/sdl/window.c b/arch/sdl/window.c index 16286ebd2..504774cc4 100644 --- a/arch/sdl/window.c +++ b/arch/sdl/window.c @@ -18,6 +18,7 @@ struct window grs_canvas w_canv; // the window's canvas to draw to int (*w_callback)(window *wind, d_event *event, void *data); // the event handler int w_visible; // whether it's visible + ubyte w_closing_state; void *data; // whatever the user wants (eg menu data for 'newmenu' menus) struct window *prev; // the previous window in the doubly linked list struct window *next; // the next window in the doubly linked list @@ -41,6 +42,7 @@ window *window_create(grs_canvas *src, int x, int y, int w, int h, int (*event_c gr_init_sub_canvas(&wind->w_canv, src, x, y, w, h); wind->w_callback = event_callback; wind->w_visible = 1; // default to visible + wind->w_closing_state = 0; wind->data = data; if (FirstWindow == NULL) @@ -59,11 +61,20 @@ window *window_create(grs_canvas *src, int x, int y, int w, int h, int (*event_c } int window_close(window *wind) +{ + wind->w_closing_state = 1; // mark this window to close + + return 1; +} + +int window_do_close(window *wind) { window *prev; d_event event; int (*w_callback)(window *wind, d_event *event, void *data) = wind->w_callback; + if (!wind->w_closing_state) + return 0; if (wind == window_get_front()) WINDOW_SEND_EVENT(wind, EVENT_WINDOW_DEACTIVATED); // Deactivate first @@ -74,7 +85,10 @@ int window_close(window *wind) { // User 'handled' the event, cancelling close if (wind == window_get_front()) - WINDOW_SEND_EVENT(wind, EVENT_WINDOW_ACTIVATED); // Reactivate. May cause flashing of some sort, too bad + { + WINDOW_SEND_EVENT(wind, EVENT_WINDOW_ACTIVATED); + wind->w_closing_state = 0; + } return 0; } @@ -88,8 +102,8 @@ int window_close(window *wind) wind->prev->next = wind->next; if ((prev = window_get_front())) - WINDOW_SEND_EVENT(prev, EVENT_WINDOW_ACTIVATED); // Reactivate. May cause flashing of some sort, too bad - + WINDOW_SEND_EVENT(prev, EVENT_WINDOW_ACTIVATED); + d_free(wind); event.type = EVENT_WINDOW_CLOSED;