gpui: Update animated image timing to pause when inactive (#52685)

MostlyK created

- only advance frames and request animation frames while the window is
active.
- Reset last_frame_time to None when inactive to avoid fast catch-up
after resuming focus
- This fixes an issue where if you would have a gif open and lose focus,
the app tries to speedup to catch up the elapsed time


Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

Might Close #21563, I shall measure the performance, I originally only
intended the fix to fix the speed up issue as I faced it while working
on gifs.


Release Notes:

- N/A or Added/Fixed/Improved ...

Change summary

crates/gpui/src/elements/img.rs | 33 ++++++++++++++++++++-------------
1 file changed, 20 insertions(+), 13 deletions(-)

Detailed changes

crates/gpui/src/elements/img.rs 🔗

@@ -315,20 +315,24 @@ impl Element for Img {
                             if let Some(state) = &mut state {
                                 let frame_count = data.frame_count();
                                 if frame_count > 1 {
-                                    let current_time = Instant::now();
-                                    if let Some(last_frame_time) = state.last_frame_time {
-                                        let elapsed = current_time - last_frame_time;
-                                        let frame_duration =
-                                            Duration::from(data.delay(state.frame_index));
-
-                                        if elapsed >= frame_duration {
-                                            state.frame_index =
-                                                (state.frame_index + 1) % frame_count;
-                                            state.last_frame_time =
-                                                Some(current_time - (elapsed - frame_duration));
+                                    if window.is_window_active() {
+                                        let current_time = Instant::now();
+                                        if let Some(last_frame_time) = state.last_frame_time {
+                                            let elapsed = current_time - last_frame_time;
+                                            let frame_duration =
+                                                Duration::from(data.delay(state.frame_index));
+
+                                            if elapsed >= frame_duration {
+                                                state.frame_index =
+                                                    (state.frame_index + 1) % frame_count;
+                                                state.last_frame_time =
+                                                    Some(current_time - (elapsed - frame_duration));
+                                            }
+                                        } else {
+                                            state.last_frame_time = Some(current_time);
                                         }
                                     } else {
-                                        state.last_frame_time = Some(current_time);
+                                        state.last_frame_time = None;
                                     }
                                 }
                                 state.started_loading = None;
@@ -365,7 +369,10 @@ impl Element for Img {
                                 };
                             }
 
-                            if global_id.is_some() && data.frame_count() > 1 {
+                            if global_id.is_some()
+                                && data.frame_count() > 1
+                                && window.is_window_active()
+                            {
                                 window.request_animation_frame();
                             }
                         }