diff --git a/app/app.go b/app/app.go index 071de092..3cf90e44 100644 --- a/app/app.go +++ b/app/app.go @@ -9,7 +9,7 @@ import ( "strings" "time" - "gioui.org/io/event" + "gioui.org/io/input" "gioui.org/layout" "gioui.org/op" "gioui.org/unit" @@ -53,8 +53,8 @@ type FrameEvent struct { // Frame completes the FrameEvent by drawing the graphical operations // from ops into the window. Frame func(frame *op.Ops) - // Source supplies the events for event handlers. - Source event.Queue + // Source is the interface between the interface state and widgets. + Source input.Source } // Insets is the space taken up by diff --git a/app/ime_test.go b/app/ime_test.go index c939a375..f0fb511a 100644 --- a/app/ime_test.go +++ b/app/ime_test.go @@ -34,7 +34,7 @@ func FuzzIME(f *testing.F) { e.Focus() var r input.Router - gtx := layout.Context{Ops: new(op.Ops), Source: &r} + gtx := layout.Context{Ops: new(op.Ops), Source: r.Source()} // Layout once to register focus. e.Layout(gtx, cache, font.Font{}, unit.Sp(10), op.CallOp{}, op.CallOp{}) r.Frame(gtx.Ops) diff --git a/app/window.go b/app/window.go index 440b9c96..dd5128b8 100644 --- a/app/window.go +++ b/app/window.go @@ -832,7 +832,7 @@ func (w *Window) processEvent(d driver, e event.Event) bool { w.metric = e2.Metric w.hasNextFrame = false e2.Frame = w.update - e2.Source = &w.queue + e2.Source = w.queue.Source() // Prepare the decorations and update the frame insets. wrapper := &w.decorations.Ops diff --git a/gesture/gesture.go b/gesture/gesture.go index 2676d0bf..e6770551 100644 --- a/gesture/gesture.go +++ b/gesture/gesture.go @@ -17,7 +17,7 @@ import ( "gioui.org/f32" "gioui.org/internal/fling" - "gioui.org/io/event" + "gioui.org/io/input" "gioui.org/io/key" "gioui.org/io/pointer" "gioui.org/op" @@ -44,7 +44,7 @@ func (h *Hover) Add(ops *op.Ops) { } // Update state and report whether a pointer is inside the area. -func (h *Hover) Update(q event.Queue) bool { +func (h *Hover) Update(q input.Source) bool { for _, ev := range q.Events(h) { e, ok := ev.(pointer.Event) if !ok { @@ -178,7 +178,7 @@ func (c *Click) Pressed() bool { } // Update state and return the click events. -func (c *Click) Update(q event.Queue) []ClickEvent { +func (c *Click) Update(q input.Source) []ClickEvent { var events []ClickEvent for _, evt := range q.Events(c) { e, ok := evt.(pointer.Event) @@ -269,7 +269,7 @@ func (s *Scroll) Stop() { } // Update state and report the scroll distance along axis. -func (s *Scroll) Update(cfg unit.Metric, q event.Queue, t time.Time, axis Axis) int { +func (s *Scroll) Update(cfg unit.Metric, q input.Source, t time.Time, axis Axis) int { if s.axis != axis { s.axis = axis return 0 @@ -372,7 +372,7 @@ func (d *Drag) Add(ops *op.Ops) { } // Update state and return the drag events. -func (d *Drag) Update(cfg unit.Metric, q event.Queue, axis Axis) []pointer.Event { +func (d *Drag) Update(cfg unit.Metric, q input.Source, axis Axis) []pointer.Event { var events []pointer.Event for _, e := range q.Events(d) { e, ok := e.(pointer.Event) diff --git a/gesture/gesture_test.go b/gesture/gesture_test.go index 27b95f9e..0bef2a07 100644 --- a/gesture/gesture_test.go +++ b/gesture/gesture_test.go @@ -28,14 +28,14 @@ func TestHover(t *testing.T) { r.Queue( pointer.Event{Kind: pointer.Move, Position: f32.Pt(30, 30)}, ) - if !h.Update(r) { + if !h.Update(r.Source()) { t.Fatal("expected hovered") } r.Queue( pointer.Event{Kind: pointer.Move, Position: f32.Pt(50, 50)}, ) - if h.Update(r) { + if h.Update(r.Source()) { t.Fatal("expected not hovered") } } @@ -75,7 +75,7 @@ func TestMouseClicks(t *testing.T) { r.Frame(&ops) r.Queue(tc.events...) - events := click.Update(&r) + events := click.Update(r.Source()) clicks := filterMouseClicks(events) if got, want := len(clicks), len(tc.clicks); got != want { t.Fatalf("got %d mouse clicks, expected %d", got, want) diff --git a/io/event/event.go b/io/event/event.go index 7a6751f5..c664d63a 100644 --- a/io/event/event.go +++ b/io/event/event.go @@ -1,42 +1,8 @@ // 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(op.Ops) - var h *Handler = ... - key.InputOp{Tag: h, Filter: ...}.Add(ops) -*/ +// Package event contains types for event handling. package event -// Queue maps an event handler key to the events -// available to the handler. -type Queue interface { - // Events returns the available events for an - // event handler tag. - Events(t Tag) []Event -} - // Tag is the stable identifier for an event handler. // For a handler h, the tag is typically &h. type Tag interface{} diff --git a/io/input/doc.go b/io/input/doc.go new file mode 100644 index 00000000..c0295763 --- /dev/null +++ b/io/input/doc.go @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: Unlicense OR MIT + +/* +Package input implements input routing and tracking of interface +state for a window. + +The [Source] is the interface between the window and the widgets +of a user interface and is exposed by [gioui.org/app.FrameEvent] +received from windows. + +The [Router] is used by [gioui.org/app.Window] to track window state and route +events from the platform to event handlers. It is otherwise only +useful for using Gio with external window implementations. +*/ +package input diff --git a/io/input/router.go b/io/input/router.go index fb8fcf3f..6c07c716 100644 --- a/io/input/router.go +++ b/io/input/router.go @@ -1,13 +1,5 @@ // SPDX-License-Identifier: Unlicense OR MIT -/* -Package input implements Router, an event.Queue implementation -that disambiguates and routes events to handlers declared -in operation lists. - -Router is used by app.Window and is otherwise only useful for -using Gio with external window implementations. -*/ package input import ( @@ -31,8 +23,8 @@ import ( "gioui.org/op" ) -// Router is a Queue implementation that routes events -// to handlers declared in operation lists. +// Router tracks the [io/event.Tag] identifiers of user interface widgets +// and routes events to them. [Source] is its interface exposed to widgets. type Router struct { savedTrans []f32.Affine2D transStack []f32.Affine2D @@ -55,6 +47,12 @@ type Router struct { wakeupTime time.Time } +// Source implements the interface between a Router and user interface widgets. +// The value Source is disabled. +type Source struct { + r *Router +} + // SemanticNode represents a node in the tree describing the components // contained in a frame. type SemanticNode struct { @@ -95,7 +93,25 @@ type handlerEvents struct { hadEvents bool } -// Events returns the available events for the handler key. +// Source returns a Source backed by this Router. +func (q *Router) Source() Source { + return Source{r: q} +} + +// Enabled reports whether the source is enabled. Only enabled +// Sources deliver events and respond to commands. +func (s Source) Enabled() bool { + return s.r != nil +} + +// Events returns the available events for the handler tag. +func (s Source) Events(k event.Tag) []event.Event { + if !s.Enabled() { + return nil + } + return s.r.Events(k) +} + func (q *Router) Events(k event.Tag) []event.Event { events := q.handlers.Events(k) return events diff --git a/layout/context.go b/layout/context.go index 4cbb7eaa..58ee4f86 100644 --- a/layout/context.go +++ b/layout/context.go @@ -5,7 +5,7 @@ package layout import ( "time" - "gioui.org/io/event" + "gioui.org/io/input" "gioui.org/io/system" "gioui.org/op" "gioui.org/unit" @@ -20,9 +20,6 @@ type Context struct { Constraints Constraints Metric unit.Metric - // By convention, a nil Source is a signal to widgets to draw themselves - // in a disabled state. - Source event.Queue // Now is the animation time. Now time.Time @@ -31,6 +28,7 @@ type Context struct { // Interested users must look up and populate these values manually. Locale system.Locale + input.Source *op.Ops } @@ -44,21 +42,9 @@ func (c Context) Sp(v unit.Sp) int { return c.Metric.Sp(v) } -// Events returns the events available for the key. If no -// queue is configured, Events returns nil. -func (c Context) Events(k event.Tag) []event.Event { - if c.Source == nil { - return nil - } - return c.Source.Events(k) -} - -// Disabled returns a copy of this context with a nil Queue, -// blocking events to widgets using it. -// -// By convention, a nil Queue is a signal to widgets to draw themselves -// in a disabled state. +// Disabled returns a copy of this context with a disabled Source, +// blocking widgets from changing its state and receiving events. func (c Context) Disabled() Context { - c.Source = nil + c.Source = input.Source{} return c } diff --git a/layout/list.go b/layout/list.go index 22915e7c..9d8c568c 100644 --- a/layout/list.go +++ b/layout/list.go @@ -144,7 +144,7 @@ func (l *List) Dragging() bool { } func (l *List) update(gtx Context) { - d := l.scroll.Update(gtx.Metric, gtx, gtx.Now, gesture.Axis(l.Axis)) + d := l.scroll.Update(gtx.Metric, gtx.Source, gtx.Now, gesture.Axis(l.Axis)) l.scrollDelta = d l.Position.Offset += d } diff --git a/layout/list_test.go b/layout/list_test.go index 65fcc8ef..ad0163f0 100644 --- a/layout/list_test.go +++ b/layout/list_test.go @@ -70,7 +70,7 @@ func TestListPosition(t *testing.T) { Constraints: Constraints{ Max: image.Pt(20, 10), }, - Source: r, + Source: r.Source(), } el := func(gtx Context, idx int) Dimensions { return Dimensions{Size: image.Pt(10, 10)} diff --git a/widget/bool.go b/widget/bool.go index dfed65f6..00c559a1 100644 --- a/widget/bool.go +++ b/widget/bool.go @@ -46,7 +46,7 @@ func (b *Bool) Layout(gtx layout.Context, w layout.Widget) layout.Dimensions { b.Update(gtx) dims := b.clk.Layout(gtx, func(gtx layout.Context) layout.Dimensions { semantic.SelectedOp(b.Value).Add(gtx.Ops) - semantic.EnabledOp(gtx.Source != nil).Add(gtx.Ops) + semantic.EnabledOp(gtx.Enabled()).Add(gtx.Ops) return w(gtx) }) return dims diff --git a/widget/button.go b/widget/button.go index 4c3ba365..1f956bc5 100644 --- a/widget/button.go +++ b/widget/button.go @@ -101,10 +101,9 @@ func (b *Clickable) Layout(gtx layout.Context, w layout.Widget) layout.Dimension dims := w(gtx) c := m.Stop() defer clip.Rect(image.Rectangle{Max: dims.Size}).Push(gtx.Ops).Pop() - enabled := gtx.Source != nil - semantic.EnabledOp(enabled).Add(gtx.Ops) + semantic.EnabledOp(gtx.Enabled()).Add(gtx.Ops) b.click.Add(gtx.Ops) - if enabled { + if gtx.Enabled() { keys := key.Set("⏎|Space") if !b.focused { keys = "" @@ -119,7 +118,7 @@ func (b *Clickable) Layout(gtx layout.Context, w layout.Widget) layout.Dimension // clicks, if any. func (b *Clickable) Update(gtx layout.Context) []Click { b.clicks = nil - if gtx.Source == nil { + if !gtx.Enabled() { b.focused = false } if b.requestFocus { @@ -141,7 +140,7 @@ func (b *Clickable) Update(gtx layout.Context) []Click { NumClicks: c, }) } - for _, e := range b.click.Update(gtx) { + for _, e := range b.click.Update(gtx.Source) { switch e.Kind { case gesture.KindClick: if l := len(b.history); l > 0 { diff --git a/widget/button_test.go b/widget/button_test.go index fd18684c..92c9e3f9 100644 --- a/widget/button_test.go +++ b/widget/button_test.go @@ -21,7 +21,7 @@ func TestClickable(t *testing.T) { b1 widget.Clickable b2 widget.Clickable ) - gtx := app.NewContext(&ops, app.FrameEvent{Source: &r}) + gtx := app.NewContext(&ops, app.FrameEvent{Source: r.Source()}) layout := func() { b1.Layout(gtx, func(gtx layout.Context) layout.Dimensions { return layout.Dimensions{Size: image.Pt(100, 100)} diff --git a/widget/dnd.go b/widget/dnd.go index 84027359..48fc559b 100644 --- a/widget/dnd.go +++ b/widget/dnd.go @@ -24,7 +24,7 @@ type Draggable struct { } func (d *Draggable) Layout(gtx layout.Context, w, drag layout.Widget) layout.Dimensions { - if gtx.Source == nil { + if !gtx.Enabled() { return w(gtx) } dims := w(gtx) diff --git a/widget/dnd_test.go b/widget/dnd_test.go index d5474c52..3c106376 100644 --- a/widget/dnd_test.go +++ b/widget/dnd_test.go @@ -17,7 +17,7 @@ func TestDraggable(t *testing.T) { var r input.Router gtx := layout.Context{ Constraints: layout.Exact(image.Pt(100, 100)), - Source: &r, + Source: r.Source(), Ops: new(op.Ops), } diff --git a/widget/editor.go b/widget/editor.go index 1e6b1a7d..6937d3e3 100644 --- a/widget/editor.go +++ b/widget/editor.go @@ -225,7 +225,7 @@ func (e *Editor) processPointer(gtx layout.Context) { axis = gesture.Vertical smin, smax = sbounds.Min.Y, sbounds.Max.Y } - sdist := e.scroller.Update(gtx.Metric, gtx, gtx.Now, axis) + sdist := e.scroller.Update(gtx.Metric, gtx.Source, gtx.Now, axis) var soff int if e.SingleLine { e.text.ScrollRel(sdist, 0) @@ -305,10 +305,10 @@ func (e *Editor) processPointer(gtx layout.Context) { func (e *Editor) clickDragEvents(gtx layout.Context) []event.Event { var combinedEvents []event.Event - for _, evt := range e.clicker.Update(gtx) { + for _, evt := range e.clicker.Update(gtx.Source) { combinedEvents = append(combinedEvents, evt) } - for _, evt := range e.dragger.Update(gtx.Metric, gtx, gesture.Both) { + for _, evt := range e.dragger.Update(gtx.Metric, gtx.Source, gesture.Both) { combinedEvents = append(combinedEvents, evt) } return combinedEvents @@ -677,14 +677,12 @@ func (e *Editor) layout(gtx layout.Context, textMaterial, selectMaterial op.Call } e.showCaret = e.focused && (!blinking || dt%timePerBlink < timePerBlink/2) } - disabled := gtx.Source == nil - semantic.Editor.Add(gtx.Ops) if e.Len() > 0 { e.paintSelection(gtx, selectMaterial) e.paintText(gtx, textMaterial) } - if !disabled { + if gtx.Enabled() { e.paintCaret(gtx, textMaterial) } return visibleDims diff --git a/widget/editor_test.go b/widget/editor_test.go index a13a907c..fba25455 100644 --- a/widget/editor_test.go +++ b/widget/editor_test.go @@ -103,7 +103,7 @@ func TestEditorReadOnly(t *testing.T) { Max: image.Pt(100, 100), }, Locale: english, - Source: r, + Source: r.Source(), } cache := text.NewShaper(text.NoSystemFonts(), text.WithCollection(gofont.Collection())) fontSize := unit.Sp(10) @@ -505,7 +505,7 @@ func TestEditorDimensions(t *testing.T) { gtx := layout.Context{ Ops: new(op.Ops), Constraints: layout.Constraints{Max: image.Pt(100, 100)}, - Source: r, + Source: r.Source(), Locale: english, } cache := text.NewShaper(text.NoSystemFonts(), text.WithCollection(gofont.Collection())) @@ -891,7 +891,7 @@ g 2 4 6 8 g gtx := layout.Context{ Ops: new(op.Ops), Locale: english, - Source: r, + Source: r.Source(), } cache := text.NewShaper(text.NoSystemFonts(), text.WithCollection(gofont.Collection())) font := font.Font{} @@ -900,13 +900,13 @@ g 2 4 6 8 g var tim time.Duration selected := func(start, end int) string { // Layout once with no events; populate e.lines. - gtx.Source = nil + gtx = gtx.Disabled() e.Layout(gtx, cache, font, fontSize, op.CallOp{}, op.CallOp{}) e.Events() // throw away any events from this layout e.Focus() r.Frame(gtx.Ops) - gtx.Source = r + gtx.Source = r.Source() // Build the selection events startPos := e.text.closestToRune(start) endPos := e.text.closestToRune(end) @@ -972,7 +972,7 @@ g 2 4 6 8 g // Constrain the editor to roughly 6 columns wide and redraw gtx.Constraints = layout.Exact(image.Pt(36, 36)) // Keep existing selection - gtx.Source = nil + gtx = gtx.Disabled() e.Layout(gtx, cache, font, fontSize, op.CallOp{}, op.CallOp{}) caretStart := e.text.closestToRune(e.text.caret.start) @@ -991,7 +991,7 @@ func TestSelectMove(t *testing.T) { gtx := layout.Context{ Ops: new(op.Ops), Locale: english, - Source: r, + Source: r.Source(), } cache := text.NewShaper(text.NoSystemFonts(), text.WithCollection(gofont.Collection())) font := font.Font{} @@ -1080,7 +1080,7 @@ func TestEditor_MaxLen(t *testing.T) { gtx := layout.Context{ Ops: new(op.Ops), Constraints: layout.Exact(image.Pt(100, 100)), - Source: r, + Source: r.Source(), } cache := text.NewShaper(text.NoSystemFonts(), text.WithCollection(gofont.Collection())) fontSize := unit.Sp(10) @@ -1116,7 +1116,7 @@ func TestEditor_Filter(t *testing.T) { gtx := layout.Context{ Ops: new(op.Ops), Constraints: layout.Exact(image.Pt(100, 100)), - Source: r, + Source: r.Source(), } cache := text.NewShaper(text.NoSystemFonts(), text.WithCollection(gofont.Collection())) fontSize := unit.Sp(10) @@ -1146,7 +1146,7 @@ func TestEditor_Submit(t *testing.T) { gtx := layout.Context{ Ops: new(op.Ops), Constraints: layout.Exact(image.Pt(100, 100)), - Source: r, + Source: r.Source(), } cache := text.NewShaper(text.NoSystemFonts(), text.WithCollection(gofont.Collection())) fontSize := unit.Sp(10) diff --git a/widget/enum.go b/widget/enum.go index 45359209..fa4c6fce 100644 --- a/widget/enum.go +++ b/widget/enum.go @@ -40,13 +40,13 @@ func (e *Enum) index(k string) *enumKey { // Update the state and report whether Value has changed by user interaction. func (e *Enum) Update(gtx layout.Context) bool { - if gtx.Source == nil { + if !gtx.Enabled() { e.focused = false } e.hovering = false changed := false for _, state := range e.keys { - for _, ev := range state.click.Update(gtx) { + for _, ev := range state.click.Update(gtx.Source) { switch ev.Kind { case gesture.KindPress: if ev.Source == pointer.Mouse { @@ -117,12 +117,11 @@ func (e *Enum) Layout(gtx layout.Context, k string, content layout.Widget) layou } clk := &state.click clk.Add(gtx.Ops) - enabled := gtx.Source != nil - if enabled { + if gtx.Enabled() { key.InputOp{Tag: &state.tag, Keys: "⏎|Space"}.Add(gtx.Ops) } semantic.SelectedOp(k == e.Value).Add(gtx.Ops) - semantic.EnabledOp(enabled).Add(gtx.Ops) + semantic.EnabledOp(gtx.Enabled()).Add(gtx.Ops) c.Add(gtx.Ops) return dims diff --git a/widget/example_test.go b/widget/example_test.go index 393190cf..940ede19 100644 --- a/widget/example_test.go +++ b/widget/example_test.go @@ -25,7 +25,7 @@ func ExampleClickable_passthrough() { gtx := layout.Context{ Ops: new(op.Ops), Constraints: layout.Exact(image.Pt(100, 100)), - Source: &r, + Source: r.Source(), } // widget lays out two buttons on top of each other. @@ -75,7 +75,7 @@ func ExampleDraggable_Layout() { gtx := layout.Context{ Ops: new(op.Ops), Constraints: layout.Exact(image.Pt(100, 100)), - Source: &r, + Source: r.Source(), } // mime is the type used to match drag and drop operations. // It could be left empty in this example. diff --git a/widget/float.go b/widget/float.go index 52f0f595..d0bb5f8e 100644 --- a/widget/float.go +++ b/widget/float.go @@ -48,7 +48,7 @@ func (f *Float) Layout(gtx layout.Context, axis layout.Axis, pointerMargin unit. // The range of f is set by the minimum constraints main axis value. func (f *Float) Update(gtx layout.Context) bool { changed := false - for _, e := range f.drag.Update(gtx.Metric, gtx, gesture.Axis(f.axis)) { + for _, e := range f.drag.Update(gtx.Metric, gtx.Source, gesture.Axis(f.axis)) { if f.length > 0 && (e.Kind == pointer.Press || e.Kind == pointer.Drag) { pos := e.Position.X if f.axis == layout.Vertical { diff --git a/widget/list.go b/widget/list.go index 3e916910..b9de5ee6 100644 --- a/widget/list.go +++ b/widget/list.go @@ -61,7 +61,7 @@ func (s *Scrollbar) Update(gtx layout.Context, axis layout.Axis, viewportStart, } // Jump to a click in the track. - for _, event := range s.track.Update(gtx) { + for _, event := range s.track.Update(gtx.Source) { if event.Kind != gesture.KindClick || event.Modifiers != key.Modifiers(0) || event.NumClicks > 1 { @@ -80,7 +80,7 @@ func (s *Scrollbar) Update(gtx layout.Context, axis layout.Axis, viewportStart, } // Offset to account for any drags. - for _, event := range s.drag.Update(gtx.Metric, gtx, gesture.Axis(axis)) { + for _, event := range s.drag.Update(gtx.Metric, gtx.Source, gesture.Axis(axis)) { switch event.Kind { case pointer.Drag: case pointer.Release, pointer.Cancel: @@ -136,7 +136,7 @@ func (s *Scrollbar) Update(gtx layout.Context, axis layout.Axis, viewportStart, // Process events from the indicator so that hover is // detected properly. - _ = s.indicator.Update(gtx) + _ = s.indicator.Update(gtx.Source) } // AddTrack configures the track click listener for the scrollbar to use diff --git a/widget/material/button.go b/widget/material/button.go index e238e432..d3c6278e 100644 --- a/widget/material/button.go +++ b/widget/material/button.go @@ -133,7 +133,7 @@ func (b ButtonLayoutStyle) Layout(gtx layout.Context, w layout.Widget) layout.Di defer clip.UniformRRect(image.Rectangle{Max: gtx.Constraints.Min}, rr).Push(gtx.Ops).Pop() background := b.Background switch { - case gtx.Source == nil: + case !gtx.Enabled(): background = f32color.Disabled(b.Background) case b.Button.Hovered() || b.Button.Focused(): background = f32color.Hovered(b.Background) @@ -165,7 +165,7 @@ func (b IconButtonStyle) Layout(gtx layout.Context) layout.Dimensions { defer clip.UniformRRect(image.Rectangle{Max: gtx.Constraints.Min}, rr).Push(gtx.Ops).Pop() background := b.Background switch { - case gtx.Source == nil: + case !gtx.Enabled(): background = f32color.Disabled(b.Background) case b.Button.Hovered() || b.Button.Focused(): background = f32color.Hovered(b.Background) diff --git a/widget/material/checkable.go b/widget/material/checkable.go index d4662eaf..b5face88 100644 --- a/widget/material/checkable.go +++ b/widget/material/checkable.go @@ -60,7 +60,7 @@ func (c *checkable) layout(gtx layout.Context, checked, hovered bool) layout.Dim return layout.UniformInset(2).Layout(gtx, func(gtx layout.Context) layout.Dimensions { size := gtx.Dp(c.Size) col := c.IconColor - if gtx.Source == nil { + if !gtx.Enabled() { col = f32color.Disabled(col) } gtx.Constraints.Min = image.Point{X: size} diff --git a/widget/material/editor.go b/widget/material/editor.go index b00a48fb..3f717c02 100644 --- a/widget/material/editor.go +++ b/widget/material/editor.go @@ -61,7 +61,7 @@ func (e EditorStyle) Layout(gtx layout.Context) layout.Dimensions { paint.ColorOp{Color: e.HintColor}.Add(gtx.Ops) hintColor := hintColorMacro.Stop() selectionColorMacro := op.Record(gtx.Ops) - paint.ColorOp{Color: blendDisabledColor(gtx.Source == nil, e.SelectionColor)}.Add(gtx.Ops) + paint.ColorOp{Color: blendDisabledColor(!gtx.Enabled(), e.SelectionColor)}.Add(gtx.Ops) selectionColor := selectionColorMacro.Stop() var maxlines int diff --git a/widget/material/progressbar.go b/widget/material/progressbar.go index fc17cf0c..c842171d 100644 --- a/widget/material/progressbar.go +++ b/widget/material/progressbar.go @@ -51,7 +51,7 @@ func (p ProgressBarStyle) Layout(gtx layout.Context) layout.Dimensions { layout.Stacked(func(gtx layout.Context) layout.Dimensions { fillWidth := int(float32(progressBarWidth) * clamp1(p.Progress)) fillColor := p.Color - if gtx.Source == nil { + if !gtx.Enabled() { fillColor = f32color.Disabled(fillColor) } return shader(fillWidth, fillColor) diff --git a/widget/material/slider.go b/widget/material/slider.go index d3283d21..97253259 100644 --- a/widget/material/slider.go +++ b/widget/material/slider.go @@ -56,7 +56,7 @@ func (s SliderStyle) Layout(gtx layout.Context) layout.Dimensions { trans.Pop() color := s.Color - if gtx.Source == nil { + if !gtx.Enabled() { color = f32color.Disabled(color) } diff --git a/widget/material/switch.go b/widget/material/switch.go index 62fbb942..7bf18e77 100644 --- a/widget/material/switch.go +++ b/widget/material/switch.go @@ -55,7 +55,7 @@ func (s SwitchStyle) Layout(gtx layout.Context) layout.Dimensions { if s.Switch.Value { col = s.Color.Enabled } - if gtx.Source == nil { + if !gtx.Enabled() { col = f32color.Disabled(col) } trackColor := s.Color.Track diff --git a/widget/selectable.go b/widget/selectable.go index 186a2ac8..bff04a42 100644 --- a/widget/selectable.go +++ b/widget/selectable.go @@ -298,10 +298,10 @@ func (e *Selectable) processPointer(gtx layout.Context) { func (e *Selectable) clickDragEvents(gtx layout.Context) []event.Event { var combinedEvents []event.Event - for _, evt := range e.clicker.Update(gtx) { + for _, evt := range e.clicker.Update(gtx.Source) { combinedEvents = append(combinedEvents, evt) } - for _, evt := range e.dragger.Update(gtx.Metric, gtx, gesture.Both) { + for _, evt := range e.dragger.Update(gtx.Metric, gtx.Source, gesture.Both) { combinedEvents = append(combinedEvents, evt) } return combinedEvents diff --git a/widget/selectable_test.go b/widget/selectable_test.go index 8b40d2d9..b4f514ca 100644 --- a/widget/selectable_test.go +++ b/widget/selectable_test.go @@ -38,7 +38,7 @@ func TestSelectableMove(t *testing.T) { gtx := layout.Context{ Ops: new(op.Ops), Locale: english, - Source: r, + Source: r.Source(), } cache := text.NewShaper(text.NoSystemFonts(), text.WithCollection(gofont.Collection())) fnt := font.Font{} diff --git a/widget/widget_test.go b/widget/widget_test.go index 6f7aad3a..08183ebd 100644 --- a/widget/widget_test.go +++ b/widget/widget_test.go @@ -22,7 +22,7 @@ func TestBool(t *testing.T) { r input.Router b widget.Bool ) - gtx := app.NewContext(&ops, app.FrameEvent{Source: &r}) + gtx := app.NewContext(&ops, app.FrameEvent{Source: r.Source()}) layout := func() { b.Layout(gtx, func(gtx layout.Context) layout.Dimensions { semantic.CheckBox.Add(gtx.Ops)