diff options
Diffstat (limited to 'source/blender/windowmanager/intern/wm_event_system.cc')
-rw-r--r-- | source/blender/windowmanager/intern/wm_event_system.cc | 241 |
1 files changed, 165 insertions, 76 deletions
diff --git a/source/blender/windowmanager/intern/wm_event_system.cc b/source/blender/windowmanager/intern/wm_event_system.cc index 102441f1b4d..181ec89cabd 100644 --- a/source/blender/windowmanager/intern/wm_event_system.cc +++ b/source/blender/windowmanager/intern/wm_event_system.cc @@ -27,6 +27,7 @@ #include "BLI_blenlib.h" #include "BLI_dynstr.h" +#include "BLI_ghash.h" #include "BLI_math.h" #include "BLI_timer.h" #include "BLI_utildefines.h" @@ -55,6 +56,8 @@ #include "ED_util.h" #include "ED_view3d.h" +#include "GPU_context.h" + #include "RNA_access.h" #include "UI_interface.h" @@ -90,6 +93,7 @@ #define USE_GIZMO_MOUSE_PRIORITY_HACK static void wm_notifier_clear(wmNotifier *note); +static bool wm_notifier_is_clear(const wmNotifier *note); static int wm_operator_call_internal(bContext *C, wmOperatorType *ot, @@ -252,36 +256,67 @@ void wm_event_init_from_window(wmWindow *win, wmEvent *event) /** \name Notifiers & Listeners * \{ */ -static bool wm_test_duplicate_notifier(const wmWindowManager *wm, uint type, void *reference) +/** + * Hash for #wmWindowManager.notifier_queue_set, ignores `window`. + */ +static uint note_hash_for_queue_fn(const void *ptr) { - LISTBASE_FOREACH (wmNotifier *, note, &wm->notifier_queue) { - if ((note->category | note->data | note->subtype | note->action) == type && - note->reference == reference) { - return true; - } - } + const wmNotifier *note = static_cast<const wmNotifier *>(ptr); + return (BLI_ghashutil_ptrhash(note->reference) ^ + (note->category | note->data | note->subtype | note->action)); +} - return false; +/** + * Comparison for #wmWindowManager.notifier_queue_set + * + * \note This is not an exact equality function as the `window` is ignored. + */ +static bool note_cmp_for_queue_fn(const void *a, const void *b) +{ + const wmNotifier *note_a = static_cast<const wmNotifier *>(a); + const wmNotifier *note_b = static_cast<const wmNotifier *>(b); + return !(((note_a->category | note_a->data | note_a->subtype | note_a->action) == + (note_b->category | note_b->data | note_b->subtype | note_b->action)) && + (note_a->reference == note_b->reference)); } void WM_event_add_notifier_ex(wmWindowManager *wm, const wmWindow *win, uint type, void *reference) { - if (wm_test_duplicate_notifier(wm, type, reference)) { + if (wm == nullptr) { + /* There may be some cases where e.g. `G_MAIN` is not actually the real current main, but some + * other temporary one (e.g. during liboverride processing over linked data), leading to null + * window manager. + * + * This is fairly bad and weak, but unfortunately RNA does not have any way to operate over + * another main than G_MAIN currently. */ return; } - wmNotifier *note = MEM_cnew<wmNotifier>(__func__); + wmNotifier note_test = {nullptr}; - BLI_addtail(&wm->notifier_queue, note); + note_test.window = win; + + note_test.category = type & NOTE_CATEGORY; + note_test.data = type & NOTE_DATA; + note_test.subtype = type & NOTE_SUBTYPE; + note_test.action = type & NOTE_ACTION; + note_test.reference = reference; - note->window = win; + BLI_assert(!wm_notifier_is_clear(¬e_test)); - note->category = type & NOTE_CATEGORY; - note->data = type & NOTE_DATA; - note->subtype = type & NOTE_SUBTYPE; - note->action = type & NOTE_ACTION; + if (wm->notifier_queue_set == nullptr) { + wm->notifier_queue_set = BLI_gset_new_ex( + note_hash_for_queue_fn, note_cmp_for_queue_fn, __func__, 1024); + } - note->reference = reference; + void **note_p; + if (BLI_gset_ensure_p_ex(wm->notifier_queue_set, ¬e_test, ¬e_p)) { + return; + } + wmNotifier *note = MEM_new<wmNotifier>(__func__); + *note = note_test; + *note_p = note; + BLI_addtail(&wm->notifier_queue, note); } /* XXX: in future, which notifiers to send to other windows? */ @@ -290,25 +325,12 @@ void WM_event_add_notifier(const bContext *C, uint type, void *reference) WM_event_add_notifier_ex(CTX_wm_manager(C), CTX_wm_window(C), type, reference); } -void WM_main_add_notifier(unsigned int type, void *reference) +void WM_main_add_notifier(uint type, void *reference) { Main *bmain = G_MAIN; wmWindowManager *wm = static_cast<wmWindowManager *>(bmain->wm.first); - if (!wm || wm_test_duplicate_notifier(wm, type, reference)) { - return; - } - - wmNotifier *note = MEM_cnew<wmNotifier>(__func__); - - BLI_addtail(&wm->notifier_queue, note); - - note->category = type & NOTE_CATEGORY; - note->data = type & NOTE_DATA; - note->subtype = type & NOTE_SUBTYPE; - note->action = type & NOTE_ACTION; - - note->reference = reference; + WM_event_add_notifier_ex(wm, nullptr, type, reference); } void WM_main_remove_notifier_reference(const void *reference) @@ -319,6 +341,9 @@ void WM_main_remove_notifier_reference(const void *reference) if (wm) { LISTBASE_FOREACH_MUTABLE (wmNotifier *, note, &wm->notifier_queue) { if (note->reference == reference) { + const bool removed = BLI_gset_remove(wm->notifier_queue_set, note, nullptr); + BLI_assert(removed); + UNUSED_VARS_NDEBUG(removed); /* Don't remove because this causes problems for #wm_event_do_notifiers * which may be looping on the data (deleting screens). */ wm_notifier_clear(note); @@ -334,7 +359,7 @@ void WM_main_remove_notifier_reference(const void *reference) } } -static void wm_main_remap_assetlist(ID *old_id, ID *new_id, void *UNUSED(user_data)) +static void wm_main_remap_assetlist(ID *old_id, ID *new_id, void * /*user_data*/) { ED_assetlist_storage_id_remap(old_id, new_id); } @@ -374,6 +399,12 @@ static void wm_notifier_clear(wmNotifier *note) { /* nullptr the entire notifier, only leaving (`next`, `prev`) members intact. */ memset(((char *)note) + sizeof(Link), 0, sizeof(*note) - sizeof(Link)); + note->category = NOTE_CATEGORY_TAG_CLEARED; +} + +static bool wm_notifier_is_clear(const wmNotifier *note) +{ + return note->category == NOTE_CATEGORY_TAG_CLEARED; } void wm_event_do_depsgraph(bContext *C, bool is_after_open_file) @@ -455,11 +486,15 @@ static void wm_event_execute_timers(bContext *C) void wm_event_do_notifiers(bContext *C) { + /* Ensure inside render boundary. */ + GPU_render_begin(); + /* Run the timer before assigning `wm` in the unlikely case a timer loads a file, see T80028. */ wm_event_execute_timers(C); wmWindowManager *wm = CTX_wm_manager(C); if (wm == nullptr) { + GPU_render_end(); return; } @@ -473,7 +508,7 @@ void wm_event_do_notifiers(bContext *C) CTX_wm_window_set(C, win); - LISTBASE_FOREACH_MUTABLE (wmNotifier *, note, &wm->notifier_queue) { + LISTBASE_FOREACH_MUTABLE (const wmNotifier *, note, &wm->notifier_queue) { if (note->category == NC_WM) { if (ELEM(note->data, ND_FILEREAD, ND_FILESAVE)) { wm->file_saved = 1; @@ -532,7 +567,7 @@ void wm_event_do_notifiers(bContext *C) } if (note->window == win || - (note->window == nullptr && (ELEM(note->reference, nullptr, scene)))) { + (note->window == nullptr && ELEM(note->reference, nullptr, scene))) { if (note->category == NC_SCENE) { if (note->data == ND_FRAME) { do_anim = true; @@ -565,8 +600,15 @@ void wm_event_do_notifiers(bContext *C) } /* The notifiers are sent without context, to keep it clean. */ - wmNotifier *note; - while ((note = static_cast<wmNotifier *>(BLI_pophead(&wm->notifier_queue)))) { + const wmNotifier *note; + while ((note = static_cast<const wmNotifier *>(BLI_pophead(&wm->notifier_queue)))) { + if (wm_notifier_is_clear(note)) { + MEM_freeN((void *)note); + continue; + } + const bool removed = BLI_gset_remove(wm->notifier_queue_set, note, nullptr); + BLI_assert(removed); + UNUSED_VARS_NDEBUG(removed); LISTBASE_FOREACH (wmWindow *, win, &wm->windows) { Scene *scene = WM_window_get_active_scene(win); bScreen *screen = WM_window_get_active_screen(win); @@ -590,6 +632,7 @@ void wm_event_do_notifiers(bContext *C) win->screen->id.name + 2, note->category); # endif + ED_workspace_do_listen(C, note); ED_screen_do_listen(C, note); LISTBASE_FOREACH (ARegion *, region, &screen->regionbase) { @@ -630,7 +673,7 @@ void wm_event_do_notifiers(bContext *C) } } - MEM_freeN(note); + MEM_freeN((void *)note); } #endif /* If 1 (postpone disabling for in favor of message-bus), eventually. */ @@ -655,9 +698,11 @@ void wm_event_do_notifiers(bContext *C) /* Auto-run warning. */ wm_test_autorun_warning(C); + + GPU_render_end(); } -static int wm_event_always_pass(const wmEvent *event) +static bool wm_event_always_pass(const wmEvent *event) { /* Some events we always pass on, to ensure proper communication. */ return ISTIMER(event->type) || (event->type == WINDEACTIVATE); @@ -667,14 +712,23 @@ static int wm_event_always_pass(const wmEvent *event) * Debug only sanity check for the return value of event handlers. Checks that "always pass" events * don't cause non-passing handler return values, and thus actually pass. * - * Can't be executed if the handler just loaded a file (typically identified by `CTX_wm_window(C)` - * returning `nullptr`), because the event will have been freed then. + * \param C: Pass in the context to check if it's "window" was cleared. + * The event check can't be executed if the handler just loaded a file or closed the window. + * (typically identified by `CTX_wm_window(C)` returning null), + * because the event will have been freed then. + * When null, always check the event (assume the caller knows the event was not freed). */ -BLI_INLINE void wm_event_handler_return_value_check(const wmEvent *event, const int action) +BLI_INLINE void wm_event_handler_return_value_check(const bContext *C, + const wmEvent *event, + const int action) { - BLI_assert_msg(!wm_event_always_pass(event) || (action != WM_HANDLER_BREAK), - "Return value for events that should always pass should never be BREAK."); - UNUSED_VARS_NDEBUG(event, action); +#ifndef NDEBUG + if (C == nullptr || CTX_wm_window(C)) { + BLI_assert_msg(!wm_event_always_pass(event) || (action != WM_HANDLER_BREAK), + "Return value for events that should always pass should never be BREAK."); + } +#endif + UNUSED_VARS_NDEBUG(C, event, action); } /** \} */ @@ -1172,7 +1226,7 @@ int WM_operator_repeat_last(bContext *C, wmOperator *op) op->flag &= ~op_flag; return ret; } -bool WM_operator_repeat_check(const bContext *UNUSED(C), wmOperator *op) +bool WM_operator_repeat_check(const bContext * /*C*/, wmOperator *op) { if (op->type->exec != nullptr) { return true; @@ -1546,6 +1600,7 @@ static int wm_operator_call_internal(bContext *C, case WM_OP_EXEC_AREA: case WM_OP_EXEC_SCREEN: event = nullptr; + break; default: break; } @@ -2131,26 +2186,26 @@ static bool wm_eventmatch(const wmEvent *winevent, const wmKeyMapItem *kmi) /* Account for rare case of when these keys are used as the 'type' not as modifiers. */ if (kmi->shift != KM_ANY) { const bool shift = (winevent->modifier & KM_SHIFT) != 0; - if ((shift != (bool)kmi->shift) && + if ((shift != bool(kmi->shift)) && !ELEM(winevent->type, EVT_LEFTSHIFTKEY, EVT_RIGHTSHIFTKEY)) { return false; } } if (kmi->ctrl != KM_ANY) { const bool ctrl = (winevent->modifier & KM_CTRL) != 0; - if (ctrl != (bool)kmi->ctrl && !ELEM(winevent->type, EVT_LEFTCTRLKEY, EVT_RIGHTCTRLKEY)) { + if (ctrl != bool(kmi->ctrl) && !ELEM(winevent->type, EVT_LEFTCTRLKEY, EVT_RIGHTCTRLKEY)) { return false; } } if (kmi->alt != KM_ANY) { const bool alt = (winevent->modifier & KM_ALT) != 0; - if (alt != (bool)kmi->alt && !ELEM(winevent->type, EVT_LEFTALTKEY, EVT_RIGHTALTKEY)) { + if (alt != bool(kmi->alt) && !ELEM(winevent->type, EVT_LEFTALTKEY, EVT_RIGHTALTKEY)) { return false; } } if (kmi->oskey != KM_ANY) { const bool oskey = (winevent->modifier & KM_OSKEY) != 0; - if ((oskey != (bool)kmi->oskey) && (winevent->type != EVT_OSKEY)) { + if ((oskey != bool(kmi->oskey)) && (winevent->type != EVT_OSKEY)) { return false; } } @@ -2175,7 +2230,7 @@ static wmKeyMapItem *wm_eventmatch_modal_keymap_items(const wmKeyMap *keymap, /* Should already be handled by #wm_user_modal_keymap_set_items. */ BLI_assert(kmi->propvalue_str[0] == '\0'); if (wm_eventmatch(event, kmi)) { - if ((keymap->poll_modal_item == nullptr) || (keymap->poll_modal_item(op, kmi->propvalue))) { + if ((keymap->poll_modal_item == nullptr) || keymap->poll_modal_item(op, kmi->propvalue)) { return kmi; } } @@ -2333,7 +2388,7 @@ static int wm_handler_operator_call(bContext *C, /* When the window changes the modal modifier may have loaded a new blend file * (the `system_demo_mode` add-on does this), so we have to assume the event, * operator, area, region etc have all been freed. */ - if ((CTX_wm_window(C) == win)) { + if (CTX_wm_window(C) == win) { wm_event_modalkeymap_end(event, &event_backup); @@ -2731,7 +2786,7 @@ static int wm_handler_fileselect_call(bContext *C, return wm_handler_fileselect_do(C, handlers, handler, event->val); } -static int wm_action_not_handled(int action) +static bool wm_action_not_handled(int action) { return action == WM_HANDLER_CONTINUE || action == (WM_HANDLER_BREAK | WM_HANDLER_MODAL); } @@ -3101,7 +3156,7 @@ static int wm_handlers_do_intern(bContext *C, wmWindow *win, wmEvent *event, Lis int action = WM_HANDLER_CONTINUE; if (handlers == nullptr) { - wm_event_handler_return_value_check(event, action); + wm_event_handler_return_value_check(C, event, action); return action; } @@ -3267,9 +3322,7 @@ static int wm_handlers_do_intern(bContext *C, wmWindow *win, wmEvent *event, Lis } /* Do some extra sanity checking before returning the action. */ - if (CTX_wm_window(C) != nullptr) { - wm_event_handler_return_value_check(event, action); - } + wm_event_handler_return_value_check(C, event, action); return action; } @@ -3440,7 +3493,7 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) } } - wm_event_handler_return_value_check(event, action); + wm_event_handler_return_value_check(C, event, action); return action; } @@ -3568,7 +3621,7 @@ static void wm_event_drag_and_drop_test(wmWindowManager *wm, wmWindow *win, wmEv /* Clear drop icon. */ screen->do_draw_drag = true; - /* Restore cursor (disabled, see `wm_dragdrop.c`) */ + /* Restore cursor (disabled, see `wm_dragdrop.cc`) */ // WM_cursor_modal_restore(win); } } @@ -3717,7 +3770,7 @@ static int wm_event_do_handlers_area_regions(bContext *C, wmEvent *event, ScrAre action |= wm_event_do_region_handlers(C, event, region); } - wm_event_handler_return_value_check(event, action); + wm_event_handler_return_value_check(C, event, action); return action; } @@ -4038,9 +4091,9 @@ void WM_event_fileselect_event(wmWindowManager *wm, void *ophandle, int eventval * An appropriate window is either of the following: * * A parent window that does not yet contain a modal File Browser. This is determined using * #ED_fileselect_handler_area_find_any_with_op(). - * * A parent window containing a modal File Browser, but in a maximized/fullscreen state. Users + * * A parent window containing a modal File Browser, but in a maximized/full-screen state. Users * shouldn't be able to put a temporary screen like the modal File Browser into - * maximized/fullscreen state themselves. So this setup indicates that the File Browser was + * maximized/full-screen state themselves. So this setup indicates that the File Browser was * opened using #USER_TEMP_SPACE_DISPLAY_FULLSCREEN. * * If no appropriate parent window can be found from the context window, return the first @@ -4223,7 +4276,7 @@ void WM_event_modal_handler_region_replace(wmWindow *win, * it needs to keep old region stored in handler, so don't change it. */ if ((handler->context.region == old_region) && (handler->is_fileselect == false)) { handler->context.region = new_region; - handler->context.region_type = new_region ? new_region->regiontype : (int)RGN_TYPE_WINDOW; + handler->context.region_type = new_region ? new_region->regiontype : int(RGN_TYPE_WINDOW); } } } @@ -4404,7 +4457,7 @@ wmEventHandler_Keymap *WM_event_add_keymap_handler_dynamic( wmEventHandler_Keymap *WM_event_add_keymap_handler_priority(ListBase *handlers, wmKeyMap *keymap, - int UNUSED(priority)) + int /*priority*/) { WM_event_remove_keymap_handler(handlers, keymap); @@ -4626,16 +4679,16 @@ void WM_event_add_mousemove(wmWindow *win) static int convert_key(GHOST_TKey key) { if (key >= GHOST_kKeyA && key <= GHOST_kKeyZ) { - return (EVT_AKEY + ((int)key - GHOST_kKeyA)); + return (EVT_AKEY + (int(key) - GHOST_kKeyA)); } if (key >= GHOST_kKey0 && key <= GHOST_kKey9) { - return (EVT_ZEROKEY + ((int)key - GHOST_kKey0)); + return (EVT_ZEROKEY + (int(key) - GHOST_kKey0)); } if (key >= GHOST_kKeyNumpad0 && key <= GHOST_kKeyNumpad9) { - return (EVT_PAD0 + ((int)key - GHOST_kKeyNumpad0)); + return (EVT_PAD0 + (int(key) - GHOST_kKeyNumpad0)); } if (key >= GHOST_kKeyF1 && key <= GHOST_kKeyF24) { - return (EVT_F1KEY + ((int)key - GHOST_kKeyF1)); + return (EVT_F1KEY + (int(key) - GHOST_kKeyF1)); } switch (key) { @@ -4689,7 +4742,8 @@ static int convert_key(GHOST_TKey key) return EVT_LEFTCTRLKEY; case GHOST_kKeyRightControl: return EVT_RIGHTCTRLKEY; - case GHOST_kKeyOS: + case GHOST_kKeyLeftOS: + case GHOST_kKeyRightOS: return EVT_OSKEY; case GHOST_kKeyLeftAlt: return EVT_LEFTALTKEY; @@ -4777,7 +4831,7 @@ static int convert_key(GHOST_TKey key) #endif } - CLOG_WARN(WM_LOG_EVENTS, "unknown event type %d from ghost", (int)key); + CLOG_WARN(WM_LOG_EVENTS, "unknown event type %d from ghost", int(key)); return EVENT_NONE; } @@ -4890,7 +4944,7 @@ void WM_event_tablet_data_default_set(wmTabletData *tablet_data) void wm_tablet_data_from_ghost(const GHOST_TabletData *tablet_data, wmTabletData *wmtab) { if ((tablet_data != nullptr) && tablet_data->Active != GHOST_kTabletModeNone) { - wmtab->active = (int)tablet_data->Active; + wmtab->active = int(tablet_data->Active); wmtab->pressure = wm_pressure_curve(tablet_data->Pressure); wmtab->x_tilt = tablet_data->Xtilt; wmtab->y_tilt = tablet_data->Ytilt; @@ -5174,7 +5228,7 @@ static bool wm_event_is_ignorable_key_press(const wmWindow *win, const wmEvent & return false; } - const wmEvent &last_event = *reinterpret_cast<const wmEvent *>(win->event_queue.last); + const wmEvent &last_event = *static_cast<const wmEvent *>(win->event_queue.last); return wm_event_is_same_key_press(last_event, event); } @@ -5214,6 +5268,13 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void event.prev_type = event.type; event.prev_val = event.val; + /* Always use modifiers from the active window since + * changes to modifiers aren't sent to inactive windows, see: T66088. */ + if ((wm->winactive != win) && (wm->winactive && wm->winactive->eventstate)) { + event.modifier = wm->winactive->eventstate->modifier; + event.keymodifier = wm->winactive->eventstate->keymodifier; + } + /* Ensure the event state is correct, any deviation from this may cause bugs. * * NOTE: #EVENT_NONE is set when unknown keys are pressed, @@ -5256,6 +5317,10 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void if (win_other) { wmEvent event_other = *win_other->eventstate; + /* Use the modifier state of this window. */ + event_other.modifier = event.modifier; + event_other.keymodifier = event.keymodifier; + /* See comment for this operation on `event` for details. */ event_other.prev_type = event_other.type; event_other.prev_val = event_other.val; @@ -5345,6 +5410,10 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void if (win_other) { wmEvent event_other = *win_other->eventstate; + /* Use the modifier state of this window. */ + event_other.modifier = event.modifier; + event_other.keymodifier = event.keymodifier; + /* See comment for this operation on `event` for details. */ event_other.prev_type = event_other.type; event_other.prev_val = event_other.val; @@ -5402,7 +5471,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void * special handling of Latin1 when building without UTF8 support. * Avoid regressions by adding this conversions, it should eventually be removed. */ if ((event.utf8_buf[0] >= 0x80) && (event.utf8_buf[1] == '\0')) { - const uint c = (uint)event.utf8_buf[0]; + const uint c = uint(event.utf8_buf[0]); int utf8_buf_len = BLI_str_utf8_from_unicode(c, event.utf8_buf, sizeof(event.utf8_buf)); CLOG_ERROR(WM_LOG_EVENTS, "ghost detected non-ASCII single byte character '%u', converting to utf8 " @@ -5416,11 +5485,30 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void if (BLI_str_utf8_size(event.utf8_buf) == -1) { CLOG_ERROR(WM_LOG_EVENTS, "ghost detected an invalid unicode character '%d'", - (int)(unsigned char)event.utf8_buf[0]); + int(uchar(event.utf8_buf[0]))); event.utf8_buf[0] = '\0'; } } + /* NOTE(@campbellbarton): Setting the modifier state based on press/release + * is technically incorrect. + * + * - The user might hold both left/right modifier keys, then only release one. + * + * This could be solved by storing a separate flag for the left/right modifiers, + * and combine them into `event.modifiers`. + * + * - The user might have multiple keyboards (or keyboard + NDOF device) + * where it's possible to press the same modifier key multiple times. + * + * This could be solved by tracking the number of held modifier keys, + * (this is in fact what LIBXKB does), however doing this relies on all GHOST + * back-ends properly reporting every press/release as any mismatch could result + * in modifier keys being stuck (which is very bad!). + * + * To my knowledge users never reported a bug relating to these limitations so + * it seems reasonable to keep the current logic. */ + switch (event.type) { case EVT_LEFTSHIFTKEY: case EVT_RIGHTSHIFTKEY: { @@ -5532,7 +5620,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void case GHOST_kEventNDOFButton: { GHOST_TEventNDOFButtonData *e = static_cast<GHOST_TEventNDOFButtonData *>(customdata); - event.type = NDOF_BUTTON_NONE + e->button; + event.type = NDOF_BUTTON_INDEX_AS_EVENT(e->button); switch (e->action) { case GHOST_kPress: @@ -5870,11 +5958,12 @@ void WM_window_cursor_keymap_status_refresh(bContext *C, wmWindow *win) bToolRef *tref = nullptr; if ((region->regiontype == RGN_TYPE_WINDOW) && ((1 << area->spacetype) & WM_TOOLSYSTEM_SPACE_MASK)) { + const Scene *scene = WM_window_get_active_scene(win); ViewLayer *view_layer = WM_window_get_active_view_layer(win); WorkSpace *workspace = WM_window_get_active_workspace(win); bToolKey tkey{}; tkey.space_type = area->spacetype; - tkey.mode = WM_toolsystem_mode_from_spacetype(view_layer, area, area->spacetype); + tkey.mode = WM_toolsystem_mode_from_spacetype(scene, view_layer, area, area->spacetype); tref = WM_toolsystem_ref_find(workspace, &tkey); } wm_event_cursor_store(&cd->state, win->eventstate, area->spacetype, region->regiontype, tref); |