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
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2021-10-15 16:42:19 +0300
committerCampbell Barton <ideasman42@gmail.com>2021-10-15 17:13:28 +0300
commit6e4ab5b761b03b52177985ecbeb2c2f576159c74 (patch)
treeb9e14c71a9840adfe578c73a45a5dce5e7fb1d54 /source/blender
parentd4f1bc5f39b219466978a1c9e74618ff8fa27433 (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/blender')
-rw-r--r--source/blender/editors/interface/interface_template_search_menu.c2
-rw-r--r--source/blender/windowmanager/WM_api.h5
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c40
-rw-r--r--source/blender/windowmanager/intern/wm_keymap.c71
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, &region->handlers, opname, opcontext, properties, is_strict, params, r_keymap);
+ found = wm_keymap_item_find_handlers(C,
+ wm,
+ win,
+ &region->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, &region->handlers, opname, opcontext, properties, is_strict, params, r_keymap);
+ found = wm_keymap_item_find_handlers(C,
+ wm,
+ win,
+ &region->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, &region->handlers, opname, opcontext, properties, is_strict, params, r_keymap);
+ found = wm_keymap_item_find_handlers(C,
+ wm,
+ win,
+ &region->handlers,
+ opname,
+ opcontext,
+ properties,
+ is_strict,
+ params,
+ r_keymap);
}
}
else {
if (region) {
- found = wm_keymap_item_find_handlers(
- C, &region->handlers, opname, opcontext, properties, is_strict, params, r_keymap);
+ found = wm_keymap_item_find_handlers(C,
+ wm,
+ win,
+ &region->handlers,
+ opname,
+ opcontext,
+ properties,
+ is_strict,
+ params,
+ r_keymap);
}
}
}