GNOME Bugzilla – Bug 692744
ClutterActor size caches may become stale
Last modified: 2021-06-10 11:32:48 UTC
After applying gnome-shell's dash patches at bug 690643, I got the dash resizing to be mostly working. But occasionally it stretches over the entirety of the screen, even if its contents would make it smaller. The layout of the dash is fairly complex: it consists of an StBin which is allocated by the overview StBoxLayout. The height of the bin is tracked by JS code and used as the maximum height available. The bin contains a Gjs_DashActor, which has a BoxLayout, but if the allocation is less than required clips the first actor to show the second one. The first actor in the Gjs_DashActor is a StBoxLayout, which holds the actual icons (Gjs_DashItemContainer). The icons are sized manually when the size of the StBin changes (ie. on resolution changes) or as application come and go. After a bit of debugging, I found that StBoxLayout occasionally gets a stale size cache, which forces it to return the same invalid values from get_preferred_height(-1). Indeed, trying St.BoxLayout.vfunc_get_preferred_height.call(theLayout, -1) (ie. going straight to the St implementation) causes it to behave fine. Also, manually calling queue_relayout() works, so this bug is easily workaroundable at the JS level, but my belief is that add_child() and remove_child() should queue a relayout on the parent always. Instead, I see a queue_relayout() in remove only if the actor is mapped, and in add only if the child has invalid cache. Please tell me if I'm completely off track here.
if a child is not mapped, the layout manager should be allocating it, so its allocation should not be valid in the first place; if you remove an unmapped child then the parent does not require any state invalidation. if you add a child that is not visible (which means that the child won't be mapped, if its new parent is mapped) then, again, no invalidation will happen. if a child was added, then set to be invisible using hide() (which does queue a relayout), then the child's flags would be reset (as well as its parent's); the allocation code would then skip the child, which means that its flags would never be reset - so on remove_child() there would be no need to queue a relayout on its parent. I think you may want to look at the state of the needs_* flags in the child, and see if they are going out of sync.
Uhm... you say that unmapped actors should not be allocated, but Gjs_DashActor doesn't check for that, so that could be the bug. Although it's impossible that the boxlayout inside it becomes invisible without that being invisible too..
GNOME is going to shut down bugzilla.gnome.org in favor of gitlab.gnome.org. As part of that, we are mass-closing older open tickets in bugzilla.gnome.org which have not seen updates for a longer time (resources are unfortunately quite limited so not every ticket can get handled). If you can still reproduce the situation described in this ticket in a recent and supported software version of clutter, then please follow https://wiki.gnome.org/GettingInTouch/BugReportingGuidelines and create a ticket at https://gitlab.gnome.org/GNOME/clutter/-/issues/ Thank you for your understanding and your help.