LR-BEHAV-TITLEBAR: a dialog leaves the integrated title bar undimmed

On macOS the window buttons are drawn by the OS above our content, so a backdrop over the
top bar left them bright on a dimmed bar. As under a sheet, the backdrop now stops below the
bar, the bar keeps its color with its controls inactive, a click on it is not a click outside
the dialog, and its empty space still moves the window.
This commit is contained in:
Nathaniel Ledford
2026-10-29 13:47:52 -04:00
parent 77c0a6adfa
commit 62c3344d3c
6 changed files with 173 additions and 8 deletions
+42 -2
View File
@@ -93,8 +93,11 @@ pub fn show(app: &mut LightcraftApp, ctx: &egui::Context, blocked: bool) {
let t = Tokens::get(ctx);
let screen = ctx.content_rect();
// The backdrop is an area below the dialog window (a bare `Middle` layer painter would be
// painted after every area — i.e. over the dialog too).
// painted after every area — i.e. over the dialog too). Like a macOS sheet, the dialog leaves
// the integrated title bar lit: the window buttons the OS draws over it do not dim.
let title_bar = title_bar_band(app);
egui::Area::new(egui::Id::unique("dialog-dim")).order(egui::Order::Middle).fixed_pos(screen.min).interactable(false).show(ctx, |ui| {
let screen = below_title_bar(screen, title_bar);
ui.painter().rect_filled(screen, 0.0, egui::Color32::from_black_alpha(140));
});
let mut close = false;
@@ -189,7 +192,7 @@ pub fn show(app: &mut LightcraftApp, ctx: &egui::Context, blocked: bool) {
}
if let Some(w) = &shown {
// (the import review keeps its hand-picked photos however the click lands)
if !raw_blocked && app.ui.settings.close_dialogs_outside && !import && clicked_backdrop(ctx, w.response.rect, popup_was_open) {
if !raw_blocked && app.ui.settings.close_dialogs_outside && !import && clicked_backdrop(ctx, w.response.rect, title_bar, popup_was_open) {
close = true;
} else if raw_blocked {
// A press made under the prompt or library window must not be remembered as a
@@ -208,6 +211,9 @@ pub fn show(app: &mut LightcraftApp, ctx: &egui::Context, blocked: bool) {
}
ctx.move_to_top(w.response.layer_id);
crate::widgets::register_response("dialog:window", w.response.rect, &w.response);
if let Some(band) = title_bar {
title_bar_handle(ctx, band, w.response.rect);
}
}
// (while the shortcuts editor records a key, it takes Esc itself to cancel; an open popup in
// the dialog, such as a date picker's calendar, takes it to close itself)
@@ -228,6 +234,40 @@ pub fn show(app: &mut LightcraftApp, ctx: &egui::Context, blocked: bool) {
app.ui.dialog = if close { None } else { Some(dlg) };
}
/// The band of the top bar that doubles as the window's title bar, as drawn last frame: `None`
/// without the integrated title bar (Windows, Linux, the web), in macOS full screen, and while the
/// bar isn't on screen (the full-screen photo view).
fn title_bar_band(app: &LightcraftApp) -> Option<egui::Rect> {
if !app.integrated_titlebar || app.window_is_fullscreen {
return None;
}
app.widgets.iter().find(|(id, _)| id == "region:titlebar").map(|(_, r)| *r)
}
/// `screen` less the title bar band across its top.
fn below_title_bar(screen: egui::Rect, band: Option<egui::Rect>) -> egui::Rect {
band.map_or(screen, |b| egui::Rect::from_min_max(egui::pos2(screen.min.x, b.max.y.clamp(screen.min.y, screen.max.y)), screen.max))
}
/// The bar's controls are disabled under a dialog, and the modal layer takes the hits of the layers
/// below it: this keeps the bar a window handle (drag to move, double-click to zoom), above the
/// modal like a sheet's title bar. A tall dialog reaching into the band keeps its own clicks: the
/// handle is the band on either side of it, and isn't run while the pointer is on the dialog (each
/// handle records whether the window may move, and one the pointer isn't in would say yes).
fn title_bar_handle(ctx: &egui::Context, band: egui::Rect, dialog: egui::Rect) {
if ctx.pointer_hover_pos().is_some_and(|p| dialog.contains(p)) {
return;
}
let sides =
if band.intersects(dialog) { [(band.min.x, dialog.min.x), (dialog.max.x, band.max.x)] } else { [(band.min.x, band.max.x), (0.0, 0.0)] };
for (i, (from, to)) in sides.into_iter().enumerate().filter(|(_, (from, to))| to - from > 1.0) {
let part = egui::Rect::from_x_y_ranges(from..=to, band.y_range());
egui::Area::new(egui::Id::unique("dialog-title-bar").with(i)).order(egui::Order::Foreground).fixed_pos(part.min).show(ctx, |ui| {
craft_window::title_bar::empty_area(ui, part);
});
}
}
/// The title of a dialog.
fn dialog_title(app: &LightcraftApp, dlg: &Dialog) -> String {
match dlg {
+2 -2
View File
@@ -8,7 +8,7 @@ use super::{BACKDROP_SHOWN, ControlSpec, Dialog, LightcraftApp, Tokens};
/// while the dialog is shown counts: in the frame a dialog appears, its input is the click that
/// opened it (a quick click on a slow frame presses and releases in that one frame), so it never
/// closes it. (Read from the raw events: egui forgets the press origin on release.)
pub(super) fn clicked_backdrop(ctx: &egui::Context, window: egui::Rect, popup_was_open: bool) -> bool {
pub(super) fn clicked_backdrop(ctx: &egui::Context, window: egui::Rect, title_bar: Option<egui::Rect>, popup_was_open: bool) -> bool {
let press_id = egui::Id::unique("dialog-backdrop-press");
let frame = ctx.cumulative_frame_nr();
// the same frame too: a second pass of it gets no input
@@ -27,7 +27,7 @@ pub(super) fn clicked_backdrop(ctx: &egui::Context, window: egui::Rect, popup_wa
(at(true), at(false), i.pointer.primary_clicked())
});
if let Some(p) = press {
let outside = !window.contains(p) && !popup_was_open;
let outside = !window.contains(p) && !title_bar.is_some_and(|b| b.contains(p)) && !popup_was_open;
ctx.data_mut(|d| d.insert_temp(press_id, outside));
}
let Some(release) = release else { return false };
+11 -2
View File
@@ -28,9 +28,15 @@ pub fn show(app: &mut LightcraftApp, ui: &mut egui::Ui) {
(true, true) => 16,
(false, _) => 10,
};
egui::Panel::top("top_bar")
// A dialog fades the disabled bar's controls, and its fill with them. A sheet leaves the title bar's
// color alone (the window buttons the OS draws over it stay lit), so the fill is painted unfaded
// beneath, in a slot reserved before the bar's own shapes.
let sheet = app.integrated_titlebar && !app.window_is_fullscreen && app.ui.dialog.is_some();
let slot = sheet.then(|| ui.ctx().layer_painter(ui.layer_id()).add(egui::Shape::Noop));
let fill = if sheet { egui::Color32::TRANSPARENT } else { t.chrome };
let panel = egui::Panel::top("top_bar")
.exact_size(t.top_bar_h)
.frame(egui::Frame::NONE.fill(t.chrome).inner_margin(egui::Margin { left, right: 12, top: 0, bottom: 0 }))
.frame(egui::Frame::NONE.fill(fill).inner_margin(egui::Margin { left, right: 12, top: 0, bottom: 0 }))
.show(ui, |ui| {
let full = ui.max_rect();
// The whole bar, its margins included. The search field is centred on this and not on
@@ -57,6 +63,9 @@ pub fn show(app: &mut LightcraftApp, ui: &mut egui::Ui) {
let x = right_icons(app, ui, &t, full);
appearance_button(app, ui, &t, full, x);
});
if let Some(slot) = slot {
ui.ctx().layer_painter(ui.layer_id()).set(slot, egui::Shape::rect_filled(panel.response.rect, 0.0, t.chrome));
}
}
/// Sidebar toggle, back/forward and, without a native menu bar, the in-window menus.
+107
View File
@@ -191,3 +191,110 @@ fn a_panel_floating_over_the_bar_keeps_the_window_from_moving() {
play(&mut h);
assert!(!hover(&mut h, empty), "the floating panel covers the empty bar there");
}
// A dialog on the integrated title bar behaves like a macOS sheet: the backdrop leaves the bar
// undimmed (the window buttons AppKit draws over it stay lit beside a bar that looks live), while
// the bar's own controls stay inactive.
fn pixel(img: &egui::ColorImage, p: egui::Pos2) -> egui::Color32 {
img.pixels[p.y as usize * img.size[0] + p.x as usize]
}
fn with_export_dialog(mut h: Headless) -> Headless {
h.app.run("dialog.export", json!({})).unwrap();
h.step();
h.step();
h.settle(T);
h
}
// Scenario: the dialog's backdrop does not dim the integrated title bar
#[test]
fn a_dialog_leaves_the_integrated_title_bar_undimmed() {
let mut h = integrated();
let spot = empty_spot(&h);
let below = egui::pos2(spot.x, widget(&h, "region:titlebar").bottom() + 60.0);
let closed = h.snapshot(T);
let mut h = with_export_dialog(h);
let open = h.snapshot(T);
assert_eq!(pixel(&open, spot), pixel(&closed, spot), "the bar keeps its color under a dialog");
assert_ne!(pixel(&open, below), pixel(&closed, below), "the window below the bar is dimmed");
}
// Scenario: a window with its native title bar dims everything, the top bar included
#[test]
fn a_dialog_dims_the_top_bar_without_the_integrated_title_bar() {
let services = Services { png: None, ..Default::default() };
let app = LightcraftApp::new(lightcraft_engine::Session::with_demo(), services);
let mut h = Headless::new(app, [1200.0, 800.0], 1.0);
h.settle(Duration::from_secs(120));
let spot = egui::pos2(20.0, 20.0);
let closed = h.snapshot(T);
let mut h = with_export_dialog(h);
let open = h.snapshot(T);
assert_ne!(pixel(&open, spot), pixel(&closed, spot), "the top bar is dimmed");
}
// Scenario: a click on the undimmed bar is not a click outside the dialog
#[test]
fn a_click_on_the_title_bar_keeps_the_dialog_open() {
let mut h = integrated();
h.app.ui.settings.close_dialogs_outside = true;
let mut h = with_export_dialog(h);
let at = empty_spot(&h);
h.request("ui.click", json!({"x": at.x, "y": at.y}), T);
play(&mut h);
assert!(h.app.ui.dialog.is_some(), "the bar is not the backdrop");
let below = egui::pos2(at.x, widget(&h, "region:titlebar").bottom() + 60.0);
h.request("ui.click", json!({"x": below.x, "y": below.y}), T);
play(&mut h);
assert!(h.app.ui.dialog.is_none(), "the backdrop below it still closes the dialog");
}
// Scenario: the bar's controls take no clicks under a dialog
#[test]
fn the_title_bar_buttons_are_inactive_under_a_dialog() {
let mut h = with_export_dialog(integrated());
let left = h.app.ui.left_panel;
let at = widget(&h, "icon:sidebar").center();
h.request("ui.click", json!({"x": at.x, "y": at.y}), T);
play(&mut h);
assert_eq!(h.app.ui.left_panel, left, "the sidebar button does nothing");
assert!(h.app.ui.dialog.is_some());
}
// Scenario: dragging the empty bar still moves the window under a dialog, whether the dialog is
// tall enough to reach into the bar (Export) or not (Copy Settings)
#[test]
fn dragging_the_empty_bar_moves_the_window_under_a_dialog() {
for command in ["dialog.export", "dialog.copySettings"] {
let mut h = integrated();
h.app.run(command, json!({})).unwrap();
h.step();
h.step();
h.settle(T);
let p = empty_spot(&h);
h.window_commands.clear();
h.request("ui.drag", json!({"x": p.x, "y": p.y, "toX": p.x + 120.0, "toY": p.y + 40.0}), T);
play(&mut h);
assert_eq!(h.window_commands, vec![ViewportCommand::StartDrag], "{command}");
}
}
// Scenario: a tall dialog reaching into the bar keeps a press on itself from moving the window
// (AppKit's `movable` is off while the pointer is over it), the bar beside it still moves it
#[test]
fn a_dialog_inside_the_bar_keeps_the_window_from_moving() {
let mut h = with_export_dialog(integrated());
let bar = widget(&h, "region:titlebar");
let window = widget(&h, "dialog:window");
assert!(window.top() < bar.bottom(), "the dialog reaches into the bar");
let hover = |h: &mut Headless, p: egui::Pos2| {
h.events.push(egui::Event::PointerMoved(p));
play(h);
craft_window::title_bar::window_movable(&h.view.ctx)
};
let spot = empty_spot(&h);
assert!(hover(&mut h, spot), "the bar beside the dialog moves the window");
assert!(!hover(&mut h, egui::pos2(window.center().x, bar.center().y)), "the dialog over the bar does not");
}
+3 -2
View File
@@ -1,6 +1,6 @@
# Lightroom parity checklist
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-25 · **Change:** minor (LR-BEHAV-TITLEBAR: a double-click follows the system setting, and a panel over the bar keeps the window still; KEYC-METADATA, LRC-LIB-KEYWORDS: ⌥0 / ⌥⇧0 go to the next / previous keyword set; LRC-DEV-HISTOGRAM-DRAG: the histogram's five tonal zones — hover for the value, drag to adjust the Basic control the press locked, double-click to reset; LR-VIEW-HISTOGRAM note updated; MENU-BAR: on macOS a menu item that yields its key to a focused text field or to shortcut recording really lets it go; LR-MERGE-HDR / LR-MERGE-PANO: Lanczos-3 warps; LR-IMP-LOCAL: browsing from the sidebar records the folder; LR-VIEW-ZOOM: only a full-size drag within 20 ms clears a slow-drag verdict; LR-IMP-ADD-DIALOG: hierarchical import album destination reconciled with main, #2362; KEY-SLIDER-NUDGE: vertical wheel nudges need a click or drag in the row; leaving it disarms them; LR-EDIT-OPTICS-PROFILE: Fujifilm nine-knot lens tables read at the plain radius; LR-VIEW-ZOOM: only a full-size drag within 20 ms clears a slow-drag verdict; LRC-LIB-LIBFOLDERS, LR-BEHAV-BG-TASKS: Synchronize Folder's scan shows its folder listing and stops it on ✕; LRC-LIB-LIBFOLDERS: Synchronize Folder says a folder is up to date; LR-LIB-STACK: filmstrip stack badge click; LRC-LIB-REFVIEW / CATALOG-SWITCH: Escape preserves edits; catalog-local pins; deleted and malformed references refused; LRC-LIB-COMPARE: the Info panel labels the active photo while culling, #2398; KEYC-RATING: `\` shows / hides the Filter Bar in the grids; LR-VIEW-PHOTOGRID: the grid reads only the photos an import batch or an edit touched, not the whole list; earlier: LRC-PRINT-PAGE: Print Page Options; LR-META-XMP: fewer false unimported-XMP warnings; KEYC-METADATA: ⌘K / Ctrl+K Add Keywords; LRC-DEV-HISTOGRAM-DRAG: the histogram's five tonal zones — hover for the value, drag to adjust the Basic control the press locked, double-click to reset; LR-VIEW-HISTOGRAM note updated; MENU-BAR: on macOS a menu item that yields its key to a focused text field or to shortcut recording really lets it go; LR-MERGE-HDR / LR-MERGE-PANO: Lanczos-3 warps; LR-IMP-LOCAL: browsing from the sidebar records the folder; LR-VIEW-ZOOM: only a full-size drag within 20 ms clears a slow-drag verdict; LR-IMP-ADD-DIALOG: hierarchical import album destination reconciled with main, #2362; KEY-SLIDER-NUDGE: vertical wheel nudges need a click or drag in the row; leaving it disarms them; LR-EDIT-OPTICS-PROFILE: Fujifilm nine-knot lens tables read at the plain radius; LR-VIEW-ZOOM: only a full-size drag within 20 ms clears a slow-drag verdict; LRC-LIB-LIBFOLDERS, LR-BEHAV-BG-TASKS: Synchronize Folder's scan shows its folder listing and stops it on ✕; LRC-LIB-LIBFOLDERS: Synchronize Folder says a folder is up to date; LR-LIB-STACK: filmstrip stack badge click; LRC-LIB-REFVIEW / CATALOG-SWITCH: Escape preserves edits; catalog-local pins; deleted and malformed references refused; LRC-LIB-COMPARE: the Info panel labels the active photo while culling, #2398; KEYC-RATING: `\` shows / hides the Filter Bar in the grids; LR-VIEW-PHOTOGRID: the grid reads only the photos an import batch or an edit touched, not the whole list; earlier: LRC-PRINT-PAGE: Print Page Options; LR-META-XMP: fewer false unimported-XMP warnings) · **Target:** Adobe Lightroom Classic 15.5 / Lightroom 9.6
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-29 · **Change:** minor (LR-BEHAV-TITLEBAR: a dialog leaves the title bar undimmed, as a macOS sheet does; LR-BEHAV-TITLEBAR: a double-click follows the system setting, and a panel over the bar keeps the window still; KEYC-METADATA, LRC-LIB-KEYWORDS: ⌥0 / ⌥⇧0 go to the next / previous keyword set; LRC-DEV-HISTOGRAM-DRAG: the histogram's five tonal zones — hover for the value, drag to adjust the Basic control the press locked, double-click to reset; LR-VIEW-HISTOGRAM note updated; MENU-BAR: on macOS a menu item that yields its key to a focused text field or to shortcut recording really lets it go; LR-MERGE-HDR / LR-MERGE-PANO: Lanczos-3 warps; LR-IMP-LOCAL: browsing from the sidebar records the folder; LR-VIEW-ZOOM: only a full-size drag within 20 ms clears a slow-drag verdict; LR-IMP-ADD-DIALOG: hierarchical import album destination reconciled with main, #2362; KEY-SLIDER-NUDGE: vertical wheel nudges need a click or drag in the row; leaving it disarms them; LR-EDIT-OPTICS-PROFILE: Fujifilm nine-knot lens tables read at the plain radius; LR-VIEW-ZOOM: only a full-size drag within 20 ms clears a slow-drag verdict; LRC-LIB-LIBFOLDERS, LR-BEHAV-BG-TASKS: Synchronize Folder's scan shows its folder listing and stops it on ✕; LRC-LIB-LIBFOLDERS: Synchronize Folder says a folder is up to date; LR-LIB-STACK: filmstrip stack badge click; LRC-LIB-REFVIEW / CATALOG-SWITCH: Escape preserves edits; catalog-local pins; deleted and malformed references refused; LRC-LIB-COMPARE: the Info panel labels the active photo while culling, #2398; KEYC-RATING: `\` shows / hides the Filter Bar in the grids; LR-VIEW-PHOTOGRID: the grid reads only the photos an import batch or an edit touched, not the whole list; earlier: LRC-PRINT-PAGE: Print Page Options; LR-META-XMP: fewer false unimported-XMP warnings; KEYC-METADATA: ⌘K / Ctrl+K Add Keywords; LRC-DEV-HISTOGRAM-DRAG: the histogram's five tonal zones — hover for the value, drag to adjust the Basic control the press locked, double-click to reset; LR-VIEW-HISTOGRAM note updated; MENU-BAR: on macOS a menu item that yields its key to a focused text field or to shortcut recording really lets it go; LR-MERGE-HDR / LR-MERGE-PANO: Lanczos-3 warps; LR-IMP-LOCAL: browsing from the sidebar records the folder; LR-VIEW-ZOOM: only a full-size drag within 20 ms clears a slow-drag verdict; LR-IMP-ADD-DIALOG: hierarchical import album destination reconciled with main, #2362; KEY-SLIDER-NUDGE: vertical wheel nudges need a click or drag in the row; leaving it disarms them; LR-EDIT-OPTICS-PROFILE: Fujifilm nine-knot lens tables read at the plain radius; LR-VIEW-ZOOM: only a full-size drag within 20 ms clears a slow-drag verdict; LRC-LIB-LIBFOLDERS, LR-BEHAV-BG-TASKS: Synchronize Folder's scan shows its folder listing and stops it on ✕; LRC-LIB-LIBFOLDERS: Synchronize Folder says a folder is up to date; LR-LIB-STACK: filmstrip stack badge click; LRC-LIB-REFVIEW / CATALOG-SWITCH: Escape preserves edits; catalog-local pins; deleted and malformed references refused; LRC-LIB-COMPARE: the Info panel labels the active photo while culling, #2398; KEYC-RATING: `\` shows / hides the Filter Bar in the grids; LR-VIEW-PHOTOGRID: the grid reads only the photos an import batch or an edit touched, not the whole list; earlier: LRC-PRINT-PAGE: Print Page Options; LR-META-XMP: fewer false unimported-XMP warnings) · **Target:** Adobe Lightroom Classic 15.5 / Lightroom 9.6
The measured, row-by-row checklist: one row per Lightroom feature, menu item and shortcut, what we
have and what is missing. It answers *does the feature exist?* (feature breadth). Whether it is good
@@ -485,7 +485,7 @@ differences and missing bindings are in [ui-parity.md](ui-parity.md#shortcuts).
| LR-BEHAV-LEARN | Tutorials | OOS | 🚫 | | |
| LR-BEHAV-WHATSNEW | What's new | P2 | ✅ | `cmd:app.whatsNew`, `docs/whats-new.md` | Help ▸ What's New: release highlights |
| LR-BEHAV-AI-EA | Early-access badges | P2 | ⬜ | | |
| LR-BEHAV-TITLEBAR | Title bar drag and double-click zoom (macOS) | P2 | 🟡 | `crates/ui-egui/src/panels/topbar.rs`, `crates/ui-egui/src/tests/titlebar.rs` | the native title bar is hidden on macOS, so the top bar's empty space (including the traffic-light margin) moves the window and a double-click does what System Settings › “Double-click a window's title bar to” says (zoom or restore, minimize, nothing; craft-window's `title_bar`); buttons and the search field keep their clicks; ignored in full screen, where the traffic lights are gone and the bar's left buttons move into their space (#1763). A press that starts on a button, the search field or a panel floating over the bar never moves the window (AppKit's `movable` is off while the pointer is there). Known gap: egui-winit reads the zoomed state only at start-up and after our own `Maximized` command, so a window zoomed another way (green button, Window ▸ Zoom, snapping) makes the first double-click a no-op before the toggle catches up. Checked by hand on a real macOS window (drag, zoom, restore) |
| LR-BEHAV-TITLEBAR | Title bar drag and double-click zoom (macOS) | P2 | 🟡 | `crates/ui-egui/src/panels/topbar.rs`, `crates/ui-egui/src/tests/titlebar.rs` | the native title bar is hidden on macOS, so the top bar's empty space (including the traffic-light margin) moves the window and a double-click does what System Settings › “Double-click a window's title bar to” says (zoom or restore, minimize, nothing; craft-window's `title_bar`); buttons and the search field keep their clicks; ignored in full screen, where the traffic lights are gone and the bar's left buttons move into their space (#1763). A press that starts on a button, the search field or a panel floating over the bar never moves the window (AppKit's `movable` is off while the pointer is there). While a dialog is open the bar is not dimmed, so it stays level with the window buttons AppKit draws over it (as under a macOS sheet): its controls are inactive, a click on it does not close the dialog, and its empty space still moves the window; not on a window with its native title bar, nor in full screen. Known gap: egui-winit reads the zoomed state only at start-up and after our own `Maximized` command, so a window zoomed another way (green button, Window ▸ Zoom, snapping) makes the first double-click a no-op before the toggle catches up. Checked by hand on a real macOS window (drag, zoom, restore) |
## Y. Menus
@@ -959,3 +959,4 @@ Latin stays upright. Advanced Japanese composition remains open. Regression cove
| 2026-10-23 | patch | LR-BEHAV-ACCESS: the name field of New Album, New Smart Album, Rename and the other one-field dialogs takes the keyboard focus once when the dialog opens instead of every frame, so Tab and Shift+Tab reach the check box, Cancel and OK; status unchanged (🟡) |
| 2026-10-22 | minor | LR-CROP-AUTO: Auto straighten turns by at most 10° and only on at least 3 agreeing lines, and says when it finds nothing to level by; measured on 68 photos straightened by hand and 300 left as shot, unwanted turns of more than 1° fell from 79 to 19 of the 300. Downgraded ✅ → 🟡: it still leaves most tilted photos alone |
| 2026-10-23 | patch | LRC-LIB-FILTERBAR: showing an album (`library.source`) while the filter holds an album drops the filter's album, as showing a library folder already dropped its folder filter; before, the old album stayed in the filter unseen (the filter bar has no album chip) and narrowed the next source such as All Photos; the row's note says so; status unchanged (✅) |
| 2026-10-29 | patch | LR-BEHAV-TITLEBAR: a dialog's backdrop leaves the integrated title bar undimmed, as a macOS sheet does (the bar's controls stay inactive, a click on it is not a click outside the dialog, dragging its empty space still moves the window); status unchanged (🟡) |
+8
View File
@@ -1,5 +1,13 @@
# What's new in LightCraft
## 2026-10-29
### A dialog no longer dims the macOS title bar
- On macOS the top bar is the window's title bar, and the window buttons drawn over it stayed bright while a dialog dimmed
the bar under them. As under a macOS sheet, the dialog's backdrop now leaves the bar alone: its buttons are inactive, a
click on it does not close the dialog, and dragging its empty space still moves the window. Windows, Linux and full
screen are unchanged.
## 2026-10-24
### Relative-date filters and smart albums follow the clock