Fix crash on shutdown when one of the windows had outstanding input events

This commit is contained in:
2026-04-03 12:46:49 +02:00
parent 5e894ea45c
commit 2afca52a41
2 changed files with 18 additions and 12 deletions
+13 -9
View File
@@ -41,7 +41,7 @@ struct AxisData
uint64 FrameIndex = 0; uint64 FrameIndex = 0;
}; };
namespace InputImpl namespace
{ {
Dictionary<String, ActionData> Actions; Dictionary<String, ActionData> Actions;
Dictionary<String, AxisData> Axes; Dictionary<String, AxisData> Axes;
@@ -50,8 +50,6 @@ namespace InputImpl
InputDevice::EventQueue InputEvents; InputDevice::EventQueue InputEvents;
} }
using namespace InputImpl;
class InputService : public EngineService class InputService : public EngineService
{ {
public: public:
@@ -91,6 +89,17 @@ Delegate<StringView> Input::AxisValueChanged;
Array<ActionConfig> Input::ActionMappings; Array<ActionConfig> Input::ActionMappings;
Array<AxisConfig> Input::AxisMappings; Array<AxisConfig> Input::AxisMappings;
void ClearWindowInputs(Window* window)
{
WindowsManager::WindowsLocker.Lock();
for (int32 i = InputEvents.Count() - 1; i >= 0; i--)
{
if (InputEvents[i].Target == window)
InputEvents.RemoveAtKeepOrder(i);
}
WindowsManager::WindowsLocker.Unlock();
}
void InputSettings::Apply() void InputSettings::Apply()
{ {
PROFILE_MEM(Input); PROFILE_MEM(Input);
@@ -926,8 +935,8 @@ void InputService::Update()
} }
// Pick the first focused window for input events // Pick the first focused window for input events
WindowsManager::WindowsLocker.Lock();
Window* defaultWindow = nullptr; Window* defaultWindow = nullptr;
WindowsManager::WindowsLocker.Lock();
for (auto window : WindowsManager::Windows) for (auto window : WindowsManager::Windows)
{ {
if (window->IsFocused() && window->GetSettings().AllowInput) if (window->IsFocused() && window->GetSettings().AllowInput)
@@ -936,9 +945,7 @@ void InputService::Update()
break; break;
} }
} }
#if PLATFORM_SDL
WindowsManager::WindowsLocker.Unlock(); WindowsManager::WindowsLocker.Unlock();
#endif
// Send input events for the focused window // Send input events for the focused window
for (const auto& e : InputEvents) for (const auto& e : InputEvents)
@@ -992,9 +999,6 @@ void InputService::Update()
break; break;
} }
} }
#if !PLATFORM_SDL
WindowsManager::WindowsLocker.Unlock();
#endif
// Skip if game has no focus to handle the input // Skip if game has no focus to handle the input
if (!Engine::HasGameViewportFocus()) if (!Engine::HasGameViewportFocus())
+5 -3
View File
@@ -17,6 +17,8 @@
#include "Engine/Scripting/ManagedCLR/MMethod.h" #include "Engine/Scripting/ManagedCLR/MMethod.h"
#include "Engine/Scripting/ManagedCLR/MClass.h" #include "Engine/Scripting/ManagedCLR/MClass.h"
extern void ClearWindowInputs(Window* window);
#if USE_CSHARP #if USE_CSHARP
// Helper macros for calling C# events // Helper macros for calling C# events
#define BEGIN_INVOKE_EVENT(name, paramsCount) \ #define BEGIN_INVOKE_EVENT(name, paramsCount) \
@@ -122,6 +124,7 @@ WindowBase::WindowBase(const CreateWindowSettings& settings)
WindowBase::~WindowBase() WindowBase::~WindowBase()
{ {
ClearWindowInputs((Window*)this);
ASSERT(!RenderTask); ASSERT(!RenderTask);
ASSERT(!_swapChain); ASSERT(!_swapChain);
WindowsManager::Unregister((Window*)this); WindowsManager::Unregister((Window*)this);
@@ -182,15 +185,14 @@ String WindowBase::ToString() const
void WindowBase::OnDeleteObject() void WindowBase::OnDeleteObject()
{ {
// Dereference window
ClearWindowInputs((Window*)this);
#if !USE_EDITOR #if !USE_EDITOR
// Unlink main task (if was used)
if (RenderTask && RenderTask == MainRenderTask::Instance) if (RenderTask && RenderTask == MainRenderTask::Instance)
{ {
MainRenderTask::Instance->SwapChain = nullptr; MainRenderTask::Instance->SwapChain = nullptr;
RenderTask = nullptr; RenderTask = nullptr;
} }
#endif #endif
// Release resources // Release resources