diff --git a/src/Android/Avalonia.Android/AndroidInputMethod.cs b/src/Android/Avalonia.Android/AndroidInputMethod.cs
index 590dc70cb4..b2ce2a38b1 100644
--- a/src/Android/Avalonia.Android/AndroidInputMethod.cs
+++ b/src/Android/Avalonia.Android/AndroidInputMethod.cs
@@ -100,12 +100,13 @@ namespace Avalonia.Android
{
var surroundingText = Client.SurroundingText;
- _imm.UpdateSelection(_host, surroundingText.AnchorOffset, surroundingText.CursorOffset, _inputConnection.ComposingRegion.Start, _inputConnection.ComposingRegion.End);
+ _imm.UpdateSelection(_host, surroundingText.AnchorOffset, surroundingText.CursorOffset, surroundingText.AnchorOffset, surroundingText.CursorOffset);
}
}
public void SetCursorRect(Rect rect)
{
+
}
public void SetOptions(TextInputOptions options)
@@ -114,7 +115,7 @@ namespace Avalonia.Android
_host.InitEditorInfo((_host, outAttrs) =>
{
- _inputConnection?.FinishComposingText();
+ //_inputConnection?.FinishComposingText();
outAttrs.InputType = options.ContentType switch
{
diff --git a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs
index fce7106674..491d590762 100644
--- a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs
+++ b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs
@@ -276,7 +276,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform
public View View { get; }
- public ComposingRegion ComposingRegion { get; private set; }
+ public ComposingRegion ComposingRegion { get; internal set; }
public string CompositionText { get; private set; }
@@ -365,14 +365,18 @@ namespace Avalonia.Android.Platform.SkiaPlatform
{
_inputMethod.Client.SetPreeditText(null);
- var textLength = text.Length();
-
- if (string.IsNullOrEmpty(CompositionText) && ComposingRegion.End > 0)
+ if (string.IsNullOrEmpty(CompositionText))
{
- _inputMethod.Client.SelectInSurroundingText(ComposingRegion.Start, ComposingRegion.Start + textLength);
+ var surroundingText = _inputMethod.Client.SurroundingText;
+
+ var composingRegionLength = ComposingRegion.End - ComposingRegion.Start;
+
+ var composingRegionText = surroundingText.Text?.Substring(ComposingRegion.Start, composingRegionLength);
+
+ _inputMethod.Client.SelectInSurroundingText(ComposingRegion.Start, ComposingRegion.End);
}
- ComposingRegion = new ComposingRegion(ComposingRegion.Start, ComposingRegion.Start + textLength);
+ ComposingRegion = new ComposingRegion(ComposingRegion.End, ComposingRegion.End);
}
return base.CommitText(text, newCursorPosition);
diff --git a/src/Avalonia.Base/Input/TextInput/ITextInputMethodClient.cs b/src/Avalonia.Base/Input/TextInput/ITextInputMethodClient.cs
index 14d57334d1..325b6dd0ef 100644
--- a/src/Avalonia.Base/Input/TextInput/ITextInputMethodClient.cs
+++ b/src/Avalonia.Base/Input/TextInput/ITextInputMethodClient.cs
@@ -42,13 +42,6 @@ namespace Avalonia.Input.TextInput
///
event EventHandler? SurroundingTextChanged;
- ///
- /// Deletes specified length before and after current selection.
- ///
- /// The length before current selection.
- /// The length after current selection.
- void DeleteSurroundingText(int beforeLength, int afterLength);
-
void SelectInSurroundingText(int start, int end);
}
diff --git a/src/Avalonia.Controls/Presenters/TextPresenter.cs b/src/Avalonia.Controls/Presenters/TextPresenter.cs
index b0b12d1ff9..a9bb16c7df 100644
--- a/src/Avalonia.Controls/Presenters/TextPresenter.cs
+++ b/src/Avalonia.Controls/Presenters/TextPresenter.cs
@@ -847,12 +847,21 @@ namespace Avalonia.Controls.Presenters
_caretTimer.Tick -= CaretTimerTick;
}
- protected void OnPreeditTextChanged(string? preeditText)
+ protected void OnPreeditTextChanged(string? oldValue, string? newValue)
{
InvalidateTextLayout();
- if (preeditText is null)
+ if (string.IsNullOrEmpty(newValue))
{
+ if (!string.IsNullOrEmpty(oldValue))
+ {
+ var textPosition = _compositionStartHit.FirstCharacterIndex + _compositionStartHit.TrailingLength + newValue?.Length ?? 0;
+
+ var characterHit = GetCharacterHitFromTextPosition(textPosition);
+
+ UpdateCaret(characterHit, true);
+ }
+
_compositionStartHit = new CharacterHit(-1);
}
else
@@ -865,18 +874,25 @@ namespace Avalonia.Controls.Presenters
if (_compositionStartHit.FirstCharacterIndex != -1)
{
- var textPosition = _compositionStartHit.FirstCharacterIndex + _compositionStartHit.TrailingLength + preeditText?.Length ?? 0;
-
- var lineIndex = TextLayout.GetLineIndexFromCharacterIndex(textPosition, true);
-
- var textLine = TextLayout.TextLines[lineIndex];
+ var textPosition = _compositionStartHit.FirstCharacterIndex + _compositionStartHit.TrailingLength + newValue?.Length ?? 0;
- var characterHit = textLine.GetNextCaretCharacterHit(new CharacterHit(textPosition - 1));
+ var characterHit = GetCharacterHitFromTextPosition(textPosition);
UpdateCaret(characterHit, false);
}
}
+ private CharacterHit GetCharacterHitFromTextPosition(int textPosition)
+ {
+ var lineIndex = TextLayout.GetLineIndexFromCharacterIndex(textPosition, true);
+
+ var textLine = TextLayout.TextLines[lineIndex];
+
+ var characterHit = textLine.GetNextCaretCharacterHit(new CharacterHit(textPosition - 1));
+
+ return characterHit;
+ }
+
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
@@ -885,7 +901,7 @@ namespace Avalonia.Controls.Presenters
{
case nameof(PreeditText):
{
- OnPreeditTextChanged(change.NewValue as string);
+ OnPreeditTextChanged(change.OldValue as string, change.NewValue as string);
break;
}
diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs
index d14074a2ff..964a153c8b 100644
--- a/src/Avalonia.Controls/TextBox.cs
+++ b/src/Avalonia.Controls/TextBox.cs
@@ -831,6 +831,11 @@ namespace Avalonia.Controls
return;
}
+ if (!string.IsNullOrEmpty(_presenter.PreeditText))
+ {
+ return;
+ }
+
var text = Text ?? string.Empty;
var caretIndex = CaretIndex;
var movement = false;
diff --git a/src/Avalonia.Controls/TextBoxTextInputMethodClient.cs b/src/Avalonia.Controls/TextBoxTextInputMethodClient.cs
index d1277f5855..d39d964277 100644
--- a/src/Avalonia.Controls/TextBoxTextInputMethodClient.cs
+++ b/src/Avalonia.Controls/TextBoxTextInputMethodClient.cs
@@ -1,7 +1,9 @@
using System;
using Avalonia.Controls.Presenters;
using Avalonia.Input.TextInput;
+using Avalonia.Media.TextFormatting;
using Avalonia.Threading;
+using Avalonia.Utilities;
using Avalonia.VisualTree;
namespace Avalonia.Controls
@@ -54,7 +56,7 @@ namespace Avalonia.Controls
var lineStart = textLine.FirstTextSourceIndex;
- var lineText = _presenter.Text?.Substring(lineStart, textLine.Length);
+ var lineText = GetTextLineText(textLine);
var anchorOffset = Math.Max(0, _parent.SelectionStart - lineStart);
@@ -69,6 +71,29 @@ namespace Avalonia.Controls
}
}
+ private static string GetTextLineText(TextLine textLine)
+ {
+ var builder = StringBuilderCache.Acquire(textLine.Length);
+
+ foreach (var run in textLine.TextRuns)
+ {
+ if(run.Text.Length > 0)
+ {
+#if NET6_0
+ builder.Append(run.Text.Span);
+#else
+ builder.Append(run.Text.Span.ToArray());
+#endif
+ }
+ }
+
+ var lineText = builder.ToString();
+
+ StringBuilderCache.Release(builder);
+
+ return lineText;
+ }
+
public event EventHandler? TextViewVisualChanged;
public event EventHandler? CursorRectangleChanged;
@@ -149,19 +174,6 @@ namespace Avalonia.Controls
}
}
- public void DeleteSurroundingText(int beforeLength, int afterLength)
- {
- if (_parent != null && _presenter != null && string.IsNullOrEmpty(_presenter.PreeditText))
- {
- var start = _presenter.SelectionStart;
-
- _parent.SelectionStart = start - beforeLength;
- _parent.SelectionEnd = start + afterLength;
-
- _parent.DeleteSelection(true);
- }
- }
-
private void OnCaretBoundsChanged(object? sender, EventArgs e)
{
Dispatcher.UIThread.Post(() =>
diff --git a/src/Windows/Avalonia.Win32/Input/Imm32InputMethod.cs b/src/Windows/Avalonia.Win32/Input/Imm32InputMethod.cs
index b504b306c7..7ef1cb1d1c 100644
--- a/src/Windows/Avalonia.Win32/Input/Imm32InputMethod.cs
+++ b/src/Windows/Avalonia.Win32/Input/Imm32InputMethod.cs
@@ -1,5 +1,4 @@
using System;
-using System.Runtime.InteropServices;
using System.Text;
using Avalonia.Input.TextInput;
using Avalonia.Threading;
@@ -79,9 +78,7 @@ namespace Avalonia.Win32.Input
{
HWND = hwnd;
_parent = parent;
- _active = false;
_langId = PRIMARYLANGID(LGID(HKL));
- _showCompositionWindow = true;
_parent = parent;
@@ -105,7 +102,6 @@ namespace Avalonia.Win32.Input
_parent = null;
_client = null;
_langId = 0;
- _showCompositionWindow = false;
IsComposing = false;
}