Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorTon Roosendaal <ton@blender.org>2011-04-20 15:15:58 +0400
committerTon Roosendaal <ton@blender.org>2011-04-20 15:15:58 +0400
commit069a3c193c19842d126579e22237da3880333ac5 (patch)
treeebd88357900973d44f1dd6dc9613508233b6aba5 /source
parent141be02c90cbdb2f1d8cd2702ea79e3b3e9590f7 (diff)
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.
Diffstat (limited to 'source')
-rw-r--r--source/blender/editors/interface/interface_handlers.c6
-rw-r--r--source/blender/editors/interface/interface_panel.c2
-rw-r--r--source/blender/windowmanager/WM_api.h2
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c29
-rw-r--r--source/blender/windowmanager/wm_event_system.h2
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