Bugfix #27058
[blender.git] / source / blender / windowmanager / intern / wm_event_system.c
index 2b74d35d59e55c94e319a25a4d10002ff40dfdd6..c9e2567a45b372f835cd8ac9f2faa0436ac5e417 100644 (file)
@@ -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;
                }
        }