committed by
GitHub
25 changed files with 619 additions and 145 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