Reuse layout for view's element when it wasn't cached (#4156)

Antonio Scandurra created

Refs https://github.com/zed-industries/zed/pull/4131
Refs https://github.com/zed-industries/community/issues/2415

Previously, when a view cache miss occurred during paint, we would
either use the element produced during layout or create a new, detached
node layout node. In both cases, we would issue a call to `draw`.

The problem with this approach, however, is that `draw` would always
paint the element at the given `bounds.origin`, which was required when
the layout node was detached but harmful when the element was already
embedded in the layout tree and already knew its bounds. In this second
case, in fact, it was as if we were positioning the element "twice",
which caused content to jump.

Release Notes:

- N/A

Change summary

crates/gpui/src/view.rs | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)

Detailed changes

crates/gpui/src/view.rs 🔗

@@ -321,8 +321,12 @@ impl Element for AnyView {
                 }
             }
 
-            let mut element = (self.request_layout)(self, cx).1;
-            element.draw(bounds.origin, bounds.size.into(), cx);
+            if let Some(mut element) = state.element.take() {
+                element.paint(cx);
+            } else {
+                let mut element = (self.request_layout)(self, cx).1;
+                element.draw(bounds.origin, bounds.size.into(), cx);
+            }
 
             state.cache_key = Some(ViewCacheKey {
                 bounds,