From 069a3c193c19842d126579e22237da3880333ac5 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Wed, 20 Apr 2011 11:15:58 +0000 Subject: Bugfix #27058 Top bar: Add -> Mesh -> UV Sphere + Enter crashed. It didn't crash with leftmouse, but that was coincidentally working. Menus were freeing modal handlers in Window, while handlers were still in use. Fix provides to tag handlers for being freed now. Will add on my attention list for more elaborate checking work here, for upcoming 2.57a I rather stick to minimal change in code here. --- .../blender/editors/interface/interface_handlers.c | 6 ++--- source/blender/editors/interface/interface_panel.c | 2 +- source/blender/windowmanager/WM_api.h | 2 +- .../blender/windowmanager/intern/wm_event_system.c | 29 +++++++++++++++++----- source/blender/windowmanager/wm_event_system.h | 2 ++ 5 files changed, 30 insertions(+), 11 deletions(-) (limited to 'source') diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index d3aa5bc9132..cf11effc57b 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -4898,7 +4898,7 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s } else { if(button_modal_state(data->state)) - WM_event_remove_ui_handler(&data->window->modalhandlers, ui_handler_region_menu, NULL, data); + WM_event_remove_ui_handler(&data->window->modalhandlers, ui_handler_region_menu, NULL, data, 1); /* 1 = postpone free */ } } @@ -6154,7 +6154,7 @@ static void ui_handler_remove_popup(bContext *C, void *userdata) void UI_add_region_handlers(ListBase *handlers) { - WM_event_remove_ui_handler(handlers, ui_handler_region, ui_handler_remove_region, NULL); + WM_event_remove_ui_handler(handlers, ui_handler_region, ui_handler_remove_region, NULL, 0); WM_event_add_ui_handler(NULL, handlers, ui_handler_region, ui_handler_remove_region, NULL); } @@ -6165,7 +6165,7 @@ void UI_add_popup_handlers(bContext *C, ListBase *handlers, uiPopupBlockHandle * void UI_remove_popup_handlers(ListBase *handlers, uiPopupBlockHandle *popup) { - WM_event_remove_ui_handler(handlers, ui_handler_popup, ui_handler_remove_popup, popup); + WM_event_remove_ui_handler(handlers, ui_handler_popup, ui_handler_remove_popup, popup, 0); } diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index b47194ba1b4..6677f2b1bae 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -1211,7 +1211,7 @@ static void panel_activate_state(const bContext *C, Panel *pa, uiHandlePanelStat MEM_freeN(data); pa->activedata= NULL; - WM_event_remove_ui_handler(&win->modalhandlers, ui_handler_panel, ui_handler_remove_panel, pa); + WM_event_remove_ui_handler(&win->modalhandlers, ui_handler_panel, ui_handler_remove_panel, pa, 0); } else { if(!data) { diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index dafa05fd974..1b4fff8cd13 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -173,7 +173,7 @@ struct wmEventHandler *WM_event_add_ui_handler(const struct bContext *C, ListBas void (*remove)(struct bContext *C, void *userdata), void *userdata); void WM_event_remove_ui_handler(ListBase *handlers, int (*func)(struct bContext *C, struct wmEvent *event, void *userdata), - void (*remove)(struct bContext *C, void *userdata), void *userdata); + void (*remove)(struct bContext *C, void *userdata), void *userdata, int postpone); void WM_event_remove_area_handler(struct ListBase *handlers, void *area); struct wmEventHandler *WM_event_add_modal_handler(struct bContext *C, struct wmOperator *op); diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 2b74d35d59e..c9e2567a45b 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -1452,10 +1452,13 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) /* modal handlers can get removed in this loop, we keep the loop this way */ for(handler= handlers->first; handler; handler= nexthandler) { + nexthandler= handler->next; - - /* optional boundbox */ - if(handler_boundbox_test(handler, event)) { + + /* during this loop, ui handlers for nested menus can tag multiple handlers free */ + if(handler->flag & WM_HANDLER_DO_FREE); + /* optional boundbox */ + else if(handler_boundbox_test(handler, event)) { /* in advance to avoid access to freed event on window close */ always_pass= wm_event_always_pass(event); @@ -1534,6 +1537,13 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) } } + /* modal ui handler can be tagged to be freed */ + if(handler->flag & WM_HANDLER_DO_FREE) { + BLI_remlink(handlers, handler); + wm_event_free_handler(handler); + } + + /* XXX fileread case */ if(CTX_wm_window(C)==NULL) return action; @@ -2067,14 +2077,21 @@ wmEventHandler *WM_event_add_ui_handler(const bContext *C, ListBase *handlers, w return handler; } -void WM_event_remove_ui_handler(ListBase *handlers, wmUIHandlerFunc func, wmUIHandlerRemoveFunc remove, void *userdata) +/* set "postpone" for win->modalhandlers, this is in a running for() loop in wm_handlers_do() */ +void WM_event_remove_ui_handler(ListBase *handlers, wmUIHandlerFunc func, wmUIHandlerRemoveFunc remove, void *userdata, int postpone) { wmEventHandler *handler; for(handler= handlers->first; handler; handler= handler->next) { if(handler->ui_handle == func && handler->ui_remove == remove && handler->ui_userdata == userdata) { - BLI_remlink(handlers, handler); - wm_event_free_handler(handler); + /* handlers will be freed in wm_handlers_do() */ + if(postpone) { + handler->flag |= WM_HANDLER_DO_FREE; + } + else { + BLI_remlink(handlers, handler); + wm_event_free_handler(handler); + } break; } } diff --git a/source/blender/windowmanager/wm_event_system.h b/source/blender/windowmanager/wm_event_system.h index 6ad9d1daede..cd110d3bc1a 100644 --- a/source/blender/windowmanager/wm_event_system.h +++ b/source/blender/windowmanager/wm_event_system.h @@ -78,6 +78,8 @@ typedef struct wmEventHandler { /* handler flag */ /* after this handler all others are ignored */ #define WM_HANDLER_BLOCKING 1 + /* handler tagged to be freed in wm_handlers_do() */ +#define WM_HANDLER_DO_FREE 2 -- cgit v1.2.3