all: replace InvalidateOp with InvalidateCmd command

Curiously, InvalidateCmd is probably the only command that is appropriate
to call during layout.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2023-11-25 13:57:15 -06:00
parent 0fab08bd6c
commit c515b7804e
9 changed files with 31 additions and 51 deletions
+2 -2
View File
@@ -339,8 +339,8 @@ func (w *Window) processFrame(d driver) {
// If the window is inactive, the event is sent when the window becomes active.
//
// Note that Invalidate is intended for externally triggered updates, such as a
// response from a network request. InvalidateOp is more efficient for animation
// and similar internal updates.
// response from a network request. The [op.InvalidateCmd] command is more efficient
// for animation.
//
// Invalidate is safe for concurrent use.
func (w *Window) Invalidate() {
+3 -3
View File
@@ -252,9 +252,6 @@ func (ClickEvent) ImplementsEvent() {}
// as defined in io/pointer.InputOp.
func (s *Scroll) Add(ops *op.Ops) {
event.InputOp(ops, s)
if s.flinger.Active() {
op.InvalidateOp{}.Add(ops)
}
}
// Stop any remaining fling movement.
@@ -336,6 +333,9 @@ func (s *Scroll) Update(cfg unit.Metric, q input.Source, t time.Time, axis Axis,
}
}
total += s.flinger.Tick(t)
if s.flinger.Active() {
q.Execute(op.InvalidateCmd{})
}
return total
}
-4
View File
@@ -55,7 +55,6 @@ const (
TypePopTransform
TypePushOpacity
TypePopOpacity
TypeInvalidate
TypeImage
TypePaint
TypeColor
@@ -405,7 +404,6 @@ var opProps = [0x100]opProp{
TypePopTransform: {Size: TypePopTransformLen, NumRefs: 0},
TypePushOpacity: {Size: TypePushOpacityLen, NumRefs: 0},
TypePopOpacity: {Size: TypePopOpacityLen, NumRefs: 0},
TypeInvalidate: {Size: TypeRedrawLen, NumRefs: 0},
TypeImage: {Size: TypeImageLen, NumRefs: 2},
TypePaint: {Size: TypePaintLen, NumRefs: 0},
TypeColor: {Size: TypeColorLen, NumRefs: 0},
@@ -459,8 +457,6 @@ func (t OpType) String() string {
return "PushOpacity"
case TypePopOpacity:
return "PopOpacity"
case TypeInvalidate:
return "Invalidate"
case TypeImage:
return "Image"
case TypePaint:
+9 -22
View File
@@ -3,7 +3,6 @@
package input
import (
"encoding/binary"
"image"
"io"
"strings"
@@ -44,7 +43,7 @@ type Router struct {
reader ops.Reader
// InvalidateOp summary.
// InvalidateCmd summary.
wakeup bool
wakeupTime time.Time
@@ -261,7 +260,6 @@ func (q *Router) Frame(frame *op.Ops) {
}
}
q.transfers = nil
q.wakeup = false
q.deferring = false
for _, h := range q.handlers {
h.filter, h.nextFilter = h.nextFilter, h.filter
@@ -470,6 +468,11 @@ func (q *Router) executeCommand(c Command) (event.Tag, stateChange) {
case pointer.GrabCmd:
tag = req.Tag
state.pointerState, evts = q.pointer.queue.grab(state.pointerState, req)
case op.InvalidateCmd:
if !q.wakeup || req.At.Before(q.wakeupTime) {
q.wakeup = true
q.wakeupTime = req.At
}
}
return tag, stateChange{state: state, events: evts}
}
@@ -727,12 +730,6 @@ func (q *Router) collect() {
var t f32.Affine2D
for encOp, ok := q.reader.Decode(); ok; encOp, ok = q.reader.Decode() {
switch ops.OpType(encOp.Data[0]) {
case ops.TypeInvalidate:
op := decodeInvalidateOp(encOp.Data)
if !q.wakeup || op.At.Before(q.wakeupTime) {
q.wakeup = true
q.wakeupTime = op.At
}
case ops.TypeSave:
id := ops.DecodeSave(encOp.Data)
if extra := id - len(q.savedTrans) + 1; extra > 0 {
@@ -822,19 +819,9 @@ func (q *Router) collect() {
// WakeupTime returns the most recent time for doing another frame,
// as determined from the last call to Frame.
func (q *Router) WakeupTime() (time.Time, bool) {
return q.wakeupTime, q.wakeup
}
func decodeInvalidateOp(d []byte) op.InvalidateOp {
bo := binary.LittleEndian
if ops.OpType(d[0]) != ops.TypeInvalidate {
panic("invalid op")
}
var o op.InvalidateOp
if nanos := bo.Uint64(d[1:]); nanos > 0 {
o.At = time.Unix(0, int64(nanos))
}
return o
w := q.wakeup
q.wakeup = false
return q.wakeupTime, w
}
func (s SemanticGestures) String() string {
+10
View File
@@ -6,6 +6,7 @@ import (
"testing"
"gioui.org/io/pointer"
"gioui.org/op"
)
func TestNoFilterAllocs(t *testing.T) {
@@ -22,3 +23,12 @@ func TestNoFilterAllocs(t *testing.T) {
t.Fatalf("expected 0 AllocsPerOp, got %d", allocs)
}
}
func TestRouterWakeup(t *testing.T) {
r := new(Router)
r.Source().Execute(op.InvalidateCmd{})
r.Frame(new(op.Ops))
if _, wake := r.WakeupTime(); !wake {
t.Errorf("InvalidateCmd did not trigger a redraw")
}
}
+4 -16
View File
@@ -53,7 +53,6 @@ The MacroOp records a list of operations to be executed later:
ops := new(op.Ops)
macro := op.Record(ops)
// Record operations by adding them.
op.InvalidateOp{}.Add(ops)
...
// End recording.
call := macro.Stop()
@@ -96,9 +95,9 @@ type CallOp struct {
end ops.PC
}
// InvalidateOp requests a redraw at the given time. Use
// InvalidateCmd requests a redraw at the given time. Use
// the zero value to request an immediate redraw.
type InvalidateOp struct {
type InvalidateCmd struct {
At time.Time
}
@@ -181,19 +180,6 @@ func (c CallOp) Add(o *Ops) {
ops.AddCall(&o.Internal, c.ops, c.start, c.end)
}
func (r InvalidateOp) Add(o *Ops) {
data := ops.Write(&o.Internal, ops.TypeRedrawLen)
data[0] = byte(ops.TypeInvalidate)
bo := binary.LittleEndian
// UnixNano cannot represent the zero time.
if t := r.At; !t.IsZero() {
nanos := t.UnixNano()
if nanos > 0 {
bo.PutUint64(data[1:], uint64(nanos))
}
}
}
// Offset converts an offset to a TransformOp.
func Offset(off image.Point) TransformOp {
offf := f32.Pt(float32(off.X), float32(off.Y))
@@ -240,3 +226,5 @@ func (t TransformStack) Pop() {
data := ops.Write(t.ops, ops.TypePopTransformLen)
data[0] = byte(ops.TypePopTransform)
}
func (InvalidateCmd) ImplementsCommand() {}
+1 -2
View File
@@ -692,8 +692,7 @@ func (e *Editor) layout(gtx layout.Context, textMaterial, selectMaterial op.Call
const timePerBlink = time.Second / blinksPerSecond
nextBlink := now.Add(timePerBlink/2 - dt%(timePerBlink/2))
if blinking {
redraw := op.InvalidateOp{At: nextBlink}
redraw.Add(gtx.Ops)
gtx.Execute(op.InvalidateCmd{At: nextBlink})
}
e.showCaret = e.focused && (!blinking || dt%timePerBlink < timePerBlink/2)
}
+1 -1
View File
@@ -258,7 +258,7 @@ func drawInk(gtx layout.Context, c widget.Press) {
// Animate only ended presses, and presses that are fading in.
if !c.End.IsZero() || sizet <= 1.0 {
op.InvalidateOp{}.Add(gtx.Ops)
gtx.Execute(op.InvalidateCmd{})
}
if sizet > 1.0 {
+1 -1
View File
@@ -47,7 +47,7 @@ func (l LoaderStyle) Layout(gtx layout.Context) layout.Dimensions {
}.Add(gtx.Ops)
defer op.Offset(image.Pt(-radius, -radius)).Push(gtx.Ops).Pop()
paint.PaintOp{}.Add(gtx.Ops)
op.InvalidateOp{}.Add(gtx.Ops)
gtx.Execute(op.InvalidateCmd{})
return layout.Dimensions{
Size: sz,
}