|
|
|
@ -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); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|