mirror of
https://github.com/LGUG2Z/komorebi.git
synced 2026-01-16 06:16:43 +01:00
Compare commits
78 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6308414129 | ||
|
|
035e77bd25 | ||
|
|
7b98b563eb | ||
|
|
5fda4a39b8 | ||
|
|
3ad0ae6aca | ||
|
|
2575ca2da4 | ||
|
|
37f1a163cc | ||
|
|
91c532d9b1 | ||
|
|
75d72522a2 | ||
|
|
438bfc86ff | ||
|
|
ca86418e3c | ||
|
|
d8c76b97a9 | ||
|
|
a4be1b95e0 | ||
|
|
6e666bc4d8 | ||
|
|
857b3c9ccf | ||
|
|
9b916c0c21 | ||
|
|
b642eddb96 | ||
|
|
1229c65580 | ||
|
|
b25cc1c8bf | ||
|
|
e02ddd47cc | ||
|
|
e20b4aabc3 | ||
|
|
acaee5595d | ||
|
|
083a142597 | ||
|
|
1633a5ebc2 | ||
|
|
352c010021 | ||
|
|
33965f92ad | ||
|
|
635272fc10 | ||
|
|
5354e9c7a4 | ||
|
|
e35164f106 | ||
|
|
a637eefd82 | ||
|
|
db361f36db | ||
|
|
577fa0a97f | ||
|
|
f8ada73739 | ||
|
|
ffcc2f71d1 | ||
|
|
ed79793002 | ||
|
|
afb819a383 | ||
|
|
3438818999 | ||
|
|
611e4cc4a8 | ||
|
|
27490de0d1 | ||
|
|
5112a8f39d | ||
|
|
c3f77ef4f8 | ||
|
|
33520a46b5 | ||
|
|
0903be7931 | ||
|
|
e78e6b1382 | ||
|
|
adafa32488 | ||
|
|
329b3052a4 | ||
|
|
b25662fea2 | ||
|
|
edc9b0cd3d | ||
|
|
a43eb8fbf5 | ||
|
|
8b0f1d007f | ||
|
|
83a502f199 | ||
|
|
5006aa9009 | ||
|
|
e4a8117a94 | ||
|
|
748c389b34 | ||
|
|
26a18adeb4 | ||
|
|
5d094f601f | ||
|
|
5a0ba4cdbb | ||
|
|
7c41460b14 | ||
|
|
d34a561753 | ||
|
|
04146a3ce9 | ||
|
|
09a544b45b | ||
|
|
0e1ad164d4 | ||
|
|
cec8b04ffd | ||
|
|
f4b3d568ee | ||
|
|
d3dc193d29 | ||
|
|
441bfce053 | ||
|
|
458d1ef80a | ||
|
|
be5945c64b | ||
|
|
38ce38d65c | ||
|
|
6ed52c9387 | ||
|
|
e466a17877 | ||
|
|
f5def84010 | ||
|
|
12473aa41c | ||
|
|
33d1c0edbc | ||
|
|
8d346627d5 | ||
|
|
be83b4b5f2 | ||
|
|
f7ac1d0ece | ||
|
|
2ba3ca4f31 |
2
.github/dependabot.yml
vendored
2
.github/dependabot.yml
vendored
@@ -13,7 +13,7 @@ updates:
|
||||
- package-ecosystem: "cargo"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "weekly"
|
||||
assignees:
|
||||
- "LGUG2Z"
|
||||
commit-message:
|
||||
|
||||
28
.github/workflows/windows.yaml
vendored
28
.github/workflows/windows.yaml
vendored
@@ -76,6 +76,10 @@ jobs:
|
||||
- name: Run a full build
|
||||
run: |
|
||||
cargo build --locked --release --target ${{ matrix.target }}
|
||||
- name: Create MSI installer
|
||||
run: |
|
||||
cargo install cargo-wix
|
||||
cargo wix -p komorebi --nocapture -I .\wix\main.wxs --target x86_64-pc-windows-msvc
|
||||
- name: Upload the built artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
@@ -85,19 +89,39 @@ jobs:
|
||||
target/${{ matrix.target }}/release/komorebic.exe
|
||||
target/${{ matrix.target }}/release/komorebi.pdb
|
||||
target/${{ matrix.target }}/release/komorebic.pdb
|
||||
target/wix/komorebi-*.msi
|
||||
retention-days: 7
|
||||
|
||||
# Release
|
||||
- name: Generate changelog
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
shell: bash
|
||||
run: |
|
||||
if ! type kokai >/dev/null; then cargo install --locked kokai --force; fi
|
||||
kokai release --no-emoji --add-links github:commits,issues --ref "$(git tag --points-at HEAD)" >"CHANGELOG.md"
|
||||
- name: Run GoReleaser
|
||||
uses: goreleaser/goreleaser-action@v3
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
with:
|
||||
version: latest
|
||||
args: release --skip-validate --rm-dist --release-notes=CHANGELOG.md
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
SCOOP_TOKEN: ${{ secrets.SCOOP_TOKEN }}
|
||||
- name: Add MSI to release
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
with:
|
||||
files: "target/wix/komorebi-*.msi"
|
||||
|
||||
winget:
|
||||
name: Publish to WinGet
|
||||
runs-on: windows-latest
|
||||
needs: build
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
|
||||
steps:
|
||||
- uses: vedantmgoyal2009/winget-releaser@v1
|
||||
with:
|
||||
identifier: LGUG2Z.komorebi
|
||||
token: ${{ secrets.WINGET_TOKEN }}
|
||||
|
||||
@@ -35,11 +35,10 @@ archives:
|
||||
name_template: "{{ .ProjectName }}-{{ .Version }}-{{ .Arch }}-{{ .Os }}"
|
||||
files:
|
||||
- LICENSE
|
||||
- komorebi.sample.ahk
|
||||
- CHANGELOG.md
|
||||
|
||||
checksum:
|
||||
name_template: checksums.txt
|
||||
|
||||
changelog:
|
||||
sort: asc
|
||||
sort: asc
|
||||
|
||||
419
Cargo.lock
generated
419
Cargo.lock
generated
@@ -17,15 +17,6 @@ version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||
|
||||
[[package]]
|
||||
name = "ansi_term"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
|
||||
dependencies = [
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
@@ -66,9 +57,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.73"
|
||||
version = "1.0.76"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
|
||||
checksum = "76a284da2e6fe2092f2353e51713435363112dfd60030e22add80be333fb928f"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
@@ -84,27 +75,25 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "3.2.16"
|
||||
version = "4.0.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a3dbbb6653e7c55cc8595ad3e1f7be8f32aba4eb7ff7f0fd1163d4f3d137c0a9"
|
||||
checksum = "91b9970d7505127a162fdaa9b96428d28a479ba78c9ec7550a63a5d9863db682"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"bitflags",
|
||||
"clap_derive",
|
||||
"clap_lex",
|
||||
"indexmap",
|
||||
"once_cell",
|
||||
"strsim",
|
||||
"termcolor",
|
||||
"terminal_size",
|
||||
"textwrap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "3.2.15"
|
||||
version = "4.0.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ba52acd3b0a5c33aeada5cdaa3267cdc7c594a98731d4268cdc1532f4264cb4"
|
||||
checksum = "0177313f9f02afc995627906bbd8967e2be069f5261954222dac78290c2b9014"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro-error",
|
||||
@@ -115,9 +104,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.2.4"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5"
|
||||
checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8"
|
||||
dependencies = [
|
||||
"os_str_bytes",
|
||||
]
|
||||
@@ -178,33 +167,31 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.10"
|
||||
version = "0.9.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "045ebe27666471bb549370b4b0b3e51b07f56325befa4284db65fc89c02511b1"
|
||||
checksum = "f916dfc5d356b0ed9dae65f1db9fc9770aa2851d2662b988ccf4fe3516e86348"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cfg-if 1.0.0",
|
||||
"crossbeam-utils",
|
||||
"memoffset",
|
||||
"once_cell",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.11"
|
||||
version = "0.8.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc"
|
||||
checksum = "edbafec5fa1f196ca66527c1b12c2ec4745ca14b50f1ad8f9f6f720b55d11fac"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ctrlc"
|
||||
version = "3.2.2"
|
||||
version = "3.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b37feaa84e6861e00a1f5e5aa8da3ee56d605c9992d33e082786754828e20865"
|
||||
checksum = "1d91974fbbe88ec1df0c24a4f00f99583667a7e2e6272b2b92d294d81e462173"
|
||||
dependencies = [
|
||||
"nix",
|
||||
"winapi 0.3.9",
|
||||
@@ -212,7 +199,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "derive-ahk"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -247,9 +234,30 @@ checksum = "4f94fa09c2aeea5b8839e414b7b841bf429fd25b9c522116ac97ee87856d88b2"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.7.0"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be"
|
||||
checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1"
|
||||
dependencies = [
|
||||
"errno-dragonfly",
|
||||
"libc",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "errno-dragonfly"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "eyre"
|
||||
@@ -272,14 +280,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "filetime"
|
||||
version = "0.2.17"
|
||||
version = "0.2.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e94a7bbaa59354bc20dd75b67f23e2797b4490e9d6928203fb105c79e448c86c"
|
||||
checksum = "4b9663d381d07ae25dc88dbdf27df458faa83a9b25336bcac83d5e452b5fc9d3"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"windows-sys 0.36.1",
|
||||
"windows-sys 0.42.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -334,9 +342,9 @@ checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.7"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
|
||||
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
@@ -437,6 +445,12 @@ dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "io-lifetimes"
|
||||
version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59ce5ef949d49ee85593fc4d3f3f95ad61657076395cbbce23e2121fc5542074"
|
||||
|
||||
[[package]]
|
||||
name = "iovec"
|
||||
version = "0.1.4"
|
||||
@@ -448,9 +462,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.3"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754"
|
||||
checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc"
|
||||
|
||||
[[package]]
|
||||
name = "kernel32-sys"
|
||||
@@ -464,7 +478,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "komorebi"
|
||||
version = "0.1.12"
|
||||
version = "0.1.14"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"clap",
|
||||
@@ -479,6 +493,7 @@ dependencies = [
|
||||
"lazy_static",
|
||||
"miow 0.4.0",
|
||||
"nanoid",
|
||||
"net2",
|
||||
"os_info",
|
||||
"parking_lot",
|
||||
"paste",
|
||||
@@ -499,7 +514,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "komorebi-core"
|
||||
version = "0.1.12"
|
||||
version = "0.1.14"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"color-eyre",
|
||||
@@ -513,7 +528,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "komorebic"
|
||||
version = "0.1.12"
|
||||
version = "0.1.14"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"color-eyre",
|
||||
@@ -528,6 +543,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_yaml",
|
||||
"sysinfo",
|
||||
"uds_windows",
|
||||
"windows",
|
||||
]
|
||||
@@ -546,15 +562,21 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.129"
|
||||
version = "0.2.137"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "64de3cc433455c14174d42e554d4027ee631c4d046d43e3ecc6efc4636cdc7a7"
|
||||
checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.0.46"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4d2456c373231a208ad294c33dc5bff30051eafd954cd4caae83a712b12854d"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.7"
|
||||
version = "0.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53"
|
||||
checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"scopeguard",
|
||||
@@ -595,9 +617,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.5.3"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc"
|
||||
checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34"
|
||||
dependencies = [
|
||||
"adler",
|
||||
]
|
||||
@@ -665,9 +687,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "net2"
|
||||
version = "0.2.37"
|
||||
version = "0.2.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae"
|
||||
checksum = "74d0df99cfcd2530b2e694f6e17e7f37b8e26bb23983ac530c0c97408837c631"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10",
|
||||
"libc",
|
||||
@@ -676,10 +698,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.24.2"
|
||||
version = "0.25.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "195cdbc1741b8134346d515b3a56a1c94b0912758009cfd53f99ea0f57b065fc"
|
||||
checksum = "e322c04a9e3440c327fca7b6c8a63e6890a32fa2ad689db972425f07e0d22abb"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"bitflags",
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
@@ -705,29 +728,30 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ntapi"
|
||||
version = "0.3.7"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f"
|
||||
checksum = "bc51db7b362b205941f71232e56c625156eb9a929f8cf74a428fd5bc094a4afc"
|
||||
dependencies = [
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.13.1"
|
||||
name = "nu-ansi-term"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
|
||||
checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"overload",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_threads"
|
||||
version = "0.1.6"
|
||||
name = "num_cpus"
|
||||
version = "1.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44"
|
||||
checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
]
|
||||
|
||||
@@ -742,15 +766,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.13.0"
|
||||
version = "1.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1"
|
||||
checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
|
||||
|
||||
[[package]]
|
||||
name = "os_info"
|
||||
version = "3.5.0"
|
||||
version = "3.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5209b2162b2c140df493a93689e04f8deab3a67634f5bc7a553c0a98e5b8d399"
|
||||
checksum = "c4750134fb6a5d49afc80777394ad5d95b04bc12068c6abb92fae8f43817270f"
|
||||
dependencies = [
|
||||
"log",
|
||||
"serde",
|
||||
@@ -759,15 +783,21 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "os_str_bytes"
|
||||
version = "6.2.0"
|
||||
version = "6.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "648001efe5d5c0102d8cea768e348da85d90af8ba91f0bea908f157951493cd4"
|
||||
checksum = "3baf96e39c5359d2eb0dd6ccb42c62b91d9678aa68160d261b9e0ccbf9e9dea9"
|
||||
|
||||
[[package]]
|
||||
name = "overload"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
|
||||
|
||||
[[package]]
|
||||
name = "owo-colors"
|
||||
version = "3.4.0"
|
||||
version = "3.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "decf7381921fea4dcb2549c5667eda59b3ec297ab7e2b5fc33eac69d2e7da87b"
|
||||
checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
@@ -781,9 +811,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.9.3"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929"
|
||||
checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"cfg-if 1.0.0",
|
||||
@@ -792,14 +822,14 @@ dependencies = [
|
||||
"redox_syscall",
|
||||
"smallvec",
|
||||
"thread-id",
|
||||
"windows-sys 0.36.1",
|
||||
"windows-sys 0.42.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "paste"
|
||||
version = "1.0.8"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9423e2b32f7a043629287a536f21951e8c6a82482d0acb1eeebfc90bc2225b22"
|
||||
checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1"
|
||||
|
||||
[[package]]
|
||||
name = "petgraph"
|
||||
@@ -819,15 +849,15 @@ checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
|
||||
|
||||
[[package]]
|
||||
name = "powershell_script"
|
||||
version = "1.0.2"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d5c8599ccb442b80c8c04437bcbcac2f76ff34d7b658b759fb26744dcab6c03"
|
||||
checksum = "54bde2e1a395c0aee9423072d781610da37b7b120edf17d4da99f83d04f2cd54"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.16"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
|
||||
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
@@ -855,9 +885,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.43"
|
||||
version = "1.0.47"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
|
||||
checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
@@ -894,9 +924,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.3"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
@@ -947,9 +977,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.6.0"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
|
||||
checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a"
|
||||
dependencies = [
|
||||
"regex-syntax",
|
||||
]
|
||||
@@ -965,9 +995,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.27"
|
||||
version = "0.6.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
|
||||
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
|
||||
|
||||
[[package]]
|
||||
name = "remove_dir_all"
|
||||
@@ -984,6 +1014,20 @@ version = "0.1.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.35.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "727a1a6d65f786ec22df8a81ca3121107f235970dc1705ed681d3e6e8b9cd5f9"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"errno",
|
||||
"io-lifetimes",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys 0.42.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.9"
|
||||
@@ -1007,9 +1051,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "schemars"
|
||||
version = "0.8.10"
|
||||
version = "0.8.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1847b767a3d62d95cbf3d8a9f0e421cf57a0d8aa4f411d4b16525afb0284d4ed"
|
||||
checksum = "2a5fb6c61f29e723026dc8e923d94c694313212abbecbbe5f55a7748eec5b307"
|
||||
dependencies = [
|
||||
"dyn-clone",
|
||||
"schemars_derive",
|
||||
@@ -1019,9 +1063,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "schemars_derive"
|
||||
version = "0.8.10"
|
||||
version = "0.8.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af4d7e1b012cb3d9129567661a63755ea4b8a7386d339dc945ae187e403c6743"
|
||||
checksum = "f188d036977451159430f3b8dc82ec76364a42b7e289c2b18a9a18f4470058e9"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1037,18 +1081,18 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.143"
|
||||
version = "1.0.147"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53e8e5d5b70924f74ff5c6d64d9a5acd91422117c60f48c4e07855238a254553"
|
||||
checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.143"
|
||||
version = "1.0.147"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3d8e8de557aee63c26b85b947f5e59b690d0454c753f3adeb5cd7835ab88391"
|
||||
checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1068,9 +1112,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.83"
|
||||
version = "1.0.87"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38dd04e3c8279e75b31ef29dbdceebfe5ad89f4d0937213c53f7d49d01b3d5a7"
|
||||
checksum = "6ce777b7b150d76b9cf60d28b55f5847135a003f7d7350c6be7a773508ce7d45"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
@@ -1079,9 +1123,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_yaml"
|
||||
version = "0.9.4"
|
||||
version = "0.9.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79b7c9017c64a49806c6e8df8ef99b92446d09c92457f85f91835b01a8064ae0"
|
||||
checksum = "6d232d893b10de3eb7258ff01974d6ee20663d8e833263c99409d4b13a0209da"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"itoa",
|
||||
@@ -1110,9 +1154,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.9.0"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1"
|
||||
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
@@ -1144,9 +1188,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.99"
|
||||
version = "1.0.103"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13"
|
||||
checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1155,9 +1199,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sysinfo"
|
||||
version = "0.25.2"
|
||||
version = "0.26.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1594a36887d0f70096702bffadfb67dfbfe76ad4bf84605e86157dc9fce9961a"
|
||||
checksum = "c375d5fd899e32847b8566e10598d6e9f1d9b55ec6de3cdf9e7da4bdc51371bc"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"core-foundation-sys",
|
||||
@@ -1193,37 +1237,28 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "terminal_size"
|
||||
version = "0.1.17"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df"
|
||||
checksum = "40ca90c434fd12083d1a6bdcbe9f92a14f96c8a1ba600ba451734ac334521f7a"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"
|
||||
dependencies = [
|
||||
"terminal_size",
|
||||
"rustix",
|
||||
"windows-sys 0.42.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.32"
|
||||
version = "1.0.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f5f6586b7f764adc0231f4c79be7b920e766bb2f3e51b3661cdb263828f19994"
|
||||
checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.32"
|
||||
version = "1.0.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12bafc5b54507e0149cdf1b145a5d80ab80a90bcd9275df43d4fff68460f6c21"
|
||||
checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1252,20 +1287,36 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.13"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db76ff9fa4b1458b3c7f077f3ff9887394058460d21e634355b273aaf11eea45"
|
||||
checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"libc",
|
||||
"num_threads",
|
||||
"serde",
|
||||
"time-core",
|
||||
"time-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time-core"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd"
|
||||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2"
|
||||
dependencies = [
|
||||
"time-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
version = "0.1.36"
|
||||
version = "0.1.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307"
|
||||
checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"pin-project-lite",
|
||||
@@ -1286,9 +1337,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tracing-attributes"
|
||||
version = "0.1.22"
|
||||
version = "0.1.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "11c75893af559bc8e10716548bdef5cb2b983f8e637db9d0e15126b61b484ee2"
|
||||
checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1297,9 +1348,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tracing-core"
|
||||
version = "0.1.29"
|
||||
version = "0.1.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7"
|
||||
checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"valuable",
|
||||
@@ -1328,12 +1379,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tracing-subscriber"
|
||||
version = "0.3.15"
|
||||
version = "0.3.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60db860322da191b40952ad9affe65ea23e7dd6a5c442c2c42865810c6ab8e6b"
|
||||
checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70"
|
||||
dependencies = [
|
||||
"ansi_term",
|
||||
"matchers",
|
||||
"nu-ansi-term",
|
||||
"once_cell",
|
||||
"regex",
|
||||
"sharded-slab",
|
||||
@@ -1356,15 +1407,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.3"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf"
|
||||
checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
|
||||
|
||||
[[package]]
|
||||
name = "unsafe-libyaml"
|
||||
version = "0.2.2"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "931179334a56395bcf64ba5e0ff56781381c1a5832178280c7d7f91d1679aeb0"
|
||||
checksum = "c1e5fa573d8ac5f1a856f8d7be41d390ee973daf97c806b2c1a465e4e1406e68"
|
||||
|
||||
[[package]]
|
||||
name = "valuable"
|
||||
@@ -1397,13 +1448,13 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "which"
|
||||
version = "4.2.5"
|
||||
version = "4.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c4fb54e6113b6a8772ee41c3404fb0301ac79604489467e0a9ce1f3e97c24ae"
|
||||
checksum = "1c831fbbee9e129a8cf93e7747a82da9d95ba8e16621cae60ec2cdc849bacb7b"
|
||||
dependencies = [
|
||||
"either",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1451,15 +1502,17 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.39.0"
|
||||
version = "0.43.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1c4bd0a50ac6020f65184721f758dba47bb9fbc2133df715ec74a237b26794a"
|
||||
checksum = "04662ed0e3e5630dfa9b26e4cb823b817f1a9addda855d973a9458c236556244"
|
||||
dependencies = [
|
||||
"windows_aarch64_msvc 0.39.0",
|
||||
"windows_i686_gnu 0.39.0",
|
||||
"windows_i686_msvc 0.39.0",
|
||||
"windows_x86_64_gnu 0.39.0",
|
||||
"windows_x86_64_msvc 0.39.0",
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc 0.42.0",
|
||||
"windows_i686_gnu 0.42.0",
|
||||
"windows_i686_msvc 0.42.0",
|
||||
"windows_x86_64_gnu 0.42.0",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc 0.42.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1477,17 +1530,25 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.36.1"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
|
||||
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
|
||||
dependencies = [
|
||||
"windows_aarch64_msvc 0.36.1",
|
||||
"windows_i686_gnu 0.36.1",
|
||||
"windows_i686_msvc 0.36.1",
|
||||
"windows_x86_64_gnu 0.36.1",
|
||||
"windows_x86_64_msvc 0.36.1",
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc 0.42.0",
|
||||
"windows_i686_gnu 0.42.0",
|
||||
"windows_i686_msvc 0.42.0",
|
||||
"windows_x86_64_gnu 0.42.0",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc 0.42.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.28.0"
|
||||
@@ -1496,15 +1557,9 @@ checksum = "52695a41e536859d5308cc613b4a022261a274390b25bd29dfff4bf08505f3c2"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.36.1"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.39.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec7711666096bd4096ffa835238905bb33fb87267910e154b18b44eaabb340f2"
|
||||
checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
@@ -1514,15 +1569,9 @@ checksum = "f54725ac23affef038fecb177de6c9bf065787c2f432f79e3c373da92f3e1d8a"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.36.1"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.39.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "763fc57100a5f7042e3057e7e8d9bdd7860d330070251a73d003563a3bb49e1b"
|
||||
checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
@@ -1532,15 +1581,9 @@ checksum = "51d5158a43cc43623c0729d1ad6647e62fa384a3d135fd15108d37c683461f64"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.36.1"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.39.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7bc7cbfe58828921e10a9f446fcaaf649204dcfe6c1ddd712c5eebae6bda1106"
|
||||
checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
@@ -1550,15 +1593,15 @@ checksum = "bc31f409f565611535130cfe7ee8e6655d3fa99c1c61013981e491921b5ce954"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.36.1"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
|
||||
checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.39.0"
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6868c165637d653ae1e8dc4d82c25d4f97dd6605eaa8d784b5c6e0ab2a252b65"
|
||||
checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
@@ -1568,15 +1611,9 @@ checksum = "3f2b8c7cbd3bfdddd9ab98769f9746a7fad1bca236554cd032b78d768bc0e89f"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.36.1"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.39.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e4d40883ae9cae962787ca76ba76390ffa29214667a111db9e0a1ad8377e809"
|
||||
checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
|
||||
|
||||
[[package]]
|
||||
name = "winput"
|
||||
|
||||
179
README.md
179
README.md
@@ -2,12 +2,27 @@
|
||||
|
||||
Tiling Window Management for Windows.
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
<p>
|
||||
<img alt="GitHub Workflow Status" src="https://img.shields.io/github/workflow/status/LGUG2Z/komorebi/Windows">
|
||||
<img alt="GitHub" src="https://img.shields.io/github/license/LGUG2Z/komorebi">
|
||||
<img alt="GitHub all releases" src="https://img.shields.io/github/downloads/LGUG2Z/komorebi/total">
|
||||
<img alt="GitHub commits since latest release (by date) for a branch" src="https://img.shields.io/github/commits-since/LGUG2Z/komorebi/latest">
|
||||
<a href="https://discord.gg/mGkn66PHkx">
|
||||
<img alt="Discord" src="https://img.shields.io/discord/898554690126630914">
|
||||
</a>
|
||||
<a href="https://github.com/sponsors/LGUG2Z">
|
||||
<img alt="GitHub Sponsors" src="https://img.shields.io/github/sponsors/LGUG2Z">
|
||||
</a>
|
||||
<a href="https://notado.app/feeds/jado/software-development">
|
||||
<img alt="Notado Feed" src="https://img.shields.io/badge/Notado-Subscribe-informational">
|
||||
</a>
|
||||
<a href="https://jeezy.substack.com">
|
||||
<img alt="Substack Read" src="https://img.shields.io/badge/Substack-Read-orange">
|
||||
</a>
|
||||
<a href="https://twitter.com/LGUG2Z">
|
||||
<img alt="Twitter Follow" src="https://img.shields.io/twitter/follow/LGUG2Z">
|
||||
</a>
|
||||
</p>
|
||||
|
||||

|
||||
|
||||
@@ -33,6 +48,7 @@ Articles, blog posts, demos, and videos about _komorebi_ can be added to this li
|
||||
|
||||
- [Moving to Windows from Linux Pt 1](https://kvwu.io/posts/moving-to-windows/)
|
||||
- [Windows 下的现代化平铺窗口管理器 komorebi](https://zhuanlan.zhihu.com/p/455064481)
|
||||
- [komorebi を導入してみる](https://zenn.dev/omochice/articles/50f42a3df8f426)
|
||||
|
||||
## GitHub Sponsors Early Access
|
||||
|
||||
@@ -46,6 +62,15 @@ available for free in the public repository once it meets the requisite level of
|
||||
Features-in-progress that are available in early access will be tagged in the issues with
|
||||
an ["early access" label](https://github.com/LGUG2Z/komorebi/issues?q=is%3Aopen+is%3Aissue+label%3A%22early+access%22).
|
||||
|
||||
## Charitable Donations
|
||||
|
||||
`komorebi`, like `vim`, is a free and open-source project, and one that encourages you to make charitable donations if
|
||||
you find the software to be useful and have the financial means.
|
||||
|
||||
I encourage you to make a charitable donation
|
||||
to [Fresh Start Refugee](https://www.freshstartrefugee.org/donate) before
|
||||
you consider sponsoring me on GitHub.
|
||||
|
||||
## Demonstrations
|
||||
|
||||
[@haxibami](https://github.com/haxibami) showing _komorebi_ running on Windows
|
||||
@@ -119,6 +144,14 @@ using [`setx`](https://docs.microsoft.com/en-us/windows-server/administration/wi
|
||||
Variables pop up in System Properties Advanced (which can be launched with `SystemPropertiesAdvanced.exe` at a
|
||||
PowerShell prompt), and then move the binaries to that directory.
|
||||
|
||||
### Winget
|
||||
|
||||
You can use the builtin package manager from Windows to install the latest komorebi release:
|
||||
|
||||
```powershell
|
||||
winget install LGUG2Z.komorebi
|
||||
```
|
||||
|
||||
### Scoop
|
||||
|
||||
If you use the [Scoop](https://scoop.sh/) command line installer, you can run the following commands to install the
|
||||
@@ -127,10 +160,14 @@ binaries from the latest GitHub Release:
|
||||
```powershell
|
||||
scoop bucket add extras
|
||||
scoop install komorebi
|
||||
|
||||
# To download the example configuration
|
||||
iwr https://raw.githubusercontent.com/LGUG2Z/komorebi/master/komorebi.sample.ahk -OutFile $Env:USERPROFILE\komorebi.ahk
|
||||
iwr https://raw.githubusercontent.com/LGUG2Z/komorebi/master/komorebic.lib.ahk -OutFile $Env:USERPROFILE\komorebic.lib.ahk
|
||||
iwr https://raw.githubusercontent.com/LGUG2Z/komorebi/master/komorebi.generated.ahk -OutFile $Env:USERPROFILE\komorebi.generated.ahk
|
||||
```
|
||||
|
||||
If you install _komorebi_ using Scoop, the binaries will automatically be added to your `Path` and a command will be
|
||||
shown for you to run in order to get started using the sample configuration file.
|
||||
If you install _komorebi_ using Scoop, the binaries will automatically be added to your `Path`.
|
||||
|
||||
Thanks to [@sitiom](https://github.com/sitiom) for getting _komorebi_ added to the popular Scoop Extras bucket.
|
||||
|
||||
@@ -152,7 +189,7 @@ cargo install --path komorebic --locked
|
||||
|
||||
Once you have either the prebuilt binaries in your `Path`, or have compiled the binaries from source (these will already
|
||||
be in your `Path` if you installed Rust with [rustup](https://rustup.rs), which you absolutely should), you can
|
||||
run `komorebic start` at a Powershell prompt, and you will see the following output:
|
||||
run `komorebic start --await-configuration` at a Powershell prompt, and you will see the following output:
|
||||
|
||||
```
|
||||
Start-Process komorebi -WindowStyle hidden
|
||||
@@ -264,7 +301,10 @@ If you would like to add a visual border around the currently focused window, tw
|
||||
|
||||
```powershell
|
||||
komorebic.exe active-window-border [enable|disable]
|
||||
komorebic.exe active-window-border-colour [R G B]
|
||||
komorebic.exe active-window-border-colour [R G B] --window-kind single
|
||||
|
||||
# optionally, if you want a different colour for stacks of windows
|
||||
komorebic.exe active-window-border-colour [R G B] --window-kind stack
|
||||
```
|
||||
|
||||
It is important to note that the active window border will only apply to windows managed by `komorebi`.
|
||||
@@ -480,95 +520,6 @@ You can run `komorebic.exe` to get a full list of the commands that you can use
|
||||
keybindings with. You can run `komorebic.exe <COMMAND> --help` to get a full explanation of the arguments required for
|
||||
each command.
|
||||
|
||||
```
|
||||
start Start komorebi.exe as a background process
|
||||
stop Stop the komorebi.exe process and restore all hidden windows
|
||||
state Show a JSON representation of the current window manager state
|
||||
query Query the current window manager state
|
||||
subscribe Subscribe to komorebi events
|
||||
unsubscribe Unsubscribe from komorebi events
|
||||
log Tail komorebi.exe's process logs (cancel with Ctrl-C)
|
||||
quick-save-resize Quicksave the current resize layout dimensions
|
||||
quick-load-resize Load the last quicksaved resize layout dimensions
|
||||
save-resize Save the current resize layout dimensions to a file
|
||||
load-resize Load the resize layout dimensions from a file
|
||||
focus Change focus to the window in the specified direction
|
||||
move Move the focused window in the specified direction
|
||||
cycle-focus Change focus to the window in the specified cycle direction
|
||||
cycle-move Move the focused window in the specified cycle direction
|
||||
stack Stack the focused window in the specified direction
|
||||
resize-edge Resize the focused window in the specified direction
|
||||
resize-axis Resize the focused window or primary column along the specified axis
|
||||
unstack Unstack the focused window
|
||||
cycle-stack Cycle the focused stack in the specified cycle direction
|
||||
move-to-monitor Move the focused window to the specified monitor
|
||||
move-to-workspace Move the focused window to the specified workspace
|
||||
send-to-monitor Send the focused window to the specified monitor
|
||||
send-to-workspace Send the focused window to the specified workspace
|
||||
send-to-monitor-workspace Send the focused window to the specified monitor workspace
|
||||
focus-monitor Focus the specified monitor
|
||||
focus-workspace Focus the specified workspace on the focused monitor
|
||||
focus-monitor-workspace Focus the specified workspace on the target monitor
|
||||
cycle-monitor Focus the monitor in the given cycle direction
|
||||
cycle-workspace Focus the workspace in the given cycle direction
|
||||
move-workspace-to-monitor Move the focused workspace to the specified monitor
|
||||
new-workspace Create and append a new workspace on the focused monitor
|
||||
resize-delta Set the resize delta (used by resize-edge and resize-axis)
|
||||
invisible-borders Set the invisible border dimensions around each window
|
||||
work-area-offset Set offsets to exclude parts of the work area from tiling
|
||||
adjust-container-padding Adjust container padding on the focused workspace
|
||||
adjust-workspace-padding Adjust workspace padding on the focused workspace
|
||||
change-layout Set the layout on the focused workspace
|
||||
load-custom-layout Load a custom layout from file for the focused workspace
|
||||
flip-layout Flip the layout on the focused workspace (BSP only)
|
||||
promote Promote the focused window to the top of the tree
|
||||
retile Force the retiling of all managed windows
|
||||
ensure-workspaces Create at least this many workspaces for the specified monitor
|
||||
container-padding Set the container padding for the specified workspace
|
||||
workspace-padding Set the workspace padding for the specified workspace
|
||||
workspace-layout Set the layout for the specified workspace
|
||||
workspace-custom-layout Set a custom layout for the specified workspace
|
||||
workspace-layout-rule Add a dynamic layout rule for the specified workspace
|
||||
workspace-custom-layout-rule Add a dynamic custom layout for the specified workspace
|
||||
clear-workspace-layout-rules Clear all dynamic layout rules for the specified workspace
|
||||
workspace-tiling Enable or disable window tiling for the specified workspace
|
||||
workspace-name Set the workspace name for the specified workspace
|
||||
toggle-window-container-behaviour Toggle the behaviour for new windows (stacking or dynamic tiling)
|
||||
toggle-pause Toggle window tiling on the focused workspace
|
||||
toggle-tiling Toggle window tiling on the focused workspace
|
||||
toggle-float Toggle floating mode for the focused window
|
||||
toggle-monocle Toggle monocle mode for the focused container
|
||||
toggle-maximize Toggle native maximization for the focused window
|
||||
restore-windows Restore all hidden windows (debugging command)
|
||||
manage Force komorebi to manage the focused window
|
||||
unmanage Unmanage a window that was forcibly managed
|
||||
reload-configuration Reload ~/komorebi.ahk (if it exists)
|
||||
watch-configuration Enable or disable watching of ~/komorebi.ahk (if it exists)
|
||||
complete-configuration Signal that the final configuration option has been sent
|
||||
window-hiding-behaviour Set the window behaviour when switching workspaces / cycling stacks
|
||||
cross-monitor-move-behaviour Set the behaviour when moving windows across monitor boundaries
|
||||
toggle-cross-monitor-move-behaviour Toggle the behaviour when moving windows across monitor boundaries
|
||||
unmanaged-window-operation-behaviour Set the operation behaviour when the focused window is not managed
|
||||
float-rule Add a rule to always float the specified application
|
||||
manage-rule Add a rule to always manage the specified application
|
||||
workspace-rule Add a rule to associate an application with a workspace
|
||||
identify-object-name-change-application Identify an application that sends EVENT_OBJECT_NAMECHANGE on launch
|
||||
identify-tray-application Identify an application that closes to the system tray
|
||||
identify-layered-application Identify an application that has WS_EX_LAYERED, but should still be managed
|
||||
identify-border-overflow-application Identify an application that has overflowing borders
|
||||
active-window-border Enable or disable the active window border
|
||||
active-window-border-colour Set the colour for the active window border
|
||||
focus-follows-mouse Enable or disable focus follows mouse for the operating system
|
||||
toggle-focus-follows-mouse Toggle focus follows mouse for the operating system
|
||||
mouse-follows-focus Enable or disable mouse follows focus on all workspaces
|
||||
toggle-mouse-follows-focus Toggle mouse follows focus on all workspaces
|
||||
ahk-library Generate a library of AutoHotKey helper functions
|
||||
ahk-app-specific-configuration Generate common app-specific configurations and fixes to use in komorebi.ahk
|
||||
format-app-specific-configuration Format a YAML file for use with the 'ahk-app-specific-configuration' command
|
||||
notification-schema Generate a JSON Schema of subscription notifications
|
||||
help Print this message or the help of the given subcommand(s)
|
||||
```
|
||||
|
||||
### AutoHotKey Helper Library for `komorebic`
|
||||
|
||||
Additionally, you may run `komorebic.exe ahk-library` to
|
||||
@@ -598,7 +549,7 @@ used [is available here](komorebi.sample.with.lib.ahk).
|
||||
- [x] Resize window container in direction
|
||||
- [x] Resize window container on axis
|
||||
- [x] Set custom resize delta
|
||||
- [ ] Resize child window containers by split ratio
|
||||
- [x] Active window border
|
||||
- [x] Quicksave and quickload layouts with resize dimensions
|
||||
- [x] Save and load layouts with resize dimensions to/from specific files
|
||||
- [x] Mouse drag to swap window container position
|
||||
@@ -619,7 +570,7 @@ used [is available here](komorebi.sample.with.lib.ahk).
|
||||
- [x] Identify applications which overflow their borders by exe name and class
|
||||
- [x] Identify 'close/minimize to tray' applications by exe name and class
|
||||
- [x] Configure work area offsets to preserve space for custom taskbars
|
||||
- [x] Configure and compensate for the size of Windows 10's invisible borders
|
||||
- [x] Configure and compensate for the size of Windows invisible borders
|
||||
- [x] Toggle floating windows
|
||||
- [x] Toggle monocle window
|
||||
- [x] Toggle native maximization
|
||||
@@ -729,9 +680,35 @@ An example of how to create a named pipe and a subscription to `komorebi`'s hand
|
||||
by [@denBot](https://github.com/denBot) can be
|
||||
found [here](https://gist.github.com/denBot/4136279812f87819f86d99eba77c1ee0).
|
||||
|
||||
An example of how to create a named pipe and a subscription to `komorebi`'s handled events in Rust can also be found
|
||||
in the [`komokana`](https://github.com/LGUG2Z/komokana) repository.
|
||||
|
||||
### Subscription Event Notification Schema
|
||||
|
||||
A [JSON Schema](https://json-schema.org/) of the event notifications emitted to subscribers can be generated with
|
||||
the `komorebic notification-schema` command. The output of this command can be redirected to the clipboard or a file,
|
||||
which can be used with services such as [Quicktype](https://app.quicktype.io/) to generate type definitions in different
|
||||
programming languages.
|
||||
|
||||
### Communication over TCP
|
||||
|
||||
A TCP listener can optionally be exposed on a port of your choosing with the `--tcp-port=N` flag. If this flag is not
|
||||
provided to `komorebi` or `komorebic start`, no TCP listener will be created.
|
||||
|
||||
Once created, your client may send
|
||||
any [SocketMessage](https://github.com/LGUG2Z/komorebi/blob/master/komorebi-core/src/lib.rs#L37) to `komorebi` in the
|
||||
same way that `komorebic` would.
|
||||
|
||||
This can be used if you would like to create your own alternative to `komorebic` which incorporates scripting and
|
||||
various middleware layers, and similarly it can be used if you would like to integrate `komorebi` with
|
||||
a [custom input handler](https://github.com/LGUG2Z/komorebi/issues/176#issue-1302643961).
|
||||
|
||||
If a client sends an unrecognized message, it will be disconnected and have to reconnect before trying to communicate
|
||||
again.
|
||||
|
||||
### Socket Message Schema
|
||||
|
||||
A [JSON Schema](https://json-schema.org/) of socket messages used to send instructions to `komorebi` can be generated
|
||||
with the `komorebic socket-schema` command. The output of this command can be redirected to the clipboard or a file,
|
||||
which can be used with services such as [Quicktype](https://app.quicktype.io/) to generate type definitions in different
|
||||
programming languages.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "derive-ahk"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
|
||||
@@ -5,12 +5,15 @@
|
||||
use ::std::clone::Clone;
|
||||
use ::std::convert::From;
|
||||
use ::std::convert::Into;
|
||||
use ::std::format;
|
||||
use ::std::iter::Extend;
|
||||
use ::std::iter::Iterator;
|
||||
use ::std::matches;
|
||||
use ::std::option::Option::Some;
|
||||
use ::std::string::String;
|
||||
use ::std::string::ToString;
|
||||
use ::std::unreachable;
|
||||
use ::std::vec::Vec;
|
||||
|
||||
use ::quote::quote;
|
||||
use ::syn::parse_macro_input;
|
||||
@@ -102,7 +105,8 @@ pub fn ahk_function(input: ::proc_macro::TokenStream) -> ::proc_macro::TokenStre
|
||||
let flag_idents_clone = flag_idents.clone();
|
||||
let flags = quote! {#(--#flag_idents_clone) *}
|
||||
.to_string()
|
||||
.replace("- - ", "--");
|
||||
.replace("- - ", "--")
|
||||
.replace('_', "-");
|
||||
|
||||
let called_flag_arguments = quote! {#(%#flag_idents%) *}
|
||||
.to_string()
|
||||
@@ -110,19 +114,28 @@ pub fn ahk_function(input: ::proc_macro::TokenStream) -> ::proc_macro::TokenStre
|
||||
.replace("% ", "%")
|
||||
.replace("%%", "% %");
|
||||
|
||||
let flags_split: Vec<_> = flags.split(' ').collect();
|
||||
let flag_args_split: Vec<_> = called_flag_arguments.split(' ').collect();
|
||||
let mut consolidated_flags: Vec<String> = Vec::new();
|
||||
|
||||
for (idx, flag) in flags_split.iter().enumerate() {
|
||||
consolidated_flags.push(format!("{} {}", flag, flag_args_split[idx]));
|
||||
}
|
||||
|
||||
let all_flags = consolidated_flags.join(" ");
|
||||
|
||||
quote! {
|
||||
impl AhkFunction for #name {
|
||||
fn generate_ahk_function() -> String {
|
||||
::std::format!(r#"
|
||||
{}({}) {{
|
||||
Run, komorebic.exe {} {} {} {}, , Hide
|
||||
RunWait, komorebic.exe {} {} {}, , Hide
|
||||
}}"#,
|
||||
::std::stringify!(#name),
|
||||
#all_arguments,
|
||||
::std::stringify!(#name).to_kebab_case(),
|
||||
#called_arguments,
|
||||
#flags,
|
||||
#called_flag_arguments
|
||||
#all_flags,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -135,7 +148,7 @@ pub fn ahk_function(input: ::proc_macro::TokenStream) -> ::proc_macro::TokenStre
|
||||
fn generate_ahk_function() -> String {
|
||||
::std::format!(r#"
|
||||
{}({}) {{
|
||||
Run, komorebic.exe {} {}, , Hide
|
||||
RunWait, komorebic.exe {} {}, , Hide
|
||||
}}"#,
|
||||
::std::stringify!(#name),
|
||||
#arguments,
|
||||
@@ -181,7 +194,7 @@ pub fn ahk_library(input: ::proc_macro::TokenStream) -> ::proc_macro::TokenStrea
|
||||
stream.extend(quote! {
|
||||
v.push(::std::format!(r#"
|
||||
{}() {{
|
||||
Run, komorebic.exe {}, , Hide
|
||||
RunWait, komorebic.exe {}, , Hide
|
||||
}}"#,
|
||||
::std::stringify!(#name),
|
||||
::std::stringify!(#name).to_kebab_case()
|
||||
|
||||
7
justfile
7
justfile
@@ -8,6 +8,10 @@ fmt:
|
||||
cargo +nightly fmt
|
||||
cargo +stable clippy
|
||||
prettier --write README.md
|
||||
prettier --write .goreleaser.yml
|
||||
prettier --write .github/dependabot.yml
|
||||
prettier --write .github/FUNDING.yml
|
||||
prettier --write .github/workflows/windows.yaml
|
||||
|
||||
install-komorebic:
|
||||
cargo +stable install --path komorebic --locked
|
||||
@@ -19,7 +23,8 @@ install:
|
||||
just install-komorebic
|
||||
just install-komorebi
|
||||
komorebic ahk-library
|
||||
cat '%USERPROFILE%\.config\komorebi\komorebic.lib.ahk' > komorebic.lib.sample.ahk
|
||||
cat '%USERPROFILE%\.config\komorebi\komorebic.lib.ahk' > komorebic.lib.ahk
|
||||
cat '%USERPROFILE%\.config\komorebi\komorebi.generated.ahk' > komorebi.generated.ahk
|
||||
|
||||
run:
|
||||
just install-komorebic
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
[package]
|
||||
name = "komorebi-core"
|
||||
version = "0.1.12"
|
||||
version = "0.1.14"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "3", features = ["derive"] }
|
||||
clap = { version = "4", features = ["derive"] }
|
||||
color-eyre = "0.6"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
@@ -15,7 +15,7 @@ strum = { version = "0.24", features = ["derive"] }
|
||||
schemars = "0.8"
|
||||
|
||||
[dependencies.windows]
|
||||
version = "0.39"
|
||||
version = "0.43"
|
||||
features = [
|
||||
"Win32_Foundation",
|
||||
]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::num::NonZeroUsize;
|
||||
|
||||
use clap::ArgEnum;
|
||||
use clap::ValueEnum;
|
||||
use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
@@ -342,7 +342,9 @@ impl Arrangement for CustomLayout {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString, ArgEnum, JsonSchema)]
|
||||
#[derive(
|
||||
Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString, ValueEnum, JsonSchema,
|
||||
)]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum Axis {
|
||||
Horizontal,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use clap::ArgEnum;
|
||||
use clap::ValueEnum;
|
||||
use color_eyre::Result;
|
||||
use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
@@ -8,7 +8,7 @@ use strum::EnumString;
|
||||
|
||||
use crate::ApplicationIdentifier;
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, Display, EnumString, ArgEnum, JsonSchema)]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, Display, EnumString, ValueEnum, JsonSchema)]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum ApplicationOptions {
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
use std::num::NonZeroUsize;
|
||||
|
||||
use clap::ArgEnum;
|
||||
use clap::ValueEnum;
|
||||
use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use strum::Display;
|
||||
use strum::EnumString;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString, ArgEnum, JsonSchema)]
|
||||
#[derive(
|
||||
Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString, ValueEnum, JsonSchema,
|
||||
)]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum CycleDirection {
|
||||
Previous,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use clap::ArgEnum;
|
||||
use clap::ValueEnum;
|
||||
use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
@@ -9,7 +9,9 @@ use crate::OperationDirection;
|
||||
use crate::Rect;
|
||||
use crate::Sizing;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString, ArgEnum, JsonSchema)]
|
||||
#[derive(
|
||||
Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString, ValueEnum, JsonSchema,
|
||||
)]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum DefaultLayout {
|
||||
BSP,
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
|
||||
use clap::ArgEnum;
|
||||
use clap::ValueEnum;
|
||||
use color_eyre::Result;
|
||||
use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
@@ -51,7 +51,10 @@ pub enum SocketMessage {
|
||||
SendContainerToWorkspaceNumber(usize),
|
||||
SendContainerToMonitorWorkspaceNumber(usize, usize),
|
||||
MoveWorkspaceToMonitorNumber(usize),
|
||||
Close,
|
||||
Minimize,
|
||||
Promote,
|
||||
PromoteFocus,
|
||||
ToggleFloat,
|
||||
ToggleMonocle,
|
||||
ToggleMaximize,
|
||||
@@ -69,6 +72,7 @@ pub enum SocketMessage {
|
||||
ChangeLayoutCustom(PathBuf),
|
||||
FlipLayout(Axis),
|
||||
// Monitor and Workspace Commands
|
||||
MonitorIndexPreference(usize, i32, i32, i32, i32),
|
||||
EnsureWorkspaces(usize, usize),
|
||||
NewWorkspace,
|
||||
ToggleTiling,
|
||||
@@ -98,7 +102,7 @@ pub enum SocketMessage {
|
||||
WatchConfiguration(bool),
|
||||
CompleteConfiguration,
|
||||
ActiveWindowBorder(bool),
|
||||
ActiveWindowBorderColour(u32, u32, u32),
|
||||
ActiveWindowBorderColour(WindowKind, u32, u32, u32),
|
||||
InvisibleBorders(Rect),
|
||||
WorkAreaOffset(Rect),
|
||||
ResizeDelta(i32),
|
||||
@@ -118,6 +122,7 @@ pub enum SocketMessage {
|
||||
AddSubscriber(String),
|
||||
RemoveSubscriber(String),
|
||||
NotificationSchema,
|
||||
SocketSchema,
|
||||
}
|
||||
|
||||
impl SocketMessage {
|
||||
@@ -134,7 +139,18 @@ impl FromStr for SocketMessage {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize, Display, EnumString, ArgEnum, JsonSchema)]
|
||||
#[derive(
|
||||
Copy, Clone, Debug, Serialize, Deserialize, Display, EnumString, ValueEnum, JsonSchema,
|
||||
)]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum WindowKind {
|
||||
Single,
|
||||
Stack,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Copy, Clone, Debug, Serialize, Deserialize, Display, EnumString, ValueEnum, JsonSchema,
|
||||
)]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum StateQuery {
|
||||
FocusedMonitorIndex,
|
||||
@@ -143,7 +159,9 @@ pub enum StateQuery {
|
||||
FocusedWindowIndex,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize, Display, EnumString, ArgEnum, JsonSchema)]
|
||||
#[derive(
|
||||
Copy, Clone, Debug, Serialize, Deserialize, Display, EnumString, ValueEnum, JsonSchema,
|
||||
)]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum ApplicationIdentifier {
|
||||
@@ -152,42 +170,54 @@ pub enum ApplicationIdentifier {
|
||||
Title,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize, Display, EnumString, ArgEnum, JsonSchema)]
|
||||
#[derive(
|
||||
Copy, Clone, Debug, Serialize, Deserialize, Display, EnumString, ValueEnum, JsonSchema,
|
||||
)]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum FocusFollowsMouseImplementation {
|
||||
Komorebi,
|
||||
Windows,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString, ArgEnum, JsonSchema)]
|
||||
#[derive(
|
||||
Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString, ValueEnum, JsonSchema,
|
||||
)]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum WindowContainerBehaviour {
|
||||
Create,
|
||||
Append,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString, ArgEnum, JsonSchema)]
|
||||
#[derive(
|
||||
Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString, ValueEnum, JsonSchema,
|
||||
)]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum MoveBehaviour {
|
||||
Swap,
|
||||
Insert,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize, Display, EnumString, ArgEnum, JsonSchema)]
|
||||
#[derive(
|
||||
Copy, Clone, Debug, Serialize, Deserialize, Display, EnumString, ValueEnum, JsonSchema,
|
||||
)]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum HidingBehaviour {
|
||||
Hide,
|
||||
Minimize,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString, ArgEnum, JsonSchema)]
|
||||
#[derive(
|
||||
Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString, ValueEnum, JsonSchema,
|
||||
)]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum OperationBehaviour {
|
||||
Op,
|
||||
NoOp,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString, ArgEnum, JsonSchema)]
|
||||
#[derive(
|
||||
Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString, ValueEnum, JsonSchema,
|
||||
)]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum Sizing {
|
||||
Increase,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::num::NonZeroUsize;
|
||||
|
||||
use clap::ArgEnum;
|
||||
use clap::ValueEnum;
|
||||
use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
@@ -10,7 +10,9 @@ use strum::EnumString;
|
||||
use crate::direction::Direction;
|
||||
use crate::Axis;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString, ArgEnum, JsonSchema)]
|
||||
#[derive(
|
||||
Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString, ValueEnum, JsonSchema,
|
||||
)]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum OperationDirection {
|
||||
Left,
|
||||
|
||||
394
komorebi.generated.ahk
Normal file
394
komorebi.generated.ahk
Normal file
@@ -0,0 +1,394 @@
|
||||
; Generated by komorebic.exe
|
||||
; To use this file, add the line below to the top of your komorebi.ahk configuration file
|
||||
; #Include %A_ScriptDir%\komorebi.generated.ahk
|
||||
|
||||
; 1Password
|
||||
Run, komorebic.exe float-rule exe "1Password.exe", , Hide
|
||||
|
||||
; Adobe Creative Cloud
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application class "CreativeCloudDesktopWindowClass", , Hide
|
||||
|
||||
; ArmCord
|
||||
Run, komorebic.exe identify-border-overflow-application exe "ArmCord.exe", , Hide
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "ArmCord.exe", , Hide
|
||||
|
||||
; AutoHotkey
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "AutoHotkeyU64.exe", , Hide
|
||||
Run, komorebic.exe float-rule title "Window Spy", , Hide
|
||||
|
||||
; Beeper
|
||||
Run, komorebic.exe identify-border-overflow-application exe "Beeper.exe", , Hide
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "Beeper.exe", , Hide
|
||||
|
||||
; Bitwarden
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "Bitwarden.exe", , Hide
|
||||
|
||||
; Calculator
|
||||
Run, komorebic.exe float-rule title "Calculator", , Hide
|
||||
|
||||
; Credential Manager UI Host
|
||||
; Targets the Windows popup prompting you for a PIN instead of a password on 1Password etc.
|
||||
Run, komorebic.exe float-rule exe "CredentialUIBroker.exe", , Hide
|
||||
|
||||
; Cron
|
||||
Run, komorebic.exe identify-border-overflow-application exe "Cron.exe", , Hide
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "Cron.exe", , Hide
|
||||
|
||||
; Discord
|
||||
Run, komorebic.exe identify-border-overflow-application exe "Discord.exe", , Hide
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "Discord.exe", , Hide
|
||||
|
||||
; DiscordCanary
|
||||
Run, komorebic.exe identify-border-overflow-application exe "DiscordCanary.exe", , Hide
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "DiscordCanary.exe", , Hide
|
||||
|
||||
; DiscordDevelopment
|
||||
Run, komorebic.exe identify-border-overflow-application exe "DiscordDevelopment.exe", , Hide
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "DiscordDevelopment.exe", , Hide
|
||||
|
||||
; DiscordPTB
|
||||
Run, komorebic.exe identify-border-overflow-application exe "DiscordPTB.exe", , Hide
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "DiscordPTB.exe", , Hide
|
||||
|
||||
; ElectronMail
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "ElectronMail.exe", , Hide
|
||||
|
||||
; Element
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "Element.exe", , Hide
|
||||
|
||||
; ElevenClock
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "ElevenClock.exe", , Hide
|
||||
|
||||
; Elgato Camera Hub
|
||||
Run, komorebic.exe float-rule exe "Camera Hub.exe", , Hide
|
||||
|
||||
; Elgato Control Center
|
||||
Run, komorebic.exe float-rule exe "ControlCenter.exe", , Hide
|
||||
|
||||
; Elgato Wave Link
|
||||
Run, komorebic.exe float-rule exe "WaveLink.exe", , Hide
|
||||
|
||||
; Epic Games Launcher
|
||||
Run, komorebic.exe identify-border-overflow-application exe "EpicGamesLauncher.exe", , Hide
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "EpicGamesLauncher.exe", , Hide
|
||||
|
||||
; Flow Launcher
|
||||
Run, komorebic.exe identify-border-overflow-application exe "Flow.Launcher.exe", , Hide
|
||||
|
||||
; GOG Galaxy
|
||||
Run, komorebic.exe identify-border-overflow-application exe "GalaxyClient.exe", , Hide
|
||||
Run, komorebic.exe manage-rule exe "GalaxyClient.exe", , Hide
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "GalaxyClient.exe", , Hide
|
||||
; Targets a hidden window spawned by GOG Galaxy
|
||||
Run, komorebic.exe float-rule class "Chrome_RenderWidgetHostHWND", , Hide
|
||||
|
||||
; GoPro Webcam
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application class "GoPro Webcam", , Hide
|
||||
|
||||
; Google Chrome
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "chrome.exe", , Hide
|
||||
|
||||
; Google Drive
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "GoogleDriveFS.exe", , Hide
|
||||
|
||||
; Houdoku
|
||||
Run, komorebic.exe identify-border-overflow-application exe "Houdoku.exe", , Hide
|
||||
|
||||
; Inno Setup
|
||||
; Target hidden window spawned by Inno Setup applications
|
||||
Run, komorebic.exe float-rule class "TApplication", , Hide
|
||||
; Target Inno Setup installers
|
||||
Run, komorebic.exe float-rule class "TWizardForm", , Hide
|
||||
|
||||
; IntelliJ IDEA
|
||||
Run, komorebic.exe identify-object-name-change-application exe "idea64.exe", , Hide
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "idea64.exe", , Hide
|
||||
; Targets JetBrains IDE popups and floating windows
|
||||
Run, komorebic.exe float-rule class "SunAwtDialog", , Hide
|
||||
|
||||
; Kleopatra
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "kleopatra.exe", , Hide
|
||||
|
||||
; Kotatogram
|
||||
Run, komorebic.exe identify-border-overflow-application exe "Kotatogram.exe", , Hide
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "Kotatogram.exe", , Hide
|
||||
|
||||
; Logi Bolt
|
||||
Run, komorebic.exe float-rule exe "LogiBolt.exe", , Hide
|
||||
|
||||
; LogiTune
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "LogiTune.exe", , Hide
|
||||
Run, komorebic.exe float-rule exe "LogiTune.exe", , Hide
|
||||
|
||||
; Logitech G HUB
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "lghub.exe", , Hide
|
||||
Run, komorebic.exe identify-border-overflow-application exe "lghub.exe", , Hide
|
||||
|
||||
; Logitech Options
|
||||
Run, komorebic.exe float-rule exe "LogiOptionsUI.exe", , Hide
|
||||
|
||||
; Mailspring
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "mailspring.exe", , Hide
|
||||
|
||||
; ManyCam
|
||||
Run, komorebic.exe identify-border-overflow-application exe "ManyCam.exe", , Hide
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "ManyCam.exe", , Hide
|
||||
|
||||
; Mica For Everyone
|
||||
|
||||
; Microsoft Excel
|
||||
Run, komorebic.exe identify-border-overflow-application exe "EXCEL.EXE", , Hide
|
||||
Run, komorebic.exe identify-layered-application exe "EXCEL.EXE", , Hide
|
||||
; Targets a hidden window spawned by Microsoft Office applications
|
||||
Run, komorebic.exe float-rule class "_WwB", , Hide
|
||||
|
||||
; Microsoft Outlook
|
||||
Run, komorebic.exe identify-border-overflow-application exe "OUTLOOK.EXE", , Hide
|
||||
Run, komorebic.exe identify-layered-application exe "OUTLOOK.EXE", , Hide
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "OUTLOOK.EXE", , Hide
|
||||
|
||||
; Microsoft PowerPoint
|
||||
Run, komorebic.exe identify-border-overflow-application exe "POWERPNT.EXE", , Hide
|
||||
Run, komorebic.exe identify-layered-application exe "POWERPNT.EXE", , Hide
|
||||
|
||||
; Microsoft Teams
|
||||
; Target Teams pop-up notification windows
|
||||
Run, komorebic.exe float-rule title "Microsoft Teams Notifications", , Hide
|
||||
|
||||
; Microsoft Word
|
||||
Run, komorebic.exe identify-border-overflow-application exe "WINWORD.EXE", , Hide
|
||||
Run, komorebic.exe identify-layered-application exe "WINWORD.EXE", , Hide
|
||||
|
||||
; Modern Flyouts
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "ModernFlyoutsHost.exe", , Hide
|
||||
|
||||
; Mozilla Firefox
|
||||
Run, komorebic.exe identify-object-name-change-application exe "firefox.exe", , Hide
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "firefox.exe", , Hide
|
||||
; Targets invisible windows spawned by Firefox to show tab previews in the taskbar
|
||||
Run, komorebic.exe float-rule class "MozillaTaskbarPreviewClass", , Hide
|
||||
|
||||
; NVIDIA GeForce Experience
|
||||
Run, komorebic.exe identify-border-overflow-application exe "NVIDIA GeForce Experience.exe", , Hide
|
||||
|
||||
; NiceHash Miner
|
||||
Run, komorebic.exe identify-border-overflow-application exe "nhm_app.exe", , Hide
|
||||
Run, komorebic.exe manage-rule exe "nhm_app.exe", , Hide
|
||||
|
||||
; NohBoard
|
||||
Run, komorebic.exe float-rule exe "NohBoard.exe", , Hide
|
||||
|
||||
; Notion Enhanced
|
||||
Run, komorebic.exe identify-border-overflow-application exe "Notion Enhanced.exe", , Hide
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "Notion Enhanced.exe", , Hide
|
||||
|
||||
; OBS Studio (32-bit)
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "obs32.exe", , Hide
|
||||
|
||||
; OBS Studio (64-bit)
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "obs64.exe", , Hide
|
||||
|
||||
; ONLYOFFICE Editors
|
||||
Run, komorebic.exe identify-border-overflow-application class "DocEditorsWindowClass", , Hide
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application class "DocEditorsWindowClass", , Hide
|
||||
|
||||
; Obsidian
|
||||
Run, komorebic.exe identify-border-overflow-application exe "Obsidian.exe", , Hide
|
||||
Run, komorebic.exe manage-rule exe "Obsidian.exe", , Hide
|
||||
|
||||
; OpenRGB
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "OpenRGB.exe", , Hide
|
||||
|
||||
; Paradox Launcher
|
||||
Run, komorebic.exe float-rule exe "Paradox Launcher.exe", , Hide
|
||||
|
||||
; PowerToys
|
||||
; Target color picker dialog
|
||||
Run, komorebic.exe float-rule exe "PowerToys.ColorPickerUI.exe", , Hide
|
||||
; Target image resizer dialog
|
||||
Run, komorebic.exe float-rule exe "PowerToys.ImageResizer.exe", , Hide
|
||||
|
||||
; Process Hacker
|
||||
Run, komorebic.exe identify-border-overflow-application exe "ProcessHacker.exe", , Hide
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "ProcessHacker.exe", , Hide
|
||||
Run, komorebic.exe float-rule exe "ProcessHacker.exe", , Hide
|
||||
|
||||
; ProtonVPN
|
||||
Run, komorebic.exe identify-border-overflow-application exe "ProtonVPN.exe", , Hide
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "ProtonVPN.exe", , Hide
|
||||
|
||||
; PyCharm
|
||||
Run, komorebic.exe identify-object-name-change-application exe "pycharm64.exe", , Hide
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "pycharm64.exe", , Hide
|
||||
|
||||
; QuickLook
|
||||
Run, komorebic.exe float-rule exe "QuickLook.exe", , Hide
|
||||
|
||||
; RepoZ
|
||||
Run, komorebic.exe float-rule exe "RepoZ.exe", , Hide
|
||||
|
||||
; Roblox FPS Unlocker
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "rbxfpsunlocker.exe", , Hide
|
||||
|
||||
; RoundedTB
|
||||
Run, komorebic.exe float-rule exe "RoundedTB.exe", , Hide
|
||||
|
||||
; RoundedTB
|
||||
Run, komorebic.exe identify-border-overflow-application exe "RoundedTB.exe", , Hide
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "RoundedTB.exe", , Hide
|
||||
|
||||
; ShareX
|
||||
Run, komorebic.exe identify-border-overflow-application exe "ShareX.exe", , Hide
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "ShareX.exe", , Hide
|
||||
|
||||
; Signal
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "signal.exe", , Hide
|
||||
|
||||
; SiriKali
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "sirikali.exe", , Hide
|
||||
|
||||
; Slack
|
||||
Run, komorebic.exe identify-border-overflow-application exe "Slack.exe", , Hide
|
||||
Run, komorebic.exe manage-rule exe "Slack.exe", , Hide
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "Slack.exe", , Hide
|
||||
|
||||
; Slack
|
||||
Run, komorebic.exe identify-border-overflow-application exe "slack.exe", , Hide
|
||||
Run, komorebic.exe manage-rule exe "slack.exe", , Hide
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "slack.exe", , Hide
|
||||
|
||||
; SoulseekQt
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "SoulseekQt.exe", , Hide
|
||||
|
||||
; Spotify
|
||||
Run, komorebic.exe identify-border-overflow-application exe "Spotify.exe", , Hide
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "Spotify.exe", , Hide
|
||||
|
||||
; Steam
|
||||
Run, komorebic.exe identify-border-overflow-application class "vguiPopupWindow", , Hide
|
||||
|
||||
; SystemSettings
|
||||
Run, komorebic.exe float-rule class "Shell_Dialog", , Hide
|
||||
|
||||
; Task Manager
|
||||
Run, komorebic.exe float-rule class "TaskManagerWindow", , Hide
|
||||
|
||||
; Telegram
|
||||
Run, komorebic.exe identify-border-overflow-application exe "Telegram.exe", , Hide
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "Telegram.exe", , Hide
|
||||
|
||||
; TouchCursor
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "tcconfig.exe", , Hide
|
||||
Run, komorebic.exe float-rule exe "tcconfig.exe", , Hide
|
||||
|
||||
; TranslucentTB
|
||||
Run, komorebic.exe float-rule exe "TranslucentTB.exe", , Hide
|
||||
|
||||
; TranslucentTB
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "TranslucentTB.exe", , Hide
|
||||
|
||||
; Unreal Editor
|
||||
Run, komorebic.exe identify-border-overflow-application exe "UnrealEditor.exe", , Hide
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "UnrealEditor.exe", , Hide
|
||||
|
||||
; Visual Studio
|
||||
Run, komorebic.exe manage-rule exe "devenv.exe", , Hide
|
||||
Run, komorebic.exe float-rule class "GenericPane", , Hide
|
||||
|
||||
; Visual Studio Code
|
||||
Run, komorebic.exe identify-border-overflow-application exe "Code.exe", , Hide
|
||||
|
||||
; WebTorrent Desktop
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "WebTorrent.exe", , Hide
|
||||
|
||||
; Windows Console (conhost.exe)
|
||||
Run, komorebic.exe manage-rule class "ConsoleWindowClass", , Hide
|
||||
|
||||
; Windows Explorer
|
||||
; Targets copy/move operation windows
|
||||
Run, komorebic.exe float-rule class "OperationStatusWindow", , Hide
|
||||
Run, komorebic.exe float-rule title "Control Panel", , Hide
|
||||
|
||||
; Windows Installer
|
||||
; Targets MSI Installers
|
||||
Run, komorebic.exe float-rule class "MsiDialogCloseClass", , Hide
|
||||
|
||||
; WingetUI
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "WingetUI.exe", , Hide
|
||||
|
||||
; WingetUI
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "wingetui.exe", , Hide
|
||||
|
||||
; Wox
|
||||
; Targets a hidden window spawned by Wox
|
||||
Run, komorebic.exe float-rule title "Hotkey sink", , Hide
|
||||
|
||||
; Zoom
|
||||
Run, komorebic.exe float-rule exe "Zoom.exe", , Hide
|
||||
|
||||
; mpv.net
|
||||
Run, komorebic.exe identify-object-name-change-application exe "mpvnet.exe", , Hide
|
||||
|
||||
; paint.net
|
||||
Run, komorebic.exe float-rule exe "paintdotnet.exe", , Hide
|
||||
|
||||
; qBittorrent
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "qbittorrent.exe", , Hide
|
||||
|
||||
; ueli
|
||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||
Run, komorebic.exe identify-tray-application exe "ueli.exe", , Hide
|
||||
Run, komorebic.exe float-rule exe "ueli.exe", , Hide
|
||||
15
komorebi.iml
15
komorebi.iml
@@ -1,15 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="RUST_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/bindings/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/komorebi-core/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/komorebi/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/komorebic/src" isTestSource="false" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/target" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -1,225 +1,93 @@
|
||||
#SingleInstance Force
|
||||
|
||||
; You can generate a fresh version of this file with "komorebic ahk-library"
|
||||
#Include %A_ScriptDir%\komorebic.lib.ahk
|
||||
; https://github.com/LGUG2Z/komorebi/#generating-common-application-specific-configurations
|
||||
#Include %A_ScriptDir%\komorebi.generated.ahk
|
||||
|
||||
; Default to minimizing windows when switching workspaces
|
||||
WindowHidingBehaviour("minimize")
|
||||
|
||||
; Set cross-monitor move behaviour to insert instead of swap
|
||||
CrossMonitorMoveBehaviour("insert")
|
||||
|
||||
; Enable hot reloading of changes to this file
|
||||
Run, komorebic.exe watch-configuration enable, , Hide
|
||||
WatchConfiguration("enable")
|
||||
|
||||
; Ensure there is 1 workspace created on monitor 0
|
||||
EnsureWorkspaces(0, 1)
|
||||
|
||||
; Configure the invisible border dimensions
|
||||
Run, komorebic.exe invisible-borders 7 0 14 7, , Hide
|
||||
InvisibleBorders(7, 0, 14, 7)
|
||||
|
||||
; Enable focus follows mouse
|
||||
Run, komorebic.exe focus-follows-mouse enable, , Hide
|
||||
; Configure the 1st workspace
|
||||
WorkspaceName(0, 0, "I")
|
||||
|
||||
; Ensure there are 3 workspaces created on monitor 0
|
||||
Run, komorebic.exe ensure-workspaces 0 5, , Hide
|
||||
; Uncomment the next two lines if you want a visual border drawn around the focused window
|
||||
; ActiveWindowBorderColour(66, 165, 245, "single") ; this is a nice blue colour
|
||||
; ActiveWindowBorder("enable")
|
||||
|
||||
; Give the workspaces some optional names
|
||||
Run, komorebic.exe workspace-name 0 0 bsp, , Hide
|
||||
Run, komorebic.exe workspace-name 0 1 columns, , Hide
|
||||
Run, komorebic.exe workspace-name 0 2 thicc, , Hide
|
||||
Run, komorebic.exe workspace-name 0 3 matrix, , Hide
|
||||
Run, komorebic.exe workspace-name 0 4 floaty, , Hide
|
||||
; Allow komorebi to start managing windows
|
||||
CompleteConfiguration()
|
||||
|
||||
; Set the padding of the different workspaces
|
||||
Run, komorebic.exe workspace-padding 0 1 30, , Hide
|
||||
Run, komorebic.exe container-padding 0 1 30, , Hide
|
||||
Run, komorebic.exe workspace-padding 0 2 200, , Hide
|
||||
Run, komorebic.exe workspace-padding 0 3 0, , Hide
|
||||
Run, komorebic.exe container-padding 0 3 0, , Hide
|
||||
|
||||
; Set the layouts of different workspaces
|
||||
Run, komorebic.exe workspace-layout 0 1 columns, , Hide
|
||||
|
||||
; Set the floaty layout to not tile any windows
|
||||
Run, komorebic.exe workspace-tiling 0 4 disable, , Hide
|
||||
|
||||
; Always show chat apps on the second workspace
|
||||
Run, komorebic.exe workspace-rule exe slack.exe 0 1, , Hide
|
||||
Run, komorebic.exe workspace-rule exe Discord.exe 0 1, , Hide
|
||||
|
||||
; Always float IntelliJ popups, matching on class
|
||||
Run, komorebic.exe float-rule class SunAwtDialog, , Hide
|
||||
; Always float Control Panel, matching on title
|
||||
Run, komorebic.exe float-rule title "Control Panel", , Hide
|
||||
; Always float Task Manager, matching on class
|
||||
Run, komorebic.exe float-rule class TaskManagerWindow, , Hide
|
||||
; Always float Wally, matching on executable name
|
||||
Run, komorebic.exe float-rule exe Wally.exe, , Hide
|
||||
Run, komorebic.exe float-rule exe wincompose.exe, , Hide
|
||||
; Always float Calculator app, matching on window title
|
||||
Run, komorebic.exe float-rule title Calculator, , Hide
|
||||
Run, komorebic.exe float-rule exe 1Password.exe, , Hide
|
||||
|
||||
; Always manage forcibly these applications that don't automatically get picked up by komorebi
|
||||
Run, komorebic.exe manage-rule exe TIM.exe, , Hide
|
||||
|
||||
; Identify applications that close to the tray
|
||||
Run, komorebic.exe identify-tray-application exe Discord.exe, , Hide
|
||||
|
||||
; Identify applications that have overflowing borders
|
||||
Run, komorebic.exe identify-border-overflow exe Discord.exe, , Hide
|
||||
|
||||
; Change the focused window, Alt + Vim direction keys
|
||||
; Change the focused window, Alt + Vim direction keys (HJKL)
|
||||
!h::
|
||||
Run, komorebic.exe focus left, , Hide
|
||||
Focus("left")
|
||||
return
|
||||
|
||||
!j::
|
||||
Run, komorebic.exe focus down, , Hide
|
||||
Focus("down")
|
||||
return
|
||||
|
||||
!k::
|
||||
Run, komorebic.exe focus up, , Hide
|
||||
Focus("up")
|
||||
return
|
||||
|
||||
!l::
|
||||
Run, komorebic.exe focus right, , Hide
|
||||
Focus("right")
|
||||
return
|
||||
|
||||
; Move the focused window in a given direction, Alt + Shift + Vim direction keys
|
||||
; Move the focused window in a given direction, Alt + Shift + Vim direction keys (HJKL)
|
||||
!+h::
|
||||
Run, komorebic.exe move left, , Hide
|
||||
Move("left")
|
||||
return
|
||||
|
||||
!+j::
|
||||
Run, komorebic.exe move down, , Hide
|
||||
Move("down")
|
||||
return
|
||||
|
||||
!+k::
|
||||
Run, komorebic.exe move up, , Hide
|
||||
Move("up")
|
||||
return
|
||||
|
||||
!+l::
|
||||
Run, komorebic.exe move right, , Hide
|
||||
Move("right")
|
||||
return
|
||||
|
||||
; Stack the focused window in a given direction, Alt + Shift + direction keys
|
||||
!+Left::
|
||||
Run, komorebic.exe stack left, , Hide
|
||||
return
|
||||
|
||||
!+Down::
|
||||
Run, komorebic.exe stack down, , Hide
|
||||
return
|
||||
|
||||
!+Up::
|
||||
Run, komorebic.exe stack up, , Hide
|
||||
return
|
||||
|
||||
!+Right::
|
||||
Run, komorebic.exe stack right, , Hide
|
||||
return
|
||||
|
||||
!]::
|
||||
Run, komorebic.exe cycle-stack next, , Hide
|
||||
return
|
||||
|
||||
![::
|
||||
Run, komorebic.exe cycle-stack previous, , Hide
|
||||
return
|
||||
|
||||
; Unstack the focused window, Alt + Shift + D
|
||||
!+d::
|
||||
Run, komorebic.exe unstack, , Hide
|
||||
return
|
||||
|
||||
; Promote the focused window to the top of the tree, Alt + Shift + Enter
|
||||
!+Enter::
|
||||
Run, komorebic.exe promote, , Hide
|
||||
return
|
||||
|
||||
; Switch to an equal-width, max-height column layout on the main workspace, Alt + Shift + C
|
||||
!+c::
|
||||
Run, komorebic.exe workspace-layout 0 0 columns, , Hide
|
||||
return
|
||||
|
||||
; Switch to the default bsp tiling layout on the main workspace, Alt + Shift + T
|
||||
!+t::
|
||||
Run, komorebic.exe workspace-layout 0 0 bsp, , Hide
|
||||
return
|
||||
|
||||
; Toggle the Monocle layout for the focused window, Alt + Shift + F
|
||||
!+f::
|
||||
Run, komorebic.exe toggle-monocle, , Hide
|
||||
return
|
||||
|
||||
; Toggle native maximize for the focused window, Alt + Shift + =
|
||||
!+=::
|
||||
Run, komorebic.exe toggle-maximize, , Hide
|
||||
return
|
||||
|
||||
; Flip horizontally, Alt + X
|
||||
!x::
|
||||
Run, komorebic.exe flip-layout horizontal, , Hide
|
||||
return
|
||||
|
||||
; Flip vertically, Alt + Y
|
||||
!y::
|
||||
Run, komorebic.exe flip-layout vertical, , Hide
|
||||
return
|
||||
|
||||
; Force a retile if things get janky, Alt + Shift + R
|
||||
!+r::
|
||||
Run, komorebic.exe retile, , Hide
|
||||
return
|
||||
|
||||
; Float the focused window, Alt + T
|
||||
!t::
|
||||
Run, komorebic.exe toggle-float, , Hide
|
||||
return
|
||||
|
||||
; Reload ~/komorebi.ahk, Alt + O
|
||||
!o::
|
||||
Run, komorebic.exe reload-configuration, , Hide
|
||||
return
|
||||
|
||||
; Pause responding to any window events or komorebic commands, Alt + P
|
||||
!p::
|
||||
Run, komorebic.exe toggle-pause, , Hide
|
||||
return
|
||||
|
||||
; Switch to workspace
|
||||
!1::
|
||||
Send !
|
||||
Run, komorebic.exe focus-workspace 0, , Hide
|
||||
return
|
||||
|
||||
!2::
|
||||
Send !
|
||||
Run, komorebic.exe focus-workspace 1, , Hide
|
||||
return
|
||||
|
||||
!3::
|
||||
Send !
|
||||
Run, komorebic.exe focus-workspace 2, , Hide
|
||||
return
|
||||
|
||||
!4::
|
||||
Send !
|
||||
Run, komorebic.exe focus-workspace 3, , Hide
|
||||
return
|
||||
|
||||
!5::
|
||||
Send !
|
||||
Run, komorebic.exe focus-workspace 4, , Hide
|
||||
return
|
||||
|
||||
; Move window to workspace
|
||||
!+1::
|
||||
Run, komorebic.exe move-to-workspace 0, , Hide
|
||||
return
|
||||
|
||||
!+2::
|
||||
Run, komorebic.exe move-to-workspace 1, , Hide
|
||||
return
|
||||
|
||||
!+3::
|
||||
Run, komorebic.exe move-to-workspace 2, , Hide
|
||||
return
|
||||
|
||||
!+4::
|
||||
Run, komorebic.exe move-to-workspace 3, , Hide
|
||||
return
|
||||
|
||||
!+5::
|
||||
Run, komorebic.exe move-to-workspace 4, , Hide
|
||||
return
|
||||
; There are many more commands that you can bind to whatever keys combinations you want!
|
||||
;
|
||||
; Have a look at the komorebic.lib.ahk file to see which arguments are required by different commands
|
||||
;
|
||||
; If you want more information about a command, you can run every komorebic command with "--help"
|
||||
;
|
||||
; For example, if you see this in komorebic.lib.ahk
|
||||
;
|
||||
; WorkspaceLayout(monitor, workspace, value) {
|
||||
; Run, komorebic.exe workspace-layout %monitor% %workspace% %value%, , Hide
|
||||
; }
|
||||
;
|
||||
; Just run "komorebic.exe workspace-layout --help" and you'll get all the information you need to use the command
|
||||
;
|
||||
; komorebic.exe-workspace-layout
|
||||
; Set the layout for the specified workspace
|
||||
;
|
||||
; USAGE:
|
||||
; komorebic.exe workspace-layout <MONITOR> <WORKSPACE> <VALUE>
|
||||
;
|
||||
; ARGS:
|
||||
; <MONITOR> Monitor index (zero-indexed)
|
||||
; <WORKSPACE> Workspace index on the specified monitor (zero-indexed)
|
||||
; <VALUE> [possible values: bsp, columns, rows, vertical-stack, horizontal-stack, ultrawide-vertical-stack]
|
||||
;
|
||||
; OPTIONS:
|
||||
; -h, --help Print help information
|
||||
|
||||
@@ -1,243 +0,0 @@
|
||||
#SingleInstance Force
|
||||
#Include %A_ScriptDir%\komorebic.lib.ahk
|
||||
|
||||
; Default to minimizing windows when switching workspaces
|
||||
WindowHidingBehaviour("minimize")
|
||||
|
||||
; Enable hot reloading of changes to this file
|
||||
WatchConfiguration("enable")
|
||||
|
||||
; Ensure there are 5 workspaces created on monitor 0
|
||||
EnsureWorkspaces(0, 5)
|
||||
|
||||
; Configure the invisible border dimensions
|
||||
InvisibleBorders(7, 0, 14, 7)
|
||||
|
||||
; Configure the 1st workspace
|
||||
WorkspaceName(0, 0, "bsp")
|
||||
|
||||
; Configure the 2nd workspace
|
||||
WorkspaceName(0, 1, "columns") ; Optionally set the name of the workspace
|
||||
WorkspacePadding(0, 1, 30) ; Set the padding around the edge of the screen
|
||||
ContainerPadding(0, 1, 30) ; Set the padding between the containers on the screen
|
||||
WorkspaceRule("exe", "slack.exe", 0, 1) ; Always show chat apps on this workspace
|
||||
|
||||
; Configure the 3rd workspace
|
||||
WorkspaceName(0, 2, "thicc")
|
||||
WorkspacePadding(0, 2, 200) ; Set some super thicc padding
|
||||
|
||||
; Configure the 4th workspace
|
||||
WorkspaceName(0, 3, "matrix")
|
||||
WorkspacePadding(0, 3, 0) ; No padding at all
|
||||
ContainerPadding(0, 3, 0) ; Matrix-y hacker vibes
|
||||
|
||||
; Configure the 5th workspace
|
||||
WorkspaceName(0, 4, "floaty")
|
||||
WorkspaceTiling(0, 4, "disable") ; Everything floats here
|
||||
|
||||
; Configure floating rules
|
||||
FloatRule("class", "SunAwtDialog") ; All the IntelliJ popups
|
||||
FloatRule("title", "Control Panel")
|
||||
FloatRule("class", "TaskManagerWindow")
|
||||
FloatRule("exe", "Wally.exe")
|
||||
FloatRule("exe", "wincompose.exe")
|
||||
FloatRule("exe", "1Password.exe")
|
||||
FloatRule("exe", "Wox.exe")
|
||||
FloatRule("exe", "ddm.exe")
|
||||
FloatRule("class", "Chrome_RenderWidgetHostHWND") ; GOG Electron invisible overlay
|
||||
FloatRule("class", "CEFCLIENT")
|
||||
|
||||
; Identify Minimize-to-Tray Applications
|
||||
IdentifyTrayApplication("exe", "Discord.exe")
|
||||
IdentifyTrayApplication("exe", "Spotify.exe")
|
||||
IdentifyTrayApplication("exe", "GalaxyClient.exe")
|
||||
|
||||
; Identify Electron applications with overflowing borders
|
||||
IdentifyBorderOverflow("exe", "Discord.exe")
|
||||
IdentifyBorderOverflow("exe", "Spotify.exe")
|
||||
IdentifyBorderOverflow("exe", "GalaxyClient.exe")
|
||||
IdentifyBorderOverflow("class", "ZPFTEWndClass")
|
||||
|
||||
; Identify applications to be forcibly managed
|
||||
ManageRule("exe", "GalaxyClient.exe")
|
||||
|
||||
; Change the focused window, Alt + Vim direction keys
|
||||
!h::
|
||||
Focus("left")
|
||||
return
|
||||
|
||||
!j::
|
||||
Focus("down")
|
||||
return
|
||||
|
||||
!k::
|
||||
Focus("up")
|
||||
return
|
||||
|
||||
!l::
|
||||
Focus("right")
|
||||
return
|
||||
|
||||
; Move the focused window in a given direction, Alt + Shift + Vim direction keys
|
||||
!+h::
|
||||
Move("left")
|
||||
return
|
||||
|
||||
!+j::
|
||||
Move("down")
|
||||
return
|
||||
|
||||
!+k::
|
||||
Move("up")
|
||||
return
|
||||
|
||||
!+l::
|
||||
Move("right")
|
||||
return
|
||||
|
||||
; Stack the focused window in a given direction, Alt + Shift + direction keys
|
||||
!+Left::
|
||||
Stack("left")
|
||||
return
|
||||
|
||||
!+Down::
|
||||
Stack("down")
|
||||
return
|
||||
|
||||
!+Up::
|
||||
Stack("up")
|
||||
return
|
||||
|
||||
!+Right::
|
||||
Stack("right")
|
||||
return
|
||||
|
||||
!]::
|
||||
CycleStack("next")
|
||||
return
|
||||
|
||||
![::
|
||||
CycleStack("previous")
|
||||
return
|
||||
|
||||
; Unstack the focused window, Alt + Shift + D
|
||||
!+d::
|
||||
Unstack()
|
||||
return
|
||||
|
||||
; Promote the focused window to the top of the tree, Alt + Shift + Enter
|
||||
!+Enter::
|
||||
Promote()
|
||||
return
|
||||
|
||||
; Manage the focused window
|
||||
!=::
|
||||
Manage()
|
||||
return
|
||||
|
||||
; Unmanage the focused window
|
||||
!-::
|
||||
Unmanage()
|
||||
return
|
||||
|
||||
; Switch to an equal-width, max-height column layout on the main workspace, Alt + Shift + C
|
||||
!+c::
|
||||
ChangeLayout("columns")
|
||||
return
|
||||
|
||||
; Switch to the default bsp tiling layout on the main workspace, Alt + Shift + T
|
||||
!+t::
|
||||
ChangeLayout("bsp")
|
||||
return
|
||||
|
||||
; Toggle the Monocle layout for the focused window, Alt + Shift + F
|
||||
!+f::
|
||||
ToggleMonocle()
|
||||
return
|
||||
|
||||
; Toggle native maximize for the focused window, Alt + Shift + =
|
||||
!+=::
|
||||
ToggleMaximize()
|
||||
return
|
||||
|
||||
; Flip horizontally, Alt + X
|
||||
!x::
|
||||
FlipLayout("horizontal")
|
||||
return
|
||||
|
||||
; Flip vertically, Alt + Y
|
||||
!y::
|
||||
FlipLayout("vertical")
|
||||
return
|
||||
|
||||
; Force a retile if things get janky, Alt + Shift + R
|
||||
!+r::
|
||||
Retile()
|
||||
return
|
||||
|
||||
; Float the focused window, Alt + T
|
||||
!t::
|
||||
ToggleFloat()
|
||||
return
|
||||
|
||||
; Reload ~/komorebi.ahk, Alt + O
|
||||
!o::
|
||||
ReloadConfiguration()
|
||||
return
|
||||
|
||||
; Pause responding to any window events or komorebic commands, Alt + P
|
||||
!p::
|
||||
TogglePause()
|
||||
return
|
||||
|
||||
; Enable focus follows mouse
|
||||
!0::
|
||||
ToggleFocusFollowsMouse("komorebi")
|
||||
return
|
||||
|
||||
; Switch to workspace
|
||||
!1::
|
||||
Send !
|
||||
FocusWorkspace(0)
|
||||
return
|
||||
|
||||
!2::
|
||||
Send !
|
||||
FocusWorkspace(1)
|
||||
return
|
||||
|
||||
!3::
|
||||
Send !
|
||||
FocusWorkspace(2)
|
||||
return
|
||||
|
||||
!4::
|
||||
Send !
|
||||
FocusWorkspace(3)
|
||||
return
|
||||
|
||||
!5::
|
||||
Send !
|
||||
FocusWorkspace(4)
|
||||
return
|
||||
|
||||
; Move window to workspace
|
||||
!+1::
|
||||
MoveToWorkspace(0)
|
||||
return
|
||||
|
||||
!+2::
|
||||
MoveToWorkspace(1)
|
||||
return
|
||||
|
||||
!+3::
|
||||
MoveToWorkspace(2)
|
||||
return
|
||||
|
||||
!+4::
|
||||
MoveToWorkspace(3)
|
||||
return
|
||||
|
||||
!+5::
|
||||
MoveToWorkspace(4)
|
||||
return
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "komorebi"
|
||||
version = "0.1.12"
|
||||
version = "0.1.14"
|
||||
authors = ["Jade Iqbal <jadeiqbal@fastmail.com>"]
|
||||
description = "A tiling window manager for Windows"
|
||||
categories = ["tiling-window-manager", "windows"]
|
||||
@@ -14,7 +14,7 @@ edition = "2021"
|
||||
komorebi-core = { path = "../komorebi-core" }
|
||||
|
||||
bitflags = "1"
|
||||
clap = { version = "3", features = ["derive"] }
|
||||
clap = { version = "4", features = ["derive"] }
|
||||
color-eyre = "0.6"
|
||||
crossbeam-channel = "0.5"
|
||||
crossbeam-utils = "0.8"
|
||||
@@ -25,6 +25,7 @@ hotwatch = "0.4"
|
||||
lazy_static = "1"
|
||||
miow = "0.4"
|
||||
nanoid = "0.4"
|
||||
net2 = "0.2"
|
||||
os_info = "3.4"
|
||||
parking_lot = { version = "0.12", features = ["deadlock_detection"] }
|
||||
paste = "1"
|
||||
@@ -32,7 +33,7 @@ schemars = "0.8"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
strum = { version = "0.24", features = ["derive"] }
|
||||
sysinfo = "0.25"
|
||||
sysinfo = "0.26"
|
||||
tracing = "0.1"
|
||||
tracing-appender = "0.2"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
@@ -42,7 +43,7 @@ winput = "0.2"
|
||||
winreg = "0.10"
|
||||
|
||||
[dependencies.windows]
|
||||
version = "0.39"
|
||||
version = "0.43"
|
||||
features = [
|
||||
"Win32_Foundation",
|
||||
"Win32_Graphics_Dwm",
|
||||
@@ -55,7 +56,8 @@ features = [
|
||||
"Win32_UI_Input_KeyboardAndMouse",
|
||||
"Win32_UI_Shell",
|
||||
"Win32_UI_Shell_Common",
|
||||
"Win32_UI_WindowsAndMessaging"
|
||||
"Win32_UI_WindowsAndMessaging",
|
||||
"Win32_System_SystemServices"
|
||||
]
|
||||
|
||||
[features]
|
||||
|
||||
@@ -2,7 +2,6 @@ use std::sync::atomic::Ordering;
|
||||
use std::time::Duration;
|
||||
|
||||
use color_eyre::Result;
|
||||
use komorebi_core::Rect;
|
||||
use windows::core::PCSTR;
|
||||
use windows::Win32::Foundation::HWND;
|
||||
use windows::Win32::UI::WindowsAndMessaging::DispatchMessageA;
|
||||
@@ -13,11 +12,15 @@ use windows::Win32::UI::WindowsAndMessaging::CS_VREDRAW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::MSG;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WNDCLASSA;
|
||||
|
||||
use komorebi_core::Rect;
|
||||
|
||||
use crate::window::Window;
|
||||
use crate::windows_callbacks;
|
||||
use crate::WindowsApi;
|
||||
use crate::BORDER_HWND;
|
||||
use crate::BORDER_OVERFLOW_IDENTIFIERS;
|
||||
use crate::BORDER_RECT;
|
||||
use crate::TRANSPARENCY_COLOUR;
|
||||
use crate::WINDOWS_11;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
@@ -40,7 +43,7 @@ impl Border {
|
||||
let name = format!("{name}\0");
|
||||
let instance = WindowsApi::module_handle_w()?;
|
||||
let class_name = PCSTR(name.as_ptr());
|
||||
let brush = WindowsApi::create_solid_brush(255, 140, 0);
|
||||
let brush = WindowsApi::create_solid_brush(TRANSPARENCY_COLOUR);
|
||||
let window_class = WNDCLASSA {
|
||||
hInstance: instance,
|
||||
lpszClassName: class_name,
|
||||
@@ -84,7 +87,11 @@ impl Border {
|
||||
}
|
||||
|
||||
pub fn hide(self) -> Result<()> {
|
||||
WindowsApi::hide_border_window(self.hwnd())
|
||||
if self.hwnd == 0 {
|
||||
Ok(())
|
||||
} else {
|
||||
WindowsApi::hide_border_window(self.hwnd())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_position(
|
||||
@@ -93,27 +100,33 @@ impl Border {
|
||||
invisible_borders: &Rect,
|
||||
activate: bool,
|
||||
) -> Result<()> {
|
||||
let mut should_expand_border = false;
|
||||
if self.hwnd == 0 {
|
||||
Ok(())
|
||||
} else {
|
||||
let mut should_expand_border = false;
|
||||
|
||||
let mut rect = WindowsApi::window_rect(window.hwnd())?;
|
||||
rect.top -= invisible_borders.bottom;
|
||||
rect.bottom += invisible_borders.bottom;
|
||||
|
||||
let border_overflows = BORDER_OVERFLOW_IDENTIFIERS.lock();
|
||||
if border_overflows.contains(&window.title()?)
|
||||
|| border_overflows.contains(&window.exe()?)
|
||||
|| border_overflows.contains(&window.class()?)
|
||||
{
|
||||
should_expand_border = true;
|
||||
}
|
||||
|
||||
if should_expand_border {
|
||||
rect.left -= invisible_borders.left;
|
||||
rect.top -= invisible_borders.top;
|
||||
rect.right += invisible_borders.right;
|
||||
let mut rect = WindowsApi::window_rect(window.hwnd())?;
|
||||
rect.top -= invisible_borders.bottom;
|
||||
rect.bottom += invisible_borders.bottom;
|
||||
}
|
||||
|
||||
WindowsApi::position_border_window(self.hwnd(), &rect, activate)
|
||||
let border_overflows = BORDER_OVERFLOW_IDENTIFIERS.lock();
|
||||
if border_overflows.contains(&window.title()?)
|
||||
|| border_overflows.contains(&window.exe()?)
|
||||
|| border_overflows.contains(&window.class()?)
|
||||
{
|
||||
should_expand_border = true;
|
||||
}
|
||||
|
||||
if should_expand_border {
|
||||
rect.left -= invisible_borders.left;
|
||||
rect.top -= invisible_borders.top;
|
||||
rect.right += invisible_borders.right;
|
||||
rect.bottom += invisible_borders.bottom;
|
||||
}
|
||||
|
||||
*BORDER_RECT.lock() = rect;
|
||||
|
||||
WindowsApi::position_border_window(self.hwnd(), &rect, activate)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
78
komorebi/src/hidden.rs
Normal file
78
komorebi/src/hidden.rs
Normal file
@@ -0,0 +1,78 @@
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::time::Duration;
|
||||
|
||||
use color_eyre::Result;
|
||||
use windows::core::PCSTR;
|
||||
use windows::Win32::Foundation::HWND;
|
||||
use windows::Win32::UI::WindowsAndMessaging::DispatchMessageA;
|
||||
use windows::Win32::UI::WindowsAndMessaging::FindWindowA;
|
||||
use windows::Win32::UI::WindowsAndMessaging::GetMessageA;
|
||||
use windows::Win32::UI::WindowsAndMessaging::CS_HREDRAW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::CS_VREDRAW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::MSG;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WNDCLASSA;
|
||||
|
||||
use crate::windows_callbacks;
|
||||
use crate::WindowsApi;
|
||||
use crate::HIDDEN_HWND;
|
||||
use crate::TRANSPARENCY_COLOUR;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Hidden {
|
||||
pub(crate) hwnd: isize,
|
||||
}
|
||||
|
||||
impl From<isize> for Hidden {
|
||||
fn from(hwnd: isize) -> Self {
|
||||
Self { hwnd }
|
||||
}
|
||||
}
|
||||
|
||||
impl Hidden {
|
||||
pub const fn hwnd(self) -> HWND {
|
||||
HWND(self.hwnd)
|
||||
}
|
||||
|
||||
pub fn create(name: &str) -> Result<()> {
|
||||
let name = format!("{name}\0");
|
||||
let instance = WindowsApi::module_handle_w()?;
|
||||
let class_name = PCSTR(name.as_ptr());
|
||||
let brush = WindowsApi::create_solid_brush(TRANSPARENCY_COLOUR);
|
||||
let window_class = WNDCLASSA {
|
||||
hInstance: instance,
|
||||
lpszClassName: class_name,
|
||||
style: CS_HREDRAW | CS_VREDRAW,
|
||||
lpfnWndProc: Some(windows_callbacks::hidden_window),
|
||||
hbrBackground: brush,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let _atom = WindowsApi::register_class_a(&window_class)?;
|
||||
|
||||
let name_cl = name.clone();
|
||||
std::thread::spawn(move || -> Result<()> {
|
||||
let hwnd = WindowsApi::create_hidden_window(PCSTR(name_cl.as_ptr()), instance)?;
|
||||
let hidden = Self::from(hwnd);
|
||||
|
||||
let mut message = MSG::default();
|
||||
|
||||
unsafe {
|
||||
while GetMessageA(&mut message, hidden.hwnd(), 0, 0).into() {
|
||||
DispatchMessageA(&message);
|
||||
std::thread::sleep(Duration::from_millis(10));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
});
|
||||
|
||||
let mut hwnd = HWND(0);
|
||||
while hwnd == HWND(0) {
|
||||
hwnd = unsafe { FindWindowA(PCSTR(name.as_ptr()), PCSTR::null()) };
|
||||
}
|
||||
|
||||
HIDDEN_HWND.store(hwnd.0, Ordering::SeqCst);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@
|
||||
use std::collections::HashMap;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::net::TcpStream;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
@@ -37,11 +38,13 @@ use which::which;
|
||||
use winreg::enums::HKEY_CURRENT_USER;
|
||||
use winreg::RegKey;
|
||||
|
||||
use crate::hidden::Hidden;
|
||||
use komorebi_core::HidingBehaviour;
|
||||
use komorebi_core::Rect;
|
||||
use komorebi_core::SocketMessage;
|
||||
|
||||
use crate::border::Border;
|
||||
use crate::process_command::listen_for_commands;
|
||||
use crate::process_command::listen_for_commands_tcp;
|
||||
use crate::process_event::listen_for_events;
|
||||
use crate::process_movement::listen_for_movements;
|
||||
use crate::window_manager::State;
|
||||
@@ -54,6 +57,7 @@ mod ring;
|
||||
|
||||
mod border;
|
||||
mod container;
|
||||
mod hidden;
|
||||
mod monitor;
|
||||
mod process_command;
|
||||
mod process_event;
|
||||
@@ -86,6 +90,8 @@ lazy_static! {
|
||||
"firefox.exe".to_string(),
|
||||
"idea64.exe".to_string(),
|
||||
]));
|
||||
static ref MONITOR_INDEX_PREFERENCES: Arc<Mutex<HashMap<usize, Rect>>> =
|
||||
Arc::new(Mutex::new(HashMap::new()));
|
||||
static ref WORKSPACE_RULES: Arc<Mutex<HashMap<String, (usize, usize)>>> =
|
||||
Arc::new(Mutex::new(HashMap::new()));
|
||||
static ref MANAGE_IDENTIFIERS: Arc<Mutex<Vec<String>>> = Arc::new(Mutex::new(vec![]));
|
||||
@@ -98,11 +104,12 @@ lazy_static! {
|
||||
static ref BORDER_OVERFLOW_IDENTIFIERS: Arc<Mutex<Vec<String>>> = Arc::new(Mutex::new(vec![]));
|
||||
static ref WSL2_UI_PROCESSES: Arc<Mutex<Vec<String>>> = Arc::new(Mutex::new(vec![
|
||||
"X410.exe".to_string(),
|
||||
"mstsc.exe".to_string(),
|
||||
"vcxsrv.exe".to_string(),
|
||||
]));
|
||||
static ref SUBSCRIPTION_PIPES: Arc<Mutex<HashMap<String, File>>> =
|
||||
Arc::new(Mutex::new(HashMap::new()));
|
||||
static ref TCP_CONNECTIONS: Arc<Mutex<HashMap<String, TcpStream>>> =
|
||||
Arc::new(Mutex::new(HashMap::new()));
|
||||
static ref HIDING_BEHAVIOUR: Arc<Mutex<HidingBehaviour>> =
|
||||
Arc::new(Mutex::new(HidingBehaviour::Minimize));
|
||||
static ref HOME_DIR: PathBuf = {
|
||||
@@ -151,6 +158,9 @@ lazy_static! {
|
||||
Version::Semantic(_, _, x) if x >= &22000
|
||||
)
|
||||
};
|
||||
|
||||
static ref BORDER_RECT: Arc<Mutex<Rect>> =
|
||||
Arc::new(Mutex::new(Rect::default()));
|
||||
}
|
||||
|
||||
pub static INITIAL_CONFIGURATION_LOADED: AtomicBool = AtomicBool::new(false);
|
||||
@@ -159,6 +169,13 @@ pub static SESSION_ID: AtomicU32 = AtomicU32::new(0);
|
||||
pub static BORDER_ENABLED: AtomicBool = AtomicBool::new(false);
|
||||
pub static BORDER_HWND: AtomicIsize = AtomicIsize::new(0);
|
||||
pub static BORDER_HIDDEN: AtomicBool = AtomicBool::new(false);
|
||||
pub static BORDER_COLOUR_SINGLE: AtomicU32 = AtomicU32::new(0);
|
||||
pub static BORDER_COLOUR_STACK: AtomicU32 = AtomicU32::new(0);
|
||||
pub static BORDER_COLOUR_CURRENT: AtomicU32 = AtomicU32::new(0);
|
||||
// 0 0 0 aka pure black, I doubt anyone will want this as a border colour
|
||||
pub const TRANSPARENCY_COLOUR: u32 = 0;
|
||||
|
||||
pub static HIDDEN_HWND: AtomicIsize = AtomicIsize::new(0);
|
||||
|
||||
fn setup() -> Result<(WorkerGuard, WorkerGuard)> {
|
||||
if std::env::var("RUST_LIB_BACKTRACE").is_err() {
|
||||
@@ -383,19 +400,33 @@ struct Opts {
|
||||
/// Wait for 'komorebic complete-configuration' to be sent before processing events
|
||||
#[clap(action, short, long)]
|
||||
await_configuration: bool,
|
||||
/// Start a TCP server on the given port to allow the direct sending of SocketMessages
|
||||
#[clap(action, short, long)]
|
||||
tcp_port: Option<usize>,
|
||||
}
|
||||
|
||||
#[tracing::instrument]
|
||||
#[allow(clippy::nonminimal_bool)]
|
||||
fn main() -> Result<()> {
|
||||
let opts: Opts = Opts::parse();
|
||||
CUSTOM_FFM.store(opts.focus_follows_mouse, Ordering::SeqCst);
|
||||
|
||||
let arg_count = std::env::args().count();
|
||||
|
||||
let has_valid_args = arg_count == 1
|
||||
|| (arg_count == 2 && (opts.await_configuration || opts.focus_follows_mouse))
|
||||
|| (arg_count == 3 && opts.await_configuration && opts.focus_follows_mouse);
|
||||
|| (arg_count == 2
|
||||
&& (opts.await_configuration || opts.focus_follows_mouse || opts.tcp_port.is_some()))
|
||||
|| (arg_count == 3 && opts.await_configuration && opts.focus_follows_mouse)
|
||||
|| (arg_count == 3 && opts.tcp_port.is_some() && opts.focus_follows_mouse)
|
||||
|| (arg_count == 3 && opts.tcp_port.is_some() && opts.await_configuration)
|
||||
|| (arg_count == 4
|
||||
&& (opts.focus_follows_mouse && opts.await_configuration && opts.tcp_port.is_some()));
|
||||
|
||||
if has_valid_args {
|
||||
let process_id = WindowsApi::current_process_id();
|
||||
WindowsApi::allow_set_foreground_window(process_id)?;
|
||||
WindowsApi::set_process_dpi_awareness_context()?;
|
||||
|
||||
let session_id = WindowsApi::process_id_to_session_id()?;
|
||||
SESSION_ID.store(session_id, Ordering::SeqCst);
|
||||
|
||||
@@ -424,17 +455,14 @@ fn main() -> Result<()> {
|
||||
#[cfg(feature = "deadlock_detection")]
|
||||
detect_deadlocks();
|
||||
|
||||
let process_id = WindowsApi::current_process_id();
|
||||
WindowsApi::allow_set_foreground_window(process_id)?;
|
||||
WindowsApi::set_process_dpi_awareness_context()?;
|
||||
Border::create("komorebi-border-window")?;
|
||||
|
||||
let (outgoing, incoming): (Sender<WindowManagerEvent>, Receiver<WindowManagerEvent>) =
|
||||
crossbeam_channel::unbounded();
|
||||
|
||||
let winevent_listener = winevent_listener::new(Arc::new(Mutex::new(outgoing)));
|
||||
winevent_listener.start();
|
||||
|
||||
Hidden::create("komorebi-hidden")?;
|
||||
|
||||
let wm = Arc::new(Mutex::new(WindowManager::new(Arc::new(Mutex::new(
|
||||
incoming,
|
||||
)))?));
|
||||
@@ -446,6 +474,10 @@ fn main() -> Result<()> {
|
||||
INITIAL_CONFIGURATION_LOADED.store(true, Ordering::SeqCst);
|
||||
};
|
||||
|
||||
if let Some(port) = opts.tcp_port {
|
||||
listen_for_commands_tcp(wm.clone(), port);
|
||||
}
|
||||
|
||||
std::thread::spawn(|| {
|
||||
load_configuration().expect("could not load configuration");
|
||||
});
|
||||
|
||||
@@ -21,6 +21,8 @@ pub struct Monitor {
|
||||
#[getset(get_copy = "pub", set = "pub")]
|
||||
id: isize,
|
||||
#[getset(get = "pub", set = "pub")]
|
||||
name: String,
|
||||
#[getset(get = "pub", set = "pub")]
|
||||
size: Rect,
|
||||
#[getset(get = "pub", set = "pub")]
|
||||
work_area_size: Rect,
|
||||
@@ -32,12 +34,13 @@ pub struct Monitor {
|
||||
|
||||
impl_ring_elements!(Monitor, Workspace);
|
||||
|
||||
pub fn new(id: isize, size: Rect, work_area_size: Rect) -> Monitor {
|
||||
pub fn new(id: isize, size: Rect, work_area_size: Rect, name: String) -> Monitor {
|
||||
let mut workspaces = Ring::default();
|
||||
workspaces.elements_mut().push_back(Workspace::default());
|
||||
|
||||
Monitor {
|
||||
id,
|
||||
name,
|
||||
size,
|
||||
work_area_size,
|
||||
workspaces,
|
||||
|
||||
@@ -2,15 +2,20 @@ use std::fs::File;
|
||||
use std::fs::OpenOptions;
|
||||
use std::io::BufRead;
|
||||
use std::io::BufReader;
|
||||
use std::io::Read;
|
||||
use std::io::Write;
|
||||
use std::net::TcpListener;
|
||||
use std::net::TcpStream;
|
||||
use std::num::NonZeroUsize;
|
||||
use std::str::FromStr;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use color_eyre::eyre::anyhow;
|
||||
use color_eyre::Result;
|
||||
use miow::pipe::connect;
|
||||
use net2::TcpStreamExt;
|
||||
use parking_lot::Mutex;
|
||||
use schemars::schema_for;
|
||||
use uds_windows::UnixStream;
|
||||
@@ -26,6 +31,7 @@ use komorebi_core::Sizing;
|
||||
use komorebi_core::SocketMessage;
|
||||
use komorebi_core::StateQuery;
|
||||
use komorebi_core::WindowContainerBehaviour;
|
||||
use komorebi_core::WindowKind;
|
||||
|
||||
use crate::border::Border;
|
||||
use crate::current_virtual_desktop;
|
||||
@@ -36,18 +42,23 @@ use crate::window_manager::WindowManager;
|
||||
use crate::windows_api::WindowsApi;
|
||||
use crate::Notification;
|
||||
use crate::NotificationEvent;
|
||||
use crate::BORDER_COLOUR_CURRENT;
|
||||
use crate::BORDER_COLOUR_SINGLE;
|
||||
use crate::BORDER_COLOUR_STACK;
|
||||
use crate::BORDER_ENABLED;
|
||||
use crate::BORDER_HWND;
|
||||
use crate::BORDER_OVERFLOW_IDENTIFIERS;
|
||||
use crate::CUSTOM_FFM;
|
||||
use crate::DATA_DIR;
|
||||
use crate::FLOAT_IDENTIFIERS;
|
||||
use crate::HIDING_BEHAVIOUR;
|
||||
use crate::HOME_DIR;
|
||||
use crate::INITIAL_CONFIGURATION_LOADED;
|
||||
use crate::LAYERED_WHITELIST;
|
||||
use crate::MANAGE_IDENTIFIERS;
|
||||
use crate::MONITOR_INDEX_PREFERENCES;
|
||||
use crate::OBJECT_NAME_CHANGE_ON_LAUNCH;
|
||||
use crate::SUBSCRIPTION_PIPES;
|
||||
use crate::TCP_CONNECTIONS;
|
||||
use crate::TRAY_AND_MULTI_WINDOW_IDENTIFIERS;
|
||||
use crate::WORKSPACE_RULES;
|
||||
|
||||
@@ -60,10 +71,10 @@ pub fn listen_for_commands(wm: Arc<Mutex<WindowManager>>) {
|
||||
.expect("could not clone unix listener");
|
||||
|
||||
std::thread::spawn(move || {
|
||||
tracing::info!("listening");
|
||||
tracing::info!("listening on komorebi.sock");
|
||||
for client in listener.incoming() {
|
||||
match client {
|
||||
Ok(stream) => match wm.lock().read_commands(stream) {
|
||||
Ok(stream) => match read_commands_uds(&wm, stream) {
|
||||
Ok(()) => {}
|
||||
Err(error) => tracing::error!("{}", error),
|
||||
},
|
||||
@@ -76,6 +87,48 @@ pub fn listen_for_commands(wm: Arc<Mutex<WindowManager>>) {
|
||||
});
|
||||
}
|
||||
|
||||
#[tracing::instrument]
|
||||
pub fn listen_for_commands_tcp(wm: Arc<Mutex<WindowManager>>, port: usize) {
|
||||
let listener =
|
||||
TcpListener::bind(format!("0.0.0.0:{}", port)).expect("could not start tcp server");
|
||||
|
||||
std::thread::spawn(move || {
|
||||
tracing::info!("listening on 0.0.0.0:43663");
|
||||
for client in listener.incoming() {
|
||||
match client {
|
||||
Ok(mut stream) => {
|
||||
stream
|
||||
.set_keepalive(Some(Duration::from_secs(30)))
|
||||
.expect("TCP keepalive should be set");
|
||||
|
||||
let addr = stream
|
||||
.peer_addr()
|
||||
.expect("incoming connection should have an address")
|
||||
.to_string();
|
||||
|
||||
let mut connections = TCP_CONNECTIONS.lock();
|
||||
|
||||
connections.insert(
|
||||
addr.clone(),
|
||||
stream.try_clone().expect("stream should be cloneable"),
|
||||
);
|
||||
|
||||
tracing::info!("listening for incoming tcp messages from {}", &addr);
|
||||
|
||||
match read_commands_tcp(&wm, &mut stream, &addr) {
|
||||
Ok(()) => {}
|
||||
Err(error) => tracing::error!("{}", error),
|
||||
}
|
||||
}
|
||||
Err(error) => {
|
||||
tracing::error!("{}", error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
impl WindowManager {
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub fn process_command(&mut self, message: SocketMessage) -> Result<()> {
|
||||
@@ -107,6 +160,7 @@ impl WindowManager {
|
||||
|
||||
match message {
|
||||
SocketMessage::Promote => self.promote_container_to_front()?,
|
||||
SocketMessage::PromoteFocus => self.promote_focus_to_front()?,
|
||||
SocketMessage::FocusWindow(direction) => {
|
||||
self.focus_container_in_direction(direction)?;
|
||||
}
|
||||
@@ -124,6 +178,8 @@ impl WindowManager {
|
||||
SocketMessage::CycleStack(direction) => {
|
||||
self.cycle_container_window_in_direction(direction)?;
|
||||
}
|
||||
SocketMessage::Close => self.focused_window()?.close()?,
|
||||
SocketMessage::Minimize => self.focused_window()?.minimize(),
|
||||
SocketMessage::ToggleFloat => self.toggle_float()?,
|
||||
SocketMessage::ToggleMonocle => self.toggle_monocle()?,
|
||||
SocketMessage::ToggleMaximize => self.toggle_maximize()?,
|
||||
@@ -347,6 +403,18 @@ impl WindowManager {
|
||||
|
||||
std::process::exit(0)
|
||||
}
|
||||
SocketMessage::MonitorIndexPreference(index_preference, left, top, right, bottom) => {
|
||||
let mut monitor_index_preferences = MONITOR_INDEX_PREFERENCES.lock();
|
||||
monitor_index_preferences.insert(
|
||||
index_preference,
|
||||
Rect {
|
||||
left,
|
||||
top,
|
||||
right,
|
||||
bottom,
|
||||
},
|
||||
);
|
||||
}
|
||||
SocketMessage::EnsureWorkspaces(monitor_idx, workspace_count) => {
|
||||
self.ensure_workspaces_for_monitor(monitor_idx, workspace_count)?;
|
||||
}
|
||||
@@ -363,7 +431,7 @@ impl WindowManager {
|
||||
Err(error) => error.to_string(),
|
||||
};
|
||||
|
||||
let mut socket = HOME_DIR.clone();
|
||||
let mut socket = DATA_DIR.clone();
|
||||
socket.push("komorebic.sock");
|
||||
let socket = socket.as_path();
|
||||
|
||||
@@ -386,7 +454,7 @@ impl WindowManager {
|
||||
}
|
||||
.to_string();
|
||||
|
||||
let mut socket = HOME_DIR.clone();
|
||||
let mut socket = DATA_DIR.clone();
|
||||
socket.push("komorebic.sock");
|
||||
let socket = socket.as_path();
|
||||
|
||||
@@ -751,6 +819,10 @@ impl WindowManager {
|
||||
}
|
||||
SocketMessage::ActiveWindowBorder(enable) => {
|
||||
if enable {
|
||||
if BORDER_HWND.load(Ordering::SeqCst) == 0 {
|
||||
Border::create("komorebi-border-window")?;
|
||||
}
|
||||
|
||||
BORDER_ENABLED.store(true, Ordering::SeqCst);
|
||||
self.show_border()?;
|
||||
} else {
|
||||
@@ -758,14 +830,33 @@ impl WindowManager {
|
||||
self.hide_border()?;
|
||||
}
|
||||
}
|
||||
SocketMessage::ActiveWindowBorderColour(r, g, b) => {
|
||||
let hwnd = BORDER_HWND.load(Ordering::SeqCst);
|
||||
WindowsApi::change_border_colour(hwnd, r, g, b)?;
|
||||
SocketMessage::ActiveWindowBorderColour(kind, r, g, b) => {
|
||||
match kind {
|
||||
WindowKind::Single => {
|
||||
BORDER_COLOUR_SINGLE.store(r | (g << 8) | (b << 16), Ordering::SeqCst);
|
||||
BORDER_COLOUR_CURRENT.store(r | (g << 8) | (b << 16), Ordering::SeqCst);
|
||||
}
|
||||
WindowKind::Stack => {
|
||||
BORDER_COLOUR_STACK.store(r | (g << 8) | (b << 16), Ordering::SeqCst);
|
||||
}
|
||||
}
|
||||
|
||||
WindowsApi::invalidate_border_rect()?;
|
||||
}
|
||||
SocketMessage::NotificationSchema => {
|
||||
let notification = schema_for!(Notification);
|
||||
let schema = serde_json::to_string_pretty(¬ification)?;
|
||||
let mut socket = HOME_DIR.clone();
|
||||
let mut socket = DATA_DIR.clone();
|
||||
socket.push("komorebic.sock");
|
||||
let socket = socket.as_path();
|
||||
|
||||
let mut stream = UnixStream::connect(&socket)?;
|
||||
stream.write_all(schema.as_bytes())?;
|
||||
}
|
||||
SocketMessage::SocketSchema => {
|
||||
let socket_message = schema_for!(SocketMessage);
|
||||
let schema = serde_json::to_string_pretty(&socket_message)?;
|
||||
let mut socket = DATA_DIR.clone();
|
||||
socket.push("komorebic.sock");
|
||||
let socket = socket.as_path();
|
||||
|
||||
@@ -788,7 +879,14 @@ impl WindowManager {
|
||||
| SocketMessage::ToggleMonocle
|
||||
| SocketMessage::ToggleMaximize
|
||||
| SocketMessage::Promote
|
||||
| SocketMessage::PromoteFocus
|
||||
| SocketMessage::Retile
|
||||
// Adding this one because sometimes EVENT_SYSTEM_FOREGROUND isn't
|
||||
// getting sent on FocusWindow, meaning the border won't be set
|
||||
// when processing events
|
||||
| SocketMessage::FocusWindow(_)
|
||||
| SocketMessage::InvisibleBorders(_)
|
||||
| SocketMessage::WorkAreaOffset(_)
|
||||
| SocketMessage::MoveWindow(_) => {
|
||||
let foreground = WindowsApi::foreground_window()?;
|
||||
let foreground_window = Window { hwnd: foreground };
|
||||
@@ -829,32 +927,87 @@ impl WindowManager {
|
||||
tracing::info!("processed");
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self, stream))]
|
||||
pub fn read_commands(&mut self, stream: UnixStream) -> Result<()> {
|
||||
let stream = BufReader::new(stream);
|
||||
for line in stream.lines() {
|
||||
let message = SocketMessage::from_str(&line?)?;
|
||||
pub fn read_commands_uds(wm: &Arc<Mutex<WindowManager>>, stream: UnixStream) -> Result<()> {
|
||||
let stream = BufReader::new(stream);
|
||||
for line in stream.lines() {
|
||||
let message = SocketMessage::from_str(&line?)?;
|
||||
|
||||
if self.is_paused {
|
||||
return match message {
|
||||
SocketMessage::TogglePause | SocketMessage::State | SocketMessage::Stop => {
|
||||
Ok(self.process_command(message)?)
|
||||
}
|
||||
_ => {
|
||||
tracing::trace!("ignoring while paused");
|
||||
Ok(())
|
||||
}
|
||||
};
|
||||
}
|
||||
let mut wm = wm.lock();
|
||||
|
||||
self.process_command(message.clone())?;
|
||||
notify_subscribers(&serde_json::to_string(&Notification {
|
||||
event: NotificationEvent::Socket(message.clone()),
|
||||
state: self.as_ref().into(),
|
||||
})?)?;
|
||||
if wm.is_paused {
|
||||
return match message {
|
||||
SocketMessage::TogglePause | SocketMessage::State | SocketMessage::Stop => {
|
||||
Ok(wm.process_command(message)?)
|
||||
}
|
||||
_ => {
|
||||
tracing::trace!("ignoring while paused");
|
||||
Ok(())
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Ok(())
|
||||
wm.process_command(message.clone())?;
|
||||
notify_subscribers(&serde_json::to_string(&Notification {
|
||||
event: NotificationEvent::Socket(message.clone()),
|
||||
state: wm.as_ref().into(),
|
||||
})?)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn read_commands_tcp(
|
||||
wm: &Arc<Mutex<WindowManager>>,
|
||||
stream: &mut TcpStream,
|
||||
addr: &str,
|
||||
) -> Result<()> {
|
||||
let mut stream = BufReader::new(stream);
|
||||
|
||||
loop {
|
||||
let mut buf = vec![0; 1024];
|
||||
match stream.read(&mut buf) {
|
||||
Err(..) => {
|
||||
tracing::warn!("removing disconnected tcp client: {addr}");
|
||||
let mut connections = TCP_CONNECTIONS.lock();
|
||||
connections.remove(addr);
|
||||
break;
|
||||
}
|
||||
Ok(size) => {
|
||||
let message = if let Ok(message) =
|
||||
SocketMessage::from_str(&String::from_utf8_lossy(&buf[..size]))
|
||||
{
|
||||
message
|
||||
} else {
|
||||
tracing::warn!("client sent an invalid message, disconnecting: {addr}");
|
||||
let mut connections = TCP_CONNECTIONS.lock();
|
||||
connections.remove(addr);
|
||||
break;
|
||||
};
|
||||
|
||||
let mut wm = wm.lock();
|
||||
|
||||
if wm.is_paused {
|
||||
return match message {
|
||||
SocketMessage::TogglePause | SocketMessage::State | SocketMessage::Stop => {
|
||||
Ok(wm.process_command(message)?)
|
||||
}
|
||||
_ => {
|
||||
tracing::trace!("ignoring while paused");
|
||||
Ok(())
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
wm.process_command(message.clone())?;
|
||||
notify_subscribers(&serde_json::to_string(&Notification {
|
||||
event: NotificationEvent::Socket(message.clone()),
|
||||
state: wm.as_ref().into(),
|
||||
})?)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -20,6 +20,9 @@ use crate::window_manager_event::WindowManagerEvent;
|
||||
use crate::windows_api::WindowsApi;
|
||||
use crate::Notification;
|
||||
use crate::NotificationEvent;
|
||||
use crate::BORDER_COLOUR_CURRENT;
|
||||
use crate::BORDER_COLOUR_SINGLE;
|
||||
use crate::BORDER_COLOUR_STACK;
|
||||
use crate::BORDER_ENABLED;
|
||||
use crate::BORDER_HIDDEN;
|
||||
use crate::BORDER_HWND;
|
||||
@@ -71,9 +74,9 @@ impl WindowManager {
|
||||
|
||||
// Make sure we have the most recently focused monitor from any event
|
||||
match event {
|
||||
WindowManagerEvent::MonitorPoll(_, window)
|
||||
| WindowManagerEvent::FocusChange(_, window)
|
||||
WindowManagerEvent::FocusChange(_, window)
|
||||
| WindowManagerEvent::Show(_, window)
|
||||
| WindowManagerEvent::DisplayChange(window)
|
||||
| WindowManagerEvent::MoveResizeEnd(_, window) => {
|
||||
self.reconcile_monitors()?;
|
||||
|
||||
@@ -132,7 +135,7 @@ impl WindowManager {
|
||||
|
||||
match event {
|
||||
WindowManagerEvent::Raise(window) => {
|
||||
window.raise()?;
|
||||
window.raise();
|
||||
self.has_pending_raise_op = false;
|
||||
}
|
||||
WindowManagerEvent::Destroy(_, window) | WindowManagerEvent::Unmanage(window) => {
|
||||
@@ -184,22 +187,26 @@ impl WindowManager {
|
||||
}
|
||||
WindowManagerEvent::FocusChange(_, window) => {
|
||||
let workspace = self.focused_workspace_mut()?;
|
||||
if workspace
|
||||
if !workspace
|
||||
.floating_windows()
|
||||
.iter()
|
||||
.any(|w| w.hwnd == window.hwnd)
|
||||
{
|
||||
return Ok(());
|
||||
}
|
||||
if let Some(w) = workspace.maximized_window() {
|
||||
if w.hwnd == window.hwnd {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(w) = workspace.maximized_window() {
|
||||
if w.hwnd == window.hwnd {
|
||||
return Ok(());
|
||||
if let Some(monocle) = workspace.monocle_container() {
|
||||
if let Some(window) = monocle.focused_window() {
|
||||
window.focus(false)?;
|
||||
}
|
||||
} else {
|
||||
self.focused_workspace_mut()?
|
||||
.focus_container_by_window(window.hwnd)?;
|
||||
}
|
||||
}
|
||||
|
||||
self.focused_workspace_mut()?
|
||||
.focus_container_by_window(window.hwnd)?;
|
||||
}
|
||||
WindowManagerEvent::Show(_, window) | WindowManagerEvent::Manage(window) => {
|
||||
let mut switch_to = None;
|
||||
@@ -265,7 +272,7 @@ impl WindowManager {
|
||||
}
|
||||
}
|
||||
}
|
||||
WindowManagerEvent::MoveResizeStart(_, _) => {
|
||||
WindowManagerEvent::MoveResizeStart(_, window) => {
|
||||
let monitor_idx = self.focused_monitor_idx();
|
||||
let workspace_idx = self
|
||||
.focused_monitor()
|
||||
@@ -278,6 +285,8 @@ impl WindowManager {
|
||||
.ok_or_else(|| anyhow!("there is no workspace with this idx"))?
|
||||
.focused_container_idx();
|
||||
|
||||
WindowsApi::bring_window_to_top(window.hwnd())?;
|
||||
|
||||
self.pending_move_op = Option::from((monitor_idx, workspace_idx, container_idx));
|
||||
}
|
||||
WindowManagerEvent::MoveResizeEnd(_, window) => {
|
||||
@@ -295,147 +304,148 @@ impl WindowManager {
|
||||
let invisible_borders = self.invisible_borders;
|
||||
|
||||
let workspace = self.focused_workspace_mut()?;
|
||||
if workspace
|
||||
if !workspace
|
||||
.floating_windows()
|
||||
.iter()
|
||||
.any(|w| w.hwnd == window.hwnd)
|
||||
{
|
||||
return Ok(());
|
||||
}
|
||||
let focused_container_idx = workspace.focused_container_idx();
|
||||
|
||||
let focused_container_idx = workspace.focused_container_idx();
|
||||
let mut new_position = WindowsApi::window_rect(window.hwnd())?;
|
||||
|
||||
let mut new_position = WindowsApi::window_rect(window.hwnd())?;
|
||||
let old_position = *workspace
|
||||
.latest_layout()
|
||||
.get(focused_container_idx)
|
||||
// If the move was to another monitor with an empty workspace, the
|
||||
// workspace here will refer to that empty workspace, which won't
|
||||
// have any latest layout set. We fall back to a Default for Rect
|
||||
// which allows us to make a reasonable guess that the drag has taken
|
||||
// place across a monitor boundary to an empty workspace
|
||||
.unwrap_or(&Rect::default());
|
||||
|
||||
let old_position = *workspace
|
||||
.latest_layout()
|
||||
.get(focused_container_idx)
|
||||
// If the move was to another monitor with an empty workspace, the
|
||||
// workspace here will refer to that empty workspace, which won't
|
||||
// have any latest layout set. We fall back to a Default for Rect
|
||||
// which allows us to make a reasonable guess that the drag has taken
|
||||
// place across a monitor boundary to an empty workspace
|
||||
.unwrap_or(&Rect::default());
|
||||
// This will be true if we have moved to an empty workspace on another monitor
|
||||
let mut moved_across_monitors = old_position == Rect::default();
|
||||
|
||||
// This will be true if we have moved to an empty workspace on another monitor
|
||||
let mut moved_across_monitors = old_position == Rect::default();
|
||||
|
||||
if let Some((origin_monitor_idx, _, _)) = pending {
|
||||
// If we didn't move to another monitor with an empty workspace, it is
|
||||
// still possible that we moved to another monitor with a populated workspace
|
||||
if !moved_across_monitors {
|
||||
// So we'll check if the origin monitor index and the target monitor index
|
||||
// are different, if they are, we can set the override
|
||||
moved_across_monitors = origin_monitor_idx != target_monitor_idx;
|
||||
}
|
||||
}
|
||||
|
||||
// Adjust for the invisible borders
|
||||
new_position.left += invisible_borders.left;
|
||||
new_position.top += invisible_borders.top;
|
||||
new_position.right -= invisible_borders.right;
|
||||
new_position.bottom -= invisible_borders.bottom;
|
||||
|
||||
let resize = Rect {
|
||||
left: new_position.left - old_position.left,
|
||||
top: new_position.top - old_position.top,
|
||||
right: new_position.right - old_position.right,
|
||||
bottom: new_position.bottom - old_position.bottom,
|
||||
};
|
||||
|
||||
// If we have moved across the monitors, use that override, otherwise determine
|
||||
// if a move has taken place by ruling out a resize
|
||||
let is_move = moved_across_monitors
|
||||
|| resize.right == 0 && resize.bottom == 0
|
||||
|| resize.right.abs() == invisible_borders.right
|
||||
&& resize.bottom.abs() == invisible_borders.bottom;
|
||||
|
||||
if is_move {
|
||||
tracing::info!("moving with mouse");
|
||||
|
||||
if moved_across_monitors {
|
||||
if let Some((
|
||||
origin_monitor_idx,
|
||||
origin_workspace_idx,
|
||||
origin_container_idx,
|
||||
)) = pending
|
||||
{
|
||||
let target_workspace_idx = self
|
||||
.monitors()
|
||||
.get(target_monitor_idx)
|
||||
.ok_or_else(|| anyhow!("there is no monitor at this idx"))?
|
||||
.focused_workspace_idx();
|
||||
|
||||
let target_container_idx = self
|
||||
.monitors()
|
||||
.get(target_monitor_idx)
|
||||
.ok_or_else(|| anyhow!("there is no monitor at this idx"))?
|
||||
.focused_workspace()
|
||||
.ok_or_else(|| {
|
||||
anyhow!("there is no focused workspace for this monitor")
|
||||
})?
|
||||
.container_idx_from_current_point()
|
||||
// Default to 0 in the case of an empty workspace
|
||||
.unwrap_or(0);
|
||||
|
||||
self.transfer_container(
|
||||
(
|
||||
origin_monitor_idx,
|
||||
origin_workspace_idx,
|
||||
origin_container_idx,
|
||||
),
|
||||
(
|
||||
target_monitor_idx,
|
||||
target_workspace_idx,
|
||||
target_container_idx,
|
||||
),
|
||||
)?;
|
||||
|
||||
// We want to make sure both the origin and target monitors are updated,
|
||||
// so that we don't have ghost tiles until we force an interaction on
|
||||
// the origin monitor's focused workspace
|
||||
self.focus_monitor(origin_monitor_idx)?;
|
||||
self.focus_workspace(origin_workspace_idx)?;
|
||||
self.update_focused_workspace(false)?;
|
||||
|
||||
self.focus_monitor(target_monitor_idx)?;
|
||||
self.focus_workspace(target_workspace_idx)?;
|
||||
self.update_focused_workspace(false)?;
|
||||
if let Some((origin_monitor_idx, _, _)) = pending {
|
||||
// If we didn't move to another monitor with an empty workspace, it is
|
||||
// still possible that we moved to another monitor with a populated workspace
|
||||
if !moved_across_monitors {
|
||||
// So we'll check if the origin monitor index and the target monitor index
|
||||
// are different, if they are, we can set the override
|
||||
moved_across_monitors = origin_monitor_idx != target_monitor_idx;
|
||||
}
|
||||
}
|
||||
|
||||
// Adjust for the invisible borders
|
||||
new_position.left += invisible_borders.left;
|
||||
new_position.top += invisible_borders.top;
|
||||
new_position.right -= invisible_borders.right;
|
||||
new_position.bottom -= invisible_borders.bottom;
|
||||
|
||||
let resize = Rect {
|
||||
left: new_position.left - old_position.left,
|
||||
top: new_position.top - old_position.top,
|
||||
right: new_position.right - old_position.right,
|
||||
bottom: new_position.bottom - old_position.bottom,
|
||||
};
|
||||
|
||||
// If we have moved across the monitors, use that override, otherwise determine
|
||||
// if a move has taken place by ruling out a resize
|
||||
let is_move = moved_across_monitors
|
||||
|| resize.right == 0 && resize.bottom == 0
|
||||
|| resize.right.abs() == invisible_borders.right
|
||||
&& resize.bottom.abs() == invisible_borders.bottom;
|
||||
|
||||
if is_move {
|
||||
tracing::info!("moving with mouse");
|
||||
|
||||
if moved_across_monitors {
|
||||
if let Some((
|
||||
origin_monitor_idx,
|
||||
origin_workspace_idx,
|
||||
origin_container_idx,
|
||||
)) = pending
|
||||
{
|
||||
let target_workspace_idx = self
|
||||
.monitors()
|
||||
.get(target_monitor_idx)
|
||||
.ok_or_else(|| anyhow!("there is no monitor at this idx"))?
|
||||
.focused_workspace_idx();
|
||||
|
||||
let target_container_idx = self
|
||||
.monitors()
|
||||
.get(target_monitor_idx)
|
||||
.ok_or_else(|| anyhow!("there is no monitor at this idx"))?
|
||||
.focused_workspace()
|
||||
.ok_or_else(|| {
|
||||
anyhow!("there is no focused workspace for this monitor")
|
||||
})?
|
||||
.container_idx_from_current_point()
|
||||
// Default to 0 in the case of an empty workspace
|
||||
.unwrap_or(0);
|
||||
|
||||
self.transfer_container(
|
||||
(
|
||||
origin_monitor_idx,
|
||||
origin_workspace_idx,
|
||||
origin_container_idx,
|
||||
),
|
||||
(
|
||||
target_monitor_idx,
|
||||
target_workspace_idx,
|
||||
target_container_idx,
|
||||
),
|
||||
)?;
|
||||
|
||||
// We want to make sure both the origin and target monitors are updated,
|
||||
// so that we don't have ghost tiles until we force an interaction on
|
||||
// the origin monitor's focused workspace
|
||||
self.focus_monitor(origin_monitor_idx)?;
|
||||
self.focus_workspace(origin_workspace_idx)?;
|
||||
self.update_focused_workspace(false)?;
|
||||
|
||||
self.focus_monitor(target_monitor_idx)?;
|
||||
self.focus_workspace(target_workspace_idx)?;
|
||||
self.update_focused_workspace(false)?;
|
||||
}
|
||||
// Here we handle a simple move on the same monitor which is treated as
|
||||
// a container swap
|
||||
} else {
|
||||
match new_window_behaviour {
|
||||
WindowContainerBehaviour::Create => {
|
||||
match workspace.container_idx_from_current_point() {
|
||||
Some(target_idx) => {
|
||||
workspace
|
||||
.swap_containers(focused_container_idx, target_idx);
|
||||
self.update_focused_workspace(false)?;
|
||||
}
|
||||
None => {
|
||||
self.update_focused_workspace(
|
||||
self.mouse_follows_focus,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
WindowContainerBehaviour::Append => {
|
||||
match workspace.container_idx_from_current_point() {
|
||||
Some(target_idx) => {
|
||||
workspace.move_window_to_container(target_idx)?;
|
||||
self.update_focused_workspace(false)?;
|
||||
}
|
||||
None => {
|
||||
self.update_focused_workspace(
|
||||
self.mouse_follows_focus,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Here we handle a simple move on the same monitor which is treated as
|
||||
// a container swap
|
||||
} else {
|
||||
match new_window_behaviour {
|
||||
WindowContainerBehaviour::Create => {
|
||||
match workspace.container_idx_from_current_point() {
|
||||
Some(target_idx) => {
|
||||
workspace
|
||||
.swap_containers(focused_container_idx, target_idx);
|
||||
self.update_focused_workspace(false)?;
|
||||
}
|
||||
None => {
|
||||
self.update_focused_workspace(self.mouse_follows_focus)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
WindowContainerBehaviour::Append => {
|
||||
match workspace.container_idx_from_current_point() {
|
||||
Some(target_idx) => {
|
||||
workspace.move_window_to_container(target_idx)?;
|
||||
self.update_focused_workspace(false)?;
|
||||
}
|
||||
None => {
|
||||
self.update_focused_workspace(self.mouse_follows_focus)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tracing::info!("resizing with mouse");
|
||||
let mut ops = vec![];
|
||||
tracing::info!("resizing with mouse");
|
||||
let mut ops = vec![];
|
||||
|
||||
macro_rules! resize_op {
|
||||
macro_rules! resize_op {
|
||||
($coordinate:expr, $comparator:tt, $direction:expr) => {{
|
||||
let adjusted = $coordinate * 2;
|
||||
let sizing = if adjusted $comparator 0 {
|
||||
@@ -448,30 +458,31 @@ impl WindowManager {
|
||||
}};
|
||||
}
|
||||
|
||||
if resize.left != 0 {
|
||||
ops.push(resize_op!(resize.left, >, OperationDirection::Left));
|
||||
}
|
||||
if resize.left != 0 {
|
||||
ops.push(resize_op!(resize.left, >, OperationDirection::Left));
|
||||
}
|
||||
|
||||
if resize.top != 0 {
|
||||
ops.push(resize_op!(resize.top, >, OperationDirection::Up));
|
||||
}
|
||||
if resize.top != 0 {
|
||||
ops.push(resize_op!(resize.top, >, OperationDirection::Up));
|
||||
}
|
||||
|
||||
if resize.right != 0 && resize.left == 0 {
|
||||
ops.push(resize_op!(resize.right, <, OperationDirection::Right));
|
||||
}
|
||||
if resize.right != 0 && resize.left == 0 {
|
||||
ops.push(resize_op!(resize.right, <, OperationDirection::Right));
|
||||
}
|
||||
|
||||
if resize.bottom != 0 && resize.top == 0 {
|
||||
ops.push(resize_op!(resize.bottom, <, OperationDirection::Down));
|
||||
}
|
||||
if resize.bottom != 0 && resize.top == 0 {
|
||||
ops.push(resize_op!(resize.bottom, <, OperationDirection::Down));
|
||||
}
|
||||
|
||||
for (edge, sizing, delta) in ops {
|
||||
self.resize_window(edge, sizing, delta, true)?;
|
||||
}
|
||||
for (edge, sizing, delta) in ops {
|
||||
self.resize_window(edge, sizing, delta, true)?;
|
||||
}
|
||||
|
||||
self.update_focused_workspace(false)?;
|
||||
self.update_focused_workspace(false)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
WindowManagerEvent::MonitorPoll(..) | WindowManagerEvent::MouseCapture(..) => {}
|
||||
WindowManagerEvent::DisplayChange(..) | WindowManagerEvent::MouseCapture(..) => {}
|
||||
};
|
||||
|
||||
if *self.focused_workspace()?.tile() && BORDER_ENABLED.load(Ordering::SeqCst) {
|
||||
@@ -481,21 +492,72 @@ impl WindowManager {
|
||||
border.hide()?;
|
||||
BORDER_HIDDEN.store(true, Ordering::SeqCst);
|
||||
}
|
||||
WindowManagerEvent::MoveResizeEnd(_, _)
|
||||
| WindowManagerEvent::Show(_, _)
|
||||
| WindowManagerEvent::FocusChange(_, _) => {
|
||||
let window = self.focused_window()?;
|
||||
let mut rect = WindowsApi::window_rect(window.hwnd())?;
|
||||
rect.top -= self.invisible_borders.bottom;
|
||||
rect.bottom += self.invisible_borders.bottom;
|
||||
|
||||
let activate = BORDER_HIDDEN.load(Ordering::SeqCst);
|
||||
|
||||
WindowManagerEvent::MoveResizeEnd(_, window)
|
||||
| WindowManagerEvent::Show(_, window)
|
||||
| WindowManagerEvent::FocusChange(_, window)
|
||||
| WindowManagerEvent::Hide(_, window)
|
||||
| WindowManagerEvent::Minimize(_, window) => {
|
||||
let border = Border::from(BORDER_HWND.load(Ordering::SeqCst));
|
||||
border.set_position(*window, &self.invisible_borders, activate)?;
|
||||
let mut target_window = None;
|
||||
if self
|
||||
.focused_workspace()?
|
||||
.floating_windows()
|
||||
.iter()
|
||||
.any(|w| w.hwnd == window.hwnd)
|
||||
{
|
||||
target_window = Option::from(*window);
|
||||
WindowsApi::raise_window(border.hwnd())?;
|
||||
};
|
||||
|
||||
if activate {
|
||||
BORDER_HIDDEN.store(false, Ordering::SeqCst);
|
||||
if let Some(monocle_container) = self.focused_workspace()?.monocle_container() {
|
||||
if let Some(window) = monocle_container.focused_window() {
|
||||
target_window = Option::from(*window);
|
||||
}
|
||||
}
|
||||
|
||||
if target_window.is_none() {
|
||||
match self.focused_container() {
|
||||
// if there is no focused container, the desktop is empty
|
||||
Err(..) => {
|
||||
WindowsApi::hide_border_window(border.hwnd())?;
|
||||
}
|
||||
Ok(container) => {
|
||||
if !(matches!(event, WindowManagerEvent::Minimize(_, _))
|
||||
&& container.windows().len() == 1)
|
||||
{
|
||||
let container_size = self.focused_container()?.windows().len();
|
||||
target_window = Option::from(*self.focused_window()?);
|
||||
|
||||
if container_size > 1 {
|
||||
BORDER_COLOUR_CURRENT.store(
|
||||
BORDER_COLOUR_STACK.load(Ordering::SeqCst),
|
||||
Ordering::SeqCst,
|
||||
);
|
||||
} else {
|
||||
BORDER_COLOUR_CURRENT.store(
|
||||
BORDER_COLOUR_SINGLE.load(Ordering::SeqCst),
|
||||
Ordering::SeqCst,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(target_window) = target_window {
|
||||
let window = target_window;
|
||||
let mut rect = WindowsApi::window_rect(window.hwnd())?;
|
||||
rect.top -= self.invisible_borders.bottom;
|
||||
rect.bottom += self.invisible_borders.bottom;
|
||||
|
||||
let activate = BORDER_HIDDEN.load(Ordering::SeqCst);
|
||||
|
||||
WindowsApi::invalidate_border_rect()?;
|
||||
border.set_position(target_window, &self.invisible_borders, activate)?;
|
||||
|
||||
if activate {
|
||||
BORDER_HIDDEN.store(false, Ordering::SeqCst);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
||||
@@ -151,6 +151,14 @@ impl Window {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn minimize(self) {
|
||||
WindowsApi::minimize_window(self.hwnd());
|
||||
}
|
||||
|
||||
pub fn close(self) -> Result<()> {
|
||||
WindowsApi::close_window(self.hwnd())
|
||||
}
|
||||
|
||||
pub fn restore(self) {
|
||||
let mut programmatically_hidden_hwnds = HIDDEN_HWNDS.lock();
|
||||
if let Some(idx) = programmatically_hidden_hwnds
|
||||
@@ -187,25 +195,55 @@ impl Window {
|
||||
WindowsApi::unmaximize_window(self.hwnd());
|
||||
}
|
||||
|
||||
pub fn raise(self) -> Result<()> {
|
||||
pub fn raise(self) {
|
||||
// Attach komorebi thread to Window thread
|
||||
let (_, window_thread_id) = WindowsApi::window_thread_process_id(self.hwnd());
|
||||
let current_thread_id = WindowsApi::current_thread_id();
|
||||
WindowsApi::attach_thread_input(current_thread_id, window_thread_id, true)?;
|
||||
|
||||
// This can be allowed to fail if a window doesn't have a message queue or if a journal record
|
||||
// hook has been installed
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-attachthreadinput#remarks
|
||||
match WindowsApi::attach_thread_input(current_thread_id, window_thread_id, true) {
|
||||
Ok(()) => {}
|
||||
Err(error) => {
|
||||
tracing::error!(
|
||||
"could not attach to window thread input processing mechanism, but continuing execution of raise(): {}",
|
||||
error
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// Raise Window to foreground
|
||||
match WindowsApi::set_foreground_window(self.hwnd()) {
|
||||
Ok(_) => {}
|
||||
Err(error) => {
|
||||
tracing::error!(
|
||||
"could not set as foreground window, but continuing execution of focus(): {}",
|
||||
"could not set as foreground window, but continuing execution of raise(): {}",
|
||||
error
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// This isn't really needed when the above command works as expected via AHK
|
||||
WindowsApi::set_focus(self.hwnd())
|
||||
match WindowsApi::set_focus(self.hwnd()) {
|
||||
Ok(_) => {}
|
||||
Err(error) => {
|
||||
tracing::error!(
|
||||
"could not set focus, but continuing execution of raise(): {}",
|
||||
error
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
match WindowsApi::attach_thread_input(current_thread_id, window_thread_id, false) {
|
||||
Ok(()) => {}
|
||||
Err(error) => {
|
||||
tracing::error!(
|
||||
"could not detach from window thread input processing mechanism, but continuing execution of raise(): {}",
|
||||
error
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub fn focus(self, mouse_follows_focus: bool) -> Result<()> {
|
||||
@@ -227,15 +265,30 @@ impl Window {
|
||||
};
|
||||
|
||||
// Raise Window to foreground
|
||||
match WindowsApi::set_foreground_window(self.hwnd()) {
|
||||
Ok(_) => {}
|
||||
Err(error) => {
|
||||
tracing::error!(
|
||||
"could not set as foreground window, but continuing execution of focus(): {}",
|
||||
error
|
||||
);
|
||||
}
|
||||
};
|
||||
let mut foregrounded = false;
|
||||
let mut tried_resetting_foreground_access = false;
|
||||
let mut max_attempts = 10;
|
||||
while !foregrounded && max_attempts > 0 {
|
||||
match WindowsApi::set_foreground_window(self.hwnd()) {
|
||||
Ok(_) => {
|
||||
foregrounded = true;
|
||||
}
|
||||
Err(error) => {
|
||||
max_attempts -= 1;
|
||||
tracing::error!(
|
||||
"could not set as foreground window, but continuing execution of focus(): {}",
|
||||
error
|
||||
);
|
||||
|
||||
// If this still doesn't work then maybe try https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-locksetforegroundwindow
|
||||
if !tried_resetting_foreground_access {
|
||||
let process_id = WindowsApi::current_process_id();
|
||||
WindowsApi::allow_set_foreground_window(process_id)?;
|
||||
tried_resetting_foreground_access = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Center cursor in Window
|
||||
if mouse_follows_focus {
|
||||
@@ -253,6 +306,16 @@ impl Window {
|
||||
}
|
||||
};
|
||||
|
||||
match WindowsApi::attach_thread_input(current_thread_id, window_thread_id, false) {
|
||||
Ok(()) => {}
|
||||
Err(error) => {
|
||||
tracing::error!(
|
||||
"could not detach from window thread input processing mechanism, but continuing execution of focus(): {}",
|
||||
error
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -294,7 +357,7 @@ impl Window {
|
||||
|
||||
#[tracing::instrument(fields(exe, title))]
|
||||
pub fn should_manage(self, event: Option<WindowManagerEvent>) -> Result<bool> {
|
||||
if let Some(WindowManagerEvent::MonitorPoll(_, _)) = event {
|
||||
if let Some(WindowManagerEvent::DisplayChange(_)) = event {
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use std::collections::HashMap;
|
||||
use std::collections::VecDeque;
|
||||
use std::io::ErrorKind;
|
||||
use std::num::NonZeroUsize;
|
||||
@@ -15,7 +16,6 @@ use schemars::JsonSchema;
|
||||
use serde::Serialize;
|
||||
use uds_windows::UnixListener;
|
||||
|
||||
use crate::border::Border;
|
||||
use komorebi_core::custom_layout::CustomLayout;
|
||||
use komorebi_core::Arrangement;
|
||||
use komorebi_core::Axis;
|
||||
@@ -30,6 +30,7 @@ use komorebi_core::Rect;
|
||||
use komorebi_core::Sizing;
|
||||
use komorebi_core::WindowContainerBehaviour;
|
||||
|
||||
use crate::border::Border;
|
||||
use crate::container::Container;
|
||||
use crate::current_virtual_desktop;
|
||||
use crate::load_configuration;
|
||||
@@ -54,6 +55,7 @@ use crate::WORKSPACE_RULES;
|
||||
#[derive(Debug)]
|
||||
pub struct WindowManager {
|
||||
pub monitors: Ring<Monitor>,
|
||||
pub monitor_cache: HashMap<usize, Monitor>,
|
||||
pub incoming_events: Arc<Mutex<Receiver<WindowManagerEvent>>>,
|
||||
pub command_listener: UnixListener,
|
||||
pub is_paused: bool,
|
||||
@@ -166,6 +168,7 @@ impl WindowManager {
|
||||
|
||||
Ok(Self {
|
||||
monitors: Ring::default(),
|
||||
monitor_cache: HashMap::new(),
|
||||
incoming_events: incoming,
|
||||
command_listener: listener,
|
||||
is_paused: false,
|
||||
@@ -205,7 +208,8 @@ impl WindowManager {
|
||||
rect.bottom += self.invisible_borders.bottom;
|
||||
|
||||
let border = Border::from(BORDER_HWND.load(Ordering::SeqCst));
|
||||
border.set_position(foreground_window, &self.invisible_borders, true)
|
||||
border.set_position(foreground_window, &self.invisible_borders, true)?;
|
||||
WindowsApi::invalidate_border_rect()
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
@@ -325,44 +329,77 @@ impl WindowManager {
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub fn reconcile_monitors(&mut self) -> Result<()> {
|
||||
if self.pending_move_op.is_some() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let valid_hmonitors = WindowsApi::valid_hmonitors()?;
|
||||
let mut invalid = vec![];
|
||||
let mut valid_names = vec![];
|
||||
let before_count = self.monitors().len();
|
||||
|
||||
for monitor in self.monitors_mut() {
|
||||
if !valid_hmonitors.contains(&monitor.id()) {
|
||||
let mut mark_as_invalid = true;
|
||||
|
||||
// If an invalid hmonitor has at least one window in the window manager state,
|
||||
// we can attempt to update its hmonitor id in-place so that it doesn't get reaped
|
||||
if let Some(workspace) = monitor.focused_workspace() {
|
||||
if let Some(container) = workspace.focused_container() {
|
||||
if let Some(window) = container.focused_window() {
|
||||
let actual_hmonitor = WindowsApi::monitor_from_window(window.hwnd());
|
||||
if actual_hmonitor != monitor.id() {
|
||||
monitor.set_id(actual_hmonitor);
|
||||
mark_as_invalid = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if mark_as_invalid {
|
||||
invalid.push(monitor.id());
|
||||
for (valid_name, valid_id) in &valid_hmonitors {
|
||||
let actual_name = monitor.name().clone();
|
||||
if actual_name == *valid_name {
|
||||
monitor.set_id(*valid_id);
|
||||
valid_names.push(actual_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut orphaned_containers = vec![];
|
||||
let mut invalid_indices = vec![];
|
||||
|
||||
for (i, invalid) in self
|
||||
.monitors()
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|(_, m)| !valid_names.contains(m.name()))
|
||||
{
|
||||
invalid_indices.push(i);
|
||||
for workspace in invalid.workspaces() {
|
||||
for container in workspace.containers() {
|
||||
// Save the orphaned containers from an invalid monitor
|
||||
// (which has most likely been disconnected)
|
||||
orphaned_containers.push(container.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for i in invalid_indices {
|
||||
if let Some(monitor) = self.monitors().get(i) {
|
||||
self.monitor_cache.insert(i, monitor.clone());
|
||||
}
|
||||
}
|
||||
|
||||
// Remove any invalid monitors from our state
|
||||
self.monitors_mut().retain(|m| !invalid.contains(&m.id()));
|
||||
self.monitors_mut()
|
||||
.retain(|m| valid_names.contains(m.name()));
|
||||
|
||||
let after_count = self.monitors().len();
|
||||
|
||||
if let Some(primary) = self.monitors_mut().front_mut() {
|
||||
if let Some(focused_ws) = primary.focused_workspace_mut() {
|
||||
let focused_container_idx = focused_ws.focused_container_idx();
|
||||
|
||||
// Put the orphaned containers somewhere visible
|
||||
for container in orphaned_containers {
|
||||
focused_ws.add_container(container);
|
||||
}
|
||||
|
||||
// Gotta reset the focus or the movement will feel "off"
|
||||
focused_ws.focus_container(focused_container_idx);
|
||||
}
|
||||
}
|
||||
|
||||
let invisible_borders = self.invisible_borders;
|
||||
let offset = self.work_area_offset;
|
||||
|
||||
for monitor in self.monitors_mut() {
|
||||
let mut should_update = false;
|
||||
let reference = WindowsApi::monitor(monitor.id())?;
|
||||
// TODO: If this is different, force a redraw
|
||||
// If we have lost a monitor, update everything to filter out any jank
|
||||
let mut should_update = before_count != after_count;
|
||||
|
||||
let reference = WindowsApi::monitor(monitor.id())?;
|
||||
if reference.work_area_size() != monitor.work_area_size() {
|
||||
monitor.set_work_area_size(Rect {
|
||||
left: reference.work_area_size().left,
|
||||
@@ -390,9 +427,51 @@ impl WindowManager {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_collect)]
|
||||
let old_sizes = self
|
||||
.monitors()
|
||||
.iter()
|
||||
.map(Monitor::size)
|
||||
.copied()
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// Check for and add any new monitors that may have been plugged in
|
||||
WindowsApi::load_monitor_information(&mut self.monitors)?;
|
||||
|
||||
let mut check_cache = vec![];
|
||||
|
||||
for (i, m) in self.monitors().iter().enumerate() {
|
||||
if !old_sizes.contains(m.size()) {
|
||||
check_cache.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
for i in check_cache {
|
||||
if let Some(cached) = self.monitor_cache.get(&i).cloned() {
|
||||
if let Some(monitor) = self.monitors_mut().get_mut(i) {
|
||||
for (w_idx, workspace) in monitor.workspaces_mut().iter_mut().enumerate() {
|
||||
if let Some(cached_workspace) = cached.workspaces().get(w_idx) {
|
||||
workspace.set_layout(cached_workspace.layout().clone());
|
||||
workspace.set_layout_rules(cached_workspace.layout_rules().clone());
|
||||
workspace.set_layout_flip(cached_workspace.layout_flip());
|
||||
workspace.set_workspace_padding(cached_workspace.workspace_padding());
|
||||
workspace.set_container_padding(cached_workspace.container_padding());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let final_count = self.monitors().len();
|
||||
if after_count != final_count {
|
||||
self.retile_all(true)?;
|
||||
// Second retile to fix DPI/resolution related jank when a window
|
||||
// moves between monitors with different resolutions - this doesn't
|
||||
// really get seen by the user since the screens are flickering anyway
|
||||
// as a result of the display connections / disconnections
|
||||
self.retile_all(true)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1046,8 +1125,10 @@ impl WindowManager {
|
||||
let origin_workspace =
|
||||
self.focused_workspace_for_monitor_idx_mut(origin_monitor_idx)?;
|
||||
|
||||
origin_workspace
|
||||
.focus_container(origin_workspace.focused_container_idx() - 1);
|
||||
if origin_workspace.focused_container_idx() != 0 {
|
||||
origin_workspace
|
||||
.focus_container(origin_workspace.focused_container_idx() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1250,6 +1331,23 @@ impl WindowManager {
|
||||
self.update_focused_workspace(self.mouse_follows_focus)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub fn promote_focus_to_front(&mut self) -> Result<()> {
|
||||
self.handle_unmanaged_window_behaviour()?;
|
||||
|
||||
tracing::info!("promoting focus");
|
||||
|
||||
let workspace = self.focused_workspace_mut()?;
|
||||
let target_idx = match workspace.layout() {
|
||||
Layout::Default(_) => 0,
|
||||
Layout::Custom(custom) => custom
|
||||
.first_container_idx(custom.primary_idx().map_or(0, |primary_idx| primary_idx)),
|
||||
};
|
||||
|
||||
workspace.focus_container(target_idx);
|
||||
self.update_focused_workspace(self.mouse_follows_focus)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub fn remove_window_from_container(&mut self) -> Result<()> {
|
||||
self.handle_unmanaged_window_behaviour()?;
|
||||
|
||||
@@ -22,7 +22,7 @@ pub enum WindowManagerEvent {
|
||||
Manage(Window),
|
||||
Unmanage(Window),
|
||||
Raise(Window),
|
||||
MonitorPoll(WinEvent, Window),
|
||||
DisplayChange(Window),
|
||||
}
|
||||
|
||||
impl Display for WindowManagerEvent {
|
||||
@@ -77,12 +77,8 @@ impl Display for WindowManagerEvent {
|
||||
Self::Raise(window) => {
|
||||
write!(f, "Raise (Window: {})", window)
|
||||
}
|
||||
Self::MonitorPoll(winevent, window) => {
|
||||
write!(
|
||||
f,
|
||||
"MonitorPoll (WinEvent: {}, Window: {})",
|
||||
winevent, window
|
||||
)
|
||||
Self::DisplayChange(window) => {
|
||||
write!(f, "DisplayChange (Window: {})", window)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -99,9 +95,9 @@ impl WindowManagerEvent {
|
||||
| Self::MoveResizeStart(_, window)
|
||||
| Self::MoveResizeEnd(_, window)
|
||||
| Self::MouseCapture(_, window)
|
||||
| Self::MonitorPoll(_, window)
|
||||
| Self::Raise(window)
|
||||
| Self::Manage(window)
|
||||
| Self::DisplayChange(window)
|
||||
| Self::Unmanage(window) => window,
|
||||
}
|
||||
}
|
||||
@@ -147,17 +143,6 @@ impl WindowManagerEvent {
|
||||
None
|
||||
}
|
||||
}
|
||||
WinEvent::ObjectCreate => {
|
||||
if let Ok(title) = window.title() {
|
||||
// Hidden COM support mechanism window that fires this event on both DPI/scaling
|
||||
// changes and resolution changes, a good candidate for polling
|
||||
if title == "OLEChannelWnd" {
|
||||
return Option::from(Self::MonitorPoll(winevent, window));
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
use std::collections::VecDeque;
|
||||
use std::convert::TryFrom;
|
||||
use std::ffi::c_void;
|
||||
use std::ffi::OsString;
|
||||
use std::os::windows::ffi::OsStringExt;
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
use color_eyre::eyre::anyhow;
|
||||
use color_eyre::eyre::Error;
|
||||
@@ -9,16 +12,16 @@ use windows::core::Result as WindowsCrateResult;
|
||||
use windows::core::PCSTR;
|
||||
use windows::core::PWSTR;
|
||||
use windows::Win32::Foundation::BOOL;
|
||||
use windows::Win32::Foundation::COLORREF;
|
||||
use windows::Win32::Foundation::HANDLE;
|
||||
use windows::Win32::Foundation::HINSTANCE;
|
||||
use windows::Win32::Foundation::HWND;
|
||||
use windows::Win32::Foundation::LPARAM;
|
||||
use windows::Win32::Foundation::POINT;
|
||||
use windows::Win32::Foundation::RECT;
|
||||
use windows::Win32::Foundation::WPARAM;
|
||||
use windows::Win32::Graphics::Dwm::DwmGetWindowAttribute;
|
||||
use windows::Win32::Graphics::Dwm::DwmSetWindowAttribute;
|
||||
use windows::Win32::Graphics::Dwm::DWMWA_CLOAKED;
|
||||
use windows::Win32::Graphics::Dwm::DWMWA_EXTENDED_FRAME_BOUNDS;
|
||||
use windows::Win32::Graphics::Dwm::DWMWA_WINDOW_CORNER_PREFERENCE;
|
||||
use windows::Win32::Graphics::Dwm::DWMWCP_ROUND;
|
||||
use windows::Win32::Graphics::Dwm::DWMWINDOWATTRIBUTE;
|
||||
@@ -28,13 +31,14 @@ use windows::Win32::Graphics::Dwm::DWM_CLOAKED_SHELL;
|
||||
use windows::Win32::Graphics::Gdi::CreateSolidBrush;
|
||||
use windows::Win32::Graphics::Gdi::EnumDisplayMonitors;
|
||||
use windows::Win32::Graphics::Gdi::GetMonitorInfoW;
|
||||
use windows::Win32::Graphics::Gdi::InvalidateRect;
|
||||
use windows::Win32::Graphics::Gdi::MonitorFromPoint;
|
||||
use windows::Win32::Graphics::Gdi::MonitorFromWindow;
|
||||
use windows::Win32::Graphics::Gdi::HBRUSH;
|
||||
use windows::Win32::Graphics::Gdi::HDC;
|
||||
use windows::Win32::Graphics::Gdi::HMONITOR;
|
||||
use windows::Win32::Graphics::Gdi::MONITORENUMPROC;
|
||||
use windows::Win32::Graphics::Gdi::MONITORINFO;
|
||||
use windows::Win32::Graphics::Gdi::MONITORINFOEXW;
|
||||
use windows::Win32::Graphics::Gdi::MONITOR_DEFAULTTONEAREST;
|
||||
use windows::Win32::System::LibraryLoader::GetModuleHandleW;
|
||||
use windows::Win32::System::RemoteDesktop::ProcessIdToSessionId;
|
||||
@@ -52,6 +56,7 @@ use windows::Win32::UI::Input::KeyboardAndMouse::SetFocus;
|
||||
use windows::Win32::UI::Shell::Common::DEVICE_SCALE_FACTOR;
|
||||
use windows::Win32::UI::Shell::GetScaleFactorForMonitor;
|
||||
use windows::Win32::UI::WindowsAndMessaging::AllowSetForegroundWindow;
|
||||
use windows::Win32::UI::WindowsAndMessaging::BringWindowToTop;
|
||||
use windows::Win32::UI::WindowsAndMessaging::CreateWindowExA;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EnumWindows;
|
||||
use windows::Win32::UI::WindowsAndMessaging::GetCursorPos;
|
||||
@@ -66,24 +71,25 @@ use windows::Win32::UI::WindowsAndMessaging::GetWindowThreadProcessId;
|
||||
use windows::Win32::UI::WindowsAndMessaging::IsIconic;
|
||||
use windows::Win32::UI::WindowsAndMessaging::IsWindow;
|
||||
use windows::Win32::UI::WindowsAndMessaging::IsWindowVisible;
|
||||
use windows::Win32::UI::WindowsAndMessaging::PostMessageW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::RealGetWindowClassW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::RegisterClassA;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SetClassLongPtrW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SetCursorPos;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SetForegroundWindow;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SetLayeredWindowAttributes;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SetWindowLongPtrW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SetWindowPos;
|
||||
use windows::Win32::UI::WindowsAndMessaging::ShowWindow;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SystemParametersInfoW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WindowFromPoint;
|
||||
use windows::Win32::UI::WindowsAndMessaging::CW_USEDEFAULT;
|
||||
use windows::Win32::UI::WindowsAndMessaging::GCLP_HBRBACKGROUND;
|
||||
use windows::Win32::UI::WindowsAndMessaging::GWL_EXSTYLE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::GWL_STYLE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::GW_HWNDNEXT;
|
||||
use windows::Win32::UI::WindowsAndMessaging::HWND_BOTTOM;
|
||||
use windows::Win32::UI::WindowsAndMessaging::HWND_NOTOPMOST;
|
||||
use windows::Win32::UI::WindowsAndMessaging::HWND_TOPMOST;
|
||||
use windows::Win32::UI::WindowsAndMessaging::LWA_COLORKEY;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SET_WINDOW_POS_FLAGS;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SHOW_WINDOW_CMD;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SPIF_SENDCHANGE;
|
||||
@@ -97,8 +103,12 @@ use windows::Win32::UI::WindowsAndMessaging::SW_SHOWNOACTIVATE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SYSTEM_PARAMETERS_INFO_ACTION;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SYSTEM_PARAMETERS_INFO_UPDATE_FLAGS;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WINDOW_LONG_PTR_INDEX;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WM_CLOSE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WNDCLASSA;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WNDENUMPROC;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_DISABLED;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_EX_LAYERED;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_EX_NOACTIVATE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_EX_TOOLWINDOW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_MAXIMIZEBOX;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_MINIMIZEBOX;
|
||||
@@ -113,6 +123,8 @@ use crate::monitor::Monitor;
|
||||
use crate::ring::Ring;
|
||||
use crate::set_window_position::SetWindowPosition;
|
||||
use crate::windows_callbacks;
|
||||
use crate::BORDER_HWND;
|
||||
use crate::TRANSPARENCY_COLOUR;
|
||||
|
||||
pub enum WindowsResult<T, E> {
|
||||
Err(E),
|
||||
@@ -187,24 +199,17 @@ impl WindowsApi {
|
||||
callback: MONITORENUMPROC,
|
||||
callback_data_address: isize,
|
||||
) -> Result<()> {
|
||||
unsafe {
|
||||
EnumDisplayMonitors(
|
||||
HDC(0),
|
||||
std::ptr::null_mut(),
|
||||
callback,
|
||||
LPARAM(callback_data_address),
|
||||
)
|
||||
}
|
||||
.ok()
|
||||
.process()
|
||||
unsafe { EnumDisplayMonitors(HDC(0), None, callback, LPARAM(callback_data_address)) }
|
||||
.ok()
|
||||
.process()
|
||||
}
|
||||
|
||||
pub fn valid_hmonitors() -> Result<Vec<isize>> {
|
||||
let mut monitors: Vec<isize> = vec![];
|
||||
let monitors_ref: &mut Vec<isize> = monitors.as_mut();
|
||||
pub fn valid_hmonitors() -> Result<Vec<(String, isize)>> {
|
||||
let mut monitors: Vec<(String, isize)> = vec![];
|
||||
let monitors_ref: &mut Vec<(String, isize)> = monitors.as_mut();
|
||||
Self::enum_display_monitors(
|
||||
Option::Some(windows_callbacks::valid_display_monitors),
|
||||
monitors_ref as *mut Vec<isize> as isize,
|
||||
monitors_ref as *mut Vec<(String, isize)> as isize,
|
||||
)?;
|
||||
|
||||
Ok(monitors)
|
||||
@@ -225,7 +230,7 @@ impl WindowsApi {
|
||||
|
||||
pub fn load_workspace_information(monitors: &mut Ring<Monitor>) -> Result<()> {
|
||||
for monitor in monitors.elements_mut() {
|
||||
let monitor_id = monitor.id();
|
||||
let monitor_name = monitor.name().clone();
|
||||
if let Some(workspace) = monitor.workspaces_mut().front_mut() {
|
||||
// EnumWindows will enumerate through windows on all monitors
|
||||
Self::enum_windows(
|
||||
@@ -243,7 +248,7 @@ impl WindowsApi {
|
||||
|
||||
for container in workspace.containers_mut() {
|
||||
for window in container.windows() {
|
||||
if Self::monitor_from_window(window.hwnd()) != monitor_id {
|
||||
if Self::monitor_name_from_window(window.hwnd())? != monitor_name {
|
||||
windows_on_other_monitors.push(window.hwnd().0);
|
||||
}
|
||||
}
|
||||
@@ -270,6 +275,16 @@ impl WindowsApi {
|
||||
unsafe { MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST) }.0
|
||||
}
|
||||
|
||||
pub fn monitor_name_from_window(hwnd: HWND) -> Result<String> {
|
||||
// MONITOR_DEFAULTTONEAREST ensures that the return value will never be NULL
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-monitorfromwindow
|
||||
Ok(
|
||||
Self::monitor(unsafe { MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST) }.0)?
|
||||
.name()
|
||||
.to_string(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn monitor_from_point(point: POINT) -> isize {
|
||||
// MONITOR_DEFAULTTONEAREST ensures that the return value will never be NULL
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-monitorfromwindow
|
||||
@@ -279,10 +294,21 @@ impl WindowsApi {
|
||||
pub fn position_window(hwnd: HWND, layout: &Rect, top: bool) -> Result<()> {
|
||||
let flags = SetWindowPosition::NO_ACTIVATE;
|
||||
|
||||
let position = if top { HWND_TOPMOST } else { HWND_NOTOPMOST };
|
||||
let position = if top { HWND_TOPMOST } else { HWND_BOTTOM };
|
||||
Self::set_window_pos(hwnd, layout, position, flags.bits())
|
||||
}
|
||||
|
||||
pub fn bring_window_to_top(hwnd: HWND) -> Result<()> {
|
||||
unsafe { BringWindowToTop(hwnd) }.ok().process()
|
||||
}
|
||||
|
||||
pub fn raise_window(hwnd: HWND) -> Result<()> {
|
||||
let flags = SetWindowPosition::NO_MOVE;
|
||||
|
||||
let position = HWND_TOPMOST;
|
||||
Self::set_window_pos(hwnd, &Rect::default(), position, flags.bits())
|
||||
}
|
||||
|
||||
pub fn position_border_window(hwnd: HWND, layout: &Rect, activate: bool) -> Result<()> {
|
||||
let flags = if activate {
|
||||
SetWindowPosition::SHOW_WINDOW | SetWindowPosition::NO_ACTIVATE
|
||||
@@ -290,7 +316,7 @@ impl WindowsApi {
|
||||
SetWindowPosition::NO_ACTIVATE
|
||||
};
|
||||
|
||||
let position = HWND_BOTTOM;
|
||||
let position = HWND_NOTOPMOST;
|
||||
Self::set_window_pos(hwnd, layout, position, flags.bits())
|
||||
}
|
||||
|
||||
@@ -327,6 +353,19 @@ impl WindowsApi {
|
||||
Self::show_window(hwnd, SW_MINIMIZE);
|
||||
}
|
||||
|
||||
fn post_message(hwnd: HWND, message: u32, wparam: WPARAM, lparam: LPARAM) -> Result<()> {
|
||||
unsafe { PostMessageW(hwnd, message, wparam, lparam) }
|
||||
.ok()
|
||||
.process()
|
||||
}
|
||||
|
||||
pub fn close_window(hwnd: HWND) -> Result<()> {
|
||||
match Self::post_message(hwnd, WM_CLOSE, WPARAM(0), LPARAM(0)) {
|
||||
Ok(_) => Ok(()),
|
||||
Err(_) => Err(anyhow!("could not close window")),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn hide_window(hwnd: HWND) {
|
||||
Self::show_window(hwnd, SW_HIDE);
|
||||
}
|
||||
@@ -416,7 +455,9 @@ impl WindowsApi {
|
||||
|
||||
// Behaviour is undefined if an invalid HWND is given
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowthreadprocessid
|
||||
let thread_id = unsafe { GetWindowThreadProcessId(hwnd, &mut process_id) };
|
||||
let thread_id = unsafe {
|
||||
GetWindowThreadProcessId(hwnd, Option::from(std::ptr::addr_of_mut!(process_id)))
|
||||
};
|
||||
|
||||
(process_id, thread_id)
|
||||
}
|
||||
@@ -517,12 +558,7 @@ impl WindowsApi {
|
||||
let text_ptr = path.as_mut_ptr();
|
||||
|
||||
unsafe {
|
||||
QueryFullProcessImageNameW(
|
||||
handle,
|
||||
PROCESS_NAME_WIN32,
|
||||
PWSTR(text_ptr),
|
||||
std::ptr::addr_of_mut!(len),
|
||||
)
|
||||
QueryFullProcessImageNameW(handle, PROCESS_NAME_WIN32, PWSTR(text_ptr), &mut len)
|
||||
}
|
||||
.ok()
|
||||
.process()?;
|
||||
@@ -566,14 +602,6 @@ impl WindowsApi {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn window_rect_with_extended_frame_bounds(hwnd: HWND) -> Result<Rect> {
|
||||
let mut rect = RECT::default();
|
||||
Self::dwm_get_window_attribute(hwnd, DWMWA_EXTENDED_FRAME_BOUNDS, &mut rect)?;
|
||||
|
||||
Ok(Rect::from(rect))
|
||||
}
|
||||
|
||||
pub fn is_window_cloaked(hwnd: HWND) -> Result<bool> {
|
||||
let mut cloaked: u32 = 0;
|
||||
Self::dwm_get_window_attribute(hwnd, DWMWA_CLOAKED, &mut cloaked)?;
|
||||
@@ -596,24 +624,30 @@ impl WindowsApi {
|
||||
unsafe { IsIconic(hwnd) }.into()
|
||||
}
|
||||
|
||||
pub fn monitor_info_w(hmonitor: HMONITOR) -> Result<MONITORINFO> {
|
||||
let mut monitor_info: MONITORINFO = unsafe { std::mem::zeroed() };
|
||||
monitor_info.cbSize = u32::try_from(std::mem::size_of::<MONITORINFO>())?;
|
||||
|
||||
unsafe { GetMonitorInfoW(hmonitor, std::ptr::addr_of_mut!(monitor_info).cast()) }
|
||||
pub fn monitor_info_w(hmonitor: HMONITOR) -> Result<MONITORINFOEXW> {
|
||||
let mut ex_info = MONITORINFOEXW::default();
|
||||
ex_info.monitorInfo.cbSize = u32::try_from(std::mem::size_of::<MONITORINFOEXW>())?;
|
||||
unsafe { GetMonitorInfoW(hmonitor, &mut ex_info.monitorInfo) }
|
||||
.ok()
|
||||
.process()?;
|
||||
|
||||
Ok(monitor_info)
|
||||
Ok(ex_info)
|
||||
}
|
||||
|
||||
pub fn monitor(hmonitor: isize) -> Result<Monitor> {
|
||||
let monitor_info = Self::monitor_info_w(HMONITOR(hmonitor))?;
|
||||
let ex_info = Self::monitor_info_w(HMONITOR(hmonitor))?;
|
||||
let name = OsString::from_wide(&ex_info.szDevice);
|
||||
let name = name
|
||||
.to_string_lossy()
|
||||
.replace('\u{0000}', "")
|
||||
.trim_start_matches(r"\\.\")
|
||||
.to_string();
|
||||
|
||||
Ok(monitor::new(
|
||||
hmonitor,
|
||||
monitor_info.rcMonitor.into(),
|
||||
monitor_info.rcWork.into(),
|
||||
ex_info.monitorInfo.rcMonitor.into(),
|
||||
ex_info.monitorInfo.rcWork.into(),
|
||||
name,
|
||||
))
|
||||
}
|
||||
|
||||
@@ -630,7 +664,7 @@ impl WindowsApi {
|
||||
pv_param: *mut c_void,
|
||||
update_flags: SYSTEM_PARAMETERS_INFO_UPDATE_FLAGS,
|
||||
) -> Result<()> {
|
||||
unsafe { SystemParametersInfoW(action, ui_param, pv_param, update_flags) }
|
||||
unsafe { SystemParametersInfoW(action, ui_param, Option::from(pv_param), update_flags) }
|
||||
.ok()
|
||||
.process()
|
||||
}
|
||||
@@ -673,8 +707,8 @@ impl WindowsApi {
|
||||
unsafe { GetModuleHandleW(None) }.process()
|
||||
}
|
||||
|
||||
pub fn create_solid_brush(r: u32, g: u32, b: u32) -> HBRUSH {
|
||||
unsafe { CreateSolidBrush(r | (g << 8) | (b << 16)) }
|
||||
pub fn create_solid_brush(colour: u32) -> HBRUSH {
|
||||
unsafe { CreateSolidBrush(COLORREF(colour)) }
|
||||
}
|
||||
|
||||
pub fn register_class_a(window_class: &WNDCLASSA) -> Result<u16> {
|
||||
@@ -692,16 +726,6 @@ impl WindowsApi {
|
||||
Ok(a == b)
|
||||
}
|
||||
|
||||
pub fn change_border_colour(hwnd: isize, r: u32, g: u32, b: u32) -> Result<usize> {
|
||||
Result::from(WindowsResult::from(unsafe {
|
||||
SetClassLongPtrW(
|
||||
HWND(hwnd),
|
||||
GCLP_HBRBACKGROUND,
|
||||
Self::create_solid_brush(r, g, b).0,
|
||||
)
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn round_corners(hwnd: isize) -> Result<()> {
|
||||
let round = DWMWCP_ROUND;
|
||||
|
||||
@@ -718,8 +742,8 @@ impl WindowsApi {
|
||||
|
||||
pub fn create_border_window(name: PCSTR, instance: HINSTANCE) -> Result<isize> {
|
||||
unsafe {
|
||||
CreateWindowExA(
|
||||
WS_EX_TOOLWINDOW,
|
||||
let hwnd = CreateWindowExA(
|
||||
WS_EX_TOOLWINDOW | WS_EX_LAYERED,
|
||||
name,
|
||||
name,
|
||||
WS_POPUP | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX,
|
||||
@@ -730,9 +754,39 @@ impl WindowsApi {
|
||||
None,
|
||||
None,
|
||||
instance,
|
||||
std::ptr::null(),
|
||||
None,
|
||||
);
|
||||
|
||||
SetLayeredWindowAttributes(hwnd, COLORREF(TRANSPARENCY_COLOUR), 0, LWA_COLORKEY);
|
||||
|
||||
hwnd
|
||||
}
|
||||
.process()
|
||||
}
|
||||
|
||||
pub fn create_hidden_window(name: PCSTR, instance: HINSTANCE) -> Result<isize> {
|
||||
unsafe {
|
||||
CreateWindowExA(
|
||||
WS_EX_NOACTIVATE,
|
||||
name,
|
||||
name,
|
||||
WS_DISABLED,
|
||||
CW_USEDEFAULT,
|
||||
CW_USEDEFAULT,
|
||||
CW_USEDEFAULT,
|
||||
CW_USEDEFAULT,
|
||||
None,
|
||||
None,
|
||||
instance,
|
||||
None,
|
||||
)
|
||||
}
|
||||
.process()
|
||||
}
|
||||
|
||||
pub fn invalidate_border_rect() -> Result<()> {
|
||||
unsafe { InvalidateRect(HWND(BORDER_HWND.load(Ordering::SeqCst)), None, false) }
|
||||
.ok()
|
||||
.process()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,34 @@
|
||||
use std::collections::VecDeque;
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
use windows::Win32::Foundation::BOOL;
|
||||
use windows::Win32::Foundation::COLORREF;
|
||||
use windows::Win32::Foundation::HWND;
|
||||
use windows::Win32::Foundation::LPARAM;
|
||||
use windows::Win32::Foundation::LRESULT;
|
||||
use windows::Win32::Foundation::RECT;
|
||||
use windows::Win32::Foundation::WPARAM;
|
||||
use windows::Win32::Graphics::Gdi::InvalidateRect;
|
||||
use windows::Win32::Graphics::Gdi::BeginPaint;
|
||||
use windows::Win32::Graphics::Gdi::CreatePen;
|
||||
use windows::Win32::Graphics::Gdi::EndPaint;
|
||||
use windows::Win32::Graphics::Gdi::Rectangle;
|
||||
use windows::Win32::Graphics::Gdi::SelectObject;
|
||||
use windows::Win32::Graphics::Gdi::ValidateRect;
|
||||
use windows::Win32::Graphics::Gdi::HDC;
|
||||
use windows::Win32::Graphics::Gdi::HMONITOR;
|
||||
use windows::Win32::Graphics::Gdi::PAINTSTRUCT;
|
||||
use windows::Win32::Graphics::Gdi::PS_SOLID;
|
||||
use windows::Win32::System::SystemServices::DBT_DEVNODES_CHANGED;
|
||||
use windows::Win32::UI::Accessibility::HWINEVENTHOOK;
|
||||
use windows::Win32::UI::WindowsAndMessaging::DefWindowProcW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::PostQuitMessage;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SPI_ICONVERTICALSPACING;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SPI_SETWORKAREA;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WM_DESTROY;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WM_DEVICECHANGE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WM_DISPLAYCHANGE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WM_PAINT;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WM_SETTINGCHANGE;
|
||||
|
||||
use crate::container::Container;
|
||||
use crate::monitor::Monitor;
|
||||
@@ -22,6 +37,10 @@ use crate::window::Window;
|
||||
use crate::window_manager_event::WindowManagerEvent;
|
||||
use crate::windows_api::WindowsApi;
|
||||
use crate::winevent_listener::WINEVENT_CALLBACK_CHANNEL;
|
||||
use crate::BORDER_COLOUR_CURRENT;
|
||||
use crate::BORDER_RECT;
|
||||
use crate::MONITOR_INDEX_PREFERENCES;
|
||||
use crate::TRANSPARENCY_COLOUR;
|
||||
|
||||
pub extern "system" fn valid_display_monitors(
|
||||
hmonitor: HMONITOR,
|
||||
@@ -29,8 +48,11 @@ pub extern "system" fn valid_display_monitors(
|
||||
_: *mut RECT,
|
||||
lparam: LPARAM,
|
||||
) -> BOOL {
|
||||
let monitors = unsafe { &mut *(lparam.0 as *mut Vec<isize>) };
|
||||
monitors.push(hmonitor.0);
|
||||
let monitors = unsafe { &mut *(lparam.0 as *mut Vec<(String, isize)>) };
|
||||
if let Ok(m) = WindowsApi::monitor(hmonitor.0) {
|
||||
monitors.push((m.name().to_string(), hmonitor.0));
|
||||
}
|
||||
|
||||
true.into()
|
||||
}
|
||||
|
||||
@@ -50,7 +72,24 @@ pub extern "system" fn enum_display_monitor(
|
||||
}
|
||||
|
||||
if let Ok(m) = WindowsApi::monitor(hmonitor.0) {
|
||||
monitors.elements_mut().push_back(m);
|
||||
let monitor_index_preferences = MONITOR_INDEX_PREFERENCES.lock();
|
||||
let mut index_preference = None;
|
||||
for (index, monitor_size) in &*monitor_index_preferences {
|
||||
if m.size() == monitor_size {
|
||||
index_preference = Option::from(index);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(preference) = index_preference {
|
||||
let current_len = monitors.elements().len();
|
||||
if *preference > current_len {
|
||||
monitors.elements_mut().reserve(1);
|
||||
}
|
||||
|
||||
monitors.elements_mut().insert(*preference, m);
|
||||
} else {
|
||||
monitors.elements_mut().push_back(m);
|
||||
}
|
||||
}
|
||||
|
||||
true.into()
|
||||
@@ -120,7 +159,22 @@ pub extern "system" fn border_window(
|
||||
unsafe {
|
||||
match message as u32 {
|
||||
WM_PAINT => {
|
||||
InvalidateRect(window, std::ptr::null(), true);
|
||||
let border_rect = *BORDER_RECT.lock();
|
||||
let mut ps = PAINTSTRUCT::default();
|
||||
let hdc = BeginPaint(window, &mut ps);
|
||||
let hpen = CreatePen(
|
||||
PS_SOLID,
|
||||
20,
|
||||
COLORREF(BORDER_COLOUR_CURRENT.load(Ordering::SeqCst)),
|
||||
);
|
||||
let hbrush = WindowsApi::create_solid_brush(TRANSPARENCY_COLOUR);
|
||||
|
||||
SelectObject(hdc, hpen);
|
||||
SelectObject(hdc, hbrush);
|
||||
Rectangle(hdc, 0, 0, border_rect.right, border_rect.bottom);
|
||||
EndPaint(window, &ps);
|
||||
ValidateRect(window, None);
|
||||
|
||||
LRESULT(0)
|
||||
}
|
||||
WM_DESTROY => {
|
||||
@@ -131,3 +185,54 @@ pub extern "system" fn border_window(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub extern "system" fn hidden_window(
|
||||
window: HWND,
|
||||
message: u32,
|
||||
wparam: WPARAM,
|
||||
lparam: LPARAM,
|
||||
) -> LRESULT {
|
||||
unsafe {
|
||||
match message as u32 {
|
||||
WM_DISPLAYCHANGE => {
|
||||
let event_type = WindowManagerEvent::DisplayChange(Window { hwnd: window.0 });
|
||||
WINEVENT_CALLBACK_CHANNEL
|
||||
.lock()
|
||||
.0
|
||||
.send(event_type)
|
||||
.expect("could not send message on WINEVENT_CALLBACK_CHANNEL");
|
||||
|
||||
LRESULT(0)
|
||||
}
|
||||
// Added based on this https://stackoverflow.com/a/33762334
|
||||
WM_SETTINGCHANGE => {
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
if wparam.0 as u32 == SPI_SETWORKAREA.0
|
||||
|| wparam.0 as u32 == SPI_ICONVERTICALSPACING.0
|
||||
{
|
||||
let event_type = WindowManagerEvent::DisplayChange(Window { hwnd: window.0 });
|
||||
WINEVENT_CALLBACK_CHANNEL
|
||||
.lock()
|
||||
.0
|
||||
.send(event_type)
|
||||
.expect("could not send message on WINEVENT_CALLBACK_CHANNEL");
|
||||
}
|
||||
LRESULT(0)
|
||||
}
|
||||
// Added based on this https://stackoverflow.com/a/33762334
|
||||
WM_DEVICECHANGE => {
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
if wparam.0 as u32 == DBT_DEVNODES_CHANGED {
|
||||
let event_type = WindowManagerEvent::DisplayChange(Window { hwnd: window.0 });
|
||||
WINEVENT_CALLBACK_CHANNEL
|
||||
.lock()
|
||||
.0
|
||||
.send(event_type)
|
||||
.expect("could not send message on WINEVENT_CALLBACK_CHANNEL");
|
||||
}
|
||||
LRESULT(0)
|
||||
}
|
||||
_ => DefWindowProcW(window, message, wparam, lparam),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
361
komorebic.lib.ahk
Normal file
361
komorebic.lib.ahk
Normal file
@@ -0,0 +1,361 @@
|
||||
; Generated by komorebic.exe
|
||||
|
||||
Start(ffm, await_configuration, tcp_port) {
|
||||
RunWait, komorebic.exe start %ffm% --await-configuration %await_configuration% --tcp-port %tcp_port%, , Hide
|
||||
}
|
||||
|
||||
Stop() {
|
||||
RunWait, komorebic.exe stop, , Hide
|
||||
}
|
||||
|
||||
State() {
|
||||
RunWait, komorebic.exe state, , Hide
|
||||
}
|
||||
|
||||
Query(state_query) {
|
||||
RunWait, komorebic.exe query %state_query%, , Hide
|
||||
}
|
||||
|
||||
Subscribe(named_pipe) {
|
||||
RunWait, komorebic.exe subscribe %named_pipe%, , Hide
|
||||
}
|
||||
|
||||
Unsubscribe(named_pipe) {
|
||||
RunWait, komorebic.exe unsubscribe %named_pipe%, , Hide
|
||||
}
|
||||
|
||||
Log() {
|
||||
RunWait, komorebic.exe log, , Hide
|
||||
}
|
||||
|
||||
QuickSaveResize() {
|
||||
RunWait, komorebic.exe quick-save-resize, , Hide
|
||||
}
|
||||
|
||||
QuickLoadResize() {
|
||||
RunWait, komorebic.exe quick-load-resize, , Hide
|
||||
}
|
||||
|
||||
SaveResize(path) {
|
||||
RunWait, komorebic.exe save-resize %path%, , Hide
|
||||
}
|
||||
|
||||
LoadResize(path) {
|
||||
RunWait, komorebic.exe load-resize %path%, , Hide
|
||||
}
|
||||
|
||||
Focus(operation_direction) {
|
||||
RunWait, komorebic.exe focus %operation_direction%, , Hide
|
||||
}
|
||||
|
||||
Move(operation_direction) {
|
||||
RunWait, komorebic.exe move %operation_direction%, , Hide
|
||||
}
|
||||
|
||||
Minimize() {
|
||||
RunWait, komorebic.exe minimize, , Hide
|
||||
}
|
||||
|
||||
Close() {
|
||||
RunWait, komorebic.exe close, , Hide
|
||||
}
|
||||
|
||||
CycleFocus(cycle_direction) {
|
||||
RunWait, komorebic.exe cycle-focus %cycle_direction%, , Hide
|
||||
}
|
||||
|
||||
CycleMove(cycle_direction) {
|
||||
RunWait, komorebic.exe cycle-move %cycle_direction%, , Hide
|
||||
}
|
||||
|
||||
Stack(operation_direction) {
|
||||
RunWait, komorebic.exe stack %operation_direction%, , Hide
|
||||
}
|
||||
|
||||
Resize(edge, sizing) {
|
||||
RunWait, komorebic.exe resize %edge% %sizing%, , Hide
|
||||
}
|
||||
|
||||
ResizeAxis(axis, sizing) {
|
||||
RunWait, komorebic.exe resize-axis %axis% %sizing%, , Hide
|
||||
}
|
||||
|
||||
Unstack() {
|
||||
RunWait, komorebic.exe unstack, , Hide
|
||||
}
|
||||
|
||||
CycleStack(cycle_direction) {
|
||||
RunWait, komorebic.exe cycle-stack %cycle_direction%, , Hide
|
||||
}
|
||||
|
||||
MoveToMonitor(target) {
|
||||
RunWait, komorebic.exe move-to-monitor %target%, , Hide
|
||||
}
|
||||
|
||||
MoveToWorkspace(target) {
|
||||
RunWait, komorebic.exe move-to-workspace %target%, , Hide
|
||||
}
|
||||
|
||||
SendToMonitor(target) {
|
||||
RunWait, komorebic.exe send-to-monitor %target%, , Hide
|
||||
}
|
||||
|
||||
SendToWorkspace(target) {
|
||||
RunWait, komorebic.exe send-to-workspace %target%, , Hide
|
||||
}
|
||||
|
||||
SendToMonitorWorkspace(target_monitor, target_workspace) {
|
||||
RunWait, komorebic.exe send-to-monitor-workspace %target_monitor% %target_workspace%, , Hide
|
||||
}
|
||||
|
||||
FocusMonitor(target) {
|
||||
RunWait, komorebic.exe focus-monitor %target%, , Hide
|
||||
}
|
||||
|
||||
FocusWorkspace(target) {
|
||||
RunWait, komorebic.exe focus-workspace %target%, , Hide
|
||||
}
|
||||
|
||||
FocusMonitorWorkspace(target_monitor, target_workspace) {
|
||||
RunWait, komorebic.exe focus-monitor-workspace %target_monitor% %target_workspace%, , Hide
|
||||
}
|
||||
|
||||
CycleMonitor(cycle_direction) {
|
||||
RunWait, komorebic.exe cycle-monitor %cycle_direction%, , Hide
|
||||
}
|
||||
|
||||
CycleWorkspace(cycle_direction) {
|
||||
RunWait, komorebic.exe cycle-workspace %cycle_direction%, , Hide
|
||||
}
|
||||
|
||||
MoveWorkspaceToMonitor(target) {
|
||||
RunWait, komorebic.exe move-workspace-to-monitor %target%, , Hide
|
||||
}
|
||||
|
||||
NewWorkspace() {
|
||||
RunWait, komorebic.exe new-workspace, , Hide
|
||||
}
|
||||
|
||||
ResizeDelta(pixels) {
|
||||
RunWait, komorebic.exe resize-delta %pixels%, , Hide
|
||||
}
|
||||
|
||||
InvisibleBorders(left, top, right, bottom) {
|
||||
RunWait, komorebic.exe invisible-borders %left% %top% %right% %bottom%, , Hide
|
||||
}
|
||||
|
||||
WorkAreaOffset(left, top, right, bottom) {
|
||||
RunWait, komorebic.exe work-area-offset %left% %top% %right% %bottom%, , Hide
|
||||
}
|
||||
|
||||
AdjustContainerPadding(sizing, adjustment) {
|
||||
RunWait, komorebic.exe adjust-container-padding %sizing% %adjustment%, , Hide
|
||||
}
|
||||
|
||||
AdjustWorkspacePadding(sizing, adjustment) {
|
||||
RunWait, komorebic.exe adjust-workspace-padding %sizing% %adjustment%, , Hide
|
||||
}
|
||||
|
||||
ChangeLayout(default_layout) {
|
||||
RunWait, komorebic.exe change-layout %default_layout%, , Hide
|
||||
}
|
||||
|
||||
LoadCustomLayout(path) {
|
||||
RunWait, komorebic.exe load-custom-layout %path%, , Hide
|
||||
}
|
||||
|
||||
FlipLayout(axis) {
|
||||
RunWait, komorebic.exe flip-layout %axis%, , Hide
|
||||
}
|
||||
|
||||
Promote() {
|
||||
RunWait, komorebic.exe promote, , Hide
|
||||
}
|
||||
|
||||
PromoteFocus() {
|
||||
RunWait, komorebic.exe promote-focus, , Hide
|
||||
}
|
||||
|
||||
Retile() {
|
||||
RunWait, komorebic.exe retile, , Hide
|
||||
}
|
||||
|
||||
MonitorIndexPreference(index_preference, left, top, right, bottom) {
|
||||
RunWait, komorebic.exe monitor-index-preference %index_preference% %left% %top% %right% %bottom%, , Hide
|
||||
}
|
||||
|
||||
EnsureWorkspaces(monitor, workspace_count) {
|
||||
RunWait, komorebic.exe ensure-workspaces %monitor% %workspace_count%, , Hide
|
||||
}
|
||||
|
||||
ContainerPadding(monitor, workspace, size) {
|
||||
RunWait, komorebic.exe container-padding %monitor% %workspace% %size%, , Hide
|
||||
}
|
||||
|
||||
WorkspacePadding(monitor, workspace, size) {
|
||||
RunWait, komorebic.exe workspace-padding %monitor% %workspace% %size%, , Hide
|
||||
}
|
||||
|
||||
WorkspaceLayout(monitor, workspace, value) {
|
||||
RunWait, komorebic.exe workspace-layout %monitor% %workspace% %value%, , Hide
|
||||
}
|
||||
|
||||
WorkspaceCustomLayout(monitor, workspace, path) {
|
||||
RunWait, komorebic.exe workspace-custom-layout %monitor% %workspace% %path%, , Hide
|
||||
}
|
||||
|
||||
WorkspaceLayoutRule(monitor, workspace, at_container_count, layout) {
|
||||
RunWait, komorebic.exe workspace-layout-rule %monitor% %workspace% %at_container_count% %layout%, , Hide
|
||||
}
|
||||
|
||||
WorkspaceCustomLayoutRule(monitor, workspace, at_container_count, path) {
|
||||
RunWait, komorebic.exe workspace-custom-layout-rule %monitor% %workspace% %at_container_count% %path%, , Hide
|
||||
}
|
||||
|
||||
ClearWorkspaceLayoutRules(monitor, workspace) {
|
||||
RunWait, komorebic.exe clear-workspace-layout-rules %monitor% %workspace%, , Hide
|
||||
}
|
||||
|
||||
WorkspaceTiling(monitor, workspace, value) {
|
||||
RunWait, komorebic.exe workspace-tiling %monitor% %workspace% %value%, , Hide
|
||||
}
|
||||
|
||||
WorkspaceName(monitor, workspace, value) {
|
||||
RunWait, komorebic.exe workspace-name %monitor% %workspace% %value%, , Hide
|
||||
}
|
||||
|
||||
ToggleWindowContainerBehaviour() {
|
||||
RunWait, komorebic.exe toggle-window-container-behaviour, , Hide
|
||||
}
|
||||
|
||||
TogglePause() {
|
||||
RunWait, komorebic.exe toggle-pause, , Hide
|
||||
}
|
||||
|
||||
ToggleTiling() {
|
||||
RunWait, komorebic.exe toggle-tiling, , Hide
|
||||
}
|
||||
|
||||
ToggleFloat() {
|
||||
RunWait, komorebic.exe toggle-float, , Hide
|
||||
}
|
||||
|
||||
ToggleMonocle() {
|
||||
RunWait, komorebic.exe toggle-monocle, , Hide
|
||||
}
|
||||
|
||||
ToggleMaximize() {
|
||||
RunWait, komorebic.exe toggle-maximize, , Hide
|
||||
}
|
||||
|
||||
RestoreWindows() {
|
||||
RunWait, komorebic.exe restore-windows, , Hide
|
||||
}
|
||||
|
||||
Manage() {
|
||||
RunWait, komorebic.exe manage, , Hide
|
||||
}
|
||||
|
||||
Unmanage() {
|
||||
RunWait, komorebic.exe unmanage, , Hide
|
||||
}
|
||||
|
||||
ReloadConfiguration() {
|
||||
RunWait, komorebic.exe reload-configuration, , Hide
|
||||
}
|
||||
|
||||
WatchConfiguration(boolean_state) {
|
||||
RunWait, komorebic.exe watch-configuration %boolean_state%, , Hide
|
||||
}
|
||||
|
||||
CompleteConfiguration() {
|
||||
RunWait, komorebic.exe complete-configuration, , Hide
|
||||
}
|
||||
|
||||
WindowHidingBehaviour(hiding_behaviour) {
|
||||
RunWait, komorebic.exe window-hiding-behaviour %hiding_behaviour%, , Hide
|
||||
}
|
||||
|
||||
CrossMonitorMoveBehaviour(move_behaviour) {
|
||||
RunWait, komorebic.exe cross-monitor-move-behaviour %move_behaviour%, , Hide
|
||||
}
|
||||
|
||||
ToggleCrossMonitorMoveBehaviour() {
|
||||
RunWait, komorebic.exe toggle-cross-monitor-move-behaviour, , Hide
|
||||
}
|
||||
|
||||
UnmanagedWindowOperationBehaviour(operation_behaviour) {
|
||||
RunWait, komorebic.exe unmanaged-window-operation-behaviour %operation_behaviour%, , Hide
|
||||
}
|
||||
|
||||
FloatRule(identifier, id) {
|
||||
RunWait, komorebic.exe float-rule %identifier% "%id%", , Hide
|
||||
}
|
||||
|
||||
ManageRule(identifier, id) {
|
||||
RunWait, komorebic.exe manage-rule %identifier% "%id%", , Hide
|
||||
}
|
||||
|
||||
WorkspaceRule(identifier, id, monitor, workspace) {
|
||||
RunWait, komorebic.exe workspace-rule %identifier% "%id%" %monitor% %workspace%, , Hide
|
||||
}
|
||||
|
||||
IdentifyObjectNameChangeApplication(identifier, id) {
|
||||
RunWait, komorebic.exe identify-object-name-change-application %identifier% "%id%", , Hide
|
||||
}
|
||||
|
||||
IdentifyTrayApplication(identifier, id) {
|
||||
RunWait, komorebic.exe identify-tray-application %identifier% "%id%", , Hide
|
||||
}
|
||||
|
||||
IdentifyLayeredApplication(identifier, id) {
|
||||
RunWait, komorebic.exe identify-layered-application %identifier% "%id%", , Hide
|
||||
}
|
||||
|
||||
IdentifyBorderOverflowApplication(identifier, id) {
|
||||
RunWait, komorebic.exe identify-border-overflow-application %identifier% "%id%", , Hide
|
||||
}
|
||||
|
||||
ActiveWindowBorder(boolean_state) {
|
||||
RunWait, komorebic.exe active-window-border %boolean_state%, , Hide
|
||||
}
|
||||
|
||||
ActiveWindowBorderColour(r, g, b, window_kind) {
|
||||
RunWait, komorebic.exe active-window-border-colour %r% %g% %b% --window-kind %window_kind%, , Hide
|
||||
}
|
||||
|
||||
FocusFollowsMouse(boolean_state, implementation) {
|
||||
RunWait, komorebic.exe focus-follows-mouse %boolean_state% --implementation %implementation%, , Hide
|
||||
}
|
||||
|
||||
ToggleFocusFollowsMouse(implementation) {
|
||||
RunWait, komorebic.exe toggle-focus-follows-mouse --implementation %implementation%, , Hide
|
||||
}
|
||||
|
||||
MouseFollowsFocus(boolean_state) {
|
||||
RunWait, komorebic.exe mouse-follows-focus %boolean_state%, , Hide
|
||||
}
|
||||
|
||||
ToggleMouseFollowsFocus() {
|
||||
RunWait, komorebic.exe toggle-mouse-follows-focus, , Hide
|
||||
}
|
||||
|
||||
AhkLibrary() {
|
||||
RunWait, komorebic.exe ahk-library, , Hide
|
||||
}
|
||||
|
||||
AhkAppSpecificConfiguration(path, override_path) {
|
||||
RunWait, komorebic.exe ahk-app-specific-configuration %path% %override_path%, , Hide
|
||||
}
|
||||
|
||||
FormatAppSpecificConfiguration(path) {
|
||||
RunWait, komorebic.exe format-app-specific-configuration %path%, , Hide
|
||||
}
|
||||
|
||||
NotificationSchema() {
|
||||
RunWait, komorebic.exe notification-schema, , Hide
|
||||
}
|
||||
|
||||
SocketSchema() {
|
||||
RunWait, komorebic.exe socket-schema, , Hide
|
||||
}
|
||||
@@ -1,341 +0,0 @@
|
||||
; Generated by komorebic.exe
|
||||
|
||||
Start(ffm, await_configuration) {
|
||||
Run, komorebic.exe start %ffm% --await_configuration %await_configuration%, , Hide
|
||||
}
|
||||
|
||||
Stop() {
|
||||
Run, komorebic.exe stop, , Hide
|
||||
}
|
||||
|
||||
State() {
|
||||
Run, komorebic.exe state, , Hide
|
||||
}
|
||||
|
||||
Query(state_query) {
|
||||
Run, komorebic.exe query %state_query%, , Hide
|
||||
}
|
||||
|
||||
Subscribe(named_pipe) {
|
||||
Run, komorebic.exe subscribe %named_pipe%, , Hide
|
||||
}
|
||||
|
||||
Unsubscribe(named_pipe) {
|
||||
Run, komorebic.exe unsubscribe %named_pipe%, , Hide
|
||||
}
|
||||
|
||||
Log() {
|
||||
Run, komorebic.exe log, , Hide
|
||||
}
|
||||
|
||||
QuickSaveResize() {
|
||||
Run, komorebic.exe quick-save-resize, , Hide
|
||||
}
|
||||
|
||||
QuickLoadResize() {
|
||||
Run, komorebic.exe quick-load-resize, , Hide
|
||||
}
|
||||
|
||||
SaveResize(path) {
|
||||
Run, komorebic.exe save-resize %path%, , Hide
|
||||
}
|
||||
|
||||
LoadResize(path) {
|
||||
Run, komorebic.exe load-resize %path%, , Hide
|
||||
}
|
||||
|
||||
Focus(operation_direction) {
|
||||
Run, komorebic.exe focus %operation_direction%, , Hide
|
||||
}
|
||||
|
||||
Move(operation_direction) {
|
||||
Run, komorebic.exe move %operation_direction%, , Hide
|
||||
}
|
||||
|
||||
CycleFocus(cycle_direction) {
|
||||
Run, komorebic.exe cycle-focus %cycle_direction%, , Hide
|
||||
}
|
||||
|
||||
CycleMove(cycle_direction) {
|
||||
Run, komorebic.exe cycle-move %cycle_direction%, , Hide
|
||||
}
|
||||
|
||||
Stack(operation_direction) {
|
||||
Run, komorebic.exe stack %operation_direction%, , Hide
|
||||
}
|
||||
|
||||
Resize(edge, sizing) {
|
||||
Run, komorebic.exe resize %edge% %sizing%, , Hide
|
||||
}
|
||||
|
||||
ResizeAxis(axis, sizing) {
|
||||
Run, komorebic.exe resize-axis %axis% %sizing%, , Hide
|
||||
}
|
||||
|
||||
Unstack() {
|
||||
Run, komorebic.exe unstack, , Hide
|
||||
}
|
||||
|
||||
CycleStack(cycle_direction) {
|
||||
Run, komorebic.exe cycle-stack %cycle_direction%, , Hide
|
||||
}
|
||||
|
||||
MoveToMonitor(target) {
|
||||
Run, komorebic.exe move-to-monitor %target%, , Hide
|
||||
}
|
||||
|
||||
MoveToWorkspace(target) {
|
||||
Run, komorebic.exe move-to-workspace %target%, , Hide
|
||||
}
|
||||
|
||||
SendToMonitor(target) {
|
||||
Run, komorebic.exe send-to-monitor %target%, , Hide
|
||||
}
|
||||
|
||||
SendToWorkspace(target) {
|
||||
Run, komorebic.exe send-to-workspace %target%, , Hide
|
||||
}
|
||||
|
||||
SendToMonitorWorkspace(target_monitor, target_workspace) {
|
||||
Run, komorebic.exe send-to-monitor-workspace %target_monitor% %target_workspace%, , Hide
|
||||
}
|
||||
|
||||
FocusMonitor(target) {
|
||||
Run, komorebic.exe focus-monitor %target%, , Hide
|
||||
}
|
||||
|
||||
FocusWorkspace(target) {
|
||||
Run, komorebic.exe focus-workspace %target%, , Hide
|
||||
}
|
||||
|
||||
FocusMonitorWorkspace(target_monitor, target_workspace) {
|
||||
Run, komorebic.exe focus-monitor-workspace %target_monitor% %target_workspace%, , Hide
|
||||
}
|
||||
|
||||
CycleMonitor(cycle_direction) {
|
||||
Run, komorebic.exe cycle-monitor %cycle_direction%, , Hide
|
||||
}
|
||||
|
||||
CycleWorkspace(cycle_direction) {
|
||||
Run, komorebic.exe cycle-workspace %cycle_direction%, , Hide
|
||||
}
|
||||
|
||||
MoveWorkspaceToMonitor(target) {
|
||||
Run, komorebic.exe move-workspace-to-monitor %target%, , Hide
|
||||
}
|
||||
|
||||
NewWorkspace() {
|
||||
Run, komorebic.exe new-workspace, , Hide
|
||||
}
|
||||
|
||||
ResizeDelta(pixels) {
|
||||
Run, komorebic.exe resize-delta %pixels%, , Hide
|
||||
}
|
||||
|
||||
InvisibleBorders(left, top, right, bottom) {
|
||||
Run, komorebic.exe invisible-borders %left% %top% %right% %bottom%, , Hide
|
||||
}
|
||||
|
||||
WorkAreaOffset(left, top, right, bottom) {
|
||||
Run, komorebic.exe work-area-offset %left% %top% %right% %bottom%, , Hide
|
||||
}
|
||||
|
||||
AdjustContainerPadding(sizing, adjustment) {
|
||||
Run, komorebic.exe adjust-container-padding %sizing% %adjustment%, , Hide
|
||||
}
|
||||
|
||||
AdjustWorkspacePadding(sizing, adjustment) {
|
||||
Run, komorebic.exe adjust-workspace-padding %sizing% %adjustment%, , Hide
|
||||
}
|
||||
|
||||
ChangeLayout(default_layout) {
|
||||
Run, komorebic.exe change-layout %default_layout%, , Hide
|
||||
}
|
||||
|
||||
LoadCustomLayout(path) {
|
||||
Run, komorebic.exe load-custom-layout %path%, , Hide
|
||||
}
|
||||
|
||||
FlipLayout(axis) {
|
||||
Run, komorebic.exe flip-layout %axis%, , Hide
|
||||
}
|
||||
|
||||
Promote() {
|
||||
Run, komorebic.exe promote, , Hide
|
||||
}
|
||||
|
||||
Retile() {
|
||||
Run, komorebic.exe retile, , Hide
|
||||
}
|
||||
|
||||
EnsureWorkspaces(monitor, workspace_count) {
|
||||
Run, komorebic.exe ensure-workspaces %monitor% %workspace_count%, , Hide
|
||||
}
|
||||
|
||||
ContainerPadding(monitor, workspace, size) {
|
||||
Run, komorebic.exe container-padding %monitor% %workspace% %size%, , Hide
|
||||
}
|
||||
|
||||
WorkspacePadding(monitor, workspace, size) {
|
||||
Run, komorebic.exe workspace-padding %monitor% %workspace% %size%, , Hide
|
||||
}
|
||||
|
||||
WorkspaceLayout(monitor, workspace, value) {
|
||||
Run, komorebic.exe workspace-layout %monitor% %workspace% %value%, , Hide
|
||||
}
|
||||
|
||||
WorkspaceCustomLayout(monitor, workspace, path) {
|
||||
Run, komorebic.exe workspace-custom-layout %monitor% %workspace% %path%, , Hide
|
||||
}
|
||||
|
||||
WorkspaceLayoutRule(monitor, workspace, at_container_count, layout) {
|
||||
Run, komorebic.exe workspace-layout-rule %monitor% %workspace% %at_container_count% %layout%, , Hide
|
||||
}
|
||||
|
||||
WorkspaceCustomLayoutRule(monitor, workspace, at_container_count, path) {
|
||||
Run, komorebic.exe workspace-custom-layout-rule %monitor% %workspace% %at_container_count% %path%, , Hide
|
||||
}
|
||||
|
||||
ClearWorkspaceLayoutRules(monitor, workspace) {
|
||||
Run, komorebic.exe clear-workspace-layout-rules %monitor% %workspace%, , Hide
|
||||
}
|
||||
|
||||
WorkspaceTiling(monitor, workspace, value) {
|
||||
Run, komorebic.exe workspace-tiling %monitor% %workspace% %value%, , Hide
|
||||
}
|
||||
|
||||
WorkspaceName(monitor, workspace, value) {
|
||||
Run, komorebic.exe workspace-name %monitor% %workspace% %value%, , Hide
|
||||
}
|
||||
|
||||
ToggleWindowContainerBehaviour() {
|
||||
Run, komorebic.exe toggle-window-container-behaviour, , Hide
|
||||
}
|
||||
|
||||
TogglePause() {
|
||||
Run, komorebic.exe toggle-pause, , Hide
|
||||
}
|
||||
|
||||
ToggleTiling() {
|
||||
Run, komorebic.exe toggle-tiling, , Hide
|
||||
}
|
||||
|
||||
ToggleFloat() {
|
||||
Run, komorebic.exe toggle-float, , Hide
|
||||
}
|
||||
|
||||
ToggleMonocle() {
|
||||
Run, komorebic.exe toggle-monocle, , Hide
|
||||
}
|
||||
|
||||
ToggleMaximize() {
|
||||
Run, komorebic.exe toggle-maximize, , Hide
|
||||
}
|
||||
|
||||
RestoreWindows() {
|
||||
Run, komorebic.exe restore-windows, , Hide
|
||||
}
|
||||
|
||||
Manage() {
|
||||
Run, komorebic.exe manage, , Hide
|
||||
}
|
||||
|
||||
Unmanage() {
|
||||
Run, komorebic.exe unmanage, , Hide
|
||||
}
|
||||
|
||||
ReloadConfiguration() {
|
||||
Run, komorebic.exe reload-configuration, , Hide
|
||||
}
|
||||
|
||||
WatchConfiguration(boolean_state) {
|
||||
Run, komorebic.exe watch-configuration %boolean_state%, , Hide
|
||||
}
|
||||
|
||||
CompleteConfiguration() {
|
||||
Run, komorebic.exe complete-configuration, , Hide
|
||||
}
|
||||
|
||||
WindowHidingBehaviour(hiding_behaviour) {
|
||||
Run, komorebic.exe window-hiding-behaviour %hiding_behaviour%, , Hide
|
||||
}
|
||||
|
||||
CrossMonitorMoveBehaviour(move_behaviour) {
|
||||
Run, komorebic.exe cross-monitor-move-behaviour %move_behaviour%, , Hide
|
||||
}
|
||||
|
||||
ToggleCrossMonitorMoveBehaviour() {
|
||||
Run, komorebic.exe toggle-cross-monitor-move-behaviour, , Hide
|
||||
}
|
||||
|
||||
UnmanagedWindowOperationBehaviour(operation_behaviour) {
|
||||
Run, komorebic.exe unmanaged-window-operation-behaviour %operation_behaviour%, , Hide
|
||||
}
|
||||
|
||||
FloatRule(identifier, id) {
|
||||
Run, komorebic.exe float-rule %identifier% "%id%", , Hide
|
||||
}
|
||||
|
||||
ManageRule(identifier, id) {
|
||||
Run, komorebic.exe manage-rule %identifier% "%id%", , Hide
|
||||
}
|
||||
|
||||
WorkspaceRule(identifier, id, monitor, workspace) {
|
||||
Run, komorebic.exe workspace-rule %identifier% "%id%" %monitor% %workspace%, , Hide
|
||||
}
|
||||
|
||||
IdentifyObjectNameChangeApplication(identifier, id) {
|
||||
Run, komorebic.exe identify-object-name-change-application %identifier% "%id%", , Hide
|
||||
}
|
||||
|
||||
IdentifyTrayApplication(identifier, id) {
|
||||
Run, komorebic.exe identify-tray-application %identifier% "%id%", , Hide
|
||||
}
|
||||
|
||||
IdentifyLayeredApplication(identifier, id) {
|
||||
Run, komorebic.exe identify-layered-application %identifier% "%id%", , Hide
|
||||
}
|
||||
|
||||
IdentifyBorderOverflowApplication(identifier, id) {
|
||||
Run, komorebic.exe identify-border-overflow-application %identifier% "%id%", , Hide
|
||||
}
|
||||
|
||||
ActiveWindowBorder(boolean_state) {
|
||||
Run, komorebic.exe active-window-border %boolean_state%, , Hide
|
||||
}
|
||||
|
||||
ActiveWindowBorderColour(r, g, b) {
|
||||
Run, komorebic.exe active-window-border-colour %r% %g% %b%, , Hide
|
||||
}
|
||||
|
||||
FocusFollowsMouse(boolean_state, implementation) {
|
||||
Run, komorebic.exe focus-follows-mouse %boolean_state% --implementation %implementation%, , Hide
|
||||
}
|
||||
|
||||
ToggleFocusFollowsMouse(implementation) {
|
||||
Run, komorebic.exe toggle-focus-follows-mouse --implementation %implementation%, , Hide
|
||||
}
|
||||
|
||||
MouseFollowsFocus(boolean_state) {
|
||||
Run, komorebic.exe mouse-follows-focus %boolean_state%, , Hide
|
||||
}
|
||||
|
||||
ToggleMouseFollowsFocus() {
|
||||
Run, komorebic.exe toggle-mouse-follows-focus, , Hide
|
||||
}
|
||||
|
||||
AhkLibrary() {
|
||||
Run, komorebic.exe ahk-library, , Hide
|
||||
}
|
||||
|
||||
AhkAppSpecificConfiguration(path, override_path) {
|
||||
Run, komorebic.exe ahk-app-specific-configuration %path% %override_path%, , Hide
|
||||
}
|
||||
|
||||
FormatAppSpecificConfiguration(path) {
|
||||
Run, komorebic.exe format-app-specific-configuration %path%, , Hide
|
||||
}
|
||||
|
||||
NotificationSchema() {
|
||||
Run, komorebic.exe notification-schema, , Hide
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "komorebic"
|
||||
version = "0.1.12"
|
||||
version = "0.1.14"
|
||||
authors = ["Jade Iqbal <jadeiqbal@fastmail.com>"]
|
||||
description = "The command-line interface for Komorebi, a tiling window manager for Windows"
|
||||
categories = ["cli", "tiling-window-manager", "windows"]
|
||||
@@ -14,7 +14,7 @@ edition = "2021"
|
||||
derive-ahk = { path = "../derive-ahk" }
|
||||
komorebi-core = { path = "../komorebi-core" }
|
||||
|
||||
clap = { version = "3", features = ["derive", "wrap_help"] }
|
||||
clap = { version = "4", features = ["derive", "wrap_help"] }
|
||||
color-eyre = "0.6"
|
||||
dirs = "4"
|
||||
fs-tail = "0.1"
|
||||
@@ -25,10 +25,11 @@ powershell_script = "1.0"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
serde_yaml = "0.9"
|
||||
sysinfo = "0.26"
|
||||
uds_windows = "1"
|
||||
|
||||
[dependencies.windows]
|
||||
version = "0.39"
|
||||
version = "0.43"
|
||||
features = [
|
||||
"Win32_Foundation",
|
||||
"Win32_UI_WindowsAndMessaging"
|
||||
|
||||
@@ -10,16 +10,17 @@ use std::io::ErrorKind;
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
use std::time::Duration;
|
||||
|
||||
use clap::AppSettings;
|
||||
use clap::ArgEnum;
|
||||
use clap::Parser;
|
||||
use clap::ValueEnum;
|
||||
use color_eyre::eyre::anyhow;
|
||||
use color_eyre::Result;
|
||||
use fs_tail::TailedFile;
|
||||
use heck::ToKebabCase;
|
||||
use lazy_static::lazy_static;
|
||||
use paste::paste;
|
||||
use sysinfo::SystemExt;
|
||||
use uds_windows::UnixListener;
|
||||
use uds_windows::UnixStream;
|
||||
use windows::Win32::Foundation::HWND;
|
||||
@@ -43,6 +44,7 @@ use komorebi_core::Rect;
|
||||
use komorebi_core::Sizing;
|
||||
use komorebi_core::SocketMessage;
|
||||
use komorebi_core::StateQuery;
|
||||
use komorebi_core::WindowKind;
|
||||
|
||||
lazy_static! {
|
||||
static ref HOME_DIR: PathBuf = {
|
||||
@@ -74,7 +76,7 @@ trait AhkFunction {
|
||||
fn generate_ahk_function() -> String;
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, ArgEnum)]
|
||||
#[derive(Copy, Clone, ValueEnum)]
|
||||
enum BooleanState {
|
||||
Enable,
|
||||
Disable,
|
||||
@@ -96,7 +98,7 @@ macro_rules! gen_enum_subcommand_args {
|
||||
paste! {
|
||||
#[derive(clap::Parser, derive_ahk::AhkFunction)]
|
||||
pub struct $name {
|
||||
#[clap(arg_enum)]
|
||||
#[clap(value_enum)]
|
||||
[<$element:snake>]: $element
|
||||
}
|
||||
}
|
||||
@@ -151,7 +153,7 @@ gen_target_subcommand_args! {
|
||||
macro_rules! gen_workspace_subcommand_args {
|
||||
// Workspace Property: #[enum] Value Enum (if the value is an Enum)
|
||||
// Workspace Property: Value Type (if the value is anything else)
|
||||
( $( $name:ident: $(#[enum] $(@$arg_enum:tt)?)? $value:ty ),+ $(,)? ) => (
|
||||
( $( $name:ident: $(#[enum] $(@$value_enum:tt)?)? $value:ty ),+ $(,)? ) => (
|
||||
paste! {
|
||||
$(
|
||||
#[derive(clap::Parser, derive_ahk::AhkFunction)]
|
||||
@@ -162,9 +164,9 @@ macro_rules! gen_workspace_subcommand_args {
|
||||
/// Workspace index on the specified monitor (zero-indexed)
|
||||
workspace: usize,
|
||||
|
||||
$(#[clap(arg_enum)] $($arg_enum)?)?
|
||||
$(#[clap(value_enum)] $($value_enum)?)?
|
||||
#[cfg_attr(
|
||||
all($(FALSE $($arg_enum)?)?),
|
||||
all($(FALSE $($value_enum)?)?),
|
||||
doc = ""$name " of the workspace as a "$value ""
|
||||
)]
|
||||
value: $value,
|
||||
@@ -212,7 +214,7 @@ pub struct WorkspaceLayoutRule {
|
||||
/// The number of window containers on-screen required to trigger this layout rule
|
||||
at_container_count: usize,
|
||||
|
||||
#[clap(arg_enum)]
|
||||
#[clap(value_enum)]
|
||||
layout: DefaultLayout,
|
||||
}
|
||||
|
||||
@@ -233,17 +235,17 @@ pub struct WorkspaceCustomLayoutRule {
|
||||
|
||||
#[derive(Parser, AhkFunction)]
|
||||
struct Resize {
|
||||
#[clap(arg_enum)]
|
||||
#[clap(value_enum)]
|
||||
edge: OperationDirection,
|
||||
#[clap(arg_enum)]
|
||||
#[clap(value_enum)]
|
||||
sizing: Sizing,
|
||||
}
|
||||
|
||||
#[derive(Parser, AhkFunction)]
|
||||
struct ResizeAxis {
|
||||
#[clap(arg_enum)]
|
||||
#[clap(value_enum)]
|
||||
axis: Axis,
|
||||
#[clap(arg_enum)]
|
||||
#[clap(value_enum)]
|
||||
sizing: Sizing,
|
||||
}
|
||||
|
||||
@@ -277,6 +279,20 @@ struct WorkAreaOffset {
|
||||
bottom: i32,
|
||||
}
|
||||
|
||||
#[derive(Parser, AhkFunction)]
|
||||
struct MonitorIndexPreference {
|
||||
/// Preferred monitor index (zero-indexed)
|
||||
index_preference: usize,
|
||||
/// Left value of the monitor's size Rect
|
||||
left: i32,
|
||||
/// Top value of the monitor's size Rect
|
||||
top: i32,
|
||||
/// Right value of the monitor's size Rect
|
||||
right: i32,
|
||||
/// Bottom value of the monitor's size Rect
|
||||
bottom: i32,
|
||||
}
|
||||
|
||||
#[derive(Parser, AhkFunction)]
|
||||
struct EnsureWorkspaces {
|
||||
/// Monitor index (zero-indexed)
|
||||
@@ -329,7 +345,7 @@ macro_rules! gen_padding_adjustment_subcommand_args {
|
||||
$(
|
||||
#[derive(clap::Parser, derive_ahk::AhkFunction)]
|
||||
pub struct $name {
|
||||
#[clap(arg_enum)]
|
||||
#[clap(value_enum)]
|
||||
sizing: Sizing,
|
||||
/// Pixels to adjust by as an integer
|
||||
adjustment: i32,
|
||||
@@ -349,7 +365,7 @@ macro_rules! gen_application_target_subcommand_args {
|
||||
$(
|
||||
#[derive(clap::Parser, derive_ahk::AhkFunction)]
|
||||
pub struct $name {
|
||||
#[clap(arg_enum)]
|
||||
#[clap(value_enum)]
|
||||
identifier: ApplicationIdentifier,
|
||||
/// Identifier as a string
|
||||
id: String,
|
||||
@@ -369,7 +385,7 @@ gen_application_target_subcommand_args! {
|
||||
|
||||
#[derive(Parser, AhkFunction)]
|
||||
struct WorkspaceRule {
|
||||
#[clap(arg_enum)]
|
||||
#[clap(value_enum)]
|
||||
identifier: ApplicationIdentifier,
|
||||
/// Identifier as a string
|
||||
id: String,
|
||||
@@ -381,26 +397,28 @@ struct WorkspaceRule {
|
||||
|
||||
#[derive(Parser, AhkFunction)]
|
||||
struct ToggleFocusFollowsMouse {
|
||||
#[clap(arg_enum, short, long, default_value = "windows")]
|
||||
#[clap(value_enum, short, long, default_value = "windows")]
|
||||
implementation: FocusFollowsMouseImplementation,
|
||||
}
|
||||
|
||||
#[derive(Parser, AhkFunction)]
|
||||
struct FocusFollowsMouse {
|
||||
#[clap(arg_enum, short, long, default_value = "windows")]
|
||||
#[clap(value_enum, short, long, default_value = "windows")]
|
||||
implementation: FocusFollowsMouseImplementation,
|
||||
#[clap(arg_enum)]
|
||||
#[clap(value_enum)]
|
||||
boolean_state: BooleanState,
|
||||
}
|
||||
|
||||
#[derive(Parser, AhkFunction)]
|
||||
struct ActiveWindowBorder {
|
||||
#[clap(arg_enum)]
|
||||
#[clap(value_enum)]
|
||||
boolean_state: BooleanState,
|
||||
}
|
||||
|
||||
#[derive(Parser, AhkFunction)]
|
||||
struct ActiveWindowBorderColour {
|
||||
#[clap(value_enum, short, long, default_value = "single")]
|
||||
window_kind: WindowKind,
|
||||
/// Red
|
||||
r: u32,
|
||||
/// Green
|
||||
@@ -417,6 +435,9 @@ struct Start {
|
||||
/// Wait for 'komorebic complete-configuration' to be sent before processing events
|
||||
#[clap(action, short, long)]
|
||||
await_configuration: bool,
|
||||
/// Start a TCP server on the given port to allow the direct sending of SocketMessages
|
||||
#[clap(action, short, long)]
|
||||
tcp_port: Option<usize>,
|
||||
}
|
||||
|
||||
#[derive(Parser, AhkFunction)]
|
||||
@@ -464,7 +485,7 @@ struct FormatAppSpecificConfiguration {
|
||||
}
|
||||
|
||||
#[derive(Parser)]
|
||||
#[clap(author, about, version, setting = AppSettings::DeriveDisplayOrder)]
|
||||
#[clap(author, about, version)]
|
||||
struct Opts {
|
||||
#[clap(subcommand)]
|
||||
subcmd: SubCommand,
|
||||
@@ -509,6 +530,10 @@ enum SubCommand {
|
||||
/// Move the focused window in the specified direction
|
||||
#[clap(arg_required_else_help = true)]
|
||||
Move(Move),
|
||||
/// Minimize the focused window
|
||||
Minimize,
|
||||
/// Close the focused window
|
||||
Close,
|
||||
/// Change focus to the window in the specified cycle direction
|
||||
#[clap(arg_required_else_help = true)]
|
||||
CycleFocus(CycleFocus),
|
||||
@@ -591,8 +616,13 @@ enum SubCommand {
|
||||
FlipLayout(FlipLayout),
|
||||
/// Promote the focused window to the top of the tree
|
||||
Promote,
|
||||
/// Promote the user focus to the top of the tree
|
||||
PromoteFocus,
|
||||
/// Force the retiling of all managed windows
|
||||
Retile,
|
||||
/// Set the monitor index preference for a monitor identified using its size
|
||||
#[clap(arg_required_else_help = true)]
|
||||
MonitorIndexPreference(MonitorIndexPreference),
|
||||
/// Create at least this many workspaces for the specified monitor
|
||||
#[clap(arg_required_else_help = true)]
|
||||
EnsureWorkspaces(EnsureWorkspaces),
|
||||
@@ -710,6 +740,8 @@ enum SubCommand {
|
||||
FormatAppSpecificConfiguration(FormatAppSpecificConfiguration),
|
||||
/// Generate a JSON Schema of subscription notifications
|
||||
NotificationSchema,
|
||||
/// Generate a JSON Schema of socket messages
|
||||
SocketSchema,
|
||||
}
|
||||
|
||||
pub fn send_message(bytes: &[u8]) -> Result<()> {
|
||||
@@ -763,9 +795,18 @@ fn main() -> Result<()> {
|
||||
SubCommand::Focus(arg) => {
|
||||
send_message(&SocketMessage::FocusWindow(arg.operation_direction).as_bytes()?)?;
|
||||
}
|
||||
SubCommand::Close => {
|
||||
send_message(&SocketMessage::Close.as_bytes()?)?;
|
||||
}
|
||||
SubCommand::Minimize => {
|
||||
send_message(&SocketMessage::Minimize.as_bytes()?)?;
|
||||
}
|
||||
SubCommand::Promote => {
|
||||
send_message(&SocketMessage::Promote.as_bytes()?)?;
|
||||
}
|
||||
SubCommand::PromoteFocus => {
|
||||
send_message(&SocketMessage::PromoteFocus.as_bytes()?)?;
|
||||
}
|
||||
SubCommand::TogglePause => {
|
||||
send_message(&SocketMessage::TogglePause.as_bytes()?)?;
|
||||
}
|
||||
@@ -937,16 +978,27 @@ fn main() -> Result<()> {
|
||||
|
||||
let script = exec.map_or_else(
|
||||
|| {
|
||||
if arg.ffm | arg.await_configuration {
|
||||
if arg.ffm | arg.await_configuration | arg.tcp_port.is_some() {
|
||||
format!(
|
||||
"Start-Process komorebi.exe -ArgumentList {} -WindowStyle hidden",
|
||||
if arg.ffm && arg.await_configuration {
|
||||
"'--ffm','--await-configuration'"
|
||||
} else if arg.ffm {
|
||||
"'--ffm'"
|
||||
} else {
|
||||
"'--await-configuration'"
|
||||
}
|
||||
arg.tcp_port.map_or_else(
|
||||
|| if arg.ffm && arg.await_configuration {
|
||||
"'--ffm','--await-configuration'".to_string()
|
||||
} else if arg.ffm {
|
||||
"'--ffm'".to_string()
|
||||
} else {
|
||||
"'--await-configuration'".to_string()
|
||||
},
|
||||
|port| if arg.ffm {
|
||||
format!("'--ffm','--tcp-port={}'", port)
|
||||
} else if arg.await_configuration {
|
||||
format!("'--await-configuration','--tcp-port={}'", port)
|
||||
} else if arg.ffm && arg.await_configuration {
|
||||
format!("'--ffm','--await-configuration','--tcp-port={}'", port)
|
||||
} else {
|
||||
format!("'--tcp-port={}'", port)
|
||||
}
|
||||
)
|
||||
)
|
||||
} else {
|
||||
String::from("Start-Process komorebi.exe -WindowStyle hidden")
|
||||
@@ -957,13 +1009,24 @@ fn main() -> Result<()> {
|
||||
format!(
|
||||
"Start-Process '{}' -ArgumentList {} -WindowStyle hidden",
|
||||
exec,
|
||||
if arg.ffm && arg.await_configuration {
|
||||
"'--ffm','--await-configuration'"
|
||||
} else if arg.ffm {
|
||||
"'--ffm'"
|
||||
} else {
|
||||
"'--await-configuration'"
|
||||
}
|
||||
arg.tcp_port.map_or_else(
|
||||
|| if arg.ffm && arg.await_configuration {
|
||||
"'--ffm','--await-configuration'".to_string()
|
||||
} else if arg.ffm {
|
||||
"'--ffm'".to_string()
|
||||
} else {
|
||||
"'--await-configuration'".to_string()
|
||||
},
|
||||
|port| if arg.ffm {
|
||||
format!("'--ffm','--tcp-port={}'", port)
|
||||
} else if arg.await_configuration {
|
||||
format!("'--await-configuration','--tcp-port={}'", port)
|
||||
} else if arg.ffm && arg.await_configuration {
|
||||
format!("'--ffm','--await-configuration','--tcp-port={}'", port)
|
||||
} else {
|
||||
format!("'--tcp-port={}'", port)
|
||||
}
|
||||
)
|
||||
)
|
||||
} else {
|
||||
format!("Start-Process '{}' -WindowStyle hidden", exec)
|
||||
@@ -971,12 +1034,29 @@ fn main() -> Result<()> {
|
||||
},
|
||||
);
|
||||
|
||||
match powershell_script::run(&script) {
|
||||
Ok(output) => {
|
||||
println!("{}", output);
|
||||
let mut running = false;
|
||||
|
||||
while !running {
|
||||
match powershell_script::run(&script) {
|
||||
Ok(_) => {
|
||||
println!("{}", script);
|
||||
}
|
||||
Err(error) => {
|
||||
println!("Error: {}", error);
|
||||
}
|
||||
}
|
||||
Err(error) => {
|
||||
println!("Error: {}", error);
|
||||
|
||||
print!("Waiting for komorebi.exe to start...");
|
||||
std::thread::sleep(Duration::from_secs(3));
|
||||
|
||||
let mut system = sysinfo::System::new_all();
|
||||
system.refresh_processes();
|
||||
|
||||
if system.processes_by_name("komorebi.exe").next().is_some() {
|
||||
println!("Started!");
|
||||
running = true;
|
||||
} else {
|
||||
println!("komorebi.exe did not start... Trying again");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1045,6 +1125,18 @@ fn main() -> Result<()> {
|
||||
.as_bytes()?,
|
||||
)?;
|
||||
}
|
||||
SubCommand::MonitorIndexPreference(arg) => {
|
||||
send_message(
|
||||
&SocketMessage::MonitorIndexPreference(
|
||||
arg.index_preference,
|
||||
arg.left,
|
||||
arg.top,
|
||||
arg.right,
|
||||
arg.bottom,
|
||||
)
|
||||
.as_bytes()?,
|
||||
)?;
|
||||
}
|
||||
SubCommand::EnsureWorkspaces(workspaces) => {
|
||||
send_message(
|
||||
&SocketMessage::EnsureWorkspaces(workspaces.monitor, workspaces.workspace_count)
|
||||
@@ -1052,7 +1144,7 @@ fn main() -> Result<()> {
|
||||
)?;
|
||||
}
|
||||
SubCommand::State => {
|
||||
let home = HOME_DIR.clone();
|
||||
let home = DATA_DIR.clone();
|
||||
let mut socket = home;
|
||||
socket.push("komorebic.sock");
|
||||
let socket = socket.as_path();
|
||||
@@ -1068,9 +1160,10 @@ fn main() -> Result<()> {
|
||||
},
|
||||
};
|
||||
|
||||
let listener = UnixListener::bind(&socket)?;
|
||||
|
||||
send_message(&SocketMessage::State.as_bytes()?)?;
|
||||
|
||||
let listener = UnixListener::bind(&socket)?;
|
||||
match listener.accept() {
|
||||
Ok(incoming) => {
|
||||
let stream = BufReader::new(incoming.0);
|
||||
@@ -1086,7 +1179,7 @@ fn main() -> Result<()> {
|
||||
}
|
||||
}
|
||||
SubCommand::Query(arg) => {
|
||||
let home = HOME_DIR.clone();
|
||||
let home = DATA_DIR.clone();
|
||||
let mut socket = home;
|
||||
socket.push("komorebic.sock");
|
||||
let socket = socket.as_path();
|
||||
@@ -1102,9 +1195,10 @@ fn main() -> Result<()> {
|
||||
},
|
||||
};
|
||||
|
||||
let listener = UnixListener::bind(&socket)?;
|
||||
|
||||
send_message(&SocketMessage::Query(arg.state_query).as_bytes()?)?;
|
||||
|
||||
let listener = UnixListener::bind(&socket)?;
|
||||
match listener.accept() {
|
||||
Ok(incoming) => {
|
||||
let stream = BufReader::new(incoming.0);
|
||||
@@ -1209,7 +1303,8 @@ fn main() -> Result<()> {
|
||||
}
|
||||
SubCommand::ActiveWindowBorderColour(arg) => {
|
||||
send_message(
|
||||
&SocketMessage::ActiveWindowBorderColour(arg.r, arg.g, arg.b).as_bytes()?,
|
||||
&SocketMessage::ActiveWindowBorderColour(arg.window_kind, arg.r, arg.g, arg.b)
|
||||
.as_bytes()?,
|
||||
)?;
|
||||
}
|
||||
SubCommand::ResizeDelta(arg) => {
|
||||
@@ -1287,7 +1382,7 @@ fn main() -> Result<()> {
|
||||
println!("File successfully formatted for PRs to https://github.com/LGUG2Z/komorebi-application-specific-configuration");
|
||||
}
|
||||
SubCommand::NotificationSchema => {
|
||||
let home = HOME_DIR.clone();
|
||||
let home = DATA_DIR.clone();
|
||||
let mut socket = home;
|
||||
socket.push("komorebic.sock");
|
||||
let socket = socket.as_path();
|
||||
@@ -1305,6 +1400,40 @@ fn main() -> Result<()> {
|
||||
|
||||
send_message(&SocketMessage::NotificationSchema.as_bytes()?)?;
|
||||
|
||||
let listener = UnixListener::bind(&socket)?;
|
||||
match listener.accept() {
|
||||
Ok(incoming) => {
|
||||
let stream = BufReader::new(incoming.0);
|
||||
for line in stream.lines() {
|
||||
println!("{}", line?);
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
Err(error) => {
|
||||
panic!("{}", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
SubCommand::SocketSchema => {
|
||||
let home = DATA_DIR.clone();
|
||||
let mut socket = home;
|
||||
socket.push("komorebic.sock");
|
||||
let socket = socket.as_path();
|
||||
|
||||
match std::fs::remove_file(&socket) {
|
||||
Ok(_) => {}
|
||||
Err(error) => match error.kind() {
|
||||
// Doing this because ::exists() doesn't work reliably on Windows via IntelliJ
|
||||
ErrorKind::NotFound => {}
|
||||
_ => {
|
||||
return Err(error.into());
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
send_message(&SocketMessage::SocketSchema.as_bytes()?)?;
|
||||
|
||||
let listener = UnixListener::bind(&socket)?;
|
||||
match listener.accept() {
|
||||
Ok(incoming) => {
|
||||
|
||||
BIN
wix/License.rtf
Normal file
BIN
wix/License.rtf
Normal file
Binary file not shown.
174
wix/main.wxs
Normal file
174
wix/main.wxs
Normal file
@@ -0,0 +1,174 @@
|
||||
<?xml version='1.0' encoding='windows-1252'?>
|
||||
<!--
|
||||
Copyright (C) 2017 Christopher R. Field.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<!--
|
||||
The "cargo wix" subcommand provides a variety of predefined variables available
|
||||
for customization of this template. The values for each variable are set at
|
||||
installer creation time. The following variables are available:
|
||||
|
||||
TargetTriple = The rustc target triple name.
|
||||
TargetEnv = The rustc target environment. This is typically either
|
||||
"msvc" or "gnu" depending on the toolchain downloaded and
|
||||
installed.
|
||||
TargetVendor = The rustc target vendor. This is typically "pc", but Rust
|
||||
does support other vendors, like "uwp".
|
||||
CargoTargetBinDir = The complete path to the binary (exe). The default would
|
||||
be "target\release\<BINARY_NAME>.exe" where
|
||||
"<BINARY_NAME>" is replaced with the name of each binary
|
||||
target defined in the package's manifest (Cargo.toml). If
|
||||
a different rustc target triple is used than the host,
|
||||
i.e. cross-compiling, then the default path would be
|
||||
"target\<CARGO_TARGET>\<CARGO_PROFILE>\<BINARY_NAME>.exe",
|
||||
where "<CARGO_TARGET>" is replaced with the "CargoTarget"
|
||||
variable value and "<CARGO_PROFILE>" is replaced with the
|
||||
value from the `CargoProfile` variable.
|
||||
CargoTargetDir = The path to the directory for the build artifacts, i.e.
|
||||
"target".
|
||||
CargoProfile = Either "debug" or `release` depending on the build
|
||||
profile. The default is "release".
|
||||
Version = The version for the installer. The default is the
|
||||
"Major.Minor.Fix" semantic versioning number of the Rust
|
||||
package.
|
||||
-->
|
||||
|
||||
<!--
|
||||
Please do not remove these pre-processor If-Else blocks. These are used with
|
||||
the `cargo wix` subcommand to automatically determine the installation
|
||||
destination for 32-bit versus 64-bit installers. Removal of these lines will
|
||||
cause installation errors.
|
||||
-->
|
||||
<?if $(sys.BUILDARCH) = x64 or $(sys.BUILDARCH) = arm64?>
|
||||
<?define PlatformProgramFilesFolder = "ProgramFiles64Folder"?>
|
||||
<?else ?>
|
||||
<?define PlatformProgramFilesFolder = "ProgramFilesFolder"?>
|
||||
<?endif ?>
|
||||
|
||||
<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>
|
||||
|
||||
<Product Id='*' Name='komorebi' UpgradeCode='F8B967B5-7E7B-4E3A-895B-B789EC898B54' Manufacturer='LGUG2Z' Language='1033' Codepage='1252' Version='$(var.Version)'>
|
||||
|
||||
<Package Id='*' Keywords='Installer' Description='A tiling window manager for Windows' Manufacturer='LGUG2Z' InstallerVersion='450' Languages='1033' Compressed='yes' InstallScope='perMachine' SummaryCodepage='1252' />
|
||||
|
||||
<MajorUpgrade Schedule='afterInstallInitialize' DowngradeErrorMessage='A newer version of [ProductName] is already installed. Setup will now exit.' />
|
||||
|
||||
<Media Id='1' Cabinet='media1.cab' EmbedCab='yes' DiskPrompt='CD-ROM #1' />
|
||||
<Property Id='DiskPrompt' Value='komorebi Installation' />
|
||||
|
||||
<Directory Id='TARGETDIR' Name='SourceDir'>
|
||||
<Directory Id='$(var.PlatformProgramFilesFolder)' Name='PFiles'>
|
||||
<Directory Id='APPLICATIONFOLDER' Name='komorebi'>
|
||||
<!--
|
||||
Disabling the license sidecar file in the installer is a two step process:
|
||||
|
||||
1. Comment out or remove the `Component` tag along with its contents.
|
||||
2. Comment out or remove the `ComponentRef` tag with the "License" Id
|
||||
attribute value further down in this file.
|
||||
-->
|
||||
<Component Id='License' Guid='*'>
|
||||
<File Id='LicenseFile' Name='License.rtf' DiskId='1' Source='wix\License.rtf' KeyPath='yes' />
|
||||
</Component>
|
||||
|
||||
<Directory Id='Bin' Name='bin'>
|
||||
<Component Id='Path' Guid='6C6DF276-06C4-4675-BDED-48C5C2BC9BC5' KeyPath='yes'>
|
||||
<Environment Id='PATH' Name='PATH' Value='[Bin]' Permanent='no' Part='last' Action='set' System='yes' />
|
||||
</Component>
|
||||
<Component Id='binary0' Guid='*'>
|
||||
<File Id='exe0' Name='komorebi.exe' DiskId='1' Source='$(var.CargoTargetBinDir)\komorebi.exe' KeyPath='yes' />
|
||||
</Component>
|
||||
<Component Id='binary1' Guid='*'>
|
||||
<File Id='exe1' Name='komorebic.exe' DiskId='1' Source='$(var.CargoTargetBinDir)\komorebic.exe' KeyPath='yes' />
|
||||
</Component>
|
||||
</Directory>
|
||||
</Directory>
|
||||
</Directory>
|
||||
</Directory>
|
||||
|
||||
<Feature Id='Binaries' Title='Application' Description='Installs all binaries and the license.' Level='1' ConfigurableDirectory='APPLICATIONFOLDER' AllowAdvertise='no' Display='expand' Absent='disallow'>
|
||||
<!--
|
||||
Comment out or remove the following `ComponentRef` tag to remove
|
||||
the license sidecar file from the installer.
|
||||
-->
|
||||
<ComponentRef Id='License' />
|
||||
|
||||
<ComponentRef Id='binary0' />
|
||||
|
||||
<ComponentRef Id='binary1' />
|
||||
|
||||
<Feature Id='Environment' Title='PATH Environment Variable' Description='Add the install location of the [ProductName] executable to the PATH system environment variable. This allows the [ProductName] executable to be called from any location.' Level='1' Absent='allow'>
|
||||
<ComponentRef Id='Path' />
|
||||
</Feature>
|
||||
</Feature>
|
||||
|
||||
<SetProperty Id='ARPINSTALLLOCATION' Value='[APPLICATIONFOLDER]' After='CostFinalize' />
|
||||
|
||||
|
||||
<!--
|
||||
Uncomment the following `Icon` and `Property` tags to change the product icon.
|
||||
|
||||
The product icon is the graphic that appears in the Add/Remove
|
||||
Programs control panel for the application.
|
||||
-->
|
||||
<!--<Icon Id='ProductICO' SourceFile='wix\Product.ico'/>-->
|
||||
<!--<Property Id='ARPPRODUCTICON' Value='ProductICO' />-->
|
||||
|
||||
<Property Id='ARPHELPLINK' Value='https://github.com/LGUG2Z/komorebi' />
|
||||
|
||||
<UI>
|
||||
<UIRef Id='WixUI_FeatureTree' />
|
||||
<!--
|
||||
Disabling the EULA dialog in the installer is a two step process:
|
||||
|
||||
1. Uncomment the following two `Publish` tags
|
||||
2. Comment out or remove the `<WiXVariable Id='WixUILicenseRtf'...` tag further down
|
||||
|
||||
-->
|
||||
<!--<Publish Dialog='WelcomeDlg' Control='Next' Event='NewDialog' Value='CustomizeDlg' Order='99'>1</Publish>-->
|
||||
<!--<Publish Dialog='CustomizeDlg' Control='Back' Event='NewDialog' Value='WelcomeDlg' Order='99'>1</Publish>-->
|
||||
|
||||
</UI>
|
||||
|
||||
<!--
|
||||
Disabling the EULA dialog in the installer requires commenting out
|
||||
or removing the following `WixVariable` tag
|
||||
-->
|
||||
<WixVariable Id='WixUILicenseRtf' Value='wix\License.rtf' />
|
||||
|
||||
|
||||
<!--
|
||||
Uncomment the next `WixVaraible` tag to customize the installer's
|
||||
Graphical User Interface (GUI) and add a custom banner image across
|
||||
the top of each screen. See the WiX Toolset documentation for details
|
||||
about customization.
|
||||
|
||||
The banner BMP dimensions are 493 x 58 pixels.
|
||||
-->
|
||||
<!--<WixVariable Id='WixUIBannerBmp' Value='wix\Banner.bmp'/>-->
|
||||
|
||||
|
||||
<!--
|
||||
Uncomment the next `WixVariable` tag to customize the installer's
|
||||
Graphical User Interface (GUI) and add a custom image to the first
|
||||
dialog, or screen. See the WiX Toolset documentation for details about
|
||||
customization.
|
||||
|
||||
The dialog BMP dimensions are 493 x 312 pixels.
|
||||
-->
|
||||
<!--<WixVariable Id='WixUIDialogBmp' Value='wix\Dialog.bmp'/>-->
|
||||
|
||||
</Product>
|
||||
|
||||
</Wix>
|
||||
Reference in New Issue
Block a user