Stop insetting apps by the title bar twice

Painting the title bar showed that the window's content view runs the
full height including the bar, so the shell was given a top inset to keep
clear of it. Child webviews were still being offset by the same amount on
top of that, which left a title bar's worth of empty space above every
page.

The shell and a child webview share an origin, so no correction is needed
between them: the shell pads itself, and the rect it reports is already
right. The measurement stays, for that padding only.
This commit is contained in:
2026-09-01 19:23:11 +02:00
parent 899f0b41c4
commit c96154ca33
+13 -10
View File
@@ -708,7 +708,7 @@ pub fn create(
window
.add_child(
builder,
LogicalPosition::new(stage.0, stage.1 + chrome_offset(handle)),
LogicalPosition::new(stage.0, stage.1),
LogicalSize::new(stage.2, stage.3),
)
.map_err(|e| e.to_string())?;
@@ -773,7 +773,15 @@ pub fn measure_chrome(_: &AppHandle) -> f64 {
0.0
}
/// How far the window's frame sits above its content, in logical pixels.
/// The title bar's height, for the shell to keep clear of.
///
/// Not an offset for positioning apps. The window's content view runs the full
/// height *including* the title bar, so a child webview and the shell share an
/// origin and no correction is needed between them — the shell simply pads
/// itself by this much, and the rect it then reports is already right.
///
/// Adding it here as well was the bug that left a title bar's worth of gap
/// above every page: the inset was being applied twice.
pub fn chrome_offset(handle: &AppHandle) -> f64 {
*handle.state::<crate::commands::AppState>().chrome.lock().unwrap()
}
@@ -800,10 +808,9 @@ pub fn show_only(
cfg: &Config,
stage: (f64, f64, f64, f64),
) {
let top = stage.1 + chrome_offset(handle);
for app in &cfg.apps {
let Some(wv) = handle.get_webview(&label_for(&app.id)) else { continue };
let _ = wv.set_position(LogicalPosition::new(stage.0, top));
let _ = wv.set_position(LogicalPosition::new(stage.0, stage.1));
let _ = wv.set_size(LogicalSize::new(stage.2, stage.3));
let _ = wv.set_zoom(app.zoom);
let _ = wv.show();
@@ -827,10 +834,9 @@ pub fn set_stage(
radius: f64,
) {
let cfg = handle.state::<crate::commands::AppState>().cfg();
let top = stage.1 + chrome_offset(handle);
for app in &cfg.apps {
let Some(wv) = handle.get_webview(&label_for(&app.id)) else { continue };
let _ = wv.set_position(LogicalPosition::new(stage.0, top));
let _ = wv.set_position(LogicalPosition::new(stage.0, stage.1));
let _ = wv.set_size(LogicalSize::new(stage.2, stage.3));
set_corner_radius(handle, &app.id, radius);
}
@@ -848,10 +854,7 @@ pub fn set_stage(
pub fn hide_all(handle: &AppHandle, cfg: &Config, stage: (f64, f64, f64, f64)) {
for app in &cfg.apps {
if let Some(wv) = handle.get_webview(&label_for(&app.id)) {
let _ = wv.set_position(LogicalPosition::new(
stage.0,
stage.1 + chrome_offset(handle) + PARKED_OFFSET,
));
let _ = wv.set_position(LogicalPosition::new(stage.0, stage.1 + PARKED_OFFSET));
}
// Nothing is on screen behind a dialog, so nothing should think it is.
set_page_visibility(handle, &app.id, false);