Merge PR #2371: #2365: centre the search field on the window, not inside the bar's margins

This commit is contained in:
aiongg
2026-10-22 02:37:49 +00:00
2 changed files with 35 additions and 9 deletions
+13 -9
View File
@@ -10,9 +10,8 @@ use crate::widgets::{icon_button, register};
/// The bar doubles as the window's title bar: dragging its empty space moves the window and a
/// double-click zooms or restores it. Registered before the bar's widgets so they win the click.
fn window_handle(app: &LightcraftApp, ui: &mut egui::Ui, content: Rect, margin_left: f32, margin_right: f32, search_rect: Rect) {
fn window_handle(app: &LightcraftApp, ui: &mut egui::Ui, bar: Rect, search_rect: Rect) {
use crate::titlebar::{Gesture, WindowState, command_for};
let bar = Rect::from_min_max(pos2(content.left() - margin_left, content.top()), pos2(content.right() + margin_right, content.bottom()));
register(ui.ctx(), "region:titlebar", bar);
let handle = egui::Id::new("titlebar-handle");
let resp = ui.interact(bar, handle, Sense::click_and_drag());
@@ -60,18 +59,23 @@ pub fn show(app: &mut LightcraftApp, ui: &mut egui::Ui) {
.frame(egui::Frame::NONE.fill(t.chrome).inner_margin(egui::Margin { left, right: 12, top: 0, bottom: 0 }))
.show(ui, |ui| {
let full = ui.max_rect();
// room for the filter icon and the seven icons on the right
// (the field is centred, so each icon on the right takes its width from both sides)
let mut sw = 640.0f32.min(full.width() - 620.0).max(190.0);
// The whole bar, its margins included. The search field is centred on this and not on
// `full`, which is only what the margins leave: on macOS the left margin holds the
// traffic lights' room, and full screen gives that room back. Centring on `full` moved
// the field, and changed its width, every time that room changed (issue #2365).
let bar = Rect::from_min_max(pos2(full.left() - left as f32, full.top()), pos2(full.right() + 12.0, full.bottom()));
// The field stops short of the filter icon and the seven icons on the right; centred,
// it is twice the room between the window's centre and them.
let mut sw = 640.0f32.min(2.0 * (full.right() - 310.0 - bar.center().x)).max(190.0);
if !app.native_menu {
// leave room for the in-window menus left of the (centred) search field
let menus_right = full.left() + 140.0 + crate::menubar::bar_width(ui) + 24.0;
sw = sw.min(2.0 * (full.center().x - menus_right)).max(190.0);
sw = sw.min(2.0 * (bar.center().x - menus_right)).max(190.0);
}
let search_left = full.center().x - sw / 2.0;
let sr = Rect::from_center_size(pos2(full.center().x, full.center().y), vec2(sw, 28.0));
let search_left = bar.center().x - sw / 2.0;
let sr = Rect::from_center_size(pos2(bar.center().x, full.center().y), vec2(sw, 28.0));
if app.integrated_titlebar {
window_handle(app, ui, full, left as f32, 12.0, sr);
window_handle(app, ui, bar, sr);
}
ui.horizontal_centered(|ui| {
ui.spacing_mut().item_spacing.x = 4.0;
+22
View File
@@ -130,6 +130,28 @@ fn without_the_integrated_title_bar_the_bar_is_not_a_window_handle() {
assert!(bar.is_none());
}
// Scenario: the search field is centred on the window, whatever room the traffic lights take (#2365)
#[test]
fn the_search_field_stays_centred_on_the_window() {
let mut h = integrated();
let window_centre = 1200.0 / 2.0;
let windowed = widget(&h, "field:search");
assert_eq!(windowed.center().x, window_centre, "windowed, the field is centred on the window");
// the filter icon rides with the field, so it moves whenever the field does
let filter = widget(&h, "icon:filter").center().x;
h.request("ui.key", json!({"key": "f", "cmd": true, "shift": true}), T);
play(&mut h);
assert!(h.app.window_is_fullscreen);
let full_screen = widget(&h, "field:search");
assert_eq!(full_screen.center().x, window_centre, "full screen leaves it centred");
assert_eq!(full_screen.width(), windowed.width(), "and the same width");
assert_eq!(widget(&h, "icon:filter").center().x, filter);
h.request("ui.key", json!({"key": "f", "cmd": true, "shift": true}), T);
play(&mut h);
assert!(!h.app.window_is_fullscreen);
assert_eq!(widget(&h, "field:search").center().x, window_centre, "and so does leaving it");
}
// Scenario: in full screen the traffic lights are gone, so the bar's buttons move into their space
#[test]
fn full_screen_moves_the_left_buttons_into_the_traffic_lights_space() {