Browse Source

suspend selection updates in TextBoxTextInputMethodClient until all changes are completed (#15659)

pull/15666/head
Emmanuel Hansen 2 years ago
committed by GitHub
parent
commit
7da4f3b05f
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 12
      src/Android/Avalonia.Android/AndroidInputMethod.cs
  2. 19
      src/Avalonia.Controls/TextBox.cs
  3. 27
      src/Avalonia.Controls/TextBoxTextInputMethodClient.cs

12
src/Android/Avalonia.Android/AndroidInputMethod.cs

@ -117,16 +117,20 @@ namespace Avalonia.Android
private void OnSelectionChanged()
{
if (Client is null)
if (Client is null || _inputConnection is null)
{
return;
}
OnSurroundingTextChanged();
var selection = Client.Selection;
_imm.UpdateSelection(_host, selection.Start, selection.End, selection.Start, selection.End);
_inputConnection.SetSelection(selection.Start, selection.End);
var composition = _inputConnection.EditableWrapper.CurrentComposition;
_inputConnection?.SetSelection(selection.Start, selection.End);
_imm.UpdateSelection(_host, selection.Start, selection.End, composition.Start, composition.End);
}
private void _client_SurroundingTextChanged(object? sender, EventArgs e)
@ -140,8 +144,6 @@ namespace Avalonia.Android
{
if (_inputConnection is null || _inputConnection.IsInBatchEdit)
return;
OnSurroundingTextChanged();
OnSelectionChanged();
}

19
src/Avalonia.Controls/TextBox.cs

@ -406,6 +406,8 @@ namespace Avalonia.Controls
if (IsUndoEnabled && _undoRedoHelper.TryGetLastState(out state) && state.Text == Text)
_undoRedoHelper.UpdateLastState();
using var _ = _imClient.BeginChange();
var newValue = e.GetNewValue<int>();
SetCurrentValue(SelectionStartProperty, newValue);
SetCurrentValue(SelectionEndProperty, newValue);
@ -1216,6 +1218,8 @@ namespace Avalonia.Controls
var keymap = Application.Current!.PlatformSettings!.HotkeyConfiguration;
using var _ = _imClient.BeginChange();
bool Match(List<KeyGesture> gestures) => gestures.Any(g => g.Matches(e));
bool DetectSelection() => e.KeyModifiers.HasAllFlags(keymap.SelectionModifiers);
@ -1547,6 +1551,8 @@ namespace Avalonia.Controls
var text = Text;
var clickInfo = e.GetCurrentPoint(this);
using var _ = _imClient.BeginChange();
if (text != null && (e.Pointer.Type == PointerType.Mouse || e.ClickCount >= 2) && clickInfo.Properties.IsLeftButtonPressed &&
!(clickInfo.Pointer?.Captured is Border))
{
@ -1631,6 +1637,7 @@ namespace Avalonia.Controls
{
return;
}
using var _ = _imClient.BeginChange();
// selection should not change during pointer move if the user right clicks
if (e.Pointer.Captured == _presenter && e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
@ -1713,6 +1720,8 @@ namespace Avalonia.Controls
return;
}
using var _ = _imClient.BeginChange();
if (e.Pointer.Type != PointerType.Mouse && !_isDoubleTapped)
{
var text = Text;
@ -1857,6 +1866,8 @@ namespace Avalonia.Controls
return;
}
using var _ = _imClient.BeginChange();
var text = Text ?? string.Empty;
var selectionStart = SelectionStart;
var selectionEnd = SelectionEnd;
@ -2017,6 +2028,8 @@ namespace Avalonia.Controls
/// </summary>
public void SelectAll()
{
using var _ = _imClient.BeginChange();
SetCurrentValue(SelectionStartProperty, 0);
SetCurrentValue(SelectionEndProperty, Text?.Length ?? 0);
}
@ -2034,6 +2047,8 @@ namespace Avalonia.Controls
if (IsReadOnly)
return true;
using var _ = _imClient.BeginChange();
var (start, end) = GetSelectionRange();
if (start != end)
@ -2141,6 +2156,8 @@ namespace Avalonia.Controls
var text = Text ?? string.Empty;
var selectionStart = CaretIndex;
using var _ = _imClient.BeginChange();
MoveHorizontal(-1, true, false, false);
if (SelectionEnd > 0 &&
@ -2160,6 +2177,8 @@ namespace Avalonia.Controls
return;
}
using var _ = _imClient.BeginChange();
SetCurrentValue(SelectionStartProperty, CaretIndex);
MoveHorizontal(1, true, true, false);

27
src/Avalonia.Controls/TextBoxTextInputMethodClient.cs

@ -2,6 +2,7 @@ using System;
using Avalonia.Controls.Presenters;
using Avalonia.Input.TextInput;
using Avalonia.Media.TextFormatting;
using Avalonia.Reactive;
using Avalonia.Utilities;
namespace Avalonia.Controls
@ -10,6 +11,8 @@ namespace Avalonia.Controls
{
private TextBox? _parent;
private TextPresenter? _presenter;
private bool _selectionChanged;
private bool _isInChange;
public override Visual TextViewVisual => _presenter!;
@ -190,8 +193,30 @@ namespace Avalonia.Controls
if (e.Property == TextBox.SelectionStartProperty || e.Property == TextBox.SelectionEndProperty)
{
RaiseSelectionChanged();
if (_isInChange)
_selectionChanged = true;
else
RaiseSelectionChanged();
}
}
internal IDisposable BeginChange()
{
if (_isInChange)
return Disposable.Empty;
_isInChange = true;
return Disposable.Create(RaiseEvents);
}
private void RaiseEvents()
{
_isInChange = false;
if (_selectionChanged)
RaiseSelectionChanged();
_selectionChanged = false;
}
}
}

Loading…
Cancel
Save