diff options
author | Campbell Barton <ideasman42@gmail.com> | 2021-10-15 16:42:19 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2021-10-15 17:13:28 +0300 |
commit | 6e4ab5b761b03b52177985ecbeb2c2f576159c74 (patch) | |
tree | b9e14c71a9840adfe578c73a45a5dce5e7fb1d54 /source | |
parent | d4f1bc5f39b219466978a1c9e74618ff8fa27433 (diff) |
Fix crash handling tool-keymap events
There was a rare crash in WM_event_get_keymap_from_toolsystem_fallback
when wm->winactive was NULL.
This could happen when the event was handled
immediately after closing a window.
Diffstat (limited to 'source')
4 files changed, 86 insertions, 32 deletions
diff --git a/source/blender/editors/interface/interface_template_search_menu.c b/source/blender/editors/interface/interface_template_search_menu.c index 3a5d65475f7..bbb04a9911c 100644 --- a/source/blender/editors/interface/interface_template_search_menu.c +++ b/source/blender/editors/interface/interface_template_search_menu.c @@ -351,7 +351,7 @@ static void menu_types_add_from_keymap_items(bContext *C, if (handler_base->poll == NULL || handler_base->poll(region, win->eventstate)) { wmEventHandler_Keymap *handler = (wmEventHandler_Keymap *)handler_base; wmEventHandler_KeymapResult km_result; - WM_event_get_keymaps_from_handler(wm, handler, &km_result); + WM_event_get_keymaps_from_handler(wm, win, handler, &km_result); for (int km_index = 0; km_index < km_result.keymaps_len; km_index++) { wmKeyMap *keymap = km_result.keymaps[km_index]; if (keymap && WM_keymap_poll(C, keymap)) { diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 26406966952..4ee514edb3c 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -272,13 +272,16 @@ typedef struct wmEventHandler_KeymapResult { } wmEventHandler_KeymapResult; typedef void(wmEventHandler_KeymapDynamicFn)(wmWindowManager *wm, + struct wmWindow *win, struct wmEventHandler_Keymap *handler, struct wmEventHandler_KeymapResult *km_result); void WM_event_get_keymap_from_toolsystem_fallback(struct wmWindowManager *wm, + struct wmWindow *win, struct wmEventHandler_Keymap *handler, wmEventHandler_KeymapResult *km_result); void WM_event_get_keymap_from_toolsystem(struct wmWindowManager *wm, + struct wmWindow *win, struct wmEventHandler_Keymap *handler, wmEventHandler_KeymapResult *km_result); @@ -293,6 +296,7 @@ void WM_event_set_keymap_handler_post_callback(struct wmEventHandler_Keymap *han void *user_data), void *user_data); void WM_event_get_keymaps_from_handler(wmWindowManager *wm, + struct wmWindow *win, struct wmEventHandler_Keymap *handler, struct wmEventHandler_KeymapResult *km_result); @@ -302,6 +306,7 @@ wmKeyMapItem *WM_event_match_keymap_item(struct bContext *C, wmKeyMapItem *WM_event_match_keymap_item_from_handlers(struct bContext *C, struct wmWindowManager *wm, + struct wmWindow *win, struct ListBase *handlers, const struct wmEvent *event); diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index ef86df4a8e8..df4d2c13ba7 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -2977,7 +2977,7 @@ static int wm_handlers_do_gizmo_handler(bContext *C, /** \name Handle Single Event (All Handler Types) * \{ */ -static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers) +static int wm_handlers_do_intern(bContext *C, wmWindow *win, wmEvent *event, ListBase *handlers) { const bool do_debug_handler = (G.debug & G_DEBUG_HANDLERS) && @@ -3020,7 +3020,7 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers if (handler_base->type == WM_HANDLER_TYPE_KEYMAP) { wmEventHandler_Keymap *handler = (wmEventHandler_Keymap *)handler_base; wmEventHandler_KeymapResult km_result; - WM_event_get_keymaps_from_handler(wm, handler, &km_result); + WM_event_get_keymaps_from_handler(wm, win, handler, &km_result); int action_iter = WM_HANDLER_CONTINUE; for (int km_index = 0; km_index < km_result.keymaps_len; km_index++) { wmKeyMap *keymap = km_result.keymaps[km_index]; @@ -3161,10 +3161,10 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers /* This calls handlers twice - to solve (double-)click events. */ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) { - int action = wm_handlers_do_intern(C, event, handlers); - /* Will be NULL in the file read case. */ wmWindow *win = CTX_wm_window(C); + int action = wm_handlers_do_intern(C, win, event, handlers); + if (win == NULL) { return action; } @@ -3188,7 +3188,7 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) CLOG_INFO(WM_LOG_HANDLERS, 1, "handling PRESS_DRAG"); - action |= wm_handlers_do_intern(C, event, handlers); + action |= wm_handlers_do_intern(C, win, event, handlers); event->val = val; event->type = type; @@ -3247,7 +3247,7 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) CLOG_INFO(WM_LOG_HANDLERS, 1, "handling CLICK"); - action |= wm_handlers_do_intern(C, event, handlers); + action |= wm_handlers_do_intern(C, win, event, handlers); event->val = KM_RELEASE; event->x = x; @@ -3259,7 +3259,7 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) else if (event->val == KM_DBL_CLICK) { /* The underlying event is a press, so try and handle this. */ event->val = KM_PRESS; - action |= wm_handlers_do_intern(C, event, handlers); + action |= wm_handlers_do_intern(C, win, event, handlers); /* revert value if not handled */ if (wm_action_not_handled(action)) { @@ -4020,6 +4020,7 @@ wmEventHandler_Keymap *WM_event_add_keymap_handler(ListBase *handlers, wmKeyMap * Follow #wmEventHandler_KeymapDynamicFn signature. */ void WM_event_get_keymap_from_toolsystem_fallback(wmWindowManager *wm, + wmWindow *win, wmEventHandler_Keymap *handler, wmEventHandler_KeymapResult *km_result) { @@ -4028,7 +4029,13 @@ void WM_event_get_keymap_from_toolsystem_fallback(wmWindowManager *wm, const char *keymap_id_list[ARRAY_SIZE(km_result->keymaps)]; int keymap_id_list_len = 0; - const Scene *scene = wm->winactive->scene; + /* NOTE(@campbellbarton): If `win` is NULL, this function may not behave as expected. + * Assert since this should not happen in practice. + * If it does, the window could be looked up in `wm` using the `area`. + * Keep NULL checks in run-time code since any crashes here are difficult to redo. */ + BLI_assert_msg(win != NULL, "The window should always be set for tool interactions!"); + const Scene *scene = win ? win->scene : NULL; + ScrArea *area = handler->dynamic.user_data; handler->keymap_tool = NULL; bToolRef_Runtime *tref_rt = area->runtime.tool ? area->runtime.tool->runtime : NULL; @@ -4041,7 +4048,7 @@ void WM_event_get_keymap_from_toolsystem_fallback(wmWindowManager *wm, bool is_gizmo_highlight = false; if ((tref_rt && tref_rt->keymap_fallback[0]) && - (scene->toolsettings->workspace_tool_type == SCE_WORKSPACE_TOOL_FALLBACK)) { + (scene && (scene->toolsettings->workspace_tool_type == SCE_WORKSPACE_TOOL_FALLBACK))) { bool add_keymap = false; /* Support for the gizmo owning the tool keymap. */ @@ -4100,6 +4107,7 @@ void WM_event_get_keymap_from_toolsystem_fallback(wmWindowManager *wm, } void WM_event_get_keymap_from_toolsystem(wmWindowManager *wm, + wmWindow *UNUSED(win), wmEventHandler_Keymap *handler, wmEventHandler_KeymapResult *km_result) { @@ -5257,11 +5265,12 @@ void WM_set_locked_interface(wmWindowManager *wm, bool lock) * \{ */ void WM_event_get_keymaps_from_handler(wmWindowManager *wm, + wmWindow *win, wmEventHandler_Keymap *handler, wmEventHandler_KeymapResult *km_result) { if (handler->dynamic.keymap_fn != NULL) { - handler->dynamic.keymap_fn(wm, handler, km_result); + handler->dynamic.keymap_fn(wm, win, handler, km_result); BLI_assert(handler->keymap == NULL); } else { @@ -5287,10 +5296,8 @@ wmKeyMapItem *WM_event_match_keymap_item(bContext *C, wmKeyMap *keymap, const wm return NULL; } -wmKeyMapItem *WM_event_match_keymap_item_from_handlers(bContext *C, - wmWindowManager *wm, - ListBase *handlers, - const wmEvent *event) +wmKeyMapItem *WM_event_match_keymap_item_from_handlers( + bContext *C, wmWindowManager *wm, wmWindow *win, ListBase *handlers, const wmEvent *event) { LISTBASE_FOREACH (wmEventHandler *, handler_base, handlers) { /* During this loop, UI handlers for nested menus can tag multiple handlers free. */ @@ -5301,7 +5308,7 @@ wmKeyMapItem *WM_event_match_keymap_item_from_handlers(bContext *C, if (handler_base->type == WM_HANDLER_TYPE_KEYMAP) { wmEventHandler_Keymap *handler = (wmEventHandler_Keymap *)handler_base; wmEventHandler_KeymapResult km_result; - WM_event_get_keymaps_from_handler(wm, handler, &km_result); + WM_event_get_keymaps_from_handler(wm, win, handler, &km_result); for (int km_index = 0; km_index < km_result.keymaps_len; km_index++) { wmKeyMap *keymap = km_result.keymaps[km_index]; if (WM_keymap_poll(C, keymap)) { @@ -5531,7 +5538,8 @@ void WM_window_cursor_keymap_status_refresh(bContext *C, wmWindow *win) wm_eventemulation(&test_event, true); wmKeyMapItem *kmi = NULL; for (int handler_index = 0; handler_index < ARRAY_SIZE(handlers); handler_index++) { - kmi = WM_event_match_keymap_item_from_handlers(C, wm, handlers[handler_index], &test_event); + kmi = WM_event_match_keymap_item_from_handlers( + C, wm, win, handlers[handler_index], &test_event); if (kmi) { break; } diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index e5aedfc7f47..658424b84a6 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -1390,6 +1390,8 @@ static wmKeyMapItem *wm_keymap_item_find_in_keymap(wmKeyMap *keymap, } static wmKeyMapItem *wm_keymap_item_find_handlers(const bContext *C, + wmWindowManager *wm, + wmWindow *win, ListBase *handlers, const char *opname, int UNUSED(opcontext), @@ -1398,14 +1400,12 @@ static wmKeyMapItem *wm_keymap_item_find_handlers(const bContext *C, const struct wmKeyMapItemFind_Params *params, wmKeyMap **r_keymap) { - wmWindowManager *wm = CTX_wm_manager(C); - /* find keymap item in handlers */ LISTBASE_FOREACH (wmEventHandler *, handler_base, handlers) { if (handler_base->type == WM_HANDLER_TYPE_KEYMAP) { wmEventHandler_Keymap *handler = (wmEventHandler_Keymap *)handler_base; wmEventHandler_KeymapResult km_result; - WM_event_get_keymaps_from_handler(wm, handler, &km_result); + WM_event_get_keymaps_from_handler(wm, win, handler, &km_result); for (int km_index = 0; km_index < km_result.keymaps_len; km_index++) { wmKeyMap *keymap = km_result.keymaps[km_index]; if (WM_keymap_poll((bContext *)C, keymap)) { @@ -1436,6 +1436,7 @@ static wmKeyMapItem *wm_keymap_item_find_props(const bContext *C, const struct wmKeyMapItemFind_Params *params, wmKeyMap **r_keymap) { + wmWindowManager *wm = CTX_wm_manager(C); wmWindow *win = CTX_wm_window(C); ScrArea *area = CTX_wm_area(C); ARegion *region = CTX_wm_region(C); @@ -1443,17 +1444,25 @@ static wmKeyMapItem *wm_keymap_item_find_props(const bContext *C, /* look into multiple handler lists to find the item */ if (win) { - found = wm_keymap_item_find_handlers( - C, &win->modalhandlers, opname, opcontext, properties, is_strict, params, r_keymap); + found = wm_keymap_item_find_handlers(C, + wm, + win, + &win->modalhandlers, + opname, + opcontext, + properties, + is_strict, + params, + r_keymap); if (found == NULL) { found = wm_keymap_item_find_handlers( - C, &win->handlers, opname, opcontext, properties, is_strict, params, r_keymap); + C, wm, win, &win->handlers, opname, opcontext, properties, is_strict, params, r_keymap); } } if (area && found == NULL) { found = wm_keymap_item_find_handlers( - C, &area->handlers, opname, opcontext, properties, is_strict, params, r_keymap); + C, wm, win, &area->handlers, opname, opcontext, properties, is_strict, params, r_keymap); } if (found == NULL) { @@ -1464,8 +1473,16 @@ static wmKeyMapItem *wm_keymap_item_find_props(const bContext *C, } if (region) { - found = wm_keymap_item_find_handlers( - C, ®ion->handlers, opname, opcontext, properties, is_strict, params, r_keymap); + found = wm_keymap_item_find_handlers(C, + wm, + win, + ®ion->handlers, + opname, + opcontext, + properties, + is_strict, + params, + r_keymap); } } } @@ -1475,8 +1492,16 @@ static wmKeyMapItem *wm_keymap_item_find_props(const bContext *C, } if (region) { - found = wm_keymap_item_find_handlers( - C, ®ion->handlers, opname, opcontext, properties, is_strict, params, r_keymap); + found = wm_keymap_item_find_handlers(C, + wm, + win, + ®ion->handlers, + opname, + opcontext, + properties, + is_strict, + params, + r_keymap); } } else if (ELEM(opcontext, WM_OP_EXEC_REGION_PREVIEW, WM_OP_INVOKE_REGION_PREVIEW)) { @@ -1485,14 +1510,30 @@ static wmKeyMapItem *wm_keymap_item_find_props(const bContext *C, } if (region) { - found = wm_keymap_item_find_handlers( - C, ®ion->handlers, opname, opcontext, properties, is_strict, params, r_keymap); + found = wm_keymap_item_find_handlers(C, + wm, + win, + ®ion->handlers, + opname, + opcontext, + properties, + is_strict, + params, + r_keymap); } } else { if (region) { - found = wm_keymap_item_find_handlers( - C, ®ion->handlers, opname, opcontext, properties, is_strict, params, r_keymap); + found = wm_keymap_item_find_handlers(C, + wm, + win, + ®ion->handlers, + opname, + opcontext, + properties, + is_strict, + params, + r_keymap); } } } |