breadbox: replace wofi with native GTK4 layer-shell UI
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>
This commit is contained in:
parent
d94a00d982
commit
30e40ec54f
3 changed files with 1057 additions and 90 deletions
720
Cargo.lock
generated
720
Cargo.lock
generated
|
|
@ -2,6 +2,726 @@
|
|||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3"
|
||||
|
||||
[[package]]
|
||||
name = "breadbox"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"gtk4",
|
||||
"gtk4-layer-shell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cairo-rs"
|
||||
version = "0.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5cc8d9aa793480744cd9a0524fef1a2e197d9eaa0f739cde19d16aba530dcb95"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cairo-sys-rs",
|
||||
"glib",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cairo-sys-rs"
|
||||
version = "0.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8b4985713047f5faee02b8db6a6ef32bbb50269ff53c1aee716d1d195b76d54"
|
||||
dependencies = [
|
||||
"glib-sys",
|
||||
"libc",
|
||||
"system-deps",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-expr"
|
||||
version = "0.20.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c6b04e07d8080154ed4ac03546d9a2b303cc2fe1901ba0b35b301516e289368"
|
||||
dependencies = [
|
||||
"smallvec",
|
||||
"target-lexicon",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
||||
|
||||
[[package]]
|
||||
name = "field-offset"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f"
|
||||
dependencies = [
|
||||
"memoffset",
|
||||
"rustc_version",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-channel"
|
||||
version = "0.3.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-core"
|
||||
version = "0.3.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d"
|
||||
|
||||
[[package]]
|
||||
name = "futures-executor"
|
||||
version = "0.3.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-task",
|
||||
"futures-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-io"
|
||||
version = "0.3.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718"
|
||||
|
||||
[[package]]
|
||||
name = "futures-macro"
|
||||
version = "0.3.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-task"
|
||||
version = "0.3.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393"
|
||||
|
||||
[[package]]
|
||||
name = "futures-util"
|
||||
version = "0.3.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-macro",
|
||||
"futures-task",
|
||||
"pin-project-lite",
|
||||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gdk-pixbuf"
|
||||
version = "0.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25f420376dbee041b2db374ce4573892a36222bb3f6c0c43e24f0d67eae9b646"
|
||||
dependencies = [
|
||||
"gdk-pixbuf-sys",
|
||||
"gio",
|
||||
"glib",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gdk-pixbuf-sys"
|
||||
version = "0.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48f31b37b1fc4b48b54f6b91b7ef04c18e00b4585d98359dd7b998774bbd91fb"
|
||||
dependencies = [
|
||||
"gio-sys",
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"libc",
|
||||
"system-deps",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gdk4"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd42fdbbf48612c6e8f47c65fb92d2e8f39c25aecd6af047e83897c1a22d2a4e"
|
||||
dependencies = [
|
||||
"cairo-rs",
|
||||
"gdk-pixbuf",
|
||||
"gdk4-sys",
|
||||
"gio",
|
||||
"gl",
|
||||
"glib",
|
||||
"libc",
|
||||
"pango",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gdk4-sys"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d974ac4f15e67472c3a9728daf612590b4a5762a4b33f0edd298df0b80d043c"
|
||||
dependencies = [
|
||||
"cairo-sys-rs",
|
||||
"gdk-pixbuf-sys",
|
||||
"gio-sys",
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"libc",
|
||||
"pango-sys",
|
||||
"pkg-config",
|
||||
"system-deps",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gio"
|
||||
version = "0.22.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3848bcba3a35cc0a71df8ba8ecfd799d6bfb862342a53a4a915fb62213aa4e6"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-io",
|
||||
"futures-util",
|
||||
"gio-sys",
|
||||
"glib",
|
||||
"libc",
|
||||
"pin-project-lite",
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gio-sys"
|
||||
version = "0.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "64729ba2772c080448f9f966dba8f4456beeb100d8c28a865ef8a0f2ef4987e1"
|
||||
dependencies = [
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"libc",
|
||||
"system-deps",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gl"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a94edab108827d67608095e269cf862e60d920f144a5026d3dbcfd8b877fb404"
|
||||
dependencies = [
|
||||
"gl_generator",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gl_generator"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d"
|
||||
dependencies = [
|
||||
"khronos_api",
|
||||
"log",
|
||||
"xml-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glib"
|
||||
version = "0.22.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c207e04e51605dcf7b2924c41591b3a10e1438eaac5bcf448fb91f325381104a"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-executor",
|
||||
"futures-task",
|
||||
"futures-util",
|
||||
"gio-sys",
|
||||
"glib-macros",
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"libc",
|
||||
"memchr",
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glib-macros"
|
||||
version = "0.22.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "506d23499707c7142898429757e8d9a3871d965239a2cb66dfa05052be6d6f19"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glib-sys"
|
||||
version = "0.22.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f7fbac234ed5bc2a28359b7bde8e1b9cdf1441cc2d7f068e4824672d7db9445"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"system-deps",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gobject-sys"
|
||||
version = "0.22.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22a861859b887a79cf461359c192c97a57d8fb0229dd291232e57aa11f6fa72c"
|
||||
dependencies = [
|
||||
"glib-sys",
|
||||
"libc",
|
||||
"system-deps",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "graphene-rs"
|
||||
version = "0.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7d1b7881f96869f49808b6adfe906a93a57a34204952253444d68c3208d71f1"
|
||||
dependencies = [
|
||||
"glib",
|
||||
"graphene-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "graphene-sys"
|
||||
version = "0.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "517f062f3fd6b7fd3e57a3f038a74b3c23ca32f51199ff028aa704609943f79c"
|
||||
dependencies = [
|
||||
"glib-sys",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
"system-deps",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gsk4"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53c912dfcbd28acace5fc99c40bb9f25e1dcb73efb1f2608327f66a99acdcb62"
|
||||
dependencies = [
|
||||
"cairo-rs",
|
||||
"gdk4",
|
||||
"glib",
|
||||
"graphene-rs",
|
||||
"gsk4-sys",
|
||||
"libc",
|
||||
"pango",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gsk4-sys"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7d54bbc7a9d8b6ffe4f0c95eede15ccfb365c8bf521275abe6bcfb57b18fb8a"
|
||||
dependencies = [
|
||||
"cairo-sys-rs",
|
||||
"gdk4-sys",
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"graphene-sys",
|
||||
"libc",
|
||||
"pango-sys",
|
||||
"system-deps",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gtk4"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7181b837f04cbe93f79441475f7a00560a92cba7a72e38cc1a68b6f8b78eaae2"
|
||||
dependencies = [
|
||||
"cairo-rs",
|
||||
"field-offset",
|
||||
"futures-channel",
|
||||
"gdk-pixbuf",
|
||||
"gdk4",
|
||||
"gio",
|
||||
"glib",
|
||||
"graphene-rs",
|
||||
"gsk4",
|
||||
"gtk4-macros",
|
||||
"gtk4-sys",
|
||||
"libc",
|
||||
"pango",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gtk4-layer-shell"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4069987ff4793699511a251028cc336b438e46565b463f111250148d574752a"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"gdk4",
|
||||
"glib",
|
||||
"glib-sys",
|
||||
"gtk4",
|
||||
"gtk4-layer-shell-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gtk4-layer-shell-sys"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f566a5ec5bcc454e7fcf2ab76930887ced5365afce12c1e5201bb296b95f1b9"
|
||||
dependencies = [
|
||||
"gdk4-sys",
|
||||
"glib-sys",
|
||||
"gtk4-sys",
|
||||
"libc",
|
||||
"system-deps",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gtk4-macros"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3581b242ba62fdff122ebb626ea641582ec326031622bd19d60f85029c804a87"
|
||||
dependencies = [
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gtk4-sys"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20ba8e695e2640455561274e65e45f0a151619e450746007667f4b23ceae4e1b"
|
||||
dependencies = [
|
||||
"cairo-sys-rs",
|
||||
"gdk-pixbuf-sys",
|
||||
"gdk4-sys",
|
||||
"gio-sys",
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"graphene-sys",
|
||||
"gsk4-sys",
|
||||
"libc",
|
||||
"pango-sys",
|
||||
"system-deps",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.17.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "khronos_api"
|
||||
version = "3.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.186"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pango"
|
||||
version = "0.22.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "251bdc6e6487b811be0e406a21e301e07e45c0aa8fa39e00c0c8e12a91752438"
|
||||
dependencies = [
|
||||
"gio",
|
||||
"glib",
|
||||
"libc",
|
||||
"pango-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pango-sys"
|
||||
version = "0.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbd111a20ca90fedf03e09c59783c679c00900f1d8491cca5399f5e33609d5d6"
|
||||
dependencies = [
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"libc",
|
||||
"system-deps",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-crate"
|
||||
version = "3.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f"
|
||||
dependencies = [
|
||||
"toml_edit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.106"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
|
||||
dependencies = [
|
||||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
|
||||
|
||||
[[package]]
|
||||
name = "serde_core"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_spanned"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.15.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.117"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "system-deps"
|
||||
version = "7.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "396a35feb67335377e0251fcbc1092fc85c484bd4e3a7a54319399da127796e7"
|
||||
dependencies = [
|
||||
"cfg-expr",
|
||||
"heck",
|
||||
"pkg-config",
|
||||
"toml",
|
||||
"version-compare",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "target-lexicon"
|
||||
version = "0.13.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df7f62577c25e07834649fc3b39fafdc597c0a3527dc1c60129201ccfcbaa50c"
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "1.1.2+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"serde_core",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"toml_parser",
|
||||
"toml_writer",
|
||||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "1.1.1+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.25.11+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"toml_datetime",
|
||||
"toml_parser",
|
||||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_parser"
|
||||
version = "1.1.2+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526"
|
||||
dependencies = [
|
||||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_writer"
|
||||
version = "1.1.1+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||
|
||||
[[package]]
|
||||
name = "version-compare"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "03c2856837ef78f57382f06b2b8563a2f512f7185d732608fd9176cb3b8edf0e"
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.61.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xml-rs"
|
||||
version = "0.8.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f"
|
||||
|
|
|
|||
|
|
@ -2,3 +2,7 @@
|
|||
name = "breadbox"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
gtk4 = "0.11"
|
||||
gtk4-layer-shell = "0.8"
|
||||
|
|
|
|||
423
src/main.rs
423
src/main.rs
|
|
@ -8,17 +8,62 @@ use std::{
|
|||
time::{SystemTime, UNIX_EPOCH},
|
||||
};
|
||||
|
||||
use gtk4::{
|
||||
gdk::Display,
|
||||
glib,
|
||||
pango::EllipsizeMode,
|
||||
prelude::*,
|
||||
Application, ApplicationWindow, Box as GBox, CssProvider, EventControllerKey, Label,
|
||||
ListBox, Orientation, PolicyType, ScrolledWindow, SearchEntry, SelectionMode,
|
||||
};
|
||||
use gtk4_layer_shell::{Edge, KeyboardMode, Layer, LayerShell};
|
||||
|
||||
const CACHE_TIMEOUT_SECS: u64 = 86400;
|
||||
|
||||
const CSS: &str = "
|
||||
window, .background {
|
||||
background-color: #1e1e2e;
|
||||
}
|
||||
searchentry {
|
||||
background-color: #313244;
|
||||
color: #cdd6f4;
|
||||
caret-color: #cba6f7;
|
||||
border: none;
|
||||
outline: none;
|
||||
box-shadow: none;
|
||||
padding: 12px 16px;
|
||||
font-size: 15px;
|
||||
}
|
||||
listbox {
|
||||
background-color: transparent;
|
||||
padding: 4px;
|
||||
}
|
||||
row {
|
||||
padding: 6px 12px;
|
||||
color: #cdd6f4;
|
||||
background-color: transparent;
|
||||
border-radius: 4px;
|
||||
}
|
||||
row:selected {
|
||||
background-color: #45475a;
|
||||
}
|
||||
.action {
|
||||
color: #6c7086;
|
||||
font-size: 12px;
|
||||
}
|
||||
";
|
||||
|
||||
// ---- cache helpers --------------------------------------------------------
|
||||
|
||||
fn home_dir() -> PathBuf {
|
||||
PathBuf::from(env::var("HOME").unwrap_or_else(|_| "/tmp".into()))
|
||||
}
|
||||
|
||||
fn cache_path() -> PathBuf {
|
||||
let dir = env::var("XDG_CACHE_HOME")
|
||||
env::var("XDG_CACHE_HOME")
|
||||
.map(PathBuf::from)
|
||||
.unwrap_or_else(|_| home_dir().join(".cache"));
|
||||
dir.join("breadbox.cache")
|
||||
.unwrap_or_else(|_| home_dir().join(".cache"))
|
||||
.join("breadbox.cache")
|
||||
}
|
||||
|
||||
fn app_dirs() -> [PathBuf; 2] {
|
||||
|
|
@ -41,10 +86,8 @@ fn cache_valid(cache: &Path) -> bool {
|
|||
.unwrap_or_default()
|
||||
.as_secs();
|
||||
let cm = mtime(cache);
|
||||
if now.saturating_sub(cm) >= CACHE_TIMEOUT_SECS {
|
||||
return false;
|
||||
}
|
||||
app_dirs().iter().all(|d| !d.is_dir() || mtime(d) <= cm)
|
||||
now.saturating_sub(cm) < CACHE_TIMEOUT_SECS
|
||||
&& app_dirs().iter().all(|d| !d.is_dir() || mtime(d) <= cm)
|
||||
}
|
||||
|
||||
fn strip_exec_codes(exec: &str) -> String {
|
||||
|
|
@ -69,13 +112,13 @@ fn strip_exec_codes(exec: &str) -> String {
|
|||
out
|
||||
}
|
||||
|
||||
struct App {
|
||||
struct DesktopApp {
|
||||
name: String,
|
||||
exec: String,
|
||||
terminal: bool,
|
||||
}
|
||||
|
||||
fn parse_desktop(path: &Path) -> Option<App> {
|
||||
fn parse_desktop(path: &Path) -> Option<DesktopApp> {
|
||||
let file = File::open(path).ok()?;
|
||||
let mut in_entry = false;
|
||||
let (mut name, mut exec, mut app_type) = (None::<String>, None::<String>, None::<String>);
|
||||
|
|
@ -123,12 +166,12 @@ fn parse_desktop(path: &Path) -> Option<App> {
|
|||
return None;
|
||||
}
|
||||
|
||||
Some(App { name, exec, terminal })
|
||||
Some(DesktopApp { name, exec, terminal })
|
||||
}
|
||||
|
||||
fn build_cache(cache: &Path) {
|
||||
let _ = fs::create_dir_all(cache.parent().unwrap_or(Path::new("/tmp")));
|
||||
let mut apps: HashMap<String, App> = HashMap::new();
|
||||
let mut apps: HashMap<String, DesktopApp> = HashMap::new();
|
||||
|
||||
for dir in &app_dirs() {
|
||||
let Ok(entries) = fs::read_dir(dir) else { continue };
|
||||
|
|
@ -137,9 +180,8 @@ fn build_cache(cache: &Path) {
|
|||
if path.extension().and_then(|e| e.to_str()) != Some("desktop") {
|
||||
continue;
|
||||
}
|
||||
let id = entry.file_name().to_string_lossy().into_owned();
|
||||
if let Some(app) = parse_desktop(&path) {
|
||||
apps.insert(id, app);
|
||||
apps.insert(entry.file_name().to_string_lossy().into_owned(), app);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -162,6 +204,21 @@ fn build_cache(cache: &Path) {
|
|||
}
|
||||
}
|
||||
|
||||
fn load_entries(cache: &Path) -> Vec<(String, String)> {
|
||||
fs::read_to_string(cache)
|
||||
.unwrap_or_default()
|
||||
.lines()
|
||||
.filter_map(|line| {
|
||||
let mut parts = line.splitn(2, '\t');
|
||||
let name = parts.next()?.to_string();
|
||||
let action = parts.next()?.to_string();
|
||||
(!name.is_empty() && !action.is_empty()).then_some((name, action))
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
// ---- launch ---------------------------------------------------------------
|
||||
|
||||
fn pick_terminal() -> String {
|
||||
if let Ok(t) = env::var("TERMINAL") {
|
||||
if !t.is_empty() {
|
||||
|
|
@ -177,83 +234,7 @@ fn pick_terminal() -> String {
|
|||
"xterm".to_string()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let cache = cache_path();
|
||||
|
||||
if env::var("BREADBOX_REBUILD_ONLY").as_deref() == Ok("1") {
|
||||
build_cache(&cache);
|
||||
return;
|
||||
}
|
||||
|
||||
// Toggle: second press closes an open wofi instance
|
||||
if Command::new("pgrep")
|
||||
.args(["-f", "wofi.*breadbox"])
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.status()
|
||||
.map(|s| s.success())
|
||||
.unwrap_or(false)
|
||||
{
|
||||
let _ = Command::new("pkill")
|
||||
.args(["-f", "wofi.*breadbox"])
|
||||
.status();
|
||||
return;
|
||||
}
|
||||
|
||||
// Stale-while-revalidate: never block on a rebuild if cache exists
|
||||
if !cache.exists() {
|
||||
build_cache(&cache);
|
||||
} else if !cache_valid(&cache) {
|
||||
if let Ok(exe) = env::current_exe() {
|
||||
let _ = Command::new(exe)
|
||||
.env("BREADBOX_REBUILD_ONLY", "1")
|
||||
.stdin(Stdio::null())
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.spawn();
|
||||
}
|
||||
}
|
||||
|
||||
let content = fs::read_to_string(&cache).unwrap_or_default();
|
||||
|
||||
let mut child = match Command::new("wofi")
|
||||
.args([
|
||||
"--dmenu",
|
||||
"--parse-search",
|
||||
"--matching",
|
||||
"fuzzy",
|
||||
"--insensitive",
|
||||
"--prompt",
|
||||
"breadbox",
|
||||
])
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::null())
|
||||
.spawn()
|
||||
{
|
||||
Ok(c) => c,
|
||||
Err(_) => return,
|
||||
};
|
||||
|
||||
if let Some(mut stdin) = child.stdin.take() {
|
||||
let _ = write!(stdin, "{}", content);
|
||||
}
|
||||
|
||||
let out = match child.wait_with_output() {
|
||||
Ok(o) => o,
|
||||
Err(_) => return,
|
||||
};
|
||||
|
||||
let choice = std::str::from_utf8(&out.stdout)
|
||||
.unwrap_or("")
|
||||
.trim()
|
||||
.to_string();
|
||||
if choice.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
let action = choice.split('\t').nth(1).unwrap_or("");
|
||||
|
||||
fn do_launch(action: &str) {
|
||||
if let Some(cmd) = action.strip_prefix("app::") {
|
||||
let _ = Command::new("bash")
|
||||
.args(["-c", cmd])
|
||||
|
|
@ -271,3 +252,265 @@ fn main() {
|
|||
.spawn();
|
||||
}
|
||||
}
|
||||
|
||||
// ---- fuzzy matching -------------------------------------------------------
|
||||
|
||||
fn fuzzy_matches(pattern: &str, text: &str) -> bool {
|
||||
if pattern.is_empty() {
|
||||
return true;
|
||||
}
|
||||
let mut chars = text.chars();
|
||||
for pc in pattern.chars() {
|
||||
let pl = pc.to_lowercase().next().unwrap_or(pc);
|
||||
if !chars
|
||||
.by_ref()
|
||||
.any(|tc| tc.to_lowercase().next().unwrap_or(tc) == pl)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
// ---- toggle via pid file --------------------------------------------------
|
||||
|
||||
fn pid_file() -> PathBuf {
|
||||
env::var("XDG_RUNTIME_DIR")
|
||||
.map(PathBuf::from)
|
||||
.unwrap_or_else(|_| PathBuf::from("/tmp"))
|
||||
.join("breadbox.pid")
|
||||
}
|
||||
|
||||
// Returns false if an existing instance was killed (caller should exit).
|
||||
fn toggle_or_continue() -> bool {
|
||||
let pf = pid_file();
|
||||
if let Ok(content) = fs::read_to_string(&pf) {
|
||||
if let Ok(pid) = content.trim().parse::<u32>() {
|
||||
if Path::new(&format!("/proc/{}", pid)).exists() {
|
||||
let _ = Command::new("kill").arg(pid.to_string()).status();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
let _ = fs::write(&pf, std::process::id().to_string());
|
||||
true
|
||||
}
|
||||
|
||||
fn cleanup_pid() {
|
||||
let _ = fs::remove_file(pid_file());
|
||||
}
|
||||
|
||||
// ---- UI -------------------------------------------------------------------
|
||||
|
||||
fn get_row_data(row: >k4::ListBoxRow, key: &str) -> String {
|
||||
unsafe {
|
||||
row.data::<String>(key)
|
||||
.map(|p| p.as_ref().clone())
|
||||
.unwrap_or_default()
|
||||
}
|
||||
}
|
||||
|
||||
fn run_ui(entries: Vec<(String, String)>) {
|
||||
let app = Application::builder()
|
||||
.application_id("com.breadway.breadbox")
|
||||
.build();
|
||||
|
||||
app.connect_activate(move |app| {
|
||||
let provider = CssProvider::new();
|
||||
provider.load_from_data(CSS);
|
||||
gtk4::style_context_add_provider_for_display(
|
||||
&Display::default().expect("no display"),
|
||||
&provider,
|
||||
gtk4::STYLE_PROVIDER_PRIORITY_APPLICATION,
|
||||
);
|
||||
|
||||
let window = ApplicationWindow::builder()
|
||||
.application(app)
|
||||
.default_width(700)
|
||||
.build();
|
||||
|
||||
window.init_layer_shell();
|
||||
window.set_layer(Layer::Overlay);
|
||||
window.set_keyboard_mode(KeyboardMode::OnDemand);
|
||||
window.set_anchor(Edge::Top, true);
|
||||
window.set_exclusive_zone(-1);
|
||||
|
||||
let vbox = GBox::new(Orientation::Vertical, 0);
|
||||
|
||||
let search = SearchEntry::new();
|
||||
search.set_placeholder_text(Some("breadbox"));
|
||||
vbox.append(&search);
|
||||
|
||||
let scroll = ScrolledWindow::new();
|
||||
scroll.set_policy(PolicyType::Never, PolicyType::Automatic);
|
||||
scroll.set_max_content_height(400);
|
||||
scroll.set_propagate_natural_height(true);
|
||||
|
||||
let list = ListBox::new();
|
||||
list.set_selection_mode(SelectionMode::Browse);
|
||||
|
||||
for (name, action) in &entries {
|
||||
let row = gtk4::ListBoxRow::new();
|
||||
let hbox = GBox::new(Orientation::Horizontal, 8);
|
||||
hbox.set_margin_start(4);
|
||||
hbox.set_margin_end(4);
|
||||
|
||||
let name_lbl = Label::new(Some(name));
|
||||
name_lbl.set_xalign(0.0);
|
||||
name_lbl.set_hexpand(true);
|
||||
hbox.append(&name_lbl);
|
||||
|
||||
let action_lbl = Label::new(Some(action));
|
||||
action_lbl.add_css_class("action");
|
||||
action_lbl.set_xalign(1.0);
|
||||
action_lbl.set_ellipsize(EllipsizeMode::End);
|
||||
action_lbl.set_max_width_chars(50);
|
||||
hbox.append(&action_lbl);
|
||||
|
||||
row.set_child(Some(&hbox));
|
||||
unsafe {
|
||||
row.set_data("name", name.clone());
|
||||
row.set_data("action", action.clone());
|
||||
}
|
||||
list.append(&row);
|
||||
}
|
||||
|
||||
if let Some(first) = list.row_at_index(0) {
|
||||
list.select_row(Some(&first));
|
||||
}
|
||||
|
||||
scroll.set_child(Some(&list));
|
||||
vbox.append(&scroll);
|
||||
window.set_child(Some(&vbox));
|
||||
|
||||
// Filter rows on every keystroke
|
||||
let list_f = list.clone();
|
||||
search.connect_changed(move |entry| {
|
||||
let text = entry.text();
|
||||
let query = text.as_str();
|
||||
let mut first_vis: Option<gtk4::ListBoxRow> = None;
|
||||
let mut i = 0i32;
|
||||
while let Some(row) = list_f.row_at_index(i) {
|
||||
let name = get_row_data(&row, "name");
|
||||
let vis = fuzzy_matches(query, &name);
|
||||
row.set_visible(vis);
|
||||
if vis && first_vis.is_none() {
|
||||
first_vis = Some(row);
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
list_f.select_row(first_vis.as_ref());
|
||||
});
|
||||
|
||||
// Keyboard: Esc, Enter, arrows — keep focus in search bar
|
||||
let key_ctrl = EventControllerKey::new();
|
||||
let window_k = window.clone();
|
||||
let list_k = list.clone();
|
||||
key_ctrl.connect_key_pressed(move |_, key, _, _| {
|
||||
use gtk4::gdk::Key;
|
||||
match key {
|
||||
Key::Escape => {
|
||||
cleanup_pid();
|
||||
window_k.close();
|
||||
glib::Propagation::Stop
|
||||
}
|
||||
Key::Return | Key::KP_Enter => {
|
||||
if let Some(row) = list_k.selected_row() {
|
||||
let action = get_row_data(&row, "action");
|
||||
if !action.is_empty() {
|
||||
do_launch(&action);
|
||||
cleanup_pid();
|
||||
window_k.close();
|
||||
}
|
||||
}
|
||||
glib::Propagation::Stop
|
||||
}
|
||||
Key::Down => {
|
||||
let cur = list_k.selected_row().map(|r| r.index()).unwrap_or(-1);
|
||||
let mut i = cur + 1;
|
||||
loop {
|
||||
match list_k.row_at_index(i) {
|
||||
Some(r) if r.is_visible() => {
|
||||
list_k.select_row(Some(&r));
|
||||
break;
|
||||
}
|
||||
Some(_) => i += 1,
|
||||
None => break,
|
||||
}
|
||||
}
|
||||
glib::Propagation::Stop
|
||||
}
|
||||
Key::Up => {
|
||||
let cur = list_k.selected_row().map(|r| r.index()).unwrap_or(0);
|
||||
let mut i = cur - 1;
|
||||
loop {
|
||||
if i < 0 {
|
||||
break;
|
||||
}
|
||||
match list_k.row_at_index(i) {
|
||||
Some(r) if r.is_visible() => {
|
||||
list_k.select_row(Some(&r));
|
||||
break;
|
||||
}
|
||||
Some(_) => i -= 1,
|
||||
None => break,
|
||||
}
|
||||
}
|
||||
glib::Propagation::Stop
|
||||
}
|
||||
_ => glib::Propagation::Proceed,
|
||||
}
|
||||
});
|
||||
search.add_controller(key_ctrl);
|
||||
|
||||
// Click to launch
|
||||
let window_a = window.clone();
|
||||
list.connect_row_activated(move |_, row| {
|
||||
let action = get_row_data(row, "action");
|
||||
if !action.is_empty() {
|
||||
do_launch(&action);
|
||||
cleanup_pid();
|
||||
window_a.close();
|
||||
}
|
||||
});
|
||||
|
||||
// Cleanup pid when window is destroyed for any reason
|
||||
window.connect_destroy(|_| cleanup_pid());
|
||||
|
||||
window.present();
|
||||
search.grab_focus();
|
||||
});
|
||||
|
||||
app.run();
|
||||
}
|
||||
|
||||
// ---- main -----------------------------------------------------------------
|
||||
|
||||
fn main() {
|
||||
let cache = cache_path();
|
||||
|
||||
if env::var("BREADBOX_REBUILD_ONLY").as_deref() == Ok("1") {
|
||||
build_cache(&cache);
|
||||
return;
|
||||
}
|
||||
|
||||
if !toggle_or_continue() {
|
||||
return;
|
||||
}
|
||||
|
||||
if !cache.exists() {
|
||||
build_cache(&cache);
|
||||
} else if !cache_valid(&cache) {
|
||||
if let Ok(exe) = env::current_exe() {
|
||||
let _ = Command::new(exe)
|
||||
.env("BREADBOX_REBUILD_ONLY", "1")
|
||||
.stdin(Stdio::null())
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.spawn();
|
||||
}
|
||||
}
|
||||
|
||||
let entries = load_entries(&cache);
|
||||
run_ui(entries);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue