From 8e497fb4e97c7cecc7d14570f81ac3ab51e11a4a Mon Sep 17 00:00:00 2001 From: Darren Kelly Date: Mon, 2 Mar 2026 17:37:03 +0100 Subject: [PATCH 1/8] Add progress with bug fix for Editor closing when clicking cancel in a save dialog prompt. --- .../InputActionsEditorWindow.cs | 58 +++++++++++++------ 1 file changed, 39 insertions(+), 19 deletions(-) diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/InputActionsEditorWindow.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/InputActionsEditorWindow.cs index 41e890533a..b3bf666002 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/InputActionsEditorWindow.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/InputActionsEditorWindow.cs @@ -24,6 +24,7 @@ static InputActionsEditorWindow() private string m_AssetJson; private bool m_IsDirty; + private bool m_IsEditorQuitting; private StateContainer m_StateContainer; private InputActionsEditorView m_View; @@ -313,11 +314,21 @@ private void DirtyInputActionsEditorWindow(InputActionsEditorState newState) private void OnEnable() { analytics.Begin(); + EditorApplication.wantsToQuit += OnWantsToQuit; } private void OnDisable() { analytics.End(); + EditorApplication.wantsToQuit -= OnWantsToQuit; + } + + private bool OnWantsToQuit() + { + // Here the user will be prompted + bool isAllowedToQuit = OnDestroyIsApplicationAllowedToQuit(false); + m_IsEditorQuitting = isAllowedToQuit; + return m_IsEditorQuitting; } private void OnFocus() @@ -342,39 +353,48 @@ private void OnLostFocus() analytics.RegisterEditorFocusOut(); } - private void HandleOnDestroy() + private bool OnDestroyIsApplicationAllowedToQuit(bool rebuildUIOnCancel) { // Do we have unsaved changes that we need to ask the user to save or discard? if (!m_IsDirty) - return; + return true; // Get target asset path from GUID, if this fails file no longer exists and we need to abort. var assetPath = AssetDatabase.GUIDToAssetPath(m_AssetGUID); if (string.IsNullOrEmpty(assetPath)) - return; + return true; - // Prompt user with a dialog - var result = Dialog.InputActionAsset.ShowSaveChanges(assetPath); - switch (result) + if (!m_IsEditorQuitting) { - case Dialog.Result.Save: - Save(isAutoSave: false); - break; - case Dialog.Result.Cancel: - // Cancel editor quit. (open new editor window with the edited asset) - ReshowEditorWindowWithUnsavedChanges(); - break; - case Dialog.Result.Discard: - // Don't save, quit - reload the old asset from the json to prevent the asset from being dirtied - break; - default: - throw new ArgumentOutOfRangeException(nameof(result)); + // Prompt user with a dialog + var result = Dialog.InputActionAsset.ShowSaveChanges(assetPath); + switch (result) + { + case Dialog.Result.Save: + Save(isAutoSave: false); + return true; + case Dialog.Result.Cancel: + if (rebuildUIOnCancel) + { + // Cancel editor quit. (open new editor window with the edited asset) + ReshowEditorWindowWithUnsavedChanges(); + } + + return false; + case Dialog.Result.Discard: + // Don't save, quit - reload the old asset from the json to prevent the asset from being dirtied + return true; + default: + throw new ArgumentOutOfRangeException(nameof(result)); + } } + + return true; } private void OnDestroy() { - HandleOnDestroy(); + OnDestroyIsApplicationAllowedToQuit(true); // Clean-up CleanupStateContainer(); From c27e8ca9c03b335f8da88a7463ee6f993602a6b6 Mon Sep 17 00:00:00 2001 From: Darren Kelly Date: Wed, 4 Mar 2026 11:05:58 +0100 Subject: [PATCH 2/8] Update changelog for editor closing fix. --- Packages/com.unity.inputsystem/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Packages/com.unity.inputsystem/CHANGELOG.md b/Packages/com.unity.inputsystem/CHANGELOG.md index 71a26a51d7..c15fc036df 100644 --- a/Packages/com.unity.inputsystem/CHANGELOG.md +++ b/Packages/com.unity.inputsystem/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Improved New Input System warning dialog, Native Device Inputs Not Enabled [UUM-132151]. - Fixed caching for InputControlPath display name [ISX-2501](https://jira.unity3d.com/browse/ISX-2501) +- Fixed editor closing and not saving the input asset when clicking cancel in the dialog prompt [UUM-134748](https://jira.unity3d.com/browse/UUM-134748) ### Changed From e0c04bfef041797f243d34ae2f3c3ec74bceab7f Mon Sep 17 00:00:00 2001 From: Darren Kelly Date: Wed, 4 Mar 2026 11:09:53 +0100 Subject: [PATCH 3/8] Update method signature to better reflect what it does. --- .../Editor/UITKAssetEditor/InputActionsEditorWindow.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/InputActionsEditorWindow.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/InputActionsEditorWindow.cs index c26a290166..1dfd324660 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/InputActionsEditorWindow.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/InputActionsEditorWindow.cs @@ -329,7 +329,7 @@ private void OnDisable() private bool OnWantsToQuit() { // Here the user will be prompted - bool isAllowedToQuit = OnDestroyIsApplicationAllowedToQuit(false); + bool isAllowedToQuit = HandleOnDestroyIfApplicationIsAllowedToQuit(false); m_IsEditorQuitting = isAllowedToQuit; return m_IsEditorQuitting; } @@ -356,7 +356,11 @@ private void OnLostFocus() analytics.RegisterEditorFocusOut(); } - private bool OnDestroyIsApplicationAllowedToQuit(bool rebuildUIOnCancel) + /// + /// Shows a dialog when trying to close an input asset without saving changes. + /// + /// Returns true if you should allow the Unity Editor to close. + private bool HandleOnDestroyIfApplicationIsAllowedToQuit(bool rebuildUIOnCancel) { // Do we have unsaved changes that we need to ask the user to save or discard? if (!m_IsDirty) @@ -397,7 +401,7 @@ private bool OnDestroyIsApplicationAllowedToQuit(bool rebuildUIOnCancel) private void OnDestroy() { - OnDestroyIsApplicationAllowedToQuit(true); + HandleOnDestroyIfApplicationIsAllowedToQuit(true); // Clean-up CleanupStateContainer(); From 6ca605d7a24b89917108cb913785c3e405a096ba Mon Sep 17 00:00:00 2001 From: Darren-Kelly-Unity <118264423+Darren-Kelly-Unity@users.noreply.github.com> Date: Thu, 5 Mar 2026 09:42:47 +0100 Subject: [PATCH 4/8] Update InputActionsEditorWindow.cs with code suggestion for simplified code. Co-authored-by: Morgan Hoarau <122548697+MorganHoarau@users.noreply.github.com> --- .../Editor/UITKAssetEditor/InputActionsEditorWindow.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/InputActionsEditorWindow.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/InputActionsEditorWindow.cs index 1dfd324660..2c0b887fef 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/InputActionsEditorWindow.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/InputActionsEditorWindow.cs @@ -363,7 +363,8 @@ private void OnLostFocus() private bool HandleOnDestroyIfApplicationIsAllowedToQuit(bool rebuildUIOnCancel) { // Do we have unsaved changes that we need to ask the user to save or discard? - if (!m_IsDirty) + // Early out if asset up to date or editor closing. + if (!m_IsDirty || m_IsEditorQuitting) return true; // Get target asset path from GUID, if this fails file no longer exists and we need to abort. From f714895938a545a55f3ae4aa5448efd68e948334 Mon Sep 17 00:00:00 2001 From: Darren Kelly Date: Thu, 5 Mar 2026 11:08:10 +0100 Subject: [PATCH 5/8] Add code review changes. --- .../InputActionsEditorWindow.cs | 50 +++++++++---------- 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/InputActionsEditorWindow.cs b/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/InputActionsEditorWindow.cs index 2c0b887fef..84ba6fabb7 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/InputActionsEditorWindow.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Editor/UITKAssetEditor/InputActionsEditorWindow.cs @@ -329,7 +329,7 @@ private void OnDisable() private bool OnWantsToQuit() { // Here the user will be prompted - bool isAllowedToQuit = HandleOnDestroyIfApplicationIsAllowedToQuit(false); + bool isAllowedToQuit = CheckCanCloseAndPromptIfDirty(false); m_IsEditorQuitting = isAllowedToQuit; return m_IsEditorQuitting; } @@ -359,8 +359,9 @@ private void OnLostFocus() /// /// Shows a dialog when trying to close an input asset without saving changes. /// + /// If true, reopens the editor window when user cancels. /// Returns true if you should allow the Unity Editor to close. - private bool HandleOnDestroyIfApplicationIsAllowedToQuit(bool rebuildUIOnCancel) + private bool CheckCanCloseAndPromptIfDirty(bool rebuildUIOnCancel) { // Do we have unsaved changes that we need to ask the user to save or discard? // Early out if asset up to date or editor closing. @@ -372,37 +373,32 @@ private bool HandleOnDestroyIfApplicationIsAllowedToQuit(bool rebuildUIOnCancel) if (string.IsNullOrEmpty(assetPath)) return true; - if (!m_IsEditorQuitting) + // Prompt user with a dialog + var result = Dialog.InputActionAsset.ShowSaveChanges(assetPath); + switch (result) { - // Prompt user with a dialog - var result = Dialog.InputActionAsset.ShowSaveChanges(assetPath); - switch (result) - { - case Dialog.Result.Save: - Save(isAutoSave: false); - return true; - case Dialog.Result.Cancel: - if (rebuildUIOnCancel) - { - // Cancel editor quit. (open new editor window with the edited asset) - ReshowEditorWindowWithUnsavedChanges(); - } - - return false; - case Dialog.Result.Discard: - // Don't save, quit - reload the old asset from the json to prevent the asset from being dirtied - return true; - default: - throw new ArgumentOutOfRangeException(nameof(result)); - } - } + case Dialog.Result.Save: + Save(isAutoSave: false); + return true; + case Dialog.Result.Cancel: + if (rebuildUIOnCancel) + { + // Cancel editor quit. (open new editor window with the edited asset) + ReshowEditorWindowWithUnsavedChanges(); + } - return true; + return false; + case Dialog.Result.Discard: + // Don't save, quit - reload the old asset from the json to prevent the asset from being dirtied + return true; + default: + throw new ArgumentOutOfRangeException(nameof(result)); + } } private void OnDestroy() { - HandleOnDestroyIfApplicationIsAllowedToQuit(true); + CheckCanCloseAndPromptIfDirty(true); // Clean-up CleanupStateContainer(); From 5396b58a941541130ed9184ecb4fc4682145f841 Mon Sep 17 00:00:00 2001 From: Darren Kelly Date: Mon, 9 Mar 2026 17:42:04 +0100 Subject: [PATCH 6/8] Add hopeful fix for CI issues. --- Assets/Tests/InputSystem/APIVerificationTests.cs | 6 +++--- .../InputSystem/DocumentationBasedAPIVerficationTests.cs | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Assets/Tests/InputSystem/APIVerificationTests.cs b/Assets/Tests/InputSystem/APIVerificationTests.cs index 502279c8da..7e710d39b4 100644 --- a/Assets/Tests/InputSystem/APIVerificationTests.cs +++ b/Assets/Tests/InputSystem/APIVerificationTests.cs @@ -244,10 +244,10 @@ public void API_MonoBehavioursHaveHelpUrls() t.IsPublic && !t.IsAbstract && !IgnoreTypeForDocsByName(t.FullName) && !IgnoreTypeForDocsByNamespace(t.Namespace) && typeof(MonoBehaviour).IsAssignableFrom(t)); var monoBehaviourTypesHelpUrls = - monoBehaviourTypes.Where(t => t.GetCustomAttribute() != null) - .Select(t => t.GetCustomAttribute().URL); + monoBehaviourTypes.Where(t => t.GetCustomAttributes().FirstOrDefault() != null) + .Select(t => t.GetCustomAttributes().FirstOrDefault().URL); var monoBehaviourTypesWithoutHelpUrls = - monoBehaviourTypes.Where(t => t.GetCustomAttribute() == null); + monoBehaviourTypes.Where(t => t.GetCustomAttributes().FirstOrDefault() == null); Assert.That(monoBehaviourTypesWithoutHelpUrls, Is.Empty); Assert.That(monoBehaviourTypesHelpUrls, Has.All.StartWith(InputSystem.kDocUrl)); diff --git a/Assets/Tests/InputSystem/DocumentationBasedAPIVerficationTests.cs b/Assets/Tests/InputSystem/DocumentationBasedAPIVerficationTests.cs index 7c6c1cc9c9..4828083c9b 100644 --- a/Assets/Tests/InputSystem/DocumentationBasedAPIVerficationTests.cs +++ b/Assets/Tests/InputSystem/DocumentationBasedAPIVerficationTests.cs @@ -127,7 +127,7 @@ public void API_MonoBehaviourHelpUrlsAreValid() typeof(MonoBehaviour).IsAssignableFrom(t)); var monoBehaviourTypesWithHelpUrls = monoBehaviourTypes - .Where(t => t.GetCustomAttribute() != null); + .Where(t => t.GetCustomAttributes().FirstOrDefault() != null); var brokenHelpUrlErrors = new StringBuilder(); @@ -135,7 +135,8 @@ public void API_MonoBehaviourHelpUrlsAreValid() foreach (var monoBehaviorTypeWithHelpUrl in monoBehaviourTypesWithHelpUrls) { // Get url - var url = monoBehaviorTypeWithHelpUrl.GetCustomAttribute().URL; + var test = monoBehaviorTypeWithHelpUrl.GetCustomAttributes(); + var url = test.FirstOrDefault()?.URL; // Parse file path and anchor. var path = url.Substring(InputSystem.kDocUrl.Length); From bbfc39d33c99dea19f596d4af74ed036c93ccf9f Mon Sep 17 00:00:00 2001 From: Darren Kelly Date: Mon, 9 Mar 2026 17:57:41 +0100 Subject: [PATCH 7/8] Add updated code fix for test. --- Assets/Tests/InputSystem/APIVerificationTests.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Assets/Tests/InputSystem/APIVerificationTests.cs b/Assets/Tests/InputSystem/APIVerificationTests.cs index 7e710d39b4..4f51f85726 100644 --- a/Assets/Tests/InputSystem/APIVerificationTests.cs +++ b/Assets/Tests/InputSystem/APIVerificationTests.cs @@ -243,12 +243,14 @@ public void API_MonoBehavioursHaveHelpUrls() var monoBehaviourTypes = typeof(InputSystem).Assembly.ExportedTypes.Where(t => t.IsPublic && !t.IsAbstract && !IgnoreTypeForDocsByName(t.FullName) && !IgnoreTypeForDocsByNamespace(t.Namespace) && typeof(MonoBehaviour).IsAssignableFrom(t)); + var monoBehaviourTypesHelpUrls = - monoBehaviourTypes.Where(t => t.GetCustomAttributes().FirstOrDefault() != null) - .Select(t => t.GetCustomAttributes().FirstOrDefault().URL); + monoBehaviourTypes.Where(t => t.GetCustomAttribute() != null) + .Select(t => t.GetCustomAttribute().URL); + monoBehaviourTypes.Where(t => t.GetCustomAttributes().Any()).Select(t => t.GetCustomAttributes().First().URL); var monoBehaviourTypesWithoutHelpUrls = - monoBehaviourTypes.Where(t => t.GetCustomAttributes().FirstOrDefault() == null); - + monoBehaviourTypes.Where(t => t.GetCustomAttribute() == null); + monoBehaviourTypes.Where(t => !t.GetCustomAttributes().Any()); Assert.That(monoBehaviourTypesWithoutHelpUrls, Is.Empty); Assert.That(monoBehaviourTypesHelpUrls, Has.All.StartWith(InputSystem.kDocUrl)); } From b9780bf3d018fa85e5b8835f49543804311641b1 Mon Sep 17 00:00:00 2001 From: Darren Kelly Date: Mon, 9 Mar 2026 18:01:04 +0100 Subject: [PATCH 8/8] Add fix to test changes. --- Assets/Tests/InputSystem/APIVerificationTests.cs | 9 ++------- .../InputSystem/DocumentationBasedAPIVerficationTests.cs | 2 +- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/Assets/Tests/InputSystem/APIVerificationTests.cs b/Assets/Tests/InputSystem/APIVerificationTests.cs index 4f51f85726..03fd7e5275 100644 --- a/Assets/Tests/InputSystem/APIVerificationTests.cs +++ b/Assets/Tests/InputSystem/APIVerificationTests.cs @@ -244,13 +244,8 @@ public void API_MonoBehavioursHaveHelpUrls() t.IsPublic && !t.IsAbstract && !IgnoreTypeForDocsByName(t.FullName) && !IgnoreTypeForDocsByNamespace(t.Namespace) && typeof(MonoBehaviour).IsAssignableFrom(t)); - var monoBehaviourTypesHelpUrls = - monoBehaviourTypes.Where(t => t.GetCustomAttribute() != null) - .Select(t => t.GetCustomAttribute().URL); - monoBehaviourTypes.Where(t => t.GetCustomAttributes().Any()).Select(t => t.GetCustomAttributes().First().URL); - var monoBehaviourTypesWithoutHelpUrls = - monoBehaviourTypes.Where(t => t.GetCustomAttribute() == null); - monoBehaviourTypes.Where(t => !t.GetCustomAttributes().Any()); + var monoBehaviourTypesHelpUrls = monoBehaviourTypes.Where(t => t.GetCustomAttributes().Any()).Select(t => t.GetCustomAttributes().First().URL); + var monoBehaviourTypesWithoutHelpUrls = monoBehaviourTypes.Where(t => !t.GetCustomAttributes().Any()); Assert.That(monoBehaviourTypesWithoutHelpUrls, Is.Empty); Assert.That(monoBehaviourTypesHelpUrls, Has.All.StartWith(InputSystem.kDocUrl)); } diff --git a/Assets/Tests/InputSystem/DocumentationBasedAPIVerficationTests.cs b/Assets/Tests/InputSystem/DocumentationBasedAPIVerficationTests.cs index 4828083c9b..1b0fb6f378 100644 --- a/Assets/Tests/InputSystem/DocumentationBasedAPIVerficationTests.cs +++ b/Assets/Tests/InputSystem/DocumentationBasedAPIVerficationTests.cs @@ -127,7 +127,7 @@ public void API_MonoBehaviourHelpUrlsAreValid() typeof(MonoBehaviour).IsAssignableFrom(t)); var monoBehaviourTypesWithHelpUrls = monoBehaviourTypes - .Where(t => t.GetCustomAttributes().FirstOrDefault() != null); + .Where(t => t.GetCustomAttributes().Any()); var brokenHelpUrlErrors = new StringBuilder();