diff --git a/src/Avalonia.Controls/Presenters/TextPresenter.cs b/src/Avalonia.Controls/Presenters/TextPresenter.cs index 14d8270647..2e6f1a0f2d 100644 --- a/src/Avalonia.Controls/Presenters/TextPresenter.cs +++ b/src/Avalonia.Controls/Presenters/TextPresenter.cs @@ -10,6 +10,7 @@ using Avalonia.Layout; using Avalonia.Media.Immutable; using Avalonia.Controls.Documents; using Avalonia.Input.TextInput; +using Avalonia.Data; namespace Avalonia.Controls.Presenters { @@ -52,7 +53,7 @@ namespace Avalonia.Controls.Presenters AvaloniaProperty.RegisterDirect( nameof(Text), o => o.Text, - (o, v) => o.Text = v); + (o, v) => o.Text = v, defaultBindingMode: BindingMode.OneWay); /// /// Defines the property. @@ -107,7 +108,7 @@ namespace Avalonia.Controls.Presenters private int _selectionStart; private int _selectionEnd; private bool _caretBlink; - private string? _text; + internal string? _text; private TextLayout? _textLayout; private Size _constraint; @@ -526,22 +527,22 @@ namespace Avalonia.Controls.Presenters } } - private string? GetText() - { - if (!string.IsNullOrEmpty(_preeditText)) - { - if (string.IsNullOrEmpty(_text) || _caretIndex > _text.Length) - { - return _preeditText; - } + //private string? GetText() + //{ + // if (!string.IsNullOrEmpty(_preeditText)) + // { + // if (string.IsNullOrEmpty(_text) || _caretIndex > _text.Length) + // { + // return _preeditText; + // } - var text = _text.Substring(0, _caretIndex) + _preeditText + _text.Substring(_caretIndex); + // var text = _text.Substring(0, _caretIndex) + _preeditText + _text.Substring(_caretIndex); - return text; - } + // return text; + // } - return _text; - } + // return _text; + //} /// /// Creates the used to render the text. @@ -551,7 +552,7 @@ namespace Avalonia.Controls.Presenters { TextLayout result; - var text = GetText(); + var text = _text; var typeface = new Typeface(FontFamily, FontStyle, FontWeight); @@ -851,7 +852,7 @@ namespace Avalonia.Controls.Presenters CaretChanged(); } - private void UpdateCaret(CharacterHit characterHit, bool notify = true) + internal void UpdateCaret(CharacterHit characterHit, bool notify = true) { _lastCharacterHit = characterHit; @@ -883,10 +884,6 @@ namespace Avalonia.Controls.Presenters { SetAndRaise(CaretIndexProperty, ref _caretIndex, caretIndex); } - else - { - _caretIndex = caretIndex; - } } internal Rect GetCursorRectangle() @@ -903,17 +900,6 @@ namespace Avalonia.Controls.Presenters _caretTimer.Tick -= CaretTimerTick; } - 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); diff --git a/src/Avalonia.Controls/TextBoxTextInputMethodClient.cs b/src/Avalonia.Controls/TextBoxTextInputMethodClient.cs index 347cac13ef..6f8f3f3cab 100644 --- a/src/Avalonia.Controls/TextBoxTextInputMethodClient.cs +++ b/src/Avalonia.Controls/TextBoxTextInputMethodClient.cs @@ -1,6 +1,8 @@ using System; +using System.Diagnostics; using Avalonia.Controls.Presenters; using Avalonia.Input.TextInput; +using Avalonia.Media; using Avalonia.Media.TextFormatting; using Avalonia.Threading; using Avalonia.Utilities; @@ -75,7 +77,7 @@ namespace Avalonia.Controls { get => _textEditable; set { - if(_textEditable != null) + if (_textEditable != null) { _textEditable.TextChanged -= TextEditable_TextChanged; _textEditable.SelectionChanged -= TextEditable_SelectionChanged; @@ -84,7 +86,7 @@ namespace Avalonia.Controls _textEditable = value; - if(_textEditable != null) + if (_textEditable != null) { _textEditable.TextChanged += TextEditable_TextChanged; _textEditable.SelectionChanged += TextEditable_SelectionChanged; @@ -110,7 +112,7 @@ namespace Avalonia.Controls private void TextEditable_SelectionChanged(object? sender, EventArgs e) { - if(_parent != null && _textEditable != null) + if (_parent != null && _textEditable != null) { _parent.SelectionStart = _textEditable.SelectionStart; _parent.SelectionEnd = _textEditable.SelectionEnd; @@ -157,16 +159,53 @@ namespace Avalonia.Controls public event EventHandler? SurroundingTextChanged; - public void SetPreeditText(string? text) + private string? _presenterText; + private int _compositionStart; + + public void SetPreeditText(string? preeditText) { if (_presenter == null || _parent == null) { return; } - _presenter.CaretIndex = _parent.CaretIndex; + if (_presenterText is null) + { + _presenterText = _parent.Text ?? ""; + _compositionStart = _parent.CaretIndex; + } + + var text = GetText(preeditText); + + Debug.WriteLine(text); + + _presenter._text = text; + + _presenter.PreeditText = preeditText; + + _presenter.UpdateCaret(new CharacterHit(_compositionStart + (preeditText != null ? preeditText.Length : 0)), false); + + if (string.IsNullOrEmpty(preeditText)) + { + _presenterText = null; + } + } + + private string? GetText(string? preeditText) + { + if (string.IsNullOrEmpty(preeditText)) + { + return _presenterText; + } + + if (string.IsNullOrEmpty(_presenterText)) + { + return preeditText; + } + + var text = _presenterText.Substring(0, _compositionStart) + preeditText + _presenterText.Substring(_compositionStart); - _presenter.PreeditText = text; + return text; } public void SetComposingRegion(TextRange? region) @@ -175,6 +214,7 @@ namespace Avalonia.Controls { return; } + _presenter.CompositionRegion = region; } @@ -256,9 +296,9 @@ namespace Avalonia.Controls } } - if(e.Property == TextBox.TextProperty) + if (e.Property == TextBox.TextProperty) { - if(_textEditable != null) + if (_textEditable != null) { _textEditable.Text = (string?)e.NewValue; } diff --git a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs index e8d2d8f0c5..1cc9d1fa2f 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs @@ -713,13 +713,14 @@ namespace Avalonia.Win32 break; } + case WindowsMessage.WM_IME_SELECT: + break; case WindowsMessage.WM_IME_CHAR: case WindowsMessage.WM_IME_COMPOSITIONFULL: case WindowsMessage.WM_IME_CONTROL: case WindowsMessage.WM_IME_KEYDOWN: case WindowsMessage.WM_IME_KEYUP: case WindowsMessage.WM_IME_NOTIFY: - case WindowsMessage.WM_IME_SELECT: break; case WindowsMessage.WM_IME_STARTCOMPOSITION: Imm32InputMethod.Current.IsComposing = true;