mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-01 07:35:40 +00:00
io/key: [API] implement key event propagation
Before this change, every Event would be passed to the focused InputOp tag, making it impossible to implement, say, program-wide shortcuts. This change implements key.Event routing similar to how pointer.Events are routed: every InputOp describes the set of keys it can handle, and the router use that information to deliver an Event to the matching handler. This is an API change, because every InputOp must now include a filter matching the keys it wants to handle. Fixes: https://todo.sr.ht/~eliasnaur/gio/395 Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
+1
-1
@@ -111,7 +111,7 @@ func (b *Clickable) Layout(gtx layout.Context, w layout.Widget) layout.Dimension
|
||||
semantic.DisabledOp(disabled).Add(gtx.Ops)
|
||||
b.click.Add(gtx.Ops)
|
||||
if !disabled {
|
||||
key.InputOp{Tag: &b.keyTag}.Add(gtx.Ops)
|
||||
key.InputOp{Tag: &b.keyTag, Keys: "⏎|Space"}.Add(gtx.Ops)
|
||||
} else {
|
||||
b.focused = false
|
||||
}
|
||||
|
||||
+7
-24
@@ -8,7 +8,6 @@ import (
|
||||
"image"
|
||||
"io"
|
||||
"math"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -364,10 +363,9 @@ func (e *Editor) processKey(gtx layout.Context) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
if e.command(gtx, ke) {
|
||||
e.caret.scroll = true
|
||||
e.scroller.Stop()
|
||||
}
|
||||
e.command(gtx, ke)
|
||||
e.caret.scroll = true
|
||||
e.scroller.Stop()
|
||||
case key.SnippetEvent:
|
||||
e.updateSnippet(gtx, ke.Start, ke.End)
|
||||
case key.EditEvent:
|
||||
@@ -403,16 +401,12 @@ func (e *Editor) moveLines(distance int, selAct selectionAction) {
|
||||
e.updateSelection(selAct)
|
||||
}
|
||||
|
||||
func (e *Editor) command(gtx layout.Context, k key.Event) bool {
|
||||
func (e *Editor) command(gtx layout.Context, k key.Event) {
|
||||
direction := 1
|
||||
if e.locale.Direction.Progression() == system.TowardOrigin {
|
||||
direction = -1
|
||||
}
|
||||
modSkip := key.ModCtrl
|
||||
if runtime.GOOS == "darwin" {
|
||||
modSkip = key.ModAlt
|
||||
}
|
||||
moveByWord := k.Modifiers.Contain(modSkip)
|
||||
moveByWord := k.Modifiers.Contain(key.ModShortcutAlt)
|
||||
selAct := selectionClear
|
||||
if k.Modifiers.Contain(key.ModShift) {
|
||||
selAct = selectionExtend
|
||||
@@ -465,15 +459,9 @@ func (e *Editor) command(gtx layout.Context, k key.Event) bool {
|
||||
// Initiate a paste operation, by requesting the clipboard contents; other
|
||||
// half is in Editor.processKey() under clipboard.Event.
|
||||
case "V":
|
||||
if k.Modifiers != key.ModShortcut {
|
||||
return false
|
||||
}
|
||||
clipboard.ReadOp{Tag: &e.eventKey}.Add(gtx.Ops)
|
||||
// Copy or Cut selection -- ignored if nothing selected.
|
||||
case "C", "X":
|
||||
if k.Modifiers != key.ModShortcut {
|
||||
return false
|
||||
}
|
||||
if text := e.SelectedText(); text != "" {
|
||||
clipboard.WriteOp{Text: text}.Add(gtx.Ops)
|
||||
if k.Name == "X" {
|
||||
@@ -482,15 +470,9 @@ func (e *Editor) command(gtx layout.Context, k key.Event) bool {
|
||||
}
|
||||
// Select all
|
||||
case "A":
|
||||
if k.Modifiers != key.ModShortcut {
|
||||
return false
|
||||
}
|
||||
e.caret.end = 0
|
||||
e.caret.start = e.Len()
|
||||
default:
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Focus requests the input focus for the Editor.
|
||||
@@ -625,7 +607,8 @@ func (e *Editor) layout(gtx layout.Context, content layout.Widget) layout.Dimens
|
||||
|
||||
defer clip.Rect(image.Rectangle{Max: e.viewSize}).Push(gtx.Ops).Pop()
|
||||
pointer.CursorText.Add(gtx.Ops)
|
||||
key.InputOp{Tag: &e.eventKey, Hint: e.InputHint}.Add(gtx.Ops)
|
||||
const keyFilter = "(Short)-(Shift)-[←,→,↑,↓]|(Shift)-[⏎,⌤]|(Short)-(Shift)-[⌫,⌦]|(Shift)-[⇞,⇟,⇱,⇲]|Short-[C,V,X,A]"
|
||||
key.InputOp{Tag: &e.eventKey, Hint: e.InputHint, Keys: keyFilter}.Add(gtx.Ops)
|
||||
if e.requestFocus {
|
||||
key.FocusOp{Tag: &e.eventKey}.Add(gtx.Ops)
|
||||
key.SoftKeyboardOp{Show: true}.Add(gtx.Ops)
|
||||
|
||||
+1
-1
@@ -120,7 +120,7 @@ func (e *Enum) Layout(gtx layout.Context, k string, content layout.Widget) layou
|
||||
clk.Add(gtx.Ops)
|
||||
disabled := gtx.Queue == nil
|
||||
if !disabled {
|
||||
key.InputOp{Tag: &state.tag}.Add(gtx.Ops)
|
||||
key.InputOp{Tag: &state.tag, Keys: "⏎|Space"}.Add(gtx.Ops)
|
||||
} else if e.focus == k {
|
||||
e.focused = false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user