diff --git a/src/Avalonia.Base/Input/TextInput/ITextInputMethodClient.cs b/src/Avalonia.Base/Input/TextInput/ITextInputMethodClient.cs
index 9ef2214cd8..14d57334d1 100644
--- a/src/Avalonia.Base/Input/TextInput/ITextInputMethodClient.cs
+++ b/src/Avalonia.Base/Input/TextInput/ITextInputMethodClient.cs
@@ -49,16 +49,7 @@ namespace Avalonia.Input.TextInput
/// The length after current selection.
void DeleteSurroundingText(int beforeLength, int afterLength);
- ///
- /// Returns the text before the cursor. Must return a non-empty string if cursor is not at the beginning of the text entry
- ///
- string? TextBeforeCursor { get; }
- ///
- /// Returns the text before the cursor. Must return a non-empty string if cursor is not at the end of the text entry
- ///
- string? TextAfterCursor { get; }
-
- public void SelectInSurroundingText(int start, int end);
+ void SelectInSurroundingText(int start, int end);
}
public struct TextInputMethodSurroundingText
diff --git a/src/Avalonia.Controls/TextBoxTextInputMethodClient.cs b/src/Avalonia.Controls/TextBoxTextInputMethodClient.cs
index c17d32ec17..425273d779 100644
--- a/src/Avalonia.Controls/TextBoxTextInputMethodClient.cs
+++ b/src/Avalonia.Controls/TextBoxTextInputMethodClient.cs
@@ -1,9 +1,6 @@
using System;
-using System.Diagnostics;
using Avalonia.Controls.Presenters;
-using Avalonia.Input;
using Avalonia.Input.TextInput;
-using Avalonia.Media;
using Avalonia.Threading;
using Avalonia.VisualTree;
@@ -14,6 +11,12 @@ namespace Avalonia.Controls
private TextBox? _parent;
private TextPresenter? _presenter;
+ public IVisual TextViewVisual => _presenter!;
+
+ public bool SupportsPreedit => true;
+
+ public bool SupportsSurroundingText => true;
+
public Rect CursorRectangle
{
get
@@ -36,10 +39,41 @@ namespace Avalonia.Controls
}
}
- public event EventHandler? CursorRectangleChanged;
- public IVisual TextViewVisual => _presenter!;
+ public TextInputMethodSurroundingText SurroundingText
+ {
+ get
+ {
+ if(_presenter is null)
+ {
+ return default;
+ }
+
+ var lineIndex = _presenter.TextLayout.GetLineIndexFromCharacterIndex(_presenter.CaretIndex, false);
+
+ var textLine = _presenter.TextLayout.TextLines[lineIndex];
+
+ var lineStart = textLine.FirstTextSourceIndex;
+
+ var lineText = _presenter.Text?.Substring(lineStart, textLine.Length);
+
+ var anchorOffset = Math.Max(0, _presenter.SelectionStart - lineStart);
+
+ var cursorOffset = Math.Max(0, _presenter.SelectionEnd - lineStart);
+
+ return new TextInputMethodSurroundingText
+ {
+ Text = lineText ?? "",
+ AnchorOffset = anchorOffset,
+ CursorOffset = cursorOffset
+ };
+ }
+ }
+
public event EventHandler? TextViewVisualChanged;
- public bool SupportsPreedit => true;
+
+ public event EventHandler? CursorRectangleChanged;
+
+ public event EventHandler? SurroundingTextChanged;
public void SetPreeditText(string? text)
{
@@ -51,58 +85,27 @@ namespace Avalonia.Controls
_presenter.PreeditText = text;
}
- public bool SupportsSurroundingText => true;
-
- public event EventHandler? SurroundingTextChanged;
-
- public TextInputMethodSurroundingText SurroundingText => new()
- {
- Text = _presenter?.Text ?? "",
- CursorOffset = _presenter?.CaretIndex ?? 0,
- AnchorOffset = _presenter?.SelectionStart ?? 0
- };
-
- public string? TextBeforeCursor => null;
-
- public string? TextAfterCursor => null;
public void SelectInSurroundingText(int start, int end)
{
if(_parent == null)
- return;
- // TODO: Account for the offset
- _parent.SelectionStart = start;
- _parent.SelectionEnd = end;
- }
-
- private void OnCaretBoundsChanged(object? sender, EventArgs e) =>
- Dispatcher.UIThread.Post(() => CursorRectangleChanged?.Invoke(this, EventArgs.Empty), DispatcherPriority.Input);
-
- private void OnTextBoxPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e)
- {
- if (e.Property == TextBox.TextProperty || e.Property == TextBox.SelectionStartProperty ||
- e.Property == TextBox.SelectionEndProperty)
{
- if (string.IsNullOrEmpty(_presenter?.PreeditText))
- {
- SurroundingTextChanged?.Invoke(this, EventArgs.Empty);
- }
+ return;
}
- }
+ //start and end are relative to surroundingText
+ var surroundingText = SurroundingText;
+
+ var selectionStart = surroundingText.AnchorOffset + start;
+ var selectionEnd = surroundingText.AnchorOffset + end;
+
+ _parent.SelectionStart = selectionStart;
+ _parent.SelectionEnd = selectionEnd;
+ }
+
public void SetPresenter(TextPresenter? presenter, TextBox? parent)
{
- if (_parent != null)
- {
- _parent.PropertyChanged -= OnTextBoxPropertyChanged;
- }
-
_parent = parent;
- if (_parent != null)
- {
- _parent.PropertyChanged += OnTextBoxPropertyChanged;
- }
-
if (_presenter != null)
{
_presenter.PreeditText = null;
@@ -118,7 +121,8 @@ namespace Avalonia.Controls
}
TextViewVisualChanged?.Invoke(this, EventArgs.Empty);
- CursorRectangleChanged?.Invoke(this, EventArgs.Empty);
+
+ OnCaretBoundsChanged(this, EventArgs.Empty);
}
public void DeleteSurroundingText(int beforeLength, int afterLength)
@@ -133,5 +137,19 @@ namespace Avalonia.Controls
_parent.DeleteSelection(true);
}
}
+
+ private void OnCaretBoundsChanged(object? sender, EventArgs e)
+ {
+ Dispatcher.UIThread.Post(() =>
+ {
+ if (SupportsSurroundingText)
+ {
+ SurroundingTextChanged?.Invoke(sender, e);
+ }
+
+ CursorRectangleChanged?.Invoke(sender, e);
+
+ }, DispatcherPriority.Input);
+ }
}
}
diff --git a/src/Web/Avalonia.Web.Blazor/AvaloniaView.razor.cs b/src/Web/Avalonia.Web.Blazor/AvaloniaView.razor.cs
index edd9c3e6e3..5b5951e800 100644
--- a/src/Web/Avalonia.Web.Blazor/AvaloniaView.razor.cs
+++ b/src/Web/Avalonia.Web.Blazor/AvaloniaView.razor.cs
@@ -349,12 +349,12 @@ namespace Avalonia.Web.Blazor
IsComposing = true;
break;
case WebCompositionEventArgs.WebCompositionEventType.Update:
- _client?.SetPreeditText(e.Data);
+ _client.SetPreeditText(e.Data);
break;
case WebCompositionEventArgs.WebCompositionEventType.End:
IsComposing = false;
- _client?.SetPreeditText(null);
- _topLevelImpl.RawTextEvent(e.Data);
+ _client.SetPreeditText(null);
+ _topLevelImpl.RawTextEvent(e.Data);
break;
}
}
@@ -471,7 +471,7 @@ namespace Avalonia.Web.Blazor
private void SurroundingTextChanged(object? sender, EventArgs e)
{
- if(_client != null && IsComposing)
+ if(_client != null)
{
var surroundingText = _client.SurroundingText;
@@ -484,15 +484,8 @@ namespace Avalonia.Web.Blazor
_inputHelper?.Focus();
var bounds = new PixelRect((int)rect.X, (int) rect.Y, (int) rect.Width, (int) rect.Height);
- if (_client != null)
- {
- var surroundingText = _client.SurroundingText;
-
- _inputHelper?.SetSurroundingText(surroundingText.Text, surroundingText.AnchorOffset,
- surroundingText.CursorOffset);
-
- _inputHelper?.SetBounds(bounds, surroundingText.CursorOffset);
- }
+ _inputHelper?.SetBounds(bounds, _client?.SurroundingText.CursorOffset ?? 0);
+ _inputHelper?.Focus();
}
public void SetOptions(TextInputOptions options)