From 0fdd84f594d10595f58dfd3c6cce85a8c6ada38d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Karger=20=E3=83=84=20=E2=98=80?= Date: Sun, 10 Nov 2024 14:06:49 +0100 Subject: [PATCH] AutoCompleteBox don't lose text selection when contextmenu opens (#17462) * fix: 17453 don't lose text selection when contextmenu opens on another control * fix: 17453 don't effect other callers and move the check to FocusChanged method --- .../AutoCompleteBox/AutoCompleteBox.cs | 6 +- .../AutoCompleteBoxTests.cs | 58 ++++++++++++++++++- 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.cs b/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.cs index 95ea8f9ece..b142ce5eb2 100644 --- a/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.cs +++ b/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.cs @@ -812,7 +812,11 @@ namespace Avalonia.Controls } _userCalledPopulate = false; - ClearTextBoxSelection(); + + if (ContextMenu is not { IsOpen: true }) + { + ClearTextBoxSelection(); + } } _isFocused = hasFocus; diff --git a/tests/Avalonia.Controls.UnitTests/AutoCompleteBoxTests.cs b/tests/Avalonia.Controls.UnitTests/AutoCompleteBoxTests.cs index 5cc3901cd7..67f55055ec 100644 --- a/tests/Avalonia.Controls.UnitTests/AutoCompleteBoxTests.cs +++ b/tests/Avalonia.Controls.UnitTests/AutoCompleteBoxTests.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using Avalonia.Controls.Primitives; @@ -9,7 +9,10 @@ using Avalonia.UnitTests; using Xunit; using System.Collections.ObjectModel; using System.Reactive.Subjects; +using Avalonia.Headless; using Avalonia.Input; +using Avalonia.Platform; +using Moq; namespace Avalonia.Controls.UnitTests { @@ -520,6 +523,42 @@ namespace Avalonia.Controls.UnitTests }); } + [Fact] + public void Opening_Context_Menu_Does_not_Lose_Selection() + { + using (UnitTestApplication.Start(FocusServices)) + { + var target1 = CreateControl(); + target1.ContextMenu = new TestContextMenu(); + var textBox1 = GetTextBox(target1); + textBox1.Text = "1234"; + + var target2 = CreateControl(); + var textBox2 = GetTextBox(target2); + textBox2.Text = "5678"; + + var sp = new StackPanel(); + sp.Children.Add(target1); + sp.Children.Add(target2); + + target1.ApplyTemplate(); + target2.ApplyTemplate(); + + var root = new TestRoot() { Child = sp }; + + textBox1.SelectionStart = 0; + textBox1.SelectionEnd = 3; + + target1.Focus(); + Assert.False(target2.IsFocused); + Assert.True(target1.IsFocused); + + target2.Focus(); + + Assert.Equal("123", textBox1.SelectedText); + } + } + /// /// Retrieves a defined predicate filter through a new AutoCompleteBox /// control instance. @@ -1198,5 +1237,22 @@ namespace Avalonia.Controls.UnitTests return panel; }); } + + private static TestServices FocusServices => TestServices.MockThreadingInterface.With( + focusManager: new FocusManager(), + keyboardDevice: () => new KeyboardDevice(), + keyboardNavigation: () => new KeyboardNavigationHandler(), + inputManager: new InputManager(), + standardCursorFactory: Mock.Of(), + textShaperImpl: new HeadlessTextShaperStub(), + fontManagerImpl: new HeadlessFontManagerStub()); + + private class TestContextMenu : ContextMenu + { + public TestContextMenu() + { + IsOpen = true; + } + } } }