mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-06 01:45:36 +00:00
ui/key: don't drop handlers that haven't had their events read
Similar to the previous change for pointers, only determine the activeness of a handler from its presence in the ops list. Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
+54
-32
@@ -9,11 +9,15 @@ import (
|
|||||||
|
|
||||||
type Queue struct {
|
type Queue struct {
|
||||||
focus Key
|
focus Key
|
||||||
events []Event
|
handlers map[Key]*handler
|
||||||
handlers map[Key]bool
|
|
||||||
reader ui.OpsReader
|
reader ui.OpsReader
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type handler struct {
|
||||||
|
active bool
|
||||||
|
events []Event
|
||||||
|
}
|
||||||
|
|
||||||
type listenerPriority uint8
|
type listenerPriority uint8
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -24,18 +28,37 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (q *Queue) Frame(root *ui.Ops) TextInputState {
|
func (q *Queue) Frame(root *ui.Ops) TextInputState {
|
||||||
q.events = q.events[:0]
|
if q.handlers == nil {
|
||||||
|
q.handlers = make(map[Key]*handler)
|
||||||
|
}
|
||||||
|
for _, h := range q.handlers {
|
||||||
|
h.active = false
|
||||||
|
h.events = h.events[:0]
|
||||||
|
}
|
||||||
q.reader.Reset(root)
|
q.reader.Reset(root)
|
||||||
f, pri, hide := resolveFocus(&q.reader, q.focus)
|
focus, pri, hide := q.resolveFocus()
|
||||||
changed := f != nil && f != q.focus
|
for k, h := range q.handlers {
|
||||||
for k, active := range q.handlers {
|
if !h.active {
|
||||||
if !active || changed {
|
|
||||||
delete(q.handlers, k)
|
delete(q.handlers, k)
|
||||||
} else {
|
if q.focus == k {
|
||||||
q.handlers[k] = false
|
q.focus = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
changed := focus != nil && focus != q.focus
|
||||||
|
if focus != q.focus {
|
||||||
|
if q.focus != nil {
|
||||||
|
if h, ok := q.handlers[q.focus]; ok {
|
||||||
|
h.events = append(h.events, Focus{Focus: false})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
q.focus = focus
|
||||||
|
if q.focus != nil {
|
||||||
|
// A new focus always exists in the handler map.
|
||||||
|
h := q.handlers[q.focus]
|
||||||
|
h.events = append(h.events, Focus{Focus: true})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
q.focus = f
|
|
||||||
switch {
|
switch {
|
||||||
case pri == priNewFocus:
|
case pri == priNewFocus:
|
||||||
return TextInputOpen
|
return TextInputOpen
|
||||||
@@ -49,38 +72,28 @@ func (q *Queue) Frame(root *ui.Ops) TextInputState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queue) Push(e Event) {
|
func (q *Queue) Push(e Event) {
|
||||||
q.events = append(q.events, e)
|
if q.focus == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
h := q.handlers[q.focus]
|
||||||
|
h.events = append(h.events, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queue) For(k Key) []Event {
|
func (q *Queue) For(k Key) []Event {
|
||||||
if q.handlers == nil {
|
h := q.handlers[k]
|
||||||
q.handlers = make(map[Key]bool)
|
if h == nil {
|
||||||
}
|
|
||||||
_, exists := q.handlers[k]
|
|
||||||
q.handlers[k] = true
|
|
||||||
if !exists {
|
|
||||||
if k == q.focus {
|
|
||||||
// Prepend focus event.
|
|
||||||
q.events = append(q.events, nil)
|
|
||||||
copy(q.events[1:], q.events)
|
|
||||||
q.events[0] = Focus{Focus: true}
|
|
||||||
} else {
|
|
||||||
return []Event{Focus{Focus: false}}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if k != q.focus {
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return q.events
|
return h.events
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolveFocus(r *ui.OpsReader, focus Key) (Key, listenerPriority, bool) {
|
func (q *Queue) resolveFocus() (Key, listenerPriority, bool) {
|
||||||
var k Key
|
var k Key
|
||||||
var pri listenerPriority
|
var pri listenerPriority
|
||||||
var hide bool
|
var hide bool
|
||||||
loop:
|
loop:
|
||||||
for {
|
for {
|
||||||
encOp, ok := r.Decode()
|
encOp, ok := q.reader.Decode()
|
||||||
if !ok {
|
if !ok {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -92,7 +105,7 @@ loop:
|
|||||||
switch {
|
switch {
|
||||||
case op.Focus:
|
case op.Focus:
|
||||||
newPri = priNewFocus
|
newPri = priNewFocus
|
||||||
case op.Key == focus:
|
case op.Key == q.focus:
|
||||||
newPri = priCurrentFocus
|
newPri = priCurrentFocus
|
||||||
default:
|
default:
|
||||||
newPri = priDefault
|
newPri = priDefault
|
||||||
@@ -100,10 +113,19 @@ loop:
|
|||||||
if newPri >= pri {
|
if newPri >= pri {
|
||||||
k, pri = op.Key, newPri
|
k, pri = op.Key, newPri
|
||||||
}
|
}
|
||||||
|
h, ok := q.handlers[op.Key]
|
||||||
|
if !ok {
|
||||||
|
h = &handler{
|
||||||
|
// Reset the handler on (each) first appearance.
|
||||||
|
events: []Event{Focus{Focus: false}},
|
||||||
|
}
|
||||||
|
q.handlers[op.Key] = h
|
||||||
|
}
|
||||||
|
h.active = true
|
||||||
case ops.TypeHideInput:
|
case ops.TypeHideInput:
|
||||||
hide = true
|
hide = true
|
||||||
case ops.TypePush:
|
case ops.TypePush:
|
||||||
newK, newPri, h := resolveFocus(r, focus)
|
newK, newPri, h := q.resolveFocus()
|
||||||
hide = hide || h
|
hide = hide || h
|
||||||
if newPri >= pri {
|
if newPri >= pri {
|
||||||
k, pri = newK, newPri
|
k, pri = newK, newPri
|
||||||
|
|||||||
Reference in New Issue
Block a user