The way this is done everywhere is to invalidate the entire area of the button. Buttons usually change background on hover/click anyway, so it just doesn't make sense to do more. Text input is special because these widgets can be very large, sometimes spanning the whole screen, so you want fine-grained dirty regions.
> Also, if you stop passing dirty regions around then the widget drawing method is closer to being a pure function meaning the UI framework can cache the draw instructions instead of calling it over and over for different regions.
I've never heard of anyone adding a general Widget-Level cache, considering that most UI elements don't change position that would be quite expensive. In any case the rendering is still a "pure" function regardless of whether you're using dirty regions or not, so not sure what you're trying to say here.
> Looks like it but it doesn't show any renders for the cursor flashing so I don't fully trust it.
That is definitely weird, but it still clearly shows that the regions are being tracked.