Browse Source

Added PluggableTextInputMethod API

pull/19486/head
Nikita Tsukanov 7 months ago
parent
commit
57ac0cc7fb
  1. 47
      src/Avalonia.Base/Input/TextInput/InputMethodManager.cs
  2. 57
      src/Avalonia.Base/Input/TextInput/PluggableTextInputMethod.cs

47
src/Avalonia.Base/Input/TextInput/InputMethodManager.cs

@ -88,7 +88,7 @@ namespace Avalonia.Input.TextInput
{ {
if (ReferenceEquals(obj.Sender, _focusedElement)) if (ReferenceEquals(obj.Sender, _focusedElement))
{ {
TryFindAndApplyClient(); RediscoverInputMethodAndClient();
} }
} }
@ -132,42 +132,59 @@ namespace Avalonia.Input.TextInput
InputMethod.AddTextInputMethodClientRequeryRequestedHandler(_visualRoot, InputMethod.AddTextInputMethodClientRequeryRequestedHandler(_visualRoot,
TextInputMethodClientRequeryRequested); TextInputMethodClientRequeryRequested);
var inputMethod = ((element as Visual)?.VisualRoot as ITextInputMethodRoot)?.InputMethod; RediscoverInputMethodAndClient();
}
if (_im != inputMethod)
{ void RediscoverInputMethodAndClient()
_im?.SetClient(null); {
} var (inputMethod, inputClient) = FindInputMethodAndClient();
// Reset the previous input method and our state on input method change
if (_im != inputMethod)
Client = null;
_im = inputMethod; _im = inputMethod;
Client = inputClient;
TryFindAndApplyClient();
} }
private void TextInputMethodClientRequeryRequested(object? sender, RoutedEventArgs e) private void TextInputMethodClientRequeryRequested(object? sender, RoutedEventArgs e)
{ {
if (_im != null) if (_im != null)
TryFindAndApplyClient(); RediscoverInputMethodAndClient();
} }
private void TryFindAndApplyClient() private (ITextInputMethodImpl? im, TextInputMethodClient? client) FindInputMethodAndClient()
{ {
if (_focusedElement is not InputElement focused || if (_focusedElement is not InputElement focused ||
_im == null || _im == null ||
!InputMethod.GetIsInputMethodEnabled(focused)) !InputMethod.GetIsInputMethodEnabled(focused))
{ {
Client = null; // Input method system is disabled by focused element
return; return (null, null);
} }
// Attempt to get a user-provided input method
var imQuery = new PluggableTextInputMethodRequestedEventArgs()
{
RoutedEvent = PluggableTextInputMethod.TextInputMethodRequestedEvent
};
_focusedElement.RaiseEvent(imQuery);
// Fall back to the system provided one, if any
var im = imQuery.InputMethod?.Adapter
?? (focused.VisualRoot as ITextInputMethodRoot)?.InputMethod;
if (im == null)
return (null, null);
var clientQuery = new TextInputMethodClientRequestedEventArgs var clientQuery = new TextInputMethodClientRequestedEventArgs
{ {
RoutedEvent = InputElement.TextInputMethodClientRequestedEvent RoutedEvent = InputElement.TextInputMethodClientRequestedEvent
}; };
_focusedElement.RaiseEvent(clientQuery); _focusedElement.RaiseEvent(clientQuery);
Client = clientQuery.Client; return (im, clientQuery.Client);
} }
} }
} }

57
src/Avalonia.Base/Input/TextInput/PluggableTextInputMethod.cs

@ -0,0 +1,57 @@
using Avalonia.Interactivity;
namespace Avalonia.Input.TextInput;
public abstract class PluggableTextInputMethod
{
internal TextInputMethodAdapter Adapter { get; }
public PluggableTextInputMethod()
{
Adapter = new(this);
}
public virtual void SetClient(TextInputMethodClient? client)
{
}
public virtual void SetOptions(TextInputOptions options)
{
}
internal class TextInputMethodAdapter(PluggableTextInputMethod method) : ITextInputMethodImpl
{
public void SetClient(TextInputMethodClient? client)
{
method.SetClient(client);
}
public void SetCursorRect(Rect rect)
{
// No-op
}
public void SetOptions(TextInputOptions options) => method.SetOptions(options);
public void Reset()
{
// Implementations should be subscribing to reset event manually
}
}
/// <summary>
/// Defines the <see cref="TextInputMethodRequestedEvent"/> event.
/// </summary>
public static readonly RoutedEvent<TextInputMethodClientRequestedEventArgs> TextInputMethodRequestedEvent =
RoutedEvent.Register<InputElement, TextInputMethodClientRequestedEventArgs>(
nameof(PluggableTextInputMethodRequestedEventArgs),
RoutingStrategies.Tunnel | RoutingStrategies.Bubble);
}
public class PluggableTextInputMethodRequestedEventArgs : RoutedEventArgs
{
/// <summary>
/// Set this property to a valid pluggable text input method to enable its usage with the input system
/// </summary>
public PluggableTextInputMethod? InputMethod { get; set; }
}
Loading…
Cancel
Save