committed by
GitHub
25 changed files with 587 additions and 128 deletions
@ -0,0 +1,46 @@ |
|||
//
|
|||
// AvnTextInputMethod.h
|
|||
// Avalonia.Native.OSX
|
|||
//
|
|||
// Created by Benedikt Stebner on 22.11.22.
|
|||
// Copyright © 2022 Avalonia. All rights reserved.
|
|||
//
|
|||
|
|||
#ifndef AvnTextInputMethod_h |
|||
#define AvnTextInputMethod_h |
|||
|
|||
#import <Foundation/Foundation.h> |
|||
|
|||
#include "com.h" |
|||
#include "comimpl.h" |
|||
#include "avalonia-native.h" |
|||
#import "AvnTextInputMethodDelegate.h" |
|||
|
|||
class AvnTextInputMethod: public virtual ComObject, public virtual IAvnTextInputMethod{ |
|||
private: |
|||
id<AvnTextInputMethodDelegate> _inputMethodDelegate; |
|||
public: |
|||
FORWARD_IUNKNOWN() |
|||
|
|||
BEGIN_INTERFACE_MAP() |
|||
INTERFACE_MAP_ENTRY(IAvnTextInputMethod, IID_IAvnTextInputMethod) |
|||
END_INTERFACE_MAP() |
|||
|
|||
virtual ~AvnTextInputMethod(); |
|||
|
|||
AvnTextInputMethod(id<AvnTextInputMethodDelegate> inputMethodDelegate); |
|||
|
|||
bool IsActive (); |
|||
|
|||
HRESULT SetClient (IAvnTextInputMethodClient* client) override; |
|||
|
|||
virtual void Reset () override; |
|||
|
|||
virtual void SetCursorRect (AvnRect rect) override; |
|||
|
|||
virtual void SetSurroundingText (char* text, int anchorOffset, int cursorOffset) override; |
|||
|
|||
public: |
|||
ComPtr<IAvnTextInputMethodClient> Client; |
|||
}; |
|||
#endif /* AvnTextInputMethod_h */ |
|||
@ -0,0 +1,41 @@ |
|||
// |
|||
// AvnTextInputMethod.mm |
|||
// Avalonia.Native.OSX |
|||
// |
|||
// Created by Benedikt Stebner on 23.11.22. |
|||
// Copyright © 2022 Avalonia. All rights reserved. |
|||
// |
|||
|
|||
#include "AvnTextInputMethod.h" |
|||
|
|||
AvnTextInputMethod::~AvnTextInputMethod() { |
|||
Client = nullptr; |
|||
} |
|||
|
|||
AvnTextInputMethod::AvnTextInputMethod(id<AvnTextInputMethodDelegate> inputMethodDelegate) { |
|||
_inputMethodDelegate = inputMethodDelegate; |
|||
} |
|||
|
|||
bool AvnTextInputMethod::IsActive() { |
|||
return Client != nullptr; |
|||
} |
|||
|
|||
HRESULT AvnTextInputMethod::SetClient(IAvnTextInputMethodClient *client) { |
|||
START_COM_CALL; |
|||
|
|||
Client = client; |
|||
|
|||
return S_OK; |
|||
} |
|||
|
|||
void AvnTextInputMethod::Reset() { |
|||
} |
|||
|
|||
void AvnTextInputMethod::SetSurroundingText(char* text, int anchorOffset, int cursorOffset) { |
|||
[_inputMethodDelegate setText:[NSString stringWithUTF8String:text]]; |
|||
[_inputMethodDelegate setSelection: anchorOffset : cursorOffset]; |
|||
} |
|||
|
|||
void AvnTextInputMethod::SetCursorRect(AvnRect rect) { |
|||
[_inputMethodDelegate setCursorRect: rect]; |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
//
|
|||
// AvnTextInputMethodHost.h
|
|||
// Avalonia.Native.OSX
|
|||
//
|
|||
// Created by Benedikt Stebner on 24.11.22.
|
|||
// Copyright © 2022 Avalonia. All rights reserved.
|
|||
//
|
|||
|
|||
#ifndef AvnTextInputMethodHost_h |
|||
#define AvnTextInputMethodHost_h |
|||
|
|||
@protocol AvnTextInputMethodDelegate |
|||
@required |
|||
-(void) setText:(NSString* _Nonnull) text; |
|||
-(void) setCursorRect:(AvnRect) cursorRect; |
|||
-(void) setSelection: (int) start : (int) end; |
|||
|
|||
@end |
|||
|
|||
#endif /* AvnTextInputMethodHost_h */ |
|||
@ -0,0 +1,118 @@ |
|||
using System; |
|||
using Avalonia.Input.TextInput; |
|||
using Avalonia.Native.Interop; |
|||
|
|||
namespace Avalonia.Native |
|||
{ |
|||
internal class AvaloniaNativeTextInputMethod : ITextInputMethodImpl, IDisposable |
|||
{ |
|||
private ITextInputMethodClient _client; |
|||
private IAvnTextInputMethodClient _nativeClient; |
|||
private readonly IAvnTextInputMethod _inputMethod; |
|||
|
|||
public AvaloniaNativeTextInputMethod(IAvnWindowBase nativeWindow) |
|||
{ |
|||
_inputMethod = nativeWindow.InputMethod; |
|||
} |
|||
|
|||
public void Dispose() |
|||
{ |
|||
_inputMethod.Dispose(); |
|||
_nativeClient?.Dispose(); |
|||
} |
|||
|
|||
public void Reset() |
|||
{ |
|||
_inputMethod.Reset(); |
|||
} |
|||
|
|||
public void SetClient(ITextInputMethodClient client) |
|||
{ |
|||
if (_client is { SupportsSurroundingText: true }) |
|||
{ |
|||
_client.SurroundingTextChanged -= OnSurroundingTextChanged; |
|||
_client.CursorRectangleChanged -= OnCursorRectangleChanged; |
|||
|
|||
_nativeClient?.Dispose(); |
|||
} |
|||
|
|||
_nativeClient = null; |
|||
_client = client; |
|||
|
|||
if (client != null) |
|||
{ |
|||
_nativeClient = new AvnTextInputMethodClient(client); |
|||
|
|||
OnSurroundingTextChanged(this, EventArgs.Empty); |
|||
OnCursorRectangleChanged(this, EventArgs.Empty); |
|||
|
|||
_client.SurroundingTextChanged += OnSurroundingTextChanged; |
|||
_client.CursorRectangleChanged += OnCursorRectangleChanged; |
|||
} |
|||
|
|||
_inputMethod.SetClient(_nativeClient); |
|||
} |
|||
|
|||
private void OnCursorRectangleChanged(object sender, EventArgs e) |
|||
{ |
|||
if (_client == null) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
_inputMethod.SetCursorRect(_client.CursorRectangle.ToAvnRect()); |
|||
} |
|||
|
|||
private void OnSurroundingTextChanged(object sender, EventArgs e) |
|||
{ |
|||
if (_client == null) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
var surroundingText = _client.SurroundingText; |
|||
|
|||
_inputMethod.SetSurroundingText( |
|||
surroundingText.Text, |
|||
surroundingText.AnchorOffset, |
|||
surroundingText.CursorOffset |
|||
); |
|||
} |
|||
|
|||
public void SetCursorRect(Rect rect) |
|||
{ |
|||
_inputMethod.SetCursorRect(rect.ToAvnRect()); |
|||
} |
|||
|
|||
public void SetOptions(TextInputOptions options) |
|||
{ |
|||
|
|||
} |
|||
|
|||
private class AvnTextInputMethodClient : NativeCallbackBase, IAvnTextInputMethodClient |
|||
{ |
|||
private readonly ITextInputMethodClient _client; |
|||
|
|||
public AvnTextInputMethodClient(ITextInputMethodClient client) |
|||
{ |
|||
_client = client; |
|||
} |
|||
|
|||
public void SetPreeditText(string preeditText) |
|||
{ |
|||
if (_client.SupportsPreedit) |
|||
{ |
|||
_client.SetPreeditText(preeditText); |
|||
} |
|||
} |
|||
|
|||
public void SelectInSurroundingText(int start, int end) |
|||
{ |
|||
if (_client.SupportsSurroundingText) |
|||
{ |
|||
_client.SelectInSurroundingText(start, end); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
{ |
|||
"profiles": { |
|||
"Avalonia.Benchmarks": { |
|||
"commandName": "Project" |
|||
}, |
|||
"Avalonia.Benchmarks (in-process)": { |
|||
"commandName": "Project", |
|||
"commandLineArgs": "--inprocess" |
|||
}, |
|||
"Avalonia.Benchmarks (debug)": { |
|||
"commandName": "Project", |
|||
"commandLineArgs": "--debug" |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue