Repository: H3rmt/hyprswitch
Branch: hyprshell-release
Commit: 30ce7a9e2579
Files: 331
Total size: 1.2 MB
Directory structure:
gitextract_elrb4jir/
├── .githooks/
│ └── pre-commit
├── .github/
│ └── workflows/
│ ├── publish.yml
│ ├── release-please.yml
│ ├── test.yml
│ └── update.yml
├── .gitignore
├── .idea/
│ ├── .gitignore
│ ├── copilot.data.migration.agent.xml
│ ├── copilot.data.migration.ask.xml
│ ├── copilot.data.migration.ask2agent.xml
│ ├── copilot.data.migration.edit.xml
│ ├── file.template.settings.xml
│ ├── hyprshell.iml
│ ├── inspectionProfiles/
│ │ └── Project_Default.xml
│ ├── modules.xml
│ ├── rust.xml
│ └── vcs.xml
├── .release-please-manifest.json
├── CHANGELOG.md
├── Cargo.toml
├── DEVELOPMENT.md
├── LICENSE
├── README.md
├── crates/
│ ├── clipboard-lib/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ ├── config/
│ │ │ └── mod.rs
│ │ ├── lib.rs
│ │ ├── store/
│ │ │ ├── listen.rs
│ │ │ ├── mime.rs
│ │ │ ├── mod.rs
│ │ │ ├── save_image.rs
│ │ │ ├── save_map.rs
│ │ │ ├── save_text.rs
│ │ │ ├── util.rs
│ │ │ └── write.rs
│ │ └── util/
│ │ ├── brotli_compressor.rs
│ │ ├── crypt.rs
│ │ ├── lz4_compressor.rs
│ │ ├── mod.rs
│ │ ├── secret_service.rs
│ │ └── zstd_compressor.rs
│ ├── config-edit-lib/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ ├── components/
│ │ │ ├── changes.rs
│ │ │ ├── footer.rs
│ │ │ ├── generate/
│ │ │ │ ├── main.rs
│ │ │ │ ├── mod.rs
│ │ │ │ ├── step0.rs
│ │ │ │ ├── step1.rs
│ │ │ │ ├── step2.rs
│ │ │ │ ├── step3.rs
│ │ │ │ └── step4.rs
│ │ │ ├── launcher.rs
│ │ │ ├── launcher_plugins/
│ │ │ │ ├── actions.rs
│ │ │ │ ├── applications.rs
│ │ │ │ ├── main.rs
│ │ │ │ ├── mod.rs
│ │ │ │ ├── simple.rs
│ │ │ │ └── websearch.rs
│ │ │ ├── mod.rs
│ │ │ ├── nix_preview.rs
│ │ │ ├── root.rs
│ │ │ ├── shortcut_dialog.rs
│ │ │ ├── switch.rs
│ │ │ ├── theme.rs
│ │ │ ├── windows.rs
│ │ │ └── windows_overview.rs
│ │ ├── lib.rs
│ │ ├── start.rs
│ │ ├── structs.rs
│ │ ├── styles.css
│ │ └── util.rs
│ ├── config-lib/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ ├── actions.rs
│ │ ├── check.rs
│ │ ├── explain.rs
│ │ ├── lib.rs
│ │ ├── load.rs
│ │ ├── migrate/
│ │ │ ├── check.rs
│ │ │ ├── m1t2/
│ │ │ │ ├── convert.rs
│ │ │ │ ├── mod.rs
│ │ │ │ └── old_structs.rs
│ │ │ ├── m2t3/
│ │ │ │ ├── convert.rs
│ │ │ │ ├── mod.rs
│ │ │ │ └── old_structs.rs
│ │ │ ├── migrate_config.rs
│ │ │ └── mod.rs
│ │ ├── modifier.rs
│ │ ├── save.rs
│ │ ├── structs.rs
│ │ └── style/
│ │ ├── load.rs
│ │ ├── mod.rs
│ │ └── structs.rs
│ ├── core-lib/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ ├── binds/
│ │ │ ├── mod.rs
│ │ │ ├── structs.rs
│ │ │ └── transfer.rs
│ │ ├── const.rs
│ │ ├── data.rs
│ │ ├── default/
│ │ │ └── mod.rs
│ │ ├── ini.rs
│ │ ├── ini_owned.rs
│ │ ├── lib.rs
│ │ ├── listener.rs
│ │ ├── notify.rs
│ │ ├── path.rs
│ │ ├── transfer/
│ │ │ ├── mod.rs
│ │ │ ├── receive.rs
│ │ │ ├── send.rs
│ │ │ └── structs.rs
│ │ └── util/
│ │ ├── boot.rs
│ │ ├── exec.rs
│ │ ├── exists.rs
│ │ ├── helpers.rs
│ │ ├── mod.rs
│ │ └── path.rs
│ ├── exec-lib/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ ├── binds.rs
│ │ ├── collect.rs
│ │ ├── lib.rs
│ │ ├── listener.rs
│ │ ├── plugin.rs
│ │ ├── run.rs
│ │ ├── switch.rs
│ │ └── util.rs
│ ├── hyprland-plugin/
│ │ ├── Cargo.toml
│ │ ├── build.rs
│ │ ├── plugin/
│ │ │ ├── .gitignore
│ │ │ ├── .idea/
│ │ │ │ ├── copilot.data.migration.agent.xml
│ │ │ │ ├── copilot.data.migration.ask2agent.xml
│ │ │ │ ├── copilot.data.migration.edit.xml
│ │ │ │ ├── dictionaries/
│ │ │ │ │ └── project.xml
│ │ │ │ ├── editor.xml
│ │ │ │ ├── misc.xml
│ │ │ │ ├── vcs.xml
│ │ │ │ └── workspace.xml
│ │ │ ├── Makefile
│ │ │ ├── README.md
│ │ │ ├── src-52/
│ │ │ │ ├── defs-test.h
│ │ │ │ ├── defs.h
│ │ │ │ ├── exit.cpp
│ │ │ │ ├── globals.h
│ │ │ │ ├── handlers.h
│ │ │ │ ├── init.cpp
│ │ │ │ ├── key-press.cpp
│ │ │ │ ├── keyboard-focus.cpp
│ │ │ │ ├── layer-change.cpp
│ │ │ │ ├── main.cpp
│ │ │ │ ├── mouse-button.cpp
│ │ │ │ ├── send.cpp
│ │ │ │ └── send.h
│ │ │ ├── src-54/
│ │ │ │ ├── defs-test.h
│ │ │ │ ├── defs.h
│ │ │ │ ├── exit.cpp
│ │ │ │ ├── globals.h
│ │ │ │ ├── handlers.h
│ │ │ │ ├── init.cpp
│ │ │ │ ├── key-press.cpp
│ │ │ │ ├── keyboard-focus.cpp
│ │ │ │ ├── layer-change.cpp
│ │ │ │ ├── main.cpp
│ │ │ │ ├── mouse-button.cpp
│ │ │ │ ├── send.cpp
│ │ │ │ └── send.h
│ │ │ └── test-hyprland.conf
│ │ └── src/
│ │ ├── build.rs
│ │ ├── configure.rs
│ │ ├── extract.rs
│ │ ├── lib.rs
│ │ └── test.rs
│ ├── launcher-lib/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ ├── close.rs
│ │ ├── create.rs
│ │ ├── css.rs
│ │ ├── debug.rs
│ │ ├── global.rs
│ │ ├── lib.rs
│ │ ├── open.rs
│ │ ├── plugins/
│ │ │ ├── actions.rs
│ │ │ ├── applications/
│ │ │ │ ├── data.rs
│ │ │ │ ├── map.rs
│ │ │ │ ├── mod.rs
│ │ │ │ └── plugin.rs
│ │ │ ├── calc.rs
│ │ │ ├── mod.rs
│ │ │ ├── path.rs
│ │ │ ├── search.rs
│ │ │ ├── shell.rs
│ │ │ └── terminal.rs
│ │ ├── stop.rs
│ │ ├── styles.css
│ │ └── update.rs
│ └── windows-lib/
│ ├── Cargo.toml
│ └── src/
│ ├── css.rs
│ ├── data.rs
│ ├── desktop_map.rs
│ ├── global.rs
│ ├── icon.rs
│ ├── keybinds.rs
│ ├── lib.rs
│ ├── next.rs
│ ├── overview/
│ │ ├── close.rs
│ │ ├── create.rs
│ │ ├── mod.rs
│ │ ├── open.rs
│ │ ├── stop.rs
│ │ └── update.rs
│ ├── sort.rs
│ ├── styles.css
│ └── switch/
│ ├── close.rs
│ ├── create.rs
│ ├── mod.rs
│ ├── open.rs
│ ├── stop.rs
│ └── update.rs
├── dep-crates/
│ ├── hyprland-rs/
│ │ ├── Cargo.toml
│ │ ├── LICENSE
│ │ ├── MIGRATION.md
│ │ ├── README.md
│ │ ├── examples/
│ │ │ ├── bind.rs
│ │ │ ├── bind_async.rs
│ │ │ ├── data.rs
│ │ │ ├── data_async.rs
│ │ │ ├── dispatch.rs
│ │ │ ├── dispatch_async.rs
│ │ │ ├── events.rs
│ │ │ ├── events_async.rs
│ │ │ ├── keyword.rs
│ │ │ └── keyword_async.rs
│ │ ├── flake.nix
│ │ ├── hyprland-macros/
│ │ │ ├── Cargo.toml
│ │ │ ├── README.md
│ │ │ └── src/
│ │ │ └── lib.rs
│ │ ├── src/
│ │ │ ├── config.rs
│ │ │ ├── ctl.rs
│ │ │ ├── data/
│ │ │ │ ├── helpers.rs
│ │ │ │ ├── macros.rs
│ │ │ │ ├── mod.rs
│ │ │ │ └── regular.rs
│ │ │ ├── dispatch.rs
│ │ │ ├── error.rs
│ │ │ ├── event_listener/
│ │ │ │ ├── async_im.rs
│ │ │ │ ├── immutable.rs
│ │ │ │ ├── macros.rs
│ │ │ │ ├── mod.rs
│ │ │ │ ├── shared.rs
│ │ │ │ └── stream.rs
│ │ │ ├── hyprpaper/
│ │ │ │ ├── error.rs
│ │ │ │ ├── keyword.rs
│ │ │ │ ├── monitor.rs
│ │ │ │ ├── preload.rs
│ │ │ │ ├── reload.rs
│ │ │ │ ├── unload.rs
│ │ │ │ ├── wallpaper.rs
│ │ │ │ ├── wallpaper_listing.rs
│ │ │ │ └── wallpaper_mode.rs
│ │ │ ├── hyprpaper.rs
│ │ │ ├── instance.rs
│ │ │ ├── keyword.rs
│ │ │ ├── lib.rs
│ │ │ ├── shared.rs
│ │ │ └── unsafe_impl.rs
│ │ ├── test.sh
│ │ └── treefmt.toml
│ └── wl-clipboard-rs/
│ ├── .github/
│ │ ├── dependabot.yml
│ │ └── workflows/
│ │ └── ci.yml
│ ├── .gitignore
│ ├── CHANGELOG.md
│ ├── Cargo.toml
│ ├── LICENSE-APACHE
│ ├── LICENSE-MIT
│ ├── README.md
│ ├── README.tpl
│ ├── doc/
│ │ └── index.html
│ ├── rustfmt.toml
│ └── src/
│ ├── common.rs
│ ├── copy.rs
│ ├── data_control.rs
│ ├── lib.rs
│ ├── paste.rs
│ ├── seat_data.rs
│ ├── tests/
│ │ ├── copy.rs
│ │ ├── mod.rs
│ │ ├── paste.rs
│ │ ├── state.rs
│ │ └── utils.rs
│ └── utils.rs
├── docs/
│ ├── CONFIGURE.md
│ ├── DEBUG.md
│ ├── NIX.md
│ └── css-examples/
│ ├── default.css
│ ├── dracula.css
│ ├── gruvbox_dark.css
│ ├── liquid-glass.css
│ ├── modern.css
│ ├── solarized_dark.css
│ ├── test.css
│ └── tokyo_night_storm.css
├── flake.nix
├── justfile
├── nix/
│ ├── build.nix
│ ├── checks.nix
│ ├── meta.nix
│ ├── module.nix
│ └── util.nix
├── packaging/
│ ├── hyprshell-settings.desktop
│ ├── hyprshell.service
│ └── pkgbuild/
│ ├── PKGBUILD
│ ├── PKGBUILD-bin
│ └── PKGBUILD-slim
├── pkgbuild/
│ ├── PKGBUILD
│ ├── PKGBUILD-bin
│ └── PKGBUILD-slim
├── release-please-config.json
├── renovate.json
├── scripts/
│ ├── check-all-feature-combinations.sh
│ └── ci/
│ ├── build-aarch64.sh
│ ├── build-x86.sh
│ ├── install-gtk4-layer-shell-aarch64.sh
│ └── install-gtk4-layer-shell.sh
└── src/
├── cli.rs
├── completions.rs
├── data.rs
├── debug.rs
├── default_apps.rs
├── default_styles.css
├── explain.rs
├── keybinds.rs
├── main.rs
├── receive_handle.rs
├── socket.rs
├── start.rs
└── util.rs
================================================
FILE CONTENTS
================================================
================================================
FILE: .githooks/pre-commit
================================================
just check
================================================
FILE: .github/workflows/publish.yml
================================================
name: publish
on:
push:
tags:
- 'v*'
jobs:
check:
runs-on: ubuntu-latest
outputs:
should_publish: ${{ steps.check_commit.outputs.should_publish }}
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Check commit message
id: check_commit
run: |
commit_msg=$(git log -1 --pretty=%B)
if [[ $commit_msg =~ ^chore\(hyprshell.*\):\ release ]]; then
echo "should_publish=true" >> $GITHUB_OUTPUT
else
echo "Error: Commit message must start with 'chore(hyprshell): release'"
echo "should_publish=false" >> $GITHUB_OUTPUT
fi
publish:
needs: check
runs-on: ubuntu-latest
container:
image: ghcr.io/h3rmt/actions-image:latest
options: --privileged
if: needs.check.outputs.should_publish == 'true'
steps:
- run: rustup default stable
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
fetch-depth: 0
ssh-key: ${{ secrets.SSH_KEY }}
- name: Install gtk4-layer-shell
run: ./scripts/ci/install-gtk4-layer-shell.sh
- name: Install cargo-workspaces
run: |
mkdir -p $HOME/.cargo/bin
cargo install cargo-workspaces
cargo ws --version
- name: Publish to crates.io
run: |
set -euxo pipefail
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git fetch --tags origin hyprshell-release
git checkout ${{ github.ref }} -b hyprshell-release
git log -1 --pretty=%B
git push origin HEAD:hyprshell-release --force
git switch hyprshell-release
current_sha=$(git rev-parse HEAD)
jq --arg sha "$current_sha" '.["last-release-sha"]=$sha' release-please-config.json > tmp.json
mv tmp.json release-please-config.json
git add release-please-config.json
git commit -m "chore(release): update last-release-sha"
git push origin hyprshell-release
git tag --delete ${{ github.ref_name }}
git push --delete origin ${{ github.ref_name }}
version=$(echo ${{ github.ref_name }} | sed 's/v//')
cargo ws publish custom $version -m "chore(release): bump versions to $version" --no-individual-tags --allow-branch hyprshell-release --exact --yes --force "hyprshell*" --token ${{ secrets.CRATES_TOKEN }}
# push current branch to hyprshell branch (for development)
git push origin HEAD:hyprshell-release
gh release edit ${{ github.ref_name }} --latest --draft=false --title "hyprshell ${{ github.ref_name }}"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Publish AUR package
uses: KSXGitHub/github-actions-deploy-aur@2ac5a4c1d7035885d46b10e3193393be8460b6f1 # v4.1.1
with:
pkgname: hyprshell
pkgbuild: ./packaging/pkgbuild/PKGBUILD
commit_username: ${{ secrets.AUR_USERNAME }}
commit_email: ${{ secrets.AUR_EMAIL }}
ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
commit_message: Update hyprshell AUR package
updpkgsums: true
ssh_keyscan_types: rsa,ecdsa,ed25519
- name: Publish AUR slim package
uses: KSXGitHub/github-actions-deploy-aur@2ac5a4c1d7035885d46b10e3193393be8460b6f1 # v4.1.1
with:
pkgname: hyprshell-slim
pkgbuild: ./packaging/pkgbuild/PKGBUILD-slim
commit_username: ${{ secrets.AUR_USERNAME }}
commit_email: ${{ secrets.AUR_EMAIL }}
ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
commit_message: Update hyprshell-slim AUR package
updpkgsums: true
ssh_keyscan_types: rsa,ecdsa,ed25519
- name: Build binary for x86_64-unknown-linux-gnu
run: |
version=$(echo ${{ github.ref_name }} | sed 's/v//')
./scripts/ci/build-x86.sh
mv "/tmp/hyprshell-x86_64.tar.zst" "/tmp/hyprshell-$version-x86_64.tar.zst"
gh release upload ${{ github.ref_name }} "/tmp/hyprshell-$version-x86_64.tar.zst"
mv "/tmp/hyprshell-slim-x86_64.tar.zst" "/tmp/hyprshell-slim-$version-x86_64.tar.zst"
gh release upload ${{ github.ref_name }} "/tmp/hyprshell-slim-$version-x86_64.tar.zst"
cargo clean
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Build binary for aarch64-unknown-linux-gnu
run: |
version=$(echo ${{ github.ref_name }} | sed 's/v//')
./scripts/ci/install-gtk4-layer-shell-aarch64.sh
./scripts/ci/build-aarch64.sh
mv "/tmp/hyprshell-aarch64.tar.zst" "/tmp/hyprshell-$version-aarch64.tar.zst"
gh release upload ${{ github.ref_name }} "/tmp/hyprshell-$version-aarch64.tar.zst"
mv "/tmp/hyprshell-slim-aarch64.tar.zst" "/tmp/hyprshell-slim-$version-aarch64.tar.zst"
gh release upload ${{ github.ref_name }} "/tmp/hyprshell-slim-$version-aarch64.tar.zst"
cargo clean
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Publish AUR bin package
uses: KSXGitHub/github-actions-deploy-aur@2ac5a4c1d7035885d46b10e3193393be8460b6f1 # v4.1.1
with:
pkgname: hyprshell-bin
pkgbuild: ./packaging/pkgbuild/PKGBUILD-bin
commit_username: ${{ secrets.AUR_USERNAME }}
commit_email: ${{ secrets.AUR_EMAIL }}
ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
commit_message: Update hyprshell-bin AUR package
updpkgsums: true
ssh_keyscan_types: rsa,ecdsa,ed25519
- uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16
with:
name: hyprshell
extraPullNames: hyprshell-dev, hyprland
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
- name: Run Nix Flake Build
run: nix build '.#packages.x86_64-linux.hyprshell' -L
================================================
FILE: .github/workflows/release-please.yml
================================================
name: release-please
on:
push:
branches:
- 'hyprshell'
- 'hyprshell-patch-**'
jobs:
release-please:
runs-on: ubuntu-latest
steps:
- uses: googleapis/release-please-action@16a9c90856f42705d54a6fda1823352bdc62cf38 # v4.4.0
with:
token: ${{ secrets.RELEASE_PLEASE_TOKEN }}
config-file: release-please-config.json
manifest-file: .release-please-manifest.json
target-branch: ${{ github.ref_name }}
================================================
FILE: .github/workflows/test.yml
================================================
name: test
on:
push:
branches-ignore:
- 'release-please-**'
- 'hyprshell-release'
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
check-nix:
name: Run Nix Flake Check
runs-on: "ubuntu-latest"
container:
image: ghcr.io/h3rmt/actions-image:latest
options: --privileged
steps:
- run: rustup default stable
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16
with:
name: hyprshell-dev
extraPullNames: hyprland
pushFilter: "hyprshell-(nextest|clippy|fmt|check-all-feature-combinations|check-nix-configs).*"
authToken: ${{ secrets.CACHIX_AUTH_TOKEN_DEV }}
- name: Run Nix Flake Build deps
run: nix build '.#checks.x86_64-linux.hyprshell-build-deps' -L
- name: Run Nix Flake Check build
run: nix build '.#checks.x86_64-linux.hyprshell-config-check' -L
- name: Run Nix Flake Check clippy
run: nix build '.#checks.x86_64-linux.hyprshell-clippy' -L
- name: Run Nix Flake Check fmt
run: nix build '.#checks.x86_64-linux.hyprshell-fmt' -L
- name: Run Nix Flake Check test
run: nix build '.#checks.x86_64-linux.hyprshell-test' -L
- name: Run Nix Flake Check check-nix-configs
run: nix build '.#checks.x86_64-linux.hyprshell-check-nix-configs' -L
- name: Run Nix Flake Check check-all-feature-combinations
run: nix build '.#checks.x86_64-linux.hyprshell-check-all-feature-combinations' -L
check:
name: Run build tests
runs-on: "ubuntu-latest"
container:
image: ghcr.io/h3rmt/actions-image:latest
options: --privileged
if: github.ref == 'refs/heads/hyprshell'
steps:
- run: rustup default stable
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # v2.8.1
with:
prefix-key: hyprshell
cache-on-failure: true
- name: Build binary for x86_64-unknown-linux-gnu
run: |
./scripts/ci/install-gtk4-layer-shell.sh
./scripts/ci/build-x86.sh
- name: Build binary for aarch64-unknown-linux-gnu
run: |
./scripts/ci/install-gtk4-layer-shell-aarch64.sh
./scripts/ci/build-aarch64.sh
================================================
FILE: .github/workflows/update.yml
================================================
name: update flake.lock
on:
workflow_dispatch: # allows manual triggering
schedule:
- cron: '30 2 1,15 * *' # At 02:30 on every 14th day-of-month.
jobs:
nix-flake-update:
permissions:
contents: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: cachix/install-nix-action@0b0e072294b088b73964f1d72dfdac0951439dbd # v31.8.4
with:
github_access_token: ${{ secrets.GITHUB_TOKEN }}
- name: Update flake
run: |
git fetch
git switch hyprshell
nix flake update
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add flake.lock
git commit -m "fix(nix-flake): update flake.lock"
git push origin hyprshell
================================================
FILE: .gitignore
================================================
/target
/*/target
/result
/test-data
================================================
FILE: .idea/.gitignore
================================================
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
================================================
FILE: .idea/copilot.data.migration.agent.xml
================================================
================================================
FILE: .idea/copilot.data.migration.ask.xml
================================================
================================================
FILE: .idea/copilot.data.migration.ask2agent.xml
================================================
================================================
FILE: .idea/copilot.data.migration.edit.xml
================================================
================================================
FILE: .idea/file.template.settings.xml
================================================
================================================
FILE: .idea/hyprshell.iml
================================================
================================================
FILE: .idea/inspectionProfiles/Project_Default.xml
================================================
================================================
FILE: .idea/modules.xml
================================================
================================================
FILE: .idea/rust.xml
================================================
================================================
FILE: .idea/vcs.xml
================================================
================================================
FILE: .release-please-manifest.json
================================================
{
".": "4.9.5"
}
================================================
FILE: CHANGELOG.md
================================================
# Changelog
## [4.9.5](https://github.com/H3rmt/hyprshell/compare/v4.9.4...v4.9.5) (2026-03-31)
### Bug Fixes
* use cpp26 for hyprland plugin ([6fcff3b](https://github.com/H3rmt/hyprshell/commit/6fcff3b3de906497f96648f53fe20522ea5db577))
## [4.9.4](https://github.com/H3rmt/hyprshell/compare/v4.9.3...v4.9.4) (2026-03-02)
### Bug Fixes
* bundle multiple plugin versions to support wider range of hyprland versions ([95908e0](https://github.com/H3rmt/hyprshell/commit/95908e067293fd4ad4381f6b11bf923a69f96637))
* fix use correct keyboard in plugin ([805bbb4](https://github.com/H3rmt/hyprshell/commit/805bbb44c9671b57fb633e90227bc69b318c685d))
* update plugin to new hyprland plugin api ([6bfc01d](https://github.com/H3rmt/hyprshell/commit/6bfc01de8e0461119d2e4b5b0bc4b2202c36b4c9))
## [4.9.3](https://github.com/H3rmt/hyprshell/compare/v4.9.2...v4.9.3) (2026-03-02)
### Bug Fixes
* bundle multiple plugin versions to support wider range of hyprland versions ([95908e0](https://github.com/H3rmt/hyprshell/commit/95908e067293fd4ad4381f6b11bf923a69f96637))
* update plugin to new hyprland plugin api ([6bfc01d](https://github.com/H3rmt/hyprshell/commit/6bfc01de8e0461119d2e4b5b0bc4b2202c36b4c9))
## [4.9.2](https://github.com/H3rmt/hyprshell/compare/v4.9.1...v4.9.2) (2026-01-06)
### Bug Fixes
* fix release ci workflow ([eada938](https://github.com/H3rmt/hyprshell/commit/eada9385f52846c6468891cb061c5a879fd16098))
## [4.9.1](https://github.com/H3rmt/hyprshell/compare/v4.9.0...v4.9.1) (2026-01-06)
### Bug Fixes
* add websearch and actions configs ([923055e](https://github.com/H3rmt/hyprshell/commit/923055ea721fd01a3abce376564cb7b2f81449dd))
* reduce image size ([923055e](https://github.com/H3rmt/hyprshell/commit/923055ea721fd01a3abce376564cb7b2f81449dd))
## [4.9.0](https://github.com/H3rmt/hyprshell/compare/v4.8.3...v4.9.0) (2026-01-05)
### Features
* add generate page ([1f9cb52](https://github.com/H3rmt/hyprshell/commit/1f9cb52edf6f48c446b92ec3398e19fe3e5cb224))
* add terminal settings and overview keyboard shortcut chooser to generate setup ([f7ae9bf](https://github.com/H3rmt/hyprshell/commit/f7ae9bf3d2b5769627faa2735fb7c6058a6de998))
* added data file to themes ([9e13a4a](https://github.com/H3rmt/hyprshell/commit/9e13a4a3e2273cd9be56438f0b6515e3fa593c52))
* added debug info command ([efa1010](https://github.com/H3rmt/hyprshell/commit/efa10109c0af9ed04912f1e2066632650d460494))
* added theme chooser ([8deccc2](https://github.com/H3rmt/hyprshell/commit/8deccc2dba445411bca4f781b93d9ddab52ac942))
* added theme settings to config editor ([178f60b](https://github.com/H3rmt/hyprshell/commit/178f60b975a85ec54840801d627bdfd0a1bfd0b3))
* allow custom key for switch mode ([3d07d3c](https://github.com/H3rmt/hyprshell/commit/3d07d3ceac3f1233f58498e7725c34c867450016))
* generate config from gui ([c6237a2](https://github.com/H3rmt/hyprshell/commit/c6237a25ef6d0b676aedd48aa5260fd12e6b39f8))
* retry getting version for 40 times ([9207c2a](https://github.com/H3rmt/hyprshell/commit/9207c2a9485211b3ba8c86c5e15cac35ca5e7c1d))
### Bug Fixes
* **deps:** update rust crate ron to 0.12.0 ([1c6038a](https://github.com/H3rmt/hyprshell/commit/1c6038a3f546d56da6ce18a2cccdeaedc7fdd90b))
* fix bin package for aur ([4906ccb](https://github.com/H3rmt/hyprshell/commit/4906ccb8344d3022298d225841276e89b703702a))
* fix bin package for aur ([22a9b3b](https://github.com/H3rmt/hyprshell/commit/22a9b3b33e30ce810da9a806bbc61418f85537d9))
* fix systemd unit generation ([4318bf5](https://github.com/H3rmt/hyprshell/commit/4318bf5442ac08dfde638caa97417d5ad67bd5c9))
* **nix-flake:** update flake.lock ([54fb1d0](https://github.com/H3rmt/hyprshell/commit/54fb1d06a1e63a3abc3004caae96a306a0cdd98d))
* **nix-flake:** update flake.lock ([cfe263a](https://github.com/H3rmt/hyprshell/commit/cfe263a09189d92c218f2223d6b4552200777410))
* **nix-flake:** update flake.lock ([66e4a85](https://github.com/H3rmt/hyprshell/commit/66e4a85b98b06febd33036e8f14ed12bff923941))
* update hyprland plugin ([3d07d3c](https://github.com/H3rmt/hyprshell/commit/3d07d3ceac3f1233f58498e7725c34c867450016))
### Code Refactoring
* add remaining plugin options ([ad9359f](https://github.com/H3rmt/hyprshell/commit/ad9359f6fb99042dbc94d229a343a5dffb789186))
* fix clippy fixes ([219f14c](https://github.com/H3rmt/hyprshell/commit/219f14c2d857975cdd6f9f6149df6085956e39ef))
* use justfile ([c6237a2](https://github.com/H3rmt/hyprshell/commit/c6237a25ef6d0b676aedd48aa5260fd12e6b39f8))
* use relm4 as base for adw and gtk ([d95e69e](https://github.com/H3rmt/hyprshell/commit/d95e69e783de3333458eb2aa112ed9a22844355c))
* use relm4 as base for adw and gtk ([f2e158c](https://github.com/H3rmt/hyprshell/commit/f2e158c0611773cb96d288451b965421ee4d1b3c))
### Documentation
* add minimum gtk and adwaita versions to README.md ([c33f431](https://github.com/H3rmt/hyprshell/commit/c33f431c3ef32e8530ca56589c5e107693ef4a2c))
## [4.8.3](https://github.com/H3rmt/hyprshell/compare/v4.8.2...v4.8.3) (2025-12-27)
### Bug Fixes
* fix bin package for aur ([443febe](https://github.com/H3rmt/hyprshell/commit/443febe5d54f2b32b3eb3c5c3b8d6f0af3e7276b))
## [4.8.2](https://github.com/H3rmt/hyprshell/compare/v4.8.1...v4.8.2) (2025-12-25)
### Bug Fixes
* fix systemd unit generation ([f0fdc99](https://github.com/H3rmt/hyprshell/commit/f0fdc99832510eee5862df6b5826d07e8b16cb9e))
* **nix-flake:** update flake.lock ([01531df](https://github.com/H3rmt/hyprshell/commit/01531df3820ab6346814f83abd5852a88ccf2c69))
* **nix-flake:** update flake.lock ([b8827a3](https://github.com/H3rmt/hyprshell/commit/b8827a3b2e0528991b22eacf41ad9f07b4cbbc73))
## [4.8.1](https://github.com/H3rmt/hyprshell/compare/v4.8.0...v4.8.1) (2025-11-17)
### Bug Fixes
* crash when filtering windows or clients ([#379](https://github.com/H3rmt/hyprshell/issues/379)) ([13e0105](https://github.com/H3rmt/hyprshell/commit/13e010558b47e416322c8961e5dd1a3e75008503))
* dont check for a hyprland session on commands other than run ([c93b2dc](https://github.com/H3rmt/hyprshell/commit/c93b2dc95347f32904c45fe820fa5f9e596fcdc0))
* increase waiting time if no initial workspace is being found ([b6e2782](https://github.com/H3rmt/hyprshell/commit/b6e27827f89670c90b11401d8931beea74dcf57c))
* **nix-flake:** update flake.lock ([b166440](https://github.com/H3rmt/hyprshell/commit/b16644046b712881d8bafbdd99f8acda9f39b6d6))
* use xdg notifications instead of hyprland notifications ([0db43a7](https://github.com/H3rmt/hyprshell/commit/0db43a7b905529bf5447fd373a01c78fb804972b))
### Code Refactoring
* update dependencies ([a1c00c7](https://github.com/H3rmt/hyprshell/commit/a1c00c782ae3ffac8b4a9f7c1793c5e8daddd061))
### Documentation
* updated nix docs ([facdf5a](https://github.com/H3rmt/hyprshell/commit/facdf5a3b40544b49d26886edb65b3726129ac9c))
## [4.8.0](https://github.com/H3rmt/hyprshell/compare/v4.7.2...v4.8.0) (2025-11-09)
### Features
* add special workspace support ([0604d21](https://github.com/H3rmt/hyprshell/commit/0604d21371552666b8e62e29ef4a782948c864fc))
* Add vim navigation to the switcher ([#360](https://github.com/H3rmt/hyprshell/issues/360)) ([cc0797d](https://github.com/H3rmt/hyprshell/commit/cc0797d8f18a970170619ad3b8e17ca8646d8d93))
* added brotli compression to clipboard lib ([dd0fb3d](https://github.com/H3rmt/hyprshell/commit/dd0fb3d29939775807fa372e280b688c8001e0da))
* added gui config editor ([bb29010](https://github.com/H3rmt/hyprshell/commit/bb29010eb262dc22335e2c51d7bc5b78042e7553))
* added hyprshell-slim and hyprshell-bin aur packages ([bb29010](https://github.com/H3rmt/hyprshell/commit/bb29010eb262dc22335e2c51d7bc5b78042e7553))
* added libadwaita instead of gtk4, added more config options ([bb29010](https://github.com/H3rmt/hyprshell/commit/bb29010eb262dc22335e2c51d7bc5b78042e7553))
* remove nix wrapper fn and add hyprland input instead ([bb29010](https://github.com/H3rmt/hyprshell/commit/bb29010eb262dc22335e2c51d7bc5b78042e7553))
### Bug Fixes
* add `Edit via `hyprshell config edit`` to config file ([e9b9ca4](https://github.com/H3rmt/hyprshell/commit/e9b9ca40c705c050f91859ebe8984cf778494c7b))
* disable hyprland plugin after loading fails once ([96cb6e6](https://github.com/H3rmt/hyprshell/commit/96cb6e6f2ab97fe4fc0f2d0eb53a13104c8685cf))
* dont generate systemd file if config is generated in debug mode ([bb29010](https://github.com/H3rmt/hyprshell/commit/bb29010eb262dc22335e2c51d7bc5b78042e7553))
* downgrad gtk version ([914bc34](https://github.com/H3rmt/hyprshell/commit/914bc34ceba8add1aec1691ace18740ef629b3da))
* downgrad libadwaita version ([7b6cced](https://github.com/H3rmt/hyprshell/commit/7b6ccedb29db0af4af7ee4a96198ad41c6762ba6))
* fix selecting client in a special workspace ([97d707c](https://github.com/H3rmt/hyprshell/commit/97d707cca2affd27f9a9cbc356224e96ecd831d2))
* Fix version check for Hyprshell Plugin ([#373](https://github.com/H3rmt/hyprshell/issues/373)) ([da03596](https://github.com/H3rmt/hyprshell/commit/da035960aadb971c518e415ac273443eceaad19c))
* **nix-flake:** update flake.lock ([2d6e0ee](https://github.com/H3rmt/hyprshell/commit/2d6e0eee010f88f67d97624a44ebe00abc00bd30))
* **nix-flake:** update flake.lock ([67e720e](https://github.com/H3rmt/hyprshell/commit/67e720e953bfcd0e30fa53ba9abafbaf2dff8cd7))
### Code Refactoring
* use adw instead of gtk4 ([bb29010](https://github.com/H3rmt/hyprshell/commit/bb29010eb262dc22335e2c51d7bc5b78042e7553))
### Documentation
* add explanations to tooltips ([2d7009c](https://github.com/H3rmt/hyprshell/commit/2d7009c22efadcace58f099f7f86173ec1f8dbcb))
* update readme ([bb29010](https://github.com/H3rmt/hyprshell/commit/bb29010eb262dc22335e2c51d7bc5b78042e7553))
## [4.7.2](https://github.com/H3rmt/hyprshell/compare/v4.7.1...v4.7.2) (2025-10-14)
### Bug Fixes
* added more logging to creation of windows ([2c57b0f](https://github.com/H3rmt/hyprshell/commit/2c57b0ffb3213b164053090c7c6ef47e8ac0c0ed))
## [4.7.1](https://github.com/H3rmt/hyprshell/compare/v4.7.0...v4.7.1) (2025-10-03)
### Bug Fixes
* docs mentioned style.css instead of styles.css as the default location for the CSS file ([a32a317](https://github.com/H3rmt/hyprshell/commit/a32a3171442357ae886fd5a07367a692097dccaf))
* **nix-flake:** update flake.lock ([944c2b4](https://github.com/H3rmt/hyprshell/commit/944c2b4ad012d7ab963f20c73e6d310d94c1cb33))
## [4.7.0](https://github.com/H3rmt/hyprshell/compare/v4.6.4...v4.7.0) (2025-09-23)
### Features
* add actions plugin ([559cc8a](https://github.com/H3rmt/hyprshell/commit/559cc8a81e6a55a09c0f637b503e646e80fc2570))
* add vim keybinds (https://github.com/H3rmt/hyprshell/issues/185) ([dca2dcc](https://github.com/H3rmt/hyprshell/commit/dca2dccc4199c5823959edfef56115d7b010c177))
### Bug Fixes
* **nix-flake:** update flake.lock ([590315d](https://github.com/H3rmt/hyprshell/commit/590315d396ff3811f9115f47dd52c228bd23e5bc))
* remove and update options from homemanager module ([2ae00bf](https://github.com/H3rmt/hyprshell/commit/2ae00bf10c17ab64685fc7458b880b68b7eddf97))
## [4.6.4](https://github.com/H3rmt/hyprshell/compare/v4.6.3...v4.6.4) (2025-09-14)
### Bug Fixes
* allow multiple instances (use wayland socket as part of APPID for gtk) ([8b8bce8](https://github.com/H3rmt/hyprshell/commit/8b8bce807a8d0ad9491396532f2bbfcde037ad0b))
* allow setting custom hyprland package to fix nix plugin build ([28d0e67](https://github.com/H3rmt/hyprshell/commit/28d0e677eaa4f7032cdacee8fa9ff279188b797b))
* always apply layerrules ([fbc9cb8](https://github.com/H3rmt/hyprshell/commit/fbc9cb853b986d82b4aac5307b5cb9e8465dcaab))
* disable gestures disabling (changed in Hyprland 51) ([8b8bce8](https://github.com/H3rmt/hyprshell/commit/8b8bce807a8d0ad9491396532f2bbfcde037ad0b))
* fix https://github.com/H3rmt/hyprshell/issues/336 by converting open to switch ([5c55ba6](https://github.com/H3rmt/hyprshell/commit/5c55ba6abcd5adb28eb9d216d80e300d942a6997))
* fix meta for wrapped program ([eabdefb](https://github.com/H3rmt/hyprshell/commit/eabdefbe4ee1cd81c295e049bd3ab0473b5660d0))
* reload follow mouse prev value on config reload ([8a43141](https://github.com/H3rmt/hyprshell/commit/8a431419941aa6641fc2abaf5e73b576d6f2c40a))
### Code Refactoring
* move crates to crate folder ([68633c6](https://github.com/H3rmt/hyprshell/commit/68633c6d776383e2384af9faa7456f15f2fcda1d))
## [4.6.3](https://github.com/H3rmt/hyprshell/compare/v4.6.2...v4.6.3) (2025-09-11)
### Bug Fixes
* allow for removal of shell completions ([9699d32](https://github.com/H3rmt/hyprshell/commit/9699d32212ce1c58784d7c83f925ad043f359a4f))
* cancel key events when opening hyprshell overview and switch ([92e4ea7](https://github.com/H3rmt/hyprshell/commit/92e4ea7a7990719071eae626feeb3f43911a4def))
* check for nothing enabled in config ([66b6820](https://github.com/H3rmt/hyprshell/commit/66b682089fb94b426c3d8f7c615b097dfe9f40f4))
* **deps:** update rust crate regex to v1.11.2 ([272fd94](https://github.com/H3rmt/hyprshell/commit/272fd94aeb8ae47ae7f3523e47ecd162e869cf15))
* fix reload of hyprland if hyprland config was reloaded ([9c2dd76](https://github.com/H3rmt/hyprshell/commit/9c2dd76e4b0c2ee791f6b4fa80aeb6ea5ca017de))
* ignore virtual keyboard inputs ([9699d32](https://github.com/H3rmt/hyprshell/commit/9699d32212ce1c58784d7c83f925ad043f359a4f))
* include /usr/share/applications/mimeapps ([7022cb2](https://github.com/H3rmt/hyprshell/commit/7022cb2c4d5a436cd1ccd63b50b944265a40e9a3))
* override of desktop files (https://github.com/H3rmt/hyprshell/issues/334) ([18fe033](https://github.com/H3rmt/hyprshell/commit/18fe03365799ce372af832a61335a5cf6f8f029c))
* plugin now still works if overview or switch are disabled ([66b6820](https://github.com/H3rmt/hyprshell/commit/66b682089fb94b426c3d8f7c615b097dfe9f40f4))
* print `No runs` if hyprshell data launch-history doesnt find any runs ([c67ab1b](https://github.com/H3rmt/hyprshell/commit/c67ab1b62c23cbf4f5f047a284f62b61a144adfa))
* use Layer::Top for launcher (fix https://github.com/H3rmt/hyprshell/issues/327) ([8389d58](https://github.com/H3rmt/hyprshell/commit/8389d5871be307919dd0bb37cbc8bcf7f010b8aa))
## [4.6.2](https://github.com/H3rmt/hyprshell/compare/v4.6.1...v4.6.2) (2025-09-07)
### Bug Fixes
* fix nix packaging ([efe38a2](https://github.com/H3rmt/hyprshell/commit/efe38a2508c50fc6eb9aecb39f1f65fe7047a28c))
* remove zip dependencies ([efe38a2](https://github.com/H3rmt/hyprshell/commit/efe38a2508c50fc6eb9aecb39f1f65fe7047a28c))
* use monochrome if path in launcher is a valid path but doesn't exist ([0f59ca3](https://github.com/H3rmt/hyprshell/commit/0f59ca33d4946e1247c5ca937d7f399a03a00f44))
### Code Refactoring
* better nix caching ([0f59ca3](https://github.com/H3rmt/hyprshell/commit/0f59ca33d4946e1247c5ca937d7f399a03a00f44))
## [4.6.1](https://github.com/H3rmt/hyprshell/compare/v4.6.0...v4.6.1) (2025-09-04)
### Bug Fixes
* **deps:** update deps ([108057a](https://github.com/H3rmt/hyprshell/commit/108057aa10525cb710f7785bd7ed3221bbf7c0e8))
* hyprland plugin now build without make in OUT_DIR ([31bdfb1](https://github.com/H3rmt/hyprshell/commit/31bdfb1392c4086ee6de6805826666ece2a0c18f))
### Documentation
* update nix docs ([eac79f1](https://github.com/H3rmt/hyprshell/commit/eac79f1b2dd2f3d5cc634d2cbcecdca40d8cdd4c))
## [4.6.0](https://github.com/H3rmt/hyprshell/compare/v4.5.0...v4.6.0) (2025-09-04)
### Features
* added shell completions ([a74fa47](https://github.com/H3rmt/hyprshell/commit/a74fa4777a2f905b6a0f0269401c564e60068692))
* added toml to ron migration (toml dropped, as it can't store None values) ([9d1e370](https://github.com/H3rmt/hyprshell/commit/9d1e370b7c2223171a6fb92d0aba0f9cc2a9ca01))
* better config migrations (allow multi version migrations) ([299d388](https://github.com/H3rmt/hyprshell/commit/299d38816d02dadd97160e7a13088f6aaca2d4ea))
* enhance ini parsing and added new cli command to get, list and set default apps ([2036a3c](https://github.com/H3rmt/hyprshell/commit/2036a3cb1a3588b97eaea5967e8900cff73726c8))
* show info when new version detected ([e80fe65](https://github.com/H3rmt/hyprshell/commit/e80fe65a86da07448936babfd4a59ee33340217f))
### Bug Fixes
* apply user style with user priority ([b700ee0](https://github.com/H3rmt/hyprshell/commit/b700ee0e4954b9e463ba64263953dacfc36ad097))
* close overview with open key ([aa5be3f](https://github.com/H3rmt/hyprshell/commit/aa5be3f560bd1fd7bf0026d8c9e09b3f4b4d15b4))
* **deps:** update rust crate anyhow to v1.0.99 ([a7e96f3](https://github.com/H3rmt/hyprshell/commit/a7e96f388deb7c132bf5bd2f35e88be3f7d56d45))
* **deps:** update rust crate notify to v8.1.0 ([611cde3](https://github.com/H3rmt/hyprshell/commit/611cde3cb681f030a038439f321421d4e875222e))
* enable show_actions_submenu for nix users ([8c19498](https://github.com/H3rmt/hyprshell/commit/8c1949892c46da3ff24548ccd904741694339fb0))
* exclude empty workspaces in switch mode ([10786eb](https://github.com/H3rmt/hyprshell/commit/10786eb5001f1ed7abc3bb2483741b30e410152f))
* exit app when removing / adding monitors ([032a047](https://github.com/H3rmt/hyprshell/commit/032a047597cab6f2dbe0c6e4482c8d05eb7fbdca))
* fix cargo install cargo-workspaces ([e62a334](https://github.com/H3rmt/hyprshell/commit/e62a33465633ae87653fed679549b4cfc988f73b))
* fix cargo ws publish, allow buildscript to run make ([14b5b5a](https://github.com/H3rmt/hyprshell/commit/14b5b5a2ab9e6501c2c125203f44808a80314649))
* fix missing version in dependency of custom hyprland-rs ([94747cc](https://github.com/H3rmt/hyprshell/commit/94747cc81f554faf034bb5b7c5ec04dcbad03119))
* fix publish workflow check commit ([29e440f](https://github.com/H3rmt/hyprshell/commit/29e440f6f0685e93d24291196b16623d7721bcd6))
* fixed select window in overview ([71080a9](https://github.com/H3rmt/hyprshell/commit/71080a9211bd63de4aa0c1405810dfa1126c180c))
* **nix-flake:** update flake.lock ([918e40b](https://github.com/H3rmt/hyprshell/commit/918e40beb8e70649e52ffcf8dd21747bcdc3f27f))
* **nix-flake:** update flake.lock ([4eeaa57](https://github.com/H3rmt/hyprshell/commit/4eeaa5710aa7503b9a1307c8016879fd8df664ec))
* **plugin:** fix open overview after mouse button press ([bd03613](https://github.com/H3rmt/hyprshell/commit/bd0361332ca313d527daec85d7cfdc0d057a5fc1))
* reload desktop files, etc. after opening launcher ([a679985](https://github.com/H3rmt/hyprshell/commit/a67998550abd8069c47a6d2bd762b72208a70b2f))
* style changes, liquid gras css updated ([6871827](https://github.com/H3rmt/hyprshell/commit/687182774094aa572441ece0ad9b44c52612a196))
* typos in home manager configuration ([a9fc51e](https://github.com/H3rmt/hyprshell/commit/a9fc51e6e8d1e23302e17cc905f2f8285744c9fc))
* use bash to start apps ([c86dee1](https://github.com/H3rmt/hyprshell/commit/c86dee15733bc86f0ab81cceeb84bb1671876da3))
* use new hyprland-rs Instance ([c519605](https://github.com/H3rmt/hyprshell/commit/c51960581592469653380adfc03d3ea2f78e2e3a))
* use toml extension on lookup config file ([0ab9e9d](https://github.com/H3rmt/hyprshell/commit/0ab9e9dee21e70e80a815dbea7d833a32f5497cc))
### Code Refactoring
* add hyprland plugin ([1412e7a](https://github.com/H3rmt/hyprshell/commit/1412e7a46a3945d7a2f76dd1d1c5ac675160a17e))
* add hyprland plugin ([33ced1c](https://github.com/H3rmt/hyprshell/commit/33ced1cab64d2864de3f3b3d41f53484ec9adedb))
* better animations for launcher ([9c2a71c](https://github.com/H3rmt/hyprshell/commit/9c2a71cb275516adbd98ef084a9f5dcd564dedb2))
* build plugin at runtime ([400a93b](https://github.com/H3rmt/hyprshell/commit/400a93bbc340f933d473c393f4d71fcf2b5339ad))
* check if set desktop file is valid ([b7cfa98](https://github.com/H3rmt/hyprshell/commit/b7cfa982a371300bf523e12dbfd06f2734bc7ebd))
* fix nix wrap program ([5895432](https://github.com/H3rmt/hyprshell/commit/58954329f521daabaf67cb0c67a3f130ef9f26cc))
* implement plugin for switch mode ([9e1193e](https://github.com/H3rmt/hyprshell/commit/9e1193e14b7335af4c017593b2bcafb0a1882f90))
* more strict clippy rules ([fea4993](https://github.com/H3rmt/hyprshell/commit/fea4993df001461e1e0cc7ba64ccedfda605bb3c))
* return Ok / Err from socket ([61e09b7](https://github.com/H3rmt/hyprshell/commit/61e09b799860451290d68f46a0b98dc279ae2962))
* separate config crate ([9d1e370](https://github.com/H3rmt/hyprshell/commit/9d1e370b7c2223171a6fb92d0aba0f9cc2a9ca01))
* split launcher plugin into 2 data ([c0ff0b7](https://github.com/H3rmt/hyprshell/commit/c0ff0b74cce58f0eec04f79754971863770ebac3))
* store clippy lints in cargo.toml ([4387f52](https://github.com/H3rmt/hyprshell/commit/4387f52881a05780efa34de0457271363400c121))
* use different dirs for debug mode ([045def3](https://github.com/H3rmt/hyprshell/commit/045def381c611950851d4819b973a791ea896a2c))
* use global desktopfile and mime cache ([ea64c40](https://github.com/H3rmt/hyprshell/commit/ea64c408bbb4ca1d84eabadab3d6a9db9632b1de))
* use keymaps in hyprland plugin ([e0cd4da](https://github.com/H3rmt/hyprshell/commit/e0cd4daae2ed88ab7129a1f2c4dffca98d78d371))
* use make to improve plugin build time ([df032f4](https://github.com/H3rmt/hyprshell/commit/df032f4a1559dd13e60131a731e4d6e8d449de98))
* using plugin for all keyboard interactions ([ae39988](https://github.com/H3rmt/hyprshell/commit/ae39988bc3206089fb1b729d98b1ead4df1f32b9))
* using plugin for all keyboard interactions ([9dfa549](https://github.com/H3rmt/hyprshell/commit/9dfa5494bfd526d3acace3730f0edd9f7fbbe1eb))
### Documentation
* update CONFIGURE.md ([#304](https://github.com/H3rmt/hyprshell/issues/304)) ([9e590a0](https://github.com/H3rmt/hyprshell/commit/9e590a0339b547dfceea07ee8165eda649b1c8ec))
* updated docs ([d713230](https://github.com/H3rmt/hyprshell/commit/d713230fe5435b1f75e78b53c8e749423283a8af))
## [4.5.0](https://github.com/H3rmt/hyprshell/compare/v4.4.3...v4.5.0) (2025-06-27)
### Features
* added path plugin ([910aa35](https://github.com/H3rmt/hyprshell/commit/910aa357abc27c4c6f801d19920feed4e05549f1))
### Documentation
* update screenshots ([e9b8c7c](https://github.com/H3rmt/hyprshell/commit/e9b8c7ce5b2915ec13adf2cbd8994a3eb669408f))
## [4.4.3](https://github.com/H3rmt/hyprshell/compare/v4.4.2...v4.4.3) (2025-06-26)
### Bug Fixes
* fix modifier keys to launch again... ([d31ee66](https://github.com/H3rmt/hyprshell/commit/d31ee669c8da6460b1b0821b9b66783fd10c4a0e))
* use correct keys for switch mode ([b1c3353](https://github.com/H3rmt/hyprshell/commit/b1c335325f68ca1c5810fac772072640d5db464f))
### Code Refactoring
* changed PKGBUILD ([b3f207d](https://github.com/H3rmt/hyprshell/commit/b3f207d7bc0c27892d30fa2420053f27b8e714e6))
## [4.4.2](https://github.com/H3rmt/hyprshell/compare/v4.4.1...v4.4.2) (2025-06-26)
### Bug Fixes
* fix launcher keybinds ([05b2867](https://github.com/H3rmt/hyprshell/commit/05b28670edef4ca23e47100785b90b57b8311c06))
* fix modifier keys to launch, added launch_modifier ([19ba571](https://github.com/H3rmt/hyprshell/commit/19ba57169ae4c77e1e5331c764828f7f67703b90))
* **nix-flake:** update flake.lock ([abeaea5](https://github.com/H3rmt/hyprshell/commit/abeaea56cb568cb8e30ab8289e194ce10c46ec26))
* run flake update ci on hyprshell branch ([b39d435](https://github.com/H3rmt/hyprshell/commit/b39d435af9ceb60b25667bf70965499828f1f719))
### Code Refactoring
* simplify flake ([431536c](https://github.com/H3rmt/hyprshell/commit/431536cddc88606ebe2246ddb755c10a2db51643))
### Documentation
* update nix docs ([d0f45f1](https://github.com/H3rmt/hyprshell/commit/d0f45f1fdaeac348e25d5c5f7c95f76cabefb3d0))
## [4.4.1](https://github.com/H3rmt/hyprshell/compare/v4.4.0...v4.4.1) (2025-06-24)
### Bug Fixes
* run flake update ci on hyprshell branch ([b39d435](https://github.com/H3rmt/hyprshell/commit/b39d435af9ceb60b25667bf70965499828f1f719))
### Code Refactoring
* simplify flake ([431536c](https://github.com/H3rmt/hyprshell/commit/431536cddc88606ebe2246ddb755c10a2db51643))
### Documentation
* update nix docs ([d0f45f1](https://github.com/H3rmt/hyprshell/commit/d0f45f1fdaeac348e25d5c5f7c95f76cabefb3d0))
## [4.4.0](https://github.com/H3rmt/hyprshell/compare/v4.3.1...v4.4.0) (2025-06-24)
### Features
* add tui question for switch>show_workspaces ([8e0d925](https://github.com/H3rmt/hyprshell/commit/8e0d9254ec9e0556a1f7b214acbb70a98710c1ca))
* added show_workspaces flag ([bbba547](https://github.com/H3rmt/hyprshell/commit/bbba5472ed493b4ce5f0b4efe47e98c303e734b6))
### Bug Fixes
* dont allow opening overview and switch at the same time. ([7b61fd5](https://github.com/H3rmt/hyprshell/commit/7b61fd58627a7fe5be85c4322fd506b57b8685f0))
* dont launch plugin entries when typing num instead of ctrl + num ([7b61fd5](https://github.com/H3rmt/hyprshell/commit/7b61fd58627a7fe5be85c4322fd506b57b8685f0))
* fix nix strip_html_from_workspace_title ([e3f02ea](https://github.com/H3rmt/hyprshell/commit/e3f02ea902fd84fe6201fe29bf221e9804100f57))
* fix nix version setting ([06fd3f7](https://github.com/H3rmt/hyprshell/commit/06fd3f7f0de5e3f8c7ae80eb99e98f953766c81e))
* generate correct keybinds for opening overview with super + <key>, fix [#254](https://github.com/H3rmt/hyprshell/issues/254) ([9d52a57](https://github.com/H3rmt/hyprshell/commit/9d52a57baa17a0b41897073b3602619bc04f53d4))
* mark the current workspace as active if the overview is opened without an active client ([f6eaa02](https://github.com/H3rmt/hyprshell/commit/f6eaa0212782e35d2d0d051f77da53b3efaeda7c))
* removed old nix navigate assertions ([8151fba](https://github.com/H3rmt/hyprshell/commit/8151fba64718e69e7ed3a9d46bccfd54a84329d6))
### Code Refactoring
* add better nix checks and switch to nix only for ci ([b5f8682](https://github.com/H3rmt/hyprshell/commit/b5f86823ed599f2f133b6cba8271248417fbe03f))
* added check-if-default command for ci ([db912d1](https://github.com/H3rmt/hyprshell/commit/db912d1f1b6919e71288b9cc75e703071bce559e))
* separate nix code utils ([a3b61e8](https://github.com/H3rmt/hyprshell/commit/a3b61e869c6ff60b4b755f4b2c977ffbc4d82d91))
### Documentation
* update CONFIGURE.md ([24b9799](https://github.com/H3rmt/hyprshell/commit/24b979918340dd76515686996cf836e61cd96694))
## [4.3.1](https://github.com/H3rmt/hyprshell/compare/v4.3.0...v4.3.1) (2025-06-21)
### Bug Fixes
* repair launcher control keys ([78147fa](https://github.com/H3rmt/hyprshell/commit/78147fa354e3b961b19ce8a9a147601434d71d06))
## [4.3.0](https://github.com/H3rmt/hyprshell/compare/v4.2.12...v4.3.0) (2025-06-21)
### Features
* switch to gtk key handling ([65a0ad5](https://github.com/H3rmt/hyprshell/commit/65a0ad5f482707cab8339c3c01195ff9b5557c1a))
### Bug Fixes
* **deps:** update rust crate libc to v0.2.174 ([b6d1089](https://github.com/H3rmt/hyprshell/commit/b6d10891ce2bc1f649a6af7d62f2f7f2fa09d74b))
* fix closing on mod keys other than open key ([d6aba16](https://github.com/H3rmt/hyprshell/commit/d6aba16a2eedfee40bd74feae95750d75c2edf85))
* fix colored output for explain command ([5cbf8ed](https://github.com/H3rmt/hyprshell/commit/5cbf8ede5d3323b6d7484ab1b638f26842165e83))
### Code Refactoring
* remove launcher dependency of overview/switch crate ([df40faa](https://github.com/H3rmt/hyprshell/commit/df40faaec4bf5e5466575d6189194b97e303ac78))
* remove submaps (10/10) ([c7551ea](https://github.com/H3rmt/hyprshell/commit/c7551ea526583841b5de1b8071ee22a6d5b158fd))
* remove submaps (3/?) ([9f0c09e](https://github.com/H3rmt/hyprshell/commit/9f0c09e32d8a2ead763f38810f06b71e7dfa93e9))
* remove submaps (4/?) ([765c88c](https://github.com/H3rmt/hyprshell/commit/765c88c331c3b0e7d834857ef8dc76f235a342ad))
* remove submaps (5/?) ([65b31cf](https://github.com/H3rmt/hyprshell/commit/65b31cf95ec0edb16357cd865f8d2fa6a22f4e6a))
* remove submaps (6/?) ([0bc4396](https://github.com/H3rmt/hyprshell/commit/0bc43963a7783a03fc0681f43549e2cd55a56bc7))
* remove submaps (7/?) ([fdc797d](https://github.com/H3rmt/hyprshell/commit/fdc797d52cba759167a93f88e03b66609ef54f78))
* remove submaps (8/?) ([9de4678](https://github.com/H3rmt/hyprshell/commit/9de46780f4b2cfeb0f5f4fe9e39c67aebc9e8730))
* remove submaps (9/?) ([b3f0209](https://github.com/H3rmt/hyprshell/commit/b3f02096c69aa90ca49eebd02b922fb8a127c1b2))
## [4.2.12](https://github.com/H3rmt/hyprshell/compare/v4.2.11...v4.2.12) (2025-06-20)
### Bug Fixes
* repair ci ([eaf5391](https://github.com/H3rmt/hyprshell/commit/eaf5391a28a9821caaec626baab2a78211ee7cdd))
* repair ci ([e0f8af6](https://github.com/H3rmt/hyprshell/commit/e0f8af675a8702fa50c062030b00c51d2f0d4c30))
* repair ci ([ca782ce](https://github.com/H3rmt/hyprshell/commit/ca782ce03493b3d01f1e30540b7869ff20b0ad1e))
* repair ci ([761bd1b](https://github.com/H3rmt/hyprshell/commit/761bd1b3444f35c32924efbdd1fc375452600096))
* repair ci ([0aadfcc](https://github.com/H3rmt/hyprshell/commit/0aadfcc95262f34f49fd535fc88a35f767997423))
* show toast when using switch mode ([a34a9bb](https://github.com/H3rmt/hyprshell/commit/a34a9bbe2460dd44213fc5c15d7c34a140b19315))
* use release branch in ci to create new commits ([d8a489e](https://github.com/H3rmt/hyprshell/commit/d8a489e80070f3a3c7d9d451a9f4b04f703fb2d9))
## [4.2.11](https://github.com/H3rmt/hyprshell/compare/v4.2.10...v4.2.11) (2025-06-20)
### Bug Fixes
* repair ci ([ca782ce](https://github.com/H3rmt/hyprshell/commit/ca782ce03493b3d01f1e30540b7869ff20b0ad1e))
## [4.2.10](https://github.com/H3rmt/hyprshell/compare/v4.2.9...v4.2.10) (2025-06-20)
### Bug Fixes
* repair ci ([761bd1b](https://github.com/H3rmt/hyprshell/commit/761bd1b3444f35c32924efbdd1fc375452600096))
* repair ci ([0aadfcc](https://github.com/H3rmt/hyprshell/commit/0aadfcc95262f34f49fd535fc88a35f767997423))
* show toast when using switch mode ([a34a9bb](https://github.com/H3rmt/hyprshell/commit/a34a9bbe2460dd44213fc5c15d7c34a140b19315))
* use release branch in ci to create new commits ([d8a489e](https://github.com/H3rmt/hyprshell/commit/d8a489e80070f3a3c7d9d451a9f4b04f703fb2d9))
## [4.2.9](https://github.com/H3rmt/hyprshell/compare/v4.2.8...v4.2.9) (2025-06-20)
### Bug Fixes
* repair ci ([0aadfcc](https://github.com/H3rmt/hyprshell/commit/0aadfcc95262f34f49fd535fc88a35f767997423))
## [4.2.8](https://github.com/H3rmt/hyprshell/compare/v4.2.7...v4.2.8) (2025-06-20)
### Bug Fixes
* use release branch in ci to create new commits ([d8a489e](https://github.com/H3rmt/hyprshell/commit/d8a489e80070f3a3c7d9d451a9f4b04f703fb2d9))
## [4.2.7](https://github.com/H3rmt/hyprshell/compare/v4.2.6...v4.2.7) (2025-06-20)
### Bug Fixes
* show toast when using switch mode ([a34a9bb](https://github.com/H3rmt/hyprshell/commit/a34a9bbe2460dd44213fc5c15d7c34a140b19315))
## [4.2.6](https://github.com/H3rmt/hyprshell/compare/v4.2.5...v4.2.6) (2025-06-20)
### Bug Fixes
* show toast when using switch mode ([a34a9bb](https://github.com/H3rmt/hyprshell/commit/a34a9bbe2460dd44213fc5c15d7c34a140b19315))
## [4.2.5](https://github.com/H3rmt/hyprshell/compare/v4.2.4...v4.2.5) (2025-06-11)
### Bug Fixes
* fix run programs ([3997d2a](https://github.com/H3rmt/hyprshell/commit/3997d2a85e77d2d0e3a6799b17518ad5886aca74))
## [4.2.4](https://github.com/H3rmt/hyprswitch/compare/v4.2.3...v4.2.4) (2025-06-11)
### Bug Fixes
* diable gestures and input:follow_mouse on start and reset after close ([6a516b2](https://github.com/H3rmt/hyprswitch/commit/6a516b23e9124f577e16d2475962f8e3347237ae))
## [4.2.3](https://github.com/H3rmt/hyprswitch/compare/v4.2.2...v4.2.3) (2025-06-11)
### Bug Fixes
* fix storage of input:follow_mouse setting ([62ab0f2](https://github.com/H3rmt/hyprswitch/commit/62ab0f2f90a7235e3e2d6a8aa9267ebff4c16348))
* fix systemd exit ([26ae103](https://github.com/H3rmt/hyprswitch/commit/26ae103729696a02069c873bad76c2edbe9dcdf6))
## [4.2.2](https://github.com/H3rmt/hyprswitch/compare/v4.2.1...v4.2.2) (2025-06-11)
### Bug Fixes
* add HYPRSHELL_RELOAD_TIMEOUT to change timeout ([764cbb2](https://github.com/H3rmt/hyprswitch/commit/764cbb211ee0a2a1382443b34e58e8a4a035fdb9))
## [4.2.1](https://github.com/H3rmt/hyprswitch/compare/v4.2.0...v4.2.1) (2025-06-11)
### Bug Fixes
* add show_actions_submenu with default false ([c0828d6](https://github.com/H3rmt/hyprswitch/commit/c0828d6706157728e4af7742a8e97f7190a8eec0))
* file watchers work again ([73c7ebf](https://github.com/H3rmt/hyprswitch/commit/73c7ebf0914442c85b8af49e920fdbdd87be10a9))
* use correct path to generate config ([112e7d2](https://github.com/H3rmt/hyprswitch/commit/112e7d26acde6dd98805b69b807b6a5004763a96))
## [4.2.0](https://github.com/H3rmt/hyprswitch/compare/v4.1.1...v4.2.0) (2025-06-11)
### Features
* better window selection on empty workspace ([24b36b3](https://github.com/H3rmt/hyprswitch/commit/24b36b38cc0b127fe2de2a59c223936ffc9c988e))
* **nix:** Add `show_when_empty` ([8ebb333](https://github.com/H3rmt/hyprswitch/commit/8ebb333cd0dad0ff919ea1790136c8e6120d4560))
### Bug Fixes
* close socket after restarting app ([b4a8f2e](https://github.com/H3rmt/hyprswitch/commit/b4a8f2e61d503fb6eee7850ce1ce6f33dfab72bf))
* debounce reload ([5858cfd](https://github.com/H3rmt/hyprswitch/commit/5858cfd475f1e3b604f6d035bdc5507977833af5))
* **deps:** update rust crate clap to v4.5.40 ([19272f4](https://github.com/H3rmt/hyprswitch/commit/19272f40aec98c2820919f4d5924533f12b15fc9))
* **deps:** update rust crate toml to v0.8.23 ([6268be8](https://github.com/H3rmt/hyprswitch/commit/6268be8a74f85eb90dc1d7d94a5057ce6534ce89))
* handle sigterm and reset submap ([1516024](https://github.com/H3rmt/hyprswitch/commit/1516024a04d46f4433f52984197bf6f39eeee6a6))
* improved file watcher, file descriptor limit was reached if reloaded too many times ([b4a8f2e](https://github.com/H3rmt/hyprswitch/commit/b4a8f2e61d503fb6eee7850ce1ce6f33dfab72bf))
* selecting a client with filtering form workspace without an enabled client now selects the first valid client depending on the direction instead of a first client in the workspace ([2a72d8b](https://github.com/H3rmt/hyprswitch/commit/2a72d8ba63ff7c20412d1a9a1dcd7da861c8204b))
* toml config plugins for launcher ([5858cfd](https://github.com/H3rmt/hyprswitch/commit/5858cfd475f1e3b604f6d035bdc5507977833af5))
## [4.1.1](https://github.com/H3rmt/hyprswitch/compare/v4.1.0...v4.1.1) (2025-06-02)
### Bug Fixes
* release workflow now uses deploy keys ([e2c9b89](https://github.com/H3rmt/hyprswitch/commit/e2c9b89f10505a6617f74b3e05c4129b162029ec))
## [4.1.0](https://github.com/H3rmt/hyprswitch/compare/v4.0.4...v4.1.0) (2025-06-02)
### Features
* added kill_bind if hyprshell crashes ([5e0b0fa](https://github.com/H3rmt/hyprswitch/commit/5e0b0fa2cf8b7c7d4902fafff0b0dc4b2d03a84a))
* better parsing of desktop files(ini) to add DesktopActions in launcher ([a304809](https://github.com/H3rmt/hyprswitch/commit/a3048098b1702277cf25e0454e0a7dd3d48c61ee))
* faster open speeds by applying submaps earlier ([a304809](https://github.com/H3rmt/hyprswitch/commit/a3048098b1702277cf25e0454e0a7dd3d48c61ee))
### Bug Fixes
* use new ini parser everywhere ([8db2643](https://github.com/H3rmt/hyprswitch/commit/8db2643a7c5e5b51a316d4654268c38bc2202be4))
## [4.0.4](https://github.com/H3rmt/hyprswitch/compare/v4.0.3...v4.0.4) (2025-06-01)
### Bug Fixes
* more debugging for default browser to fix [#188](https://github.com/H3rmt/hyprswitch/issues/188) ([551bfd0](https://github.com/H3rmt/hyprswitch/commit/551bfd0b58aedbccc93236595beab63dcf9195dc))
## [4.0.3](https://github.com/H3rmt/hyprswitch/compare/v4.0.2...v4.0.3) (2025-06-01)
### Bug Fixes
* fixed icon scaling ([5a0489a](https://github.com/H3rmt/hyprswitch/commit/5a0489a39742d89abed3760096c3dccee2fa5845))
* remove launch animation from plugins after close ([685b7bd](https://github.com/H3rmt/hyprswitch/commit/685b7bdf205cafc48e9a21aaccd9428e774905d9))
* use dbus to open if no browser was found ([c074a56](https://github.com/H3rmt/hyprswitch/commit/c074a56ac7603c14754a4b20a65eeb095e2a103d))
## [4.0.2](https://github.com/H3rmt/hyprswitch/compare/v4.0.1...v4.0.2) (2025-05-31)
### Bug Fixes
* fixed the PKGBUILD for arch ([89c06ba](https://github.com/H3rmt/hyprswitch/commit/89c06baa318157827e7042adeaa4ca274b251756))
## [4.0.1](https://github.com/H3rmt/hyprswitch/compare/v4.0.0...v4.0.1) (2025-05-31)
### Bug Fixes
* added the PKGBUILD for arch ([93ca69b](https://github.com/H3rmt/hyprswitch/commit/93ca69b15061f4ad8e4f1bcb674dba59c278571b))
## [4.0.0](https://github.com/H3rmt/hyprswitch/compare/v0.8.2...v4.0.0) (2025-05-31)
### Features
* add animation to plugin close launch ([b944274](https://github.com/H3rmt/hyprswitch/commit/b9442742b5a357966061c66e594b9104d158fe7b))
* add calc plugin ([06c8a41](https://github.com/H3rmt/hyprswitch/commit/06c8a41db42d482b777f158fcf9eb1b23708cc13))
* add debug command ([00afa1e](https://github.com/H3rmt/hyprswitch/commit/00afa1e34b9716a041d3bd33734700836075bd70))
* Add NixOS `home-manager` module ([cd20717](https://github.com/H3rmt/hyprswitch/commit/cd207178a0cfd44c7ad1069880ef35532f5547ae))
* add run shell commands from launcher ([879cbba](https://github.com/H3rmt/hyprswitch/commit/879cbba0597281c14b07dadfe03149b4323caf6f))
* add websearch plugin ([1a079d1](https://github.com/H3rmt/hyprswitch/commit/1a079d1552036f8713ba69f33271475ff4a41103))
* added `data` command to see LaunchHistory ([8e3de53](https://github.com/H3rmt/hyprswitch/commit/8e3de53b31834c8a034d28d26d72ebcbbd4d9815))
* added click on clients and workspaces in overview and switch ([328fc3b](https://github.com/H3rmt/hyprswitch/commit/328fc3b432b28ad1e390be10f945e1425708d430))
* added config file migrations ([db2f6cd](https://github.com/H3rmt/hyprswitch/commit/db2f6cd9fb3c08ab2f9858fb9c1dac61540353b5))
* added custom args for hyprshell systemd ([aa01139](https://github.com/H3rmt/hyprswitch/commit/aa01139aebfe2dcd717b670ac6ce557f93c2f1d0))
* added show_when_empty ([6f916d5](https://github.com/H3rmt/hyprswitch/commit/6f916d5b0355293eb0d4007b3c996deddb943c0d))
* added systemd generation (use --no-systemd to disable) ([97c2c7f](https://github.com/H3rmt/hyprswitch/commit/97c2c7f88c3ba221863a43b8adbfb50b444fa841))
* better debug commands ([b17a393](https://github.com/H3rmt/hyprswitch/commit/b17a393b04201beab8b582a340d1bb80bef5cda2))
* click on entry in launcher works ([87076ef](https://github.com/H3rmt/hyprswitch/commit/87076ef8c715fc0f7e29a7c2187aa59f17514df5))
* NixOS Support ([#171](https://github.com/H3rmt/hyprswitch/issues/171)) ([d42f12b](https://github.com/H3rmt/hyprswitch/commit/d42f12be62c08d3764bc91b034bc7aa05d531608))
* rewrite hyprswitch ([198cd0f](https://github.com/H3rmt/hyprswitch/commit/198cd0f5ae03210b46cfaba8dbf5f8d30fcc77a9))
* rewrite hyprswitch ([0d834ab](https://github.com/H3rmt/hyprswitch/commit/0d834ab64cb607d2bc10ca7b13d2642728592f50))
### Bug Fixes
* add aur publish ([fc4f9ab](https://github.com/H3rmt/hyprswitch/commit/fc4f9ab4f040646ff075930a86457bf7d4f3e77c))
* add nix back ([9efadcd](https://github.com/H3rmt/hyprswitch/commit/9efadcdc37ae0c639ab36a1880e3d48b1b6c51a2))
* allow hold of tab and arrow keys to switch ([e0aaa57](https://github.com/H3rmt/hyprswitch/commit/e0aaa570f54fce0155631c5720805886a0c275a1))
* arrow keys in the launcher ([179ca7b](https://github.com/H3rmt/hyprswitch/commit/179ca7b45e865875584a4c658a0455ea00af0bc6))
* background loading of icons ([f5c8ff0](https://github.com/H3rmt/hyprswitch/commit/f5c8ff0e29713432726bb841bafd8dd6729331fa))
* better icon detection ([453888e](https://github.com/H3rmt/hyprswitch/commit/453888e61551946cfa3dec92409df606f7aa04db))
* check for config file extensions at start ([7a41bb2](https://github.com/H3rmt/hyprswitch/commit/7a41bb2bf8abea7b2bc2efc2544deb26243faf7c))
* ci release ([4a0f45f](https://github.com/H3rmt/hyprswitch/commit/4a0f45f466d47a12e6cab70d2e71c835287287a0))
* close launcher on esc ([a003b82](https://github.com/H3rmt/hyprswitch/commit/a003b8227b709a7bb186e2b3703ec70f3f16dd7d))
* detect socat path at runtime ([312f667](https://github.com/H3rmt/hyprswitch/commit/312f6677165a023466a115d8a61f2927b31adc71))
* don't exit launcher when no items ([a4356b7](https://github.com/H3rmt/hyprswitch/commit/a4356b783c148f61736fcd9e4af23d63b1be7c85))
* don't unset all CSS styles at the start, only necessary ([b42d25c](https://github.com/H3rmt/hyprswitch/commit/b42d25c1d342d10a5af378e1ebcae167a83ca01f))
* filter apps in the launcher by name, exec and details ([ab0f23e](https://github.com/H3rmt/hyprswitch/commit/ab0f23e43c4ce540e14fe3f0ac515fa52ec56ab9))
* fix ci publish ([bb1e659](https://github.com/H3rmt/hyprswitch/commit/bb1e65987ac7c371b29cbf09000bb4f117f5b0e9))
* fix ci release ([e498ca1](https://github.com/H3rmt/hyprswitch/commit/e498ca19f86fcf2d4668fa7582f9320232fd194d))
* fix ci release ([6dc00c7](https://github.com/H3rmt/hyprswitch/commit/6dc00c719ef7beaea70c86f7851c6de8cdf9117e))
* fix focus window problem ([3c702a1](https://github.com/H3rmt/hyprswitch/commit/3c702a1da63d56168aa6e7ba2932842c55f97c8d))
* fix multiple run week caches not being added together ([c027209](https://github.com/H3rmt/hyprswitch/commit/c027209d6f01ec10210420182ea3283380f8e74f))
* Fix Nix Build ([02bd2c4](https://github.com/H3rmt/hyprswitch/commit/02bd2c400616cb96cd21ccc6b2f530143fcb511b))
* fix overflow for selecting workspaces ([9efadcd](https://github.com/H3rmt/hyprswitch/commit/9efadcdc37ae0c639ab36a1880e3d48b1b6c51a2))
* fix overview click on client or workspace ([71d445c](https://github.com/H3rmt/hyprswitch/commit/71d445c0f310f986b769eb420b55e21e9559d94d))
* fix panic when listening for changes on nonexisting file ([2e02509](https://github.com/H3rmt/hyprswitch/commit/2e025099b4b259844a6f5192a4e9db3db10a00ba))
* fix right alt bind ([4394240](https://github.com/H3rmt/hyprswitch/commit/43942408b0febe18026e278d2e4cffd7eece25db))
* fix slow start times ([0c4bb95](https://github.com/H3rmt/hyprswitch/commit/0c4bb9585806de61f73e885026083e49b2fe2048))
* fix switch mode monitor select ([b8c1d44](https://github.com/H3rmt/hyprswitch/commit/b8c1d440d47fe4a6ca2c1690e1b0be65b81de1df))
* fix versions ([899b2cc](https://github.com/H3rmt/hyprswitch/commit/899b2cc95018a342c2bf45d0fdf0ef971616be7b))
* fix versions ([e9565fd](https://github.com/H3rmt/hyprswitch/commit/e9565fd627c85ed4fa8fcf26cd35c06ceeaeb2b7))
* fix versions ([8d9a5ee](https://github.com/H3rmt/hyprswitch/commit/8d9a5eeeee5d74fef9501fec39c5d8692061ec97))
* fix versions ([05f3da6](https://github.com/H3rmt/hyprswitch/commit/05f3da60197e59d6a882fa0282127ae62091f879))
* fix versions ([b4e0380](https://github.com/H3rmt/hyprswitch/commit/b4e0380cced9b3ae35e3d8368fb336edc5530274))
* fix versions ([14e4a72](https://github.com/H3rmt/hyprswitch/commit/14e4a725dfe6b0d70c235db80069238338ec2890))
* fix versions ([89711a6](https://github.com/H3rmt/hyprswitch/commit/89711a628c45d6286742ac274ad4ec2fe487faed))
* fix wrong name in hm module ([99386d5](https://github.com/H3rmt/hyprswitch/commit/99386d56c0e40e65bc491e2b87cf28ef83305f6d))
* force command now accepts args ([7a41bb2](https://github.com/H3rmt/hyprswitch/commit/7a41bb2bf8abea7b2bc2efc2544deb26243faf7c))
* get socat path at buildtime ([a4356b7](https://github.com/H3rmt/hyprswitch/commit/a4356b783c148f61736fcd9e4af23d63b1be7c85))
* make css optional ([b0c36ee](https://github.com/H3rmt/hyprswitch/commit/b0c36eeb3f9dfbe9a85933505dc618cd0c231308))
* move scripts ([97329b7](https://github.com/H3rmt/hyprswitch/commit/97329b723d4c90e674fa74d65fb4397252266b85))
* moved size_factor to scale for a more sensible default and bounds check ([a85f3b8](https://github.com/H3rmt/hyprswitch/commit/a85f3b8948211711acf232b9834f4c9c2afadf61))
* nix allow source and text attributes ([dcd9e41](https://github.com/H3rmt/hyprswitch/commit/dcd9e417071e80cfd489eaefc8908a6b12a324eb))
* nix json config fixes ([ced4a45](https://github.com/H3rmt/hyprswitch/commit/ced4a45ef6b8361663b30062298f3084f2219a37))
* **nix:** Fix HM Module ([b8367b4](https://github.com/H3rmt/hyprswitch/commit/b8367b4de9dcd2a5b6e49a3e9322534657de4886))
* open windows earlier ([b42d25c](https://github.com/H3rmt/hyprswitch/commit/b42d25c1d342d10a5af378e1ebcae167a83ca01f))
* reload desktop maps on close ([204358d](https://github.com/H3rmt/hyprswitch/commit/204358dc20ad49ff44d79444f707d20a4535d0da))
* remove size_factor from config ([77b53bd](https://github.com/H3rmt/hyprswitch/commit/77b53bd205d32c0619d244a601cea8304f4a4b9c))
* remove socat dependency ([01758a6](https://github.com/H3rmt/hyprswitch/commit/01758a6d6384c5ad73a841c3f2e8b90ee9912393))
* search for installed terminals from PATH ([453888e](https://github.com/H3rmt/hyprswitch/commit/453888e61551946cfa3dec92409df606f7aa04db))
* show recent windows on one screen only ([f6a3016](https://github.com/H3rmt/hyprswitch/commit/f6a301689827ebb27afc10d445715c070a5762f1))
* some focus fixes ([9fa8009](https://github.com/H3rmt/hyprswitch/commit/9fa80093f943f6941aeaeb424a262cb3b4c40ec6))
* sort launcher applications by shorted exec instead of full (removed /bin/flatpak...) ([b17a393](https://github.com/H3rmt/hyprswitch/commit/b17a393b04201beab8b582a340d1bb80bef5cda2))
* speedup animation ([179ca7b](https://github.com/H3rmt/hyprswitch/commit/179ca7b45e865875584a4c658a0455ea00af0bc6))
* switch window if no results are present in launcher ([50a81a0](https://github.com/H3rmt/hyprswitch/commit/50a81a0503f8f259374fdafab73e383f930902fe))
* try all config extensions if file missing ([6cd4799](https://github.com/H3rmt/hyprswitch/commit/6cd4799198c7b170537135a611c8ed88b97aa62f))
* try to fix publication to creates.io ([c911a07](https://github.com/H3rmt/hyprswitch/commit/c911a078e40655fd869df317479a6a93cce508b2))
* update documentation ([229921d](https://github.com/H3rmt/hyprswitch/commit/229921d82167d59670cdeab488677b372ecafe73))
* Update Nix Package ([a147d38](https://github.com/H3rmt/hyprswitch/commit/a147d385ee5928e0616d232f741657069242272f))
* use char instead of String for key for websearch plugins ([eba4282](https://github.com/H3rmt/hyprswitch/commit/eba42823569cbf19dcb35cf37cc78db7bcdb0e3b))
### Documentation
* fix css explain images ([d86d566](https://github.com/H3rmt/hyprswitch/commit/d86d5667201031915100391c1eeb9571e763f370))
### Continuous Integration
* fix ci release ([a24657b](https://github.com/H3rmt/hyprswitch/commit/a24657bb9e237e69ff2f8687577114c25de921fe))
* fix ci release ([e02df4a](https://github.com/H3rmt/hyprswitch/commit/e02df4a193718664762ba8d7e22c63814f061de3))
* fix ci release ([d8d481d](https://github.com/H3rmt/hyprswitch/commit/d8d481d672809a4f8907a156eed1705caa27a9aa))
* fix release-please again ([824bf03](https://github.com/H3rmt/hyprswitch/commit/824bf032ab3b131121b16d9c16ce9f6a5215c580))
* fix release-please again ([bce2335](https://github.com/H3rmt/hyprswitch/commit/bce23355cd3f477e95179acadd5d1401544b1822))
* fix releases ([06ad9fc](https://github.com/H3rmt/hyprswitch/commit/06ad9fc8cc85a4a6fe3584510bce0efbd1aa1425))
* switch CI back to normal repo ([9aec89c](https://github.com/H3rmt/hyprswitch/commit/9aec89c4705d1c9683d30274aa442512e3665493))
================================================
FILE: Cargo.toml
================================================
[workspace]
members = ["crates/exec-lib", "crates/core-lib", "crates/windows-lib", "crates/launcher-lib", "crates/config-lib", "crates/hyprland-plugin", "crates/clipboard-lib", "dep-crates/hyprland-rs", "dep-crates/hyprland-rs/hyprland-macros", "dep-crates/wl-clipboard-rs", "crates/config-edit-lib"]
[workspace.package]
version = "4.9.5"
description = "A modern GTK4-based window switcher and application launcher for Hyprland"
license = "MIT"
authors = ["h3rmt"]
keywords = ["hyprland"]
repository = "https://github.com/h3rmt/hyprshell/"
# update when nixpkgs has a newer rustc
rust-version = "1.91.0"
edition = "2024"
[workspace.dependencies]
anyhow = { version = "1.0.100" }
tracing = { version = "0.1.44" }
serde_json = { version = "1.0.148" }
serde = { version = "1.0.228", features = ["derive"] }
async-channel = { version = "2.5.0", default-features = true }
semver = { version = "1.0.27" }
test-log = { version = "0.2.19", default-features = false, features = ["trace", "unstable"] }
relm4 = { version = "0.10.0", default-features = false, features = ["libadwaita", "macros", "gnome_48"] }
relm4-components = "0.10.0"
gtk4-layer-shell = { version = "0.7.1" }
config-lib = { path = "crates/config-lib", package = "hyprshell-config-lib", version = "=4.9.5" }
core-lib = { path = "crates/core-lib", package = "hyprshell-core-lib", version = "=4.9.5" }
exec-lib = { path = "crates/exec-lib", package = "hyprshell-exec-lib", version = "=4.9.5" }
hyprland-plugin = { path = "crates/hyprland-plugin", package = "hyprshell-hyprland-plugin", version = "=4.9.5" }
[package]
name = "hyprshell"
readme = "README.md"
categories = []
documentation = "https://docs.rs/hyprshell"
version = "4.9.5"
edition.workspace = true
description.workspace = true
license.workspace = true
authors.workspace = true
keywords.workspace = true
repository.workspace = true
rust-version.workspace = true
exclude = [".idea/*", ".github/*"]
[dependencies]
anyhow.workspace = true
tracing.workspace = true
relm4.workspace = true
async-channel.workspace = true
semver.workspace = true
clap = { version = "4.5.47", features = ["derive"] }
clap_complete = "4.5.57"
tracing-subscriber = { version = "0.3.20", features = ["fmt", "env-filter", "ansi"], default-features = false }
signal-hook = { version = "0.4.1" }
config-lib.workspace = true
core-lib.workspace = true
exec-lib.workspace = true
clipboard-lib = { path = "crates/clipboard-lib", package = "hyprshell-clipboard-lib", version = "=4.9.5" }
windows-lib = { path = "crates/windows-lib", package = "hyprshell-windows-lib", version = "=4.9.5" }
launcher-lib = { path = "crates/launcher-lib", package = "hyprshell-launcher-lib", version = "=4.9.5" }
config-edit-lib = { path = "crates/config-edit-lib", package = "hyprshell-config-edit-lib", version = "=4.9.5", optional = true }
[dev-dependencies]
test-log.workspace = true
[features]
default = ["json5_config", "gui_settings_editor", "launcher_calc", "debug_command", "clipboard_compress_lz4", "clipboard_compress_zstd", "clipboard_compress_brotli", "clipboard_encrypt_chacha20poly1305", "clipboard_encrypt_aes_gcm"]
slim = ["gui_settings_editor", "debug_command", "clipboard_compress_lz4"]
json5_config = ["config-lib/json5_config"]
gui_settings_editor = ["dep:config-edit-lib"]
launcher_calc = ["launcher-lib/calc", "config-lib/launcher_calc_plugin", "config-edit-lib?/launcher_calc_plugin"]
debug_command = []
ci_config_check = ["config-lib/ci_no_default_config_values"]
clipboard_compress_lz4 = ["clipboard-lib/compress_lz4"]
clipboard_compress_zstd = ["clipboard-lib/compress_zstd"]
clipboard_compress_brotli = ["clipboard-lib/compress_brotli"]
clipboard_encrypt_chacha20poly1305 = ["clipboard-lib/encrypt_chacha20poly1305"]
clipboard_encrypt_aes_gcm = ["clipboard-lib/encrypt_aes_gcm"]
[profile.release]
strip = "debuginfo"
lto = true
opt-level = 3
[lints]
workspace = true
[workspace.lints.clippy]
all = { level = "warn", priority = -1 }
pedantic = { level = "warn", priority = -1 }
nursery = { level = "warn", priority = -1 }
unwrap_used = "deny"
single_match = "allow"
match_wildcard_for_single_variants = "allow"
struct_excessive_bools = "allow"
missing_errors_doc = "allow"
cast_possible_truncation = "allow"
# This is broken
uninlined_format_args = "warn"
unnecessary_debug_formatting = "warn"
unnecessary_wraps = "warn"
pathbuf_init_then_push = "warn"
print_stdout = "warn"
print_stderr = "warn"
================================================
FILE: DEVELOPMENT.md
================================================
# Development Guide
Welcome to the Hyprshell development guide. This document provides information on how to set up your environment, the project structure, and common development tasks.
## Prerequisites
To develop for Hyprshell, you need to have the following installed:
- **Rust**: Latest stable version (minimum `1.92.0`).
- **GTK4 & Libadwaita**: Development headers for GTK4 and Libadwaita.
- **GTK4 Layer Shell**: Development headers for [gtk4-layer-shell](https://github.com/wmww/gtk4-layer-shell).
- **Hyprland**: Minimum version `0.52.1`. Development headers (`hyprland-devel`) are needed for the plugin.
- **just**: A handy command runner used for various development tasks.
### Installing `just`
We use [just](https://github.com/casey/just) to automate common tasks. You can install it using your package manager:
- **Arch Linux**: `sudo pacman -S just`
- **Fedora**: `sudo dnf install just`
- **Nix**: `nix-shell -p just` or add it to your flake.
- **Cargo**: `cargo install just`
## Project Structure
Hyprshell is organized as a Rust workspace with multiple crates and some vendored dependencies.
### Directories
- `crates/`: Contains the internal libraries that make up Hyprshell.
- `core-lib`: Fundamental types and utilities.
- `config-lib`: Configuration loading, generation, and migration.
- `config-edit-lib`: The GUI settings editor.
- `exec-lib`: Hyprland specific logic and plugin management.
- `launcher-lib`: Logic for the application launcher.
- `windows-lib`: Logic for the window switcher.
- `clipboard-lib`: Clipboard management and history.
- `hyprland-plugin`: A C++ Hyprland plugin used to capture keyboard events.
- `dep-crates/`: Contains forks or local versions of external dependencies.
- `hyprland-rs`: A fork of the Hyprland IPC library.
- `wl-clipboard-rs`: A fork of the Wayland clipboard library.
- `src/`: Contains the main entry point for the `hyprshell` binary.
- `scripts/`: Various helper scripts for CI and development.
- `nix/`: Nix-related files for building and development shells.
- `docs/`: Documentation files.
- `packaging/`: Files for packaging Hyprshell.
## Common Tasks
We use `just` to run common development tasks. Run `just` without arguments to see a full list of available commands.
### Development
- `just run`: Run the application in debug mode (prints available commands).
- `just run release`: Run the application in release mode.
- `just run-run`: Run the application process in debug mode.
### Environment Variables
Useful environment variables for development:
- `HYPRSHELL_EXPERIMENTAL=1`: Enables experimental features.
- `HYPRSHELL_LOG_MODULE_PATH=1`: Adds module path to logs (use with `-vv`).
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2025 Enrico Stemmer
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# Hyprshell
[](https://crates.io/crates/hyprshell) [](https://docs.rs/hyprshell)

## Overview
Hyprshell _(previously hyprswitch)_ is a Rust-based GUI designed to enhance window management in [Hyprland](https://github.com/hyprwm/Hyprland).
It provides a powerful and customizable interface for switching between windows using keyboard shortcuts and GUI.
The application also includes a launcher for running applications, doing calculations, etc.
## Features
- **Window Switching**: Switch between windows using keyboard shortcuts in a GUI.
- **Customizable Keybindings**: Define your own keybindings for window switching and GUI interactions.
- **Config**: Interactive [config file](docs/CONFIGURE.md) generation for easy setup.
- **Launcher Integration**: Launch applications directly from the GUI, sorted by usage frequency.
- **Launcher Plugins**: Different plugins like Web search, actions or calculations can be enabled.
- **Theming**: Customize the GUI appearance (gtk4) using [CSS](docs/CONFIGURE.md).
- **Settings App**: Customize the application using a settings app.
- **Dynamic Configuration**: Automatically reloads configuration/style changes without restarting the application.
- **Debug commands**: Many [Commands](docs/DEBUG.md) to debug desktop files, icons and default applications.
## Installation
**Minimum hyprland version: 0.52.1**
[](https://repology.org/project/hyprshell/versions)
### Arch Linux (AUR)
```bash
paru -S hyprshell
# or
yay -S hyprshell
```
Use `hyprshell-bin` for the pre-built binaries from GitHub releases.
Use `hyprshell-slim` for the [slim](#feature-flags) version (faster buildtime).
### Binary pre-built packages (only for x86_64 and aarch64)
Download and extract from the latest release on the [releases](https://github.com/h3rmt/hyprshell/releases) page.
### NixOS
This repository contains a `flake` and with a type-save `home-manager` module for configuration.
Hyprshell is also available in `nixpkgs` repository and can be configured using a generic `home-manager` module.
More information can be found in the [NixOS](docs/NIX.md) section.
### From Source
hyprland, gtk4[v4_18], libadwaita[v1_8] and [gtk4-layer-shell](https://github.com/wmww/gtk4-layer-shell)[1.1.1] must be installed
```bash
cargo install hyprshell
```
Build with less features in [slim](#feature-flags) mode
```bash
cargo install hyprshell --no-default-features --features "slim"
```
**hyprland-devel is needed for the hyprland headers (needed to build hyprland plugin)**
Fedora: `sudo dnf install gtk4-layer-shell-devel libadwaita-devel hyprland-devel`
Arch: `sudo pacman -Sy gtk4-layer-shell libadwaita hyprland`
Minimum required rustc version: `1.92.0`
## Usage
Run `hyprshell --help` to see available commands and options.
### Config
To generate a default configuration file, run:
```bash
hyprshell config generate
```
This launches an interactive prompt to set up your configuration.
The generated file will be located at `~/.config/hyprshell/config.ron`.
If you want to modify these settings, look at the [Documentation](docs/CONFIGURE.md) for the config file.
To validate your configuration file, run:
```bash
hyprshell config explain
```
This checks for any syntax errors or issues in your configuration file and shows a `explanation` of how to use hyprshell.
To edit the configuration file run `hyprshell config edit`. This launches the settings editor.
### Initialization
Enable the systemd service (generated with `hyprshell config generate`) [recommended]:
```bash
systemctl --user enable --now hyprshell.service
```
Or add the following to your Hyprland configuration (`~/.config/hypr/hyprland.conf`):
```ini
exec-once = hyprshell run &
```


### Debugging
Debug commands are provided to help troubleshoot desktop files, icons, default applications and launcher functionality, see [Debug.md](docs/DEBUG.md) for detailed information about available commands and their usage.
### Feature Flags
✅ = included in the default feature set.
✨ = included in the slim feature set. (build with ``--no-default-features --features "slim"``)
- `gui_settings_editor`✅✨: Adds the `hyprshell config edit` command to open the settings editor.
- `json5_config`✅: Adds support for a json5 config file.
- `launcher_calc`✅: Adds support for the calc plugin in the launcher.
- `debug_command`✅✨: Adds the `hyprshell debug` command to debug icons, desktop files, etc.
- `clipboard_compress_lz4`✅✨: Adds support for compressing clipboard content using lz4.
- `clipboard_compress_brotli`✅: Adds support for compressing clipboard content using brotli.
- `clipboard_compress_zstd`✅: Adds support for compressing clipboard content using zstd.
- `clipboard_encrypt_chacha20poly1305`✅: Adds support for encrypting clipboard content using chacha20poly1305.
- `clipboard_encrypt_aes_gcm`✅: Adds support for encrypting clipboard content using aes_256_gcm.
- `ci_config_check`: (!used for ci tests) Adds a command to check if the loaded config is equal to the default config or the full config. Also diables loading of configs without all values.
### Env Variables
- `HYPRSHELL_NO_LISTENERS`: Disable all config listeners (config file, css file, hyprland config, monitor count)
- `HYPRSHELL_NO_ALL_ICONS`: Don't check for all icons on fs and just use the ones provided by the `gtk4` icon theme.
- `HYPRSHELL_RELOAD_TIMEOUT`: Set the timeout for reloading the config file in milliseconds (default: `1500`).
- `HYPRSHELL_LOG_MODULE_PATH`: Add the module path to each log message. (use with -vv)
- `HYPRSHELL_NO_USE_PLUGIN`: Disable the use of the hyprland plugin to capture switch mode events.
- `HYPRSHELL_EXPERIMENTAL`: Enables experimental features (grep through the source code for `"HYPRSHELL_EXPERIMENTAL"` to see them)
- `HYPRSHELL_RUN_ACTIONS_IN_DEBUG`: Run actions from launcher plugin in debug mode
================================================
FILE: crates/clipboard-lib/Cargo.toml
================================================
[package]
name = "hyprshell-clipboard-lib"
documentation = "https://docs.rs/hyprshell-clipboard-lib"
version = "4.9.5"
description = "A library monitoring and storing clipboard contents"
edition.workspace = true
license.workspace = true
authors.workspace = true
keywords.workspace = true
repository.workspace = true
rust-version.workspace = true
[dependencies]
anyhow.workspace = true
tracing.workspace = true
core-lib.workspace = true
wl_clipboard = { package = "hyprshell-wl-clipboard-rs", path = "../../dep-crates/wl-clipboard-rs", version = "=4.9.5" }
fast_image_resize = { version = "5.3.0", features = ["image"] }
bitcode = { version = "0.6.9" }
image = { version = "0.25.8", features = ["png", "jpeg", "webp", "gif"], default-features = false }
lz4_flex = { version = "0.12.0", optional = true }
zstd = { version = "0.13.3", optional = true }
brotli = { version = "8.0.2", optional = true }
secret-service = { version = "5.0.0", features = ["rt-tokio-crypto-rust"], default-features = false, optional = true }
chacha20poly1305 = { version = "0.11.0-rc.2", optional = true }
aes-gcm = { version = "0.11.0-rc.2", optional = true }
crypto-common = { version = "0.2.0-rc.9", optional = true }
[features]
compress_lz4 = ["dep:lz4_flex"]
compress_zstd = ["dep:zstd"]
compress_brotli = ["dep:brotli"]
encrypt_chacha20poly1305 = ["dep:chacha20poly1305", "dep:secret-service", "dep:crypto-common"]
encrypt_aes_gcm = ["dep:aes-gcm", "dep:secret-service", "dep:crypto-common"]
[lints]
workspace = true
================================================
FILE: crates/clipboard-lib/src/config/mod.rs
================================================
#![allow(dead_code)]
#[derive(Debug, Clone)]
pub struct Config {
pub encryption: Encryption,
pub compression: Compression,
pub image_conv_filter: ConvolutionFilterType,
}
#[derive(Debug, Copy, Clone, Default)]
pub enum Encryption {
#[default]
None,
#[cfg(feature = "encrypt_chacha20poly1305")]
ChaCha20Poly1305,
#[cfg(feature = "encrypt_aes_gcm")]
AesGcm,
}
#[derive(Debug, Copy, Clone, Default)]
pub enum Compression {
#[default]
None,
#[cfg(feature = "compress_lz4")]
Lz4,
#[cfg(feature = "compress_zstd")]
Zstd(u8),
#[cfg(feature = "compress_brotli")]
Brotli(u8),
}
#[derive(Debug, Copy, Clone, Default)]
pub enum ConvolutionFilterType {
Box,
Bilinear,
Hamming,
CatmullRom,
Mitchell,
Gaussian,
#[default]
Lanczos3,
}
impl From for fast_image_resize::FilterType {
fn from(value: ConvolutionFilterType) -> Self {
match value {
ConvolutionFilterType::Box => Self::Box,
ConvolutionFilterType::Bilinear => Self::Bilinear,
ConvolutionFilterType::Hamming => Self::Hamming,
ConvolutionFilterType::CatmullRom => Self::CatmullRom,
ConvolutionFilterType::Mitchell => Self::Mitchell,
ConvolutionFilterType::Gaussian => Self::Gaussian,
ConvolutionFilterType::Lanczos3 => Self::Lanczos3,
}
}
}
================================================
FILE: crates/clipboard-lib/src/lib.rs
================================================
mod config;
pub mod store;
pub(crate) mod util;
================================================
FILE: crates/clipboard-lib/src/store/listen.rs
================================================
use crate::config::{Compression, Config, ConvolutionFilterType, Encryption};
use crate::store::mime::{filer_mimes, get_preferred_mime};
use crate::store::save_image::compress_and_store_image;
use crate::store::save_map::compress_and_store_map;
use crate::store::save_text::store_text;
use core_lib::WarnWithDetails;
use std::any::Any;
use std::collections::HashMap;
use std::path::PathBuf;
use std::sync::{Arc, RwLock};
use std::thread;
use tracing::{debug, warn};
use wl_clipboard::paste::{CallbackData, Seat, get_all_contents_callback};
/// # Panics
pub fn test_clipboard(_data_dir: PathBuf, cache_dir: PathBuf) {
debug!("Starting clipboard listener");
let cl_config = Arc::new(RwLock::new(conf()));
let config_clone = cl_config.clone();
let _ = cl_config.type_id();
let handle_values = move |val: CallbackData| -> bool {
let (mut mimes, load) = match val {
Ok(r) => r,
Err(err) => {
warn!("Failed to get clipboard contents: {err:?}");
return false;
}
};
let config = {
let Ok(config) = config_clone.read() else {
return true; // lock poisoned, aboard clipboard listener
};
config.clone()
};
filer_mimes(&mut mimes);
let Some(pref_mime) = get_preferred_mime(&mimes) else {
warn!("No preferred MIME type found, available: {mimes:?}");
return false;
};
// load data for all mime types
let mut data = HashMap::new();
for mime in &mimes {
data.insert(
mime.clone(),
load(mime.clone()).expect("mime type despawned while loading clipboard data"),
);
}
if pref_mime.starts_with("image/") {
let pref_data = data
.get(&pref_mime)
.expect("Preferred MIME type not found")
.clone();
let cache_dir_clone = cache_dir.clone();
let config_clone = config.clone();
thread::spawn(move || {
compress_and_store_image(pref_data, &config_clone, &cache_dir_clone)
.warn_details("Failed to store clipboard image")
});
} else {
let pref_data = data.get(&pref_mime).expect("Preferred MIME type not found");
let text = String::from_utf8_lossy(pref_data);
store_text(&text, &config, &cache_dir).warn_details("Failed to store clipboard text");
}
let cache_dir_clone = cache_dir.clone();
thread::spawn(move || compress_and_store_map(data, &config, &cache_dir_clone));
false
};
let _ = get_all_contents_callback(Seat::Unspecified, Box::new(handle_values))
.expect("Failed to start clipboard listener")
.join();
warn!("Clipboard listener stopped");
}
fn conf() -> Config {
let mut config = Config {
encryption: Encryption::default(),
compression: Compression::default(),
image_conv_filter: ConvolutionFilterType::Lanczos3,
};
config.encryption = Encryption::default();
config.compression = Compression::default();
#[cfg(feature = "compress_brotli")]
{
config.compression = Compression::Brotli(6);
}
#[cfg(feature = "compress_zstd")]
{
config.compression = Compression::Zstd(16);
}
#[cfg(feature = "encrypt_aes_gcm")]
{
config.encryption = Encryption::AesGcm;
}
#[cfg(feature = "compress_lz4")]
{
config.compression = Compression::Lz4;
}
#[cfg(feature = "encrypt_chacha20poly1305")]
{
config.encryption = Encryption::ChaCha20Poly1305;
}
config
}
================================================
FILE: crates/clipboard-lib/src/store/mime.rs
================================================
use std::collections::HashSet;
use tracing::trace;
static MIME_TYPES_PRIO: &[&str] = &[
"image/png",
"image/jpg",
"image/jpeg",
"image/webp",
"image/gif",
"text/plain;charset=utf-8",
"UTF8_STRING",
"STRING",
"TEXT",
"text/*",
];
static MIME_TYPES_IMAGES_PRIO: &[&str] = &[
"image/png",
"image/jpg",
"image/jpeg",
"image/webp",
"image/gif",
];
pub fn get_preferred_mime(mime_types: &HashSet) -> Option {
// Find by priority
for (index, mime) in MIME_TYPES_PRIO.iter().enumerate() {
if mime.ends_with("/*") {
let prefix = &mime[..mime.len() - 1];
if let Some(mt) = mime_types.iter().find(|x| x.starts_with(prefix)) {
trace!("Chosen MIME type: {mt:?} from prio({index}), by prefix {prefix}*");
return Some(mt.clone());
}
} else if let Some(mt) = mime_types.iter().find(|x| x == mime) {
trace!("Chosen MIME type: {mt:?} from prio({index}), by exact match {mime}");
return Some(mt.clone());
}
}
None
}
pub fn filer_mimes(mime_types: &mut HashSet) {
let count = mime_types.len();
// remove audio
mime_types.retain(|mt| !mt.starts_with("audio/"));
// Retain only one image/ MIME type.
let image_mime = MIME_TYPES_IMAGES_PRIO
.iter()
.find(|preferred| mime_types.contains(&(**preferred).to_string()))
.map(|&preferred| preferred.to_string())
.or_else(|| {
mime_types
.iter()
.find(|mt| mt.starts_with("image/"))
.cloned()
});
mime_types.retain(|mt| {
if mt.starts_with("image/") {
image_mime.as_ref() == Some(mt)
} else {
true
}
});
trace!(
"Available MIME types: {:?}, removed {} elements",
mime_types,
count - mime_types.len()
);
}
================================================
FILE: crates/clipboard-lib/src/store/mod.rs
================================================
mod listen;
mod mime;
mod save_image;
mod save_map;
mod save_text;
pub(crate) mod util;
mod write;
pub use listen::test_clipboard;
================================================
FILE: crates/clipboard-lib/src/store/save_image.rs
================================================
use crate::store::util::create_storage_path;
use anyhow::Context;
use image::{ImageEncoder, ImageReader};
use std::fs::File;
use std::io::{Cursor, Write};
use std::path::Path;
use tracing::trace;
use crate::config::Config;
use crate::store::write::get_storage_writer;
use fast_image_resize::images::Image;
use fast_image_resize::{IntoImageView, ResizeAlg, ResizeOptions, Resizer};
use image::codecs::png::PngEncoder;
const IMAGE_HEIGHT: u32 = 150;
pub fn compress_and_store_image(
pref_data: Vec,
config: &Config,
cache_dir: &Path,
) -> anyhow::Result<()> {
let now = std::time::SystemTime::now();
let img2 = ImageReader::new(Cursor::new(pref_data))
.with_guessed_format()?
.decode()?;
trace!(
"Loaded image in {:?}, Image size: {}x{}",
now.elapsed()?,
img2.width(),
img2.height()
);
let now = std::time::SystemTime::now();
#[allow(clippy::cast_sign_loss, clippy::cast_precision_loss)]
let mut dst_image = Image::new(
(img2.width() as f32 * (IMAGE_HEIGHT as f32 / img2.height() as f32)) as u32,
IMAGE_HEIGHT,
img2.pixel_type()
.context("Failed to get pixel type for clipboard image")?,
);
let mut resizer = Resizer::new();
resizer.resize(
&img2,
&mut dst_image,
&ResizeOptions::new().resize_alg(ResizeAlg::Convolution(config.image_conv_filter.into())),
)?;
trace!(
"Resized image size: {}x{} in {:?}",
dst_image.width(),
dst_image.height(),
now.elapsed()?
);
let mut cursor = Cursor::new(Vec::new());
{
let (mut write, _ext) = get_storage_writer(&mut cursor, config, false);
PngEncoder::new(&mut write).write_image(
dst_image.buffer(),
dst_image.width(),
dst_image.height(),
img2.color().into(),
)?;
}
let storage_path = create_storage_path(cache_dir, "images", "png")
.context("Failed to get storage path for clipboard image")?;
let mut file = File::create(&storage_path).context("Failed to create clipboard image file")?;
file.write_all(&cursor.into_inner())
.context("Failed to write clipboard data")?;
trace!(
"Wrote image to {:?} ({} bytes)",
storage_path.display(),
file.metadata().map(|m| m.len()).unwrap_or(0)
);
Ok(())
}
================================================
FILE: crates/clipboard-lib/src/store/save_map.rs
================================================
use crate::config::Config;
use crate::store::util::create_storage_path;
use crate::store::write::get_storage_writer;
use anyhow::Context;
use std::collections::HashMap;
use std::fs::File;
use std::io::{Cursor, Write};
use std::path::Path;
use std::time::SystemTime;
use tracing::{trace, warn};
#[derive(Debug, bitcode::Encode, bitcode::Decode)]
pub enum ClipboardDataType {
Alias(Box),
Data(Vec),
}
pub fn compress_and_store_map(data: HashMap>, config: &Config, cache_dir: &Path) {
let combined_size = data.values().map(Vec::len).sum::();
let (data, contains_image) = deduplicate_clipboard_entries(data, true);
let compressed_combined_size = data
.values()
.filter_map(|dt| {
if let ClipboardDataType::Data(d) = dt {
Some(d.len())
} else {
None
}
})
.sum::();
trace!(
"Combined size: {} bytes, compressed size {} bytes, storing {} aliased and {} data entries",
combined_size,
compressed_combined_size,
data.values()
.filter(|dt| matches!(dt, ClipboardDataType::Alias(_)))
.count(),
data.values()
.filter(|dt| matches!(dt, ClipboardDataType::Data(_)))
.count()
);
// dont compress if contains image
if let Err(err) = store_map(&data, config, !contains_image, cache_dir) {
warn!("Failed to store clipboard data: {err}");
}
}
fn store_map(
data: &HashMap, ClipboardDataType>,
config: &Config,
compress: bool,
cache_dir: &Path,
) -> anyhow::Result<()> {
let now = SystemTime::now();
let mut cursor = Cursor::new(Vec::new());
let ext = {
let (mut writer, ext) = get_storage_writer(&mut cursor, config, compress);
let encoded = bitcode::encode(data);
writer
.write_all(&encoded)
.context("Failed to write encoded clipboard data")?;
ext
};
let storage_path = create_storage_path(cache_dir, "data", &format!("bin.{ext}"))
.context("Failed to get storage path for clipboard data")?;
let mut file = File::create(&storage_path).context("Failed to create clipboard data file")?;
file.write_all(&cursor.into_inner())
.context("Failed to write clipboard data")?;
trace!(
"Wrote clipboard data to {} ({} bytes) in {:?}",
storage_path.display(),
file.metadata().map(|m| m.len()).unwrap_or(0),
now.elapsed()?
);
Ok(())
}
pub fn deduplicate_clipboard_entries(
data: HashMap>,
dedup: bool,
) -> (HashMap, ClipboardDataType>, bool) {
let time = std::time::Instant::now();
let mut image_found = false;
let mut dedupted = 0u16;
let mut map: HashMap, ClipboardDataType> = HashMap::new();
'outer: for (mime, data) in data {
if mime.starts_with("image/") {
image_found = true;
}
if dedup {
for (f_mime, f_dt) in map.iter().filter(|(m, _)| !m.starts_with("image/")) {
if let ClipboardDataType::Data(check_data) = f_dt
&& data.eq(check_data)
{
trace!("Deduped MIME type {mime} to {f_mime}");
map.insert(
mime.into_boxed_str(),
ClipboardDataType::Alias(f_mime.clone()),
);
dedupted += 1;
continue 'outer;
}
}
}
map.insert(mime.into_boxed_str(), ClipboardDataType::Data(data));
}
trace!(
"Deduplication took {:?}, dedupted {dedupted} entries",
time.elapsed()
);
(map, image_found)
}
================================================
FILE: crates/clipboard-lib/src/store/save_text.rs
================================================
use crate::config::Config;
use crate::store::util::create_storage_path;
use crate::store::write::get_storage_writer;
use anyhow::Context;
use std::fs::File;
use std::io::{Cursor, Write};
use std::path::Path;
use tracing::trace;
pub fn store_text(text: &str, config: &Config, cache_dir: &Path) -> anyhow::Result<()> {
let compress = text.len() > 100;
let mut cursor = Cursor::new(Vec::new());
let ext = {
let (mut write, ext) = get_storage_writer(&mut cursor, config, compress);
write
.write_all(text.as_bytes())
.context("Failed to write text to clipboard")?;
ext
};
let storage_path = create_storage_path(cache_dir, "text", &format!("txt.{ext}"))
.context("Failed to get storage path for clipboard data")?;
let mut file = File::create(&storage_path).context("Failed to create clipboard data file")?;
file.write_all(&cursor.into_inner())
.context("Failed to write clipboard data")?;
trace!(
"Wrote text to {} ({} bytes)",
storage_path.display(),
file.metadata().map(|m| m.len()).unwrap_or(0)
);
Ok(())
}
================================================
FILE: crates/clipboard-lib/src/store/util.rs
================================================
use anyhow::Context;
use core_lib::util::get_boot_id;
use std::fs;
use std::path::{Path, PathBuf};
use std::time::{SystemTime, UNIX_EPOCH};
/// # Panics if time went backwards or no `boot_id` is available
pub fn create_storage_path(cache_dir: &Path, path: &str, ext: &str) -> anyhow::Result {
let now_millis = SystemTime::now()
.duration_since(UNIX_EPOCH)
.context("Time went backwards?")?
.as_millis();
let get_boot_id = get_boot_id().clone().context("Failed to get boot_id")?;
let path = cache_dir
.to_path_buf()
.join("clipboard")
.join(path)
.join(get_boot_id);
fs::create_dir_all(&path).context("Failed to create storage directory")?;
Ok(path.join(format!("{now_millis}.{ext}")))
}
================================================
FILE: crates/clipboard-lib/src/store/write.rs
================================================
use crate::config::{Compression, Config, Encryption};
use std::io::Write;
pub fn get_storage_writer<'a, I: Write + 'a>(
writer: I,
config: &Config,
compress: bool,
) -> (Box, &'static str) {
let base: Box = match config.encryption {
Encryption::None => Box::new(writer),
#[cfg(any(feature = "encrypt_chacha20poly1305", feature = "encrypt_aes_gcm"))]
_ => {
let config_val = match config.encryption {
#[cfg(feature = "encrypt_chacha20poly1305")]
Encryption::ChaCha20Poly1305 => crate::util::crypt::Config::ChaCha20Poly1305,
#[cfg(feature = "encrypt_aes_gcm")]
Encryption::AesGcm => crate::util::crypt::Config::AesGcm,
_ => unreachable!(),
};
match crate::util::secret_service::get_hyprshell_key() {
Ok(key) => Box::new(crate::util::crypt::SecretEncryptWriter::new(
writer, key, config_val,
)),
Err(err) => {
tracing::warn!("Failed to load/generate new encryption key: {err:?}");
Box::new(writer)
}
}
}
};
match (compress, config.compression) {
(false, _) | (true, Compression::None) => (base, "raw"),
#[cfg(feature = "compress_lz4")]
(true, Compression::Lz4) => (
Box::new(crate::util::lz4_compressor::LZ4CompressWriter::new(base)),
"lz4",
),
#[cfg(feature = "compress_brotli")]
(true, Compression::Brotli(level)) => (
Box::new(crate::util::brotli_compressor::BrotliCompressWriter::new(
base, level,
)),
"br",
),
#[cfg(feature = "compress_zstd")]
(true, Compression::Zstd(level)) => (
Box::new(crate::util::zstd_compressor::ZstdCompressWriter::new(
base, level,
)),
"zstd",
),
}
}
================================================
FILE: crates/clipboard-lib/src/util/brotli_compressor.rs
================================================
use brotli::CompressorWriter;
use brotli::enc::BrotliEncoderParams;
use std::io::Write;
use tracing::warn;
pub struct BrotliCompressWriter {
encoder: CompressorWriter,
}
impl BrotliCompressWriter {
pub fn new(writer: W, mut level: u8) -> Self {
// use 6 as default compression level
if level > 11 {
warn!("Brotli compression level out of range, clamping to 11");
level = 11;
}
let params = BrotliEncoderParams::default();
Self {
#[allow(clippy::cast_sign_loss)]
encoder: CompressorWriter::new(writer, 4096, u32::from(level), params.lgwin as u32),
}
}
}
impl Write for BrotliCompressWriter {
fn write(&mut self, buf: &[u8]) -> std::io::Result {
self.encoder.write(buf)
}
fn flush(&mut self) -> std::io::Result<()> {
self.encoder.flush()
}
}
================================================
FILE: crates/clipboard-lib/src/util/crypt.rs
================================================
use anyhow::Context;
use crypto_common::Generate;
use std::io::Write;
use tracing::trace;
#[cfg(feature = "encrypt_chacha20poly1305")]
type K = chacha20poly1305::Key;
#[cfg(all(not(feature = "encrypt_chacha20poly1305"), feature = "encrypt_aes_gcm"))]
type K = aes_gcm::Key;
pub fn generate_new_key() -> anyhow::Result> {
K::try_generate()
.map_err(|_| anyhow::anyhow!("Failed to generate new encryption key"))
.map(|k| k.to_vec())
}
pub struct SecretEncryptWriter {
key: Vec,
buffer: Vec,
writer: W,
config: Config,
}
pub enum Config {
#[cfg(feature = "encrypt_chacha20poly1305")]
ChaCha20Poly1305,
#[cfg(feature = "encrypt_aes_gcm")]
AesGcm,
}
impl SecretEncryptWriter {
pub const fn new(writer: W, key: Vec, config: Config) -> Self {
Self {
buffer: Vec::new(),
key,
writer,
config,
}
}
pub fn encrypt(&self, cleartext: &[u8]) -> anyhow::Result> {
trace!("length of cleartext: {}", cleartext.len());
match self.config {
#[cfg(feature = "encrypt_chacha20poly1305")]
Config::ChaCha20Poly1305 => {
use chacha20poly1305::{KeyInit, aead::Aead};
let nonce = chacha20poly1305::Nonce::try_generate()
.map_err(|_| anyhow::anyhow!("Failed to generate nonce"))?;
let cypher = chacha20poly1305::ChaCha20Poly1305::new_from_slice(&self.key)
.context("Failed to generate cypher with encryption key")?;
let obsf = cypher
.encrypt(&nonce, cleartext)
.context("Encryption failed")?;
let mut nonce = nonce.to_vec();
nonce.extend_from_slice(&obsf);
Ok(nonce)
}
#[cfg(feature = "encrypt_aes_gcm")]
Config::AesGcm => {
use aes_gcm::{KeyInit, aead::Aead};
let nonce = aes_gcm::Nonce::try_generate()
.map_err(|_| anyhow::anyhow!("Failed to generate nonce"))?;
let cypher = aes_gcm::Aes256Gcm::new_from_slice(&self.key)
.context("Failed to generate cypher with encryption key")?;
let obsf = cypher
.encrypt(&nonce, cleartext)
.context("Encryption failed")?;
let mut nonce = nonce.to_vec();
nonce.extend_from_slice(&obsf);
Ok(nonce)
}
}
}
}
impl Write for SecretEncryptWriter {
fn write(&mut self, buf: &[u8]) -> std::io::Result {
self.buffer.extend_from_slice(buf);
Ok(buf.len())
}
fn flush(&mut self) -> std::io::Result<()> {
self.writer.flush()
}
}
impl Drop for SecretEncryptWriter {
fn drop(&mut self) {
if !self.buffer.is_empty() {
if let Ok(encrypted) = self.encrypt(&self.buffer) {
trace!("Writing {} bytes encrypted data to writer", encrypted.len());
let _ = self.writer.write_all(&encrypted);
}
self.buffer.clear();
}
let _ = self.writer.flush();
}
}
// pub fn decrypt(&self, obsf: &[u8]) -> anyhow::Result> {
// type NonceSize = ::NonceSize;
// let cipher = generate_cypher(&self.key).context("Failed to generate cipher")?;
// let (nonce_bytes, ciphertext) = obsf.split_at(NonceSize::to_usize());
// let nonce =
// Nonce::::try_from(nonce_bytes).context("Failed to parse nonce")?;
// let out = cipher
// .decrypt(&nonce, ciphertext)
// .context("Decryption failed")?;
// Ok(out)
// }
================================================
FILE: crates/clipboard-lib/src/util/lz4_compressor.rs
================================================
use lz4_flex::frame::FrameEncoder;
use std::io::Write;
use tracing::warn;
pub struct LZ4CompressWriter {
encoder: FrameEncoder,
}
impl LZ4CompressWriter {
pub fn new(writer: W) -> Self {
Self {
encoder: FrameEncoder::new(writer),
}
}
}
impl Write for LZ4CompressWriter {
fn write(&mut self, buf: &[u8]) -> std::io::Result {
self.encoder.write(buf)
}
fn flush(&mut self) -> std::io::Result<()> {
self.encoder.flush()
}
}
impl Drop for LZ4CompressWriter {
fn drop(&mut self) {
if let Err(err) = self.encoder.try_finish() {
warn!("Failed to finish compressor: {err:?}");
}
}
}
================================================
FILE: crates/clipboard-lib/src/util/mod.rs
================================================
#[cfg(feature = "compress_brotli")]
pub mod brotli_compressor;
#[cfg(any(feature = "encrypt_chacha20poly1305", feature = "encrypt_aes_gcm"))]
pub mod crypt;
#[cfg(feature = "compress_lz4")]
pub mod lz4_compressor;
#[cfg(any(feature = "encrypt_chacha20poly1305", feature = "encrypt_aes_gcm"))]
pub mod secret_service;
#[cfg(feature = "compress_zstd")]
pub mod zstd_compressor;
================================================
FILE: crates/clipboard-lib/src/util/secret_service.rs
================================================
use crate::util::crypt::generate_new_key;
use anyhow::Context;
use secret_service::EncryptionType;
use secret_service::blocking::SecretService;
use std::collections::HashMap;
use std::sync::OnceLock;
use tracing::warn;
fn get_secret_service() -> Option<&'static SecretService<'static>> {
static SERVICE: OnceLock