[Bf-blender-cvs] [4811b2d] blender2.8: Proper fix for crash when joining areas that doesn't break manipulators

Julian Eisel noreply at git.blender.org
Mon Oct 17 19:29:36 CEST 2016


Commit: 4811b2d3565cf72a08d8bc55d1717e71d18f7df1
Author: Julian Eisel
Date:   Mon Oct 17 19:25:56 2016 +0200
Branches: blender2.8
https://developer.blender.org/rB4811b2d3565cf72a08d8bc55d1717e71d18f7df1

Proper fix for crash when joining areas that doesn't break manipulators

Turns out CTX_wm_region returns mostly NULL in wm_manipulatormaps_handled_modal_update. Now propertly unsetting area/region data of handlers when deleting area/region.

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

M	source/blender/editors/screen/screen_edit.c
M	source/blender/windowmanager/WM_api.h
M	source/blender/windowmanager/intern/wm_event_system.c
M	source/blender/windowmanager/manipulators/intern/wm_manipulatormap.c

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

diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index 3d30f2b..5e00d15 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -1277,25 +1277,28 @@ void ED_screens_initialize(wmWindowManager *wm)
 void ED_region_exit(bContext *C, ARegion *ar)
 {
 	wmWindowManager *wm = CTX_wm_manager(C);
+	wmWindow *win = CTX_wm_window(C);
 	ARegion *prevar = CTX_wm_region(C);
 
 	if (ar->type && ar->type->exit)
 		ar->type->exit(wm, ar);
 
 	CTX_wm_region_set(C, ar);
+
 	WM_event_remove_handlers(C, &ar->handlers);
+	WM_event_modal_handler_region_replace(win, ar, NULL);
 	if (ar->swinid) {
-		wm_subwindow_close(CTX_wm_window(C), ar->swinid);
+		wm_subwindow_close(win, ar->swinid);
 		ar->swinid = 0;
 	}
-	
+
 	if (ar->headerstr) {
 		MEM_freeN(ar->headerstr);
 		ar->headerstr = NULL;
 	}
 	
 	if (ar->regiontimer) {
-		WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), ar->regiontimer);
+		WM_event_remove_timer(wm, win, ar->regiontimer);
 		ar->regiontimer = NULL;
 	}
 
@@ -1305,6 +1308,7 @@ void ED_region_exit(bContext *C, ARegion *ar)
 void ED_area_exit(bContext *C, ScrArea *sa)
 {
 	wmWindowManager *wm = CTX_wm_manager(C);
+	wmWindow *win = CTX_wm_window(C);
 	ScrArea *prevsa = CTX_wm_area(C);
 	ARegion *ar;
 
@@ -1312,10 +1316,13 @@ void ED_area_exit(bContext *C, ScrArea *sa)
 		sa->type->exit(wm, sa);
 
 	CTX_wm_area_set(C, sa);
+
 	for (ar = sa->regionbase.first; ar; ar = ar->next)
 		ED_region_exit(C, ar);
 
 	WM_event_remove_handlers(C, &sa->handlers);
+	WM_event_modal_handler_area_replace(win, sa, NULL);
+
 	CTX_wm_area_set(C, prevsa);
 }
 
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index 4d159c6..2809795 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -67,6 +67,7 @@ struct wmDrag;
 struct ImBuf;
 struct ImageFormatData;
 struct ARegion;
+struct ScrArea;
 
 #ifdef WITH_INPUT_NDOF
 struct wmNDOFMotionData;
@@ -177,6 +178,9 @@ void WM_event_free_ui_handler_all(
         wmUIHandlerFunc ui_handle, wmUIHandlerRemoveFunc ui_remove);
 
 struct wmEventHandler *WM_event_add_modal_handler(struct bContext *C, struct wmOperator *op);
+void WM_event_modal_handler_area_replace(wmWindow *win, const struct ScrArea *old_area, struct ScrArea *new_area);
+void WM_event_modal_handler_region_replace(wmWindow *win, const struct ARegion *old_region, struct ARegion *new_region);
+
 void		WM_event_remove_handlers(struct bContext *C, ListBase *handlers);
 
 /* handler flag */
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index a75b3b1..b15b47c 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -2717,6 +2717,33 @@ wmEventHandler *WM_event_add_modal_handler(bContext *C, wmOperator *op)
 	return handler;
 }
 
+/**
+ * Modal handlers store a pointer to an area which might be freed while the handler runs.
+ * Use this function to NULL all handler pointers to \a old_area.
+ */
+void WM_event_modal_handler_area_replace(wmWindow *win, const ScrArea *old_area, ScrArea *new_area)
+{
+	for (wmEventHandler *handler = win->modalhandlers.first; handler; handler = handler->next) {
+		if (handler->op_area == old_area) {
+			handler->op_area = new_area;
+		}
+	}
+}
+
+/**
+ * Modal handlers store a pointer to a region which might be freed while the handler runs.
+ * Use this function to NULL all handler pointers to \a old_region.
+ */
+void WM_event_modal_handler_region_replace(wmWindow *win, const ARegion *old_region, ARegion *new_region)
+{
+	for (wmEventHandler *handler = win->modalhandlers.first; handler; handler = handler->next) {
+		if (handler->op_region == old_region) {
+			handler->op_region = new_region;
+			handler->op_region_type = new_region ? new_region->regiontype : RGN_TYPE_WINDOW;
+		}
+	}
+}
+
 wmEventHandler *WM_event_add_keymap_handler(ListBase *handlers, wmKeyMap *keymap)
 {
 	wmEventHandler *handler;
diff --git a/source/blender/windowmanager/manipulators/intern/wm_manipulatormap.c b/source/blender/windowmanager/manipulators/intern/wm_manipulatormap.c
index eada6e3..500092f 100644
--- a/source/blender/windowmanager/manipulators/intern/wm_manipulatormap.c
+++ b/source/blender/windowmanager/manipulators/intern/wm_manipulatormap.c
@@ -394,12 +394,10 @@ void wm_manipulatormaps_handled_modal_update(
         bContext *C, wmEvent *event, wmEventHandler *handler,
         const wmOperatorType *ot)
 {
-	ScrArea *area = CTX_wm_area(C);
-	ARegion *region = CTX_wm_region(C);
 	const bool modal_running = (handler->op != NULL);
 
 	/* happens on render or when joining areas */
-	if (!region || !region->manipulator_map)
+	if (!handler->op_region || !handler->op_region->manipulator_map)
 		return;
 
 	/* hide operator manipulators */
@@ -407,8 +405,10 @@ void wm_manipulatormaps_handled_modal_update(
 		ot->mgrouptype->op = NULL;
 	}
 
-	wmManipulatorMap *mmap = region->manipulator_map;
+	wmManipulatorMap *mmap = handler->op_region->manipulator_map;
 	wmManipulator *manipulator = wm_manipulatormap_get_active_manipulator(mmap);
+	ScrArea *area = CTX_wm_area(C);
+	ARegion *region = CTX_wm_region(C);
 
 	wm_manipulatormap_handler_context(C, handler);




More information about the Bf-blender-cvs mailing list