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.
This commit is contained in:
		| @@ -1277,15 +1277,18 @@ void ED_screens_initialize(wmWindowManager *wm) | |||||||
| void ED_region_exit(bContext *C, ARegion *ar) | void ED_region_exit(bContext *C, ARegion *ar) | ||||||
| { | { | ||||||
| 	wmWindowManager *wm = CTX_wm_manager(C); | 	wmWindowManager *wm = CTX_wm_manager(C); | ||||||
|  | 	wmWindow *win = CTX_wm_window(C); | ||||||
| 	ARegion *prevar = CTX_wm_region(C); | 	ARegion *prevar = CTX_wm_region(C); | ||||||
|  |  | ||||||
| 	if (ar->type && ar->type->exit) | 	if (ar->type && ar->type->exit) | ||||||
| 		ar->type->exit(wm, ar); | 		ar->type->exit(wm, ar); | ||||||
|  |  | ||||||
| 	CTX_wm_region_set(C, ar); | 	CTX_wm_region_set(C, ar); | ||||||
|  |  | ||||||
| 	WM_event_remove_handlers(C, &ar->handlers); | 	WM_event_remove_handlers(C, &ar->handlers); | ||||||
|  | 	WM_event_modal_handler_region_replace(win, ar, NULL); | ||||||
| 	if (ar->swinid) { | 	if (ar->swinid) { | ||||||
| 		wm_subwindow_close(CTX_wm_window(C), ar->swinid); | 		wm_subwindow_close(win, ar->swinid); | ||||||
| 		ar->swinid = 0; | 		ar->swinid = 0; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -1295,7 +1298,7 @@ void ED_region_exit(bContext *C, ARegion *ar) | |||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
| 	if (ar->regiontimer) { | 	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; | 		ar->regiontimer = NULL; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -1305,6 +1308,7 @@ void ED_region_exit(bContext *C, ARegion *ar) | |||||||
| void ED_area_exit(bContext *C, ScrArea *sa) | void ED_area_exit(bContext *C, ScrArea *sa) | ||||||
| { | { | ||||||
| 	wmWindowManager *wm = CTX_wm_manager(C); | 	wmWindowManager *wm = CTX_wm_manager(C); | ||||||
|  | 	wmWindow *win = CTX_wm_window(C); | ||||||
| 	ScrArea *prevsa = CTX_wm_area(C); | 	ScrArea *prevsa = CTX_wm_area(C); | ||||||
| 	ARegion *ar; | 	ARegion *ar; | ||||||
|  |  | ||||||
| @@ -1312,10 +1316,13 @@ void ED_area_exit(bContext *C, ScrArea *sa) | |||||||
| 		sa->type->exit(wm, sa); | 		sa->type->exit(wm, sa); | ||||||
|  |  | ||||||
| 	CTX_wm_area_set(C, sa); | 	CTX_wm_area_set(C, sa); | ||||||
|  |  | ||||||
| 	for (ar = sa->regionbase.first; ar; ar = ar->next) | 	for (ar = sa->regionbase.first; ar; ar = ar->next) | ||||||
| 		ED_region_exit(C, ar); | 		ED_region_exit(C, ar); | ||||||
|  |  | ||||||
| 	WM_event_remove_handlers(C, &sa->handlers); | 	WM_event_remove_handlers(C, &sa->handlers); | ||||||
|  | 	WM_event_modal_handler_area_replace(win, sa, NULL); | ||||||
|  |  | ||||||
| 	CTX_wm_area_set(C, prevsa); | 	CTX_wm_area_set(C, prevsa); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -67,6 +67,7 @@ struct wmDrag; | |||||||
| struct ImBuf; | struct ImBuf; | ||||||
| struct ImageFormatData; | struct ImageFormatData; | ||||||
| struct ARegion; | struct ARegion; | ||||||
|  | struct ScrArea; | ||||||
|  |  | ||||||
| #ifdef WITH_INPUT_NDOF | #ifdef WITH_INPUT_NDOF | ||||||
| struct wmNDOFMotionData; | struct wmNDOFMotionData; | ||||||
| @@ -177,6 +178,9 @@ void WM_event_free_ui_handler_all( | |||||||
|         wmUIHandlerFunc ui_handle, wmUIHandlerRemoveFunc ui_remove); |         wmUIHandlerFunc ui_handle, wmUIHandlerRemoveFunc ui_remove); | ||||||
|  |  | ||||||
| struct wmEventHandler *WM_event_add_modal_handler(struct bContext *C, struct wmOperator *op); | 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); | void		WM_event_remove_handlers(struct bContext *C, ListBase *handlers); | ||||||
|  |  | ||||||
| /* handler flag */ | /* handler flag */ | ||||||
|   | |||||||
| @@ -2717,6 +2717,33 @@ wmEventHandler *WM_event_add_modal_handler(bContext *C, wmOperator *op) | |||||||
| 	return handler; | 	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 *WM_event_add_keymap_handler(ListBase *handlers, wmKeyMap *keymap) | ||||||
| { | { | ||||||
| 	wmEventHandler *handler; | 	wmEventHandler *handler; | ||||||
|   | |||||||
| @@ -394,12 +394,10 @@ void wm_manipulatormaps_handled_modal_update( | |||||||
|         bContext *C, wmEvent *event, wmEventHandler *handler, |         bContext *C, wmEvent *event, wmEventHandler *handler, | ||||||
|         const wmOperatorType *ot) |         const wmOperatorType *ot) | ||||||
| { | { | ||||||
| 	ScrArea *area = CTX_wm_area(C); |  | ||||||
| 	ARegion *region = CTX_wm_region(C); |  | ||||||
| 	const bool modal_running = (handler->op != NULL); | 	const bool modal_running = (handler->op != NULL); | ||||||
|  |  | ||||||
| 	/* happens on render or when joining areas */ | 	/* happens on render or when joining areas */ | ||||||
| 	if (!region || !region->manipulator_map) | 	if (!handler->op_region || !handler->op_region->manipulator_map) | ||||||
| 		return; | 		return; | ||||||
|  |  | ||||||
| 	/* hide operator manipulators */ | 	/* hide operator manipulators */ | ||||||
| @@ -407,8 +405,10 @@ void wm_manipulatormaps_handled_modal_update( | |||||||
| 		ot->mgrouptype->op = NULL; | 		ot->mgrouptype->op = NULL; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	wmManipulatorMap *mmap = region->manipulator_map; | 	wmManipulatorMap *mmap = handler->op_region->manipulator_map; | ||||||
| 	wmManipulator *manipulator = wm_manipulatormap_get_active_manipulator(mmap); | 	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); | 	wm_manipulatormap_handler_context(C, handler); | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Julian Eisel
					Julian Eisel