Media: the viewer's picture moves; a viewer with no picture takes no Tab

The stage's picture carries an id, so gpui keeps its frame and asks for
the next: an animated picture plays, turned or not. A viewer whose picture
has not loaded or cannot open is no Tab stop. AGENTS.md: img() moves an
animated picture's frames only with an id.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ZacharyZhang-NYandClaude Opus 5.5 committed 2026-09-26 15:51:03 -04:00
1 parent f8a51a5352
commit 12f0baab15
4 files changed
+15 -4

No files matched your search

+3
View File
@@ -282,6 +282,9 @@ fn a_picture_that_cannot_open_says_so(cx: &mut TestAppContext) {
let cx = viewing(std::env::temp_dir().join("ely-media-missing.png"), cx);
assert!(cx.debug_bounds("image-viewer-failed").is_some());
assert!(cx.debug_bounds("image-viewer-picture").is_none());
cx.update(|window, _| window.focus_next());
let focused = cx.update(|window, cx| window.focused(cx));
assert!(focused.is_none(), "with nothing to show, nothing takes Tab");
}
/// Two thumbnails, the second with no handler; the opens the first heard.
+10 -3
View File
@@ -119,7 +119,6 @@ impl RenderOnce for ImageViewer {
}
});
}
let focus = tab_stop((self.id.clone(), "focus").into(), true, window, cx);
let decoded = window.use_asset::<ImageAssetLoader>(&self.source, cx);
let turns = view.read(cx).turns;
let picture: Option<Arc<RenderImage>> = match decoded {
@@ -143,6 +142,12 @@ impl RenderOnce for ImageViewer {
let size = image.size(0);
(size.width.0 as f32, size.height.0 as f32)
});
let focus = tab_stop(
(self.id.clone(), "focus").into(),
pixels.is_some(),
window,
cx,
);
let theme = cx.theme();
let colors = theme.colors.clone();
let (zoom, offset, stage) = {
@@ -252,6 +257,7 @@ impl RenderOnce for ImageViewer {
});
let body = match (picture, shown) {
(Some(image), Some((size, left, top))) => img(ImageSource::Render(image))
.id((self.id.clone(), "picture"))
.debug_selector(|| "image-viewer-picture".into())
.absolute()
.left(Pixels::from(left))
@@ -305,8 +311,9 @@ impl RenderOnce for ImageViewer {
.bg(colors.sunken)
.border_1()
.border_color(transparent_black())
.track_focus(&focus)
.focus_ring(cx)
.when(pixels.is_some(), |stage| {
stage.track_focus(&focus).focus_ring(cx)
})
.when(overhangs, |stage| stage.cursor_grab())
.child(
canvas(