Browse Source

Properly raise surroundingText changed

pull/8963/head
Benedikt Stebner 3 years ago
parent
commit
8084bdbd78
  1. 6
      src/Android/Avalonia.Android/AndroidInputMethod.cs
  2. 80
      src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs
  3. 45
      src/Avalonia.Controls/TextBoxTextInputMethodClient.cs

6
src/Android/Avalonia.Android/AndroidInputMethod.cs

@ -17,6 +17,8 @@ namespace Avalonia.Android
public ITextInputMethodClient Client { get; } public ITextInputMethodClient Client { get; }
public bool IsActive { get; } public bool IsActive { get; }
public InputMethodManager IMM { get; }
} }
enum CustomImeFlags enum CustomImeFlags
@ -55,6 +57,8 @@ namespace Avalonia.Android
public ITextInputMethodClient Client => _client; public ITextInputMethodClient Client => _client;
public InputMethodManager IMM => _imm;
public void Reset() public void Reset()
{ {
_imm.RestartInput(_host); _imm.RestartInput(_host);
@ -96,7 +100,7 @@ namespace Avalonia.Android
{ {
var surroundingText = Client.SurroundingText; var surroundingText = Client.SurroundingText;
_imm.UpdateSelection(_host, surroundingText.AnchorOffset, surroundingText.CursorOffset, surroundingText.AnchorOffset, surroundingText.CursorOffset); _imm.UpdateSelection(_host, surroundingText.AnchorOffset, surroundingText.CursorOffset, _inputConnection.ComposingRegion.Start, _inputConnection.ComposingRegion.End);
} }
} }

80
src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs

@ -262,9 +262,11 @@ namespace Avalonia.Android.Platform.SkiaPlatform
{ {
private readonly IAndroidInputMethod _inputMethod; private readonly IAndroidInputMethod _inputMethod;
public InputConnectionImpl(View? targetView, IAndroidInputMethod inputMethod) : public InputConnectionImpl(View targetView, IAndroidInputMethod inputMethod) :
base(targetView, false) base(targetView, false)
{ {
View = targetView;
_inputMethod = inputMethod; _inputMethod = inputMethod;
} }
@ -272,20 +274,12 @@ namespace Avalonia.Android.Platform.SkiaPlatform
{ {
} }
public View View { get; }
public ComposingRegion ComposingRegion { get; private set; } public ComposingRegion ComposingRegion { get; private set; }
public string CompositionText { get; private set; } public string CompositionText { get; private set; }
public override bool SetSelection(int start, int end)
{
if (_inputMethod.IsActive)
{
_inputMethod.Client.SelectInSurroundingText(start, end);
}
return base.SetSelection(start, end);
}
public override bool SetComposingRegion(int start, int end) public override bool SetComposingRegion(int start, int end)
{ {
if (_inputMethod.IsActive) if (_inputMethod.IsActive)
@ -300,21 +294,6 @@ namespace Avalonia.Android.Platform.SkiaPlatform
return base.SetComposingRegion(start, end); return base.SetComposingRegion(start, end);
} }
public override bool CommitCorrection(CorrectionInfo correctionInfo)
{
return base.CommitCorrection(correctionInfo);
}
public override bool DeleteSurroundingText(int beforeLength, int afterLength)
{
if (_inputMethod.IsActive && _inputMethod.Client.SupportsSurroundingText)
{
_inputMethod.Client.DeleteSurroundingText(beforeLength, afterLength);
}
return base.DeleteSurroundingText(beforeLength, afterLength);
}
public override ICharSequence GetTextBeforeCursorFormatted(int length, [GeneratedEnum] GetTextFlags flags) public override ICharSequence GetTextBeforeCursorFormatted(int length, [GeneratedEnum] GetTextFlags flags)
{ {
if (_inputMethod.IsActive) if (_inputMethod.IsActive)
@ -329,7 +308,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform
var text = surroundingText.Text.Substring(start, end - start); var text = surroundingText.Text.Substring(start, end - start);
//System.Diagnostics.Debug.WriteLine($"Text Before: {text}"); System.Diagnostics.Debug.WriteLine($"Text Before: {text}");
return new Java.Lang.String(text); return new Java.Lang.String(text);
} }
@ -352,7 +331,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform
var text = surroundingText.Text.Substring(start, end - start); var text = surroundingText.Text.Substring(start, end - start);
//System.Diagnostics.Debug.WriteLine($"Text After: {text}"); System.Diagnostics.Debug.WriteLine($"Text After: {text}");
return new Java.Lang.String(text); return new Java.Lang.String(text);
} }
@ -368,16 +347,16 @@ namespace Avalonia.Android.Platform.SkiaPlatform
if (_inputMethod.IsActive) if (_inputMethod.IsActive)
{ {
_inputMethod.Client.SetPreeditText(CompositionText); _inputMethod.Client.SetPreeditText(CompositionText);
if (!string.IsNullOrEmpty(CompositionText))
{
ComposingRegion = default;
}
} }
return base.SetComposingText(text, newCursorPosition); return base.SetComposingText(text, newCursorPosition);
} }
public override bool SendKeyEvent(KeyEvent e)
{
return base.SendKeyEvent(e);
}
public override bool CommitText(ICharSequence text, int newCursorPosition) public override bool CommitText(ICharSequence text, int newCursorPosition)
{ {
CompositionText = null; CompositionText = null;
@ -386,32 +365,19 @@ namespace Avalonia.Android.Platform.SkiaPlatform
{ {
_inputMethod.Client.SetPreeditText(null); _inputMethod.Client.SetPreeditText(null);
if (string.IsNullOrEmpty(CompositionText) && ComposingRegion.Start != ComposingRegion.End) var textLength = text.Length();
if (string.IsNullOrEmpty(CompositionText) && ComposingRegion.End > 0)
{ {
_inputMethod.Client.SelectInSurroundingText(ComposingRegion.Start, ComposingRegion.End); _inputMethod.Client.SelectInSurroundingText(ComposingRegion.Start, ComposingRegion.Start + textLength);
} }
ComposingRegion = new ComposingRegion(ComposingRegion.Start, ComposingRegion.Start + text.Length()); ComposingRegion = new ComposingRegion(ComposingRegion.Start, ComposingRegion.Start + textLength);
} }
return base.CommitText(text, newCursorPosition); return base.CommitText(text, newCursorPosition);
} }
public override bool PerformEditorAction([GeneratedEnum] ImeAction actionCode)
{
return base.PerformEditorAction(actionCode);
}
public override bool PerformPrivateCommand(string action, Bundle data)
{
return base.PerformPrivateCommand(action, data);
}
public override bool SendKeyEvent(KeyEvent e)
{
return base.SendKeyEvent(e);
}
public override bool FinishComposingText() public override bool FinishComposingText()
{ {
CompositionText = null; CompositionText = null;
@ -427,14 +393,16 @@ namespace Avalonia.Android.Platform.SkiaPlatform
public readonly struct ComposingRegion public readonly struct ComposingRegion
{ {
private readonly int _start = -1;
private readonly int _end = -1;
public ComposingRegion(int start, int end) public ComposingRegion(int start, int end)
{ {
Start = start; _start = start;
End = end; _end = end;
} }
public int Start { get; } public int Start => _start;
public int End => _end;
public int End { get; }
} }
} }

45
src/Avalonia.Controls/TextBoxTextInputMethodClient.cs

@ -43,7 +43,7 @@ namespace Avalonia.Controls
{ {
get get
{ {
if(_presenter is null) if(_presenter is null || _parent is null)
{ {
return default; return default;
} }
@ -56,7 +56,7 @@ namespace Avalonia.Controls
var lineText = _presenter.Text?.Substring(lineStart, textLine.Length); var lineText = _presenter.Text?.Substring(lineStart, textLine.Length);
var anchorOffset = Math.Max(0, _presenter.SelectionStart - lineStart); var anchorOffset = Math.Max(0, _parent.SelectionStart - lineStart);
var cursorOffset = Math.Max(0, _presenter.SelectionEnd - lineStart); var cursorOffset = Math.Max(0, _presenter.SelectionEnd - lineStart);
@ -87,16 +87,19 @@ namespace Avalonia.Controls
public void SelectInSurroundingText(int start, int end) public void SelectInSurroundingText(int start, int end)
{ {
if(_parent == null) if(_parent is null ||_presenter is null)
{ {
return; return;
} }
//start and end are relative to surroundingText var lineIndex = _presenter.TextLayout.GetLineIndexFromCharacterIndex(_presenter.CaretIndex, false);
var surroundingText = SurroundingText;
var selectionStart = surroundingText.AnchorOffset + start; var textLine = _presenter.TextLayout.TextLines[lineIndex];
var selectionEnd = surroundingText.AnchorOffset + end;
var lineStart = textLine.FirstTextSourceIndex;
var selectionStart = lineStart + start;
var selectionEnd = lineStart + end;
_parent.SelectionStart = selectionStart; _parent.SelectionStart = selectionStart;
_parent.SelectionEnd = selectionEnd; _parent.SelectionEnd = selectionEnd;
@ -104,13 +107,23 @@ namespace Avalonia.Controls
public void SetPresenter(TextPresenter? presenter, TextBox? parent) public void SetPresenter(TextPresenter? presenter, TextBox? parent)
{ {
if(_parent != null)
{
_parent.PropertyChanged -= OnParentPropertyChanged;
}
_parent = parent; _parent = parent;
if(_parent != null)
{
_parent.PropertyChanged += OnParentPropertyChanged;
}
if (_presenter != null) if (_presenter != null)
{ {
_presenter.PreeditText = null; _presenter.PreeditText = null;
_presenter.CaretBoundsChanged -= OnCaretBoundsChanged; _presenter.CaretBoundsChanged -= OnCaretBoundsChanged;
} }
_presenter = presenter; _presenter = presenter;
@ -125,6 +138,17 @@ namespace Avalonia.Controls
OnCaretBoundsChanged(this, EventArgs.Empty); OnCaretBoundsChanged(this, EventArgs.Empty);
} }
private void OnParentPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e)
{
if(e.Property == TextBox.SelectionStartProperty || e.Property == TextBox.SelectionEndProperty)
{
if (SupportsSurroundingText)
{
SurroundingTextChanged?.Invoke(this, e);
}
}
}
public void DeleteSurroundingText(int beforeLength, int afterLength) public void DeleteSurroundingText(int beforeLength, int afterLength)
{ {
if (_parent != null && _presenter != null && string.IsNullOrEmpty(_presenter.PreeditText)) if (_parent != null && _presenter != null && string.IsNullOrEmpty(_presenter.PreeditText))
@ -142,11 +166,6 @@ namespace Avalonia.Controls
{ {
Dispatcher.UIThread.Post(() => Dispatcher.UIThread.Post(() =>
{ {
if (SupportsSurroundingText)
{
SurroundingTextChanged?.Invoke(this, e);
}
CursorRectangleChanged?.Invoke(this, e); CursorRectangleChanged?.Invoke(this, e);
}, DispatcherPriority.Input); }, DispatcherPriority.Input);

Loading…
Cancel
Save