Browse Source

Android preedit

Benedikt Stebner 3 years ago
parent
commit
ab6df8c9ed

+ 18 - 4
src/Android/Avalonia.Android/AndroidInputMethod.cs

@@ -1,10 +1,14 @@
 using System;
 using Android.Content;
+using Android.OS;
 using Android.Runtime;
+using Android.Text;
 using Android.Views;
 using Android.Views.InputMethods;
+using Avalonia.Android.Platform.SkiaPlatform;
 using Avalonia.Input;
 using Avalonia.Input.TextInput;
+using Java.Lang;
 
 namespace Avalonia.Android
 {
@@ -13,6 +17,8 @@ namespace Avalonia.Android
     {
         private readonly TView _host;
         private readonly InputMethodManager _imm;
+        private ITextInputMethodClient _client;
+        private InputConnectionImpl _inputConnection;
 
         public AndroidInputMethod(TView host)
         {
@@ -27,6 +33,10 @@ namespace Avalonia.Android
             _host.ViewTreeObserver.AddOnGlobalLayoutListener(new SoftKeyboardListener(_host));
         }
 
+        public bool IsActive => Client != null;
+
+        public ITextInputMethodClient Client => _client;
+
         public void Reset()
         {
             _imm.RestartInput(_host);
@@ -34,16 +44,16 @@ namespace Avalonia.Android
 
         public void SetClient(ITextInputMethodClient client)
         {
-            var active = client is { };
+            _client = client;
             
-            if (active)
+            if (IsActive)
             {
                 _host.RequestFocus();
                 Reset();
                 _imm.ShowSoftInput(_host, ShowFlags.Implicit);
             }
             else
-                _imm.HideSoftInputFromWindow(_host.WindowToken, HideSoftInputFlags.None);
+                _imm.HideSoftInputFromWindow(_host.WindowToken, HideSoftInputFlags.None);         
         }
 
         public void SetCursorRect(Rect rect)
@@ -52,7 +62,9 @@ namespace Avalonia.Android
 
         public void SetOptions(TextInputOptions options)
         {
-            _host.InitEditorInfo((outAttrs) =>
+            _inputConnection = new InputConnectionImpl(_host, this);
+
+            _host.InitEditorInfo((_host, outAttrs) =>
             {
                 outAttrs.InputType = options.ContentType switch
                 {
@@ -74,6 +86,8 @@ namespace Avalonia.Android
                     outAttrs.InputType |= global::Android.Text.InputTypes.TextFlagMultiLine;
 
                 outAttrs.ImeOptions |= ImeFlags.NoFullscreen | ImeFlags.NoExtractUi;
+
+                return _inputConnection;
             });
         }
 

+ 3 - 1
src/Android/Avalonia.Android/IInitEditorInfo.cs

@@ -1,12 +1,14 @@
 using System;
 using System.Collections.Generic;
 using System.Text;
+using Android.Views;
 using Android.Views.InputMethods;
+using Avalonia.Android.Platform.SkiaPlatform;
 
 namespace Avalonia.Android
 {
     interface IInitEditorInfo
     {
-        void InitEditorInfo(Action<EditorInfo> init);
+        void InitEditorInfo(Func<View, EditorInfo, InputConnectionImpl> init);
     }
 }

+ 49 - 7
src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs

@@ -3,6 +3,9 @@ using System.Collections.Generic;
 
 using Android.Content;
 using Android.Graphics;
+using Android.Media.TV;
+using Android.OS;
+using Android.Runtime;
 using Android.Views;
 using Android.Views.InputMethods;
 using Avalonia.Android.OpenGL;
@@ -21,6 +24,7 @@ using Avalonia.Platform;
 using Avalonia.Platform.Storage;
 using Avalonia.Rendering;
 using Avalonia.Rendering.Composition;
+using Java.Lang;
 
 namespace Avalonia.Android.Platform.SkiaPlatform
 {
@@ -148,7 +152,8 @@ namespace Avalonia.Android.Platform.SkiaPlatform
         {
             private readonly TopLevelImpl _tl;
             private Size _oldSize;
-            public ViewImpl(Context context,  TopLevelImpl tl, bool placeOnTop) : base(context)
+
+            public ViewImpl(Context context, TopLevelImpl tl, bool placeOnTop) : base(context)
             {
                 _tl = tl;
                 if (placeOnTop)
@@ -187,7 +192,6 @@ namespace Avalonia.Android.Platform.SkiaPlatform
                 return res != null ? res.Value : baseResult;
             }
 
-
             void ISurfaceHolderCallback.SurfaceChanged(ISurfaceHolder holder, Format format, int width, int height)
             {
                 var newSize = new PixelSize(width, height).ToSize(_tl.RenderScaling);
@@ -206,9 +210,10 @@ namespace Avalonia.Android.Platform.SkiaPlatform
                 return true;
             }
 
-            private Action<EditorInfo> _initEditorInfo;
+            private Func<View, EditorInfo, InputConnectionImpl> _initEditorInfo;
+            protected InputConnectionImpl _inputConnection;
 
-            public void InitEditorInfo(Action<EditorInfo> init)
+            public void InitEditorInfo(Func<View, EditorInfo, InputConnectionImpl> init)
             {
                 _initEditorInfo = init;
             }
@@ -216,9 +221,11 @@ namespace Avalonia.Android.Platform.SkiaPlatform
             public sealed override IInputConnection OnCreateInputConnection(EditorInfo outAttrs)
             {
                 if (_initEditorInfo != null)
-                    _initEditorInfo(outAttrs);
-
-                return base.OnCreateInputConnection(outAttrs);
+                {
+                    return _initEditorInfo(this, outAttrs);
+                }
+                   
+                return null;
             }
 
         }
@@ -249,4 +256,39 @@ namespace Avalonia.Android.Platform.SkiaPlatform
             throw new NotImplementedException();
         }
     }
+
+    internal class InputConnectionImpl: BaseInputConnection
+    {
+        private readonly ITextInputMethodImpl _inputMethod;
+
+        public InputConnectionImpl(View? targetView, ITextInputMethodImpl inputMethod) :
+            base(targetView, false)
+        {
+            _inputMethod = inputMethod;
+        }
+
+        public InputConnectionImpl(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
+        {
+        }
+
+        public override bool SetComposingText(ICharSequence text, int newCursorPosition)
+        {
+            if (_inputMethod.IsActive)
+            {
+                _inputMethod.Client.SetPreeditText(text.ToString());
+            }
+
+            return base.SetComposingText(text, newCursorPosition);
+        }
+
+        public override bool CommitText(ICharSequence text, int newCursorPosition)
+        {
+            if (_inputMethod.IsActive)
+            {
+                _inputMethod.Client.SetPreeditText(null);
+            }
+
+            return base.CommitText(text, newCursorPosition);
+        }
+    }
 }

+ 4 - 0
src/Avalonia.Base/Input/TextInput/ITextInputMethodImpl.cs

@@ -5,6 +5,10 @@ namespace Avalonia.Input.TextInput
     [Unstable]
     public interface ITextInputMethodImpl
     {
+        ITextInputMethodClient Client { get; }
+
+        bool IsActive { get; }
+
         void SetClient(ITextInputMethodClient? client);
         void SetCursorRect(Rect rect);
         void SetOptions(TextInputOptions options);

+ 1 - 1
src/Avalonia.Base/Media/FontFamily.cs

@@ -128,7 +128,7 @@ namespace Avalonia.Media
 
                 default:
                     {
-                        throw new ArgumentException("Specified family is not supported.");
+                        return new FontFamilyIdentifier(name, null);
                     }
             }
         }