Data dependencies between `update` and `event` require dropped updates
Ralith opened this issue · 0 comments
Some widgets (e.g. TextBox
) share ownership of data with the application by accepting a value in their Props
and returning a value modified by events. Because update
is responsible for both accepting new values from the application and returning event-modified values, the application cannot observe an updated value without first passing in an obsolete value, which the widget must ignore lest the updated value be clobbered.
This is a footgun for widget implementers. If the application is updating the shared state independently of the widget, it also causes those updates to be lost so long as events are triggering changes. Because events might be delivered every frame for arbitrarily long intervals (e.g. due to mouse motion), this can cause unbounded of user-visible lag. For some widgets (e.g. a camera controller that the application is manipulating to track a fast-moving target), even a single frame of lag might severely degrade user experience.
One possible solution would be to split Widget::update
into two phases. The first, perhaps show
, is responsible for constructing child widgets and yielding the Widget::Response
. The second is responsible for accepting new Props
from the application. User-facing API might look like:
let mut res = button();
if res.clicked {
res.update("I was clicked on this frame!");
} else {
res.update("I was not clicked on this frame");
}
Widgets which do not accept state from the application should not require the application to issue an explicit update
call.
A side benefit is that this permits non-linear data flow between widgets: when multiple widgets are show
n, any or all of their responses may influence any or all of their following update
calls.