From 819ccc23872f292c7d3d151c3743c76e1ca1bf76 Mon Sep 17 00:00:00 2001 From: Ramez Ragaa Date: Tue, 8 Oct 2024 17:49:16 +0300 Subject: [PATCH] fix(textbox): BeforeTextChanging crashing ing in specific cases --- src/Uno.UI/UI/Xaml/Controls/TextBox/TextBox.cs | 15 +++++++++++++++ .../UI/Xaml/Controls/TextBox/TextBox.skia.cs | 1 - 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/Uno.UI/UI/Xaml/Controls/TextBox/TextBox.cs b/src/Uno.UI/UI/Xaml/Controls/TextBox/TextBox.cs index 9cb6558fd361..a9b8d293542e 100644 --- a/src/Uno.UI/UI/Xaml/Controls/TextBox/TextBox.cs +++ b/src/Uno.UI/UI/Xaml/Controls/TextBox/TextBox.cs @@ -427,6 +427,21 @@ private object CoerceText(object baseValue) BeforeTextChanging?.Invoke(this, args); if (args.Cancel) { +#if __SKIA__ + if (_isSkiaTextBox) + { + // On WinUI, when a selection is canceled, the TextBox invokes a bunch of weird + // SelectionChanging events followed by a bunch of matching SelectionChanged. + // Probing for the value of SelectionStart and SelectionLength during these SelectionChanging + // events will give incorrect transient values and the SelectionChanged events will end up + // with the selection where it started (before the text change). Also, the direction of + // of the selection will be reset, i.e. if the selection end was "at the start", then it won't be + // so anymore. + // In Uno, we choose a simpler sequence. We just reset the selection direction (like WinUI) and + // we don't invoke any selection change events (since selection was in fact not changed). + _pendingSelection = (SelectionStart, SelectionLength); + } +#endif return DependencyProperty.UnsetValue; } diff --git a/src/Uno.UI/UI/Xaml/Controls/TextBox/TextBox.skia.cs b/src/Uno.UI/UI/Xaml/Controls/TextBox/TextBox.skia.cs index 977358a4fc37..310476ac58c7 100644 --- a/src/Uno.UI/UI/Xaml/Controls/TextBox/TextBox.skia.cs +++ b/src/Uno.UI/UI/Xaml/Controls/TextBox/TextBox.skia.cs @@ -140,7 +140,6 @@ private void TrySetCurrentlyTyping(bool newValue) } else { - global::System.Diagnostics.CI.Assert(!_isSkiaTextBox || _selection.length == 0); _historyIndex++; _history.RemoveAllAt(_historyIndex); _history.Add(new HistoryRecord(