Compare commits

...

60 Commits

Author SHA1 Message Date
tottoto aeb06984b7
Resolve clap deprecated api (#518) 2 weeks ago
Takashi Kokubun a9b52ccda1 Version 0.10.1 2 weeks ago
Mikael Wistoft-Ibsen 8c7af8f3ea
X11: Handle WM_CLASS reply without terminating null-byte (#525)
Fixes #523
2 weeks ago
dependabot[bot] e6f8501710 Bump fork from 0.1.23 to 0.2.0
Bumps [fork](https://github.com/immortal/fork) from 0.1.23 to 0.2.0.
- [Commits](https://github.com/immortal/fork/compare/0.1.23...0.2.0)

---
updated-dependencies:
- dependency-name: fork
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
4 weeks ago
dependabot[bot] c0395e5b8f Bump evdev from 0.12.1 to 0.12.2
Bumps [evdev](https://github.com/cmr/evdev) from 0.12.1 to 0.12.2.
- [Changelog](https://github.com/emberian/evdev/blob/main/CHANGELOG.md)
- [Commits](https://github.com/cmr/evdev/commits)

---
updated-dependencies:
- dependency-name: evdev
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
4 weeks ago
dependabot[bot] 9f019c69d7 Bump toml from 0.8.13 to 0.8.15
Bumps [toml](https://github.com/toml-rs/toml) from 0.8.13 to 0.8.15.
- [Commits](https://github.com/toml-rs/toml/compare/toml-v0.8.13...toml-v0.8.15)

---
updated-dependencies:
- dependency-name: toml
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2 months ago
dependabot[bot] bf1466c1c8 Bump serde_json from 1.0.120 to 1.0.121
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.120 to 1.0.121.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.120...v1.0.121)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2 months ago
dependabot[bot] d1e24a92c6 Bump lazy_static from 1.4.0 to 1.5.0
Bumps [lazy_static](https://github.com/rust-lang-nursery/lazy-static.rs) from 1.4.0 to 1.5.0.
- [Release notes](https://github.com/rust-lang-nursery/lazy-static.rs/releases)
- [Commits](https://github.com/rust-lang-nursery/lazy-static.rs/compare/1.4.0...1.5.0)

---
updated-dependencies:
- dependency-name: lazy_static
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2 months ago
dependabot[bot] c302d7b5a1 Bump anyhow from 1.0.82 to 1.0.86
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.82 to 1.0.86.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.82...1.0.86)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
3 months ago
dependabot[bot] b9c34692da Bump regex from 1.10.4 to 1.10.5
Bumps [regex](https://github.com/rust-lang/regex) from 1.10.4 to 1.10.5.
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.10.4...1.10.5)

---
updated-dependencies:
- dependency-name: regex
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
3 months ago
dependabot[bot] f5ae9b0ec3 Bump serde_json from 1.0.117 to 1.0.120
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.117 to 1.0.120.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.117...v1.0.120)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
3 months ago
dependabot[bot] 0d96389256 Bump log from 0.4.21 to 0.4.22
Bumps [log](https://github.com/rust-lang/log) from 0.4.21 to 0.4.22.
- [Release notes](https://github.com/rust-lang/log/releases)
- [Changelog](https://github.com/rust-lang/log/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/log/compare/0.4.21...0.4.22)

---
updated-dependencies:
- dependency-name: log
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
3 months ago
dependabot[bot] aebbcc82ee Bump serde_json from 1.0.116 to 1.0.117
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.116 to 1.0.117.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.116...v1.0.117)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
4 months ago
dependabot[bot] 8c7eff3baa Bump serde from 1.0.200 to 1.0.203
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.200 to 1.0.203.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.200...v1.0.203)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
4 months ago
dependabot[bot] 931c484eba Bump toml from 0.8.12 to 0.8.13
Bumps [toml](https://github.com/toml-rs/toml) from 0.8.12 to 0.8.13.
- [Commits](https://github.com/toml-rs/toml/compare/toml-v0.8.12...toml-v0.8.13)

---
updated-dependencies:
- dependency-name: toml
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
4 months ago
dependabot[bot] b2330d39a6 Bump x11rb from 0.13.0 to 0.13.1
Bumps [x11rb](https://github.com/psychon/x11rb) from 0.13.0 to 0.13.1.
- [Changelog](https://github.com/psychon/x11rb/blob/master/doc/changelog.md)
- [Commits](https://github.com/psychon/x11rb/compare/v0.13.0...v0.13.1)

---
updated-dependencies:
- dependency-name: x11rb
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
4 months ago
Takashi Kokubun f42ec7bdb4 Add maintainers to README 4 months ago
Takashi Kokubun d1b17c4b99 Version 0.10.0 4 months ago
Takashi Kokubun b99d09107e
Drop sway and hypr clients (#479) 4 months ago
Takashi Kokubun 98bb9ee1b1 Version 0.9.0 4 months ago
κeen 1aaafb1cd1
enable wheel by default (#478) 4 months ago
Takashi Kokubun 823b749635 Update CHANGELOG 5 months ago
Chakib Benziane ac0f4aa3ee
better to send no key for skip event (#462)
I didn't think much about it on my first patch but when skip_key_event
is set the KEY_UNKNOWN is repeated. Better to send no key at all.
5 months ago
dependabot[bot] 69ac3b08d8 Bump serde from 1.0.197 to 1.0.200
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.197 to 1.0.200.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.197...v1.0.200)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
5 months ago
dependabot[bot] 2130d92f01 Bump serde_json from 1.0.115 to 1.0.116
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.115 to 1.0.116.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.115...v1.0.116)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
5 months ago
dependabot[bot] 1aa43d2398 Bump serde_with from 3.7.0 to 3.8.1
Bumps [serde_with](https://github.com/jonasbb/serde_with) from 3.7.0 to 3.8.1.
- [Release notes](https://github.com/jonasbb/serde_with/releases)
- [Commits](https://github.com/jonasbb/serde_with/compare/v3.7.0...v3.8.1)

---
updated-dependencies:
- dependency-name: serde_with
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
5 months ago
dependabot[bot] 755acd45a1 Bump anyhow from 1.0.81 to 1.0.82
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.81 to 1.0.82.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.81...1.0.82)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
5 months ago
Takashi Kokubun f39afb076b Revert the held/alone description back to a regular one 5 months ago
dependabot[bot] 3a693d26af Bump indoc from 2.0.4 to 2.0.5
Bumps [indoc](https://github.com/dtolnay/indoc) from 2.0.4 to 2.0.5.
- [Release notes](https://github.com/dtolnay/indoc/releases)
- [Commits](https://github.com/dtolnay/indoc/compare/2.0.4...2.0.5)

---
updated-dependencies:
- dependency-name: indoc
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
6 months ago
dependabot[bot] 4c485588e2 Bump regex from 1.10.3 to 1.10.4
Bumps [regex](https://github.com/rust-lang/regex) from 1.10.3 to 1.10.4.
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.10.3...1.10.4)

---
updated-dependencies:
- dependency-name: regex
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
6 months ago
dependabot[bot] 5fa4d475d3 Bump serde_json from 1.0.114 to 1.0.115
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.114 to 1.0.115.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.114...v1.0.115)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
6 months ago
dependabot[bot] 9f3c480760 Bump serde_yaml from 0.9.33 to 0.9.34+deprecated
Bumps [serde_yaml](https://github.com/dtolnay/serde-yaml) from 0.9.33 to 0.9.34+deprecated.
- [Release notes](https://github.com/dtolnay/serde-yaml/releases)
- [Commits](https://github.com/dtolnay/serde-yaml/compare/0.9.33...0.9.34)

---
updated-dependencies:
- dependency-name: serde_yaml
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
6 months ago
dependabot[bot] dca06838e1 Bump serde_with from 3.6.0 to 3.7.0
Bumps [serde_with](https://github.com/jonasbb/serde_with) from 3.6.0 to 3.7.0.
- [Release notes](https://github.com/jonasbb/serde_with/releases)
- [Commits](https://github.com/jonasbb/serde_with/compare/v3.6.0...v3.7.0)

---
updated-dependencies:
- dependency-name: serde_with
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
6 months ago
Takashi Kokubun 53a6d0553d Version 0.8.18 6 months ago
Takashi Kokubun 3ce9b7a89d Revert "Version 0.8.18"
This reverts commit 429133067e.
6 months ago
Takashi Kokubun 2f22c52b12 Split release and publish 6 months ago
Takashi Kokubun 429133067e Version 0.8.18 6 months ago
Takashi Kokubun b1640a39e6 The username has been changed to xremap 6 months ago
Takashi Kokubun 1c0f123efd Revert "Version 0.8.18"
This reverts commit 2697d66d4f.
6 months ago
Takashi Kokubun 2697d66d4f Version 0.8.18 6 months ago
Takashi Kokubun 3ed63efc10 Reorder release operations 6 months ago
Takashi Kokubun e283960fab Update GHR_VERSION 6 months ago
N4tus 9262ff47ed Version 0.8.17 6 months ago
N4tus e54fc8ac4a
KDE: Add support for window matching. (#448)
KDE: Add support for window matching.
6 months ago
Takashi Kokubun 9405ce0516 Add an entry to CHANGELOG 6 months ago
Takashi Kokubun fa6db2c6dd Version 0.8.16 6 months ago
jixiuf f6b10cebc0
Window matcher for modmap and keymap (wlroots client only) (#447) 6 months ago
N4tus 8dede9f0b1
Merge pull request #437 from N4tus/master
Handle new KWin-6 API for the kde-backend.
6 months ago
dependabot[bot] 347fc54ce4 Bump log from 0.4.20 to 0.4.21
Bumps [log](https://github.com/rust-lang/log) from 0.4.20 to 0.4.21.
- [Release notes](https://github.com/rust-lang/log/releases)
- [Changelog](https://github.com/rust-lang/log/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/log/compare/0.4.20...0.4.21)

---
updated-dependencies:
- dependency-name: log
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
6 months ago
dependabot[bot] 5d605234d1 Bump fork from 0.1.22 to 0.1.23
Bumps [fork](https://github.com/immortal/fork) from 0.1.22 to 0.1.23.
- [Commits](https://github.com/immortal/fork/compare/0.1.22...0.1.23)

---
updated-dependencies:
- dependency-name: fork
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
6 months ago
dependabot[bot] b40c3767c1 Bump serde_yaml from 0.9.31 to 0.9.33
Bumps [serde_yaml](https://github.com/dtolnay/serde-yaml) from 0.9.31 to 0.9.33.
- [Release notes](https://github.com/dtolnay/serde-yaml/releases)
- [Commits](https://github.com/dtolnay/serde-yaml/compare/0.9.31...0.9.33)

---
updated-dependencies:
- dependency-name: serde_yaml
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
6 months ago
dependabot[bot] f8dc468583 Bump toml from 0.8.9 to 0.8.12
Bumps [toml](https://github.com/toml-rs/toml) from 0.8.9 to 0.8.12.
- [Commits](https://github.com/toml-rs/toml/compare/toml-v0.8.9...toml-v0.8.12)

---
updated-dependencies:
- dependency-name: toml
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
6 months ago
dependabot[bot] e822101ef1 Bump anyhow from 1.0.79 to 1.0.81
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.79 to 1.0.81.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.79...1.0.81)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
6 months ago
Takashi Kokubun c4127eec24 Use `xremap config.yml` consistently 7 months ago
Rocco Goßmann 47427fb887
Added info on how to find unknown keynames to Readme. (#438) 7 months ago
N4tus 93a17a042f Handle new KWin API for kde-backend. 7 months ago
dependabot[bot] 9ecf5f77f7 Bump serde_json from 1.0.109 to 1.0.114
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.109 to 1.0.114.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.109...v1.0.114)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
7 months ago
dependabot[bot] d6cd715130 Bump hyprland from 0.3.12 to 0.3.13
Bumps [hyprland](https://github.com/hyprland-community/hyprland-rs) from 0.3.12 to 0.3.13.
- [Release notes](https://github.com/hyprland-community/hyprland-rs/releases)
- [Commits](https://github.com/hyprland-community/hyprland-rs/compare/0.3.12...0.3.13)

---
updated-dependencies:
- dependency-name: hyprland
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
7 months ago
dependabot[bot] ff0963082e Bump env_logger from 0.10.1 to 0.10.2
Bumps [env_logger](https://github.com/rust-cli/env_logger) from 0.10.1 to 0.10.2.
- [Release notes](https://github.com/rust-cli/env_logger/releases)
- [Changelog](https://github.com/rust-cli/env_logger/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-cli/env_logger/compare/v0.10.1...v0.10.2)

---
updated-dependencies:
- dependency-name: env_logger
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
7 months ago
dependabot[bot] 02ff58b53a Bump serde from 1.0.196 to 1.0.197
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.196 to 1.0.197.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.196...v1.0.197)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
7 months ago

@ -22,7 +22,7 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
arch: [x86_64, aarch64] arch: [x86_64, aarch64]
feature: [x11, gnome, kde, sway, hypr, wlroots] feature: [x11, gnome, kde, wlroots]
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1 - uses: actions-rs/toolchain@v1
@ -62,7 +62,8 @@ jobs:
key: ubuntu-latest key: ubuntu-latest
- run: cargo test - run: cargo test
publish: # Release xremap binaries on GitHub
release:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: needs:
- build - build
@ -75,31 +76,17 @@ jobs:
profile: minimal profile: minimal
toolchain: stable toolchain: stable
override: true override: true
- uses: Swatinem/rust-cache@v1
with:
key: ubuntu-latest
# Release crate
- name: cargo login
run: cargo login "$CARGO_TOKEN"
env:
CARGO_TOKEN: ${{ secrets.CARGO_TOKEN }}
- run: cargo publish
# Fetch x86_64 binary # Fetch x86_64 binary
- { uses: actions/download-artifact@v3, with: { name: xremap-x86_64-x11, path: package/ } } - { uses: actions/download-artifact@v3, with: { name: xremap-x86_64-x11, path: package/ } }
- { uses: actions/download-artifact@v3, with: { name: xremap-x86_64-gnome, path: package/ } } - { uses: actions/download-artifact@v3, with: { name: xremap-x86_64-gnome, path: package/ } }
- { uses: actions/download-artifact@v3, with: { name: xremap-x86_64-kde, path: package/ } } - { uses: actions/download-artifact@v3, with: { name: xremap-x86_64-kde, path: package/ } }
- { uses: actions/download-artifact@v3, with: { name: xremap-x86_64-sway, path: package/ } }
- { uses: actions/download-artifact@v3, with: { name: xremap-x86_64-hypr, path: package/ } }
- { uses: actions/download-artifact@v3, with: { name: xremap-x86_64-wlroots, path: package/ } } - { uses: actions/download-artifact@v3, with: { name: xremap-x86_64-wlroots, path: package/ } }
# Fetch aarch64 binary # Fetch aarch64 binary
- { uses: actions/download-artifact@v3, with: { name: xremap-aarch64-x11, path: package/ } } - { uses: actions/download-artifact@v3, with: { name: xremap-aarch64-x11, path: package/ } }
- { uses: actions/download-artifact@v3, with: { name: xremap-aarch64-gnome, path: package/ } } - { uses: actions/download-artifact@v3, with: { name: xremap-aarch64-gnome, path: package/ } }
- { uses: actions/download-artifact@v3, with: { name: xremap-aarch64-kde, path: package/ } } - { uses: actions/download-artifact@v3, with: { name: xremap-aarch64-kde, path: package/ } }
- { uses: actions/download-artifact@v3, with: { name: xremap-aarch64-sway, path: package/ } }
- { uses: actions/download-artifact@v3, with: { name: xremap-aarch64-hypr, path: package/ } }
- { uses: actions/download-artifact@v3, with: { name: xremap-aarch64-wlroots, path: package/ } } - { uses: actions/download-artifact@v3, with: { name: xremap-aarch64-wlroots, path: package/ } }
# Release binary # Release binary
@ -107,7 +94,32 @@ jobs:
run: | run: |
export VERSION=$(echo "$GITHUB_REF" | sed -e 's!refs/tags/!!') export VERSION=$(echo "$GITHUB_REF" | sed -e 's!refs/tags/!!')
curl -L "https://github.com/tcnksm/ghr/releases/download/${GHR_VERSION}/ghr_${GHR_VERSION}_linux_amd64.tar.gz" | tar xvz curl -L "https://github.com/tcnksm/ghr/releases/download/${GHR_VERSION}/ghr_${GHR_VERSION}_linux_amd64.tar.gz" | tar xvz
"ghr_${GHR_VERSION}_linux_amd64/ghr" -u k0kubun -r xremap -replace -n "$VERSION" "$VERSION" package/ "ghr_${GHR_VERSION}_linux_amd64/ghr" -u xremap -r xremap -replace -n "$VERSION" "$VERSION" package/
env: env:
GHR_VERSION: v0.14.0 GHR_VERSION: v0.16.2
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Publish xremap to crates.io
publish:
runs-on: ubuntu-latest
needs:
- build
- test
if: ${{ startsWith(github.ref, 'refs/tags/') }}
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
- uses: Swatinem/rust-cache@v1
with:
key: ubuntu-latest
# Release crate
- name: cargo login
run: cargo login "$CARGO_TOKEN"
env:
CARGO_TOKEN: ${{ secrets.CARGO_TOKEN }}
- run: cargo publish

@ -1,3 +1,35 @@
## v0.10.1
- X11: Handle WM\_CLASS reply without terminating null-byte [#525](https://github.com/xremap/xremap/pull/525)
## v0.10.0
- Drop `sway` and `hypr` clients [#479](https://github.com/xremap/xremap/pull/479)
- As recommended since v0.8.9, please use `wlroots` client instead.
## v0.9.0
- Add `enable_wheel` option in the config [#478](https://github.com/xremap/xremap/pull/478)
- Enable `REL_WHEEL` and `REL_HWHEEL` by default regardless of `--mouse` option.
[#478](https://github.com/xremap/xremap/pull/478)
- This reverts v0.8.2 and v0.8.10.
- Arch Linux users on systemd-253-1 can continue to disable them by top-level `enable_wheel: false`.
See [#260](https://github.com/xremap/xremap/pull/260) for details.
- Emit no key event instead of `KEY_UNKNOWN` on `skip_key_event` [#462](https://github.com/xremap/xremap/pull/462)
## v0.8.18
- Fix issues in the release pipeline
## v0.8.17
- Add `window` matcher for the `kde` client [#448](https://github.com/xremap/xremap/pull/448)
## v0.8.16
- Add `window` matcher for the `wlroots` client [#447](https://github.com/k0kubun/xremap/issues/447)
- Handle new KWin API for the `kde` client [#437](https://github.com/k0kubun/xremap/issues/437)
## v0.8.15 ## v0.8.15
- Add `skip_key_event` option to `press`/`release` modmap action [#420](https://github.com/k0kubun/xremap/issues/420) - Add `skip_key_event` option to `press`/`release` modmap action [#420](https://github.com/k0kubun/xremap/issues/420)

432
Cargo.lock generated

@ -2,21 +2,6 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 3
[[package]]
name = "addr2line"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3"
dependencies = [
"gimli",
]
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]] [[package]]
name = "aho-corasick" name = "aho-corasick"
version = "1.0.2" version = "1.0.2"
@ -92,9 +77,9 @@ dependencies = [
[[package]] [[package]]
name = "anyhow" name = "anyhow"
version = "1.0.79" version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
[[package]] [[package]]
name = "async-io" name = "async-io"
@ -125,43 +110,17 @@ dependencies = [
"event-listener", "event-listener",
] ]
[[package]]
name = "async-trait"
version = "0.1.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc6dde6e4ed435a4c1ee4e73592f5ba9da2151af10076cc04858746af9352d09"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
]
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.1.0" version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "backtrace"
version = "0.3.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12"
dependencies = [
"addr2line",
"cc",
"cfg-if",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
]
[[package]] [[package]]
name = "base64" name = "base64"
version = "0.21.3" version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "414dcefbc63d77c526a76b3afcf6fbb9b5e2791c19c3aa2297733208750c6e53" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
@ -199,12 +158,6 @@ version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "bytes"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.80" version = "1.0.80"
@ -298,12 +251,6 @@ dependencies = [
"crossbeam-utils", "crossbeam-utils",
] ]
[[package]]
name = "convert_case"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
[[package]] [[package]]
name = "core-foundation-sys" name = "core-foundation-sys"
version = "0.8.4" version = "0.8.4"
@ -385,19 +332,6 @@ dependencies = [
"syn 2.0.48", "syn 2.0.48",
] ]
[[package]]
name = "derive_more"
version = "0.99.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321"
dependencies = [
"convert_case",
"proc-macro2",
"quote",
"rustc_version",
"syn 1.0.109",
]
[[package]] [[package]]
name = "dlib" name = "dlib"
version = "0.5.2" version = "0.5.2"
@ -407,12 +341,6 @@ dependencies = [
"libloading", "libloading",
] ]
[[package]]
name = "doc-comment"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
[[package]] [[package]]
name = "downcast-rs" name = "downcast-rs"
version = "1.2.0" version = "1.2.0"
@ -442,9 +370,9 @@ dependencies = [
[[package]] [[package]]
name = "env_logger" name = "env_logger"
version = "0.10.1" version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95b3f3e67048839cb0d0781f445682a35113da7121f7c949db0e2be96a4fbece" checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580"
dependencies = [ dependencies = [
"humantime", "humantime",
"is-terminal", "is-terminal",
@ -482,9 +410,9 @@ dependencies = [
[[package]] [[package]]
name = "evdev" name = "evdev"
version = "0.12.1" version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bed59fcc8cfd6b190814a509018388462d3b203cf6dd10db5c00087e72a83f3" checksum = "ab6055a93a963297befb0f4f6e18f314aec9767a4bbe88b151126df2433610a7"
dependencies = [ dependencies = [
"bitvec", "bitvec",
"cfg-if", "cfg-if",
@ -516,9 +444,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]] [[package]]
name = "fork" name = "fork"
version = "0.1.22" version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf2ca97a59201425e7ee4d197c9c4fea282fe87a97d666a580bda889b95b8e88" checksum = "05dc8b302e04a1c27f4fe694439ef0f29779ca4edc205b7b58f00db04e29656d"
dependencies = [ dependencies = [
"libc", "libc",
] ]
@ -643,12 +571,6 @@ dependencies = [
"windows-targets", "windows-targets",
] ]
[[package]]
name = "gimli"
version = "0.27.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e"
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.12.3" version = "0.12.3"
@ -685,39 +607,6 @@ version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
name = "hyprland"
version = "0.3.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfa94ae7899f3f1bdcad21dcd50366a60f323375a25610889246f276d7f9fb06"
dependencies = [
"async-trait",
"derive_more",
"doc-comment",
"futures",
"hex",
"hyprland-macros",
"lazy_static",
"num-traits",
"paste",
"regex",
"serde",
"serde_json",
"serde_repr",
"strum",
"tokio",
]
[[package]]
name = "hyprland-macros"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c941d3d52e979612af8cb94e8de49000c7fada2014a7791d173ab41339f4e4eb"
dependencies = [
"quote",
"syn 2.0.48",
]
[[package]] [[package]]
name = "iana-time-zone" name = "iana-time-zone"
version = "0.1.57" version = "0.1.57"
@ -771,9 +660,9 @@ dependencies = [
[[package]] [[package]]
name = "indoc" name = "indoc"
version = "2.0.4" version = "2.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e186cfbae8084e513daff4240b4797e342f988cecda4fb6c939150f96315fd8" checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5"
[[package]] [[package]]
name = "instant" name = "instant"
@ -823,9 +712,9 @@ dependencies = [
[[package]] [[package]]
name = "lazy_static" name = "lazy_static"
version = "1.4.0" version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]] [[package]]
name = "libc" name = "libc"
@ -855,21 +744,11 @@ version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503"
[[package]]
name = "lock_api"
version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16"
dependencies = [
"autocfg",
"scopeguard",
]
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.20" version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]] [[package]]
name = "memchr" name = "memchr"
@ -895,26 +774,6 @@ dependencies = [
"autocfg", "autocfg",
] ]
[[package]]
name = "miniz_oxide"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
dependencies = [
"adler",
]
[[package]]
name = "mio"
version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2"
dependencies = [
"libc",
"wasi",
"windows-sys",
]
[[package]] [[package]]
name = "nb-connect" name = "nb-connect"
version = "1.2.0" version = "1.2.0"
@ -974,25 +833,6 @@ dependencies = [
"autocfg", "autocfg",
] ]
[[package]]
name = "num_cpus"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
dependencies = [
"hermit-abi",
"libc",
]
[[package]]
name = "object"
version = "0.31.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.18.0" version = "1.18.0"
@ -1005,35 +845,6 @@ version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14f2252c834a40ed9bb5422029649578e63aa341ac401f74e719dd1afda8394e" checksum = "14f2252c834a40ed9bb5422029649578e63aa341ac401f74e719dd1afda8394e"
[[package]]
name = "parking_lot"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
dependencies = [
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
"windows-targets",
]
[[package]]
name = "paste"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
[[package]] [[package]]
name = "pin-project-lite" name = "pin-project-lite"
version = "0.2.10" version = "0.2.10"
@ -1120,20 +931,11 @@ version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
[[package]]
name = "redox_syscall"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
dependencies = [
"bitflags 1.3.2",
]
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.10.3" version = "1.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick",
"memchr", "memchr",
@ -1158,21 +960,6 @@ version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
[[package]]
name = "rustc-demangle"
version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
[[package]]
name = "rustc_version"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
dependencies = [
"semver",
]
[[package]] [[package]]
name = "rustix" name = "rustix"
version = "0.37.23" version = "0.37.23"
@ -1200,12 +987,6 @@ dependencies = [
"windows-sys", "windows-sys",
] ]
[[package]]
name = "rustversion"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
[[package]] [[package]]
name = "ryu" name = "ryu"
version = "1.0.15" version = "1.0.15"
@ -1218,32 +999,20 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
[[package]]
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "semver"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.196" version = "1.0.203"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.196" version = "1.0.203"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -1252,11 +1021,12 @@ dependencies = [
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.109" version = "1.0.121"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb0652c533506ad7a2e353cce269330d6afd8bdfb6d75e0ace5b35aacbd7b9e9" checksum = "4ab380d7d9f22ef3f21ad3e6c1ebe8e4fc7a2000ccba2e4d71fc96f15b2cb609"
dependencies = [ dependencies = [
"itoa", "itoa",
"memchr",
"ryu", "ryu",
"serde", "serde",
] ]
@ -1274,18 +1044,18 @@ dependencies = [
[[package]] [[package]]
name = "serde_spanned" name = "serde_spanned"
version = "0.6.5" version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0"
dependencies = [ dependencies = [
"serde", "serde",
] ]
[[package]] [[package]]
name = "serde_with" name = "serde_with"
version = "3.6.0" version = "3.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b0ed1662c5a68664f45b76d18deb0e234aff37207086803165c961eb695e981" checksum = "0ad483d2ab0149d5a5ebcd9972a3852711e0153d863bf5a5d0391d28883c4a20"
dependencies = [ dependencies = [
"base64", "base64",
"chrono", "chrono",
@ -1293,6 +1063,7 @@ dependencies = [
"indexmap 1.9.3", "indexmap 1.9.3",
"indexmap 2.2.2", "indexmap 2.2.2",
"serde", "serde",
"serde_derive",
"serde_json", "serde_json",
"serde_with_macros", "serde_with_macros",
"time", "time",
@ -1300,9 +1071,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_with_macros" name = "serde_with_macros"
version = "3.6.0" version = "3.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "568577ff0ef47b879f736cd66740e022f3672788cdf002a05a4e609ea5a6fb15" checksum = "65569b702f41443e8bc8bbb1c5779bd0450bbe723b56198980e80ec45780bce2"
dependencies = [ dependencies = [
"darling", "darling",
"proc-macro2", "proc-macro2",
@ -1312,9 +1083,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_yaml" name = "serde_yaml"
version = "0.9.31" version = "0.9.34+deprecated"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adf8a49373e98a4c5f0ceb5d05aa7c648d75f63774981ed95b7c7443bbd50c6e" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47"
dependencies = [ dependencies = [
"indexmap 2.2.2", "indexmap 2.2.2",
"itoa", "itoa",
@ -1323,15 +1094,6 @@ dependencies = [
"unsafe-libyaml", "unsafe-libyaml",
] ]
[[package]]
name = "signal-hook-registry"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "slab" name = "slab"
version = "0.4.8" version = "0.4.8"
@ -1369,50 +1131,6 @@ version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "strum"
version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125"
dependencies = [
"strum_macros",
]
[[package]]
name = "strum_macros"
version = "0.25.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad8d03b598d3d0fff69bf533ee3ef19b8eeb342729596df84bcc7e1f96ec4059"
dependencies = [
"heck",
"proc-macro2",
"quote",
"rustversion",
"syn 2.0.48",
]
[[package]]
name = "swayipc"
version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab1dcff328b223d85d7ca767b2e4aadbc13dad550d36b4c6b929b9ad4d26ee9a"
dependencies = [
"serde",
"serde_json",
"swayipc-types",
]
[[package]]
name = "swayipc-types"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44b43b4059d825ccc04adf9726f944d0e3aa20938f4cff3b5c6b53198afcd6b3"
dependencies = [
"serde",
"serde_json",
"thiserror",
]
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.109" version = "1.0.109"
@ -1498,37 +1216,6 @@ dependencies = [
"time-core", "time-core",
] ]
[[package]]
name = "tokio"
version = "1.29.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da"
dependencies = [
"autocfg",
"backtrace",
"bytes",
"libc",
"mio",
"num_cpus",
"parking_lot",
"pin-project-lite",
"signal-hook-registry",
"socket2",
"tokio-macros",
"windows-sys",
]
[[package]]
name = "tokio-macros"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
]
[[package]] [[package]]
name = "toml" name = "toml"
version = "0.5.11" version = "0.5.11"
@ -1540,21 +1227,21 @@ dependencies = [
[[package]] [[package]]
name = "toml" name = "toml"
version = "0.8.9" version = "0.8.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6a4b9e8023eb94392d3dca65d717c53abc5dad49c07cb65bb8fcd87115fa325" checksum = "ac2caab0bf757388c6c0ae23b3293fdb463fee59434529014f85e3263b995c28"
dependencies = [ dependencies = [
"serde", "serde",
"serde_spanned", "serde_spanned",
"toml_datetime", "toml_datetime",
"toml_edit 0.21.1", "toml_edit 0.22.16",
] ]
[[package]] [[package]]
name = "toml_datetime" name = "toml_datetime"
version = "0.6.5" version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf"
dependencies = [ dependencies = [
"serde", "serde",
] ]
@ -1567,20 +1254,20 @@ checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a"
dependencies = [ dependencies = [
"indexmap 2.2.2", "indexmap 2.2.2",
"toml_datetime", "toml_datetime",
"winnow", "winnow 0.5.3",
] ]
[[package]] [[package]]
name = "toml_edit" name = "toml_edit"
version = "0.21.1" version = "0.22.16"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" checksum = "278f3d518e152219c994ce877758516bca5e118eaed6996192a774fb9fbf0788"
dependencies = [ dependencies = [
"indexmap 2.2.2", "indexmap 2.2.2",
"serde", "serde",
"serde_spanned", "serde_spanned",
"toml_datetime", "toml_datetime",
"winnow", "winnow 0.6.5",
] ]
[[package]] [[package]]
@ -1591,9 +1278,9 @@ checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
[[package]] [[package]]
name = "unsafe-libyaml" name = "unsafe-libyaml"
version = "0.2.10" version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab4c90930b95a82d00dc9e9ac071b4991924390d46cbd0dfe566148667605e4b" checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861"
[[package]] [[package]]
name = "utf8parse" name = "utf8parse"
@ -1607,12 +1294,6 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]] [[package]]
name = "wasm-bindgen" name = "wasm-bindgen"
version = "0.2.87" version = "0.2.87"
@ -1856,6 +1537,15 @@ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "winnow"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "wyz" name = "wyz"
version = "0.5.1" version = "0.5.1"
@ -1867,9 +1557,9 @@ dependencies = [
[[package]] [[package]]
name = "x11rb" name = "x11rb"
version = "0.13.0" version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8f25ead8c7e4cba123243a6367da5d3990e0d3affa708ea19dce96356bd9f1a" checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12"
dependencies = [ dependencies = [
"gethostname", "gethostname",
"rustix 0.38.4", "rustix 0.38.4",
@ -1878,13 +1568,13 @@ dependencies = [
[[package]] [[package]]
name = "x11rb-protocol" name = "x11rb-protocol"
version = "0.13.0" version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e63e71c4b8bd9ffec2c963173a4dc4cbde9ee96961d4fcb4429db9929b606c34" checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d"
[[package]] [[package]]
name = "xremap" name = "xremap"
version = "0.8.15" version = "0.10.1"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"clap", "clap",
@ -1893,7 +1583,6 @@ dependencies = [
"env_logger", "env_logger",
"evdev", "evdev",
"fork", "fork",
"hyprland",
"indoc", "indoc",
"lazy_static", "lazy_static",
"log", "log",
@ -1903,8 +1592,7 @@ dependencies = [
"serde_json", "serde_json",
"serde_with", "serde_with",
"serde_yaml", "serde_yaml",
"swayipc", "toml 0.8.15",
"toml 0.8.9",
"wayland-client", "wayland-client",
"wayland-protocols-wlr", "wayland-protocols-wlr",
"x11rb", "x11rb",

@ -1,6 +1,6 @@
[package] [package]
name = "xremap" name = "xremap"
version = "0.8.15" version = "0.10.1"
edition = "2021" edition = "2021"
description = "Dynamic key remapp for X and Wayland" description = "Dynamic key remapp for X and Wayland"
license = "MIT" license = "MIT"
@ -8,34 +8,30 @@ repository = "https://github.com/k0kubun/xremap"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
anyhow = "1.0.79" anyhow = "1.0.86"
clap = { version = "4.3.19", features = ["derive"] } clap = { version = "4.3.19", features = ["derive"] }
clap_complete = "4.3.2" clap_complete = "4.3.2"
derive-where = "1.2.7" derive-where = "1.2.7"
env_logger = "0.10.1" env_logger = "0.10.2"
evdev = "0.12.1" evdev = "0.12.2"
fork = "0.1" fork = "0.2"
indoc = "2.0" indoc = "2.0"
lazy_static = "1.4.0" lazy_static = "1.5.0"
log = "0.4.20" log = "0.4.22"
nix = "0.26.2" nix = "0.26.2"
regex = "1.10.3" regex = "1.10.5"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" serde_json = "1.0"
serde_with = { version = "3.6", features = ["chrono"] } serde_with = { version = "3.8", features = ["chrono"] }
serde_yaml = "0.9" serde_yaml = "0.9"
swayipc = { version = "3.0.1", optional = true }
wayland-client = { version = "0.30", optional = true } wayland-client = { version = "0.30", optional = true }
wayland-protocols-wlr = { version = "0.1", features = ["client"], optional = true } wayland-protocols-wlr = { version = "0.1", features = ["client"], optional = true }
x11rb = { version = "0.13.0", optional = true } x11rb = { version = "0.13.1", optional = true }
zbus = { version = "1.9.2", optional = true } zbus = { version = "1.9.2", optional = true }
hyprland = { version = "0.3.12", optional = true } toml = "0.8.15"
toml = "0.8.9"
[features] [features]
gnome = ["zbus"] gnome = ["zbus"]
sway = ["swayipc"]
x11 = ["x11rb"] x11 = ["x11rb"]
hypr = ["hyprland"]
kde = ["zbus"] kde = ["zbus"]
wlroots = ["wayland-client", "wayland-protocols-wlr"] wlroots = ["wayland-client", "wayland-protocols-wlr"]

@ -196,8 +196,8 @@ modmap:
KEY_XXX: KEY_YYY # Required KEY_XXX: KEY_YYY # Required
# Dispatch different keys depending on whether you hold it or press it alone # Dispatch different keys depending on whether you hold it or press it alone
KEY_XXX: KEY_XXX:
held: [KEY_YYY] # Required held: KEY_YYY # Required, also accepts arrays
alone: [KEY_ZZZ] # Required alone: KEY_ZZZ # Required, also accepts arrays
alone_timeout_millis: 1000 # Optional alone_timeout_millis: 1000 # Optional
# Hook `keymap` action on key press/release events. # Hook `keymap` action on key press/release events.
KEY_XXX: KEY_XXX:
@ -208,6 +208,10 @@ modmap:
not: [Application, ...] not: [Application, ...]
# or # or
only: [Application, ...] only: [Application, ...]
window: # Optional (only wlroots/kde clients supported)
not: [/regex of window title/, ...]
# or
only: [/regex of window title/, ...]
device: # Optional device: # Optional
not: [Device, ...] not: [Device, ...]
# or # or
@ -218,6 +222,14 @@ For `KEY_XXX` and `KEY_YYY`, use [these names](https://github.com/emberian/evdev
You can skip `KEY_` and the name is case-insensitive. So `KEY_CAPSLOCK`, `CAPSLOCK`, and `CapsLock` are the same thing. You can skip `KEY_` and the name is case-insensitive. So `KEY_CAPSLOCK`, `CAPSLOCK`, and `CapsLock` are the same thing.
Some [custom aliases](src/config/key.rs) like `SHIFT_R`, `CONTROL_L`, etc. are provided. Some [custom aliases](src/config/key.rs) like `SHIFT_R`, `CONTROL_L`, etc. are provided.
In case you don't know the name of a key, you can find out by enabling the xremap debug output:
```bash
RUST_LOG=debug xremap config.yml
# or
sudo RUST_LOG=debug xremap config.yml
```
Then press the key you want to know the name of.
If you specify a map containing `held` and `alone`, you can use the key for two purposes. If you specify a map containing `held` and `alone`, you can use the key for two purposes.
The key is considered `alone` if it's pressed and released within `alone_timeout_millis` (default: 1000) The key is considered `alone` if it's pressed and released within `alone_timeout_millis` (default: 1000)
before any other key is pressed. Otherwise it's considered `held`. before any other key is pressed. Otherwise it's considered `held`.
@ -254,6 +266,10 @@ keymap:
not: [Application, ...] not: [Application, ...]
# or # or
only: [Application, ...] only: [Application, ...]
window: # Optional (only wlroots/kde clients supported)
not: [/regex of window title/, ...]
# or
only: [/regex of window title/, ...]
device: # Optional device: # Optional
not: [Device, ...] not: [Device, ...]
# or # or
@ -328,7 +344,7 @@ However, it will only start printing, once a mapping has been triggered that use
So you have to create a mapping with a filter using a dummy application name and trigger it. So you have to create a mapping with a filter using a dummy application name and trigger it.
Then each time you switch to a new window xremap will print its caption, class, and name in the following style: Then each time you switch to a new window xremap will print its caption, class, and name in the following style:
`active window: caption: '<caption>', class: '<class>', name: '<name>'` `active window: caption: '<caption>', class: '<class>', name: '<name>'`
You want to use the class for the filter. The `class` property should be used for application matching, while the `caption` property should be used for window matching.
If you use a systemd-daemon to manage xremap, the prints will be visible in the system-logs (Can be opened with `journalctl -f`) If you use a systemd-daemon to manage xremap, the prints will be visible in the system-logs (Can be opened with `journalctl -f`)
@ -429,6 +445,12 @@ keymap:
remap: *some_remaps # and we can reuse a map here. remap: *some_remaps # and we can reuse a map here.
``` ```
## Maintainers
- @k0kubun
- @N4tus (KDE client)
- @jixiuf (wlroots client)
## License ## License
`xremap` is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT). `xremap` is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).

@ -24,6 +24,10 @@ impl Client for GnomeClient {
self.connect(); self.connect();
self.current_application().is_some() self.current_application().is_some()
} }
fn current_window(&mut self) -> Option<String> {
// TODO: not implemented
None
}
fn current_application(&mut self) -> Option<String> { fn current_application(&mut self) -> Option<String> {
self.connect(); self.connect();

@ -1,24 +0,0 @@
use crate::client::Client;
use hyprland::{data::Client as HyprClient, prelude::*};
pub struct HyprlandClient;
impl HyprlandClient {
pub fn new() -> HyprlandClient {
HyprlandClient {}
}
}
impl Client for HyprlandClient {
fn supported(&mut self) -> bool {
true
}
fn current_application(&mut self) -> Option<String> {
if let Ok(win_opt) = HyprClient::get_active() {
if let Some(win) = win_opt {
return Some(win.class);
}
}
None
}
}

@ -29,14 +29,14 @@ impl Drop for KwinScriptTempFile {
} }
trait KWinScripting { trait KWinScripting {
fn load_script(&self, path: &Path) -> Result<String, ConnectionError>; fn load_script(&self, path: &Path) -> Result<i32, ConnectionError>;
fn unload_script(&self) -> Result<bool, ConnectionError>; fn unload_script(&self) -> Result<bool, ConnectionError>;
fn start_script(&self, script_obj_path: &str) -> Result<(), ConnectionError>; fn start_script(&self, script_obj_id: i32) -> Result<(), ConnectionError>;
fn is_script_loaded(&self) -> Result<bool, ConnectionError>; fn is_script_loaded(&self) -> Result<bool, ConnectionError>;
} }
impl KWinScripting for Connection { impl KWinScripting for Connection {
fn load_script(&self, path: &Path) -> Result<String, ConnectionError> { fn load_script(&self, path: &Path) -> Result<i32, ConnectionError> {
self.call_method( self.call_method(
Some("org.kde.KWin"), Some("org.kde.KWin"),
"/Scripting", "/Scripting",
@ -48,7 +48,6 @@ impl KWinScripting for Connection {
.map_err(|_| ConnectionError::LoadScriptCall)? .map_err(|_| ConnectionError::LoadScriptCall)?
.body::<i32>() .body::<i32>()
.map_err(|_| ConnectionError::InvalidLoadScriptResult) .map_err(|_| ConnectionError::InvalidLoadScriptResult)
.map(|obj_path| format!("/{obj_path}"))
} }
fn unload_script(&self) -> Result<bool, ConnectionError> { fn unload_script(&self) -> Result<bool, ConnectionError> {
@ -65,10 +64,22 @@ impl KWinScripting for Connection {
.map_err(|_| ConnectionError::InvalidUnloadScriptResult) .map_err(|_| ConnectionError::InvalidUnloadScriptResult)
} }
fn start_script(&self, script_obj_path: &str) -> Result<(), ConnectionError> { fn start_script(&self, script_obj_id: i32) -> Result<(), ConnectionError> {
self.call_method(Some("org.kde.KWin"), script_obj_path, Some("org.kde.kwin.Script"), "run", &()) for script_obj_path_fn in [|id| format!("/{id}"), |id| format!("/Scripting/Script{id}")] {
.map_err(|_| ConnectionError::StartScriptCall) if self
.map(|_| ()) .call_method(
Some("org.kde.KWin"),
script_obj_path_fn(script_obj_id).as_str(),
Some("org.kde.kwin.Script"),
"run",
&(),
)
.is_ok()
{
return Ok(());
}
}
Err(ConnectionError::StartScriptCall)
} }
fn is_script_loaded(&self) -> Result<bool, ConnectionError> { fn is_script_loaded(&self) -> Result<bool, ConnectionError> {
@ -91,8 +102,8 @@ fn load_kwin_script() -> Result<(), ConnectionError> {
let init_script = || { let init_script = || {
let temp_file_path = KwinScriptTempFile::new(); let temp_file_path = KwinScriptTempFile::new();
std::fs::write(&temp_file_path.0, KWIN_SCRIPT).map_err(|_| ConnectionError::WriteScriptToTempFile)?; std::fs::write(&temp_file_path.0, KWIN_SCRIPT).map_err(|_| ConnectionError::WriteScriptToTempFile)?;
let script_obj_path = dbus.load_script(&temp_file_path.0)?; let script_obj_id = dbus.load_script(&temp_file_path.0)?;
dbus.start_script(&script_obj_path)?; dbus.start_script(script_obj_id)?;
Ok(()) Ok(())
}; };
if let Err(err) = init_script() { if let Err(err) = init_script() {
@ -162,9 +173,13 @@ impl Client for KdeClient {
} }
conn_res.is_ok() conn_res.is_ok()
} }
fn current_window(&mut self) -> Option<String> {
let aw = self.active_window.lock().ok()?;
Some(aw.title.clone())
}
fn current_application(&mut self) -> Option<String> { fn current_application(&mut self) -> Option<String> {
let aw = self.active_window.lock().unwrap(); let aw = self.active_window.lock().ok()?;
Some(aw.res_class.clone()) Some(aw.res_class.clone())
} }
} }

@ -1,4 +1,4 @@
workspace.clientActivated.connect(function(client){ function notifyActiveWindow(client) {
callDBus( callDBus(
"com.k0kubun.Xremap", "com.k0kubun.Xremap",
"/com/k0kubun/Xremap", "/com/k0kubun/Xremap",
@ -8,4 +8,12 @@ workspace.clientActivated.connect(function(client){
"resourceClass" in client ? client.resourceClass : "", "resourceClass" in client ? client.resourceClass : "",
"resourceName" in client ? client.resourceName : "" "resourceName" in client ? client.resourceName : ""
); );
}); }
if (workspace.windowList) {
// kde 6
workspace.windowActivated.connect(notifyActiveWindow);
} else {
// kde 5
workspace.clientActivated.connect(notifyActiveWindow);
}

@ -1,6 +1,7 @@
pub trait Client { pub trait Client {
fn supported(&mut self) -> bool; fn supported(&mut self) -> bool;
fn current_application(&mut self) -> Option<String>; fn current_application(&mut self) -> Option<String>;
fn current_window(&mut self) -> Option<String>;
} }
pub struct WMClient { pub struct WMClient {
@ -8,6 +9,7 @@ pub struct WMClient {
client: Box<dyn Client>, client: Box<dyn Client>,
supported: Option<bool>, supported: Option<bool>,
last_application: String, last_application: String,
last_window: String,
} }
impl WMClient { impl WMClient {
@ -17,8 +19,28 @@ impl WMClient {
client, client,
supported: None, supported: None,
last_application: String::new(), last_application: String::new(),
last_window: String::new(),
} }
} }
pub fn current_window(&mut self) -> Option<String> {
if self.supported.is_none() {
let supported = self.client.supported();
self.supported = Some(supported);
println!("application-client: {} (supported: {})", self.name, supported);
}
if !self.supported.unwrap() {
return None;
}
let result = self.client.current_window();
if let Some(window) = &result {
if &self.last_window != window {
self.last_window = window.clone();
println!("window: {}", window);
}
}
result
}
pub fn current_application(&mut self) -> Option<String> { pub fn current_application(&mut self) -> Option<String> {
if self.supported.is_none() { if self.supported.is_none() {
@ -55,20 +77,6 @@ pub fn build_client() -> WMClient {
WMClient::new("KDE", Box::new(kde_client::KdeClient::new())) WMClient::new("KDE", Box::new(kde_client::KdeClient::new()))
} }
#[cfg(feature = "sway")]
mod sway_client;
#[cfg(feature = "sway")]
pub fn build_client() -> WMClient {
WMClient::new("Sway", Box::new(sway_client::SwayClient::new()))
}
#[cfg(feature = "hypr")]
mod hypr_client;
#[cfg(feature = "hypr")]
pub fn build_client() -> WMClient {
WMClient::new("Hypr", Box::new(hypr_client::HyprlandClient::new()))
}
#[cfg(feature = "x11")] #[cfg(feature = "x11")]
mod x11_client; mod x11_client;
#[cfg(feature = "x11")] #[cfg(feature = "x11")]

@ -6,6 +6,9 @@ impl Client for NullClient {
fn supported(&mut self) -> bool { fn supported(&mut self) -> bool {
false false
} }
fn current_window(&mut self) -> Option<String> {
None
}
fn current_application(&mut self) -> Option<String> { fn current_application(&mut self) -> Option<String> {
None None

@ -1,80 +0,0 @@
use crate::client::Client;
use std::env;
use std::fs::read_dir;
use std::os::unix::ffi::OsStrExt;
use swayipc::Connection;
pub struct SwayClient {
connection: Option<Connection>,
}
impl SwayClient {
pub fn new() -> SwayClient {
SwayClient { connection: None }
}
fn connect(&mut self) {
if let None = self.connection {
if let Err(env::VarError::NotPresent) = env::var("SWAYSOCK") {
let path = match find_socket() {
Some(path) => path,
None => {
println!("Failed to locate a SWAYSOCK from /run/user/1000/sway-ipc.*");
return;
}
};
println!("$SWAYSOCK is not set. Defaulting to \"{}\"", path);
env::set_var("SWAYSOCK", path);
}
match Connection::new() {
Ok(connection) => self.connection = Some(connection),
Err(e) => println!("SwayClient#connect() failed: {}", e),
}
}
}
}
impl Client for SwayClient {
fn supported(&mut self) -> bool {
self.connect();
self.connection.is_some()
}
fn current_application(&mut self) -> Option<String> {
self.connect();
let connection = match &mut self.connection {
Some(connection) => connection,
None => return None,
};
if let Ok(node) = connection.get_tree() {
if let Some(node) = node.find_focused(|n| n.focused) {
if node.app_id.is_some() {
return node.app_id;
} else if let Some(wp) = node.window_properties {
return wp.class;
}
}
}
None
}
}
// e.g. "/run/user/1000/sway-ipc.1000.2575.sock"
fn find_socket() -> Option<String> {
let uid = 1000; // Assume a first nornal Linux user. TODO: Make it configurable
if let Some(run_user) = read_dir(format!("/run/user/{}", uid)).as_mut().ok() {
while let Some(entry) = run_user.next() {
let path = entry.ok()?.path();
if let Some(fname) = path.file_name() {
if fname.as_bytes().starts_with(b"sway-ipc.") {
if let Ok(path) = path.into_os_string().into_string() {
return Some(path);
}
}
}
}
}
None
}

@ -20,6 +20,7 @@ use crate::client::Client;
struct State { struct State {
active_window: Option<ObjectId>, active_window: Option<ObjectId>,
windows: HashMap<ObjectId, String>, windows: HashMap<ObjectId, String>,
titles: HashMap<ObjectId, String>,
} }
#[derive(Default)] #[derive(Default)]
@ -59,6 +60,22 @@ impl Client for WlRootsClient {
} }
} }
} }
fn current_window(&mut self) -> Option<String> {
let queue = self.queue.as_mut()?;
if let Err(_) = queue.roundtrip(&mut self.state) {
// try to reconnect
if let Err(err) = self.connect() {
log::error!("{err}");
return None;
}
log::debug!("Reconnected to wayland");
}
let id = self.state.active_window.as_ref()?;
self.state.titles.get(id).cloned()
}
fn current_application(&mut self) -> Option<String> { fn current_application(&mut self) -> Option<String> {
let queue = self.queue.as_mut()?; let queue = self.queue.as_mut()?;
@ -102,6 +119,7 @@ impl Dispatch<ZwlrForeignToplevelManagerV1, ()> for State {
) { ) {
if let ManagerEvent::Toplevel { toplevel } = event { if let ManagerEvent::Toplevel { toplevel } = event {
state.windows.insert(toplevel.id(), "<unknown>".into()); state.windows.insert(toplevel.id(), "<unknown>".into());
state.titles.insert(toplevel.id(), "<unknown>".into());
} }
} }
@ -123,8 +141,12 @@ impl Dispatch<ZwlrForeignToplevelHandleV1, ()> for State {
HandleEvent::AppId { app_id } => { HandleEvent::AppId { app_id } => {
state.windows.insert(handle.id(), app_id); state.windows.insert(handle.id(), app_id);
} }
HandleEvent::Title { title } => {
state.titles.insert(handle.id(), title);
}
HandleEvent::Closed => { HandleEvent::Closed => {
state.windows.remove(&handle.id()); state.windows.remove(&handle.id());
state.titles.remove(&handle.id());
} }
HandleEvent::State { state: handle_state } => { HandleEvent::State { state: handle_state } => {
let activated = HandleState::Activated as u8; let activated = HandleState::Activated as u8;

@ -48,6 +48,10 @@ impl Client for X11Client {
return self.connection.is_some(); return self.connection.is_some();
// TODO: Test XGetInputFocus and focused_window > 0? // TODO: Test XGetInputFocus and focused_window > 0?
} }
fn current_window(&mut self) -> Option<String> {
// TODO: not implemented
None
}
fn current_application(&mut self) -> Option<String> { fn current_application(&mut self) -> Option<String> {
self.connect(); self.connect();
@ -90,8 +94,8 @@ fn get_wm_class(client: &mut X11Client, window: Window) -> Option<String> {
if let Some(delimiter) = reply.value.iter().position(|byte| *byte == '\0' as u8) { if let Some(delimiter) = reply.value.iter().position(|byte| *byte == '\0' as u8) {
if let Ok(prefix) = String::from_utf8(reply.value[..delimiter].to_vec()) { if let Ok(prefix) = String::from_utf8(reply.value[..delimiter].to_vec()) {
let name = reply.value[(delimiter + 1)..].to_vec(); let name = reply.value[(delimiter + 1)..].to_vec();
if let Some(end) = name.iter().position(|byte| *byte == '\0' as u8) { if let Some(end) = name.iter().position(|byte| *byte == '\0' as u8).or(Some(name.len())) {
if end == name.len() - 1 { if end == name.len() - 1 || end == name.len() {
if let Ok(name) = String::from_utf8(name[..end].to_vec()) { if let Ok(name) = String::from_utf8(name[..end].to_vec()) {
return Some(format!("{prefix}.{name}")); return Some(format!("{prefix}.{name}"));
} }

@ -7,7 +7,7 @@ use serde::{Deserialize, Deserializer};
// TODO: Use trait to allow only either `only` or `not` // TODO: Use trait to allow only either `only` or `not`
#[derive(Clone, Debug, Deserialize)] #[derive(Clone, Debug, Deserialize)]
#[serde(deny_unknown_fields)] #[serde(deny_unknown_fields)]
pub struct Application { pub struct OnlyOrNot {
#[serde(default, deserialize_with = "deserialize_matchers")] #[serde(default, deserialize_with = "deserialize_matchers")]
pub only: Option<Vec<ApplicationMatcher>>, pub only: Option<Vec<ApplicationMatcher>>,
#[serde(default, deserialize_with = "deserialize_matchers")] #[serde(default, deserialize_with = "deserialize_matchers")]

@ -1,5 +1,5 @@
use crate::config::application::deserialize_string_or_vec; use crate::config::application::deserialize_string_or_vec;
use crate::config::application::Application; use crate::config::application::OnlyOrNot;
use crate::config::key_press::KeyPress; use crate::config::key_press::KeyPress;
use crate::config::keymap_action::{Actions, KeymapAction}; use crate::config::keymap_action::{Actions, KeymapAction};
use evdev::Key; use evdev::Key;
@ -17,7 +17,8 @@ pub struct Keymap {
pub name: String, pub name: String,
#[serde(deserialize_with = "deserialize_remap")] #[serde(deserialize_with = "deserialize_remap")]
pub remap: HashMap<KeyPress, Vec<KeymapAction>>, pub remap: HashMap<KeyPress, Vec<KeymapAction>>,
pub application: Option<Application>, pub application: Option<OnlyOrNot>,
pub window: Option<OnlyOrNot>,
pub device: Option<Device>, pub device: Option<Device>,
#[serde(default, deserialize_with = "deserialize_string_or_vec")] #[serde(default, deserialize_with = "deserialize_string_or_vec")]
pub mode: Option<Vec<String>>, pub mode: Option<Vec<String>>,
@ -41,7 +42,8 @@ where
pub struct KeymapEntry { pub struct KeymapEntry {
pub actions: Vec<KeymapAction>, pub actions: Vec<KeymapAction>,
pub modifiers: Vec<Modifier>, pub modifiers: Vec<Modifier>,
pub application: Option<Application>, pub application: Option<OnlyOrNot>,
pub title: Option<OnlyOrNot>,
pub device: Option<Device>, pub device: Option<Device>,
pub mode: Option<Vec<String>>, pub mode: Option<Vec<String>>,
pub exact_match: bool, pub exact_match: bool,
@ -65,6 +67,7 @@ pub fn build_keymap_table(keymaps: &Vec<Keymap>) -> HashMap<Key, Vec<KeymapEntry
actions: actions.to_vec(), actions: actions.to_vec(),
modifiers: key_press.modifiers.clone(), modifiers: key_press.modifiers.clone(),
application: keymap.application.clone(), application: keymap.application.clone(),
title: keymap.window.clone(),
device: keymap.device.clone(), device: keymap.device.clone(),
mode: keymap.mode.clone(), mode: keymap.mode.clone(),
exact_match: keymap.exact_match, exact_match: keymap.exact_match,

@ -18,7 +18,7 @@ use evdev::Key;
use keymap::Keymap; use keymap::Keymap;
use modmap::Modmap; use modmap::Modmap;
use nix::sys::inotify::{AddWatchFlags, InitFlags, Inotify}; use nix::sys::inotify::{AddWatchFlags, InitFlags, Inotify};
use serde::{Deserialize, Deserializer, de::IgnoredAny}; use serde::{de::IgnoredAny, Deserialize, Deserializer};
use std::{collections::HashMap, error, fs, path::PathBuf, time::SystemTime}; use std::{collections::HashMap, error, fs, path::PathBuf, time::SystemTime};
use self::{ use self::{
@ -51,6 +51,8 @@ pub struct Config {
pub modify_time: Option<SystemTime>, pub modify_time: Option<SystemTime>,
#[serde(skip)] #[serde(skip)]
pub keymap_table: HashMap<Key, Vec<KeymapEntry>>, pub keymap_table: HashMap<Key, Vec<KeymapEntry>>,
#[serde(default = "const_true")]
pub enable_wheel: bool,
} }
enum ConfigFiletype { enum ConfigFiletype {
@ -66,7 +68,7 @@ fn get_file_ext(filename: &PathBuf) -> ConfigFiletype {
} else { } else {
ConfigFiletype::Yaml ConfigFiletype::Yaml
} }
}, }
_ => ConfigFiletype::Yaml, _ => ConfigFiletype::Yaml,
} }
} }
@ -79,7 +81,7 @@ pub fn load_configs(filenames: &Vec<PathBuf>) -> Result<Config, Box<dyn error::E
ConfigFiletype::Yaml => serde_yaml::from_str(&config_contents)?, ConfigFiletype::Yaml => serde_yaml::from_str(&config_contents)?,
ConfigFiletype::Toml => toml::from_str(&config_contents)?, ConfigFiletype::Toml => toml::from_str(&config_contents)?,
}; };
for filename in &filenames[1..] { for filename in &filenames[1..] {
let config_contents = fs::read_to_string(&filename)?; let config_contents = fs::read_to_string(&filename)?;
let c: Config = match get_file_ext(&filename) { let c: Config = match get_file_ext(&filename) {
@ -132,3 +134,7 @@ where
} }
return Ok(keys); return Ok(keys);
} }
fn const_true() -> bool {
true
}

@ -1,4 +1,4 @@
use crate::config::application::Application; use crate::config::application::OnlyOrNot;
use crate::config::key::deserialize_key; use crate::config::key::deserialize_key;
use crate::config::modmap_action::ModmapAction; use crate::config::modmap_action::ModmapAction;
use evdev::Key; use evdev::Key;
@ -14,7 +14,8 @@ pub struct Modmap {
pub name: String, pub name: String,
#[serde(deserialize_with = "deserialize_remap")] #[serde(deserialize_with = "deserialize_remap")]
pub remap: HashMap<Key, ModmapAction>, pub remap: HashMap<Key, ModmapAction>,
pub application: Option<Application>, pub application: Option<OnlyOrNot>,
pub window: Option<OnlyOrNot>,
pub device: Option<Device>, pub device: Option<Device>,
} }

@ -40,7 +40,7 @@ static MOUSE_BTNS: [&str; 20] = [
static mut DEVICE_NAME: Option<String> = None; static mut DEVICE_NAME: Option<String> = None;
// Credit: https://github.com/mooz/xkeysnail/blob/bf3c93b4fe6efd42893db4e6588e5ef1c4909cfb/xkeysnail/output.py#L10-L32 // Credit: https://github.com/mooz/xkeysnail/blob/bf3c93b4fe6efd42893db4e6588e5ef1c4909cfb/xkeysnail/output.py#L10-L32
pub fn output_device(bus_type: Option<BusType>, mouse: bool) -> Result<VirtualDevice, Box<dyn Error>> { pub fn output_device(bus_type: Option<BusType>, enable_wheel: bool) -> Result<VirtualDevice, Box<dyn Error>> {
let mut keys: AttributeSet<Key> = AttributeSet::new(); let mut keys: AttributeSet<Key> = AttributeSet::new();
for code in Key::KEY_RESERVED.code()..Key::BTN_TRIGGER_HAPPY40.code() { for code in Key::KEY_RESERVED.code()..Key::BTN_TRIGGER_HAPPY40.code() {
let key = Key::new(code); let key = Key::new(code);
@ -53,7 +53,7 @@ pub fn output_device(bus_type: Option<BusType>, mouse: bool) -> Result<VirtualDe
let mut relative_axes: AttributeSet<RelativeAxisType> = AttributeSet::new(); let mut relative_axes: AttributeSet<RelativeAxisType> = AttributeSet::new();
relative_axes.insert(RelativeAxisType::REL_X); relative_axes.insert(RelativeAxisType::REL_X);
relative_axes.insert(RelativeAxisType::REL_Y); relative_axes.insert(RelativeAxisType::REL_Y);
if mouse { if enable_wheel {
relative_axes.insert(RelativeAxisType::REL_HWHEEL); relative_axes.insert(RelativeAxisType::REL_HWHEEL);
relative_axes.insert(RelativeAxisType::REL_WHEEL); relative_axes.insert(RelativeAxisType::REL_WHEEL);
} }

@ -1,6 +1,6 @@
use crate::action::Action; use crate::action::Action;
use crate::client::WMClient; use crate::client::WMClient;
use crate::config::application::Application; use crate::config::application::OnlyOrNot;
use crate::config::key_press::{KeyPress, Modifier}; use crate::config::key_press::{KeyPress, Modifier};
use crate::config::keymap::{build_override_table, OverrideEntry}; use crate::config::keymap::{build_override_table, OverrideEntry};
use crate::config::keymap_action::KeymapAction; use crate::config::keymap_action::KeymapAction;
@ -35,6 +35,7 @@ pub struct EventHandler {
// Check the currently active application // Check the currently active application
application_client: WMClient, application_client: WMClient,
application_cache: Option<String>, application_cache: Option<String>,
title_cache: Option<String>,
// State machine for multi-purpose keys // State machine for multi-purpose keys
multi_purpose_keys: HashMap<Key, MultiPurposeKeyState>, multi_purpose_keys: HashMap<Key, MultiPurposeKeyState>,
// Current nested remaps // Current nested remaps
@ -68,6 +69,7 @@ impl EventHandler {
pressed_keys: HashMap::new(), pressed_keys: HashMap::new(),
application_client, application_client,
application_cache: None, application_cache: None,
title_cache: None,
multi_purpose_keys: HashMap::new(), multi_purpose_keys: HashMap::new(),
override_remaps: vec![], override_remaps: vec![],
override_timeout_key: None, override_timeout_key: None,
@ -113,6 +115,7 @@ impl EventHandler {
device: &InputDeviceInfo, device: &InputDeviceInfo,
) -> Result<bool, Box<dyn Error>> { ) -> Result<bool, Box<dyn Error>> {
self.application_cache = None; // expire cache self.application_cache = None; // expire cache
self.title_cache = None; // expire cache
let key = Key::new(event.code()); let key = Key::new(event.code());
debug!("=> {}: {:?}", event.value(), &key); debug!("=> {}: {:?}", event.value(), &key);
@ -329,7 +332,11 @@ impl EventHandler {
// fallthrough on state discrepancy // fallthrough on state discrepancy
vec![(key, value)] vec![(key, value)]
} }
ModmapAction::PressReleaseKey(PressReleaseKey { skip_key_event, press, release }) => { ModmapAction::PressReleaseKey(PressReleaseKey {
skip_key_event,
press,
release,
}) => {
// Just hook actions, and then emit the original event. We might want to // Just hook actions, and then emit the original event. We might want to
// support reordering the key event and dispatched actions later. // support reordering the key event and dispatched actions later.
if value == PRESS || value == RELEASE { if value == PRESS || value == RELEASE {
@ -347,7 +354,7 @@ impl EventHandler {
if skip_key_event { if skip_key_event {
// Do not dispatch the original key // Do not dispatch the original key
vec![(Key::KEY_UNKNOWN, value)] vec![]
} else { } else {
// dispatch the original key // dispatch the original key
vec![(key, value)] vec![(key, value)]
@ -381,6 +388,11 @@ impl EventHandler {
fn find_modmap(&mut self, config: &Config, key: &Key, device: &InputDeviceInfo) -> Option<ModmapAction> { fn find_modmap(&mut self, config: &Config, key: &Key, device: &InputDeviceInfo) -> Option<ModmapAction> {
for modmap in &config.modmap { for modmap in &config.modmap {
if let Some(key_action) = modmap.remap.get(key) { if let Some(key_action) = modmap.remap.get(key) {
if let Some(window_matcher) = &modmap.window {
if !self.match_window(window_matcher) {
continue;
}
}
if let Some(application_matcher) = &modmap.application { if let Some(application_matcher) = &modmap.application {
if !self.match_application(application_matcher) { if !self.match_application(application_matcher) {
continue; continue;
@ -454,6 +466,12 @@ impl EventHandler {
if (exact_match && extra_modifiers.len() > 0) || missing_modifiers.len() > 0 { if (exact_match && extra_modifiers.len() > 0) || missing_modifiers.len() > 0 {
continue; continue;
} }
if let Some(window_matcher) = &entry.title {
if !self.match_window(window_matcher) {
continue;
}
}
if let Some(application_matcher) = &entry.application { if let Some(application_matcher) = &entry.application {
if !self.match_application(application_matcher) { if !self.match_application(application_matcher) {
continue; continue;
@ -619,8 +637,27 @@ impl EventHandler {
Modifier::Key(key) => self.modifiers.contains(key), Modifier::Key(key) => self.modifiers.contains(key),
} }
} }
fn match_window(&mut self, window_matcher: &OnlyOrNot) -> bool {
// Lazily fill the wm_class cache
if self.title_cache.is_none() {
match self.application_client.current_window() {
Some(title) => self.title_cache = Some(title),
None => self.title_cache = Some(String::new()),
}
}
if let Some(title) = &self.title_cache {
if let Some(title_only) = &window_matcher.only {
return title_only.iter().any(|m| m.matches(title));
}
if let Some(title_not) = &window_matcher.not {
return title_not.iter().all(|m| !m.matches(title));
}
}
false
}
fn match_application(&mut self, application_matcher: &Application) -> bool { fn match_application(&mut self, application_matcher: &OnlyOrNot) -> bool {
// Lazily fill the wm_class cache // Lazily fill the wm_class cache
if self.application_cache.is_none() { if self.application_cache.is_none() {
match self.application_client.current_application() { match self.application_client.current_application() {

@ -31,19 +31,19 @@ mod event_handler;
mod tests; mod tests;
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
#[clap(version)] #[command(version)]
struct Args { struct Args {
/// Include a device name or path /// Include a device name or path
#[clap(long, use_value_delimiter = true)] #[arg(long, value_delimiter = ',')]
device: Vec<String>, device: Vec<String>,
/// Ignore a device name or path /// Ignore a device name or path
#[clap(long, use_value_delimiter = true)] #[arg(long, value_delimiter = ',')]
ignore: Vec<String>, ignore: Vec<String>,
/// Match mice by default /// Match mice by default
#[clap(long)] #[arg(long)]
mouse: bool, mouse: bool,
/// Targets to watch /// Targets to watch
#[clap(long, value_enum, num_args = 0.., use_value_delimiter = true, require_equals = true, #[arg(long, value_enum, num_args = 0.., value_delimiter = ',', require_equals = true,
default_missing_value = "device", verbatim_doc_comment)] default_missing_value = "device", verbatim_doc_comment)]
watch: Vec<WatchTargets>, watch: Vec<WatchTargets>,
/// Generate shell completions /// Generate shell completions
@ -51,10 +51,10 @@ struct Args {
/// You can use them by storing in your shells completion file or by running /// You can use them by storing in your shells completion file or by running
/// - in bash: eval "$(xremap --completions bash)" /// - in bash: eval "$(xremap --completions bash)"
/// - in fish: xremap --completions fish | source /// - in fish: xremap --completions fish | source
#[clap(long, value_enum, display_order = 100, value_name = "SHELL", verbatim_doc_comment)] #[arg(long, value_enum, display_order = 100, value_name = "SHELL", verbatim_doc_comment)]
completions: Option<Shell>, completions: Option<Shell>,
/// Config file(s) /// Config file(s)
#[clap(required_unless_present = "completions", num_args = 1..)] #[arg(required_unless_present = "completions", num_args = 1..)]
configs: Vec<PathBuf>, configs: Vec<PathBuf>,
} }
@ -122,10 +122,11 @@ fn main() -> anyhow::Result<()> {
let config_watcher = config_watcher(watch_config, &config_paths).context("Setting up config watcher")?; let config_watcher = config_watcher(watch_config, &config_paths).context("Setting up config watcher")?;
let watchers: Vec<_> = device_watcher.iter().chain(config_watcher.iter()).collect(); let watchers: Vec<_> = device_watcher.iter().chain(config_watcher.iter()).collect();
let mut handler = EventHandler::new(timer, &config.default_mode, delay, build_client()); let mut handler = EventHandler::new(timer, &config.default_mode, delay, build_client());
let output_device = match output_device(input_devices.values().next().map(InputDevice::bus_type), mouse) { let output_device =
Ok(output_device) => output_device, match output_device(input_devices.values().next().map(InputDevice::bus_type), config.enable_wheel) {
Err(e) => bail!("Failed to prepare an output device: {}", e), Ok(output_device) => output_device,
}; Err(e) => bail!("Failed to prepare an output device: {}", e),
};
let mut dispatcher = ActionDispatcher::new(output_device); let mut dispatcher = ActionDispatcher::new(output_device);
// Main loop // Main loop

@ -23,6 +23,9 @@ impl Client for StaticClient {
fn supported(&mut self) -> bool { fn supported(&mut self) -> bool {
true true
} }
fn current_window(&mut self) -> Option<String> {
None
}
fn current_application(&mut self) -> Option<String> { fn current_application(&mut self) -> Option<String> {
self.current_application.clone() self.current_application.clone()

Loading…
Cancel
Save