Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RDY] win32 ime #6223

Closed
wants to merge 14 commits into from
34 changes: 5 additions & 29 deletions Avalonia.sln
Original file line number Diff line number Diff line change
Expand Up @@ -224,11 +224,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Markup.Xaml.Loader
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sandbox", "samples\Sandbox\Sandbox.csproj", "{11BE52AF-E2DD-4CF0-B19A-05285ACAF571}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MicroComGenerator", "src\tools\MicroComGenerator\MicroComGenerator.csproj", "{AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MicroComGenerator", "src\tools\MicroComGenerator\MicroComGenerator.csproj", "{AEC9031E-06EA-4A9E-9E7F-7D7C719404DD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.MicroCom", "src\Avalonia.MicroCom\Avalonia.MicroCom.csproj", "{FE2F3E5E-1E34-4972-8DC1-5C2C588E5ECE}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.MicroCom", "src\Avalonia.MicroCom\Avalonia.MicroCom.csproj", "{FE2F3E5E-1E34-4972-8DC1-5C2C588E5ECE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MiniMvvm", "samples\MiniMvvm\MiniMvvm.csproj", "{BC594FD5-4AF2-409E-A1E6-04123F54D7C5}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MiniMvvm", "samples\MiniMvvm\MiniMvvm.csproj", "{BC594FD5-4AF2-409E-A1E6-04123F54D7C5}"
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
Expand Down Expand Up @@ -326,8 +326,8 @@ Global
{42472427-4774-4C81-8AFF-9F27B8E31721}.Release|iPhone.Build.0 = Release|Any CPU
{42472427-4774-4C81-8AFF-9F27B8E31721}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{42472427-4774-4C81-8AFF-9F27B8E31721}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{811A76CF-1CF6-440F-963B-BBE31BD72A82}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
{811A76CF-1CF6-440F-963B-BBE31BD72A82}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
{811A76CF-1CF6-440F-963B-BBE31BD72A82}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
{811A76CF-1CF6-440F-963B-BBE31BD72A82}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
{811A76CF-1CF6-440F-963B-BBE31BD72A82}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
{811A76CF-1CF6-440F-963B-BBE31BD72A82}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
{811A76CF-1CF6-440F-963B-BBE31BD72A82}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
Expand Down Expand Up @@ -2020,30 +2020,6 @@ Global
{909A8CBD-7D0E-42FD-B841-022AD8925820}.Release|iPhone.Build.0 = Release|Any CPU
{909A8CBD-7D0E-42FD-B841-022AD8925820}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{909A8CBD-7D0E-42FD-B841-022AD8925820}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.AppStore|Any CPU.Build.0 = Debug|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.AppStore|iPhone.Build.0 = Debug|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.Debug|iPhone.Build.0 = Debug|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.Release|Any CPU.Build.0 = Release|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.Release|iPhone.ActiveCfg = Release|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.Release|iPhone.Build.0 = Release|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{28F18757-C3E6-4BBE-A37D-11BA2AB9177C}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{11BE52AF-E2DD-4CF0-B19A-05285ACAF571}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
{11BE52AF-E2DD-4CF0-B19A-05285ACAF571}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
{11BE52AF-E2DD-4CF0-B19A-05285ACAF571}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
Expand Down
9 changes: 6 additions & 3 deletions src/Avalonia.Controls/ApiCompatBaseline.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@ MembersMustExist : Member 'public Avalonia.AvaloniaProperty<Avalonia.Media.Stret
MembersMustExist : Member 'public void Avalonia.Controls.Embedding.Offscreen.OffscreenTopLevelImplBase.SetCursor(Avalonia.Platform.IPlatformHandle)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public Avalonia.AvaloniaProperty Avalonia.AvaloniaProperty Avalonia.Controls.Notifications.NotificationCard.CloseOnClickProperty' does not exist in the implementation but it does exist in the contract.
EnumValuesMustMatch : Enum value 'Avalonia.Platform.ExtendClientAreaChromeHints Avalonia.Platform.ExtendClientAreaChromeHints.Default' is (System.Int32)2 in the implementation but (System.Int32)1 in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public System.Nullable<Avalonia.Size> Avalonia.Platform.ITopLevelImpl.FrameSize' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public System.Action Avalonia.Platform.ITopLevelImpl.InputMethodUpdated' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public System.Nullable<Avalonia.Size> Avalonia.Platform.ITopLevelImpl.FrameSize.get()' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public System.Action Avalonia.Platform.ITopLevelImpl.InputMethodUpdated.get()' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Platform.ITopLevelImpl.InputMethodUpdated.set(System.Action)' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Platform.ITopLevelImpl.SetCursor(Avalonia.Platform.ICursorImpl)' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Platform.ITopLevelImpl.SetCursor(Avalonia.Platform.IPlatformHandle)' is present in the contract but not in the implementation.
MembersMustExist : Member 'public void Avalonia.Platform.ITopLevelImpl.SetCursor(Avalonia.Platform.IPlatformHandle)' does not exist in the implementation but it does exist in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public System.Nullable<Avalonia.Size> Avalonia.Platform.ITopLevelImpl.FrameSize' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public System.Nullable<Avalonia.Size> Avalonia.Platform.ITopLevelImpl.FrameSize.get()' is present in the implementation but not in the contract.
Total Issues: 15
Total Issues: 18
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ public virtual void SetCursor(ICursorImpl cursor)
public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) { }

public WindowTransparencyLevel TransparencyLevel { get; private set; }
public Action InputMethodUpdated { get; set; }

public IPopupImpl CreatePopup() => null;
}
Expand Down
6 changes: 6 additions & 0 deletions src/Avalonia.Controls/Platform/ITopLevelImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,5 +137,11 @@ public interface ITopLevelImpl : IDisposable
/// Gets the <see cref="AcrylicPlatformCompensationLevels"/> for the platform.
/// </summary>
AcrylicPlatformCompensationLevels AcrylicCompensationLevels { get; }


/// <summary>
/// Called when the input method is changed for the current top level object.
/// </summary>
Action InputMethodUpdated { get; set; }
}
}
2 changes: 2 additions & 0 deletions src/Avalonia.Controls/TextBoxTextInputMethodClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ internal class TextBoxTextInputMethodClient : ITextInputMethodClient
public event EventHandler TextViewVisualChanged;
public bool SupportsPreedit => false;
public void SetPreeditText(string text) => throw new NotSupportedException();
public event EventHandler ActiveStateChanged;
public bool ActiveState => true;
yatli marked this conversation as resolved.
Show resolved Hide resolved

public bool SupportsSurroundingText => false;
public TextInputMethodSurroundingText SurroundingText => throw new NotSupportedException();
Expand Down
6 changes: 6 additions & 0 deletions src/Avalonia.Controls/TopLevel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ public TopLevel(ITopLevelImpl impl, IAvaloniaDependencyResolver dependencyResolv
impl.Resized = HandleResized;
impl.ScalingChanged = HandleScalingChanged;
impl.TransparencyLevelChanged = HandleTransparencyLevelChanged;
impl.InputMethodUpdated = HandleInputMethodUpdated;

_keyboardNavigationHandler?.SetOwner(this);
_accessKeyHandler?.SetOwner(this);
Expand Down Expand Up @@ -186,6 +187,11 @@ public TopLevel(ITopLevelImpl impl, IAvaloniaDependencyResolver dependencyResolv
impl.LostFocus += PlatformImpl_LostFocus;
}

private void HandleInputMethodUpdated()
{
KeyboardDevice.Instance.NotifyInputMethodUpdated(this);
}

/// <summary>
/// Fired when the window is opened.
/// </summary>
Expand Down
1 change: 1 addition & 0 deletions src/Avalonia.DesignerSupport/Remote/Stubs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ public void SetWindowManagerAddShadowHint(bool enabled)
public bool NeedsManagedDecorations => false;

public AcrylicPlatformCompensationLevels AcrylicCompensationLevels { get; } = new AcrylicPlatformCompensationLevels(1, 1, 1);
public Action InputMethodUpdated { get; set; }
}

class ClipboardStub : IClipboard
Expand Down
2 changes: 2 additions & 0 deletions src/Avalonia.Headless/HeadlessWindowImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -341,5 +341,7 @@ public void SetExtendClientAreaTitleBarHeightHint(double titleBarHeight)
{

}

public Action InputMethodUpdated { get; set; }
}
}
8 changes: 7 additions & 1 deletion src/Avalonia.Input/ApiCompatBaseline.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,17 @@ MembersMustExist : Member 'public Avalonia.Platform.IPlatformHandle Avalonia.Inp
MembersMustExist : Member 'public Avalonia.Interactivity.RoutedEvent<Avalonia.Interactivity.RoutedEventArgs> Avalonia.Interactivity.RoutedEvent<Avalonia.Interactivity.RoutedEventArgs> Avalonia.Input.Gestures.DoubleTappedEvent' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public Avalonia.Interactivity.RoutedEvent<Avalonia.Interactivity.RoutedEventArgs> Avalonia.Interactivity.RoutedEvent<Avalonia.Interactivity.RoutedEventArgs> Avalonia.Input.Gestures.RightTappedEvent' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public Avalonia.Interactivity.RoutedEvent<Avalonia.Interactivity.RoutedEventArgs> Avalonia.Interactivity.RoutedEvent<Avalonia.Interactivity.RoutedEventArgs> Avalonia.Input.Gestures.TappedEvent' does not exist in the implementation but it does exist in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Input.IKeyboardDevice.NotifyInputMethodUpdated(Avalonia.Input.TextInput.ITextInputMethodRoot)' is present in the implementation but not in the contract.
MembersMustExist : Member 'public Avalonia.Interactivity.RoutedEvent<Avalonia.Interactivity.RoutedEventArgs> Avalonia.Interactivity.RoutedEvent<Avalonia.Interactivity.RoutedEventArgs> Avalonia.Input.InputElement.DoubleTappedEvent' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public Avalonia.Interactivity.RoutedEvent<Avalonia.Interactivity.RoutedEventArgs> Avalonia.Interactivity.RoutedEvent<Avalonia.Interactivity.RoutedEventArgs> Avalonia.Input.InputElement.TappedEvent' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public void Avalonia.Input.InputElement.add_DoubleTapped(System.EventHandler<Avalonia.Interactivity.RoutedEventArgs>)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public void Avalonia.Input.InputElement.add_Tapped(System.EventHandler<Avalonia.Interactivity.RoutedEventArgs>)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public void Avalonia.Input.InputElement.remove_DoubleTapped(System.EventHandler<Avalonia.Interactivity.RoutedEventArgs>)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public void Avalonia.Input.InputElement.remove_Tapped(System.EventHandler<Avalonia.Interactivity.RoutedEventArgs>)' does not exist in the implementation but it does exist in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public System.Boolean Avalonia.Input.TextInput.ITextInputMethodClient.ActiveState' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public System.EventHandler Avalonia.Input.TextInput.ITextInputMethodClient.ActiveStateChanged' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public System.Boolean Avalonia.Input.TextInput.ITextInputMethodClient.ActiveState.get()' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Input.TextInput.ITextInputMethodClient.add_ActiveStateChanged(System.EventHandler)' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Input.TextInput.ITextInputMethodClient.remove_ActiveStateChanged(System.EventHandler)' is present in the implementation but not in the contract.
TypesMustExist : Type 'Avalonia.Platform.IStandardCursorFactory' does not exist in the implementation but it does exist in the contract.
Total Issues: 11
Total Issues: 17
2 changes: 2 additions & 0 deletions src/Avalonia.Input/IKeyboardDevice.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,5 +64,7 @@ void SetFocusedElement(
IInputElement? element,
NavigationMethod method,
KeyModifiers modifiers);

void NotifyInputMethodUpdated(TextInput.ITextInputMethodRoot? root);
}
}
5 changes: 5 additions & 0 deletions src/Avalonia.Input/KeyboardDevice.cs
Original file line number Diff line number Diff line change
Expand Up @@ -265,5 +265,10 @@ public void ProcessRawEvent(RawInputEventArgs e)
e.Handled = ev.Handled;
}
}

public void NotifyInputMethodUpdated(ITextInputMethodRoot? root)
{
_textInputManager.NotifyInputMethodUpdated(root);
}
}
}
8 changes: 8 additions & 0 deletions src/Avalonia.Input/TextInput/ITextInputMethodClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,14 @@ public interface ITextInputMethodClient
/// Returns the text before the cursor. Must return a non-empty string if cursor is not at the end of the text entry
/// </summary>
string TextAfterCursor { get; }
/// <summary>
/// Should be fired when the client requests IME active state change.
/// </summary>
event EventHandler ActiveStateChanged;
/// <summary>
/// Indicates whether the client requests active IME support.
/// </summary>
bool ActiveState { get; }
}

public struct TextInputMethodSurroundingText
Expand Down
41 changes: 30 additions & 11 deletions src/Avalonia.Input/TextInput/InputMethodManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ internal class TextInputMethodManager
private ITextInputMethodImpl? _im;
private IInputElement? _focusedElement;
private ITextInputMethodClient? _client;
private bool _clientActive = false;
private readonly TransformTrackingHelper _transformTracker = new TransformTrackingHelper();

public TextInputMethodManager() => _transformTracker.MatrixChanged += UpdateCursorRect;
Expand All @@ -23,6 +24,8 @@ private ITextInputMethodClient? Client
{
_client.CursorRectangleChanged -= OnCursorRectangleChanged;
_client.TextViewVisualChanged -= OnTextViewVisualChanged;
_client.ActiveStateChanged -= OnClientActiveStateChanged;
_clientActive = false;
}

_client = value;
Expand All @@ -31,6 +34,8 @@ private ITextInputMethodClient? Client
{
_client.CursorRectangleChanged += OnCursorRectangleChanged;
_client.TextViewVisualChanged += OnTextViewVisualChanged;
_client.ActiveStateChanged += OnClientActiveStateChanged;
_clientActive = _client.ActiveState;
var optionsQuery = new TextInputOptionsQueryEventArgs
{
RoutedEvent = InputElement.TextInputOptionsQueryEvent
Expand All @@ -40,7 +45,7 @@ private ITextInputMethodClient? Client
_im?.SetOptions(optionsQuery);
_transformTracker?.SetVisual(_client?.TextViewVisual);
UpdateCursorRect();
_im?.SetActive(true);
_im?.SetActive(_clientActive);
}
else
{
Expand All @@ -50,6 +55,15 @@ private ITextInputMethodClient? Client
}
}

private void OnClientActiveStateChanged(object sender, EventArgs e)
{
if (_client != null && sender == _client && _client.ActiveState != _clientActive)
{
_clientActive = _client.ActiveState;
_im?.SetActive(_clientActive);
}
}

private void OnTextViewVisualChanged(object sender, EventArgs e)
=> _transformTracker.SetVisual(_client?.TextViewVisual);

Expand All @@ -75,27 +89,32 @@ public void SetFocusedElement(IInputElement? element)
if(_focusedElement == element)
return;
_focusedElement = element;

var inputMethod = (element?.VisualRoot as ITextInputMethodRoot)?.InputMethod;

var root = element?.VisualRoot as ITextInputMethodRoot;

NotifyInputMethodUpdated(root);
}

public void NotifyInputMethodUpdated(ITextInputMethodRoot? root)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why exactly do we need this? Is it needed to handle keyboard layout switch between basic and IME-enabled languages?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if that should be handled on the xplat layer though. I'd expect that state to be tracked by the platform code that encapsulates such switches.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure how other users do this, but for me I heavily rely on win+space to switch between en/zh on the fly.
The ime manager queries client capabilities when it gets focus (or init?), but doesn't handle IME switch when the control is focused.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I'd expect the WindowImpl.cs to always have an active Imm32InputMethod instance (just like X11Window does) that maintains its state rather than going through the requery process. Your approach also adds more ties between input method handling and toplevels while we are kinda planning to add built-in OSK support.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WindowImpl always have that. InputMethodManager doesn't.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The initial idea was that InputMethodManager synchronizes the control with the native window implementation. The native window implementation is supposed to keep track of what was previously passed to it rather than requery that information on demand.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. Maybe it's possible to put the mutable states in IMM32InputMethod.

{
// TODO how to filter the window with the current focused element?
yatli marked this conversation as resolved.
Show resolved Hide resolved
var inputMethod = root?.InputMethod;
if(_im != inputMethod)
_im?.SetActive(false);

_im = inputMethod;

if (_focusedElement == null || _im == null)
{
Client = null;
_im?.SetActive(false);
return;
}

var clientQuery = new TextInputMethodClientRequestedEventArgs
{
RoutedEvent = InputElement.TextInputMethodClientRequestedEvent
};

_focusedElement.RaiseEvent(clientQuery);
_focusedElement?.RaiseEvent(clientQuery);
Client = clientQuery.Client;
if (Client == null)
{
_im?.SetActive(false);
}
}
}
}
2 changes: 2 additions & 0 deletions src/Avalonia.Native/WindowImplBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -478,5 +478,7 @@ public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel)
public AcrylicPlatformCompensationLevels AcrylicCompensationLevels { get; } = new AcrylicPlatformCompensationLevels(1, 0, 0);

public IPlatformHandle Handle { get; private set; }

public Action InputMethodUpdated { get; set; }
}
}
2 changes: 2 additions & 0 deletions src/Avalonia.X11/X11Window.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1158,5 +1158,7 @@ public void SetWindowManagerAddShadowHint(bool enabled)
public AcrylicPlatformCompensationLevels AcrylicCompensationLevels { get; } = new AcrylicPlatformCompensationLevels(1, 0.8, 0.8);

public bool NeedsManagedDecorations => false;

public Action InputMethodUpdated { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -84,5 +84,7 @@ public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel)
public WindowTransparencyLevel TransparencyLevel { get; private set; }

public AcrylicPlatformCompensationLevels AcrylicCompensationLevels { get; } = new AcrylicPlatformCompensationLevels(1, 1, 1);

public Action InputMethodUpdated { get; set; }
}
}
Loading