mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2026-04-22 15:57:15 +08:00
exp/textinput: clear queued states when text field is unfocused
The session's state queue buffers input events that arrive between a commit-end and the next session start, which is needed when multiple keys are pressed simultaneously (#3382). However, when a text field was unfocused, keystroke events continued to be queued by the platform layer and were replayed when a field was next focused, causing unexpected text to appear. Clear the queued states in Field.cleanUp(), which is called when a field is blurred. This preserves the queue for simultaneous keypresses within a focused field while discarding stale input from unfocused periods. Also refactor textInput to move the session field and theTextInput variable to the cross-platform textinput.go, with each platform defining only a textInputImpl with platform-specific fields. Updates #3382 Closes #3429 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -290,6 +290,8 @@ func (f *Field) cleanUp() {
|
||||
f.end = nil
|
||||
f.state = textInputState{}
|
||||
}
|
||||
|
||||
theTextInput.session.clearQueue()
|
||||
}
|
||||
|
||||
// Selection returns the current selection range in bytes.
|
||||
|
||||
@@ -117,6 +117,13 @@ func convertByteCountToUTF16Count(text string, c int) int {
|
||||
return -1
|
||||
}
|
||||
|
||||
type textInput struct {
|
||||
textInputImpl
|
||||
session session
|
||||
}
|
||||
|
||||
var theTextInput textInput
|
||||
|
||||
type session struct {
|
||||
ch chan textInputState
|
||||
done chan struct{}
|
||||
@@ -184,6 +191,15 @@ func (s *session) doSend(state textInputState) {
|
||||
}
|
||||
}
|
||||
|
||||
// clearQueue clears queued states.
|
||||
// This should be called when the text field is unfocused
|
||||
// so that the queued states are not flushed when the next session starts (#3429).
|
||||
func (s *session) clearQueue() {
|
||||
s.m.Lock()
|
||||
defer s.m.Unlock()
|
||||
s.queuedStates = s.queuedStates[:0]
|
||||
}
|
||||
|
||||
func (s *session) flushStateQueue() {
|
||||
for _, st := range s.queuedStates {
|
||||
s.doSend(st)
|
||||
|
||||
@@ -25,12 +25,7 @@ import (
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
)
|
||||
|
||||
type textInput struct {
|
||||
// session must be accessed from the main thread.
|
||||
session session
|
||||
}
|
||||
|
||||
var theTextInput textInput
|
||||
type textInputImpl struct{}
|
||||
|
||||
func (t *textInput) Start(bounds image.Rectangle) (<-chan textInputState, func()) {
|
||||
var ch <-chan textInputState
|
||||
|
||||
@@ -34,14 +34,10 @@ func init() {
|
||||
theTextInput.init()
|
||||
}
|
||||
|
||||
type textInput struct {
|
||||
type textInputImpl struct {
|
||||
textareaElement js.Value
|
||||
|
||||
session session
|
||||
}
|
||||
|
||||
var theTextInput textInput
|
||||
|
||||
func (t *textInput) init() {
|
||||
t.textareaElement = document.Call("createElement", "textarea")
|
||||
t.textareaElement.Set("id", "ebitengine-textinput")
|
||||
|
||||
@@ -22,14 +22,11 @@ import (
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
)
|
||||
|
||||
type textInput struct {
|
||||
session session
|
||||
type textInputImpl struct {
|
||||
rs []rune
|
||||
lastTick int64
|
||||
}
|
||||
|
||||
var theTextInput textInput
|
||||
|
||||
func (t *textInput) Start(bounds image.Rectangle) (<-chan textInputState, func()) {
|
||||
// AppendInputChars is updated only when the tick is updated.
|
||||
// If the tick is not updated, return nil immediately.
|
||||
|
||||
@@ -27,9 +27,7 @@ import (
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/ui"
|
||||
)
|
||||
|
||||
type textInput struct {
|
||||
session session
|
||||
|
||||
type textInputImpl struct {
|
||||
origWndProc uintptr
|
||||
wndProcCallback uintptr
|
||||
window windows.HWND
|
||||
@@ -42,8 +40,6 @@ type textInput struct {
|
||||
err error
|
||||
}
|
||||
|
||||
var theTextInput textInput
|
||||
|
||||
func (t *textInput) Start(bounds image.Rectangle) (<-chan textInputState, func()) {
|
||||
if microsoftgdk.IsXbox() {
|
||||
return nil, nil
|
||||
|
||||
Reference in New Issue
Block a user