From 548d8a397c39f43459af404170614db6a18ebde1 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 26 Jan 2021 21:56:49 +1100 Subject: Fix T85011: "Allow Execution" reloads the wrong file when recovering Support custom revert actions, necessary for recover operations to be able to reload the file with scripts enabled. --- source/blender/windowmanager/intern/wm_files.c | 80 ++++++++++++++++++++-- source/blender/windowmanager/intern/wm_init_exit.c | 3 + source/blender/windowmanager/wm_window.h | 1 + 3 files changed, 77 insertions(+), 7 deletions(-) (limited to 'source/blender/windowmanager') diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 21364f00acf..7680a786634 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -143,6 +143,8 @@ static void wm_history_file_free(RecentFile *recent); static void wm_history_file_update(void); static void wm_history_file_write(void); +static void wm_test_autorun_revert_action_exec(bContext *C); + /* -------------------------------------------------------------------- */ /** \name Misc Utility Functions * \{ */ @@ -669,6 +671,9 @@ static void wm_file_read_post(bContext *C, * won't be set to a valid value again */ CTX_wm_window_set(C, NULL); /* exits queues */ + /* Ensure auto-run action is not used from a previous blend file load. */ + wm_test_autorun_revert_action_set(NULL, NULL); + /* Ensure tools are registered. */ WM_toolsystem_init(C); } @@ -2543,7 +2548,16 @@ bool WM_recover_last_session(bContext *C, ReportList *reports) static int wm_recover_last_session_exec(bContext *C, wmOperator *op) { + wm_open_init_use_scripts(op, true); + SET_FLAG_FROM_TEST(G.f, RNA_boolean_get(op->ptr, "use_scripts"), G_FLAG_SCRIPT_AUTOEXEC); if (WM_recover_last_session(C, op->reports)) { + if (!G.background) { + wmOperatorType *ot = op->type; + PointerRNA *props_ptr = MEM_callocN(sizeof(PointerRNA), __func__); + WM_operator_properties_create_ptr(props_ptr, ot); + RNA_boolean_set(props_ptr, "use_scripts", true); + wm_test_autorun_revert_action_set(ot, props_ptr); + } return OPERATOR_FINISHED; } return OPERATOR_CANCELLED; @@ -2592,6 +2606,13 @@ static int wm_recover_auto_save_exec(bContext *C, wmOperator *op) G.fileflags &= ~G_FILE_RECOVER; if (success) { + if (!G.background) { + wmOperatorType *ot = op->type; + PointerRNA *props_ptr = MEM_callocN(sizeof(PointerRNA), __func__); + WM_operator_properties_create_ptr(props_ptr, ot); + RNA_boolean_set(props_ptr, "use_scripts", true); + wm_test_autorun_revert_action_set(ot, props_ptr); + } return OPERATOR_FINISHED; } return OPERATOR_CANCELLED; @@ -2892,6 +2913,9 @@ static void wm_block_autorun_warning_ignore(bContext *C, void *arg_block, void * { wmWindow *win = CTX_wm_window(C); UI_popup_block_close(C, win, arg_block); + + /* Free the data as it's no longer needed. */ + wm_test_autorun_revert_action_set(NULL, NULL); } static void wm_block_autorun_warning_reload_with_scripts(bContext *C, @@ -2909,13 +2933,7 @@ static void wm_block_autorun_warning_reload_with_scripts(bContext *C, /* Load file again with scripts enabled. * The reload is necessary to allow scripts to run when the files loads. */ - wmOperatorType *ot = WM_operatortype_find("WM_OT_revert_mainfile", false); - - PointerRNA props_ptr; - WM_operator_properties_create_ptr(&props_ptr, ot); - RNA_boolean_set(&props_ptr, "use_scripts", true); - WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &props_ptr); - WM_operator_properties_free(&props_ptr); + wm_test_autorun_revert_action_exec(C); } static void wm_block_autorun_warning_enable_scripts(bContext *C, @@ -3053,6 +3071,54 @@ static uiBlock *block_create_autorun_warning(struct bContext *C, return block; } +/** + * Store the action needed if the user needs to reload the file with Python scripts enabled. + * + * When left to NULL, this is simply revert. + * When loading files through the recover auto-save or session, + * we need to revert using other operators. + */ +static struct { + wmOperatorType *ot; + PointerRNA *ptr; +} wm_test_autorun_revert_action_data = { + .ot = NULL, + .ptr = NULL, +}; + +void wm_test_autorun_revert_action_set(wmOperatorType *ot, PointerRNA *ptr) +{ + BLI_assert(!G.background); + wm_test_autorun_revert_action_data.ot = NULL; + if (wm_test_autorun_revert_action_data.ptr != NULL) { + WM_operator_properties_free(wm_test_autorun_revert_action_data.ptr); + MEM_freeN(wm_test_autorun_revert_action_data.ptr); + wm_test_autorun_revert_action_data.ptr = NULL; + } + wm_test_autorun_revert_action_data.ot = ot; + wm_test_autorun_revert_action_data.ptr = ptr; +} + +void wm_test_autorun_revert_action_exec(bContext *C) +{ + wmOperatorType *ot = wm_test_autorun_revert_action_data.ot; + PointerRNA *ptr = wm_test_autorun_revert_action_data.ptr; + + /* Use regular revert. */ + if (ot == NULL) { + ot = WM_operatortype_find("WM_OT_revert_mainfile", false); + ptr = MEM_callocN(sizeof(PointerRNA), __func__); + WM_operator_properties_create_ptr(ptr, ot); + RNA_boolean_set(ptr, "use_scripts", true); + + /* Set state, so it's freed correctly */ + wm_test_autorun_revert_action_set(ot, ptr); + } + + WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, ptr); + wm_test_autorun_revert_action_set(NULL, NULL); +} + void wm_test_autorun_warning(bContext *C) { /* Test if any auto-execution of scripts failed. */ diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index d513598cf19..608aa116239 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -517,6 +517,9 @@ void WM_exit_ex(bContext *C, const bool do_python) BKE_blendfile_userdef_write_all(NULL); } } + /* Free the callback data used on file-open + * (will be set when a recover operation has run). */ + wm_test_autorun_revert_action_set(NULL, NULL); } } diff --git a/source/blender/windowmanager/wm_window.h b/source/blender/windowmanager/wm_window.h index 336db7edb50..0ac67b987d7 100644 --- a/source/blender/windowmanager/wm_window.h +++ b/source/blender/windowmanager/wm_window.h @@ -86,6 +86,7 @@ void wm_quit_with_optional_confirmation_prompt(bContext *C, wmWindow *win) ATTR_ int wm_window_new_exec(bContext *C, struct wmOperator *op); int wm_window_new_main_exec(bContext *C, struct wmOperator *op); +void wm_test_autorun_revert_action_set(struct wmOperatorType *ot, struct PointerRNA *ptr); void wm_test_autorun_warning(bContext *C); #ifdef __cplusplus -- cgit v1.2.3