diff options
-rw-r--r-- | source/blender/editors/interface/interface_handlers.c | 6 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_panel.c | 2 | ||||
-rw-r--r-- | source/blender/windowmanager/WM_api.h | 2 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_event_system.c | 29 | ||||
-rw-r--r-- | source/blender/windowmanager/wm_event_system.h | 2 |
5 files changed, 30 insertions, 11 deletions
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 |