diff --git a/source/blender/windowmanager/intern/wm.cc b/source/blender/windowmanager/intern/wm.cc index 86ca0353496..7532f8fd4f4 100644 --- a/source/blender/windowmanager/intern/wm.cc +++ b/source/blender/windowmanager/intern/wm.cc @@ -554,6 +554,19 @@ void wm_add_default(Main *bmain, bContext *C) wm_window_make_drawable(wm, win); } +static void wm_xr_data_free(wmWindowManager *wm) +{ + /* NOTE: this also runs when built without `WITH_XR_OPENXR`. + * It's necessary to prevent leaks when XR data is created or loaded into non XR builds. + * This can occur when Python reads all properties (see the `bl_rna_paths` test). */ + + /* Note that non-runtime data in `wm->xr` is freed as part of freeing the window manager. */ + if (wm->xr.session_settings.shading.prop) { + IDP_FreeProperty(wm->xr.session_settings.shading.prop); + wm->xr.session_settings.shading.prop = nullptr; + } +} + void wm_close_and_free(bContext *C, wmWindowManager *wm) { if (wm->autosavetimer) { @@ -564,6 +577,7 @@ void wm_close_and_free(bContext *C, wmWindowManager *wm) /* May send notifier, so do before freeing notifier queue. */ wm_xr_exit(wm); #endif + wm_xr_data_free(wm); while (wmWindow *win = static_cast(BLI_pophead(&wm->windows))) { /* Prevent draw clear to use screen. */ diff --git a/source/blender/windowmanager/xr/intern/wm_xr.cc b/source/blender/windowmanager/xr/intern/wm_xr.cc index 72c77561481..c8936682af6 100644 --- a/source/blender/windowmanager/xr/intern/wm_xr.cc +++ b/source/blender/windowmanager/xr/intern/wm_xr.cc @@ -134,10 +134,9 @@ void wm_xr_exit(wmWindowManager *wm) if (wm->xr.runtime != nullptr) { wm_xr_runtime_data_free(&wm->xr.runtime); } - if (wm->xr.session_settings.shading.prop) { - IDP_FreeProperty(wm->xr.session_settings.shading.prop); - wm->xr.session_settings.shading.prop = nullptr; - } + + /* See #wm_xr_data_free for logic that frees window-manager XR data + * that may exist even when built without XR. */ } bool wm_xr_events_handle(wmWindowManager *wm)