From 27b9ebc1cbbfacc00f369d0c33800dcd33e21269 Mon Sep 17 00:00:00 2001 From: CodezTree Date: Thu, 11 Dec 2025 04:07:34 +0900 Subject: [PATCH 1/2] fix: calculating corners fix on canvas mode :: screen space - camera --- Runtime/MobileInputField.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Runtime/MobileInputField.cs b/Runtime/MobileInputField.cs index b5cf747..e713e72 100644 --- a/Runtime/MobileInputField.cs +++ b/Runtime/MobileInputField.cs @@ -473,8 +473,11 @@ Rect GetScreenRectFromRectTransform(RectTransform rect) { var yMax = float.NegativeInfinity; for (var i = 0; i < 4; i++) { Vector3 coords; - if (rect.GetComponentInParent().renderMode == RenderMode.ScreenSpaceOverlay) { + var canvas = rect.GetComponentInParent(); + if (canvas.renderMode == RenderMode.ScreenSpaceOverlay) { coords = corners[i]; + } else if (canvas.renderMode == RenderMode.ScreenSpaceCamera) { + coords = canvas.worldCamera.WorldToScreenPoint (corners[i]); } else { coords = RectTransformUtility.WorldToScreenPoint(Camera.main, corners[i]); } From 03d120bd2c46cf45febd8bd3f78acfe7c450cee5 Mon Sep 17 00:00:00 2001 From: CodezTree Date: Tue, 28 Jul 2026 22:27:12 +0900 Subject: [PATCH 2/2] fix: stabilize native input lifecycle --- .../java/com/mopsicus/umi/MobileInput.java | 15 +- CHANGELOG.md | 6 +- Plugins/Android/Mobileinput.aar | Bin 24129 -> 24253 bytes Plugins/iOS/MobileInput.mm | 19 +- Runtime/MobileInput.cs | 73 ++++- Runtime/MobileInputField.cs | 273 +++++++++++++----- package.json | 4 +- 7 files changed, 312 insertions(+), 78 deletions(-) diff --git a/Android~/plugin/src/main/java/com/mopsicus/umi/MobileInput.java b/Android~/plugin/src/main/java/com/mopsicus/umi/MobileInput.java index 96e9c26..22fcfad 100644 --- a/Android~/plugin/src/main/java/com/mopsicus/umi/MobileInput.java +++ b/Android~/plugin/src/main/java/com/mopsicus/umi/MobileInput.java @@ -124,13 +124,21 @@ public static void processMessage(int id, final String data) { JSONObject json = new JSONObject(data); String msg = json.getString("msg"); if (msg.equals(CREATE)) { + if (mobileInputList.get(id) != null) { + return; + } MobileInput input = new MobileInput(Plugin.layout); - input.Create(id, json); mobileInputList.append(id, input); + input.Create(id, json); } else { MobileInput input = mobileInputList.get(id); if (input != null) { - input.processData(json); + if (msg.equals(REMOVE)) { + input.Remove(); + mobileInputList.remove(id); + } else { + input.processData(json); + } } } } catch (JSONException e) { @@ -306,6 +314,7 @@ private void Create(int id, JSONObject data) { String alignment = data.getString("align"); String customFont = data.getString("font"); boolean multiline = data.getBoolean("multiline"); + boolean isVisible = data.optBoolean("is_visible", true); caretColor = Color.argb(caretColor_a, caretColor_r, caretColor_g, caretColor_b); isCaretChange = data.getBoolean("caret_color"); edit = new EditText(Plugin.activity.getApplicationContext()); @@ -508,6 +517,8 @@ public void onTextChanged(CharSequence s, int start, int before, int count) { return false; }); + edit.setVisibility(isVisible ? View.VISIBLE : View.INVISIBLE); + edit.setEnabled(isVisible); layout.addView(edit); data = new JSONObject(); try { diff --git a/CHANGELOG.md b/CHANGELOG.md index ba2c46c..778d5eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to this project will be documented in this file. +## [2.0.6] - 2026-07-28 +- ### Fixed +- Native input lifecycle and visibility races + ## [2.0.5] - 2024-12-10 - ### Added - Set caret position @@ -26,4 +30,4 @@ All notable changes to this project will be documented in this file. - Keyboard autohide on tap #110 ## [2.0.0] - 2024-03-26 -### Release v2 \ No newline at end of file +### Release v2 diff --git a/Plugins/Android/Mobileinput.aar b/Plugins/Android/Mobileinput.aar index 22cb6c8eb98c01f0caebda40e80cb5a71ea112e6..3283913c4e52a8318b739fd0a1769b2b8aa8e956 100644 GIT binary patch delta 23179 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 /// Current input id /// - int _id = 0; + int _id = -1; + + /// + /// Receiver registration state + /// + bool _isRegistered = false; + + /// + /// Check whether native messages can safely use this receiver id + /// + protected bool IsRegistered { + get { + return _isRegistered; + } + } /// /// Init input and register interface @@ -40,6 +54,7 @@ protected virtual void Start() { #if !UNITY_EDITOR _id = MobileInput.Register(this); #endif + _isRegistered = true; } /// @@ -47,8 +62,11 @@ protected virtual void Start() { /// protected virtual void OnDestroy() { #if !UNITY_EDITOR - MobileInput.RemoveReceiver(_id); + if (_isRegistered) { + MobileInput.RemoveReceiver(_id); + } #endif + _isRegistered = false; } /// @@ -57,7 +75,9 @@ protected virtual void OnDestroy() { /// Data protected void Execute(JsonObject data) { #if !UNITY_EDITOR - MobileInput.Execute(_id, data); + if (_isRegistered) { + MobileInput.Execute(_id, data); + } #endif } @@ -175,6 +195,30 @@ public class MobileInput : MonoBehaviour { /// static bool _isInited = false; + /// + /// Current application focus state + /// + static bool _applicationHasFocus = true; + + /// + /// Current application pause state + /// + static bool _applicationPaused = false; + + /// + /// Notify inputs when temporary application visibility changes + /// + internal static event Action OnApplicationVisibilityChange = delegate { }; + + /// + /// Whether native inputs may currently be displayed + /// + internal static bool CanShowInputs { + get { + return _applicationHasFocus && !_applicationPaused; + } + } + #if UNITY_IOS /// /// Send data to plugin input @@ -360,7 +404,9 @@ public static int Register(MobileInputReceiver receiver) { /// /// Input id public static void RemoveReceiver(int id) { - _instance._inputs.Remove(id); + if ((object)_instance != null) { + _instance._inputs.Remove(id); + } } /// @@ -406,6 +452,8 @@ public static void Init() { Debug.Log($"[UMI] init"); #endif _isInited = true; + _applicationHasFocus = Application.isFocused; + _applicationPaused = false; var state = PlayerPrefs.GetInt(INIT_KEY, 0); if (state == 0) { UpdateFonts(); @@ -500,7 +548,22 @@ static void PrepareFontsAsset(string fileName) { /// /// Handler to check data on focus change /// + void OnApplicationFocus(bool hasFocus) { + if (_applicationHasFocus == hasFocus) { + return; + } + _applicationHasFocus = hasFocus; + OnApplicationVisibilityChange(); + } + + /// + /// Handler to preserve callbacks and native visibility across app pause + /// void OnApplicationPause(bool pauseStatus) { + if (_applicationPaused != pauseStatus) { + _applicationPaused = pauseStatus; + OnApplicationVisibilityChange(); + } if (!pauseStatus) { if (_data != null) { OnData(_data); @@ -508,4 +571,4 @@ void OnApplicationPause(bool pauseStatus) { } } } -} \ No newline at end of file +} diff --git a/Runtime/MobileInputField.cs b/Runtime/MobileInputField.cs index e713e72..4f8ecbe 100644 --- a/Runtime/MobileInputField.cs +++ b/Runtime/MobileInputField.cs @@ -61,6 +61,17 @@ public enum ReturnKeyType { Send } + /// + /// Native input initialization state + /// + enum InitializationState { + NotStarted, + Scheduled, + WaitingForReady, + Ready, + Destroyed + } + #if (UNITY_IOS || UNITY_ANDROID) && !UNITY_EDITOR /// /// InputField create event @@ -221,14 +232,14 @@ public enum ReturnKeyType { public UnityEvent OnReturnPressedEvent = null; /// - /// Mobile input creation flag + /// Native input initialization state /// - bool _isMobileInputCreated = false; + InitializationState _initializationState = InitializationState.NotStarted; /// - /// Mobile input init start flag + /// Currently scheduled initialization coroutine /// - bool _initStarted = false; + Coroutine _initializationCoroutine = null; /// /// InputField object @@ -246,9 +257,9 @@ public enum ReturnKeyType { bool _isFocusOnCreate = false; /// - /// Set visible on create flag + /// Last visibility requested through the public API /// - bool _isVisibleOnCreate = true; + bool _requestedVisible = true; /// /// Last field position cache @@ -282,6 +293,7 @@ void Awake() { throw new MissingComponentException(); } _inputObjectText = _inputObject.textComponent; + MobileInput.OnApplicationVisibilityChange += OnApplicationVisibilityChanged; } /// @@ -289,20 +301,19 @@ void Awake() { /// protected override void Start() { base.Start(); - if (!_initStarted) { - StartCoroutine(InitProcess()); - } + RequestInitialization(); } /// /// Show native on enable /// void OnEnable() { - if (_isMobileInputCreated) { + if (_initializationState == InitializationState.Ready) { SetRectNative(this._inputObjectText.rectTransform); - SetVisible(true); - } else if (!_initStarted) { - StartCoroutine(InitProcess()); + ApplyNativeVisibility(); + ApplyFocusOnCreate(); + } else if (_initializationState == InitializationState.NotStarted) { + RequestInitialization(); } } @@ -310,9 +321,13 @@ void OnEnable() { /// Hide native on disable /// void OnDisable() { - if (_isMobileInputCreated) { - SetFocus(false); - SetVisible(false); + if (_initializationState == InitializationState.Scheduled) { + CancelScheduledInitialization(); + } else if (_initializationState == InitializationState.Ready) { + SetFocusNative(false); + ApplyNativeVisibility(); + } else if (_initializationState == InitializationState.WaitingForReady) { + ApplyNativeVisibility(); } } @@ -320,32 +335,20 @@ void OnDisable() { /// Destructor /// protected override void OnDestroy() { + MobileInput.OnApplicationVisibilityChange -= OnApplicationVisibilityChanged; + CancelScheduledInitialization(); RemoveNative(); base.OnDestroy(); } -#if UNITY_ANDROID /// - /// Handler for app focus lost + /// Reapply logical visibility after app focus/pause changes /// - void OnApplicationFocus(bool hasFocus) { - if (!_isMobileInputCreated || !Visible) { - return; - } - SetVisible(hasFocus); + void OnApplicationVisibilityChanged() { + ApplyNativeVisibility(); + ApplyFocusOnCreate(); } - /// - /// Handler for app focus lost - /// - void OnApplicationPause(bool hasPause) { - if (!_isMobileInputCreated || !Visible) { - return; - } - SetVisible(!hasPause); - } -#endif - /// /// Current InputField for external access /// @@ -371,7 +374,7 @@ public string Text { return (_inputObject == null) ? string.Empty : _inputObject.text; } set { - if (!_isMobileInputCreated) { + if (_initializationState != InitializationState.Ready) { _textOnCreate = value; return; } @@ -380,18 +383,80 @@ public string Text { } } + /// + /// Initialization + /// + void RequestInitialization() { + if (_initializationState != InitializationState.NotStarted || !isActiveAndEnabled) { + return; + } + _initializationState = InitializationState.Scheduled; + _initializationCoroutine = StartCoroutine(InitProcess()); + } + + /// + /// Cancel initialization before CREATE has been sent + /// + void CancelScheduledInitialization() { + if (_initializationState != InitializationState.Scheduled) { + return; + } + if (_initializationCoroutine != null) { + StopCoroutine(_initializationCoroutine); + } + _initializationCoroutine = null; + _initializationState = InitializationState.NotStarted; + } + /// /// Initialization /// IEnumerator InitProcess() { - if (_initStarted) { + yield return WaitForEndOfFrame; + + _initializationCoroutine = null; + if (_initializationState != InitializationState.Scheduled) { yield break; } - _initStarted = true; - yield return WaitForEndOfFrame; + if (!isActiveAndEnabled) { + _initializationState = InitializationState.NotStarted; + yield break; + } + if (!IsRegistered) { + _initializationCoroutine = StartCoroutine(WaitForRegistration()); + yield break; + } + CreateAfterRegistration(); + } + + /// + /// Wait until base.Start has registered the receiver before CREATE + /// + IEnumerator WaitForRegistration() { + while (_initializationState == InitializationState.Scheduled && isActiveAndEnabled && !IsRegistered) { + yield return null; + } + _initializationCoroutine = null; + if (_initializationState != InitializationState.Scheduled) { + yield break; + } + if (!isActiveAndEnabled) { + _initializationState = InitializationState.NotStarted; + yield break; + } + CreateAfterRegistration(); + } + + /// + /// Prepare and send CREATE exactly once + /// + void CreateAfterRegistration() { PrepareNativeEdit(); #if (UNITY_IOS || UNITY_ANDROID) && !UNITY_EDITOR - CreateNativeEdit(); + var initialVisibility = ShouldShowNative(); + _initializationState = InitializationState.WaitingForReady; + Visible = initialVisibility; + CreateNativeEdit(initialVisibility); var data = this._inputObjectText.text.Trim(); if (data.Length == 1) { var category = Char.GetUnicodeCategory(data[0]); @@ -402,6 +467,10 @@ IEnumerator InitProcess() { _inputObject.placeholder.gameObject.SetActive(false); _inputObject.enabled = false; _inputObjectText.enabled = false; +#else + _initializationState = InitializationState.Ready; + ApplyNativeVisibility(true); + ApplyFocusOnCreate(); #endif } @@ -414,7 +483,7 @@ void Update() { #if UNITY_ANDROID && !UNITY_EDITOR UpdateForceKeyeventForAndroid(); #endif - if (_inputObject != null && _isMobileInputCreated) { + if (_inputObject != null && _initializationState == InitializationState.Ready) { #if !UNITY_EDITOR var touchCount = Input.touchCount; if (touchCount > 0) { @@ -525,6 +594,15 @@ void OnTextEditEnd(string text) { /// /// JSON public override void Send(JsonObject data) { + string msg = data["msg"]; + if (msg.Equals(READY)) { + Ready(); + return; + } + if (!isActiveAndEnabled) { + ProcessData(data); + return; + } StartCoroutine(SendDataProcess(data)); } @@ -532,7 +610,7 @@ public override void Send(JsonObject data) { /// Remove focus, keyboard when app lose focus /// public override void Hide() { - if (_inputObject != null && _isMobileInputCreated) { + if (_inputObject != null && _initializationState == InitializationState.Ready) { SetFocus(false); } } @@ -543,12 +621,17 @@ public override void Hide() { /// JSON IEnumerator SendDataProcess(JsonObject data) { yield return WaitForEndOfFrame; + ProcessData(data); + } + + /// + /// Process a native callback on Unity's main thread + /// + void ProcessData(JsonObject data) { string msg = data["msg"]; if (msg.Equals(TEXT_CHANGE)) { string text = data["text"]; OnTextChange(text); - } else if (msg.Equals(READY)) { - Ready(); } else if (msg.Equals(ON_FOCUS)) { OnFocusChanged(true); } else if (msg.Equals(ON_UNFOCUS)) { @@ -574,7 +657,7 @@ string InvariantCultureString(float value) { /// /// Create native input field /// - void CreateNativeEdit() { + void CreateNativeEdit(bool isVisible) { var rect = GetScreenRectFromRectTransform(_inputObjectText.rectTransform); var data = new JsonObject(); data["msg"] = CREATE; @@ -615,6 +698,7 @@ void CreateNativeEdit() { data["input_type"] = _config.InputType; data["keyboard_type"] = _config.KeyboardType; data["keyboard_language"] = KeyboardLanguage; + data["is_visible"] = isVisible; data["return_key_type"] = ReturnKey switch { ReturnKeyType.Next => (JsonNode)"Next", ReturnKeyType.Done => (JsonNode)"Done", @@ -630,16 +714,15 @@ void CreateNativeEdit() { /// New field successfully added /// void Ready() { - _isMobileInputCreated = true; + if (_initializationState != InitializationState.WaitingForReady) { + return; + } + _initializationState = InitializationState.Ready; if (!string.IsNullOrEmpty(_textOnCreate)) { Text = _textOnCreate; } - if (!_isVisibleOnCreate) { - SetVisible(false); - } - if (_isFocusOnCreate) { - SetFocus(true); - } + ApplyNativeVisibility(true); + ApplyFocusOnCreate(); } /// @@ -740,10 +823,15 @@ void SetTextNative(string text) { /// Remove field /// void RemoveNative() { - _isMobileInputCreated = false; - var data = new JsonObject(); - data["msg"] = REMOVE; - Execute(data); + var removeRequired = _initializationState == InitializationState.WaitingForReady || + _initializationState == InitializationState.Ready; + _initializationState = InitializationState.Destroyed; + Visible = false; + if (removeRequired) { + var data = new JsonObject(); + data["msg"] = REMOVE; + Execute(data); + } } /// @@ -752,7 +840,7 @@ void RemoveNative() { /// RectTransform public void SetRectNative(RectTransform inputRect) { var rect = GetScreenRectFromRectTransform(inputRect); - if (_inputObject == null || !_isMobileInputCreated || _lastRect == rect) { + if (_inputObject == null || _initializationState != InitializationState.Ready || _lastRect == rect) { return; } _lastRect = rect; @@ -771,10 +859,34 @@ public void SetRectNative(RectTransform inputRect) { /// true | false public void SetFocus(bool isFocus) { #if (UNITY_IOS || UNITY_ANDROID) && !UNITY_EDITOR - if (!_isMobileInputCreated) { + if (_initializationState != InitializationState.Ready || (isFocus && !ShouldShowNative())) { _isFocusOnCreate = isFocus; return; } + _isFocusOnCreate = false; + SetFocusNative(isFocus); +#else + if (gameObject.activeInHierarchy) { + if (isFocus) { + _inputObject.ActivateInputField(); + } else { + _inputObject.DeactivateInputField(); + } + _isFocusOnCreate = false; + } else { + _isFocusOnCreate = isFocus; + } +#endif + } + + /// + /// Apply focus directly without changing a deferred focus request + /// + void SetFocusNative(bool isFocus) { +#if (UNITY_IOS || UNITY_ANDROID) && !UNITY_EDITOR + if (_initializationState != InitializationState.Ready) { + return; + } var data = new JsonObject(); data["msg"] = SET_FOCUS; data["is_focus"] = isFocus; @@ -786,20 +898,41 @@ public void SetFocus(bool isFocus) { } else { _inputObject.DeactivateInputField(); } - } else { - _isFocusOnCreate = isFocus; } #endif + } + /// + /// Apply deferred focus once the native input can safely receive it + /// + void ApplyFocusOnCreate() { + if (!_isFocusOnCreate || _initializationState != InitializationState.Ready || !ShouldShowNative()) { + return; + } + _isFocusOnCreate = false; + SetFocusNative(true); } /// - /// Set field visible + /// Check the effective visibility without changing the public request /// - /// true | false - public void SetVisible(bool isVisible) { - if (!_isMobileInputCreated) { - _isVisibleOnCreate = isVisible; + bool ShouldShowNative() { + return _requestedVisible && + isActiveAndEnabled && + MobileInput.CanShowInputs && + _initializationState != InitializationState.Destroyed; + } + + /// + /// Apply the effective visibility to a native input that has been created + /// + void ApplyNativeVisibility(bool force = false) { + if (_initializationState != InitializationState.WaitingForReady && + _initializationState != InitializationState.Ready) { + return; + } + var isVisible = ShouldShowNative(); + if (!force && Visible == isVisible) { return; } var data = new JsonObject(); @@ -810,6 +943,16 @@ public void SetVisible(bool isVisible) { _lastRect = new Rect(); } + /// + /// Set requested field visibility + /// + /// true | false + public void SetVisible(bool isVisible) { + _requestedVisible = isVisible; + ApplyNativeVisibility(); + ApplyFocusOnCreate(); + } + #if UNITY_ANDROID && !UNITY_EDITOR /// @@ -844,4 +987,4 @@ private void UpdateForceKeyeventForAndroid() { #endif } -} \ No newline at end of file +} diff --git a/package.json b/package.json index 6660418..8bfdaf1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "com.mopsicus.umi", - "version": "2.0.0", + "version": "2.0.6", "displayName": "UMI", "description": "UMI – Unity plugin for Android and iOS, allows to use features of mobile native input fields.", "license": "MIT", @@ -41,4 +41,4 @@ "path": "Samples~/Demo" } ] - } \ No newline at end of file + }