widget gallery and compositor test bench
fix: only a Ramp child focuses the preset dropdown at startup
Application::new's child branch downcast slot 1 to Ramp unconditionally and
expect()ed it, but slot 1 is a Ramp only for `--type Ramp`: ColorRamp hosts a
ColorRamp there and Toplevel/Popup/LayerTop/LayerOverlay/LayerBackground host
the description Label (ChildMain). Every non-Ramp child therefore died at
startup with "panicked at main.rs: child ramp widget" — Create Window on the
Windows page spawned processes that never mapped. The panic predates the
roster retype in 0507f49 (its message records it as pre-existing) and
survived it.
The preset-dropdown focus setup is now gated on the downcast succeeding. The
other child kinds start with nothing focused: handle_key's roster sweep
already delivers keys to every visible child slot, and a click focuses the
slot it lands on, so no behaviour is lost.
Verified in a private shadow session (cce-shadow agent-14): the pre-fix
binary panics at main.rs:1248 for `--type Toplevel`; with the fix,
`cce-shadow ctl windows` lists app_id=clear-test-child-toplevel
title="Simulated Toplevel Window" at 400x250, and Ramp, ColorRamp, Popup,
LayerTop, LayerOverlay and LayerBackground children all run past startup.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
src/main.rs | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/src/main.rs b/src/main.rs
index 585e0f7..e7995ed 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1243,10 +1243,17 @@ cascades in cce."
&mut state.ui_context,
);
}
- } else {
- state.focused_widget = Some(1);
- let ramp = state.roster.get_dyn_mut(1).as_any_mut().downcast_mut::<Ramp>().expect("child ramp widget");
+ } else if let Some(ramp) = state.roster.get_dyn_mut(1).as_any_mut().downcast_mut::<Ramp>() {
+ // Only a `--type Ramp` child hosts a Ramp in slot 1: it opens with the
+ // preset dropdown focused so the keyboard drives it at once. Every other
+ // child kind (ColorRamp, or the description Label of the Toplevel /
+ // Popup / Layer* windows) starts with nothing focused — the key sweep
+ // in handle_key reaches every visible child slot anyway, and a click
+ // focuses whatever it lands on. This used to downcast unconditionally
+ // and panic for those kinds ("child ramp widget"), which is why Create
+ // Window on the Windows page spawned children that died at startup.
let preset_ptr = ramp.preset_dropdown.as_ptr_mut();
+ state.focused_widget = Some(1);
state.ui_context.set_focused_ptr(preset_ptr);
unsafe {
(*preset_ptr).focus();