Track per-app launch counts in ~/.cache/breadbox/history.json. When a
query is active, sort visible results by fuzzy match quality (exact >
prefix > contains > subsequence) then by launch count descending, so
the most relevant and most-used app rises to the top. The base list
(no query) also surfaces most-launched apps above unvisited ones.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- breadbox/Cargo.toml: depend on bread-theme with gtk feature
- breadbox/src/main.rs: remove local Palette + hex_to_rgba; use
bread_theme::{load_palette, hex_to_rgba, gtk::apply_user_css}
- bakery.toml: describes breadbox for bakery install
- release.yml: builds on hestia self-hosted runner, publishes binaries to
dl.breadway.dev and GitHub Releases on v* tags
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The backdrop approach failed because a GTK4 window with no child widget
gets an empty Wayland input region, so pointer events passed straight
through it rather than being delivered to the GestureClick handler.
Replace with a single full-screen window (anchored to all 4 edges,
transparent background). The launcher UI (vbox) is 700 px wide,
halign=Center, valign=Start — visually identical to before. A
GestureClick on the window closes it when (x,y) falls outside the
vbox's allocation rectangle; clicks inside the vbox reach child widgets
normally and don't trigger the close path.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
EventControllerFocus::connect_leave was firing whenever the pointer left
the launcher surface because Hyprland's focus-follows-mouse hands keyboard
focus back to the window under the cursor (OnDemand mode).
Fix: introduce a full-screen transparent backdrop window at Layer::Top.
The launcher sits at Layer::Overlay (above it), so the backdrop never
intercepts launcher clicks. Clicking anywhere outside the launcher hits
the backdrop and closes both windows via a shared Rc<dyn Fn()> callback.
The launcher returns to KeyboardMode::Exclusive so the compositor can no
longer steal focus on pointer leave. EventControllerFocus is removed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- KeyboardMode::Exclusive → OnDemand: with Exclusive the compositor
never sends wl_keyboard::leave, so EventControllerFocus::connect_leave
never fires. OnDemand lets Hyprland hand focus back on click-outside.
- Move EventControllerKey from search to window, capture phase: bubble
phase on SearchEntry let its own handlers consume Enter and arrows
first. Capture phase on the window intercepts all keys before any
widget sees them, so Enter/Up/Down/Esc always reach our handler.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Switch KeyboardMode to Exclusive so Hyprland hands keyboard focus to
breadbox immediately on creation. Add an EventControllerFocus on the
window that calls close() the moment focus leaves (click outside,
alt-tab, compositor focus change, etc.).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove the wofi subprocess entirely. The launcher now renders its own
Wayland overlay window via gtk4 + gtk4-layer-shell: a SearchEntry at
the top with live fuzzy filtering, a ListBox of results below, and
keyboard navigation (Enter/Esc/arrows). Toggle (keybind press while
open closes it) is handled via a PID file in $XDG_RUNTIME_DIR.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Zero-dependency Rust rewrite of the breadboard launcher. Parses
.desktop files in-process (no awk subprocesses), builds a tab-separated
cache for wofi dmenu, and supports stale-while-revalidate background
rebuilds. Apps-only for now; icon support to be added later.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>