Browse Source

Respect IME preedit cursor position on Win32 (#21632)

pull/21644/head
Shun-ichi Goto 1 month ago
committed by GitHub
parent
commit
bdc8314235
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 80
      src/Windows/Avalonia.Win32/Input/Imm32InputMethod.cs

80
src/Windows/Avalonia.Win32/Input/Imm32InputMethod.cs

@ -25,6 +25,7 @@ namespace Avalonia.Win32.Input
private const int CaretMargin = 1;
private bool _ignoreComposition;
private int? _compositionCursorPosition;
public TextInputMethodClient? Client { get; private set; }
@ -110,6 +111,7 @@ namespace Avalonia.Win32.Input
_langId = 0;
IsComposing = false;
_compositionCursorPosition = null;
}
//Dependant on CurrentThread. When Avalonia will support Multiple Dispatchers -
@ -118,6 +120,8 @@ namespace Avalonia.Win32.Input
public void Reset()
{
_compositionCursorPosition = null;
Dispatcher.UIThread.Post(() =>
{
var himc = ImmGetContext(Hwnd);
@ -141,6 +145,7 @@ namespace Avalonia.Win32.Input
IsComposing = false;
Composition = null;
_compositionCursorPosition = null;
}
});
}
@ -150,8 +155,9 @@ namespace Avalonia.Win32.Input
if(Client != null)
{
Composition = null;
_compositionCursorPosition = null;
Client.SetPreeditText(null);
Client.SetPreeditText(null, null);
}
Client = client;
@ -266,16 +272,17 @@ namespace Avalonia.Win32.Input
// we're skipping this. not usable on windows
}
public void CompositionChanged(string? composition)
public void CompositionChanged(string? composition, int? cursorPosition)
{
Composition = composition;
_compositionCursorPosition = cursorPosition;
if (!IsActive || !Client.SupportsPreedit)
{
return;
}
Client.SetPreeditText(composition);
Client.SetPreeditText(composition, cursorPosition);
}
public string? GetCompositionString(GCS flag)
@ -290,13 +297,40 @@ namespace Avalonia.Win32.Input
return ImmGetCompositionString(himc, flag);
}
private int? GetCompositionCursorPosition()
{
if (!IsComposing)
{
return null;
}
var himc = ImmGetContext(Hwnd);
if (himc == IntPtr.Zero)
{
return null;
}
try
{
var cursorPosition = ImmGetCompositionString(himc, GCS.GCS_CURSORPOS, IntPtr.Zero, 0);
return cursorPosition >= 0 ? cursorPosition : null;
}
finally
{
ImmReleaseContext(Hwnd, himc);
}
}
public void HandleCompositionStart()
{
Composition = null;
_compositionCursorPosition = null;
if (IsActive)
{
Client.SetPreeditText(null);
Client.SetPreeditText(null, null);
if (Client.SupportsSurroundingText && Client.Selection.Start != Client.Selection.End)
{
@ -325,10 +359,11 @@ namespace Avalonia.Win32.Input
}
Composition = null;
_compositionCursorPosition = null;
if (IsActive)
{
Client.SetPreeditText(null);
Client.SetPreeditText(null, null);
}
}
@ -342,25 +377,27 @@ namespace Avalonia.Win32.Input
}
var flags = (GCS)ToInt32(lParam);
var resultChanged = (flags & GCS.GCS_RESULTSTR) != 0;
if (flags == 0)
{
CompositionChanged("");
CompositionChanged("", null);
}
if ((flags & GCS.GCS_RESULTSTR) != 0)
if (resultChanged)
{
var resultString = GetCompositionString(GCS.GCS_RESULTSTR);
if (_parent != null && !string.IsNullOrEmpty(resultString))
{
Composition = null;
Composition = null;
_compositionCursorPosition = null;
if (IsActive)
{
Client.SetPreeditText(null);
}
if (IsActive)
{
Client.SetPreeditText(null, null);
}
if (_parent != null && !string.IsNullOrEmpty(resultString))
{
var e = new RawTextInputEventArgs(WindowsKeyboardDevice.Instance, timestamp, _parent.Owner, resultString);
if (_parent.Input != null)
@ -372,11 +409,20 @@ namespace Avalonia.Win32.Input
}
}
if ((flags & GCS.GCS_COMPSTR) != 0)
var compositionChanged = (flags & GCS.GCS_COMPSTR) != 0;
var cursorPositionChanged = (flags & GCS.GCS_CURSORPOS) != 0;
if (compositionChanged || (cursorPositionChanged && !resultChanged))
{
var compositionString = GetCompositionString(GCS.GCS_COMPSTR);
var compositionString = compositionChanged
? GetCompositionString(GCS.GCS_COMPSTR)
: Composition;
var cursorPosition = cursorPositionChanged
? GetCompositionCursorPosition()
: _compositionCursorPosition;
CompositionChanged(compositionString);
CompositionChanged(compositionString, cursorPosition);
}
}

Loading…
Cancel
Save