io/event: move event types from package ui to its own package

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2019-09-30 15:13:25 +02:00
parent 7a259e68f7
commit e7a97bf176
16 changed files with 107 additions and 94 deletions
+1 -1
View File
@@ -57,7 +57,7 @@ For example, to display a blank but otherwise functional window:
Event queue
A Window's Queue method returns an ui.Queue implementation that distributes
A Window's Queue method returns an event.Queue implementation that distributes
incoming events to the event handlers declared in the latest call to Update.
See the gioui.org/ui package for more information about event handlers.
+9 -8
View File
@@ -5,6 +5,7 @@ package input
import (
"gioui.org/internal/opconst"
"gioui.org/internal/ops"
"gioui.org/io/event"
"gioui.org/io/key"
"gioui.org/ui"
)
@@ -12,8 +13,8 @@ import (
type TextInputState uint8
type keyQueue struct {
focus ui.Key
handlers map[ui.Key]*keyHandler
focus event.Key
handlers map[event.Key]*keyHandler
reader ops.Reader
state TextInputState
}
@@ -45,7 +46,7 @@ func (q *keyQueue) InputState() TextInputState {
func (q *keyQueue) Frame(root *ui.Ops, events *handlerEvents) {
if q.handlers == nil {
q.handlers = make(map[ui.Key]*keyHandler)
q.handlers = make(map[event.Key]*keyHandler)
}
for _, h := range q.handlers {
h.active = false
@@ -82,14 +83,14 @@ func (q *keyQueue) Frame(root *ui.Ops, events *handlerEvents) {
}
}
func (q *keyQueue) Push(e ui.Event, events *handlerEvents) {
func (q *keyQueue) Push(e event.Event, events *handlerEvents) {
if q.focus != nil {
events.Add(q.focus, e)
}
}
func (q *keyQueue) resolveFocus(events *handlerEvents) (ui.Key, listenerPriority, bool) {
var k ui.Key
func (q *keyQueue) resolveFocus(events *handlerEvents) (event.Key, listenerPriority, bool) {
var k event.Key
var pri listenerPriority
var hide bool
loop:
@@ -115,7 +116,7 @@ loop:
h = new(keyHandler)
q.handlers[op.Key] = h
// Reset the handler on (each) first appearance.
events.Set(op.Key, []ui.Event{key.FocusEvent{Focus: false}})
events.Set(op.Key, []event.Event{key.FocusEvent{Focus: false}})
}
h.active = true
case opconst.TypeHideInput:
@@ -144,6 +145,6 @@ func decodeKeyInputOp(d []byte, refs []interface{}) key.InputOp {
}
return key.InputOp{
Focus: d[1] != 0,
Key: refs[0].(ui.Key),
Key: refs[0].(event.Key),
}
}
+10 -9
View File
@@ -9,6 +9,7 @@ import (
"gioui.org/f32"
"gioui.org/internal/opconst"
"gioui.org/internal/ops"
"gioui.org/io/event"
"gioui.org/io/pointer"
"gioui.org/ui"
)
@@ -16,10 +17,10 @@ import (
type pointerQueue struct {
hitTree []hitNode
areas []areaNode
handlers map[ui.Key]*pointerHandler
handlers map[event.Key]*pointerHandler
pointers []pointerInfo
reader ops.Reader
scratch []ui.Key
scratch []event.Key
}
type hitNode struct {
@@ -29,13 +30,13 @@ type hitNode struct {
pass bool
// For handler nodes.
key ui.Key
key event.Key
}
type pointerInfo struct {
id pointer.ID
pressed bool
handlers []ui.Key
handlers []event.Key
}
type pointerHandler struct {
@@ -100,7 +101,7 @@ func (q *pointerQueue) collectHandlers(r *ops.Reader, events *handlerEvents, t u
if !ok {
h = new(pointerHandler)
q.handlers[op.Key] = h
events.Set(op.Key, []ui.Event{pointer.Event{Type: pointer.Cancel}})
events.Set(op.Key, []event.Event{pointer.Event{Type: pointer.Cancel}})
}
h.active = true
h.area = area
@@ -110,7 +111,7 @@ func (q *pointerQueue) collectHandlers(r *ops.Reader, events *handlerEvents, t u
}
}
func (q *pointerQueue) opHit(handlers *[]ui.Key, pos f32.Point) {
func (q *pointerQueue) opHit(handlers *[]event.Key, pos f32.Point) {
// Track whether we're passing through hits.
pass := true
idx := len(q.hitTree) - 1
@@ -153,7 +154,7 @@ func (a *areaNode) hit(p f32.Point) bool {
func (q *pointerQueue) init() {
if q.handlers == nil {
q.handlers = make(map[ui.Key]*pointerHandler)
q.handlers = make(map[event.Key]*pointerHandler)
}
}
@@ -175,7 +176,7 @@ func (q *pointerQueue) Frame(root *ui.Ops, events *handlerEvents) {
}
}
func (q *pointerQueue) dropHandler(k ui.Key) {
func (q *pointerQueue) dropHandler(k event.Key) {
for i := range q.pointers {
p := &q.pointers[i]
for i := len(p.handlers) - 1; i >= 0; i-- {
@@ -319,7 +320,7 @@ func decodePointerInputOp(d []byte, refs []interface{}) pointer.InputOp {
}
return pointer.InputOp{
Grab: d[1] != 0,
Key: refs[0].(ui.Key),
Key: refs[0].(event.Key),
}
}
+10 -9
View File
@@ -8,6 +8,7 @@ import (
"gioui.org/internal/opconst"
"gioui.org/internal/ops"
"gioui.org/io/event"
"gioui.org/io/key"
"gioui.org/io/pointer"
"gioui.org/io/profile"
@@ -38,15 +39,15 @@ type Router struct {
wakeupTime time.Time
// ProfileOp summary.
profHandlers []ui.Key
profHandlers []event.Key
}
type handlerEvents struct {
handlers map[ui.Key][]ui.Event
handlers map[event.Key][]event.Event
hadEvents bool
}
func (q *Router) Events(k ui.Key) []ui.Event {
func (q *Router) Events(k event.Key) []event.Event {
events := q.handlers.Events(k)
q.deliveredEvents = q.deliveredEvents || len(events) > 0
return events
@@ -68,7 +69,7 @@ func (q *Router) Frame(ops *ui.Ops) {
}
}
func (q *Router) Add(e ui.Event) bool {
func (q *Router) Add(e event.Event) bool {
switch e := e.(type) {
case pointer.Event:
q.pqueue.Push(e, &q.handlers)
@@ -114,17 +115,17 @@ func (q *Router) WakeupTime() (time.Time, bool) {
func (h *handlerEvents) init() {
if h.handlers == nil {
h.handlers = make(map[ui.Key][]ui.Event)
h.handlers = make(map[event.Key][]event.Event)
}
}
func (h *handlerEvents) Set(k ui.Key, evts []ui.Event) {
func (h *handlerEvents) Set(k event.Key, evts []event.Event) {
h.init()
h.handlers[k] = evts
h.hadEvents = true
}
func (h *handlerEvents) Add(k ui.Key, e ui.Event) {
func (h *handlerEvents) Add(k event.Key, e event.Event) {
h.init()
h.handlers[k] = append(h.handlers[k], e)
h.hadEvents = true
@@ -136,7 +137,7 @@ func (h *handlerEvents) HadEvents() bool {
return u
}
func (h *handlerEvents) Events(k ui.Key) []ui.Event {
func (h *handlerEvents) Events(k event.Key) []event.Event {
if events, ok := h.handlers[k]; ok {
h.handlers[k] = h.handlers[k][:0]
return events
@@ -155,7 +156,7 @@ func decodeProfileOp(d []byte, refs []interface{}) profile.Op {
panic("invalid op")
}
return profile.Op{
Key: refs[0].(ui.Key),
Key: refs[0].(event.Key),
}
}
+11 -10
View File
@@ -10,6 +10,7 @@ import (
"gioui.org/app/internal/gpu"
"gioui.org/app/internal/input"
"gioui.org/io/event"
"gioui.org/io/profile"
"gioui.org/ui"
)
@@ -31,8 +32,8 @@ type Window struct {
drawStart time.Time
gpu *gpu.GPU
out chan ui.Event
in chan ui.Event
out chan event.Event
in chan event.Event
ack chan struct{}
invalidates chan struct{}
frames chan *ui.Ops
@@ -46,7 +47,7 @@ type Window struct {
queue Queue
}
// Queue is an ui.Queue implementation that distributes system events
// Queue is an event.Queue implementation that distributes system events
// to the input handlers declared in the most recent call to Update.
type Queue struct {
q input.Router
@@ -69,7 +70,7 @@ var _ interface {
} = (*window)(nil)
// Pre-allocate the ack event to avoid garbage.
var ackEvent ui.Event
var ackEvent event.Event
// NewWindow creates a new window for a set of window
// options. The options are hints; the platform is free to
@@ -94,8 +95,8 @@ func NewWindow(options ...WindowOption) *Window {
}
w := &Window{
in: make(chan ui.Event),
out: make(chan ui.Event),
in: make(chan event.Event),
out: make(chan event.Event),
ack: make(chan struct{}),
invalidates: make(chan struct{}, 1),
frames: make(chan *ui.Ops),
@@ -105,7 +106,7 @@ func NewWindow(options ...WindowOption) *Window {
}
// Events returns the channel where events are delivered.
func (w *Window) Events() <-chan ui.Event {
func (w *Window) Events() <-chan event.Event {
return w.out
}
@@ -194,7 +195,7 @@ func (w *Window) setDriver(d *window) {
w.event(driverEvent{d})
}
func (w *Window) event(e ui.Event) {
func (w *Window) event(e event.Event) {
w.in <- e
<-w.ack
}
@@ -311,7 +312,7 @@ func (w *Window) run(opts *windowOptions) {
w.out <- e2
w.ack <- struct{}{}
return
case ui.Event:
case event.Event:
if w.queue.q.Add(e2) {
w.setNextFrame(time.Time{})
w.updateAnimation()
@@ -323,7 +324,7 @@ func (w *Window) run(opts *windowOptions) {
}
}
func (q *Queue) Events(k ui.Key) []ui.Event {
func (q *Queue) Events(k event.Key) []event.Event {
return q.q.Events(k)
}
+3 -2
View File
@@ -14,6 +14,7 @@ import (
"gioui.org/f32"
"gioui.org/internal/fling"
"gioui.org/io/event"
"gioui.org/io/pointer"
"gioui.org/ui"
)
@@ -105,7 +106,7 @@ func (c *Click) State() ClickState {
}
// Events returns the next click event, if any.
func (c *Click) Events(q ui.Queue) []ClickEvent {
func (c *Click) Events(q event.Queue) []ClickEvent {
var events []ClickEvent
for _, evt := range q.Events(c) {
e, ok := evt.(pointer.Event)
@@ -154,7 +155,7 @@ func (s *Scroll) Stop() {
// Scroll detects the scrolling distance from the available events and
// ongoing fling gestures.
func (s *Scroll) Scroll(cfg ui.Config, q ui.Queue, axis Axis) int {
func (s *Scroll) Scroll(cfg ui.Config, q event.Queue, axis Axis) int {
if s.axis != axis {
s.axis = axis
return 0
+48
View File
@@ -0,0 +1,48 @@
// SPDX-License-Identifier: Unlicense OR MIT
/*
Package event contains the types for event handling.
The Queue interface is the protocol for receiving external events.
For example:
var queue event.Queue = ...
for _, e := range queue.Events(h) {
switch e.(type) {
...
}
}
In general, handlers must be declared before events become
available. Other packages such as pointer and key provide
the means for declaring handlers for specific event types.
The following example declares a handler ready for key input:
import gioui.org/io/key
ops := new(ui.Ops)
var h *Handler = ...
key.InputOp{Key: h}.Add(ops)
*/
package event
// Queue maps an event handler key to the events
// available to the handler.
type Queue interface {
// Events returns the available events for a
// Key.
Events(k Key) []Event
}
// Key is the stable identifier for an event handler.
// For a handler h, the key is typically &h.
type Key interface{}
// Event is the marker interface for events.
type Event interface {
ImplementsEvent()
}
+3 -2
View File
@@ -10,8 +10,9 @@ events.
package key
import (
"gioui.org/ui"
"gioui.org/internal/opconst"
"gioui.org/io/event"
"gioui.org/ui"
)
// InputOp declares a handler ready for key events.
@@ -19,7 +20,7 @@ import (
// focused key handler. Set the Focus flag to request
// the focus.
type InputOp struct {
Key ui.Key
Key event.Key
Focus bool
}
+1 -1
View File
@@ -6,7 +6,7 @@ A pointer is either a mouse controlled cursor or a touch
object such as a finger.
The InputOp operation is used to declare a handler ready for pointer
events. Use a ui.Queue to receive events.
events. Use an event.Queue to receive events.
Areas
+3 -2
View File
@@ -7,9 +7,10 @@ import (
"image"
"time"
"gioui.org/ui"
"gioui.org/f32"
"gioui.org/internal/opconst"
"gioui.org/io/event"
"gioui.org/ui"
)
// Event is a pointer event.
@@ -63,7 +64,7 @@ type areaOp struct {
// InputOp declares an input handler ready for pointer
// events.
type InputOp struct {
Key ui.Key
Key event.Key
// Grab, if set, request that the handler get
// Grabbed priority.
Grab bool
+2 -1
View File
@@ -6,13 +6,14 @@ package profile
import (
"gioui.org/internal/opconst"
"gioui.org/io/event"
"gioui.org/ui"
)
// Op registers a handler for receiving
// Events.
type Op struct {
Key ui.Key
Key event.Key
}
// Event contains profile data from a single
+2 -1
View File
@@ -5,6 +5,7 @@ package layout
import (
"image"
"gioui.org/io/event"
"gioui.org/ui"
)
@@ -51,7 +52,7 @@ type Context struct {
Dimensions Dimensions
ui.Config
ui.Queue
event.Queue
*ui.Ops
}
+2 -1
View File
@@ -5,6 +5,7 @@ import (
"image"
"time"
"gioui.org/io/event"
"gioui.org/layout"
"gioui.org/ui"
)
@@ -149,6 +150,6 @@ func (config) Px(v ui.Value) int {
return int(v.V + .5)
}
func (queue) Events(k ui.Key) []ui.Event {
func (queue) Events(k event.Key) []event.Event {
return nil
}
+2 -1
View File
@@ -10,6 +10,7 @@ import (
"unicode/utf8"
"gioui.org/gesture"
"gioui.org/io/event"
"gioui.org/io/key"
"gioui.org/io/pointer"
"gioui.org/layout"
@@ -64,7 +65,7 @@ type Editor struct {
clicker gesture.Click
// events is the list of events not yet processed.
events []ui.Event
events []event.Event
}
type EditorEvent interface {
-26
View File
@@ -81,31 +81,5 @@ To maintain a constant visual size across platforms and displays, always
use dps or sps to define user interfaces. Only use pixels for derived
values.
Events
The Queue interface is the protocol for receiving external events.
For example:
var queue ui.Queue = ...
for _, e := range queue.Events(h) {
switch e.(type) {
...
}
}
In general, handlers must be declared before events become
available. Other packages such as pointer and key provide
the means for declaring handlers for specific event types.
The following example declares a handler ready for key input:
import gioui.org/io/key
ops := new(ui.Ops)
var h *Handler = ...
key.InputOp{Key: h}.Add(ops)
*/
package ui
-20
View File
@@ -1,20 +0,0 @@
// SPDX-License-Identifier: Unlicense OR MIT
package ui
// Queue maps an event handler key to the events
// available to the handler.
type Queue interface {
// Events returns the available events for a
// Key.
Events(k Key) []Event
}
// Key is the stable identifier for an event handler.
// For a handler h, the key is typically &h.
type Key interface{}
// Event is the marker interface for events.
type Event interface {
ImplementsEvent()
}