|
|
|
@ -1,6 +1,7 @@ |
|
|
|
using System; |
|
|
|
using System.Collections.Generic; |
|
|
|
using System.Runtime.Versioning; |
|
|
|
using System.Threading; |
|
|
|
using Android.App; |
|
|
|
using Android.Content; |
|
|
|
using Android.Graphics; |
|
|
|
@ -454,6 +455,9 @@ namespace Avalonia.Android.Platform.SkiaPlatform |
|
|
|
_inputConnection = inputConnection; |
|
|
|
} |
|
|
|
|
|
|
|
public TextSelection CurrentSelection => new TextSelection(Selection.GetSelectionStart(this), Selection.GetSelectionEnd(this)); |
|
|
|
public TextSelection CurrentComposition => new TextSelection(BaseInputConnection.GetComposingSpanStart(this), BaseInputConnection.GetComposingSpanEnd(this)); |
|
|
|
|
|
|
|
public bool IgnoreChange { get; set; } |
|
|
|
|
|
|
|
public override IEditable Replace(int start, int end, ICharSequence tb) |
|
|
|
@ -480,11 +484,6 @@ namespace Avalonia.Android.Platform.SkiaPlatform |
|
|
|
{ |
|
|
|
_inputConnection.InputMethod.Client.Selection = new TextSelection(start, end); |
|
|
|
} |
|
|
|
|
|
|
|
public override void SetSpan(Java.Lang.Object what, int start, int end, [GeneratedEnum] SpanTypes flags) |
|
|
|
{ |
|
|
|
base.SetSpan(what, start, end, flags); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
internal class AvaloniaInputConnection : BaseInputConnection |
|
|
|
@ -493,8 +492,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform |
|
|
|
private readonly IAndroidInputMethod _inputMethod; |
|
|
|
private readonly EditableWrapper _editable; |
|
|
|
private bool _commitInProgress; |
|
|
|
private (int Start, int End)? _composingRegion; |
|
|
|
private TextSelection _selection; |
|
|
|
private int _batchLevel = 0; |
|
|
|
|
|
|
|
public AvaloniaInputConnection(TopLevelImpl toplevel, IAndroidInputMethod inputMethod) : base(inputMethod.View, true) |
|
|
|
{ |
|
|
|
@ -513,36 +511,64 @@ namespace Avalonia.Android.Platform.SkiaPlatform |
|
|
|
|
|
|
|
public TopLevelImpl Toplevel => _toplevel; |
|
|
|
|
|
|
|
public bool IsInBatchEdit => _batchLevel > 0; |
|
|
|
|
|
|
|
public override bool SetComposingRegion(int start, int end) |
|
|
|
{ |
|
|
|
_composingRegion = new(start, end); |
|
|
|
|
|
|
|
return base.SetComposingRegion(start, end); |
|
|
|
} |
|
|
|
|
|
|
|
public override bool SetComposingText(ICharSequence text, int newCursorPosition) |
|
|
|
{ |
|
|
|
if(_composingRegion != null) |
|
|
|
BeginBatchEdit(); |
|
|
|
_editable.IgnoreChange = true; |
|
|
|
|
|
|
|
try |
|
|
|
{ |
|
|
|
// Select the composing region.
|
|
|
|
InputMethod.Client.Selection = new TextSelection(_composingRegion.Value.Start, _composingRegion.Value.End); |
|
|
|
} |
|
|
|
var compositionText = text.SubSequence(0, text.Length()); |
|
|
|
if (_editable.CurrentComposition.Start > -1) |
|
|
|
{ |
|
|
|
// Select the composing region.
|
|
|
|
InputMethod.Client.Selection = new TextSelection(_editable.CurrentComposition.Start, _editable.CurrentComposition.End); |
|
|
|
} |
|
|
|
var compositionText = text.SubSequence(0, text.Length()); |
|
|
|
|
|
|
|
if (_inputMethod.IsActive && !_commitInProgress) |
|
|
|
{ |
|
|
|
if (string.IsNullOrEmpty(compositionText)) |
|
|
|
_inputMethod.View.DispatchKeyEvent(new KeyEvent(KeyEventActions.Down, Keycode.ForwardDel)); |
|
|
|
|
|
|
|
if (_inputMethod.IsActive && !_commitInProgress) |
|
|
|
else |
|
|
|
_toplevel.TextInput(compositionText); |
|
|
|
} |
|
|
|
base.SetComposingText(text, newCursorPosition); |
|
|
|
} |
|
|
|
finally |
|
|
|
{ |
|
|
|
if (string.IsNullOrEmpty(compositionText)) |
|
|
|
_inputMethod.View.DispatchKeyEvent(new KeyEvent(KeyEventActions.Down, Keycode.ForwardDel)); |
|
|
|
_editable.IgnoreChange = false; |
|
|
|
|
|
|
|
else |
|
|
|
_toplevel.TextInput(compositionText); |
|
|
|
EndBatchEdit(); |
|
|
|
} |
|
|
|
|
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
public override bool BeginBatchEdit() |
|
|
|
{ |
|
|
|
_batchLevel = Interlocked.Increment(ref _batchLevel); |
|
|
|
return base.BeginBatchEdit(); |
|
|
|
} |
|
|
|
|
|
|
|
public override bool EndBatchEdit() |
|
|
|
{ |
|
|
|
_batchLevel = Interlocked.Decrement(ref _batchLevel); |
|
|
|
|
|
|
|
_inputMethod.OnBatchEditedEnded(); |
|
|
|
return base.EndBatchEdit(); |
|
|
|
} |
|
|
|
|
|
|
|
public override bool CommitText(ICharSequence text, int newCursorPosition) |
|
|
|
{ |
|
|
|
BeginBatchEdit(); |
|
|
|
_commitInProgress = true; |
|
|
|
|
|
|
|
var ret = base.CommitText(text, newCursorPosition); |
|
|
|
@ -551,22 +577,15 @@ namespace Avalonia.Android.Platform.SkiaPlatform |
|
|
|
|
|
|
|
if (_inputMethod.IsActive && !string.IsNullOrEmpty(committedText)) |
|
|
|
{ |
|
|
|
_toplevel.TextInput(committedText); |
|
|
|
|
|
|
|
_composingRegion = null; |
|
|
|
_toplevel.TextInput(committedText); |
|
|
|
} |
|
|
|
|
|
|
|
_commitInProgress = false; |
|
|
|
EndBatchEdit(); |
|
|
|
|
|
|
|
return ret; |
|
|
|
} |
|
|
|
|
|
|
|
public override bool FinishComposingText() |
|
|
|
{ |
|
|
|
_composingRegion = null; |
|
|
|
return base.FinishComposingText(); |
|
|
|
} |
|
|
|
|
|
|
|
public override bool DeleteSurroundingText(int beforeLength, int afterLength) |
|
|
|
{ |
|
|
|
if (InputMethod.IsActive) |
|
|
|
@ -577,7 +596,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform |
|
|
|
|
|
|
|
if (InputMethod.IsActive) |
|
|
|
{ |
|
|
|
var selection = _selection; |
|
|
|
var selection = _editable.CurrentSelection; |
|
|
|
|
|
|
|
InputMethod.Client.Selection = new TextSelection(selection.Start - beforeLength, selection.End + afterLength); |
|
|
|
|
|
|
|
@ -589,12 +608,6 @@ namespace Avalonia.Android.Platform.SkiaPlatform |
|
|
|
return result; |
|
|
|
} |
|
|
|
|
|
|
|
public override bool SetSelection(int start, int end) |
|
|
|
{ |
|
|
|
_selection = new TextSelection(start, end); |
|
|
|
return base.SetSelection(start, end); |
|
|
|
} |
|
|
|
|
|
|
|
public override bool PerformEditorAction([GeneratedEnum] ImeAction actionCode) |
|
|
|
{ |
|
|
|
switch (actionCode) |
|
|
|
@ -628,7 +641,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform |
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
var selection = _selection; |
|
|
|
var selection = _editable.CurrentSelection; |
|
|
|
|
|
|
|
ExtractedText extract = new ExtractedText |
|
|
|
{ |
|
|
|
|