From b996ec19cf03efb9692d8ea909eb2a641bcb0d84 Mon Sep 17 00:00:00 2001 From: DigiEggz Date: Thu, 21 Dec 2023 15:21:44 -0500 Subject: [PATCH 1/4] Support Android browser text input Some Android browsers can not type in text input fields. I leveraged window.onTextInput to detect text changes and refactored code to remove redundancies and improve performance. Some mobile targets also require touch detection. I've tested typing and pasting text on desktop, mobile and web (both GeckoView and WebView browsers). These changes are working with the latest versions of OpenFL and Lime. --- flixel/addons/ui/FlxInputText.hx | 79 ++++++++++++++++---------------- 1 file changed, 39 insertions(+), 40 deletions(-) diff --git a/flixel/addons/ui/FlxInputText.hx b/flixel/addons/ui/FlxInputText.hx index 53ec250..d9d1dec 100644 --- a/flixel/addons/ui/FlxInputText.hx +++ b/flixel/addons/ui/FlxInputText.hx @@ -232,11 +232,6 @@ class FlxInputText extends FlxText Text = ""; } - // Register paste events for the HTML5 parent window - #if (js && html5) - FlxG.stage.window.onTextInput.add(handleClipboardText); - #end - text = Text; // ensure set_text is called to avoid bugs (like not preparing _charBoundaries on sys target, making it impossible to click) calcFrame(); @@ -264,10 +259,6 @@ class FlxInputText extends FlxText } #end - #if (js && html5) - FlxG.stage.window.onTextInput.remove(handleClipboardText); - #end - super.destroy(); } @@ -331,6 +322,27 @@ class FlxInputText extends FlxText } } #end + + #if FLX_TOUCH + // Set focus and caretIndex as a response to an initial touch event + if (FlxG.touches.list.length > 0) + { + var hadFocus:Bool = hasFocus; + if (FlxG.touches.getFirst().overlaps(this)) + { + caretIndex = getCaretIndex(); + hasFocus = true; + if (!hadFocus && focusGained != null) + focusGained(); + } + else + { + hasFocus = false; + if (hadFocus && focusLost != null) + focusLost(); + } + } + #end } /** @@ -386,22 +398,9 @@ class FlxInputText extends FlxText #else var clipboardText:String = Clipboard.text; if (clipboardText != null) - pasteClipboardText(clipboardText); + windowInputText(clipboardText); #end default: - // Actually add some text - if (e.charCode == 0) // non-printable characters crash String.fromCharCode - { - return; - } - final newText = filter(String.fromCharCode(e.charCode)); - - if (newText.length > 0 && (maxLength == 0 || (text.length + newText.length) <= maxLength)) - { - text = insertSubstring(text, newText, caretIndex); - caretIndex++; - onChange(INPUT_ACTION); - } } } } @@ -414,23 +413,6 @@ class FlxInputText extends FlxText } } - #if (html5 && js) - function handleClipboardText(clipboardText:String) - { - @:privateAccess if (Clipboard._text == clipboardText) - pasteClipboardText(clipboardText); - } - #end - - function pasteClipboardText(clipboardText:String) - { - final newText = filter(clipboardText).substring(0, maxLength > 0 ? (maxLength - text.length) : clipboardText.length); - - text = insertSubstring(text, newText, caretIndex); - caretIndex += newText.length; - onChange(INPUT_ACTION); - } - /** * Inserts a substring into a string at a specific index * @@ -462,6 +444,9 @@ class FlxInputText extends FlxText #if FLX_MOUSE var hit = FlxPoint.get(FlxG.mouse.x - x, FlxG.mouse.y - y); return getCharIndexAtPoint(hit.x, hit.y); + #elseif FLX_TOUCH + var hit = FlxPoint.get(FlxG.touches.getFirst().x - x, FlxG.touches.getFirst().y - y); + return getCharIndexAtPoint(hit.x, hit.y); #else return 0; #end @@ -817,6 +802,15 @@ class FlxInputText extends FlxText return super.set_y(Y); } + function windowInputText(textInput:String) + { + final newText = filter(textInput).substring(0, maxLength > 0 ? (maxLength - text.length) : textInput.length); + + text = insertSubstring(text, newText, caretIndex); + caretIndex += newText.length; + onChange(INPUT_ACTION); + } + private function set_hasFocus(newFocus:Bool):Bool { if (newFocus) @@ -827,6 +821,9 @@ class FlxInputText extends FlxText caret.visible = true; caretIndex = text.length; + if (!FlxG.stage.window.onTextInput.has(windowInputText)) + FlxG.stage.window.onTextInput.add(windowInputText); + #if mobile // Initialize soft keyboard FlxG.stage.window.textInputEnabled = true; @@ -842,6 +839,8 @@ class FlxInputText extends FlxText _caretTimer.cancel(); } + FlxG.stage.window.onTextInput.remove(windowInputText); + #if mobile // Remove soft keyboard FlxG.stage.window.textInputEnabled = false; From 4538c5e738340676c3364c2a5902c762e0b5565f Mon Sep 17 00:00:00 2001 From: DigiEggz Date: Fri, 22 Dec 2023 11:14:56 -0500 Subject: [PATCH 2/4] Update FlxInputText.hx --- flixel/addons/ui/FlxInputText.hx | 33 ++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/flixel/addons/ui/FlxInputText.hx b/flixel/addons/ui/FlxInputText.hx index d9d1dec..aaaa923 100644 --- a/flixel/addons/ui/FlxInputText.hx +++ b/flixel/addons/ui/FlxInputText.hx @@ -330,7 +330,7 @@ class FlxInputText extends FlxText var hadFocus:Bool = hasFocus; if (FlxG.touches.getFirst().overlaps(this)) { - caretIndex = getCaretIndex(); + caretIndex = getCaretIndex(false); hasFocus = true; if (!hadFocus && focusGained != null) focusGained(); @@ -435,21 +435,30 @@ class FlxInputText extends FlxText } /** - * Gets the index of the character in this box under the mouse cursor + * Gets the index of the character in this box under the mouse cursor or touch event * @return The index of the character. * between 0 and the length of the text */ - private function getCaretIndex():Int + private function getCaretIndex(isMouse:Bool = true):Int { - #if FLX_MOUSE - var hit = FlxPoint.get(FlxG.mouse.x - x, FlxG.mouse.y - y); - return getCharIndexAtPoint(hit.x, hit.y); - #elseif FLX_TOUCH - var hit = FlxPoint.get(FlxG.touches.getFirst().x - x, FlxG.touches.getFirst().y - y); - return getCharIndexAtPoint(hit.x, hit.y); - #else - return 0; - #end + if(isMouse) + { + #if FLX_MOUSE + var hit = FlxPoint.get(FlxG.mouse.x - x, FlxG.mouse.y - y); + return getCharIndexAtPoint(hit.x, hit.y); + #else + return 0; + #end + } + else + { + #if FLX_TOUCH + var hit = FlxPoint.get(FlxG.touches.getFirst().x - x, FlxG.touches.getFirst().y - y); + return getCharIndexAtPoint(hit.x, hit.y); + #else + return 0; + #end + } } private function getCharBoundaries(charIndex:Int):Rectangle From 1574847a5f9c2a7bb9389179d152bf08286cd789 Mon Sep 17 00:00:00 2001 From: DigiEggz Date: Fri, 22 Dec 2023 12:48:21 -0500 Subject: [PATCH 3/4] Update FlxInputText.hx --- flixel/addons/ui/FlxInputText.hx | 1 + 1 file changed, 1 insertion(+) diff --git a/flixel/addons/ui/FlxInputText.hx b/flixel/addons/ui/FlxInputText.hx index aaaa923..35d0cf3 100644 --- a/flixel/addons/ui/FlxInputText.hx +++ b/flixel/addons/ui/FlxInputText.hx @@ -243,6 +243,7 @@ class FlxInputText extends FlxText override public function destroy():Void { FlxG.stage.removeEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); + FlxG.stage.window.onTextInput.remove(windowInputText); backgroundSprite = FlxDestroyUtil.destroy(backgroundSprite); fieldBorderSprite = FlxDestroyUtil.destroy(fieldBorderSprite); From 82890bfebc22938479fe7b5e4dad69406982c96a Mon Sep 17 00:00:00 2001 From: DigiEggz Date: Thu, 25 Jan 2024 13:12:11 -0500 Subject: [PATCH 4/4] Update FlxInputText.hx Only add new listener code for mobile since Chromium-based Android browsers are not receiving keyDown events. Experienced problems pasting text longer than 32 characters on Android builds, so we use a hybrid of the two. --- flixel/addons/ui/FlxInputText.hx | 93 +++++++++++++------------------- 1 file changed, 38 insertions(+), 55 deletions(-) diff --git a/flixel/addons/ui/FlxInputText.hx b/flixel/addons/ui/FlxInputText.hx index 35d0cf3..798ca8d 100644 --- a/flixel/addons/ui/FlxInputText.hx +++ b/flixel/addons/ui/FlxInputText.hx @@ -243,7 +243,9 @@ class FlxInputText extends FlxText override public function destroy():Void { FlxG.stage.removeEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); + #if (js && html5) FlxG.stage.window.onTextInput.remove(windowInputText); + #end backgroundSprite = FlxDestroyUtil.destroy(backgroundSprite); fieldBorderSprite = FlxDestroyUtil.destroy(fieldBorderSprite); @@ -323,27 +325,6 @@ class FlxInputText extends FlxText } } #end - - #if FLX_TOUCH - // Set focus and caretIndex as a response to an initial touch event - if (FlxG.touches.list.length > 0) - { - var hadFocus:Bool = hasFocus; - if (FlxG.touches.getFirst().overlaps(this)) - { - caretIndex = getCaretIndex(false); - hasFocus = true; - if (!hadFocus && focusGained != null) - focusGained(); - } - else - { - hasFocus = false; - if (hadFocus && focusLost != null) - focusLost(); - } - } - #end } /** @@ -402,6 +383,20 @@ class FlxInputText extends FlxText windowInputText(clipboardText); #end default: + #if !(js && html5) // Actually add some text + if (e.charCode == 0) // non-printable characters crash String.fromCharCode + { + return; + } + final newText = filter(String.fromCharCode(e.charCode)); + + if (newText.length > 0 && (maxLength == 0 || (text.length + newText.length) <= maxLength)) + { + text = insertSubstring(text, newText, caretIndex); + caretIndex++; + onChange(INPUT_ACTION); + } + #end } } } @@ -414,6 +409,15 @@ class FlxInputText extends FlxText } } + function windowInputText(inputText:String) + { + final newText = filter(inputText).substring(0, maxLength > 0 ? (maxLength - text.length) : inputText.length); + + text = insertSubstring(text, newText, caretIndex); + caretIndex += newText.length; + onChange(INPUT_ACTION); + } + /** * Inserts a substring into a string at a specific index * @@ -436,30 +440,18 @@ class FlxInputText extends FlxText } /** - * Gets the index of the character in this box under the mouse cursor or touch event + * Gets the index of the character in this box under the mouse cursor * @return The index of the character. * between 0 and the length of the text */ - private function getCaretIndex(isMouse:Bool = true):Int + private function getCaretIndex():Int { - if(isMouse) - { - #if FLX_MOUSE - var hit = FlxPoint.get(FlxG.mouse.x - x, FlxG.mouse.y - y); - return getCharIndexAtPoint(hit.x, hit.y); - #else - return 0; - #end - } - else - { - #if FLX_TOUCH - var hit = FlxPoint.get(FlxG.touches.getFirst().x - x, FlxG.touches.getFirst().y - y); - return getCharIndexAtPoint(hit.x, hit.y); - #else - return 0; - #end - } + #if FLX_MOUSE + var hit = FlxPoint.get(FlxG.mouse.x - x, FlxG.mouse.y - y); + return getCharIndexAtPoint(hit.x, hit.y); + #else + return 0; + #end } private function getCharBoundaries(charIndex:Int):Rectangle @@ -812,15 +804,6 @@ class FlxInputText extends FlxText return super.set_y(Y); } - function windowInputText(textInput:String) - { - final newText = filter(textInput).substring(0, maxLength > 0 ? (maxLength - text.length) : textInput.length); - - text = insertSubstring(text, newText, caretIndex); - caretIndex += newText.length; - onChange(INPUT_ACTION); - } - private function set_hasFocus(newFocus:Bool):Bool { if (newFocus) @@ -831,10 +814,10 @@ class FlxInputText extends FlxText caret.visible = true; caretIndex = text.length; + #if (js && html5) if (!FlxG.stage.window.onTextInput.has(windowInputText)) FlxG.stage.window.onTextInput.add(windowInputText); - - #if mobile + #elseif mobile // Initialize soft keyboard FlxG.stage.window.textInputEnabled = true; #end @@ -849,9 +832,9 @@ class FlxInputText extends FlxText _caretTimer.cancel(); } + #if (js && html5) FlxG.stage.window.onTextInput.remove(windowInputText); - - #if mobile + #elseif mobile // Remove soft keyboard FlxG.stage.window.textInputEnabled = false; #end @@ -1043,4 +1026,4 @@ class FlxInputText extends FlxText calcFrame(); return backgroundColor; } -} +} \ No newline at end of file