ui/input/system: introduce package for system events

And add ProfileOp and ProfileEvent for registering and receiving
profile data.

Remove the Profiling field and Timings method from app.Window.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2019-07-12 15:31:29 +02:00
parent 032e9a380e
commit 86533ae683
4 changed files with 70 additions and 11 deletions
+20
View File
@@ -7,6 +7,7 @@ import (
"gioui.org/ui"
"gioui.org/ui/input"
"gioui.org/ui/input/system"
"gioui.org/ui/internal/ops"
"gioui.org/ui/key"
"gioui.org/ui/pointer"
@@ -21,9 +22,13 @@ type Router struct {
handlers handlerEvents
reader ui.OpsReader
// InvalidateOp summary.
redraw bool
redrawTime time.Time
// ProfileOp summary.
profHandlers []input.Key
}
type handlerEvents struct {
@@ -38,6 +43,7 @@ func (q *Router) Events(k input.Key) []input.Event {
func (q *Router) Frame(ops *ui.Ops) {
q.handlers.Clear()
q.redraw = false
q.profHandlers = q.profHandlers[:0]
q.reader.Reset(ops)
q.collect()
@@ -69,10 +75,24 @@ func (q *Router) collect() {
q.redraw = true
q.redrawTime = op.At
}
case ops.TypeProfile:
var op system.ProfileOp
op.Decode(encOp.Data, encOp.Refs)
q.profHandlers = append(q.profHandlers, op.Key)
}
}
}
func (q *Router) AddProfile(e system.ProfileEvent) {
for _, h := range q.profHandlers {
q.handlers.Add(h, e)
}
}
func (q *Router) Profiling() bool {
return len(q.profHandlers) > 0
}
func (q *Router) RedrawTime() (time.Time, bool) {
return q.redrawTime, q.redraw
}
+5 -10
View File
@@ -13,6 +13,7 @@ import (
"gioui.org/ui/app/internal/gpu"
iinput "gioui.org/ui/app/internal/input"
"gioui.org/ui/input"
"gioui.org/ui/input/system"
"gioui.org/ui/key"
)
@@ -23,13 +24,10 @@ type WindowOptions struct {
}
type Window struct {
Profiling bool
driver *window
lastFrame time.Time
drawStart time.Time
gpu *gpu.GPU
timings string
inputState key.TextInputState
err error
@@ -74,10 +72,6 @@ func (w *Window) Events() <-chan Event {
return w.events
}
func (w *Window) Timings() string {
return w.timings
}
func (w *Window) setTextInput(s key.TextInputState) {
if s != w.inputState && (s == key.TextInputClose || s == key.TextInputOpen) {
w.driver.setTextInput(s)
@@ -134,7 +128,7 @@ func (w *Window) Draw(root *ui.Ops) {
return
}
}
w.gpu.Draw(w.Profiling, size, root)
w.gpu.Draw(w.router.Profiling(), size, root)
w.router.Frame(root)
now := time.Now()
w.mu.Lock()
@@ -142,9 +136,10 @@ func (w *Window) Draw(root *ui.Ops) {
frameDur := now.Sub(w.lastFrame)
frameDur = frameDur.Truncate(100 * time.Microsecond)
w.lastFrame = now
if w.Profiling {
if w.router.Profiling() {
q := 100 * time.Microsecond
w.timings = fmt.Sprintf("tot:%7s cpu:%7s %s", frameDur.Round(q), drawDur.Round(q), w.gpu.Timings())
timings := fmt.Sprintf("tot:%7s cpu:%7s %s", frameDur.Round(q), drawDur.Round(q), w.gpu.Timings())
w.router.AddProfile(system.ProfileEvent{Timings: timings})
w.setNextFrame(time.Time{})
}
if t, ok := w.router.RedrawTime(); ok {
+41
View File
@@ -0,0 +1,41 @@
// SPDX-License-Identifier: Unlicense OR MIT
// Package system contain ops and types for
// system events.
package system
import (
"gioui.org/ui"
"gioui.org/ui/input"
"gioui.org/ui/internal/ops"
)
// ProfileOp registers a handler for receiving
// ProfileEvents.
type ProfileOp struct {
Key input.Key
}
// ProfileEvent contain profile data from a single
// rendered frame.
type ProfileEvent struct {
// String with timings. Very likely to change.
Timings string
}
func (p ProfileOp) Add(o *ui.Ops) {
data := make([]byte, ops.TypeProfileLen)
data[0] = byte(ops.TypeProfile)
o.Write(data, p.Key)
}
func (p *ProfileOp) Decode(d []byte, refs []interface{}) {
if ops.OpType(d[0]) != ops.TypeProfile {
panic("invalid op")
}
*p = ProfileOp{
Key: refs[0].(input.Key),
}
}
func (p ProfileEvent) ImplementsInputEvent() {}
+4 -1
View File
@@ -23,6 +23,7 @@ const (
TypePop
TypeAux
TypeClip
TypeProfile
)
const (
@@ -43,6 +44,7 @@ const (
TypePopLen = 1
TypeAuxLen = 1 + 4
TypeClipLen = 1 + 4*4
TypeProfileLen = 1
)
func (t OpType) Size() int {
@@ -64,12 +66,13 @@ func (t OpType) Size() int {
TypePopLen,
TypeAuxLen,
TypeClipLen,
TypeProfileLen,
}[t-firstOpIndex]
}
func (t OpType) NumRefs() int {
switch t {
case TypeBlock, TypeImage, TypeKeyHandler, TypePointerHandler:
case TypeBlock, TypeImage, TypeKeyHandler, TypePointerHandler, TypeProfile:
return 1
default:
return 0