[Bf-blender-cvs] [3ba72049270] topbar: Fix context issues when using operator repeat from top-bar

Julian Eisel noreply at git.blender.org
Thu Nov 23 19:54:46 CET 2017


Commit: 3ba72049270cc7fbd36e5364de31491d2bdb66bf
Author: Julian Eisel
Date:   Thu Nov 23 19:53:22 2017 +0100
Branches: topbar
https://developer.blender.org/rB3ba72049270cc7fbd36e5364de31491d2bdb66bf

Fix context issues when using operator repeat from top-bar

Use same fix for it as rB815eebbe17ab632.

===================================================================

M	source/blender/editors/include/ED_util.h
M	source/blender/editors/util/undo.c
M	source/blender/windowmanager/intern/wm_event_system.c

===================================================================

diff --git a/source/blender/editors/include/ED_util.h b/source/blender/editors/include/ED_util.h
index 60c4b3593aa..d8b92ffde41 100644
--- a/source/blender/editors/include/ED_util.h
+++ b/source/blender/editors/include/ED_util.h
@@ -31,11 +31,15 @@
 #ifndef __ED_UTIL_H__
 #define __ED_UTIL_H__
 
+#include "BLI_compiler_attrs.h"
+
 struct bContext;
 struct SpaceLink;
 struct wmOperator;
 struct wmOperatorType;
 
+typedef struct OperatorRepeatContextHandle OperatorRepeatContextHandle;
+
 /* ed_util.c */
 
 void    ED_editors_init(struct bContext *C);
@@ -67,6 +71,11 @@ int     ED_undo_operator_repeat(struct bContext *C, struct wmOperator *op);
 /* convenience since UI callbacks use this mostly*/
 void    ED_undo_operator_repeat_cb(struct bContext *C, void *arg_op, void *arg_unused);
 void    ED_undo_operator_repeat_cb_evt(struct bContext *C, void *arg_op, int arg_unused);
+/* Context sanity helpers for operator repeat. */
+const OperatorRepeatContextHandle *ED_operator_repeat_prepare_context(
+        bContext *C, struct wmOperator *op) ATTR_WARN_UNUSED_RESULT;
+void ED_operator_repeat_reset_context(
+        bContext *C, const OperatorRepeatContextHandle *context_info);
 
 bool    ED_undo_is_valid(const struct bContext *C, const char *undoname);
 
diff --git a/source/blender/editors/util/undo.c b/source/blender/editors/util/undo.c
index dcc2ac41732..9570061a562 100644
--- a/source/blender/editors/util/undo.c
+++ b/source/blender/editors/util/undo.c
@@ -395,19 +395,47 @@ void ED_OT_undo_redo(wmOperatorType *ot)
 	ot->poll = ed_undo_redo_poll;
 }
 
+struct OperatorRepeatContextHandle {
+	ScrArea *restore_area;
+	ARegion *restore_region;
+};
+
+/**
+ * Resets the context to the state \a op was executed in (or at least, was in when registering).
+ * #ED_operator_repeat_reset_context should be called when done repeating!
+ */
+const OperatorRepeatContextHandle *ED_operator_repeat_prepare_context(bContext *C, wmOperator *op)
+{
+	static OperatorRepeatContextHandle context_info;
+
+	context_info.restore_area = CTX_wm_area(C);
+	context_info.restore_region = CTX_wm_region(C);
+
+	CTX_wm_area_set(C, op->execution_area);
+	CTX_wm_region_set(C, op->execution_region);
+
+	return &context_info;
+}
+/**
+ * Resets context to the old state from before #ED_operator_repeat_prepare_context was called.
+ */
+void ED_operator_repeat_reset_context(bContext *C, const OperatorRepeatContextHandle *context_info)
+{
+	CTX_wm_area_set(C, context_info->restore_area);
+	CTX_wm_region_set(C, context_info->restore_region);
+}
+
 /* ui callbacks should call this rather than calling WM_operator_repeat() themselves */
-int ED_undo_operator_repeat(bContext *C, struct wmOperator *op)
+int ED_undo_operator_repeat(bContext *C, wmOperator *op)
 {
 	int ret = 0;
 
 	if (op) {
 		wmWindowManager *wm = CTX_wm_manager(C);
 		struct Scene *cur_scene = CTX_data_scene(C);
-		ScrArea *cur_area = CTX_wm_area(C);
-		ARegion *cur_region = CTX_wm_region(C);
+		const OperatorRepeatContextHandle *context_info;
 
-		CTX_wm_area_set(C, op->execution_area);
-		CTX_wm_region_set(C, op->execution_region);
+		context_info = ED_operator_repeat_prepare_context(C, op);
 
 		if ((WM_operator_repeat_check(C, op)) &&
 		    (WM_operator_poll(C, op->type)) &&
@@ -455,8 +483,7 @@ int ED_undo_operator_repeat(bContext *C, struct wmOperator *op)
 			}
 		}
 
-		CTX_wm_area_set(C, cur_area);
-		CTX_wm_region_set(C, cur_region);
+		ED_operator_repeat_reset_context(C, context_info);
 	}
 	else {
 		if (G.debug & G_DEBUG) {
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index 71a89eb84fe..4902a4bd0bc 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -915,7 +915,14 @@ int WM_operator_call_notest(bContext *C, wmOperator *op)
  */
 int WM_operator_repeat(bContext *C, wmOperator *op)
 {
-	return wm_operator_exec(C, op, true, true);
+	const OperatorRepeatContextHandle *context_info;
+	int retval;
+
+	context_info = ED_operator_repeat_prepare_context(C, op);
+	retval = wm_operator_exec(C, op, true, true);
+	ED_operator_repeat_reset_context(C, context_info);
+
+	return retval;
 }
 /**
  * \return true if #WM_operator_repeat can run



More information about the Bf-blender-cvs mailing list