diff options
-rw-r--r-- | source/blender/windowmanager/intern/wm_init_exit.c | 28 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_operators.c | 5 | ||||
-rw-r--r-- | source/blender/windowmanager/wm.h | 3 |
3 files changed, 33 insertions, 3 deletions
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 7608b015f49..4fcbff6bf98 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -434,6 +434,30 @@ static void wait_for_console_key(void) } #endif +static int wm_exit_handler(bContext *C, const wmEvent *event, void *userdata) +{ + WM_exit(C); + + UNUSED_VARS(event, userdata); + return WM_UI_HANDLER_BREAK; +} + +/** + * Cause a delayed WM_exit() call to avoid leaking memory when trying to exit from within operators. + */ +void wm_exit_schedule_delayed(const bContext *C) +{ + /* What we do here is a little bit hacky, but quite simple and doesn't require bigger + * changes: Add a handler wrapping WM_exit() to cause a delayed call of it. */ + + wmWindowManager *wm = CTX_wm_manager(C); + /* Doesn't matter which window we use. */ + wmWindow *win = wm->windows.first; + + /* Use modal UI handler for now. Could add separate WM handlers or so, but probably not worth it. */ + WM_event_add_ui_handler(C, &win->modalhandlers, wm_exit_handler, NULL, NULL, 0); +} + /** * \note doesn't run exit() call #WM_exit() for that. */ @@ -604,6 +628,10 @@ void WM_exit_ext(bContext *C, const bool do_python) BKE_tempdir_session_purge(); } +/** + * \brief Main exit function to close Blender ordinarily. + * \note Use #wm_exit_schedule_delayed() to close Blender from an operator. Might leak memory otherwise. + */ void WM_exit(bContext *C) { WM_exit_ext(C, 1); diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 363b8e61763..bf2f00e9460 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -2160,7 +2160,7 @@ static void WM_OT_window_fullscreen_toggle(wmOperatorType *ot) ot->poll = WM_operator_winactive; } -static int wm_exit_blender_exec(bContext *C, wmOperator *op) +static int wm_exit_blender_exec(bContext *C, wmOperator *UNUSED(op)) { wmWindowManager *wm = CTX_wm_manager(C); @@ -2168,8 +2168,7 @@ static int wm_exit_blender_exec(bContext *C, wmOperator *op) wm_confirm_quit(C); } else { - WM_operator_free(op); - WM_exit(C); + wm_exit_schedule_delayed(C); } return OPERATOR_FINISHED; diff --git a/source/blender/windowmanager/wm.h b/source/blender/windowmanager/wm.h index a417a719b8d..5ced36a104f 100644 --- a/source/blender/windowmanager/wm.h +++ b/source/blender/windowmanager/wm.h @@ -43,6 +43,9 @@ typedef struct wmPaintCursor { void (*draw)(bContext *C, int, int, void *customdata); } wmPaintCursor; + +void wm_exit_schedule_delayed(const bContext *C); + extern void wm_close_and_free(bContext *C, wmWindowManager *); extern void wm_close_and_free_all(bContext *C, ListBase *); |