Skip to content

Commit

Permalink
exp/textinput: bug fix: issues on browsers
Browse files Browse the repository at this point in the history
This change addresses on these issues on browsers:

* Pressing cursor keys didn't work well.
  This is fixed by calling trySend with true on desktops (not mobiles).
* Inputting failed just after moving a cursor.
  This is fixed by resetting a session correctly.
* Sometimes pressing the enter key inserted a new line unexpectedly.
  This is fixed by calling `preventDefault`.

Closes #3014
  • Loading branch information
hajimehoshi committed Jun 11, 2024
1 parent 22fd1f1 commit 546c478
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 5 deletions.
2 changes: 1 addition & 1 deletion exp/textinput/field.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ func (f *Field) HandleInput(x, y int) (handled bool, err error) {
f.ch, f.end = Start(x, y)
// Start returns nil for non-supported envrionments.
if f.ch == nil {
return true, nil
return false, nil
}
}

Expand Down
43 changes: 39 additions & 4 deletions exp/textinput/textinput_js.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package textinput

import (
"fmt"
"strings"
"syscall/js"

"github.com/hajimehoshi/ebiten/v2/internal/ui"
Expand Down Expand Up @@ -79,7 +80,10 @@ func (t *textInput) init() {
e.Call("preventDefault")
}
if e.Get("code").String() == "Enter" || e.Get("key").String() == "Enter" {
// Ignore Enter key to avoid ebiten.IsKeyPressed(ebiten.KeyEnter) unexpectedly becomes true, especially for iOS Safari.
// Ignore Enter key to avoid ebiten.IsKeyPressed(ebiten.KeyEnter) unexpectedly becomes true.
e.Call("preventDefault")
ui.Get().UpdateInputFromEvent(e)
t.trySend(true)
return nil
}
if !e.Get("isComposing").Bool() {
Expand All @@ -96,6 +100,11 @@ func (t *textInput) init() {
}))
t.textareaElement.Call("addEventListener", "input", js.FuncOf(func(this js.Value, args []js.Value) any {
e := args[0]
// On iOS Safari, `isComposing` can be undefined.
if e.Get("isComposing").IsUndefined() {
t.trySend(false)
return nil
}
if e.Get("isComposing").Bool() {
t.trySend(false)
return nil
Expand All @@ -109,8 +118,12 @@ func (t *textInput) init() {
t.trySend(true)
return nil
}
// Though `isComposing` is false, send the text as being not committed for text completion on mobile browsers.
t.trySend(false)
// Though `isComposing` is false, send the text as being not committed for text completion with a virtual keyboard.
if isVirtualKeyboard() {
t.trySend(false)
return nil
}
t.trySend(true)
return nil
}))
t.textareaElement.Call("addEventListener", "change", js.FuncOf(func(this js.Value, args []js.Value) any {
Expand Down Expand Up @@ -172,7 +185,13 @@ func (t *textInput) Start(x, y int) (chan State, func()) {
s := newSession()
t.session = s
}
return t.session.ch, t.session.end
return t.session.ch, func() {
if t.session != nil {
t.session.end()
// Reset the session explictly, or a new session cannot be created above.
t.session = nil
}
}
}

if t.session != nil {
Expand All @@ -193,6 +212,10 @@ func (t *textInput) trySend(committed bool) {
}

textareaValue := t.textareaElement.Get("value").String()
if textareaValue == "" {
return
}

start := t.textareaElement.Get("selectionStart").Int()
end := t.textareaElement.Get("selectionEnd").Int()
startInBytes := convertUTF16CountToByteCount(textareaValue, start)
Expand All @@ -213,3 +236,15 @@ func (t *textInput) trySend(committed bool) {
t.textareaElement.Set("value", "")
}
}

func isVirtualKeyboard() bool {
// Detect a virtual keyboard by the user agent.
// Note that this is not a correct way to detect a virtual keyboard.
// In the future, we should use the `navigator.virtualKeyboard` API.
// https://developer.mozilla.org/en-US/docs/Web/API/Navigator/virtualKeyboard
ua := js.Global().Get("navigator").Get("userAgent").String()
if strings.Contains(ua, "Android") || strings.Contains(ua, "iPhone") || strings.Contains(ua, "iPad") || strings.Contains(ua, "iPod") {
return true
}
return false
}

0 comments on commit 546c478

Please sign in to comment.