Browse Source

Properly sync preedit

pull/10508/head
Benedikt Stebner 3 years ago
parent
commit
397867602e
  1. 50
      src/Avalonia.Controls/Presenters/TextPresenter.cs
  2. 56
      src/Avalonia.Controls/TextBoxTextInputMethodClient.cs
  3. 3
      src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs

50
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<TextPresenter, string?>(
nameof(Text),
o => o.Text,
(o, v) => o.Text = v);
(o, v) => o.Text = v, defaultBindingMode: BindingMode.OneWay);
/// <summary>
/// Defines the <see cref="PreeditText"/> 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;
//}
/// <summary>
/// Creates the <see cref="TextLayout"/> 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);

56
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;
}

3
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;

Loading…
Cancel
Save