mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-04 00:45:35 +00:00
app,io/router: expand IME snippets if a new range overlaps the old
Instead of cmpletely replacing the IME snippet for every update, expand the old range if there is overlap. This change avoids never-ending restarts of the IME on Android where snippets are expanded in two calls, one for expanding before the selection and one for exanding after the selection. Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
@@ -108,6 +108,27 @@ func FuzzIME(f *testing.F) {
|
||||
newState := r.EditorState()
|
||||
// We don't track caret position.
|
||||
state.Selection.Caret = newState.Selection.Caret
|
||||
// Expanded snippets are ok.
|
||||
their, our := newState.Snippet, state.EditorState.Snippet
|
||||
beforeLen := 0
|
||||
for before := our.Start - their.Start; before > 0; before-- {
|
||||
_, n := utf8.DecodeRuneInString(their.Text[beforeLen:])
|
||||
beforeLen += n
|
||||
}
|
||||
afterLen := 0
|
||||
for after := their.End - our.End; after > 0; after-- {
|
||||
_, n := utf8.DecodeLastRuneInString(their.Text[:len(their.Text)-afterLen])
|
||||
afterLen += n
|
||||
}
|
||||
if beforeLen > 0 {
|
||||
our.Text = their.Text[:beforeLen] + our.Text
|
||||
our.Start = their.Start
|
||||
}
|
||||
if afterLen > 0 {
|
||||
our.Text = our.Text + their.Text[len(their.Text)-afterLen:]
|
||||
our.End = their.End
|
||||
}
|
||||
state.EditorState.Snippet = our
|
||||
if newState != state.EditorState {
|
||||
t.Errorf("IME state: %+v\neditor state: %+v", state.EditorState, newState)
|
||||
}
|
||||
|
||||
@@ -492,7 +492,6 @@ func (c *callbacks) EditorInsert(text string) {
|
||||
func (c *callbacks) EditorReplace(r key.Range, text string) {
|
||||
c.w.imeState.Replace(r, text)
|
||||
c.Event(key.EditEvent{Range: r, Text: text})
|
||||
c.Event(key.SnippetEvent(c.w.imeState.Snippet.Range))
|
||||
}
|
||||
|
||||
func (c *callbacks) SetEditorSelection(r key.Range) {
|
||||
|
||||
+28
-1
@@ -142,7 +142,20 @@ func (q *Router) Queue(events ...event.Event) bool {
|
||||
q.pointer.queue.Push(e, &q.handlers)
|
||||
case key.Event:
|
||||
q.queueKeyEvent(e)
|
||||
case key.EditEvent, key.FocusEvent, key.SnippetEvent, key.SelectionEvent:
|
||||
case key.SnippetEvent:
|
||||
// Expand existing, overlapping snippet.
|
||||
if r := q.key.queue.content.Snippet.Range; rangeOverlaps(r, key.Range(e)) {
|
||||
if e.Start > r.Start {
|
||||
e.Start = r.Start
|
||||
}
|
||||
if e.End < r.End {
|
||||
e.End = r.End
|
||||
}
|
||||
}
|
||||
if f := q.key.queue.focus; f != nil {
|
||||
q.handlers.Add(f, e)
|
||||
}
|
||||
case key.EditEvent, key.FocusEvent, key.SelectionEvent:
|
||||
if f := q.key.queue.focus; f != nil {
|
||||
q.handlers.Add(f, e)
|
||||
}
|
||||
@@ -153,6 +166,20 @@ func (q *Router) Queue(events ...event.Event) bool {
|
||||
return q.handlers.HadEvents()
|
||||
}
|
||||
|
||||
func rangeOverlaps(r1, r2 key.Range) bool {
|
||||
r1 = rangeNorm(r1)
|
||||
r2 = rangeNorm(r2)
|
||||
return r1.Start <= r2.Start && r2.Start < r1.End ||
|
||||
r1.Start <= r2.End && r2.End < r1.End
|
||||
}
|
||||
|
||||
func rangeNorm(r key.Range) key.Range {
|
||||
if r.End < r.Start {
|
||||
r.End, r.Start = r.Start, r.End
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func (q *Router) queueKeyEvent(e key.Event) {
|
||||
kq := &q.key.queue
|
||||
f := q.key.queue.focus
|
||||
|
||||
Reference in New Issue
Block a user