Compare commits

..

No commits in common. "main" and "v0.2.1" have entirely different histories.
main ... v0.2.1

16 changed files with 133 additions and 781 deletions

View file

@ -1,24 +0,0 @@
name: check
# Fast-fail lint/test on short-lived work branches, before it ever reaches
# main and triggers a dev-track release build.
on:
push:
branches: ['feature/**', 'fix/**']
jobs:
check:
runs-on: [self-hosted, hestia]
steps:
- name: checkout
run: |
set -euo pipefail
rm -rf src && mkdir src
git clone --branch "${GITHUB_REF_NAME}" --depth 1 \
"https://git.breadway.dev/${GITHUB_REPOSITORY}.git" src
- name: clippy
run: cd src && bash ci/build.sh cargo clippy --workspace --all-targets --locked -- -D warnings
- name: test
run: cd src && bash ci/build.sh cargo test --workspace --locked

View file

@ -1,78 +0,0 @@
name: dev release
# Publishes a dev-track build on every push to `main` (the trunk
# branch — there is no separate `dev` branch). See bread-ecosystem's
# docs/release-channels.md for the release-track policy this is part of.
on:
push:
branches: ['main']
jobs:
build:
runs-on: [self-hosted, hestia]
steps:
- name: checkout
run: |
set -euo pipefail
rm -rf src && mkdir src
git clone --branch main --depth 1 \
"https://git.breadway.dev/${GITHUB_REPOSITORY}.git" src
- name: build
run: cd src && bash ci/build.sh cargo build --release --locked
- name: compute dev version
run: |
set -euo pipefail
cd src
# Base the dev version off the latest published stable tag,
# not Cargo.toml — Cargo.toml can go stale relative to the last
# real release (seen in practice: breadbox/breadpad/breadcrumbs/
# breadpaper), which would make a dev build sort as OLDER than
# what's already installed and bakery would correctly refuse it.
LATEST_TAG="$(git ls-remote --tags --refs \
"https://git.breadway.dev/${GITHUB_REPOSITORY}.git" 'v*' \
| awk -F/ '{print $NF}' | sed 's/^v//' | (grep -v -- '-' || true) | sort -V | tail -1)"
if [ -n "${LATEST_TAG}" ]; then
CUR="${LATEST_TAG}"
else
CUR="$(grep -m1 '^version' breadclip/Cargo.toml | sed -E 's/.*"(.*)".*/\1/')"
fi
IFS='.' read -r MA MI PA <<< "${CUR}"
SHA="$(git rev-parse --short HEAD)"
TS="$(date -u +%Y%m%d%H%M%S)"
echo "VERSION=${MA}.${MI}.$((PA + 1))-dev.${TS}+${SHA}" >> "$GITHUB_ENV"
- name: prepare artifacts
run: |
set -euo pipefail
PKG_DIR="/srv/breadway-dl/dev/breadclip/${VERSION}"
mkdir -p "${PKG_DIR}"
for bin in breadclip breadclipd; do
cp "src/target/release/${bin}" "${PKG_DIR}/${bin}-x86_64"
strip "${PKG_DIR}/${bin}-x86_64"
sha256sum "${PKG_DIR}/${bin}-x86_64" | awk '{print $1}' \
> "${PKG_DIR}/${bin}-x86_64.sha256"
done
cp src/contrib/breadclipd.service "${PKG_DIR}/"
cp src/bakery.toml "${PKG_DIR}/bakery.toml"
ln -sfn "${VERSION}" "/srv/breadway-dl/dev/breadclip/latest"
# No GitHub Release upload — dev, like the other non-stable track,
# is only distributed via dl.breadway.dev/dev/.
- name: regenerate dev index.json
env:
MINISIGN_SEC_KEY: ${{ secrets.BAKERY_MINISIGN_SEC_KEY_PATH }}
run: |
set -euo pipefail
if [ -z "${MINISIGN_SEC_KEY:-}" ]; then
echo "::error::BAKERY_MINISIGN_SEC_KEY_PATH secret not set — refusing to regenerate dev index.json unsigned (would leave a stale signature mismatched against fresh content and break bakery for everyone on the dev track)"
exit 1
fi
rm -rf /tmp/bread-ecosystem-ci-* 2>/dev/null || true
# mktemp: a fixed clone path races when multiple repos' dev/beta
# workflows run close together on the same self-hosted runner.
ECOSYSTEM_CI_DIR="$(mktemp -d /tmp/bread-ecosystem-ci-XXXXXX)"
git clone --branch main https://git.breadway.dev/Breadway/bread-ecosystem.git "${ECOSYSTEM_CI_DIR}"
TRACK=dev bash "${ECOSYSTEM_CI_DIR}/scripts/gen-index.sh"
rm -rf "${ECOSYSTEM_CI_DIR}"

View file

@ -0,0 +1,19 @@
name: Mirror to GitHub
on:
push:
branches: ['**']
tags: ['**']
jobs:
mirror:
runs-on: [self-hosted, hestia]
steps:
- name: Mirror to GitHub
run: |
set -euo pipefail
git clone --mirror "https://git.breadway.dev/${GITHUB_REPOSITORY}.git" repo.git
cd repo.git
git push --prune \
"https://x-access-token:${{ secrets.MIRROR_TOKEN }}@github.com/Breadway/breadclip.git" \
'+refs/heads/*:refs/heads/*' '+refs/tags/*:refs/tags/*'

View file

@ -1,59 +0,0 @@
name: beta (rc) release
# Publishes a beta-track build for any `vX.Y.Z-rc.N` prerelease tag
# pushed to `main` — there is no separate `beta` branch; "freezing" is
# just pausing pushes to main while an RC gets tested. See
# bread-ecosystem's docs/release-channels.md for the release-track policy.
on:
push:
tags: ['v*']
jobs:
build:
if: ${{ contains(github.ref_name, '-rc.') }}
runs-on: [self-hosted, hestia]
steps:
- name: checkout
run: |
set -euo pipefail
rm -rf src && mkdir src
git clone --branch "${GITHUB_REF_NAME}" --depth 1 \
"https://git.breadway.dev/${GITHUB_REPOSITORY}.git" src
- name: build
run: cd src && bash ci/build.sh cargo build --release --locked
- name: prepare artifacts
run: |
set -euo pipefail
VERSION="${GITHUB_REF_NAME#v}"
PKG_DIR="/srv/breadway-dl/beta/breadclip/${VERSION}"
mkdir -p "${PKG_DIR}"
for bin in breadclip breadclipd; do
cp "src/target/release/${bin}" "${PKG_DIR}/${bin}-x86_64"
strip "${PKG_DIR}/${bin}-x86_64"
sha256sum "${PKG_DIR}/${bin}-x86_64" | awk '{print $1}' \
> "${PKG_DIR}/${bin}-x86_64.sha256"
done
cp src/contrib/breadclipd.service "${PKG_DIR}/"
cp src/bakery.toml "${PKG_DIR}/bakery.toml"
ln -sfn "${VERSION}" "/srv/breadway-dl/beta/breadclip/latest"
# No GitHub Release upload — beta, like dev, is only distributed via
# dl.breadway.dev/beta/.
- name: regenerate beta index.json
env:
MINISIGN_SEC_KEY: ${{ secrets.BAKERY_MINISIGN_SEC_KEY_PATH }}
run: |
set -euo pipefail
if [ -z "${MINISIGN_SEC_KEY:-}" ]; then
echo "::error::BAKERY_MINISIGN_SEC_KEY_PATH secret not set — refusing to regenerate beta index.json unsigned (would leave a stale signature mismatched against fresh content and break bakery for everyone on the beta track)"
exit 1
fi
rm -rf /tmp/bread-ecosystem-ci-* 2>/dev/null || true
# mktemp: a fixed clone path races when multiple repos' dev/beta
# workflows run close together on the same self-hosted runner.
ECOSYSTEM_CI_DIR="$(mktemp -d /tmp/bread-ecosystem-ci-XXXXXX)"
git clone https://git.breadway.dev/Breadway/bread-ecosystem.git "${ECOSYSTEM_CI_DIR}"
TRACK=beta bash "${ECOSYSTEM_CI_DIR}/scripts/gen-index.sh"
rm -rf "${ECOSYSTEM_CI_DIR}"

View file

@ -6,7 +6,6 @@ on:
jobs:
build:
if: ${{ !contains(github.ref_name, '-rc.') }}
runs-on: [self-hosted, hestia]
steps:
- name: checkout
@ -17,16 +16,7 @@ jobs:
"https://git.breadway.dev/${GITHUB_REPOSITORY}.git" src
- name: build
run: |
set -euo pipefail
if [ ! -f src/ci/build.sh ]; then
echo "::error::ci/build.sh is missing — bakery release builds must go through the shared CI wrapper"
exit 1
fi
cd src && bash ci/build.sh cargo build --release --locked || {
echo "::error::cargo build --release --locked failed. If Cargo.lock drifted, update and commit it; do not drop --locked."
exit 1
}
run: cd src && cargo build --release --locked
- name: prepare artifacts
run: |
@ -45,14 +35,8 @@ jobs:
ln -sfn "${VERSION}" "/srv/breadway-dl/breadclip/latest"
- name: regenerate index.json
env:
MINISIGN_SEC_KEY: ${{ secrets.BAKERY_MINISIGN_SEC_KEY_PATH }}
run: |
set -euo pipefail
if [ -z "${MINISIGN_SEC_KEY:-}" ]; then
echo "::error::BAKERY_MINISIGN_SEC_KEY_PATH secret not set — refusing to regenerate index.json unsigned (would leave a stale signature mismatched against fresh content and break bakery for everyone)"
exit 1
fi
rm -rf /tmp/bread-ecosystem-ci
git clone https://git.breadway.dev/Breadway/bread-ecosystem.git /tmp/bread-ecosystem-ci
bash /tmp/bread-ecosystem-ci/scripts/gen-index.sh

6
.gitignore vendored
View file

@ -29,9 +29,3 @@ logs/
# Runtime files
*.sock
*.pid
# Local hygiene notes (not for commit)
CLAUDE.md
# graphify knowledge-graph output (local tool cache, not for commit)
graphify-out/

View file

@ -1,62 +0,0 @@
# AGENTS.md — Repo hygiene
Scope: this file covers *repo hygiene* — branching, remotes, CI — plus a
short map of the binaries. It is not user-facing project documentation.
This repo follows the branch/release workflow documented in `CONTRIBUTING.md`
— read and follow it for any git, branch, or release work here (the
single-trunk model, `feature/x`/`fix/x` branch naming, how RC tags work,
etc). Don't improvise a different workflow. The short version: there is one
long-lived branch, `main` — no `dev` or `beta` branch exists. `main`
auto-publishes a dev-track build on every push. "Beta" and "stable" are both
just tags, not branches: push a `vX.Y.Z-rc.N` tag to publish a beta-track
build, push a plain `vX.Y.Z` tag to cut the signed stable release.
"Freezing" for stabilization means pausing pushes to `main`, not moving a
branch. This replaced an earlier three-branch (`dev`/`beta`/`main`) model
after `main` was found to have silently rotted out of sync with `dev`/`beta`
across most repos in this ecosystem.
When starting work on a new feature, create branch `feature/<feature-name>`.
When working on a bug or issue, create branch `fix/<issue you are fixing>`.
## Remotes
- `origin` — Forgejo (`git.breadway.dev` via Hestia, SSH) — authoritative.
- `github` — GitHub mirror. Push `origin` only; GitHub auto-mirrors.
## CI
- `check.yml` — clippy + test, triggers on push to `feature/**`/`fix/**`.
- `dev-release.yml` — triggers on push to `main`.
- `rc-release.yml` — triggers on `vX.Y.Z-rc.N` tag push.
- `release.yml` — triggers on any other `v*` tag push.
All four run on a self-hosted runner (`hestia`) inside a pinned Arch
container — not the host's native environment. The Containerfile/build
script are shared across bread-ecosystem products and live in
`bread-ecosystem/ci/`; this repo's `ci/build.sh` clones that repo at the
sha in `ci/bread-ecosystem.rev` (deliberately pinned, not `main`) and
delegates to it. Nothing runs automatically on plain commits or PRs
beyond what's listed.
## Architecture
Three crates:
| Crate | Role |
|---|---|
| `breadclipd` | Clipboard-watch daemon; persists history to SQLite |
| `breadclip` | GTK4 Layer Shell popup (thin UI over the same DB) |
| `breadclip-core` | Shared history schema / DB access |
`--screenshot` (`breadclip/src/screenshot.rs`) captures the history panel
through `bread-screenshots`; do not rewrite it just to retarget the crate pin.
`EVENTS.md` is the bread-event contract. App id `clip`. Implemented:
`bread.clip.copied`, `bread.clip.clear.done`/`.failed`, and command
`bread.command.clip.clear`. There is no pin/select — the history schema has
no pinned column and the popup has no pin UI. Do not invent
`bread.command.clip.pin`/`.select` (or matching events) ahead of a real
product feature.
## Don't
- Don't embed credentials in remote URLs — SSH or a credential helper only.
- Don't invent pin/select on the event bus. See `EVENTS.md`.

View file

@ -1,84 +0,0 @@
# Contributing
`breadclip` — Wayland clipboard history manager for Hyprland (daemon + GTK4 popup).
Part of the bread ecosystem; this repo follows the same branch/release
workflow as every other ecosystem product.
## Branches
There is one long-lived branch: **`main`**. All day-to-day work lands here.
Every push to `main` automatically builds and publishes a **dev-track**
build (see Tracks below) — a real install you can test before cutting
anything more formal.
New work — features and bug fixes alike — goes on a short-lived branch:
```
feature/<short-name>
fix/<issue-number-or-short-name>
```
Branch off `main`, open a PR/push back into `main` when ready. Short-lived
branches get deleted on merge — they never accumulate the kind of drift a
second long-lived branch does.
## The release cycle
There's no separate `beta` or release branch — "stable" and "beta" are both
just **tags** on `main`, not branches that need to be kept in sync:
1. Work accumulates on `main` via `feature/x` / `fix/x` branches. Each push
auto-publishes a dev build — install it with `bakery track set dev` and
`bakery update --all`, then fix anything broken with another push.
2. When you want to stabilize before a real release, tag a release
candidate: `git tag vX.Y.Z-rc.1 && git push origin vX.Y.Z-rc.1` (push to
both remotes). That tag alone triggers a beta-track build —
"freezing" is just pausing pushes to `main` while you test it, not a
branch operation. Cut `-rc.2`, `-rc.3`, etc. for further fixes.
3. Once an RC has gone without issues, tag the real release:
`git tag vX.Y.Z && git push origin vX.Y.Z` — that's what triggers the
signed stable release build.
## Tracks, from a user's perspective
```
bakery track show # what you're currently on (defaults to stable)
bakery track set dev # or beta, or stable
bakery update --all # pull the latest build on your current track
```
| Track | What it is | Published from |
|--------|-----------|-----------------|
| `stable` | The last tagged release | a `vX.Y.Z` tag |
| `beta` | Latest release candidate | a `vX.Y.Z-rc.N` tag |
| `dev` | Bleeding edge | `main`, on every push |
Dev versions are auto-computed (`X.Y.Z-dev.<timestamp>+<sha>`) from the
latest published stable tag, so they always sort as newer than what you
have installed — no manual version bumping needed. Beta versions are just
the RC tag itself (already valid semver, already sorts below the real
release it's a candidate for).
## Local development
```sh
cargo build --release --workspace
cargo test --release --workspace
```
## CI
- `dev-release.yml` — triggered on push to `main`.
- `rc-release.yml` — triggered on any `vX.Y.Z-rc.N` tag push.
- `release.yml` — triggered on any other `v*` tag push, cuts the actual
stable release.
All CI runs on a self-hosted runner; nothing runs automatically on plain
commits or PRs beyond the track builds above. See
[bread-ecosystem's docs/release-channels.md](https://git.breadway.dev/Breadway/bread-ecosystem/src/branch/main/docs/release-channels.md)
for the full policy, including how a new product gets wired onto these tracks.
## Questions
Open an issue on this repo's Forgejo tracker.

363
Cargo.lock generated
View file

@ -14,62 +14,6 @@ dependencies = [
"zerocopy",
]
[[package]]
name = "anstream"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is_terminal_polyfill",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000"
[[package]]
name = "anstyle-parse"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc"
dependencies = [
"windows-sys 0.61.2",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d"
dependencies = [
"anstyle",
"once_cell_polyfill",
"windows-sys 0.61.2",
]
[[package]]
name = "anyhow"
version = "1.0.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470"
[[package]]
name = "autocfg"
version = "1.5.1"
@ -91,16 +35,6 @@ dependencies = [
"generic-array",
]
[[package]]
name = "bread-screenshots"
version = "0.7.2"
source = "git+https://git.breadway.dev/Breadway/bread-ecosystem?tag=v0.7.2#30517f161724132cdeb658c04cf5e490be07ee73"
dependencies = [
"anyhow",
"bread-utils",
"tracing",
]
[[package]]
name = "bread-shared"
version = "0.7.0"
@ -114,8 +48,8 @@ dependencies = [
[[package]]
name = "bread-theme"
version = "0.7.4"
source = "git+https://git.breadway.dev/Breadway/bread-ecosystem?tag=v0.7.4#fcba3760387e2523edb71350f8efea3bc851b21e"
version = "0.3.0"
source = "git+https://git.breadway.dev/Breadway/bread-ecosystem?tag=v0.3.0#8e82d2d833e992ce939a5b836f910ee109f2e939"
dependencies = [
"dirs",
"gtk4",
@ -125,10 +59,19 @@ dependencies = [
[[package]]
name = "bread-utils"
version = "0.7.2"
source = "git+https://git.breadway.dev/Breadway/bread-ecosystem?tag=v0.7.2#30517f161724132cdeb658c04cf5e490be07ee73"
version = "0.3.0"
dependencies = [
"bread-shared",
"dirs",
"serde",
"serde_json",
]
[[package]]
name = "bread-utils"
version = "0.3.0"
source = "git+https://git.breadway.dev/Breadway/bread-ecosystem?tag=v0.3.0#8e82d2d833e992ce939a5b836f910ee109f2e939"
dependencies = [
"dirs",
"gtk4",
"gtk4-layer-shell",
@ -138,14 +81,11 @@ dependencies = [
[[package]]
name = "breadclip"
version = "0.2.4"
version = "0.2.1"
dependencies = [
"anyhow",
"bread-screenshots",
"bread-theme",
"bread-utils",
"bread-utils 0.3.0 (git+https://git.breadway.dev/Breadway/bread-ecosystem?tag=v0.3.0)",
"breadclip-core",
"clap",
"gtk4",
"gtk4-layer-shell",
"serde_json",
@ -153,9 +93,9 @@ dependencies = [
[[package]]
name = "breadclip-core"
version = "0.2.4"
version = "0.2.1"
dependencies = [
"bread-utils",
"bread-utils 0.3.0 (git+https://git.breadway.dev/Breadway/bread-ecosystem?tag=v0.3.0)",
"dirs",
"hex",
"rusqlite",
@ -165,9 +105,9 @@ dependencies = [
[[package]]
name = "breadclipd"
version = "0.2.4"
version = "0.2.1"
dependencies = [
"bread-utils",
"bread-utils 0.3.0",
"breadclip-core",
"serde_json",
"tempfile",
@ -193,14 +133,14 @@ checksum = "f8b4985713047f5faee02b8db6a6ef32bbb50269ff53c1aee716d1d195b76d54"
dependencies = [
"glib-sys",
"libc",
"system-deps 7.0.8",
"system-deps",
]
[[package]]
name = "cc"
version = "1.4.3"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "509591b7bcd67f4ef775afad7662703b4935daaa6ec0e5605cfb1090b32a2b6d"
checksum = "c89588d05638b5b4594a3348a2d6c20277e43a7f5c5202b05cc56888475a47b8"
dependencies = [
"find-msvc-tools",
"shlex",
@ -222,52 +162,6 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
[[package]]
name = "clap"
version = "4.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "473c7e07f409a8d772161724aa8db6a765a2532a70f9667eeb7b49d3d02fbdca"
dependencies = [
"clap_builder",
"clap_derive",
]
[[package]]
name = "clap_builder"
version = "4.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b48fea5a88e9ae728a2dcbedbfc0e730f7d60da42e1cb049a83c9fb8b789889"
dependencies = [
"anstream",
"anstyle",
"clap_lex",
"strsim",
]
[[package]]
name = "clap_derive"
version = "4.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d012d2b9d65aca7f18f4d9878a045bc17899bba951561ba5ec3c2ba1eed9a061"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn 3.0.3",
]
[[package]]
name = "clap_lex"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9"
[[package]]
name = "colorchoice"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570"
[[package]]
name = "cpufeatures"
version = "0.2.17"
@ -348,9 +242,9 @@ checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
[[package]]
name = "fastrand"
version = "2.5.0"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223"
checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6"
[[package]]
name = "field-offset"
@ -364,30 +258,30 @@ dependencies = [
[[package]]
name = "find-msvc-tools"
version = "0.1.11"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d45db016d36b838f563236e9193d0ee6ce38f3f68b6c94e914b4929c96bbb890"
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
[[package]]
name = "futures-channel"
version = "0.3.34"
version = "0.3.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1f9e3d69d39e4862ffed03ed071a76f9a13ba1d9109d355b0f0aa6b15e393c4"
checksum = "262590f4fe6afeb0bc83be1daa64e52657fe185690a958af7f3ad0e92085c5ae"
dependencies = [
"futures-core",
]
[[package]]
name = "futures-core"
version = "0.3.34"
version = "0.3.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e"
checksum = "2cd50c473c80f6d7c3670a752354b8e569b1a7cbfdc0419ec88e5edad85e0dc7"
[[package]]
name = "futures-executor"
version = "0.3.34"
version = "0.3.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "031b47cf1a3c6cc8bc2fc76cd437f521619387907d469316e7c0bc278f1f5432"
checksum = "6754879cc9f2c66f88c6e5c35344bb0bdb0708b0352b1201815667c7eabc7458"
dependencies = [
"futures-core",
"futures-task",
@ -396,32 +290,32 @@ dependencies = [
[[package]]
name = "futures-io"
version = "0.3.34"
version = "0.3.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53c0fa8157de1303bfffdaa1cc2a673bfffb60102f76b0ef4441659124373fed"
checksum = "4577ecaa3c4f96589d473f679a71b596316f6641bc350038b962a5daf0085d7a"
[[package]]
name = "futures-macro"
version = "0.3.34"
version = "0.3.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fb9654ba8355388abeb8dcb4fc62f511300867002afc858860463bdd9fe0c44"
checksum = "2d6d3cde68c518367be28956066ddfef33813991b77a55005a69dae04bf3b10b"
dependencies = [
"proc-macro2",
"quote",
"syn 3.0.3",
"syn",
]
[[package]]
name = "futures-task"
version = "0.3.34"
version = "0.3.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd"
checksum = "b231ed28831efb4a61a08580c4bc233ec56bc009f4cd8f52da2c3cb97df0c109"
[[package]]
name = "futures-util"
version = "0.3.34"
version = "0.3.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc"
checksum = "a77a90a256fce34da66415271e30f94ee91c57b04b8a2c042d9cf3220179deaa"
dependencies = [
"futures-core",
"futures-macro",
@ -452,7 +346,7 @@ dependencies = [
"glib-sys",
"gobject-sys",
"libc",
"system-deps 7.0.8",
"system-deps",
]
[[package]]
@ -485,7 +379,7 @@ dependencies = [
"libc",
"pango-sys",
"pkg-config",
"system-deps 7.0.8",
"system-deps",
]
[[package]]
@ -546,7 +440,7 @@ dependencies = [
"glib-sys",
"gobject-sys",
"libc",
"system-deps 7.0.8",
"system-deps",
"windows-sys 0.61.2",
]
@ -600,7 +494,7 @@ dependencies = [
"heck",
"proc-macro2",
"quote",
"syn 2.0.119",
"syn",
]
[[package]]
@ -610,7 +504,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "030967459f9f676851872c6304adea7825c6d462ec9b72554c733cf0c5952233"
dependencies = [
"libc",
"system-deps 7.0.8",
"system-deps",
]
[[package]]
@ -621,7 +515,7 @@ checksum = "22a861859b887a79cf461359c192c97a57d8fb0229dd291232e57aa11f6fa72c"
dependencies = [
"glib-sys",
"libc",
"system-deps 7.0.8",
"system-deps",
]
[[package]]
@ -642,7 +536,7 @@ checksum = "5c7ffdfde88f3570d3705e0d8a2433e036d387a1f2930bbf47eafcb5f569fd04"
dependencies = [
"glib-sys",
"libc",
"system-deps 7.0.8",
"system-deps",
]
[[package]]
@ -673,7 +567,7 @@ dependencies = [
"graphene-sys",
"libc",
"pango-sys",
"system-deps 7.0.8",
"system-deps",
]
[[package]]
@ -699,9 +593,9 @@ dependencies = [
[[package]]
name = "gtk4-layer-shell"
version = "0.8.1"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17c28ea0f4676fdaaae7ff2413a24d0d35c8657424f84856c1103c73454c9da4"
checksum = "a4069987ff4793699511a251028cc336b438e46565b463f111250148d574752a"
dependencies = [
"bitflags",
"gdk4",
@ -714,15 +608,15 @@ dependencies = [
[[package]]
name = "gtk4-layer-shell-sys"
version = "0.6.1"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcf19bb884ef0ef55b9e6b2b369c39b4fcc0c41e3a0c1cbc8c267720338b690b"
checksum = "8f566a5ec5bcc454e7fcf2ab76930887ced5365afce12c1e5201bb296b95f1b9"
dependencies = [
"gdk4-sys",
"glib-sys",
"gtk4-sys",
"libc",
"system-deps 8.0.0",
"system-deps",
]
[[package]]
@ -734,7 +628,7 @@ dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn 2.0.119",
"syn",
]
[[package]]
@ -753,7 +647,7 @@ dependencies = [
"gsk4-sys",
"libc",
"pango-sys",
"system-deps 7.0.8",
"system-deps",
]
[[package]]
@ -802,12 +696,6 @@ dependencies = [
"hashbrown 0.17.1",
]
[[package]]
name = "is_terminal_polyfill"
version = "1.70.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695"
[[package]]
name = "itoa"
version = "1.0.18"
@ -822,15 +710,15 @@ checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"
[[package]]
name = "libc"
version = "0.2.189"
version = "0.2.186"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
[[package]]
name = "libredox"
version = "0.1.20"
version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28d0a00925a9f930d679b6789b721e3a7f9ed110f41b86d2497caa780c3a070a"
checksum = "c943259e342f1e06ff2da7a83eabdfe7f92ce10262688dbf1895ff0b3e6e4652"
dependencies = [
"libc",
]
@ -879,12 +767,6 @@ version = "1.21.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
[[package]]
name = "once_cell_polyfill"
version = "1.70.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
[[package]]
name = "option-ext"
version = "0.2.0"
@ -911,7 +793,7 @@ dependencies = [
"glib-sys",
"gobject-sys",
"libc",
"system-deps 7.0.8",
"system-deps",
]
[[package]]
@ -922,9 +804,9 @@ checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
[[package]]
name = "pkg-config"
version = "0.3.34"
version = "0.3.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548"
checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e"
[[package]]
name = "proc-macro-crate"
@ -937,18 +819,18 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.107"
version = "1.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.47"
version = "1.0.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368"
dependencies = [
"proc-macro2",
]
@ -1014,9 +896,9 @@ checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
[[package]]
name = "serde"
version = "1.0.229"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
dependencies = [
"serde_core",
"serde_derive",
@ -1024,29 +906,29 @@ dependencies = [
[[package]]
name = "serde_core"
version = "1.0.229"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48"
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.229"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [
"proc-macro2",
"quote",
"syn 3.0.3",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.151"
version = "1.0.150"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14"
checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"
dependencies = [
"itoa",
"memchr",
@ -1102,12 +984,6 @@ version = "1.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90"
[[package]]
name = "strsim"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "syn"
version = "2.0.119"
@ -1119,17 +995,6 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "syn"
version = "3.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "system-deps"
version = "7.0.8"
@ -1139,20 +1004,7 @@ dependencies = [
"cfg-expr",
"heck",
"pkg-config",
"toml 1.1.4+spec-1.1.0",
"version-compare",
]
[[package]]
name = "system-deps"
version = "8.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83779a5c956bcb6ba627a4ecf0a9d7625db47d7537e0892d97f712ac995648a3"
dependencies = [
"cfg-expr",
"heck",
"pkg-config",
"toml 1.1.4+spec-1.1.0",
"toml 1.1.3+spec-1.1.0",
"version-compare",
]
@ -1192,7 +1044,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.119",
"syn",
]
[[package]]
@ -1209,9 +1061,9 @@ dependencies = [
[[package]]
name = "toml"
version = "1.1.4+spec-1.1.0"
version = "1.1.3+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3aace63f4bbcdfc2c965b059de67119c89c4017a70d633be6c104910f67056f5"
checksum = "53c96ecdfa941c8fc4fcaed14f99ada8ebed502eef533015095a07e3301d4c3c"
dependencies = [
"indexmap",
"serde_core",
@ -1268,9 +1120,9 @@ dependencies = [
[[package]]
name = "toml_parser"
version = "1.1.3+spec-1.1.0"
version = "1.1.2+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d38ac1cf9b95face32296c0a3ede1fdc270627c9d9c02a7274dd6d960dc4d56"
checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526"
dependencies = [
"winnow 1.0.4",
]
@ -1287,37 +1139,6 @@ version = "1.1.2+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d56353a2a665ad0f41a421187180aab746c8c325620617ad883a99a1cbe66d2"
[[package]]
name = "tracing"
version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100"
dependencies = [
"pin-project-lite",
"tracing-attributes",
"tracing-core",
]
[[package]]
name = "tracing-attributes"
version = "0.1.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.119",
]
[[package]]
name = "tracing-core"
version = "0.1.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a"
dependencies = [
"once_cell",
]
[[package]]
name = "typenum"
version = "1.20.1"
@ -1330,12 +1151,6 @@ version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
[[package]]
name = "utf8parse"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "vcpkg"
version = "0.2.15"
@ -1461,28 +1276,28 @@ dependencies = [
[[package]]
name = "xml-rs"
version = "0.8.29"
version = "0.8.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e450f9b2ed1dff33c94c12589a87338689467b9c4f5d8a5710bd09a847d2c8a7"
checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f"
[[package]]
name = "zerocopy"
version = "0.8.56"
version = "0.8.54"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "556764e583adb45a9f8d413c2a147fa7e8d821e48e12b14fd560b607998b75eb"
checksum = "b7cbbc0a705a0fd05cc3676525980d2bf5a9bc4adac6d6475209a7887cf59d19"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.8.56"
version = "0.8.54"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2ab42fc20575779bd240faa45f94a74256f755c0fa9e89f0ede20d91d0cdfc1"
checksum = "e2e817b7b52d0c7358d3246da9d69935ebb18116b2b102b4230dac079b4862f5"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.119",
"syn",
]
[[package]]

View file

@ -1,6 +1,6 @@
[package]
name = "breadclip-core"
version = "0.2.4"
version = "0.2.1"
edition = "2021"
[dependencies]
@ -8,7 +8,8 @@ rusqlite = { version = "0.31", features = ["bundled"] }
sha2 = "0.10"
hex = "0.4"
dirs = "5"
bread-utils = { git = "https://git.breadway.dev/Breadway/bread-ecosystem", tag = "v0.7.2" }
# (Path corrected: previously pointed at a since-cleaned-up "bread-ecosystem-fix-worktree" checkout that no longer exists on disk.)
bread-utils = { git = "https://git.breadway.dev/Breadway/bread-ecosystem", tag = "v0.3.0" }
[dev-dependencies]
tempfile = "3"

View file

@ -1,6 +1,6 @@
[package]
name = "breadclip"
version = "0.2.4"
version = "0.2.1"
edition = "2021"
[[bin]]
@ -9,12 +9,9 @@ path = "src/main.rs"
[dependencies]
breadclip-core = { path = "../breadclip-core" }
bread-theme = { git = "https://git.breadway.dev/Breadway/bread-ecosystem", tag = "v0.7.4", features = ["gtk"] }
bread-utils = { git = "https://git.breadway.dev/Breadway/bread-ecosystem", tag = "v0.7.2", features = ["gtk"] }
# Capture primitives for `--screenshot` mode — see src/screenshot.rs.
bread-screenshots = { git = "https://git.breadway.dev/Breadway/bread-ecosystem", tag = "v0.7.2" }
bread-theme = { git = "https://git.breadway.dev/Breadway/bread-ecosystem", tag = "v0.3.0", features = ["gtk"] }
# (Path corrected: previously pointed at a since-cleaned-up "bread-ecosystem-fix-worktree" checkout that no longer exists on disk.)
bread-utils = { git = "https://git.breadway.dev/Breadway/bread-ecosystem", tag = "v0.3.0", features = ["gtk"] }
gtk4 = { version = "0.11", features = ["v4_12"] }
gtk4-layer-shell = "0.8"
serde_json = "1"
clap = { version = "4", features = ["derive"] }
anyhow = "1"

View file

@ -1,5 +1,4 @@
mod css;
mod screenshot;
use breadclip_core::{ClipEntry, HistoryDb};
use bread_theme::{load_palette};
@ -185,17 +184,10 @@ fn do_copy(entry: &ClipEntry) {
// ---- UI ---------------------------------------------------------------------
fn run_ui(entries: Vec<ClipEntry>, screenshot_req: Option<screenshot::ScreenshotRequest>) {
let mut builder = Application::builder().application_id("com.breadway.breadclip");
if screenshot_req.is_some() {
// GApplication is single-instance by default; this machine typically
// already has a real breadclip instance, so without this a
// screenshot run would just message the *existing* instance instead
// of starting a fresh one that ever sees `screenshot_req`.
builder = builder.flags(gtk4::gio::ApplicationFlags::NON_UNIQUE);
}
let app = builder.build();
let is_screenshot_run = screenshot_req.is_some();
fn run_ui(entries: Vec<ClipEntry>) {
let app = Application::builder()
.application_id("com.breadway.breadclip")
.build();
app.connect_activate(move |app| {
bread_theme::gtk::apply_shared();
@ -203,7 +195,6 @@ fn run_ui(entries: Vec<ClipEntry>, screenshot_req: Option<screenshot::Screenshot
// Full-screen transparent overlay; panel widget is positioned inside it.
let window = bread_utils::gtk_popup::new_overlay_window(app, "breadclip");
bread_theme::gtk::bind_window_auto(&window);
// ---- Position panel relative to the active window ----
// If a non-fullscreen window is focused, anchor the panel just below it.
@ -417,50 +408,25 @@ fn run_ui(entries: Vec<ClipEntry>, screenshot_req: Option<screenshot::Screenshot
bread_utils::gtk_popup::close_on_outside_click(&window, &panel, move || close_outside());
}
if let Some(req) = screenshot_req.clone() {
screenshot::dispatch(&window, req);
}
window.present();
search.grab_focus();
});
if is_screenshot_run {
// GLib's own option parser otherwise rejects --screenshot/--output
// before clap ever sees them (`Cli::parse()` already ran in `main`,
// over the real argv).
app.run_with_args(&[] as &[&str]);
} else {
app.run();
}
app.run();
}
// ---- Main -------------------------------------------------------------------
fn main() {
use clap::Parser;
let cli = screenshot::Cli::parse();
let screenshot_req = cli.screenshot_request();
// `toggle_or_kill` kills whatever's holding the single-instance lock —
// a real, already-running breadclip included. A screenshot run must
// never touch it: it's a separate, disposable instance by design (same
// reasoning as breadbar's `allow_multiple_instances`), not a toggle of
// the operator's real clipboard panel.
//
// Kept alive for the rest of `main` — dropping it releases the
// single-instance lock and removes the pid file, which happens
// naturally once `run_ui` returns (after the window closes).
let _singleton_guard = if screenshot_req.is_some() {
None
} else {
match bread_utils::singleton::toggle_or_kill("breadclip") {
Ok(bread_utils::singleton::Toggle::Started(guard)) => Some(guard),
Ok(bread_utils::singleton::Toggle::KilledExisting) => return,
Err(e) => {
eprintln!("breadclip: single-instance lock unavailable ({e}); continuing without it");
None
}
let _singleton_guard = match bread_utils::singleton::toggle_or_kill("breadclip") {
Ok(bread_utils::singleton::Toggle::Started(guard)) => Some(guard),
Ok(bread_utils::singleton::Toggle::KilledExisting) => return,
Err(e) => {
eprintln!("breadclip: single-instance lock unavailable ({e}); continuing without it");
None
}
};
@ -468,5 +434,5 @@ fn main() {
.and_then(|db| db.list_entries(MAX_ENTRIES))
.unwrap_or_default();
run_ui(entries, screenshot_req);
run_ui(entries);
}

View file

@ -1,99 +0,0 @@
//! `--screenshot` CLI mode: render breadclip's clipboard-history panel,
//! capture it via `bread-screenshots`, then exit — driven by
//! `bread-ecosystem`'s `bread-capture` orchestrator, or run standalone for
//! one-off captures.
//!
//! breadclip has one view worth capturing: the history panel itself. Like
//! breadbox, it's a `halign`/`valign`-positioned panel over a full-screen
//! transparent overlay rather than its own layer surface, so a full
//! known-size canvas capture is the simplest reliable option. In screenshot
//! mode there's never a focused window to anchor the panel next to (see
//! `bread_utils::hypr::active_window` in `main.rs`, which the isolated
//! capture environment always reports `None` for — deliberately, see
//! `bread-capture`'s isolation module), so the panel always falls back to
//! centered, which is exactly what we want for a consistent screenshot.
use bread_utils::screenshot_cli::{validate_pair, DEFAULT_HEIGHT, DEFAULT_WIDTH, SETTLE_DELAY};
use clap::Parser;
use gtk4::prelude::*;
use std::path::PathBuf;
#[derive(Parser)]
#[command(name = "breadclip")]
pub struct Cli {
/// Render the named view, capture it, then exit instead of running
/// normally. Known views: "history".
#[arg(long)]
pub screenshot: Option<String>,
/// PNG path to write the capture to. Required together with --screenshot.
#[arg(long)]
pub output: Option<PathBuf>,
/// Capture canvas width — matches the isolated compositor's output width
/// (`bread-capture --isolate-width`).
#[arg(long, default_value_t = DEFAULT_WIDTH)]
pub width: u32,
/// Capture canvas height — see `width`.
#[arg(long, default_value_t = DEFAULT_HEIGHT)]
pub height: u32,
}
#[derive(Clone)]
pub struct ScreenshotRequest {
pub view: String,
pub output: PathBuf,
pub width: u32,
pub height: u32,
}
impl Cli {
/// `None` for a normal run. Exits the process with an error if the
/// `--screenshot` / `--output` pair is incomplete, before any GTK setup
/// happens.
pub fn screenshot_request(&self) -> Option<ScreenshotRequest> {
if let Err(e) = validate_pair(self.screenshot.as_deref(), self.output.as_deref()) {
eprintln!("breadclip: {e}");
std::process::exit(1);
}
Some(ScreenshotRequest {
view: self.screenshot.clone()?,
output: self.output.clone()?,
width: self.width,
height: self.height,
})
}
}
/// Wire up the given view's screenshot sequence against an already-built,
/// not-yet-presented window. Every path here ends by exiting the process —
/// it never returns control to the normal history-panel UI.
pub fn dispatch(window: &gtk4::ApplicationWindow, req: ScreenshotRequest) {
match req.view.as_str() {
"history" => {
let output = req.output;
let (width, height) = (req.width as i32, req.height as i32);
window.connect_map(move |_| {
let output = output.clone();
gtk4::glib::timeout_add_local_once(SETTLE_DELAY, move || {
finish(bread_screenshots::capture_region(0, 0, width, height, &output));
});
});
}
other => {
eprintln!("breadclip: unknown screenshot view '{other}' (known: history)");
std::process::exit(1);
}
}
}
fn finish(result: anyhow::Result<()>) {
match result {
Ok(()) => std::process::exit(0),
Err(e) => {
eprintln!("breadclip: screenshot capture failed: {e}");
std::process::exit(1);
}
}
}

View file

@ -1,6 +1,6 @@
[package]
name = "breadclipd"
version = "0.2.4"
version = "0.2.1"
edition = "2021"
[[bin]]
@ -9,7 +9,10 @@ path = "src/main.rs"
[dependencies]
breadclip-core = { path = "../breadclip-core" }
bread-utils = { git = "https://git.breadway.dev/Breadway/bread-ecosystem", tag = "v0.7.2", features = ["bread-client"] }
# TODO(owner): switch to a tag-pinned git dependency once bread-shared is
# released/tagged for external consumption, matching the bread-theme pattern —
# see the same stopgap already in place for bread-utils's own dependents.
bread-utils = { path = "../../bread-ecosystem/bread-utils", features = ["bread-client"] }
serde_json = "1"
[dev-dependencies]

View file

@ -1 +0,0 @@
620c5a1317a6b57276eabca961facdb78bf510db

View file

@ -1,20 +0,0 @@
#!/usr/bin/env bash
# Delegates to bread-ecosystem's shared CI build image/script, pinned to
# the commit in ci/bread-ecosystem.rev — not `main`. bread-ecosystem's CI
# files now affect every product's release pipeline, so bumping the pin
# is a deliberate act instead of silent drift.
#
# Usage: ci/build.sh cargo build --release --locked
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
REV="$(cat "${ROOT}/ci/bread-ecosystem.rev")"
CACHE_DIR="/tmp/bread-ecosystem-ci-${REV}"
if [ ! -d "$CACHE_DIR" ]; then
rm -rf /tmp/bread-ecosystem-ci-*
git clone https://git.breadway.dev/Breadway/bread-ecosystem.git "$CACHE_DIR"
git -C "$CACHE_DIR" checkout --quiet "$REV"
fi
bash "${CACHE_DIR}/ci/build.sh" breadclip "$ROOT" "$@"