Skip to content

fix(ui): square uncomposited popovers and preview path-bar files - #1912

Merged
l0gicgate merged 5 commits into
mainfrom
fix/1911-uncomposited-popups-and-path-preview
Oct 28, 2026
Merged

l0gicgate merged 5 commits into
mainfrom
fix/1911-uncomposited-popups-and-path-preview

Conversation

@JoeJoeflyn

@JoeJoeflyn JoeJoeflyn commented Oct 27, 2026 •

Copy link
Copy Markdown
Collaborator

Description

  1. On uncomposited X11 displays (without a compositing window manager), transparent pixels cannot be alpha-blended and render as solid black #000000, causing popovers and context menus to display black shadow padding frames and clipped black corner tips. This change detects !display.is_composited() via a dynamic CSS provider and sets box-shadow: none; border-radius: 0; so popovers are crisp with squared borders.
  2. When submitting a file path directly in the path/location bar, the browser reveals the file inside its parent directory and now automatically dispatches a Quick Preview request so the user can immediately view its contents.

Visual evidence

option-b-comparison
screenrecording-2026-10-28_03-49-24.mp4

How to test

  1. Launch Strata on an uncomposited X11 display (or in a bare Xvfb / openbox session without picom/compton). Right-click on a file or folder.
  2. Confirm the context menu has square right-angle corners without any black borders or clipped black corner artifacts.
  3. In the path bar (Ctrl+L), paste or type an exact file path (e.g. /path/to/image.png) and press Enter.

Expected result:
Popovers and menus on uncomposited X11 render clean square borders without black frames or pixel clipping. Submitting a file path navigates to the parent directory, focuses the file, and immediately opens Quick Preview for it.

Related issue

Closes #1911

@github-actions github-actions Bot added the fix label Oct 27, 2026
Remove box-shadow and square popup corners on uncomposited X11 displays to eliminate black framing and corner artifacts. Request quick preview automatically when a file path is submitted in the location bar.

Closes #1911
@JoeJoeflyn
JoeJoeflyn force-pushed the fix/1911-uncomposited-popups-and-path-preview branch from e83a741 to 0f789ac Compare October 27, 2026 21:05
Navigating away before a typed file path finished revealing left the preview
target set, so a later selection of that file opened Quick Preview unasked.
Clearing it on a navigation whose selection does not target the file also
re-borrowed the RefCell it was reading, which panicked.
The peek panel is an in-window widget, so its shadow renders fine without a
compositor; only tooltip and popover surfaces need the fallback.
…e menu baseline

The context-menu baseline is captured on an uncomposited Xvfb display, so it
showed the black shadow frame the fallback removes.
@wmfeht

wmfeht commented Oct 27, 2026

Copy link
Copy Markdown
Collaborator

Review

Requesting changes. The uncomposited popover CSS matches the widgets that own the black frame, and it stays under the user stylesheet. Path-bar Quick Preview crashes if another navigation happens before the parent folder selects the file.

High

src/app/browser.rs:1708 borrows preview_revealed_location for the whole if and then take()s it in the body. On Rust 2024 that temporary still lives through the body, so this panics with RefCell already borrowed.

Reproduced: navigate_input of a file whose parent validation is still pending (NestedValidationSource), then browser.navigate to another folder. Backtrace is Browser::navigate_for_selection at src/app/browser.rs:1711.

The flag is set at src/app/browser.rs:1415 before the parent probe. Local validation awaits probes::folder, so the main loop runs in between. Sidebar navigation, a second path-bar submit, and navigate_to_ancestor all enter navigate_for_selection. The check also runs before the already-open early return.

Clone the location out of the cell before take().

Also clear the token in descend_with_selection (src/app/browser.rs:1758) and restore_path (src/app/browser.rs:3976). Both abort the parent probe and leave the flag set, so the next folder navigation hits the same panic. Clear it in the browser when validation fails too. The view's abandon_deferred_reveal (src/ui/browser/events.rs:1065) only covers some errors.

Medium

Drop .peek-popover from UNCOMPOSITED_CSS (src/ui/theme.rs:50). That class is the in-window folder-peek card (src/ui/browser/peek.rs:348). Its shadow is drawn in the parent window and already blends without a compositor. The rule squares peek on uncomposited X11.

tooltip, popover, and popover contents are the right nodes. Menu shadows in src/style.css (.folder-context-popover contents and the column, jobs, and path-completion popovers) sit on contents, and this provider is above the base sheet.

Low

The new tests return only after a synchronous source has selected the file. Please cover a still-pending parent probe followed by navigate, and descend or Back during that probe.

docs/themes.md should mention this sheet directly under the user stylesheet, since a user popover shadow brings the black frame back. On an uncomposited display these rules also force popup radii to 0, which docs/preferences.md currently describes as following corner roundness.

@l0gicgate

Copy link
Copy Markdown
Contributor

Review and cleanup

Merged main at 86df474dc (no conflicts).

Review against the description and #1911.

  • Uncomposited popups: confirmed. The CSS fallback and the live composited notify hook work as described. The .peek-popover selector was dropped from the fallback: the peek panel is an in-window revealer, not a popup surface, so its shadow and corners render fine without a compositor and squaring it was an unrelated regression. popover > contents was redundant with popover contents.
  • Typed file path opens Quick Preview: confirmed, with two defects fixed (below). The preview intent is still tracked as a side-channel field that every navigation path has to clear; a follow-up could carry it on the reveal selection itself.
  • The committed context-menu QA baseline is captured on bare Xvfb, which is uncomposited, so it showed exactly the black frame this PR removes. CI did not catch the drift because the QA job only runs on workflow_dispatch. The baseline is regenerated, and the typed-path scenario now asserts the preview.

Fixes pushed

  • 0e8c08e22 fix(browser): drop a pending typed-path preview when navigation moves on. navigate_for_selection called take() while still holding the borrow() from the if let scrutinee, so navigating anywhere else while a typed path's parent validation was pending panicked with RefCell already borrowed. History restores (restore_path), descents (descend_with_selection), and a parent validation rejected with a non-mount error also left the target set, so a later selection of that file opened Quick Preview unasked. Covered by location_input::leaving_a_pending_typed_file_reveal_drops_its_preview (history, navigate, rejected, descend routes); each fix was checked to fail the test when reverted on its own.
  • a2c5d64b6 fix(theme): limit the uncomposited fallback to popup surfaces, document it in docs/themes.md, and tighten the two doc comments.
  • 635a321fa test(qa): list-typed-file-path now waits for the Quick Preview; context-menu baseline regenerated with STRATA_QA_UPDATE_BASELINES=1 and reviewed (square corners, no frame).

Validation

  • ./scripts/test-headless.py -- app::browser::tests ui::theme::tests — 346 passed
  • ./scripts/test-headless.py location_input — 30 passed
  • ./scripts/qa.sh --test-threads 6 context-menu-baseline icons-hover-baseline icons-view-baseline list-view-baseline columns-view-baseline columns-overflow-baseline selection-and-focus-baseline delete-confirmation-baseline icons-airy-view-baseline list-typed-file-path — 10 passed
  • ./scripts/quality.sh fmt, ./scripts/quality.sh clippy — clean
  • git diff --check — clean

Follow-ups outside this PR

  • install_provider connects a notify::composited handler per ThemeManager and never disconnects it; harmless for the single shared manager, but tests build many managers (they already accumulate CSS providers the same way).
  • A typed path to a non-previewable file still enables the preview drawer, the same as pressing Space on it; not changed here.

CI: all checks green on attempt 3 of run 40601724020. Attempt 1 lost Rust tests shard 2 (the test process died with no failing test while unrelated services::document and media tests were in flight) and Rust tests shard 3 (progress::tests::minimization::deletion::fast_delete_animates_only_its_own_success_without_showing_progress hit its 30 s pump deadline; it passes locally in about 7.5 s). A full rerun of the identical commit passed every shard. Note that gh run rerun --failed cannot rerun shards in this workflow: they download quality-bundle-<attempt>, which only a full rerun rebuilds.

@l0gicgate
l0gicgate merged commit bd6cd37 into main Oct 28, 2026
23 of 29 checks passed
@l0gicgate
l0gicgate deleted the fix/1911-uncomposited-popups-and-path-preview branch October 28, 2026 02:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(ui): uncomposited X11 popups show black frame and path-bar files do not preview

3 participants