fix(android): correct physical→logical px conversion for safe-area insets
`WindowInsets.getInsets(systemBars())` returns physical pixels (e.g. 84 px on a 2.625× Pixel 7) but both Bevy's `Val::Px` (UI layer) and the world- space layout coordinate system use logical pixels. Dividing by `window.scale_factor()` before applying gives the correct 32 dp offset. - `safe_area.rs::apply_safe_area_anchors`: query `Window`, divide `insets.top` by `scale_factor()` before writing `Val::Px(base_top + top_logical)`. - `layout.rs::compute_layout`: new `safe_area_top: f32` parameter (logical px) subtracts from the vertical budget (`card_width_height_based`) and from `top_y` so both card sizing and pile positioning honour the status-bar band. - `table_plugin.rs`: `setup_table` and `on_window_resized` now read `SafeAreaInsets` and divide by scale before passing `safe_area_top` to `compute_layout`. New `on_safe_area_changed` system fires a synthetic `WindowResized` when insets arrive (~frame 2-3 on Android) so the full resize pipeline (layout → pile markers → card snap) re-runs automatically. - All test call-sites updated with `, 0.0` safe_area_top (desktop/no inset). - Two regression tests added: shift amount equals `safe_area_top` exactly; horizontal layout is unaffected by vertical inset. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -71,13 +71,19 @@ impl Plugin for SafeAreaInsetsPlugin {
|
||||
/// a session.
|
||||
fn apply_safe_area_anchors(
|
||||
insets: Res<SafeAreaInsets>,
|
||||
windows: Query<&Window>,
|
||||
mut q: Query<(&SafeAreaAnchoredTop, &mut Node)>,
|
||||
) {
|
||||
if !insets.is_changed() {
|
||||
return;
|
||||
}
|
||||
// Android's WindowInsets API returns physical pixels; Bevy UI's Val::Px
|
||||
// expects logical pixels (≈ dp). Divide by the window scale factor so
|
||||
// the HUD band shifts by the correct number of dp on high-DPI devices.
|
||||
let scale = windows.iter().next().map_or(1.0, |w| w.scale_factor());
|
||||
let top_logical = insets.top / scale;
|
||||
for (anchor, mut node) in &mut q {
|
||||
node.top = Val::Px(anchor.base_top + insets.top);
|
||||
node.top = Val::Px(anchor.base_top + top_logical);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user