This might very well be intended behaviour, however it doesn't match prior versions of Gio. If it's intended feel free to close the ticket.
In short: gtx.Disabled()
has typically been used to block user input. However in the current version of Gio it will block all animations as well, since gtx.Execute(op.InvalidateCmd{})
is not processed on a disabled gtx.
Here's a minimal reproducer:
package main
import (
"log"
"os"
"gioui.org/app"
"gioui.org/layout"
"gioui.org/op"
"gioui.org/widget/material"
)
func main() {
go func() {
w := new(app.Window)
w.Option(app.Title("playground"))
if err := run(w); err != nil {
log.Fatal(err)
}
os.Exit(0)
}()
app.Main()
}
func run(w *app.Window) error {
var (
th = material.NewTheme()
ops op.Ops
)
for {
switch ev := w.Event().(type) {
case app.DestroyEvent:
return ev.Err
case app.FrameEvent:
gtx := app.NewContext(&ops, ev)
frame(gtx, th)
ev.Frame(gtx.Ops)
}
}
}
type (
C = layout.Context
D = layout.Dimensions
)
func frame(gtx C, th *material.Theme) D {
return layout.Center.Layout(gtx, func(gtx C) D {
gtx = gtx.Disabled()
return material.Loader(th).Layout(gtx)
})
}
I've countered some trouble from this as well. Originally I rationalized this change as reasonable because disabling a widget could be thought of as "not allowing the widget layout to interact with the Gio window/event system at all," but after further thought I don't like that approach.
Disabled widgets aren't supposed to accept input events, but they may be disabled while waiting for an event or during an animation, both of which require scheduling future invalidation.
More generally, is there any real problem with allowing disabled widgets to issue arbitrary commands? They aren't receiving input events from users, so their only input is their current state. Their behavior should be pretty simple to reason about in the absence of input events, and thus buggy widgets issuing incorrect commands should be easy to catch. I think the potential harm of allowing command execution on a disabled context is low, and the benefits are real.
I can see that the issue with enabling this is in the implementation though. The
gtx.Source
is zeroed to disable the context, but theSource
is also the thing responsible for handling commands. Without changing this implementation, we cannot disentangle the above behavior. Disabling the context inherently disables command execution by removing the type that actually executes commands.
I'm tempted to agree that allowing commands on a disabled gtx is a good idea. The implementation would be to replace the nil'ing of Context.Source with adding a Source.Disabled that tracks the enabled-ness of the Source.
Elias Naur referenced this ticket in commit d9ddbe6.