textinput: support every environment even without IME

Closes #3072
This commit is contained in:
Hajime Hoshi 2024-08-24 01:04:11 +09:00
parent f3bd56b0ed
commit dd63eef65e
4 changed files with 65 additions and 25 deletions

View File

@ -0,0 +1,58 @@
// Copyright 2023 The Ebitengine Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build (!darwin && !js && !windows) || ios
package textinput
import (
"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/internal/ui"
)
type textInput struct {
rs []rune
lastTick uint64
}
var theTextInput textInput
func (t *textInput) Start(x, y int) (chan State, func()) {
// AppendInputChars is updated only when the tick is updated.
// If the tick is not updated, return nil immediately.
tick := ui.Get().Tick()
if t.lastTick == tick {
return nil, nil
}
defer func() {
t.lastTick = tick
}()
s := newSession()
// This is a pseudo implementation with AppendInputChars without IME.
// This is tentative and should be replaced with IME in the future.
t.rs = ebiten.AppendInputChars(t.rs[:0])
if len(t.rs) == 0 {
return nil, nil
}
s.ch <- State{
Text: string(t.rs),
Committed: true,
}
// Keep the channel as end() resets s.ch.
ch := s.ch
s.end()
return ch, nil
}

View File

@ -1,25 +0,0 @@
// Copyright 2023 The Ebitengine Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build (!darwin && !js && !windows) || ios
package textinput
type textInput struct{}
var theTextInput textInput
func (t *textInput) Start(x, y int) (chan State, func()) {
return nil, nil
}

View File

@ -153,6 +153,8 @@ func (c *context) updateFrameImpl(graphicsDriver graphicsdriver.Graphics, update
if err := ui.error(); err != nil { if err := ui.error(); err != nil {
return err return err
} }
ui.tick.Add(1)
} }
// Update window icons during a frame, since an icon might be *ebiten.Image and // Update window icons during a frame, since an icon might be *ebiten.Image and

View File

@ -79,6 +79,7 @@ type UserInterface struct {
graphicsLibrary atomic.Int32 graphicsLibrary atomic.Int32
running atomic.Bool running atomic.Bool
terminated atomic.Bool terminated atomic.Bool
tick atomic.Uint64
whiteImage *Image whiteImage *Image
@ -230,3 +231,7 @@ func (u *UserInterface) isTerminated() bool {
func (u *UserInterface) setTerminated() { func (u *UserInterface) setTerminated() {
u.terminated.Store(true) u.terminated.Store(true)
} }
func (u *UserInterface) Tick() uint64 {
return u.tick.Load()
}