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,25 +1277,28 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ar->headerstr) {
|
if (ar->headerstr) {
|
||||||
MEM_freeN(ar->headerstr);
|
MEM_freeN(ar->headerstr);
|
||||||
ar->headerstr = NULL;
|
ar->headerstr = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
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