mirror of
https://github.com/LGUG2Z/komorebi.git
synced 2026-02-10 15:27:42 +01:00
Compare commits
1 Commits
v0.1.8
...
feature/re
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
987dc2b8dd |
2
.github/workflows/windows.yaml
vendored
2
.github/workflows/windows.yaml
vendored
@@ -83,8 +83,6 @@ jobs:
|
||||
path: |
|
||||
target/${{ matrix.target }}/release/komorebi.exe
|
||||
target/${{ matrix.target }}/release/komorebic.exe
|
||||
target/${{ matrix.target }}/release/komorebi.pdb
|
||||
target/${{ matrix.target }}/release/komorebic.pdb
|
||||
retention-days: 7
|
||||
- name: Generate changelog
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
|
||||
453
Cargo.lock
generated
453
Cargo.lock
generated
@@ -4,9 +4,9 @@ version = 3
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.17.0"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b"
|
||||
checksum = "3e61f2b7f93d2c7d2b08263acaa4a363b3e276806c68af6134c44f523bf1aacd"
|
||||
dependencies = [
|
||||
"gimli",
|
||||
]
|
||||
@@ -45,9 +45,9 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.63"
|
||||
version = "0.3.61"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "321629d8ba6513061f26707241fa9bc89524ff1cd7a915a97ef0c62c666ce1b6"
|
||||
checksum = "e7a905d892734eea339e896738c14b9afce22b5318f64b951e70bf3844419b01"
|
||||
dependencies = [
|
||||
"addr2line",
|
||||
"cc",
|
||||
@@ -58,6 +58,13 @@ dependencies = [
|
||||
"rustc-demangle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bindings"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
@@ -66,9 +73,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.72"
|
||||
version = "1.0.71"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee"
|
||||
checksum = "79c2681d6594606957bbb8631c4b90a7fcaaa72cdb714743a437b156d6a7eedd"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
@@ -83,10 +90,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "3.0.8"
|
||||
name = "chrono"
|
||||
version = "0.4.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "31b34190c12bd1d613deba77e1cc13e68eaf4a0d51e389dbd485b7bfe15a47c0"
|
||||
checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"time",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "3.0.0-beta.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fcd70aa5597dbc42f7217a543f9ef2768b2ef823ba29036072d30e1d88e98406"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"bitflags",
|
||||
@@ -96,17 +116,17 @@ dependencies = [
|
||||
"os_str_bytes",
|
||||
"strsim",
|
||||
"termcolor",
|
||||
"terminal_size",
|
||||
"textwrap",
|
||||
"vec_map",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "3.0.6"
|
||||
version = "3.0.0-beta.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "517358c28fcef6607bf6f76108e02afad7e82297d132a6b846dcc1fc3efcd153"
|
||||
checksum = "0b5bb0d655624a0b8770d1c178fb8ffcb1f91cc722cb08f451e3dc72465421ac"
|
||||
dependencies = [
|
||||
"heck 0.4.0",
|
||||
"heck",
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -140,6 +160,43 @@ dependencies = [
|
||||
"tracing-error",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "com"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a30a2b2a013da986dc5cc3eda3d19c0d59d53f835be1b2356eb8d00f000c793"
|
||||
dependencies = [
|
||||
"com_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "com_macros"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7606b05842fea68ddcc89e8053b8860ebcb2a0ba8d6abfe3a148e5d5a8d3f0c1"
|
||||
dependencies = [
|
||||
"com_macros_support",
|
||||
"proc-macro2",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "com_macros_support"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97e9a6d20f4ac8830e309a455d7e9416e65c6af5a97c88c55fbb4c2012e107da"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const-sha1"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb58b6451e8c2a812ad979ed1d83378caa5e927eef2622017a45f251457c2c9d"
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.3"
|
||||
@@ -148,9 +205,9 @@ checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.5.2"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e54ea8bc3fb1ee042f5aace6e3c6e025d3874866da222930f70ce62aceba0bfa"
|
||||
checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"crossbeam-utils",
|
||||
@@ -169,9 +226,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.6"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97242a70df9b89a65d0b6df3c4bf5b9ce03c5b7309019777fbde37e7537f8762"
|
||||
checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"crossbeam-utils",
|
||||
@@ -182,9 +239,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.6"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cfcae03edb34f947e64acdb1c33ec169824e20657e9ecb61cef6c8c74dcb8120"
|
||||
checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"lazy_static",
|
||||
@@ -229,6 +286,12 @@ dependencies = [
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dtoa"
|
||||
version = "0.4.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.6.1"
|
||||
@@ -315,9 +378,9 @@ checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.4"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c"
|
||||
checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
@@ -326,9 +389,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "getset"
|
||||
version = "0.1.2"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e45727250e75cc04ff2846a66397da8ef2b3db8e40e0cef4df67950a07621eb9"
|
||||
checksum = "24b328c01a4d71d2d8173daa93562a73ab0fe85616876f02500f53d82948c504"
|
||||
dependencies = [
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
@@ -338,9 +401,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.26.1"
|
||||
version = "0.25.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4"
|
||||
checksum = "f0a01e0497841a3b2db4f8afa483cce65f7e96a3498bd6c541734792aeac8fe7"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
@@ -357,12 +420,6 @@ dependencies = [
|
||||
"unicode-segmentation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.19"
|
||||
@@ -390,9 +447,9 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.8.0"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223"
|
||||
checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown",
|
||||
@@ -420,9 +477,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "instant"
|
||||
version = "0.1.12"
|
||||
version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
|
||||
checksum = "716d3d89f35ac6a34fd0eed635395f4c3b76fa889338a4632e5231a8684216bd"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
]
|
||||
@@ -442,12 +499,6 @@ version = "0.4.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
|
||||
|
||||
[[package]]
|
||||
name = "kernel32-sys"
|
||||
version = "0.2.2"
|
||||
@@ -460,8 +511,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "komorebi"
|
||||
version = "0.1.8"
|
||||
version = "0.1.6"
|
||||
dependencies = [
|
||||
"bindings",
|
||||
"bitflags",
|
||||
"clap",
|
||||
"color-eyre",
|
||||
@@ -473,7 +525,7 @@ dependencies = [
|
||||
"hotwatch",
|
||||
"komorebi-core",
|
||||
"lazy_static",
|
||||
"miow 0.4.0",
|
||||
"miow 0.3.7",
|
||||
"nanoid",
|
||||
"parking_lot",
|
||||
"paste",
|
||||
@@ -483,44 +535,43 @@ dependencies = [
|
||||
"sysinfo",
|
||||
"tracing",
|
||||
"tracing-appender",
|
||||
"tracing-subscriber 0.3.6",
|
||||
"tracing-subscriber",
|
||||
"uds_windows",
|
||||
"which",
|
||||
"windows",
|
||||
"winput",
|
||||
"winreg",
|
||||
"winvd",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "komorebi-core"
|
||||
version = "0.1.8"
|
||||
version = "0.1.6"
|
||||
dependencies = [
|
||||
"bindings",
|
||||
"clap",
|
||||
"color-eyre",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_yaml",
|
||||
"strum",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "komorebic"
|
||||
version = "0.1.8"
|
||||
version = "0.1.6"
|
||||
dependencies = [
|
||||
"bindings",
|
||||
"clap",
|
||||
"color-eyre",
|
||||
"derive-ahk",
|
||||
"dirs",
|
||||
"fs-tail",
|
||||
"heck 0.4.0",
|
||||
"heck",
|
||||
"komorebi-core",
|
||||
"paste",
|
||||
"powershell_script",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"uds_windows",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -537,9 +588,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.112"
|
||||
version = "0.2.103"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125"
|
||||
checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6"
|
||||
|
||||
[[package]]
|
||||
name = "linked-hash-map"
|
||||
@@ -567,9 +618,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "matchers"
|
||||
version = "0.1.0"
|
||||
version = "0.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
|
||||
checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1"
|
||||
dependencies = [
|
||||
"regex-automata",
|
||||
]
|
||||
@@ -582,9 +633,9 @@ checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.6.5"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
|
||||
checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
@@ -644,11 +695,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "miow"
|
||||
version = "0.4.0"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7377f7792b3afb6a3cba68daa54ca23c032137010460d667fda53a8d66be00e"
|
||||
checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21"
|
||||
dependencies = [
|
||||
"windows-sys",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -673,9 +724,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.23.1"
|
||||
version = "0.23.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6"
|
||||
checksum = "f305c2c2e4c39a82f7bf0bf65fb557f9070ce06781d4f2454295cc34b1c43188"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cc",
|
||||
@@ -712,10 +763,29 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.13.1"
|
||||
name = "num-integer"
|
||||
version = "0.1.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
|
||||
checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
@@ -723,27 +793,24 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.27.1"
|
||||
version = "0.26.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9"
|
||||
checksum = "39f37e50073ccad23b6d09bcb5b263f4e76d3bb6038e4a3c08e52162ffa8abc2"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.9.0"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5"
|
||||
checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"
|
||||
|
||||
[[package]]
|
||||
name = "os_str_bytes"
|
||||
version = "6.0.0"
|
||||
version = "3.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
checksum = "6acbef58a60fe69ab50510a55bc8cdd4d6cf2283d27ad338f54cb52747a9cf2d"
|
||||
|
||||
[[package]]
|
||||
name = "owo-colors"
|
||||
@@ -781,9 +848,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "paste"
|
||||
version = "1.0.6"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0744126afe1a6dd7f394cb50a716dbe086cb06e255e53d8d0185d82828358fb5"
|
||||
checksum = "acbf547ad0c65e31259204bd90935776d1c693cec2f4ff7abb7a1bbbd40dfe58"
|
||||
|
||||
[[package]]
|
||||
name = "petgraph"
|
||||
@@ -797,9 +864,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.8"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c"
|
||||
checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443"
|
||||
|
||||
[[package]]
|
||||
name = "powershell_script"
|
||||
@@ -809,9 +876,9 @@ checksum = "36d62894f5590e88d99d0d82918742ba8e5bff1985af15d4906b6a65f635adb2"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.16"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
|
||||
checksum = "c3ca011bd0129ff4ae15cd04c4eef202cadf6c51c21e47aba319b4e0501db741"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
@@ -839,18 +906,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.36"
|
||||
version = "1.0.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
|
||||
checksum = "edc3358ebc67bc8b7fa0c007f945b0b18226f78437d61bec735a9eb96b61ee70"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.14"
|
||||
version = "1.0.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "47aa80447ce4daf1717500037052af176af5d38cc3e571d9ec1c7353fc10c87d"
|
||||
checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
@@ -1015,17 +1082,11 @@ version = "0.1.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.9"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
|
||||
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
@@ -1044,18 +1105,18 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.133"
|
||||
version = "1.0.130"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97565067517b60e2d1ea8b268e59ce036de907ac523ad83a0475da04e818989a"
|
||||
checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.133"
|
||||
version = "1.0.130"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed201699328568d8d08208fdd080e3ff594e6c422e438b6705905da01005d537"
|
||||
checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1064,23 +1125,23 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.75"
|
||||
version = "1.0.68"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c059c05b48c5c0067d4b4b2b4f0732dd65feb52daf7e0ea09cd87e7dadc1af79"
|
||||
checksum = "0f690853975602e1bfe1ccbf50504d67174e3bcf340f23b5ea9992e0587a52d8"
|
||||
dependencies = [
|
||||
"itoa 1.0.1",
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_yaml"
|
||||
version = "0.8.23"
|
||||
version = "0.8.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4a521f2940385c165a24ee286aa8599633d162077a54bdcae2a6fd5a7bfa7a0"
|
||||
checksum = "d8c608a35705a5d3cdc9fbe403147647ff34b921f8e833e49306df898f9b20af"
|
||||
dependencies = [
|
||||
"dtoa",
|
||||
"indexmap",
|
||||
"ryu",
|
||||
"serde",
|
||||
"yaml-rust",
|
||||
]
|
||||
@@ -1102,9 +1163,9 @@ checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.8.0"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83"
|
||||
checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
@@ -1114,31 +1175,30 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
|
||||
[[package]]
|
||||
name = "strum"
|
||||
version = "0.23.0"
|
||||
version = "0.21.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cae14b91c7d11c9a851d3fbc80a963198998c2a64eec840477fa92d8ce9b70bb"
|
||||
checksum = "aaf86bbcfd1fa9670b7a129f64fc0c9fcbbfe4f1bc4210e9e98fe71ffc12cde2"
|
||||
dependencies = [
|
||||
"strum_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strum_macros"
|
||||
version = "0.23.1"
|
||||
version = "0.21.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5bb0dc7ee9c15cea6199cde9a127fa16a4c5819af85395457ad72d68edc85a38"
|
||||
checksum = "d06aaeeee809dbc59eb4556183dd927df67db1540de5be8d3ec0b6636358a5ec"
|
||||
dependencies = [
|
||||
"heck 0.3.3",
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rustversion",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.85"
|
||||
version = "1.0.80"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a684ac3dcd8913827e18cd09a68384ee66c1de24157e3c556c9ab16d85695fb7"
|
||||
checksum = "d010a1623fbd906d51d650a9916aaefc05ffa0e4053ff7fe601167f3e715d194"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1147,9 +1207,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sysinfo"
|
||||
version = "0.22.5"
|
||||
version = "0.20.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f1bfab07306a27332451a662ca9c8156e3a9986f82660ba9c8e744fe8455d43"
|
||||
checksum = "e223c65cd36b485a34c2ce6e38efa40777d31c4166d9076030c74cdcf971679f"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"core-foundation-sys",
|
||||
@@ -1179,23 +1239,13 @@ dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "terminal_size"
|
||||
version = "0.1.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.14.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80"
|
||||
dependencies = [
|
||||
"terminal_size",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1220,12 +1270,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.5"
|
||||
version = "0.1.43"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41effe7cfa8af36f439fac33861b66b049edc6f9a32331e2312660529c1c24ad"
|
||||
checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438"
|
||||
dependencies = [
|
||||
"itoa 0.4.8",
|
||||
"libc",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1242,13 +1292,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tracing-appender"
|
||||
version = "0.2.0"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94571df2eae3ed4353815ea5a90974a594a1792d8782ff2cbcc9392d1101f366"
|
||||
checksum = "9965507e507f12c8901432a33e31131222abac31edd90cabbcf85cf544b7127a"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"crossbeam-channel",
|
||||
"time",
|
||||
"tracing-subscriber 0.3.6",
|
||||
"tracing-subscriber",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1278,7 +1328,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4d7c0b83d4a500748fa5879461652b361edf5c9d51ede2a2ac03875ca185e24"
|
||||
dependencies = [
|
||||
"tracing",
|
||||
"tracing-subscriber 0.2.25",
|
||||
"tracing-subscriber",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1293,32 +1343,35 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-subscriber"
|
||||
version = "0.2.25"
|
||||
name = "tracing-serde"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e0d2eaa99c3c2e41547cfa109e910a68ea03823cccad4a0525dcbc9b01e8c71"
|
||||
checksum = "fb65ea441fbb84f9f6748fd496cf7f63ec9af5bca94dd86456978d055e8eb28b"
|
||||
dependencies = [
|
||||
"sharded-slab",
|
||||
"thread_local",
|
||||
"serde",
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-subscriber"
|
||||
version = "0.3.6"
|
||||
version = "0.2.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77be66445c4eeebb934a7340f227bfe7b338173d3f8c00a60a5a58005c9faecf"
|
||||
checksum = "0e0d2eaa99c3c2e41547cfa109e910a68ea03823cccad4a0525dcbc9b01e8c71"
|
||||
dependencies = [
|
||||
"ansi_term",
|
||||
"chrono",
|
||||
"lazy_static",
|
||||
"matchers",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sharded-slab",
|
||||
"smallvec",
|
||||
"thread_local",
|
||||
"tracing",
|
||||
"tracing-core",
|
||||
"tracing-log",
|
||||
"tracing-serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1337,6 +1390,12 @@ version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.2"
|
||||
@@ -1344,10 +1403,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
name = "vec_map"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
@@ -1422,89 +1487,49 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.30.0"
|
||||
version = "0.21.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b749ebd2304aa012c5992d11a25d07b406bdbe5f79d371cb7a918ce501a19eb0"
|
||||
checksum = "b8f5f8d2ea79bf690bbee453fd4a1516ae426e5d5c7215d96cc0c3dc134fc4a0"
|
||||
dependencies = [
|
||||
"windows_aarch64_msvc 0.30.0",
|
||||
"windows_i686_gnu 0.30.0",
|
||||
"windows_i686_msvc 0.30.0",
|
||||
"windows_x86_64_gnu 0.30.0",
|
||||
"windows_x86_64_msvc 0.30.0",
|
||||
"const-sha1",
|
||||
"windows_gen",
|
||||
"windows_macros",
|
||||
"windows_reader",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.28.0"
|
||||
name = "windows_gen"
|
||||
version = "0.21.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "82ca39602d5cbfa692c4b67e3bcbb2751477355141c1ed434c94da4186836ff6"
|
||||
checksum = "7e6994f42f8481387778cc608407d6703410672d57f32a66009419d7a18aa912"
|
||||
dependencies = [
|
||||
"windows_aarch64_msvc 0.28.0",
|
||||
"windows_i686_gnu 0.28.0",
|
||||
"windows_i686_msvc 0.28.0",
|
||||
"windows_x86_64_gnu 0.28.0",
|
||||
"windows_x86_64_msvc 0.28.0",
|
||||
"windows_quote",
|
||||
"windows_reader",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.28.0"
|
||||
name = "windows_macros"
|
||||
version = "0.21.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52695a41e536859d5308cc613b4a022261a274390b25bd29dfff4bf08505f3c2"
|
||||
checksum = "81cc2357b1b03c19f056cb0e6d06011f80f54beadb4e36aee2ca98493c7cfc3c"
|
||||
dependencies = [
|
||||
"syn",
|
||||
"windows_gen",
|
||||
"windows_quote",
|
||||
"windows_reader",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.30.0"
|
||||
name = "windows_quote"
|
||||
version = "0.21.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29277a4435d642f775f63c7d1faeb927adba532886ce0287bd985bffb16b6bca"
|
||||
checksum = "7cf987b5288c15e1997226848f78f3ed3ef8b78dcfd71a201c8c8684163a7e4d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.28.0"
|
||||
name = "windows_reader"
|
||||
version = "0.21.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f54725ac23affef038fecb177de6c9bf065787c2f432f79e3c373da92f3e1d8a"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1145e1989da93956c68d1864f32fb97c8f561a8f89a5125f6a2b7ea75524e4b8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.28.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51d5158a43cc43623c0729d1ad6647e62fa384a3d135fd15108d37c683461f64"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4a09e3a0d4753b73019db171c1339cd4362c8c44baf1bcea336235e955954a6"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.28.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc31f409f565611535130cfe7ee8e6655d3fa99c1c61013981e491921b5ce954"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ca64fcb0220d58db4c119e050e7af03c69e6f4f415ef69ec1773d9aab422d5a"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.28.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f2b8c7cbd3bfdddd9ab98769f9746a7fad1bca236554cd032b78d768bc0e89f"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08cabc9f0066848fef4bc6a1c1668e6efce38b661d2aeec75d18d8617eebb5f1"
|
||||
checksum = "237b53e8b40766ea7db5da0d8c6c1442d21d0429f0ee7500d7b5688967bd9d7b"
|
||||
|
||||
[[package]]
|
||||
name = "winput"
|
||||
@@ -1516,12 +1541,14 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winreg"
|
||||
version = "0.10.1"
|
||||
name = "winvd"
|
||||
version = "0.0.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d"
|
||||
checksum = "2bab2d5c745381b9c72797230150ec62244e693064fa0d654b5c4e6c75132a56"
|
||||
dependencies = [
|
||||
"winapi 0.3.9",
|
||||
"com",
|
||||
"crossbeam-channel",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
[workspace]
|
||||
|
||||
members = [
|
||||
"bindings",
|
||||
"derive-ahk",
|
||||
"komorebi",
|
||||
"komorebi-core",
|
||||
|
||||
175
README.md
175
README.md
@@ -18,15 +18,10 @@ Translations of this document can be found in the project wiki:
|
||||
|
||||
- [komorebi 中文用户指南](https://github.com/LGUG2Z/komorebi/wiki/README-zh) (by [@crosstyan](https://github.com/crosstyan))
|
||||
|
||||
There is a [Discord server](https://discord.gg/mGkn66PHkx) available for _komorebi_-related discussion, help,
|
||||
There is a [Discord server](https://discord.gg/vzBmPm6RkQ) available for _komorebi_-related discussion, help,
|
||||
troubleshooting etc. If you have any specific feature requests or bugs to report, please create an issue in this
|
||||
repository.
|
||||
|
||||
Articles, blog posts, demos, and videos about _komorebi_ can be added to this list by PR:
|
||||
|
||||
- [Moving to Windows from Linux Pt 1](https://kvwu.io/posts/moving-to-windows/)
|
||||
- [Windows 下的现代化平铺窗口管理器 komorebi](https://zhuanlan.zhihu.com/p/455064481)
|
||||
|
||||
## Description
|
||||
|
||||
_komorebi_ only responds to [WinEvents](https://docs.microsoft.com/en-us/windows/win32/winauto/event-constants) and the
|
||||
@@ -193,16 +188,6 @@ passing it as an argument to the `--implementation` flag:
|
||||
komorebic.exe toggle-focus-follows-mouse --implementation komorebi
|
||||
```
|
||||
|
||||
#### Mouse Follows Focus
|
||||
|
||||
By default, the mouse will move to the center of the window when the focus is changed in a given direction. This
|
||||
behaviour is know is 'mouse follows focus'. To disable this behaviour across all workspaces, add the following command
|
||||
to your configuration file:
|
||||
|
||||
```ahk
|
||||
Run, komorebic.exe toggle-mouse-follows-focus, , Hide
|
||||
```
|
||||
|
||||
#### Saving and Loading Resized Layouts
|
||||
|
||||
If you create a BSP layout through various resize adjustments that you want to be able to restore easily in the future,
|
||||
@@ -287,77 +272,69 @@ keybindings with. You can run `komorebic.exe <COMMAND> --help` to get a full exp
|
||||
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
|
||||
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-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)
|
||||
window-hiding-behaviour Set the window behaviour when switching workspaces / cycling stacks
|
||||
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-tray-application Identify an application that closes to the system tray
|
||||
identify-border-overflow Identify an application that has overflowing borders
|
||||
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
|
||||
help Print this message or the help of the given subcommand(s)
|
||||
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 Quicksave the current resize layout dimensions
|
||||
quick-load Load the last quicksaved resize layout dimensions
|
||||
save Save the current resize layout dimensions to a file
|
||||
load 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 Resize the focused window in the specified direction
|
||||
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
|
||||
focus-monitor Focus the specified monitor
|
||||
focus-workspace Focus the specified workspace on the focused monitor
|
||||
cycle-monitor Focus the monitor in the given cycle direction
|
||||
cycle-workspace Focus the workspace in the given cycle direction
|
||||
new-workspace Create and append a new workspace on the focused monitor
|
||||
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-tiling Enable or disable window tiling for the specified workspace
|
||||
workspace-name Set the workspace name for the specified workspace
|
||||
toggle-pause Toggle the window manager on and off across all monitors
|
||||
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)
|
||||
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-tray-application Identify an application that closes to the system tray
|
||||
identify-border-overflow Identify an application that has overflowing borders
|
||||
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
|
||||
ahk-library Generate a library of AutoHotKey helper functions
|
||||
help Print this message or the help of the given subcommand(s)
|
||||
```
|
||||
|
||||
### AutoHotKey Helper Library for `komorebic`
|
||||
@@ -382,11 +359,8 @@ used [is available here](komorebi.sample.with.lib.ahk).
|
||||
- [x] Move focused window container to workspace follow
|
||||
- [x] Send focused window container to monitor
|
||||
- [x] Send focused window container to workspace
|
||||
- [x] Move focused workspace to monitor
|
||||
- [x] Mouse follows focused container
|
||||
- [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] Quicksave and quickload layouts with resize dimensions
|
||||
- [x] Save and load layouts with resize dimensions to/from specific files
|
||||
@@ -411,7 +385,6 @@ used [is available here](komorebi.sample.with.lib.ahk).
|
||||
- [x] Toggle floating windows
|
||||
- [x] Toggle monocle window
|
||||
- [x] Toggle native maximization
|
||||
- [x] Toggle mouse follows focus
|
||||
- [x] Toggle Xmouse/Windows focus follows mouse implementation
|
||||
- [x] Toggle Komorebi focus follows mouse implementation (desktop and system tray-aware)
|
||||
- [x] Toggle automatic tiling
|
||||
@@ -497,16 +470,16 @@ Note that you do not have to include the full path of the named pipe, just the n
|
||||
If the named pipe exists, `komorebi` will start pushing JSON data of successfully handled events and messages:
|
||||
|
||||
```json lines
|
||||
{"event":{"type":"AddSubscriber","content":"yasb"},"state":{}}
|
||||
{"event":{"type":"FocusWindow","content":"Left"},"state":{}}
|
||||
{"event":{"type":"FocusChange","content":["SystemForeground",{"hwnd":131444,"title":"komorebi – README.md","exe":"idea64.exe","class":"SunAwtFrame","rect":{"left":13,"top":60,"right":1520,"bottom":1655}}]},"state":{}}
|
||||
{"event":{"type":"MonitorPoll","content":["ObjectCreate",{"hwnd":5572450,"title":"OLEChannelWnd","exe":"explorer.exe","class":"OleMainThreadWndClass","rect":{"left":0,"top":0,"right":0,"bottom":0}}]},"state":{}}
|
||||
{"event":{"type":"FocusWindow","content":"Right"},"state":{}}
|
||||
{"event":{"type":"FocusChange","content":["SystemForeground",{"hwnd":132968,"title":"Windows PowerShell","exe":"WindowsTerminal.exe","class":"CASCADIA_HOSTING_WINDOW_CLASS","rect":{"left":1539,"top":60,"right":1520,"bottom":821}}]},"state":{}}
|
||||
{"event":{"type":"FocusWindow","content":"Down"},"state":{}}
|
||||
{"event":{"type":"FocusChange","content":["SystemForeground",{"hwnd":329264,"title":"den — Mozilla Firefox","exe":"firefox.exe","class":"MozillaWindowClass","rect":{"left":1539,"top":894,"right":1520,"bottom":821}}]},"state":{}}
|
||||
{"event":{"type":"FocusWindow","content":"Up"},"state":{}}
|
||||
{"event":{"type":"FocusChange","content":["SystemForeground",{"hwnd":132968,"title":"Windows PowerShell","exe":"WindowsTerminal.exe","class":"CASCADIA_HOSTING_WINDOW_CLASS","rect":{"left":1539,"top":60,"right":1520,"bottom":821}}]},"state":{}}
|
||||
{"event":{"type":"AddSubscriber","content":"yasb"},"state":{...}}
|
||||
{"event":{"type":"FocusWindow","content":"Left"},"state":{...}}
|
||||
{"event":{"type":"FocusChange","content":["SystemForeground",{"hwnd":131444,"title":"komorebi – README.md","exe":"idea64.exe","class":"SunAwtFrame","rect":{"left":13,"top":60,"right":1520,"bottom":1655}}]},"state":{...}}
|
||||
{"event":{"type":"MonitorPoll","content":["ObjectCreate",{"hwnd":5572450,"title":"OLEChannelWnd","exe":"explorer.exe","class":"OleMainThreadWndClass","rect":{"left":0,"top":0,"right":0,"bottom":0}}]},"state":{...}}
|
||||
{"event":{"type":"FocusWindow","content":"Right"},"state":{...}}
|
||||
{"event":{"type":"FocusChange","content":["SystemForeground",{"hwnd":132968,"title":"Windows PowerShell","exe":"WindowsTerminal.exe","class":"CASCADIA_HOSTING_WINDOW_CLASS","rect":{"left":1539,"top":60,"right":1520,"bottom":821}}]},"state":{}...}
|
||||
{"event":{"type":"FocusWindow","content":"Down"},"state":{...}}
|
||||
{"event":{"type":"FocusChange","content":["SystemForeground",{"hwnd":329264,"title":"den — Mozilla Firefox","exe":"firefox.exe","class":"MozillaWindowClass","rect":{"left":1539,"top":894,"right":1520,"bottom":821}}]},"state":{...}}
|
||||
{"event":{"type":"FocusWindow","content":"Up"},"state":{...}}
|
||||
{"event":{"type":"FocusChange","content":["SystemForeground",{"hwnd":132968,"title":"Windows PowerShell","exe":"WindowsTerminal.exe","class":"CASCADIA_HOSTING_WINDOW_CLASS","rect":{"left":1539,"top":60,"right":1520,"bottom":821}}]},"state":{...}}
|
||||
```
|
||||
|
||||
You may then filter on the `type` key to listen to the events that you are interested in. For a full list of possible
|
||||
|
||||
13
bindings/Cargo.toml
Normal file
13
bindings/Cargo.toml
Normal file
@@ -0,0 +1,13 @@
|
||||
[package]
|
||||
name = "bindings"
|
||||
version = "0.1.0"
|
||||
authors = ["Jade Iqbal"]
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
windows = "0.21"
|
||||
|
||||
[build-dependencies]
|
||||
windows = "0.21"
|
||||
26
bindings/build.rs
Normal file
26
bindings/build.rs
Normal file
@@ -0,0 +1,26 @@
|
||||
fn main() {
|
||||
windows::build!(
|
||||
Windows::Win32::Foundation::RECT,
|
||||
Windows::Win32::Foundation::POINT,
|
||||
Windows::Win32::Foundation::BOOL,
|
||||
Windows::Win32::Foundation::PWSTR,
|
||||
Windows::Win32::Foundation::HWND,
|
||||
Windows::Win32::Foundation::LPARAM,
|
||||
// error: `Windows.Win32.Graphics.Dwm.DWMWA_CLOAKED` not found in metadata
|
||||
Windows::Win32::Graphics::Dwm::*,
|
||||
// error: `Windows.Win32.Graphics.Gdi.MONITOR_DEFAULTTONEAREST` not found in metadata
|
||||
Windows::Win32::Graphics::Gdi::*,
|
||||
Windows::Win32::System::Threading::PROCESS_ACCESS_RIGHTS,
|
||||
Windows::Win32::System::Threading::PROCESS_NAME_FORMAT,
|
||||
Windows::Win32::System::Threading::OpenProcess,
|
||||
Windows::Win32::System::Threading::QueryFullProcessImageNameW,
|
||||
Windows::Win32::System::Threading::GetCurrentThreadId,
|
||||
Windows::Win32::System::Threading::AttachThreadInput,
|
||||
Windows::Win32::System::Threading::GetCurrentProcessId,
|
||||
Windows::Win32::UI::KeyboardAndMouseInput::SetFocus,
|
||||
Windows::Win32::UI::Accessibility::SetWinEventHook,
|
||||
Windows::Win32::UI::Accessibility::HWINEVENTHOOK,
|
||||
// error: `Windows.Win32.UI.WindowsAndMessaging.GWL_EXSTYLE` not found in metadata
|
||||
Windows::Win32::UI::WindowsAndMessaging::*,
|
||||
);
|
||||
}
|
||||
4
bindings/src/lib.rs
Normal file
4
bindings/src/lib.rs
Normal file
@@ -0,0 +1,4 @@
|
||||
pub use windows::Handle;
|
||||
pub use windows::Result;
|
||||
|
||||
::windows::include_bindings!();
|
||||
42
justfile
42
justfile
@@ -1,42 +0,0 @@
|
||||
set shell := ["cmd.exe", "/C"]
|
||||
export RUST_BACKTRACE := "full"
|
||||
|
||||
clean:
|
||||
cargo clean
|
||||
|
||||
fmt:
|
||||
cargo +nightly fmt
|
||||
cargo +nightly clippy
|
||||
prettier --write README.md
|
||||
|
||||
install-komorebic:
|
||||
cargo +stable install --path komorebic --locked
|
||||
|
||||
install-komorebi:
|
||||
cargo +stable install --path komorebi --locked
|
||||
|
||||
install:
|
||||
just install-komorebic
|
||||
just install-komorebi
|
||||
komorebic ahk-library
|
||||
cat '%USERPROFILE%\komorebic.lib.ahk' > komorebic.lib.sample.ahk
|
||||
|
||||
run:
|
||||
just install-komorebic
|
||||
cargo +stable run --bin komorebi --locked
|
||||
|
||||
warn $RUST_LOG="warn":
|
||||
just run
|
||||
|
||||
info $RUST_LOG="info":
|
||||
just run
|
||||
|
||||
debug $RUST_LOG="debug":
|
||||
just run
|
||||
|
||||
trace $RUST_LOG="trace":
|
||||
just run
|
||||
|
||||
deadlock $RUST_LOG="trace":
|
||||
just install-komorebic
|
||||
cargo +stable run --bin komorebi --locked --features deadlock_detection
|
||||
@@ -1,20 +1,16 @@
|
||||
[package]
|
||||
name = "komorebi-core"
|
||||
version = "0.1.8"
|
||||
version = "0.1.6"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "3", features = ["derive"] }
|
||||
bindings = { package = "bindings", path = "../bindings" }
|
||||
|
||||
clap = "3.0.0-beta.4"
|
||||
color-eyre = "0.5"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
serde_yaml = "0.8"
|
||||
strum = { version = "0.23", features = ["derive"] }
|
||||
|
||||
[dependencies.windows]
|
||||
version = "0.30"
|
||||
features = [
|
||||
"Win32_Foundation",
|
||||
]
|
||||
strum = { version = "0.21", features = ["derive"] }
|
||||
|
||||
@@ -19,7 +19,7 @@ pub trait Arrangement {
|
||||
area: &Rect,
|
||||
len: NonZeroUsize,
|
||||
container_padding: Option<i32>,
|
||||
layout_flip: Option<Axis>,
|
||||
layout_flip: Option<Flip>,
|
||||
resize_dimensions: &[Option<Rect>],
|
||||
) -> Vec<Rect>;
|
||||
}
|
||||
@@ -31,7 +31,7 @@ impl Arrangement for DefaultLayout {
|
||||
area: &Rect,
|
||||
len: NonZeroUsize,
|
||||
container_padding: Option<i32>,
|
||||
layout_flip: Option<Axis>,
|
||||
layout_flip: Option<Flip>,
|
||||
resize_dimensions: &[Option<Rect>],
|
||||
) -> Vec<Rect> {
|
||||
let len = usize::from(len);
|
||||
@@ -57,7 +57,7 @@ impl Arrangement for DefaultLayout {
|
||||
let mut stack_left = area.left + primary_right;
|
||||
|
||||
match layout_flip {
|
||||
Some(Axis::Horizontal | Axis::HorizontalAndVertical) if len > 1 => {
|
||||
Some(Flip::Horizontal | Flip::HorizontalAndVertical) if len > 1 => {
|
||||
main_left = main_left + area.right - primary_right;
|
||||
stack_left = area.left;
|
||||
}
|
||||
@@ -99,7 +99,7 @@ impl Arrangement for DefaultLayout {
|
||||
let mut stack_top = area.top + bottom;
|
||||
|
||||
match layout_flip {
|
||||
Some(Axis::Vertical | Axis::HorizontalAndVertical) if len > 1 => {
|
||||
Some(Flip::Vertical | Flip::HorizontalAndVertical) if len > 1 => {
|
||||
main_top = main_top + area.bottom - bottom;
|
||||
stack_top = area.top;
|
||||
}
|
||||
@@ -150,7 +150,7 @@ impl Arrangement for DefaultLayout {
|
||||
let mut secondary = area.left;
|
||||
|
||||
match layout_flip {
|
||||
Some(Axis::Horizontal | Axis::HorizontalAndVertical) if len > 1 => {
|
||||
Some(Flip::Horizontal | Flip::HorizontalAndVertical) if len > 1 => {
|
||||
primary = area.left;
|
||||
secondary = area.left + primary_right;
|
||||
}
|
||||
@@ -165,7 +165,7 @@ impl Arrangement for DefaultLayout {
|
||||
let mut stack = area.left + primary_right + secondary_right;
|
||||
|
||||
match layout_flip {
|
||||
Some(Axis::Horizontal | Axis::HorizontalAndVertical) if len > 1 => {
|
||||
Some(Flip::Horizontal | Flip::HorizontalAndVertical) if len > 1 => {
|
||||
secondary = area.left + primary_right + secondary_right;
|
||||
stack = area.left;
|
||||
}
|
||||
@@ -224,7 +224,7 @@ impl Arrangement for CustomLayout {
|
||||
area: &Rect,
|
||||
len: NonZeroUsize,
|
||||
container_padding: Option<i32>,
|
||||
_layout_flip: Option<Axis>,
|
||||
_layout_flip: Option<Flip>,
|
||||
_resize_dimensions: &[Option<Rect>],
|
||||
) -> Vec<Rect> {
|
||||
let mut dimensions = vec![];
|
||||
@@ -343,7 +343,7 @@ impl Arrangement for CustomLayout {
|
||||
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString, ArgEnum)]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum Axis {
|
||||
pub enum Flip {
|
||||
Horizontal,
|
||||
Vertical,
|
||||
HorizontalAndVertical,
|
||||
@@ -478,7 +478,7 @@ fn recursive_fibonacci(
|
||||
idx: usize,
|
||||
count: usize,
|
||||
area: &Rect,
|
||||
layout_flip: Option<Axis>,
|
||||
layout_flip: Option<Flip>,
|
||||
resize_adjustments: Vec<Option<Rect>>,
|
||||
) -> Vec<Rect> {
|
||||
let mut a = *area;
|
||||
@@ -502,21 +502,21 @@ fn recursive_fibonacci(
|
||||
|
||||
if let Some(flip) = layout_flip {
|
||||
match flip {
|
||||
Axis::Horizontal => {
|
||||
Flip::Horizontal => {
|
||||
main_x = resized.left + half_width + (half_width - half_resized_width);
|
||||
alt_x = resized.left;
|
||||
|
||||
alt_y = resized.top + half_resized_height;
|
||||
main_y = resized.top;
|
||||
}
|
||||
Axis::Vertical => {
|
||||
Flip::Vertical => {
|
||||
main_y = resized.top + half_height + (half_height - half_resized_height);
|
||||
alt_y = resized.top;
|
||||
|
||||
main_x = resized.left;
|
||||
alt_x = resized.left + half_resized_width;
|
||||
}
|
||||
Axis::HorizontalAndVertical => {
|
||||
Flip::HorizontalAndVertical => {
|
||||
main_x = resized.left + half_width + (half_width - half_resized_width);
|
||||
alt_x = resized.left;
|
||||
main_y = resized.top + half_height + (half_height - half_resized_height);
|
||||
|
||||
@@ -2,7 +2,6 @@ use std::collections::HashMap;
|
||||
use std::fs::File;
|
||||
use std::io::BufReader;
|
||||
use std::ops::Deref;
|
||||
use std::ops::DerefMut;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use color_eyre::eyre::anyhow;
|
||||
@@ -23,12 +22,6 @@ impl Deref for CustomLayout {
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for CustomLayout {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl CustomLayout {
|
||||
pub fn from_path_buf(path: PathBuf) -> Result<Self> {
|
||||
let invalid_filetype = anyhow!("custom layouts must be json or yaml files");
|
||||
@@ -82,14 +75,6 @@ impl CustomLayout {
|
||||
None
|
||||
}
|
||||
|
||||
pub fn set_primary_width_percentage(&mut self, percentage: usize) {
|
||||
for column in self.iter_mut() {
|
||||
if let Column::Primary(Option::Some(ColumnWidth::WidthPercentage(current))) = column {
|
||||
*current = percentage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn is_valid(&self) -> bool {
|
||||
// A valid layout must have at least one column
|
||||
|
||||
@@ -28,7 +28,7 @@ impl DefaultLayout {
|
||||
resize: &Option<Rect>,
|
||||
edge: OperationDirection,
|
||||
sizing: Sizing,
|
||||
delta: i32,
|
||||
step: Option<i32>,
|
||||
) -> Option<Rect> {
|
||||
if !matches!(self, Self::BSP) {
|
||||
return None;
|
||||
@@ -37,7 +37,7 @@ impl DefaultLayout {
|
||||
let max_divisor = 1.005;
|
||||
let mut r = resize.unwrap_or_default();
|
||||
|
||||
let resize_delta = delta;
|
||||
let resize_step = step.unwrap_or(50);
|
||||
|
||||
match edge {
|
||||
OperationDirection::Left => match sizing {
|
||||
@@ -52,65 +52,65 @@ impl DefaultLayout {
|
||||
// with index 0. I don't think it's worth trying to defensively program
|
||||
// against this; if people end up in this situation they are better off
|
||||
// just hitting the retile command
|
||||
let diff = ((r.left + -resize_delta) as f32).abs();
|
||||
let diff = ((r.left + -resize_step) as f32).abs();
|
||||
let max = unaltered.right as f32 / max_divisor;
|
||||
if diff < max {
|
||||
r.left += -resize_delta;
|
||||
r.left += -resize_step;
|
||||
}
|
||||
}
|
||||
Sizing::Decrease => {
|
||||
let diff = ((r.left - -resize_delta) as f32).abs();
|
||||
let diff = ((r.left - -resize_step) as f32).abs();
|
||||
let max = unaltered.right as f32 / max_divisor;
|
||||
if diff < max {
|
||||
r.left -= -resize_delta;
|
||||
r.left -= -resize_step;
|
||||
}
|
||||
}
|
||||
},
|
||||
OperationDirection::Up => match sizing {
|
||||
Sizing::Increase => {
|
||||
let diff = ((r.top + resize_delta) as f32).abs();
|
||||
let diff = ((r.top + resize_step) as f32).abs();
|
||||
let max = unaltered.bottom as f32 / max_divisor;
|
||||
if diff < max {
|
||||
r.top += -resize_delta;
|
||||
r.top += -resize_step;
|
||||
}
|
||||
}
|
||||
Sizing::Decrease => {
|
||||
let diff = ((r.top - resize_delta) as f32).abs();
|
||||
let diff = ((r.top - resize_step) as f32).abs();
|
||||
let max = unaltered.bottom as f32 / max_divisor;
|
||||
if diff < max {
|
||||
r.top -= -resize_delta;
|
||||
r.top -= -resize_step;
|
||||
}
|
||||
}
|
||||
},
|
||||
OperationDirection::Right => match sizing {
|
||||
Sizing::Increase => {
|
||||
let diff = ((r.right + resize_delta) as f32).abs();
|
||||
let diff = ((r.right + resize_step) as f32).abs();
|
||||
let max = unaltered.right as f32 / max_divisor;
|
||||
if diff < max {
|
||||
r.right += resize_delta;
|
||||
r.right += resize_step;
|
||||
}
|
||||
}
|
||||
Sizing::Decrease => {
|
||||
let diff = ((r.right - resize_delta) as f32).abs();
|
||||
let diff = ((r.right - resize_step) as f32).abs();
|
||||
let max = unaltered.right as f32 / max_divisor;
|
||||
if diff < max {
|
||||
r.right -= resize_delta;
|
||||
r.right -= resize_step;
|
||||
}
|
||||
}
|
||||
},
|
||||
OperationDirection::Down => match sizing {
|
||||
Sizing::Increase => {
|
||||
let diff = ((r.bottom + resize_delta) as f32).abs();
|
||||
let diff = ((r.bottom + resize_step) as f32).abs();
|
||||
let max = unaltered.bottom as f32 / max_divisor;
|
||||
if diff < max {
|
||||
r.bottom += resize_delta;
|
||||
r.bottom += resize_step;
|
||||
}
|
||||
}
|
||||
Sizing::Decrease => {
|
||||
let diff = ((r.bottom - resize_delta) as f32).abs();
|
||||
let diff = ((r.bottom - resize_step) as f32).abs();
|
||||
let max = unaltered.bottom as f32 / max_divisor;
|
||||
if diff < max {
|
||||
r.bottom -= resize_delta;
|
||||
r.bottom -= resize_step;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -12,7 +12,7 @@ use strum::Display;
|
||||
use strum::EnumString;
|
||||
|
||||
pub use arrangement::Arrangement;
|
||||
pub use arrangement::Axis;
|
||||
pub use arrangement::Flip;
|
||||
pub use custom_layout::CustomLayout;
|
||||
pub use cycle_direction::CycleDirection;
|
||||
pub use default_layout::DefaultLayout;
|
||||
@@ -39,21 +39,17 @@ pub enum SocketMessage {
|
||||
CycleFocusWindow(CycleDirection),
|
||||
CycleMoveWindow(CycleDirection),
|
||||
StackWindow(OperationDirection),
|
||||
ResizeWindowEdge(OperationDirection, Sizing),
|
||||
ResizeWindowAxis(Axis, Sizing),
|
||||
ResizeWindow(OperationDirection, Sizing),
|
||||
UnstackWindow,
|
||||
CycleStack(CycleDirection),
|
||||
MoveContainerToMonitorNumber(usize),
|
||||
MoveContainerToWorkspaceNumber(usize),
|
||||
SendContainerToMonitorNumber(usize),
|
||||
SendContainerToWorkspaceNumber(usize),
|
||||
MoveWorkspaceToMonitorNumber(usize),
|
||||
Promote,
|
||||
ToggleFloat,
|
||||
ToggleMonocle,
|
||||
ToggleMaximize,
|
||||
ToggleWindowContainerBehaviour,
|
||||
WindowHidingBehaviour(HidingBehaviour),
|
||||
// Current Workspace Commands
|
||||
ManageFocusedWindow,
|
||||
UnmanageFocusedWindow,
|
||||
@@ -61,7 +57,7 @@ pub enum SocketMessage {
|
||||
AdjustWorkspacePadding(Sizing, i32),
|
||||
ChangeLayout(DefaultLayout),
|
||||
ChangeLayoutCustom(PathBuf),
|
||||
FlipLayout(Axis),
|
||||
FlipLayout(Flip),
|
||||
// Monitor and Workspace Commands
|
||||
EnsureWorkspaces(usize, usize),
|
||||
NewWorkspace,
|
||||
@@ -77,7 +73,6 @@ pub enum SocketMessage {
|
||||
CycleFocusWorkspace(CycleDirection),
|
||||
FocusMonitorNumber(usize),
|
||||
FocusWorkspaceNumber(usize),
|
||||
FocusMonitorWorkspaceNumber(usize, usize),
|
||||
ContainerPadding(usize, usize, i32),
|
||||
WorkspacePadding(usize, usize, i32),
|
||||
WorkspaceTiling(usize, usize, bool),
|
||||
@@ -89,18 +84,17 @@ pub enum SocketMessage {
|
||||
WatchConfiguration(bool),
|
||||
InvisibleBorders(Rect),
|
||||
WorkAreaOffset(Rect),
|
||||
ResizeDelta(i32),
|
||||
WorkspaceRule(ApplicationIdentifier, String, usize, usize),
|
||||
FloatRule(ApplicationIdentifier, String),
|
||||
ManageRule(ApplicationIdentifier, String),
|
||||
IdentifyTrayApplication(ApplicationIdentifier, String),
|
||||
IdentifyBorderOverflow(ApplicationIdentifier, String),
|
||||
RemoveTitleBar(ApplicationIdentifier, String),
|
||||
ToggleTitleBars,
|
||||
State,
|
||||
Query(StateQuery),
|
||||
FocusFollowsMouse(FocusFollowsMouseImplementation, bool),
|
||||
ToggleFocusFollowsMouse(FocusFollowsMouseImplementation),
|
||||
MouseFollowsFocus(bool),
|
||||
ToggleMouseFollowsFocus,
|
||||
AddSubscriber(String),
|
||||
RemoveSubscriber(String),
|
||||
}
|
||||
@@ -143,20 +137,6 @@ pub enum FocusFollowsMouseImplementation {
|
||||
Windows,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString, ArgEnum)]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum WindowContainerBehaviour {
|
||||
Create,
|
||||
Append,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, Display, EnumString, ArgEnum)]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum HidingBehaviour {
|
||||
Hide,
|
||||
Minimize,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString, ArgEnum)]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum Sizing {
|
||||
|
||||
@@ -7,7 +7,7 @@ use strum::Display;
|
||||
use strum::EnumString;
|
||||
|
||||
use crate::direction::Direction;
|
||||
use crate::Axis;
|
||||
use crate::Flip;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString, ArgEnum)]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
@@ -29,23 +29,23 @@ impl OperationDirection {
|
||||
}
|
||||
}
|
||||
|
||||
fn flip(self, layout_flip: Option<Axis>) -> Self {
|
||||
fn flip(self, layout_flip: Option<Flip>) -> Self {
|
||||
layout_flip.map_or(self, |flip| match self {
|
||||
Self::Left => match flip {
|
||||
Axis::Horizontal | Axis::HorizontalAndVertical => Self::Right,
|
||||
Axis::Vertical => self,
|
||||
Flip::Horizontal | Flip::HorizontalAndVertical => Self::Right,
|
||||
Flip::Vertical => self,
|
||||
},
|
||||
Self::Right => match flip {
|
||||
Axis::Horizontal | Axis::HorizontalAndVertical => Self::Left,
|
||||
Axis::Vertical => self,
|
||||
Flip::Horizontal | Flip::HorizontalAndVertical => Self::Left,
|
||||
Flip::Vertical => self,
|
||||
},
|
||||
Self::Up => match flip {
|
||||
Axis::Vertical | Axis::HorizontalAndVertical => Self::Down,
|
||||
Axis::Horizontal => self,
|
||||
Flip::Vertical | Flip::HorizontalAndVertical => Self::Down,
|
||||
Flip::Horizontal => self,
|
||||
},
|
||||
Self::Down => match flip {
|
||||
Axis::Vertical | Axis::HorizontalAndVertical => Self::Up,
|
||||
Axis::Horizontal => self,
|
||||
Flip::Vertical | Flip::HorizontalAndVertical => Self::Up,
|
||||
Flip::Horizontal => self,
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -54,7 +54,7 @@ impl OperationDirection {
|
||||
pub fn destination(
|
||||
self,
|
||||
layout: &dyn Direction,
|
||||
layout_flip: Option<Axis>,
|
||||
layout_flip: Option<Flip>,
|
||||
idx: usize,
|
||||
len: NonZeroUsize,
|
||||
) -> Option<usize> {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use windows::Win32::Foundation::RECT;
|
||||
|
||||
use bindings::Windows::Win32::Foundation::RECT;
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, Serialize, Deserialize, Eq, PartialEq)]
|
||||
pub struct Rect {
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
#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")
|
||||
|
||||
@@ -37,7 +34,7 @@ WorkspaceTiling(0, 4, "disable") ; Everything floats here
|
||||
|
||||
; Configure floating rules
|
||||
FloatRule("class", "SunAwtDialog") ; All the IntelliJ popups
|
||||
FloatRule("title", "Control Panel")
|
||||
FloatRule("title", "Control Panek")
|
||||
FloatRule("class", "TaskManagerWindow")
|
||||
FloatRule("exe", "Wally.exe")
|
||||
FloatRule("exe", "wincompose.exe")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "komorebi"
|
||||
version = "0.1.8"
|
||||
version = "0.1.6"
|
||||
authors = ["Jade Iqbal <jadeiqbal@fastmail.com>"]
|
||||
description = "A tiling window manager for Windows"
|
||||
categories = ["tiling-window-manager", "windows"]
|
||||
@@ -11,10 +11,11 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
bindings = { package = "bindings", path = "../bindings" }
|
||||
komorebi-core = { path = "../komorebi-core" }
|
||||
|
||||
bitflags = "1"
|
||||
clap = { version = "3", features = ["derive"] }
|
||||
clap = "3.0.0-beta.4"
|
||||
color-eyre = "0.5"
|
||||
crossbeam-channel = "0.5"
|
||||
crossbeam-utils = "0.8"
|
||||
@@ -28,29 +29,16 @@ parking_lot = { version = "0.11", features = ["deadlock_detection"] }
|
||||
paste = "1"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
strum = { version = "0.23", features = ["derive"] }
|
||||
sysinfo = "0.22"
|
||||
strum = { version = "0.21", features = ["derive"] }
|
||||
sysinfo = "0.20"
|
||||
tracing = "0.1"
|
||||
tracing-appender = "0.2"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
tracing-appender = "0.1"
|
||||
tracing-subscriber = "0.2"
|
||||
uds_windows = "1"
|
||||
which = "4"
|
||||
winput = "0.2"
|
||||
miow = "0.4"
|
||||
winreg = "0.10"
|
||||
|
||||
[dependencies.windows]
|
||||
version = "0.30"
|
||||
features = [
|
||||
"Win32_Foundation",
|
||||
"Win32_Graphics_Dwm",
|
||||
"Win32_Graphics_Gdi",
|
||||
"Win32_System_Threading",
|
||||
"Win32_System_RemoteDesktop",
|
||||
"Win32_UI_Input_KeyboardAndMouse",
|
||||
"Win32_UI_Accessibility",
|
||||
"Win32_UI_WindowsAndMessaging"
|
||||
]
|
||||
winvd = "0.0.20"
|
||||
miow = "0.3"
|
||||
|
||||
[features]
|
||||
deadlock_detection = []
|
||||
|
||||
@@ -78,18 +78,18 @@ impl Container {
|
||||
}
|
||||
|
||||
pub fn remove_window_by_idx(&mut self, idx: usize) -> Option<Window> {
|
||||
let window = self.windows_mut().remove(idx);
|
||||
|
||||
if idx != 0 {
|
||||
self.focus_window(idx - 1);
|
||||
};
|
||||
|
||||
window
|
||||
self.windows_mut().remove(idx)
|
||||
}
|
||||
|
||||
pub fn remove_focused_window(&mut self) -> Option<Window> {
|
||||
let focused_idx = self.focused_window_idx();
|
||||
self.remove_window_by_idx(focused_idx)
|
||||
let window = self.remove_window_by_idx(focused_idx);
|
||||
|
||||
if focused_idx != 0 {
|
||||
self.focus_window(focused_idx - 1);
|
||||
}
|
||||
|
||||
window
|
||||
}
|
||||
|
||||
pub fn add_window(&mut self, window: Window) {
|
||||
|
||||
@@ -6,7 +6,6 @@ use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::process::Command;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::atomic::AtomicU32;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::Arc;
|
||||
#[cfg(feature = "deadlock_detection")]
|
||||
@@ -14,7 +13,7 @@ use std::thread;
|
||||
#[cfg(feature = "deadlock_detection")]
|
||||
use std::time::Duration;
|
||||
|
||||
use clap::Parser;
|
||||
use clap::Clap;
|
||||
use color_eyre::eyre::anyhow;
|
||||
use color_eyre::Result;
|
||||
use crossbeam_channel::Receiver;
|
||||
@@ -24,16 +23,12 @@ use lazy_static::lazy_static;
|
||||
use parking_lot::deadlock;
|
||||
use parking_lot::Mutex;
|
||||
use serde::Serialize;
|
||||
use sysinfo::ProcessExt;
|
||||
use sysinfo::SystemExt;
|
||||
use tracing_appender::non_blocking::WorkerGuard;
|
||||
use tracing_subscriber::layer::SubscriberExt;
|
||||
use tracing_subscriber::EnvFilter;
|
||||
use which::which;
|
||||
use winreg::enums::HKEY_CURRENT_USER;
|
||||
use winreg::RegKey;
|
||||
|
||||
use komorebi_core::HidingBehaviour;
|
||||
use komorebi_core::SocketMessage;
|
||||
|
||||
use crate::process_command::listen_for_commands;
|
||||
@@ -83,12 +78,7 @@ lazy_static! {
|
||||
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![]));
|
||||
static ref FLOAT_IDENTIFIERS: Arc<Mutex<Vec<String>>> = Arc::new(Mutex::new(vec![
|
||||
// mstsc.exe creates these on Windows 11 when a WSL process is launched
|
||||
// https://github.com/LGUG2Z/komorebi/issues/74
|
||||
"OPContainerClass".to_string(),
|
||||
"IHWindowClass".to_string()
|
||||
]));
|
||||
static ref FLOAT_IDENTIFIERS: Arc<Mutex<Vec<String>>> = Arc::new(Mutex::new(vec![]));
|
||||
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(),
|
||||
@@ -97,12 +87,13 @@ lazy_static! {
|
||||
]));
|
||||
static ref SUBSCRIPTION_PIPES: Arc<Mutex<HashMap<String, File>>> =
|
||||
Arc::new(Mutex::new(HashMap::new()));
|
||||
static ref HIDING_BEHAVIOUR: Arc<Mutex<HidingBehaviour>> =
|
||||
Arc::new(Mutex::new(HidingBehaviour::Minimize));
|
||||
// Use app-specific titlebar removal options where possible
|
||||
// eg. Windows Terminal, IntelliJ IDEA, Firefox
|
||||
static ref NO_TITLEBAR: Arc<Mutex<Vec<String>>> = Arc::new(Mutex::new(vec![]));
|
||||
}
|
||||
|
||||
pub static CUSTOM_FFM: AtomicBool = AtomicBool::new(false);
|
||||
pub static SESSION_ID: AtomicU32 = AtomicU32::new(0);
|
||||
pub static REMOVE_TITLEBARS: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
fn setup() -> Result<(WorkerGuard, WorkerGuard)> {
|
||||
if std::env::var("RUST_LIB_BACKTRACE").is_err() {
|
||||
@@ -146,23 +137,20 @@ fn setup() -> Result<(WorkerGuard, WorkerGuard)> {
|
||||
// occurred to be recorded.
|
||||
std::panic::set_hook(Box::new(|panic| {
|
||||
// If the panic has a source location, record it as structured fields.
|
||||
panic.location().map_or_else(
|
||||
|| {
|
||||
tracing::error!(message = %panic);
|
||||
},
|
||||
|location| {
|
||||
// On nightly Rust, where the `PanicInfo` type also exposes a
|
||||
// `message()` method returning just the message, we could record
|
||||
// just the message instead of the entire `fmt::Display`
|
||||
// implementation, avoiding the duplciated location
|
||||
tracing::error!(
|
||||
message = %panic,
|
||||
panic.file = location.file(),
|
||||
panic.line = location.line(),
|
||||
panic.column = location.column(),
|
||||
);
|
||||
},
|
||||
);
|
||||
if let Some(location) = panic.location() {
|
||||
// On nightly Rust, where the `PanicInfo` type also exposes a
|
||||
// `message()` method returning just the message, we could record
|
||||
// just the message instead of the entire `fmt::Display`
|
||||
// implementation, avoiding the duplciated location
|
||||
tracing::error!(
|
||||
message = %panic,
|
||||
panic.file = location.file(),
|
||||
panic.line = location.line(),
|
||||
panic.column = location.column(),
|
||||
);
|
||||
} else {
|
||||
tracing::error!(message = %panic);
|
||||
}
|
||||
}));
|
||||
|
||||
Ok((guard, color_guard))
|
||||
@@ -206,49 +194,6 @@ pub fn load_configuration() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn current_virtual_desktop() -> Option<Vec<u8>> {
|
||||
let hkcu = RegKey::predef(HKEY_CURRENT_USER);
|
||||
|
||||
// This is the path on Windows 10
|
||||
let mut current = hkcu
|
||||
.open_subkey(format!(
|
||||
r#"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\SessionInfo\{}\VirtualDesktops"#,
|
||||
SESSION_ID.load(Ordering::SeqCst)
|
||||
))
|
||||
.ok()
|
||||
.and_then(
|
||||
|desktops| match desktops.get_raw_value("CurrentVirtualDesktop") {
|
||||
Ok(current) => Option::from(current.bytes),
|
||||
Err(_) => None,
|
||||
},
|
||||
);
|
||||
|
||||
// This is the path on Windows 11
|
||||
if current.is_none() {
|
||||
current = hkcu
|
||||
.open_subkey(r#"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VirtualDesktops"#)
|
||||
.ok()
|
||||
.and_then(
|
||||
|desktops| match desktops.get_raw_value("CurrentVirtualDesktop") {
|
||||
Ok(current) => Option::from(current.bytes),
|
||||
Err(_) => None,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// For Win10 users that do not use virtual desktops, the CurrentVirtualDesktop value will not
|
||||
// exist until one has been created in the task view
|
||||
|
||||
// The registry value will also not exist on user login if virtual desktops have been created
|
||||
// but the task view has not been initiated
|
||||
|
||||
// In both of these cases, we return None, and the virtual desktop validation will never run. In
|
||||
// the latter case, if the user desires this validation after initiating the task view, komorebi
|
||||
// should be restarted, and then when this // fn runs again for the first time, it will pick up
|
||||
// the value of CurrentVirtualDesktop and validate against it accordingly
|
||||
current
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum NotificationEvent {
|
||||
@@ -319,7 +264,7 @@ fn detect_deadlocks() {
|
||||
});
|
||||
}
|
||||
|
||||
#[derive(Parser)]
|
||||
#[derive(Clap)]
|
||||
#[clap(author, about, version)]
|
||||
struct Opts {
|
||||
/// Allow the use of komorebi's custom focus-follows-mouse implementation
|
||||
@@ -336,26 +281,12 @@ fn main() -> Result<()> {
|
||||
let has_valid_args = arg_count == 1 || (arg_count == 2 && CUSTOM_FFM.load(Ordering::SeqCst));
|
||||
|
||||
if has_valid_args {
|
||||
let session_id = WindowsApi::process_id_to_session_id()?;
|
||||
SESSION_ID.store(session_id, Ordering::SeqCst);
|
||||
|
||||
let mut system = sysinfo::System::new_all();
|
||||
system.refresh_processes();
|
||||
|
||||
let matched_procs = system.process_by_name("komorebi.exe");
|
||||
|
||||
if matched_procs.len() > 1 {
|
||||
let mut shim_is_active = false;
|
||||
for proc in matched_procs {
|
||||
if proc.root().ends_with("shims") {
|
||||
shim_is_active = true;
|
||||
}
|
||||
}
|
||||
|
||||
if !shim_is_active {
|
||||
tracing::error!("komorebi.exe is already running, please exit the existing process before starting a new one");
|
||||
std::process::exit(1);
|
||||
}
|
||||
if system.process_by_name("komorebi.exe").len() > 1 {
|
||||
tracing::error!("komorebi.exe is already running, please exit the existing process before starting a new one");
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
// File logging worker guard has to have an assignment in the main fn to work
|
||||
@@ -400,12 +331,7 @@ fn main() -> Result<()> {
|
||||
|
||||
tracing::error!("received ctrl-c, restoring all hidden windows and terminating process");
|
||||
|
||||
wm.lock().restore_all_windows();
|
||||
|
||||
if WindowsApi::focus_follows_mouse()? {
|
||||
WindowsApi::disable_focus_follows_mouse()?;
|
||||
}
|
||||
|
||||
wm.lock().restore_all_windows()?;
|
||||
std::process::exit(130);
|
||||
}
|
||||
|
||||
|
||||
@@ -45,11 +45,11 @@ pub fn new(id: isize, size: Rect, work_area_size: Rect) -> Monitor {
|
||||
}
|
||||
|
||||
impl Monitor {
|
||||
pub fn load_focused_workspace(&mut self, mouse_follows_focus: bool) -> Result<()> {
|
||||
pub fn load_focused_workspace(&mut self) -> Result<()> {
|
||||
let focused_idx = self.focused_workspace_idx();
|
||||
for (i, workspace) in self.workspaces_mut().iter_mut().enumerate() {
|
||||
if i == focused_idx {
|
||||
workspace.restore(mouse_follows_focus)?;
|
||||
workspace.restore()?;
|
||||
} else {
|
||||
workspace.hide();
|
||||
}
|
||||
@@ -68,20 +68,6 @@ impl Monitor {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn remove_workspace_by_idx(&mut self, idx: usize) -> Option<Workspace> {
|
||||
if idx < self.workspaces().len() {
|
||||
return self.workspaces_mut().remove(idx);
|
||||
}
|
||||
|
||||
if idx == 0 {
|
||||
self.workspaces_mut().push_back(Workspace::default());
|
||||
} else {
|
||||
self.focus_workspace(idx - 1).ok()?;
|
||||
};
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
pub fn ensure_workspace_count(&mut self, ensure_count: usize) {
|
||||
if self.workspaces().len() < ensure_count {
|
||||
self.workspaces_mut()
|
||||
|
||||
@@ -15,18 +15,11 @@ use miow::pipe::connect;
|
||||
use parking_lot::Mutex;
|
||||
use uds_windows::UnixStream;
|
||||
|
||||
use komorebi_core::ApplicationIdentifier;
|
||||
use komorebi_core::Axis;
|
||||
use komorebi_core::FocusFollowsMouseImplementation;
|
||||
use komorebi_core::Layout;
|
||||
use komorebi_core::OperationDirection;
|
||||
use komorebi_core::Rect;
|
||||
use komorebi_core::Sizing;
|
||||
use komorebi_core::SocketMessage;
|
||||
use komorebi_core::StateQuery;
|
||||
use komorebi_core::WindowContainerBehaviour;
|
||||
|
||||
use crate::current_virtual_desktop;
|
||||
use crate::notify_subscribers;
|
||||
use crate::window_manager;
|
||||
use crate::window_manager::WindowManager;
|
||||
@@ -36,8 +29,9 @@ use crate::NotificationEvent;
|
||||
use crate::BORDER_OVERFLOW_IDENTIFIERS;
|
||||
use crate::CUSTOM_FFM;
|
||||
use crate::FLOAT_IDENTIFIERS;
|
||||
use crate::HIDING_BEHAVIOUR;
|
||||
use crate::MANAGE_IDENTIFIERS;
|
||||
use crate::NO_TITLEBAR;
|
||||
use crate::REMOVE_TITLEBARS;
|
||||
use crate::SUBSCRIPTION_PIPES;
|
||||
use crate::TRAY_AND_MULTI_WINDOW_IDENTIFIERS;
|
||||
use crate::WORKSPACE_RULES;
|
||||
@@ -70,17 +64,7 @@ pub fn listen_for_commands(wm: Arc<Mutex<WindowManager>>) {
|
||||
impl WindowManager {
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub fn process_command(&mut self, message: SocketMessage) -> Result<()> {
|
||||
if let Some(virtual_desktop_id) = &self.virtual_desktop_id {
|
||||
if let Some(id) = current_virtual_desktop() {
|
||||
if id != *virtual_desktop_id {
|
||||
tracing::info!(
|
||||
"ignoring events and commands while not on virtual desktop {:?}",
|
||||
virtual_desktop_id
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
self.validate_virtual_desktop_id();
|
||||
|
||||
match message {
|
||||
SocketMessage::Promote => self.promote_container_to_front()?,
|
||||
@@ -124,57 +108,10 @@ impl WindowManager {
|
||||
manage_identifiers.push(id);
|
||||
}
|
||||
}
|
||||
SocketMessage::FloatRule(identifier, id) => {
|
||||
SocketMessage::FloatRule(_, id) => {
|
||||
let mut float_identifiers = FLOAT_IDENTIFIERS.lock();
|
||||
if !float_identifiers.contains(&id) {
|
||||
float_identifiers.push(id.clone());
|
||||
}
|
||||
|
||||
let invisible_borders = self.invisible_borders;
|
||||
let offset = self.work_area_offset;
|
||||
|
||||
let mut hwnds_to_purge = vec![];
|
||||
for (i, monitor) in self.monitors().iter().enumerate() {
|
||||
for container in monitor
|
||||
.focused_workspace()
|
||||
.ok_or_else(|| anyhow!("there is no workspace"))?
|
||||
.containers()
|
||||
.iter()
|
||||
{
|
||||
for window in container.windows().iter() {
|
||||
match identifier {
|
||||
ApplicationIdentifier::Exe => {
|
||||
if window.exe()? == id {
|
||||
hwnds_to_purge.push((i, window.hwnd));
|
||||
}
|
||||
}
|
||||
ApplicationIdentifier::Class => {
|
||||
if window.class()? == id {
|
||||
hwnds_to_purge.push((i, window.hwnd));
|
||||
}
|
||||
}
|
||||
ApplicationIdentifier::Title => {
|
||||
if window.title()? == id {
|
||||
hwnds_to_purge.push((i, window.hwnd));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (monitor_idx, hwnd) in hwnds_to_purge {
|
||||
let monitor = self
|
||||
.monitors_mut()
|
||||
.get_mut(monitor_idx)
|
||||
.ok_or_else(|| anyhow!("there is no monitor"))?;
|
||||
|
||||
monitor
|
||||
.focused_workspace_mut()
|
||||
.ok_or_else(|| anyhow!("there is no focused workspace"))?
|
||||
.remove_window(hwnd)?;
|
||||
|
||||
monitor.update_focused_workspace(offset, &invisible_borders)?;
|
||||
float_identifiers.push(id);
|
||||
}
|
||||
}
|
||||
SocketMessage::AdjustContainerPadding(sizing, adjustment) => {
|
||||
@@ -195,9 +132,6 @@ impl WindowManager {
|
||||
SocketMessage::SendContainerToMonitorNumber(monitor_idx) => {
|
||||
self.move_container_to_monitor(monitor_idx, false)?;
|
||||
}
|
||||
SocketMessage::MoveWorkspaceToMonitorNumber(monitor_idx) => {
|
||||
self.move_workspace_to_monitor(monitor_idx)?;
|
||||
}
|
||||
SocketMessage::TogglePause => {
|
||||
if self.is_paused {
|
||||
tracing::info!("resuming");
|
||||
@@ -206,7 +140,6 @@ impl WindowManager {
|
||||
}
|
||||
|
||||
self.is_paused = !self.is_paused;
|
||||
self.retile_all(true)?;
|
||||
}
|
||||
SocketMessage::ToggleTiling => {
|
||||
self.toggle_tiling()?;
|
||||
@@ -219,13 +152,13 @@ impl WindowManager {
|
||||
);
|
||||
|
||||
self.focus_monitor(monitor_idx)?;
|
||||
self.update_focused_workspace(self.mouse_follows_focus)?;
|
||||
self.update_focused_workspace(true)?;
|
||||
}
|
||||
SocketMessage::FocusMonitorNumber(monitor_idx) => {
|
||||
self.focus_monitor(monitor_idx)?;
|
||||
self.update_focused_workspace(self.mouse_follows_focus)?;
|
||||
self.update_focused_workspace(true)?;
|
||||
}
|
||||
SocketMessage::Retile => self.retile_all(false)?,
|
||||
SocketMessage::Retile => self.retile_all()?,
|
||||
SocketMessage::FlipLayout(layout_flip) => self.flip_layout(layout_flip)?,
|
||||
SocketMessage::ChangeLayout(layout) => self.change_workspace_layout_default(layout)?,
|
||||
SocketMessage::ChangeLayoutCustom(path) => self.change_workspace_custom_layout(path)?,
|
||||
@@ -272,22 +205,14 @@ impl WindowManager {
|
||||
})?;
|
||||
|
||||
self.focus_monitor(monitor_idx)?;
|
||||
self.focus_workspace(workspace_idx)?;
|
||||
}
|
||||
SocketMessage::FocusMonitorWorkspaceNumber(monitor_idx, workspace_idx) => {
|
||||
self.focus_monitor(monitor_idx)?;
|
||||
|
||||
self.focus_workspace(workspace_idx)?;
|
||||
}
|
||||
SocketMessage::Stop => {
|
||||
tracing::info!(
|
||||
"received stop command, restoring all hidden windows and terminating process"
|
||||
);
|
||||
self.restore_all_windows();
|
||||
|
||||
if WindowsApi::focus_follows_mouse()? {
|
||||
WindowsApi::disable_focus_follows_mouse()?;
|
||||
}
|
||||
|
||||
self.restore_all_windows()?;
|
||||
std::process::exit(0)
|
||||
}
|
||||
SocketMessage::EnsureWorkspaces(monitor_idx, workspace_count) => {
|
||||
@@ -300,12 +225,7 @@ impl WindowManager {
|
||||
self.set_workspace_name(monitor_idx, workspace_idx, name)?;
|
||||
}
|
||||
SocketMessage::State => {
|
||||
let state = match serde_json::to_string_pretty(&window_manager::State::from(&*self))
|
||||
{
|
||||
Ok(state) => state,
|
||||
Err(error) => error.to_string(),
|
||||
};
|
||||
|
||||
let state = serde_json::to_string_pretty(&window_manager::State::from(&*self))?;
|
||||
let mut socket =
|
||||
dirs::home_dir().ok_or_else(|| anyhow!("there is no home directory"))?;
|
||||
socket.push("komorebic.sock");
|
||||
@@ -338,85 +258,8 @@ impl WindowManager {
|
||||
let mut stream = UnixStream::connect(&socket)?;
|
||||
stream.write_all(response.as_bytes())?;
|
||||
}
|
||||
SocketMessage::ResizeWindowEdge(direction, sizing) => {
|
||||
self.resize_window(direction, sizing, self.resize_delta, true)?;
|
||||
}
|
||||
SocketMessage::ResizeWindowAxis(axis, sizing) => {
|
||||
// If the user has a custom layout, allow for the resizing of the primary column
|
||||
// with this signal
|
||||
if let Layout::Custom(ref mut custom) = self.focused_workspace_mut()?.layout_mut() {
|
||||
if matches!(axis, Axis::Horizontal) {
|
||||
let percentage = custom
|
||||
.primary_width_percentage()
|
||||
.unwrap_or(100 / custom.len());
|
||||
|
||||
match sizing {
|
||||
Sizing::Increase => custom.set_primary_width_percentage(percentage + 5),
|
||||
Sizing::Decrease => custom.set_primary_width_percentage(percentage - 5),
|
||||
}
|
||||
}
|
||||
// Otherwise proceed with the resizing logic for individual window containers in the
|
||||
// assumed BSP layout
|
||||
} else {
|
||||
match axis {
|
||||
Axis::Horizontal => {
|
||||
self.resize_window(
|
||||
OperationDirection::Left,
|
||||
sizing,
|
||||
self.resize_delta,
|
||||
false,
|
||||
)?;
|
||||
self.resize_window(
|
||||
OperationDirection::Right,
|
||||
sizing,
|
||||
self.resize_delta,
|
||||
false,
|
||||
)?;
|
||||
}
|
||||
Axis::Vertical => {
|
||||
self.resize_window(
|
||||
OperationDirection::Up,
|
||||
sizing,
|
||||
self.resize_delta,
|
||||
false,
|
||||
)?;
|
||||
self.resize_window(
|
||||
OperationDirection::Down,
|
||||
sizing,
|
||||
self.resize_delta,
|
||||
false,
|
||||
)?;
|
||||
}
|
||||
Axis::HorizontalAndVertical => {
|
||||
self.resize_window(
|
||||
OperationDirection::Left,
|
||||
sizing,
|
||||
self.resize_delta,
|
||||
false,
|
||||
)?;
|
||||
self.resize_window(
|
||||
OperationDirection::Right,
|
||||
sizing,
|
||||
self.resize_delta,
|
||||
false,
|
||||
)?;
|
||||
self.resize_window(
|
||||
OperationDirection::Up,
|
||||
sizing,
|
||||
self.resize_delta,
|
||||
false,
|
||||
)?;
|
||||
self.resize_window(
|
||||
OperationDirection::Down,
|
||||
sizing,
|
||||
self.resize_delta,
|
||||
false,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.update_focused_workspace(false)?;
|
||||
SocketMessage::ResizeWindow(direction, sizing) => {
|
||||
self.resize_window(direction, sizing, Option::from(50))?;
|
||||
}
|
||||
SocketMessage::FocusFollowsMouse(mut implementation, enable) => {
|
||||
if !CUSTOM_FFM.load(Ordering::SeqCst) {
|
||||
@@ -537,11 +380,11 @@ impl WindowManager {
|
||||
}
|
||||
SocketMessage::InvisibleBorders(rect) => {
|
||||
self.invisible_borders = rect;
|
||||
self.retile_all(false)?;
|
||||
self.retile_all()?;
|
||||
}
|
||||
SocketMessage::WorkAreaOffset(rect) => {
|
||||
self.work_area_offset = Option::from(rect);
|
||||
self.retile_all(false)?;
|
||||
self.retile_all()?;
|
||||
}
|
||||
SocketMessage::QuickSave => {
|
||||
let workspace = self.focused_workspace()?;
|
||||
@@ -612,28 +455,16 @@ impl WindowManager {
|
||||
let mut pipes = SUBSCRIPTION_PIPES.lock();
|
||||
pipes.remove(&subscriber);
|
||||
}
|
||||
SocketMessage::MouseFollowsFocus(enable) => {
|
||||
self.mouse_follows_focus = enable;
|
||||
}
|
||||
SocketMessage::ToggleMouseFollowsFocus => {
|
||||
self.mouse_follows_focus = !self.mouse_follows_focus;
|
||||
}
|
||||
SocketMessage::ResizeDelta(delta) => {
|
||||
self.resize_delta = delta;
|
||||
}
|
||||
SocketMessage::ToggleWindowContainerBehaviour => {
|
||||
match self.window_container_behaviour {
|
||||
WindowContainerBehaviour::Create => {
|
||||
self.window_container_behaviour = WindowContainerBehaviour::Append;
|
||||
}
|
||||
WindowContainerBehaviour::Append => {
|
||||
self.window_container_behaviour = WindowContainerBehaviour::Create;
|
||||
}
|
||||
SocketMessage::RemoveTitleBar(_, id) => {
|
||||
let mut identifiers = NO_TITLEBAR.lock();
|
||||
if !identifiers.contains(&id) {
|
||||
identifiers.push(id);
|
||||
}
|
||||
}
|
||||
SocketMessage::WindowHidingBehaviour(behaviour) => {
|
||||
let mut hiding_behaviour = HIDING_BEHAVIOUR.lock();
|
||||
*hiding_behaviour = behaviour;
|
||||
SocketMessage::ToggleTitleBars => {
|
||||
let current = REMOVE_TITLEBARS.load(Ordering::SeqCst);
|
||||
REMOVE_TITLEBARS.store(!current, Ordering::SeqCst);
|
||||
self.update_focused_workspace(false)?;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -10,9 +10,7 @@ use parking_lot::Mutex;
|
||||
use komorebi_core::OperationDirection;
|
||||
use komorebi_core::Rect;
|
||||
use komorebi_core::Sizing;
|
||||
use komorebi_core::WindowContainerBehaviour;
|
||||
|
||||
use crate::current_virtual_desktop;
|
||||
use crate::notify_subscribers;
|
||||
use crate::window_manager::WindowManager;
|
||||
use crate::window_manager_event::WindowManagerEvent;
|
||||
@@ -52,17 +50,7 @@ impl WindowManager {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if let Some(virtual_desktop_id) = &self.virtual_desktop_id {
|
||||
if let Some(id) = current_virtual_desktop() {
|
||||
if id != *virtual_desktop_id {
|
||||
tracing::info!(
|
||||
"ignoring events and commands while not on virtual desktop {:?}",
|
||||
virtual_desktop_id
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
self.validate_virtual_desktop_id();
|
||||
|
||||
// Make sure we have the most recently focused monitor from any event
|
||||
match event {
|
||||
@@ -114,25 +102,13 @@ impl WindowManager {
|
||||
window.raise()?;
|
||||
self.has_pending_raise_op = false;
|
||||
}
|
||||
WindowManagerEvent::Destroy(_, window) | WindowManagerEvent::Unmanage(window) => {
|
||||
WindowManagerEvent::Minimize(_, window)
|
||||
| WindowManagerEvent::Destroy(_, window)
|
||||
| WindowManagerEvent::Unmanage(window) => {
|
||||
self.focused_workspace_mut()?.remove_window(window.hwnd)?;
|
||||
self.update_focused_workspace(false)?;
|
||||
}
|
||||
WindowManagerEvent::Minimize(_, window) => {
|
||||
let mut hide = false;
|
||||
|
||||
{
|
||||
let programmatically_hidden_hwnds = HIDDEN_HWNDS.lock();
|
||||
if !programmatically_hidden_hwnds.contains(&window.hwnd) {
|
||||
hide = true;
|
||||
}
|
||||
}
|
||||
|
||||
if hide {
|
||||
self.focused_workspace_mut()?.remove_window(window.hwnd)?;
|
||||
self.update_focused_workspace(false)?;
|
||||
}
|
||||
}
|
||||
WindowManagerEvent::Hide(_, window) => {
|
||||
let mut hide = false;
|
||||
// Some major applications unfortunately send the HIDE signal when they are being
|
||||
@@ -225,53 +201,14 @@ impl WindowManager {
|
||||
}
|
||||
}
|
||||
|
||||
let behaviour = self.window_container_behaviour;
|
||||
let workspace = self.focused_workspace_mut()?;
|
||||
|
||||
if !workspace.contains_window(window.hwnd) {
|
||||
match behaviour {
|
||||
WindowContainerBehaviour::Create => {
|
||||
workspace.new_container_for_window(*window);
|
||||
self.update_focused_workspace(false)?;
|
||||
}
|
||||
WindowContainerBehaviour::Append => {
|
||||
workspace
|
||||
.focused_container_mut()
|
||||
.ok_or_else(|| anyhow!("there is no focused container"))?
|
||||
.add_window(*window);
|
||||
self.update_focused_workspace(true)?;
|
||||
}
|
||||
}
|
||||
workspace.new_container_for_window(*window);
|
||||
self.update_focused_workspace(false)?;
|
||||
}
|
||||
}
|
||||
WindowManagerEvent::MoveResizeStart(_, _) => {
|
||||
let monitor_idx = self.focused_monitor_idx();
|
||||
let workspace_idx = self
|
||||
.focused_monitor()
|
||||
.ok_or_else(|| anyhow!("there is no monitor with this idx"))?
|
||||
.focused_workspace_idx();
|
||||
let container_idx = self
|
||||
.focused_monitor()
|
||||
.ok_or_else(|| anyhow!("there is no monitor with this idx"))?
|
||||
.focused_workspace()
|
||||
.ok_or_else(|| anyhow!("there is no workspace with this idx"))?
|
||||
.focused_container_idx();
|
||||
|
||||
self.pending_move_op = Option::from((monitor_idx, workspace_idx, container_idx));
|
||||
}
|
||||
WindowManagerEvent::MoveResizeEnd(_, window) => {
|
||||
// We need this because if the event ends on a different monitor,
|
||||
// that monitor will already have been focused and updated in the state
|
||||
let pending = self.pending_move_op;
|
||||
// Always consume the pending move op whenever this event is handled
|
||||
self.pending_move_op = None;
|
||||
|
||||
let target_monitor_idx = self
|
||||
.monitor_idx_from_current_pos()
|
||||
.ok_or_else(|| anyhow!("cannot get monitor idx from current position"))?;
|
||||
|
||||
let new_window_behaviour = self.window_container_behaviour;
|
||||
|
||||
let workspace = self.focused_workspace_mut()?;
|
||||
if workspace
|
||||
.floating_windows()
|
||||
@@ -281,32 +218,12 @@ impl WindowManager {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let focused_container_idx = workspace.focused_container_idx();
|
||||
|
||||
let mut new_position = WindowsApi::window_rect(window.hwnd())?;
|
||||
|
||||
let focused_idx = workspace.focused_container_idx();
|
||||
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();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
.get(focused_idx)
|
||||
.ok_or_else(|| anyhow!("there is no latest layout"))?;
|
||||
let mut new_position = WindowsApi::window_rect(window.hwnd())?;
|
||||
|
||||
// Adjust for the invisible borders
|
||||
new_position.left += invisible_borders.left;
|
||||
@@ -321,90 +238,16 @@ impl WindowManager {
|
||||
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;
|
||||
let is_move = resize.right == 0 && resize.bottom == 0;
|
||||
|
||||
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)?;
|
||||
match workspace.container_idx_from_current_point() {
|
||||
Some(target_idx) => {
|
||||
workspace.swap_containers(focused_idx, target_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)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None => self.update_focused_workspace(true)?,
|
||||
}
|
||||
} else {
|
||||
tracing::info!("resizing with mouse");
|
||||
@@ -439,8 +282,8 @@ impl WindowManager {
|
||||
ops.push(resize_op!(resize.bottom, <, OperationDirection::Down));
|
||||
}
|
||||
|
||||
for (edge, sizing, delta) in ops {
|
||||
self.resize_window(edge, sizing, delta, true)?;
|
||||
for (edge, sizing, step) in ops {
|
||||
self.resize_window(edge, sizing, Option::from(step))?;
|
||||
}
|
||||
|
||||
self.update_focused_workspace(false)?;
|
||||
|
||||
@@ -1,37 +1,38 @@
|
||||
use bitflags::bitflags;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SWP_ASYNCWINDOWPOS;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SWP_DEFERERASE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SWP_DRAWFRAME;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SWP_FRAMECHANGED;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SWP_HIDEWINDOW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SWP_NOACTIVATE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SWP_NOCOPYBITS;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SWP_NOMOVE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SWP_NOOWNERZORDER;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SWP_NOREDRAW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SWP_NOREPOSITION;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SWP_NOSENDCHANGING;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SWP_NOSIZE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SWP_NOZORDER;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SWP_SHOWWINDOW;
|
||||
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::SWP_ASYNCWINDOWPOS;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::SWP_DEFERERASE;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::SWP_DRAWFRAME;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::SWP_FRAMECHANGED;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::SWP_HIDEWINDOW;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::SWP_NOACTIVATE;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::SWP_NOCOPYBITS;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::SWP_NOMOVE;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::SWP_NOOWNERZORDER;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::SWP_NOREDRAW;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::SWP_NOREPOSITION;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::SWP_NOSENDCHANGING;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::SWP_NOSIZE;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::SWP_NOZORDER;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::SWP_SHOWWINDOW;
|
||||
|
||||
bitflags! {
|
||||
#[derive(Default)]
|
||||
pub struct SetWindowPosition: u32 {
|
||||
const ASYNC_WINDOW_POS = SWP_ASYNCWINDOWPOS;
|
||||
const DEFER_ERASE = SWP_DEFERERASE;
|
||||
const DRAW_FRAME = SWP_DRAWFRAME;
|
||||
const FRAME_CHANGED = SWP_FRAMECHANGED;
|
||||
const HIDE_WINDOW = SWP_HIDEWINDOW;
|
||||
const NO_ACTIVATE = SWP_NOACTIVATE;
|
||||
const NO_COPY_BITS = SWP_NOCOPYBITS;
|
||||
const NO_MOVE = SWP_NOMOVE;
|
||||
const NO_OWNER_Z_ORDER = SWP_NOOWNERZORDER;
|
||||
const NO_REDRAW = SWP_NOREDRAW;
|
||||
const NO_REPOSITION = SWP_NOREPOSITION;
|
||||
const NO_SEND_CHANGING = SWP_NOSENDCHANGING;
|
||||
const NO_SIZE = SWP_NOSIZE;
|
||||
const NO_Z_ORDER = SWP_NOZORDER;
|
||||
const SHOW_WINDOW = SWP_SHOWWINDOW;
|
||||
const ASYNC_WINDOW_POS = SWP_ASYNCWINDOWPOS.0;
|
||||
const DEFER_ERASE = SWP_DEFERERASE.0;
|
||||
const DRAW_FRAME = SWP_DRAWFRAME.0;
|
||||
const FRAME_CHANGED = SWP_FRAMECHANGED.0;
|
||||
const HIDE_WINDOW = SWP_HIDEWINDOW.0;
|
||||
const NO_ACTIVATE = SWP_NOACTIVATE.0;
|
||||
const NO_COPY_BITS = SWP_NOCOPYBITS.0;
|
||||
const NO_MOVE = SWP_NOMOVE.0;
|
||||
const NO_OWNER_Z_ORDER = SWP_NOOWNERZORDER.0;
|
||||
const NO_REDRAW = SWP_NOREDRAW.0;
|
||||
const NO_REPOSITION = SWP_NOREPOSITION.0;
|
||||
const NO_SEND_CHANGING = SWP_NOSENDCHANGING.0;
|
||||
const NO_SIZE = SWP_NOSIZE.0;
|
||||
const NO_Z_ORDER = SWP_NOZORDER.0;
|
||||
const SHOW_WINDOW = SWP_SHOWWINDOW.0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,123 +1,122 @@
|
||||
use bitflags::bitflags;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_BORDER;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_CAPTION;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_CHILD;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_CHILDWINDOW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_CLIPCHILDREN;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_CLIPSIBLINGS;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_DISABLED;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_DLGFRAME;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_EX_ACCEPTFILES;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_EX_APPWINDOW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_EX_CLIENTEDGE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_EX_COMPOSITED;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_EX_CONTEXTHELP;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_EX_CONTROLPARENT;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_EX_DLGMODALFRAME;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_EX_LAYERED;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_EX_LAYOUTRTL;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_EX_LEFT;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_EX_LEFTSCROLLBAR;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_EX_LTRREADING;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_EX_MDICHILD;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_EX_NOACTIVATE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_EX_NOINHERITLAYOUT;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_EX_NOPARENTNOTIFY;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_EX_NOREDIRECTIONBITMAP;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_EX_OVERLAPPEDWINDOW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_EX_PALETTEWINDOW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_EX_RIGHT;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_EX_RIGHTSCROLLBAR;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_EX_RTLREADING;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_EX_STATICEDGE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_EX_TOOLWINDOW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_EX_TOPMOST;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_EX_TRANSPARENT;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_EX_WINDOWEDGE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_GROUP;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_HSCROLL;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_ICONIC;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_MAXIMIZE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_MAXIMIZEBOX;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_MINIMIZE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_MINIMIZEBOX;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_OVERLAPPED;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_OVERLAPPEDWINDOW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_POPUP;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_POPUPWINDOW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_SIZEBOX;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_SYSMENU;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_TABSTOP;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_THICKFRAME;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_TILED;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_TILEDWINDOW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_VISIBLE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_VSCROLL;
|
||||
|
||||
// https://docs.microsoft.com/en-us/windows/win32/winmsg/window-styles
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_BORDER;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_CAPTION;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_CHILD;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_CHILDWINDOW;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_CLIPCHILDREN;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_CLIPSIBLINGS;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_DISABLED;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_DLGFRAME;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_EX_ACCEPTFILES;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_EX_APPWINDOW;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_EX_CLIENTEDGE;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_EX_COMPOSITED;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_EX_CONTEXTHELP;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_EX_CONTROLPARENT;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_EX_DLGMODALFRAME;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_EX_LAYERED;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_EX_LAYOUTRTL;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_EX_LEFT;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_EX_LEFTSCROLLBAR;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_EX_LTRREADING;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_EX_MDICHILD;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_EX_NOACTIVATE;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_EX_NOINHERITLAYOUT;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_EX_NOPARENTNOTIFY;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_EX_NOREDIRECTIONBITMAP;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_EX_OVERLAPPEDWINDOW;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_EX_PALETTEWINDOW;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_EX_RIGHT;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_EX_RIGHTSCROLLBAR;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_EX_RTLREADING;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_EX_STATICEDGE;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_EX_TOOLWINDOW;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_EX_TOPMOST;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_EX_TRANSPARENT;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_EX_WINDOWEDGE;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_GROUP;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_HSCROLL;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_ICONIC;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_MAXIMIZE;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_MAXIMIZEBOX;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_MINIMIZE;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_MINIMIZEBOX;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_OVERLAPPED;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_OVERLAPPEDWINDOW;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_POPUP;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_POPUPWINDOW;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_SIZEBOX;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_SYSMENU;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_TABSTOP;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_THICKFRAME;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_TILED;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_TILEDWINDOW;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_VISIBLE;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WS_VSCROLL;
|
||||
|
||||
bitflags! {
|
||||
#[derive(Default)]
|
||||
pub struct WindowStyle: u32 {
|
||||
const BORDER = WS_BORDER;
|
||||
const CAPTION = WS_CAPTION;
|
||||
const CHILD = WS_CHILD;
|
||||
const CHILDWINDOW = WS_CHILDWINDOW;
|
||||
const CLIPCHILDREN = WS_CLIPCHILDREN;
|
||||
const CLIPSIBLINGS = WS_CLIPSIBLINGS;
|
||||
const DISABLED = WS_DISABLED;
|
||||
const DLGFRAME = WS_DLGFRAME;
|
||||
const GROUP = WS_GROUP;
|
||||
const HSCROLL = WS_HSCROLL;
|
||||
const ICONIC = WS_ICONIC;
|
||||
const MAXIMIZE = WS_MAXIMIZE;
|
||||
const MAXIMIZEBOX = WS_MAXIMIZEBOX;
|
||||
const MINIMIZE = WS_MINIMIZE;
|
||||
const MINIMIZEBOX = WS_MINIMIZEBOX;
|
||||
const OVERLAPPED = WS_OVERLAPPED;
|
||||
const OVERLAPPEDWINDOW = WS_OVERLAPPEDWINDOW;
|
||||
const POPUP = WS_POPUP;
|
||||
const POPUPWINDOW = WS_POPUPWINDOW;
|
||||
const SIZEBOX = WS_SIZEBOX;
|
||||
const SYSMENU = WS_SYSMENU;
|
||||
const TABSTOP = WS_TABSTOP;
|
||||
const THICKFRAME = WS_THICKFRAME;
|
||||
const TILED = WS_TILED;
|
||||
const TILEDWINDOW = WS_TILEDWINDOW;
|
||||
const VISIBLE = WS_VISIBLE;
|
||||
const VSCROLL = WS_VSCROLL;
|
||||
pub struct GwlStyle: u32 {
|
||||
const BORDER = WS_BORDER.0;
|
||||
const CAPTION = WS_CAPTION.0;
|
||||
const CHILD = WS_CHILD.0;
|
||||
const CHILDWINDOW = WS_CHILDWINDOW.0;
|
||||
const CLIPCHILDREN = WS_CLIPCHILDREN.0;
|
||||
const CLIPSIBLINGS = WS_CLIPSIBLINGS.0;
|
||||
const DISABLED = WS_DISABLED.0;
|
||||
const DLGFRAME = WS_DLGFRAME.0;
|
||||
const GROUP = WS_GROUP.0;
|
||||
const HSCROLL = WS_HSCROLL.0;
|
||||
const ICONIC = WS_ICONIC.0;
|
||||
const MAXIMIZE = WS_MAXIMIZE.0;
|
||||
const MAXIMIZEBOX = WS_MAXIMIZEBOX.0;
|
||||
const MINIMIZE = WS_MINIMIZE.0;
|
||||
const MINIMIZEBOX = WS_MINIMIZEBOX.0;
|
||||
const OVERLAPPED = WS_OVERLAPPED.0;
|
||||
const OVERLAPPEDWINDOW = WS_OVERLAPPEDWINDOW.0;
|
||||
const POPUP = WS_POPUP.0;
|
||||
const POPUPWINDOW = WS_POPUPWINDOW.0;
|
||||
const SIZEBOX = WS_SIZEBOX.0;
|
||||
const SYSMENU = WS_SYSMENU.0;
|
||||
const TABSTOP = WS_TABSTOP.0;
|
||||
const THICKFRAME = WS_THICKFRAME.0;
|
||||
const TILED = WS_TILED.0;
|
||||
const TILEDWINDOW = WS_TILEDWINDOW.0;
|
||||
const VISIBLE = WS_VISIBLE.0;
|
||||
const VSCROLL = WS_VSCROLL.0;
|
||||
}
|
||||
}
|
||||
|
||||
// https://docs.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles
|
||||
bitflags! {
|
||||
#[derive(Default)]
|
||||
pub struct ExtendedWindowStyle: u32 {
|
||||
const ACCEPTFILES = WS_EX_ACCEPTFILES;
|
||||
const APPWINDOW = WS_EX_APPWINDOW;
|
||||
const CLIENTEDGE = WS_EX_CLIENTEDGE;
|
||||
const COMPOSITED = WS_EX_COMPOSITED;
|
||||
const CONTEXTHELP = WS_EX_CONTEXTHELP;
|
||||
const CONTROLPARENT = WS_EX_CONTROLPARENT;
|
||||
const DLGMODALFRAME = WS_EX_DLGMODALFRAME;
|
||||
const LAYERED = WS_EX_LAYERED;
|
||||
const LAYOUTRTL = WS_EX_LAYOUTRTL;
|
||||
const LEFT = WS_EX_LEFT;
|
||||
const LEFTSCROLLBAR = WS_EX_LEFTSCROLLBAR;
|
||||
const LTRREADING = WS_EX_LTRREADING;
|
||||
const MDICHILD = WS_EX_MDICHILD;
|
||||
const NOACTIVATE = WS_EX_NOACTIVATE;
|
||||
const NOINHERITLAYOUT = WS_EX_NOINHERITLAYOUT;
|
||||
const NOPARENTNOTIFY = WS_EX_NOPARENTNOTIFY;
|
||||
const NOREDIRECTIONBITMAP = WS_EX_NOREDIRECTIONBITMAP;
|
||||
const OVERLAPPEDWINDOW = WS_EX_OVERLAPPEDWINDOW;
|
||||
const PALETTEWINDOW = WS_EX_PALETTEWINDOW;
|
||||
const RIGHT = WS_EX_RIGHT;
|
||||
const RIGHTSCROLLBAR = WS_EX_RIGHTSCROLLBAR;
|
||||
const RTLREADING = WS_EX_RTLREADING;
|
||||
const STATICEDGE = WS_EX_STATICEDGE;
|
||||
const TOOLWINDOW = WS_EX_TOOLWINDOW;
|
||||
const TOPMOST = WS_EX_TOPMOST;
|
||||
const TRANSPARENT = WS_EX_TRANSPARENT;
|
||||
const WINDOWEDGE = WS_EX_WINDOWEDGE;
|
||||
pub struct GwlExStyle: u32 {
|
||||
const ACCEPTFILES = WS_EX_ACCEPTFILES.0;
|
||||
const APPWINDOW = WS_EX_APPWINDOW.0;
|
||||
const CLIENTEDGE = WS_EX_CLIENTEDGE.0;
|
||||
const COMPOSITED = WS_EX_COMPOSITED.0;
|
||||
const CONTEXTHELP = WS_EX_CONTEXTHELP.0;
|
||||
const CONTROLPARENT = WS_EX_CONTROLPARENT.0;
|
||||
const DLGMODALFRAME = WS_EX_DLGMODALFRAME.0;
|
||||
const LAYERED = WS_EX_LAYERED.0;
|
||||
const LAYOUTRTL = WS_EX_LAYOUTRTL.0;
|
||||
const LEFT = WS_EX_LEFT.0;
|
||||
const LEFTSCROLLBAR = WS_EX_LEFTSCROLLBAR.0;
|
||||
const LTRREADING = WS_EX_LTRREADING.0;
|
||||
const MDICHILD = WS_EX_MDICHILD.0;
|
||||
const NOACTIVATE = WS_EX_NOACTIVATE.0;
|
||||
const NOINHERITLAYOUT = WS_EX_NOINHERITLAYOUT.0;
|
||||
const NOPARENTNOTIFY = WS_EX_NOPARENTNOTIFY.0;
|
||||
const NOREDIRECTIONBITMAP = WS_EX_NOREDIRECTIONBITMAP.0;
|
||||
const OVERLAPPEDWINDOW = WS_EX_OVERLAPPEDWINDOW.0;
|
||||
const PALETTEWINDOW = WS_EX_PALETTEWINDOW.0;
|
||||
const RIGHT = WS_EX_RIGHT.0;
|
||||
const RIGHTSCROLLBAR = WS_EX_RIGHTSCROLLBAR.0;
|
||||
const RTLREADING = WS_EX_RTLREADING.0;
|
||||
const STATICEDGE = WS_EX_STATICEDGE.0;
|
||||
const TOOLWINDOW = WS_EX_TOOLWINDOW.0;
|
||||
const TOPMOST = WS_EX_TOPMOST.0;
|
||||
const TRANSPARENT = WS_EX_TRANSPARENT.0;
|
||||
const WINDOWEDGE = WS_EX_WINDOWEDGE.0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,21 +8,20 @@ use serde::ser::Error;
|
||||
use serde::ser::SerializeStruct;
|
||||
use serde::Serialize;
|
||||
use serde::Serializer;
|
||||
use windows::Win32::Foundation::HWND;
|
||||
|
||||
use komorebi_core::HidingBehaviour;
|
||||
use bindings::Windows::Win32::Foundation::HWND;
|
||||
use komorebi_core::Rect;
|
||||
|
||||
use crate::styles::ExtendedWindowStyle;
|
||||
use crate::styles::WindowStyle;
|
||||
use crate::styles::GwlExStyle;
|
||||
use crate::styles::GwlStyle;
|
||||
use crate::window_manager_event::WindowManagerEvent;
|
||||
use crate::windows_api::WindowsApi;
|
||||
use crate::BORDER_OVERFLOW_IDENTIFIERS;
|
||||
use crate::FLOAT_IDENTIFIERS;
|
||||
use crate::HIDDEN_HWNDS;
|
||||
use crate::HIDING_BEHAVIOUR;
|
||||
use crate::LAYERED_EXE_WHITELIST;
|
||||
use crate::MANAGE_IDENTIFIERS;
|
||||
use crate::NO_TITLEBAR;
|
||||
use crate::WSL2_UI_PROCESSES;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
@@ -141,11 +140,7 @@ impl Window {
|
||||
programmatically_hidden_hwnds.push(self.hwnd);
|
||||
}
|
||||
|
||||
let hiding_behaviour = HIDING_BEHAVIOUR.lock();
|
||||
match *hiding_behaviour {
|
||||
HidingBehaviour::Hide => WindowsApi::hide_window(self.hwnd()),
|
||||
HidingBehaviour::Minimize => WindowsApi::minimize_window(self.hwnd()),
|
||||
}
|
||||
WindowsApi::hide_window(self.hwnd());
|
||||
}
|
||||
|
||||
pub fn restore(self) {
|
||||
@@ -193,7 +188,7 @@ impl Window {
|
||||
WindowsApi::set_focus(self.hwnd())
|
||||
}
|
||||
|
||||
pub fn focus(self, mouse_follows_focus: bool) -> Result<()> {
|
||||
pub fn focus(self) -> Result<()> {
|
||||
// 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();
|
||||
@@ -211,27 +206,39 @@ impl Window {
|
||||
};
|
||||
|
||||
// Center cursor in Window
|
||||
if mouse_follows_focus {
|
||||
WindowsApi::center_cursor_in_rect(&WindowsApi::window_rect(self.hwnd())?)?;
|
||||
}
|
||||
WindowsApi::center_cursor_in_rect(&WindowsApi::window_rect(self.hwnd())?)?;
|
||||
|
||||
// This isn't really needed when the above command works as expected via AHK
|
||||
WindowsApi::set_focus(self.hwnd())
|
||||
}
|
||||
|
||||
pub fn remove_title_bar(self) -> Result<()> {
|
||||
let mut style = self.style()?;
|
||||
style.remove(GwlStyle::CAPTION);
|
||||
style.remove(GwlStyle::THICKFRAME);
|
||||
self.update_style(style)
|
||||
}
|
||||
|
||||
pub fn add_title_bar(self) -> Result<()> {
|
||||
let mut style = self.style()?;
|
||||
style.insert(GwlStyle::CAPTION);
|
||||
style.insert(GwlStyle::THICKFRAME);
|
||||
self.update_style(style)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn update_style(self, style: WindowStyle) -> Result<()> {
|
||||
pub fn update_style(self, style: GwlStyle) -> Result<()> {
|
||||
WindowsApi::update_style(self.hwnd(), isize::try_from(style.bits())?)
|
||||
}
|
||||
|
||||
pub fn style(self) -> Result<WindowStyle> {
|
||||
pub fn style(self) -> Result<GwlStyle> {
|
||||
let bits = u32::try_from(WindowsApi::gwl_style(self.hwnd())?)?;
|
||||
WindowStyle::from_bits(bits).ok_or_else(|| anyhow!("there is no gwl style"))
|
||||
GwlStyle::from_bits(bits).ok_or_else(|| anyhow!("there is no gwl style"))
|
||||
}
|
||||
|
||||
pub fn ex_style(self) -> Result<ExtendedWindowStyle> {
|
||||
pub fn ex_style(self) -> Result<GwlExStyle> {
|
||||
let bits = u32::try_from(WindowsApi::gwl_ex_style(self.hwnd())?)?;
|
||||
ExtendedWindowStyle::from_bits(bits).ok_or_else(|| anyhow!("there is no gwl style"))
|
||||
GwlExStyle::from_bits(bits).ok_or_else(|| anyhow!("there is no gwl style"))
|
||||
}
|
||||
|
||||
pub fn title(self) -> Result<String> {
|
||||
@@ -303,16 +310,25 @@ impl Window {
|
||||
wsl2_ui_processes.contains(&exe_name)
|
||||
};
|
||||
|
||||
let allow_titlebar_removed = {
|
||||
let titlebars_removed = NO_TITLEBAR.lock();
|
||||
titlebars_removed.contains(&exe_name)
|
||||
};
|
||||
|
||||
let style = self.style()?;
|
||||
let ex_style = self.ex_style()?;
|
||||
|
||||
if (allow_wsl2_gui || style.contains(WindowStyle::CAPTION) && ex_style.contains(ExtendedWindowStyle::WINDOWEDGE))
|
||||
&& !ex_style.contains(ExtendedWindowStyle::DLGMODALFRAME)
|
||||
if (
|
||||
allow_wsl2_gui
|
||||
|| allow_titlebar_removed
|
||||
|| style.contains(GwlStyle::CAPTION) && ex_style.contains(GwlExStyle::WINDOWEDGE)
|
||||
)
|
||||
&& !ex_style.contains(GwlExStyle::DLGMODALFRAME)
|
||||
// Get a lot of dupe events coming through that make the redrawing go crazy
|
||||
// on FocusChange events if I don't filter out this one. But, if we are
|
||||
// allowing a specific layered window on the whitelist (like Steam), it should
|
||||
// pass this check
|
||||
&& (allow_layered || !ex_style.contains(ExtendedWindowStyle::LAYERED))
|
||||
&& (allow_layered || !ex_style.contains(GwlExStyle::LAYERED))
|
||||
|| managed_override
|
||||
{
|
||||
return Ok(true);
|
||||
|
||||
@@ -2,6 +2,7 @@ use std::collections::VecDeque;
|
||||
use std::io::ErrorKind;
|
||||
use std::num::NonZeroUsize;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::Arc;
|
||||
use std::thread;
|
||||
|
||||
@@ -16,18 +17,16 @@ use uds_windows::UnixListener;
|
||||
|
||||
use komorebi_core::custom_layout::CustomLayout;
|
||||
use komorebi_core::Arrangement;
|
||||
use komorebi_core::Axis;
|
||||
use komorebi_core::CycleDirection;
|
||||
use komorebi_core::DefaultLayout;
|
||||
use komorebi_core::Flip;
|
||||
use komorebi_core::FocusFollowsMouseImplementation;
|
||||
use komorebi_core::Layout;
|
||||
use komorebi_core::OperationDirection;
|
||||
use komorebi_core::Rect;
|
||||
use komorebi_core::Sizing;
|
||||
use komorebi_core::WindowContainerBehaviour;
|
||||
|
||||
use crate::container::Container;
|
||||
use crate::current_virtual_desktop;
|
||||
use crate::load_configuration;
|
||||
use crate::monitor::Monitor;
|
||||
use crate::ring::Ring;
|
||||
@@ -40,6 +39,8 @@ use crate::BORDER_OVERFLOW_IDENTIFIERS;
|
||||
use crate::FLOAT_IDENTIFIERS;
|
||||
use crate::LAYERED_EXE_WHITELIST;
|
||||
use crate::MANAGE_IDENTIFIERS;
|
||||
use crate::NO_TITLEBAR;
|
||||
use crate::REMOVE_TITLEBARS;
|
||||
use crate::TRAY_AND_MULTI_WINDOW_IDENTIFIERS;
|
||||
use crate::WORKSPACE_RULES;
|
||||
|
||||
@@ -51,14 +52,10 @@ pub struct WindowManager {
|
||||
pub is_paused: bool,
|
||||
pub invisible_borders: Rect,
|
||||
pub work_area_offset: Option<Rect>,
|
||||
pub resize_delta: i32,
|
||||
pub window_container_behaviour: WindowContainerBehaviour,
|
||||
pub focus_follows_mouse: Option<FocusFollowsMouseImplementation>,
|
||||
pub mouse_follows_focus: bool,
|
||||
pub hotwatch: Hotwatch,
|
||||
pub virtual_desktop_id: Option<Vec<u8>>,
|
||||
pub virtual_desktop_id: Option<usize>,
|
||||
pub has_pending_raise_op: bool,
|
||||
pub pending_move_op: Option<(usize, usize, usize)>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
@@ -66,12 +63,10 @@ pub struct State {
|
||||
pub monitors: Ring<Monitor>,
|
||||
pub is_paused: bool,
|
||||
pub invisible_borders: Rect,
|
||||
pub resize_delta: i32,
|
||||
pub new_window_behaviour: WindowContainerBehaviour,
|
||||
pub work_area_offset: Option<Rect>,
|
||||
pub focus_follows_mouse: Option<FocusFollowsMouseImplementation>,
|
||||
pub mouse_follows_focus: bool,
|
||||
pub has_pending_raise_op: bool,
|
||||
pub remove_titlebars: bool,
|
||||
pub float_identifiers: Vec<String>,
|
||||
pub manage_identifiers: Vec<String>,
|
||||
pub layered_exe_whitelist: Vec<String>,
|
||||
@@ -86,11 +81,9 @@ impl From<&WindowManager> for State {
|
||||
is_paused: wm.is_paused,
|
||||
invisible_borders: wm.invisible_borders,
|
||||
work_area_offset: wm.work_area_offset,
|
||||
resize_delta: wm.resize_delta,
|
||||
new_window_behaviour: wm.window_container_behaviour,
|
||||
focus_follows_mouse: wm.focus_follows_mouse.clone(),
|
||||
mouse_follows_focus: wm.mouse_follows_focus,
|
||||
has_pending_raise_op: wm.has_pending_raise_op,
|
||||
remove_titlebars: REMOVE_TITLEBARS.load(Ordering::SeqCst),
|
||||
float_identifiers: FLOAT_IDENTIFIERS.lock().clone(),
|
||||
manage_identifiers: MANAGE_IDENTIFIERS.lock().clone(),
|
||||
layered_exe_whitelist: LAYERED_EXE_WHITELIST.lock().clone(),
|
||||
@@ -147,6 +140,8 @@ impl WindowManager {
|
||||
|
||||
let listener = UnixListener::bind(&socket)?;
|
||||
|
||||
let virtual_desktop_id = winvd::helpers::get_current_desktop_number().ok();
|
||||
|
||||
Ok(Self {
|
||||
monitors: Ring::default(),
|
||||
incoming_events: incoming,
|
||||
@@ -158,15 +153,11 @@ impl WindowManager {
|
||||
right: 14,
|
||||
bottom: 7,
|
||||
},
|
||||
virtual_desktop_id: current_virtual_desktop(),
|
||||
work_area_offset: None,
|
||||
window_container_behaviour: WindowContainerBehaviour::Create,
|
||||
resize_delta: 50,
|
||||
focus_follows_mouse: None,
|
||||
mouse_follows_focus: true,
|
||||
hotwatch: Hotwatch::new()?,
|
||||
virtual_desktop_id,
|
||||
has_pending_raise_op: false,
|
||||
pending_move_op: None,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -442,7 +433,7 @@ impl WindowManager {
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub fn retile_all(&mut self, preserve_resize_dimensions: bool) -> Result<()> {
|
||||
pub fn retile_all(&mut self) -> Result<()> {
|
||||
let invisible_borders = self.invisible_borders;
|
||||
let offset = self.work_area_offset;
|
||||
|
||||
@@ -453,10 +444,8 @@ impl WindowManager {
|
||||
.ok_or_else(|| anyhow!("there is no workspace"))?;
|
||||
|
||||
// Reset any resize adjustments if we want to force a retile
|
||||
if !preserve_resize_dimensions {
|
||||
for resize in workspace.resize_dimensions_mut() {
|
||||
*resize = None;
|
||||
}
|
||||
for resize in workspace.resize_dimensions_mut() {
|
||||
*resize = None;
|
||||
}
|
||||
|
||||
workspace.update(&work_area, offset, &invisible_borders)?;
|
||||
@@ -465,6 +454,20 @@ impl WindowManager {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub fn validate_virtual_desktop_id(&self) {
|
||||
let virtual_desktop_id = winvd::helpers::get_current_desktop_number().ok();
|
||||
if let (Some(id), Some(virtual_desktop_id)) = (virtual_desktop_id, self.virtual_desktop_id)
|
||||
{
|
||||
if id != virtual_desktop_id {
|
||||
tracing::warn!(
|
||||
"ignoring events while not on virtual desktop {}",
|
||||
virtual_desktop_id
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub fn manage_focused_window(&mut self) -> Result<()> {
|
||||
let hwnd = WindowsApi::foreground_window()?;
|
||||
@@ -541,94 +544,7 @@ impl WindowManager {
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub fn transfer_container(
|
||||
&mut self,
|
||||
origin: (usize, usize, usize),
|
||||
target: (usize, usize, usize),
|
||||
) -> Result<()> {
|
||||
let (origin_monitor_idx, origin_workspace_idx, origin_container_idx) = origin;
|
||||
let (target_monitor_idx, target_workspace_idx, target_container_idx) = target;
|
||||
|
||||
let origin_container = self
|
||||
.monitors_mut()
|
||||
.get_mut(origin_monitor_idx)
|
||||
.ok_or_else(|| anyhow!("there is no monitor at this index"))?
|
||||
.workspaces_mut()
|
||||
.get_mut(origin_workspace_idx)
|
||||
.ok_or_else(|| anyhow!("there is no workspace at this index"))?
|
||||
.remove_container(origin_container_idx)
|
||||
.ok_or_else(|| anyhow!("there is no container at this index"))?;
|
||||
|
||||
let target_workspace = self
|
||||
.monitors_mut()
|
||||
.get_mut(target_monitor_idx)
|
||||
.ok_or_else(|| anyhow!("there is no monitor at this index"))?
|
||||
.workspaces_mut()
|
||||
.get_mut(target_workspace_idx)
|
||||
.ok_or_else(|| anyhow!("there is no workspace at this index"))?;
|
||||
|
||||
target_workspace
|
||||
.containers_mut()
|
||||
.insert(target_container_idx, origin_container);
|
||||
|
||||
target_workspace.focus_container(target_container_idx);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub fn swap_containers(
|
||||
&mut self,
|
||||
origin: (usize, usize, usize),
|
||||
target: (usize, usize, usize),
|
||||
) -> Result<()> {
|
||||
let (origin_monitor_idx, origin_workspace_idx, origin_container_idx) = origin;
|
||||
let (target_monitor_idx, target_workspace_idx, target_container_idx) = target;
|
||||
|
||||
let origin_container = self
|
||||
.monitors_mut()
|
||||
.get_mut(origin_monitor_idx)
|
||||
.ok_or_else(|| anyhow!("there is no monitor at this index"))?
|
||||
.workspaces_mut()
|
||||
.get_mut(origin_workspace_idx)
|
||||
.ok_or_else(|| anyhow!("there is no workspace at this index"))?
|
||||
.remove_container(origin_container_idx)
|
||||
.ok_or_else(|| anyhow!("there is no container at this index"))?;
|
||||
|
||||
let target_container = self
|
||||
.monitors_mut()
|
||||
.get_mut(target_monitor_idx)
|
||||
.ok_or_else(|| anyhow!("there is no monitor at this index"))?
|
||||
.workspaces_mut()
|
||||
.get_mut(target_workspace_idx)
|
||||
.ok_or_else(|| anyhow!("there is no workspace at this index"))?
|
||||
.remove_container(target_container_idx);
|
||||
|
||||
self.monitors_mut()
|
||||
.get_mut(target_monitor_idx)
|
||||
.ok_or_else(|| anyhow!("there is no monitor at this index"))?
|
||||
.workspaces_mut()
|
||||
.get_mut(target_workspace_idx)
|
||||
.ok_or_else(|| anyhow!("there is no workspace at this index"))?
|
||||
.containers_mut()
|
||||
.insert(target_container_idx, origin_container);
|
||||
|
||||
if let Some(target_container) = target_container {
|
||||
self.monitors_mut()
|
||||
.get_mut(origin_monitor_idx)
|
||||
.ok_or_else(|| anyhow!("there is no monitor at this index"))?
|
||||
.workspaces_mut()
|
||||
.get_mut(origin_workspace_idx)
|
||||
.ok_or_else(|| anyhow!("there is no workspace at this index"))?
|
||||
.containers_mut()
|
||||
.insert(origin_container_idx, target_container);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub fn update_focused_workspace(&mut self, follow_focus: bool) -> Result<()> {
|
||||
pub fn update_focused_workspace(&mut self, mouse_follows_focus: bool) -> Result<()> {
|
||||
tracing::info!("updating");
|
||||
|
||||
let invisible_borders = self.invisible_borders;
|
||||
@@ -638,15 +554,15 @@ impl WindowManager {
|
||||
.ok_or_else(|| anyhow!("there is no monitor"))?
|
||||
.update_focused_workspace(offset, &invisible_borders)?;
|
||||
|
||||
if follow_focus {
|
||||
if mouse_follows_focus {
|
||||
if let Some(window) = self.focused_workspace()?.maximized_window() {
|
||||
window.focus(self.mouse_follows_focus)?;
|
||||
window.focus()?;
|
||||
} else if let Some(container) = self.focused_workspace()?.monocle_container() {
|
||||
if let Some(window) = container.focused_window() {
|
||||
window.focus(self.mouse_follows_focus)?;
|
||||
window.focus()?;
|
||||
}
|
||||
} else if let Ok(window) = self.focused_window_mut() {
|
||||
window.focus(self.mouse_follows_focus)?;
|
||||
window.focus()?;
|
||||
} else {
|
||||
let desktop_window = Window {
|
||||
hwnd: WindowsApi::desktop_window()?,
|
||||
@@ -672,8 +588,7 @@ impl WindowManager {
|
||||
&mut self,
|
||||
direction: OperationDirection,
|
||||
sizing: Sizing,
|
||||
delta: i32,
|
||||
update: bool,
|
||||
step: Option<i32>,
|
||||
) -> Result<()> {
|
||||
let work_area = self.focused_monitor_work_area()?;
|
||||
let workspace = self.focused_workspace_mut()?;
|
||||
@@ -712,21 +627,21 @@ impl WindowManager {
|
||||
// can flip them however they need to be flipped once the resizing has been done
|
||||
if let Some(flip) = workspace.layout_flip() {
|
||||
match flip {
|
||||
Axis::Horizontal => {
|
||||
Flip::Horizontal => {
|
||||
if matches!(direction, OperationDirection::Left)
|
||||
|| matches!(direction, OperationDirection::Right)
|
||||
{
|
||||
direction = direction.opposite();
|
||||
}
|
||||
}
|
||||
Axis::Vertical => {
|
||||
Flip::Vertical => {
|
||||
if matches!(direction, OperationDirection::Up)
|
||||
|| matches!(direction, OperationDirection::Down)
|
||||
{
|
||||
direction = direction.opposite();
|
||||
}
|
||||
}
|
||||
Axis::HorizontalAndVertical => direction = direction.opposite(),
|
||||
Flip::HorizontalAndVertical => direction = direction.opposite(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -737,16 +652,11 @@ impl WindowManager {
|
||||
focused_idx_resize,
|
||||
direction,
|
||||
sizing,
|
||||
delta,
|
||||
step,
|
||||
);
|
||||
|
||||
workspace.resize_dimensions_mut()[focused_idx] = resize;
|
||||
|
||||
return if update {
|
||||
self.update_focused_workspace(false)
|
||||
} else {
|
||||
Ok(())
|
||||
};
|
||||
return self.update_focused_workspace(false);
|
||||
}
|
||||
|
||||
tracing::warn!("cannot resize container in this direction");
|
||||
@@ -759,18 +669,26 @@ impl WindowManager {
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub fn restore_all_windows(&mut self) {
|
||||
pub fn restore_all_windows(&mut self) -> Result<()> {
|
||||
tracing::info!("restoring all hidden windows");
|
||||
|
||||
let no_titlebar = NO_TITLEBAR.lock();
|
||||
|
||||
for monitor in self.monitors_mut() {
|
||||
for workspace in monitor.workspaces_mut() {
|
||||
for containers in workspace.containers_mut() {
|
||||
for window in containers.windows_mut() {
|
||||
if no_titlebar.contains(&window.exe()?) {
|
||||
window.add_title_bar()?;
|
||||
}
|
||||
|
||||
window.restore();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
@@ -779,7 +697,6 @@ impl WindowManager {
|
||||
|
||||
let invisible_borders = self.invisible_borders;
|
||||
let offset = self.work_area_offset;
|
||||
let mouse_follows_focus = self.mouse_follows_focus;
|
||||
|
||||
let monitor = self
|
||||
.focused_monitor_mut()
|
||||
@@ -804,57 +721,28 @@ impl WindowManager {
|
||||
.ok_or_else(|| anyhow!("there is no monitor"))?;
|
||||
|
||||
target_monitor.add_container(container)?;
|
||||
target_monitor.load_focused_workspace(mouse_follows_focus)?;
|
||||
target_monitor.load_focused_workspace()?;
|
||||
target_monitor.update_focused_workspace(offset, &invisible_borders)?;
|
||||
|
||||
if follow {
|
||||
self.focus_monitor(idx)?;
|
||||
}
|
||||
|
||||
self.update_focused_workspace(self.mouse_follows_focus)
|
||||
self.update_focused_workspace(true)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub fn move_container_to_workspace(&mut self, idx: usize, follow: bool) -> Result<()> {
|
||||
tracing::info!("moving container");
|
||||
|
||||
let mouse_follows_focus = self.mouse_follows_focus;
|
||||
let monitor = self
|
||||
.focused_monitor_mut()
|
||||
.ok_or_else(|| anyhow!("there is no monitor"))?;
|
||||
|
||||
monitor.move_container_to_workspace(idx, follow)?;
|
||||
monitor.load_focused_workspace(mouse_follows_focus)?;
|
||||
monitor.load_focused_workspace()?;
|
||||
|
||||
self.update_focused_workspace(mouse_follows_focus)
|
||||
}
|
||||
pub fn remove_focused_workspace(&mut self) -> Option<Workspace> {
|
||||
let focused_monitor: &mut Monitor = self.focused_monitor_mut()?;
|
||||
let focused_workspace_idx = focused_monitor.focused_workspace_idx();
|
||||
focused_monitor.remove_workspace_by_idx(focused_workspace_idx)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub fn move_workspace_to_monitor(&mut self, idx: usize) -> Result<()> {
|
||||
tracing::info!("moving workspace");
|
||||
let mouse_follows_focus = self.mouse_follows_focus;
|
||||
let workspace = self
|
||||
.remove_focused_workspace()
|
||||
.ok_or_else(|| anyhow!("there is no workspace"))?;
|
||||
|
||||
{
|
||||
let target_monitor: &mut Monitor = self
|
||||
.monitors_mut()
|
||||
.get_mut(idx)
|
||||
.ok_or_else(|| anyhow!("there is no monitor"))?;
|
||||
|
||||
target_monitor.workspaces_mut().push_back(workspace);
|
||||
target_monitor.focus_workspace(target_monitor.workspaces().len() - 1)?;
|
||||
target_monitor.load_focused_workspace(mouse_follows_focus)?;
|
||||
}
|
||||
|
||||
self.focus_monitor(idx)?;
|
||||
self.update_focused_workspace(mouse_follows_focus)
|
||||
self.update_focused_workspace(true)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
@@ -867,7 +755,7 @@ impl WindowManager {
|
||||
.ok_or_else(|| anyhow!("this is not a valid direction from the current position"))?;
|
||||
|
||||
workspace.focus_container(new_idx);
|
||||
self.focused_window_mut()?.focus(self.mouse_follows_focus)?;
|
||||
self.focused_window_mut()?.focus()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -885,7 +773,7 @@ impl WindowManager {
|
||||
|
||||
workspace.swap_containers(current_idx, new_idx);
|
||||
workspace.focus_container(new_idx);
|
||||
self.update_focused_workspace(self.mouse_follows_focus)
|
||||
self.update_focused_workspace(true)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
@@ -898,7 +786,7 @@ impl WindowManager {
|
||||
.ok_or_else(|| anyhow!("this is not a valid direction from the current position"))?;
|
||||
|
||||
workspace.focus_container(new_idx);
|
||||
self.focused_window_mut()?.focus(self.mouse_follows_focus)?;
|
||||
self.focused_window_mut()?.focus()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -916,7 +804,7 @@ impl WindowManager {
|
||||
|
||||
workspace.swap_containers(current_idx, new_idx);
|
||||
workspace.focus_container(new_idx);
|
||||
self.update_focused_workspace(self.mouse_follows_focus)
|
||||
self.update_focused_workspace(true)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
@@ -938,7 +826,7 @@ impl WindowManager {
|
||||
container.focus_window(next_idx);
|
||||
container.load_focused_window();
|
||||
|
||||
self.update_focused_workspace(self.mouse_follows_focus)
|
||||
self.update_focused_workspace(true)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
@@ -971,7 +859,7 @@ impl WindowManager {
|
||||
};
|
||||
|
||||
workspace.move_window_to_container(adjusted_new_index)?;
|
||||
self.update_focused_workspace(self.mouse_follows_focus)?;
|
||||
self.update_focused_workspace(true)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -983,7 +871,7 @@ impl WindowManager {
|
||||
|
||||
let workspace = self.focused_workspace_mut()?;
|
||||
workspace.promote_container()?;
|
||||
self.update_focused_workspace(self.mouse_follows_focus)
|
||||
self.update_focused_workspace(true)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
@@ -997,7 +885,7 @@ impl WindowManager {
|
||||
let workspace = self.focused_workspace_mut()?;
|
||||
|
||||
workspace.new_container_for_focused_window()?;
|
||||
self.update_focused_workspace(self.mouse_follows_focus)
|
||||
self.update_focused_workspace(true)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
@@ -1045,7 +933,7 @@ impl WindowManager {
|
||||
.ok_or_else(|| anyhow!("there is no floating window"))?;
|
||||
|
||||
window.center(&work_area, &invisible_borders)?;
|
||||
window.focus(self.mouse_follows_focus)?;
|
||||
window.focus()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -1115,7 +1003,7 @@ impl WindowManager {
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub fn flip_layout(&mut self, layout_flip: Axis) -> Result<()> {
|
||||
pub fn flip_layout(&mut self, layout_flip: Flip) -> Result<()> {
|
||||
tracing::info!("flipping layout");
|
||||
|
||||
let workspace = self.focused_workspace_mut()?;
|
||||
@@ -1127,28 +1015,28 @@ impl WindowManager {
|
||||
}
|
||||
Some(current_layout_flip) => {
|
||||
match current_layout_flip {
|
||||
Axis::Horizontal => match layout_flip {
|
||||
Axis::Horizontal => workspace.set_layout_flip(None),
|
||||
Axis::Vertical => {
|
||||
workspace.set_layout_flip(Option::from(Axis::HorizontalAndVertical))
|
||||
Flip::Horizontal => match layout_flip {
|
||||
Flip::Horizontal => workspace.set_layout_flip(None),
|
||||
Flip::Vertical => {
|
||||
workspace.set_layout_flip(Option::from(Flip::HorizontalAndVertical))
|
||||
}
|
||||
Axis::HorizontalAndVertical => {
|
||||
workspace.set_layout_flip(Option::from(Axis::HorizontalAndVertical))
|
||||
Flip::HorizontalAndVertical => {
|
||||
workspace.set_layout_flip(Option::from(Flip::HorizontalAndVertical))
|
||||
}
|
||||
},
|
||||
Axis::Vertical => match layout_flip {
|
||||
Axis::Horizontal => {
|
||||
workspace.set_layout_flip(Option::from(Axis::HorizontalAndVertical))
|
||||
Flip::Vertical => match layout_flip {
|
||||
Flip::Horizontal => {
|
||||
workspace.set_layout_flip(Option::from(Flip::HorizontalAndVertical))
|
||||
}
|
||||
Axis::Vertical => workspace.set_layout_flip(None),
|
||||
Axis::HorizontalAndVertical => {
|
||||
workspace.set_layout_flip(Option::from(Axis::HorizontalAndVertical))
|
||||
Flip::Vertical => workspace.set_layout_flip(None),
|
||||
Flip::HorizontalAndVertical => {
|
||||
workspace.set_layout_flip(Option::from(Flip::HorizontalAndVertical))
|
||||
}
|
||||
},
|
||||
Axis::HorizontalAndVertical => match layout_flip {
|
||||
Axis::Horizontal => workspace.set_layout_flip(Option::from(Axis::Vertical)),
|
||||
Axis::Vertical => workspace.set_layout_flip(Option::from(Axis::Horizontal)),
|
||||
Axis::HorizontalAndVertical => workspace.set_layout_flip(None),
|
||||
Flip::HorizontalAndVertical => match layout_flip {
|
||||
Flip::Horizontal => workspace.set_layout_flip(Option::from(Flip::Vertical)),
|
||||
Flip::Vertical => workspace.set_layout_flip(Option::from(Flip::Horizontal)),
|
||||
Flip::HorizontalAndVertical => workspace.set_layout_flip(None),
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -1179,7 +1067,7 @@ impl WindowManager {
|
||||
}
|
||||
|
||||
workspace.set_layout(Layout::Default(layout));
|
||||
self.update_focused_workspace(self.mouse_follows_focus)
|
||||
self.update_focused_workspace(true)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
@@ -1205,7 +1093,7 @@ impl WindowManager {
|
||||
}
|
||||
|
||||
workspace.set_layout(Layout::Custom(layout));
|
||||
self.update_focused_workspace(self.mouse_follows_focus)
|
||||
self.update_focused_workspace(true)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
@@ -1487,30 +1375,28 @@ impl WindowManager {
|
||||
pub fn focus_workspace(&mut self, idx: usize) -> Result<()> {
|
||||
tracing::info!("focusing workspace");
|
||||
|
||||
let mouse_follows_focus = self.mouse_follows_focus;
|
||||
let monitor = self
|
||||
.focused_monitor_mut()
|
||||
.ok_or_else(|| anyhow!("there is no workspace"))?;
|
||||
|
||||
monitor.focus_workspace(idx)?;
|
||||
monitor.load_focused_workspace(mouse_follows_focus)?;
|
||||
monitor.load_focused_workspace()?;
|
||||
|
||||
self.update_focused_workspace(mouse_follows_focus)
|
||||
self.update_focused_workspace(true)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub fn new_workspace(&mut self) -> Result<()> {
|
||||
tracing::info!("adding new workspace");
|
||||
|
||||
let mouse_follows_focus = self.mouse_follows_focus;
|
||||
let monitor = self
|
||||
.focused_monitor_mut()
|
||||
.ok_or_else(|| anyhow!("there is no workspace"))?;
|
||||
|
||||
monitor.focus_workspace(monitor.new_workspace_idx())?;
|
||||
monitor.load_focused_workspace(mouse_follows_focus)?;
|
||||
monitor.load_focused_workspace()?;
|
||||
|
||||
self.update_focused_workspace(self.mouse_follows_focus)
|
||||
self.update_focused_workspace(true)
|
||||
}
|
||||
|
||||
pub fn focused_container(&self) -> Result<&Container> {
|
||||
|
||||
@@ -15,7 +15,6 @@ pub enum WindowManagerEvent {
|
||||
Hide(WinEvent, Window),
|
||||
Minimize(WinEvent, Window),
|
||||
Show(WinEvent, Window),
|
||||
MoveResizeStart(WinEvent, Window),
|
||||
MoveResizeEnd(WinEvent, Window),
|
||||
MouseCapture(WinEvent, Window),
|
||||
Manage(Window),
|
||||
@@ -52,13 +51,6 @@ impl Display for WindowManagerEvent {
|
||||
WindowManagerEvent::Show(winevent, window) => {
|
||||
write!(f, "Show (WinEvent: {}, Window: {})", winevent, window)
|
||||
}
|
||||
WindowManagerEvent::MoveResizeStart(winevent, window) => {
|
||||
write!(
|
||||
f,
|
||||
"MoveResizeStart (WinEvent: {}, Window: {})",
|
||||
winevent, window
|
||||
)
|
||||
}
|
||||
WindowManagerEvent::MoveResizeEnd(winevent, window) => {
|
||||
write!(
|
||||
f,
|
||||
@@ -95,7 +87,6 @@ impl WindowManagerEvent {
|
||||
| WindowManagerEvent::Hide(_, window)
|
||||
| WindowManagerEvent::Minimize(_, window)
|
||||
| WindowManagerEvent::Show(_, window)
|
||||
| WindowManagerEvent::MoveResizeStart(_, window)
|
||||
| WindowManagerEvent::MoveResizeEnd(_, window)
|
||||
| WindowManagerEvent::MouseCapture(_, window)
|
||||
| WindowManagerEvent::MonitorPoll(_, window)
|
||||
@@ -122,7 +113,6 @@ impl WindowManagerEvent {
|
||||
WinEvent::ObjectFocus | WinEvent::SystemForeground => {
|
||||
Option::from(Self::FocusChange(winevent, window))
|
||||
}
|
||||
WinEvent::SystemMoveSizeStart => Option::from(Self::MoveResizeStart(winevent, window)),
|
||||
WinEvent::SystemMoveSizeEnd => Option::from(Self::MoveResizeEnd(winevent, window)),
|
||||
WinEvent::SystemCaptureStart | WinEvent::SystemCaptureEnd => {
|
||||
Option::from(Self::MouseCapture(winevent, window))
|
||||
|
||||
@@ -6,79 +6,80 @@ use std::ffi::c_void;
|
||||
use color_eyre::eyre::anyhow;
|
||||
use color_eyre::eyre::Error;
|
||||
use color_eyre::Result;
|
||||
use windows::core::Result as WindowsCrateResult;
|
||||
use windows::Win32::Foundation::BOOL;
|
||||
use windows::Win32::Foundation::HANDLE;
|
||||
use windows::Win32::Foundation::HWND;
|
||||
use windows::Win32::Foundation::LPARAM;
|
||||
use windows::Win32::Foundation::POINT;
|
||||
use windows::Win32::Foundation::PWSTR;
|
||||
use windows::Win32::Foundation::RECT;
|
||||
use windows::Win32::Graphics::Dwm::DwmGetWindowAttribute;
|
||||
use windows::Win32::Graphics::Dwm::DWMWA_CLOAKED;
|
||||
use windows::Win32::Graphics::Dwm::DWMWA_EXTENDED_FRAME_BOUNDS;
|
||||
use windows::Win32::Graphics::Dwm::DWMWINDOWATTRIBUTE;
|
||||
use windows::Win32::Graphics::Dwm::DWM_CLOAKED_APP;
|
||||
use windows::Win32::Graphics::Dwm::DWM_CLOAKED_INHERITED;
|
||||
use windows::Win32::Graphics::Dwm::DWM_CLOAKED_SHELL;
|
||||
use windows::Win32::Graphics::Gdi::EnumDisplayMonitors;
|
||||
use windows::Win32::Graphics::Gdi::GetMonitorInfoW;
|
||||
use windows::Win32::Graphics::Gdi::MonitorFromPoint;
|
||||
use windows::Win32::Graphics::Gdi::MonitorFromWindow;
|
||||
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::MONITOR_DEFAULTTONEAREST;
|
||||
use windows::Win32::System::RemoteDesktop::ProcessIdToSessionId;
|
||||
use windows::Win32::System::Threading::AttachThreadInput;
|
||||
use windows::Win32::System::Threading::GetCurrentProcessId;
|
||||
use windows::Win32::System::Threading::GetCurrentThreadId;
|
||||
use windows::Win32::System::Threading::OpenProcess;
|
||||
use windows::Win32::System::Threading::QueryFullProcessImageNameW;
|
||||
use windows::Win32::System::Threading::PROCESS_ACCESS_RIGHTS;
|
||||
use windows::Win32::System::Threading::PROCESS_QUERY_INFORMATION;
|
||||
use windows::Win32::UI::Input::KeyboardAndMouse::SetFocus;
|
||||
use windows::Win32::UI::WindowsAndMessaging::AllowSetForegroundWindow;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EnumWindows;
|
||||
use windows::Win32::UI::WindowsAndMessaging::GetCursorPos;
|
||||
use windows::Win32::UI::WindowsAndMessaging::GetDesktopWindow;
|
||||
use windows::Win32::UI::WindowsAndMessaging::GetForegroundWindow;
|
||||
use windows::Win32::UI::WindowsAndMessaging::GetTopWindow;
|
||||
use windows::Win32::UI::WindowsAndMessaging::GetWindow;
|
||||
use windows::Win32::UI::WindowsAndMessaging::GetWindowLongPtrW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::GetWindowRect;
|
||||
use windows::Win32::UI::WindowsAndMessaging::GetWindowTextW;
|
||||
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::RealGetWindowClassW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SetCursorPos;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SetForegroundWindow;
|
||||
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::GWL_EXSTYLE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::GWL_STYLE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::GW_HWNDNEXT;
|
||||
use windows::Win32::UI::WindowsAndMessaging::HWND_NOTOPMOST;
|
||||
use windows::Win32::UI::WindowsAndMessaging::HWND_TOPMOST;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SHOW_WINDOW_CMD;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SPIF_SENDCHANGE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SPI_GETACTIVEWINDOWTRACKING;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SPI_SETACTIVEWINDOWTRACKING;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SW_HIDE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SW_MAXIMIZE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SW_MINIMIZE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SW_RESTORE;
|
||||
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::WNDENUMPROC;
|
||||
|
||||
use bindings::Handle;
|
||||
use bindings::Result as WindowsCrateResult;
|
||||
use bindings::Windows::Win32::Foundation::BOOL;
|
||||
use bindings::Windows::Win32::Foundation::HANDLE;
|
||||
use bindings::Windows::Win32::Foundation::HWND;
|
||||
use bindings::Windows::Win32::Foundation::LPARAM;
|
||||
use bindings::Windows::Win32::Foundation::POINT;
|
||||
use bindings::Windows::Win32::Foundation::PWSTR;
|
||||
use bindings::Windows::Win32::Foundation::RECT;
|
||||
use bindings::Windows::Win32::Graphics::Dwm::DwmGetWindowAttribute;
|
||||
use bindings::Windows::Win32::Graphics::Dwm::DWMWA_CLOAKED;
|
||||
use bindings::Windows::Win32::Graphics::Dwm::DWMWA_EXTENDED_FRAME_BOUNDS;
|
||||
use bindings::Windows::Win32::Graphics::Dwm::DWMWINDOWATTRIBUTE;
|
||||
use bindings::Windows::Win32::Graphics::Dwm::DWM_CLOAKED_APP;
|
||||
use bindings::Windows::Win32::Graphics::Dwm::DWM_CLOAKED_INHERITED;
|
||||
use bindings::Windows::Win32::Graphics::Dwm::DWM_CLOAKED_SHELL;
|
||||
use bindings::Windows::Win32::Graphics::Gdi::EnumDisplayMonitors;
|
||||
use bindings::Windows::Win32::Graphics::Gdi::GetMonitorInfoW;
|
||||
use bindings::Windows::Win32::Graphics::Gdi::MonitorFromPoint;
|
||||
use bindings::Windows::Win32::Graphics::Gdi::MonitorFromWindow;
|
||||
use bindings::Windows::Win32::Graphics::Gdi::HDC;
|
||||
use bindings::Windows::Win32::Graphics::Gdi::HMONITOR;
|
||||
use bindings::Windows::Win32::Graphics::Gdi::MONITORENUMPROC;
|
||||
use bindings::Windows::Win32::Graphics::Gdi::MONITORINFO;
|
||||
use bindings::Windows::Win32::Graphics::Gdi::MONITOR_DEFAULTTONEAREST;
|
||||
use bindings::Windows::Win32::System::Threading::AttachThreadInput;
|
||||
use bindings::Windows::Win32::System::Threading::GetCurrentProcessId;
|
||||
use bindings::Windows::Win32::System::Threading::GetCurrentThreadId;
|
||||
use bindings::Windows::Win32::System::Threading::OpenProcess;
|
||||
use bindings::Windows::Win32::System::Threading::QueryFullProcessImageNameW;
|
||||
use bindings::Windows::Win32::System::Threading::PROCESS_ACCESS_RIGHTS;
|
||||
use bindings::Windows::Win32::System::Threading::PROCESS_NAME_FORMAT;
|
||||
use bindings::Windows::Win32::System::Threading::PROCESS_QUERY_INFORMATION;
|
||||
use bindings::Windows::Win32::UI::KeyboardAndMouseInput::SetFocus;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::AllowSetForegroundWindow;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EnumWindows;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::GetCursorPos;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::GetDesktopWindow;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::GetForegroundWindow;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::GetTopWindow;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::GetWindow;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::GetWindowLongPtrW;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::GetWindowRect;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::GetWindowTextW;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::GetWindowThreadProcessId;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::IsIconic;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::IsWindow;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::IsWindowVisible;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::RealGetWindowClassW;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::SetCursorPos;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::SetForegroundWindow;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::SetWindowLongPtrW;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::SetWindowPos;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::ShowWindow;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::SystemParametersInfoW;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WindowFromPoint;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::GWL_EXSTYLE;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::GWL_STYLE;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::GW_HWNDNEXT;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::HWND_NOTOPMOST;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::HWND_TOPMOST;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::SET_WINDOW_POS_FLAGS;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::SHOW_WINDOW_CMD;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::SPIF_SENDCHANGE;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::SPI_GETACTIVEWINDOWTRACKING;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::SPI_SETACTIVEWINDOWTRACKING;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::SW_HIDE;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::SW_MAXIMIZE;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::SW_RESTORE;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::SYSTEM_PARAMETERS_INFO_ACTION;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::SYSTEM_PARAMETERS_INFO_UPDATE_FLAGS;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WINDOW_LONG_PTR_INDEX;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::WNDENUMPROC;
|
||||
use komorebi_core::Rect;
|
||||
|
||||
use crate::container::Container;
|
||||
@@ -164,7 +165,7 @@ impl WindowsApi {
|
||||
EnumDisplayMonitors(
|
||||
HDC(0),
|
||||
std::ptr::null_mut(),
|
||||
callback,
|
||||
Option::from(callback),
|
||||
LPARAM(callback_data_address),
|
||||
)
|
||||
}
|
||||
@@ -176,7 +177,7 @@ impl WindowsApi {
|
||||
let mut monitors: Vec<isize> = vec![];
|
||||
let monitors_ref: &mut Vec<isize> = monitors.as_mut();
|
||||
Self::enum_display_monitors(
|
||||
Option::Some(windows_callbacks::valid_display_monitors),
|
||||
windows_callbacks::valid_display_monitors,
|
||||
monitors_ref as *mut Vec<isize> as isize,
|
||||
)?;
|
||||
|
||||
@@ -185,13 +186,13 @@ impl WindowsApi {
|
||||
|
||||
pub fn load_monitor_information(monitors: &mut Ring<Monitor>) -> Result<()> {
|
||||
Self::enum_display_monitors(
|
||||
Option::Some(windows_callbacks::enum_display_monitor),
|
||||
windows_callbacks::enum_display_monitor,
|
||||
monitors as *mut Ring<Monitor> as isize,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn enum_windows(callback: WNDENUMPROC, callback_data_address: isize) -> Result<()> {
|
||||
unsafe { EnumWindows(callback, LPARAM(callback_data_address)) }
|
||||
unsafe { EnumWindows(Option::from(callback), LPARAM(callback_data_address)) }
|
||||
.ok()
|
||||
.process()
|
||||
}
|
||||
@@ -202,7 +203,7 @@ impl WindowsApi {
|
||||
if let Some(workspace) = monitor.workspaces_mut().front_mut() {
|
||||
// EnumWindows will enumerate through windows on all monitors
|
||||
Self::enum_windows(
|
||||
Option::Some(windows_callbacks::enum_window),
|
||||
windows_callbacks::enum_window,
|
||||
workspace.containers_mut() as *mut VecDeque<Container> as isize,
|
||||
)?;
|
||||
|
||||
@@ -265,7 +266,7 @@ impl WindowsApi {
|
||||
layout.top,
|
||||
layout.right,
|
||||
layout.bottom,
|
||||
flags,
|
||||
SET_WINDOW_POS_FLAGS(flags),
|
||||
)
|
||||
}
|
||||
.ok()
|
||||
@@ -278,10 +279,6 @@ impl WindowsApi {
|
||||
unsafe { ShowWindow(hwnd, command) };
|
||||
}
|
||||
|
||||
pub fn minimize_window(hwnd: HWND) {
|
||||
Self::show_window(hwnd, SW_MINIMIZE);
|
||||
}
|
||||
|
||||
pub fn hide_window(hwnd: HWND) {
|
||||
Self::show_window(hwnd, SW_HIDE);
|
||||
}
|
||||
@@ -380,19 +377,6 @@ impl WindowsApi {
|
||||
unsafe { GetCurrentProcessId() }
|
||||
}
|
||||
|
||||
pub fn process_id_to_session_id() -> Result<u32> {
|
||||
let process_id = Self::current_process_id();
|
||||
let mut session_id = 0;
|
||||
|
||||
unsafe {
|
||||
if ProcessIdToSessionId(process_id, &mut session_id).as_bool() {
|
||||
Ok(session_id)
|
||||
} else {
|
||||
Err(anyhow!("could not determine current session id"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn attach_thread_input(thread_id: u32, target_thread_id: u32, attach: bool) -> Result<()> {
|
||||
unsafe { AttachThreadInput(thread_id, target_thread_id, attach) }
|
||||
.ok()
|
||||
@@ -424,9 +408,9 @@ impl WindowsApi {
|
||||
}
|
||||
|
||||
fn window_long_ptr_w(hwnd: HWND, index: WINDOW_LONG_PTR_INDEX) -> Result<isize> {
|
||||
Result::from(WindowsResult::from(unsafe {
|
||||
GetWindowLongPtrW(hwnd, index)
|
||||
}))
|
||||
// Can return 0, which does not always mean that an error has occurred
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowlongptrw
|
||||
Result::from(unsafe { WindowsResult::Ok(GetWindowLongPtrW(hwnd, index)) })
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
@@ -467,7 +451,12 @@ impl WindowsApi {
|
||||
let text_ptr = path.as_mut_ptr();
|
||||
|
||||
unsafe {
|
||||
QueryFullProcessImageNameW(handle, 0, PWSTR(text_ptr), std::ptr::addr_of_mut!(len))
|
||||
QueryFullProcessImageNameW(
|
||||
handle,
|
||||
PROCESS_NAME_FORMAT(0),
|
||||
PWSTR(text_ptr),
|
||||
&mut len as *mut u32,
|
||||
)
|
||||
}
|
||||
.ok()
|
||||
.process()?;
|
||||
@@ -502,7 +491,7 @@ impl WindowsApi {
|
||||
unsafe {
|
||||
DwmGetWindowAttribute(
|
||||
hwnd,
|
||||
attribute,
|
||||
std::mem::transmute::<_, u32>(attribute),
|
||||
(value as *mut T).cast(),
|
||||
u32::try_from(std::mem::size_of::<T>())?,
|
||||
)?;
|
||||
@@ -545,7 +534,7 @@ impl WindowsApi {
|
||||
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()) }
|
||||
unsafe { GetMonitorInfoW(hmonitor, (&mut monitor_info as *mut MONITORINFO).cast()) }
|
||||
.ok()
|
||||
.process()?;
|
||||
|
||||
@@ -581,7 +570,7 @@ impl WindowsApi {
|
||||
Self::system_parameters_info_w(
|
||||
SPI_GETACTIVEWINDOWTRACKING,
|
||||
0,
|
||||
std::ptr::addr_of_mut!(is_enabled).cast(),
|
||||
(&mut is_enabled as *mut BOOL).cast(),
|
||||
SPIF_SENDCHANGE,
|
||||
)?;
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
use std::collections::VecDeque;
|
||||
|
||||
use windows::Win32::Foundation::BOOL;
|
||||
use windows::Win32::Foundation::HWND;
|
||||
use windows::Win32::Foundation::LPARAM;
|
||||
use windows::Win32::Foundation::RECT;
|
||||
use windows::Win32::Graphics::Gdi::HDC;
|
||||
use windows::Win32::Graphics::Gdi::HMONITOR;
|
||||
use windows::Win32::UI::Accessibility::HWINEVENTHOOK;
|
||||
use bindings::Windows::Win32::Foundation::BOOL;
|
||||
use bindings::Windows::Win32::Foundation::HWND;
|
||||
use bindings::Windows::Win32::Foundation::LPARAM;
|
||||
use bindings::Windows::Win32::Foundation::RECT;
|
||||
use bindings::Windows::Win32::Graphics::Gdi::HDC;
|
||||
use bindings::Windows::Win32::Graphics::Gdi::HMONITOR;
|
||||
use bindings::Windows::Win32::UI::Accessibility::HWINEVENTHOOK;
|
||||
|
||||
use crate::container::Container;
|
||||
use crate::monitor::Monitor;
|
||||
|
||||
@@ -1,89 +1,90 @@
|
||||
use serde::Serialize;
|
||||
use strum::Display;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_AIA_END;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_AIA_START;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_CONSOLE_CARET;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_CONSOLE_END;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_CONSOLE_END_APPLICATION;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_CONSOLE_LAYOUT;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_CONSOLE_START_APPLICATION;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_CONSOLE_UPDATE_REGION;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_CONSOLE_UPDATE_SCROLL;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_CONSOLE_UPDATE_SIMPLE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_ACCELERATORCHANGE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_CLOAKED;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_CONTENTSCROLLED;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_CREATE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_DEFACTIONCHANGE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_DESCRIPTIONCHANGE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_DESTROY;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_DRAGCANCEL;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_DRAGCOMPLETE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_DRAGDROPPED;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_DRAGENTER;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_DRAGLEAVE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_DRAGSTART;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_END;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_FOCUS;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_HELPCHANGE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_HIDE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_HOSTEDOBJECTSINVALIDATED;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_IME_CHANGE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_IME_HIDE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_IME_SHOW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_INVOKED;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_LIVEREGIONCHANGED;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_LOCATIONCHANGE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_NAMECHANGE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_PARENTCHANGE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_REORDER;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_SELECTION;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_SELECTIONADD;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_SELECTIONREMOVE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_SELECTIONWITHIN;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_SHOW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_STATECHANGE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_TEXTEDIT_CONVERSIONTARGETCHANGED;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_TEXTSELECTIONCHANGED;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_UNCLOAKED;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_VALUECHANGE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OEM_DEFINED_END;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OEM_DEFINED_START;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_ALERT;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_ARRANGMENTPREVIEW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_CAPTUREEND;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_CAPTURESTART;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_CONTEXTHELPEND;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_CONTEXTHELPSTART;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_DESKTOPSWITCH;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_DIALOGEND;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_DIALOGSTART;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_DRAGDROPEND;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_DRAGDROPSTART;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_END;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_FOREGROUND;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_IME_KEY_NOTIFICATION;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_MENUEND;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_MENUPOPUPEND;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_MENUPOPUPSTART;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_MENUSTART;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_MINIMIZEEND;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_MINIMIZESTART;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_MOVESIZEEND;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_MOVESIZESTART;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_SCROLLINGEND;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_SCROLLINGSTART;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_SOUND;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_SWITCHEND;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_SWITCHER_APPDROPPED;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_SWITCHER_APPGRABBED;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_SWITCHER_APPOVERTARGET;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_SWITCHER_CANCELLED;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_SWITCHSTART;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_UIA_EVENTID_END;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_UIA_EVENTID_START;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_UIA_PROPID_END;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_UIA_PROPID_START;
|
||||
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_AIA_END;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_AIA_START;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_CONSOLE_CARET;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_CONSOLE_END;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_CONSOLE_END_APPLICATION;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_CONSOLE_LAYOUT;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_CONSOLE_START_APPLICATION;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_CONSOLE_UPDATE_REGION;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_CONSOLE_UPDATE_SCROLL;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_CONSOLE_UPDATE_SIMPLE;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_ACCELERATORCHANGE;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_CLOAKED;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_CONTENTSCROLLED;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_CREATE;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_DEFACTIONCHANGE;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_DESCRIPTIONCHANGE;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_DESTROY;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_DRAGCANCEL;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_DRAGCOMPLETE;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_DRAGDROPPED;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_DRAGENTER;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_DRAGLEAVE;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_DRAGSTART;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_END;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_FOCUS;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_HELPCHANGE;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_HIDE;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_HOSTEDOBJECTSINVALIDATED;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_IME_CHANGE;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_IME_HIDE;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_IME_SHOW;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_INVOKED;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_LIVEREGIONCHANGED;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_LOCATIONCHANGE;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_NAMECHANGE;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_PARENTCHANGE;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_REORDER;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_SELECTION;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_SELECTIONADD;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_SELECTIONREMOVE;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_SELECTIONWITHIN;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_SHOW;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_STATECHANGE;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_TEXTEDIT_CONVERSIONTARGETCHANGED;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_TEXTSELECTIONCHANGED;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_UNCLOAKED;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_VALUECHANGE;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_OEM_DEFINED_END;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_OEM_DEFINED_START;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_ALERT;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_ARRANGMENTPREVIEW;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_CAPTUREEND;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_CAPTURESTART;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_CONTEXTHELPEND;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_CONTEXTHELPSTART;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_DESKTOPSWITCH;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_DIALOGEND;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_DIALOGSTART;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_DRAGDROPEND;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_DRAGDROPSTART;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_END;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_FOREGROUND;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_IME_KEY_NOTIFICATION;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_MENUEND;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_MENUPOPUPEND;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_MENUPOPUPSTART;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_MENUSTART;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_MINIMIZEEND;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_MINIMIZESTART;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_MOVESIZEEND;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_MOVESIZESTART;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_SCROLLINGEND;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_SCROLLINGSTART;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_SOUND;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_SWITCHEND;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_SWITCHER_APPDROPPED;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_SWITCHER_APPGRABBED;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_SWITCHER_APPOVERTARGET;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_SWITCHER_CANCELLED;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_SYSTEM_SWITCHSTART;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_UIA_EVENTID_END;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_UIA_EVENTID_START;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_UIA_PROPID_END;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_UIA_PROPID_START;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Debug, Serialize, Display)]
|
||||
#[repr(u32)]
|
||||
|
||||
@@ -8,15 +8,16 @@ use crossbeam_channel::Receiver;
|
||||
use crossbeam_channel::Sender;
|
||||
use lazy_static::lazy_static;
|
||||
use parking_lot::Mutex;
|
||||
use windows::Win32::Foundation::HWND;
|
||||
use windows::Win32::UI::Accessibility::SetWinEventHook;
|
||||
use windows::Win32::UI::WindowsAndMessaging::DispatchMessageW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::PeekMessageW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::TranslateMessage;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_MAX;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_MIN;
|
||||
use windows::Win32::UI::WindowsAndMessaging::MSG;
|
||||
use windows::Win32::UI::WindowsAndMessaging::PM_REMOVE;
|
||||
|
||||
use bindings::Windows::Win32::Foundation::HWND;
|
||||
use bindings::Windows::Win32::UI::Accessibility::SetWinEventHook;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::DispatchMessageW;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::PeekMessageW;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::TranslateMessage;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_MAX;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::EVENT_MIN;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::MSG;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::PM_REMOVE;
|
||||
|
||||
use crate::window_manager_event::WindowManagerEvent;
|
||||
use crate::windows_callbacks;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use std::collections::VecDeque;
|
||||
use std::num::NonZeroUsize;
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
use color_eyre::eyre::anyhow;
|
||||
use color_eyre::Result;
|
||||
@@ -9,9 +10,9 @@ use getset::MutGetters;
|
||||
use getset::Setters;
|
||||
use serde::Serialize;
|
||||
|
||||
use komorebi_core::Axis;
|
||||
use komorebi_core::CycleDirection;
|
||||
use komorebi_core::DefaultLayout;
|
||||
use komorebi_core::Flip;
|
||||
use komorebi_core::Layout;
|
||||
use komorebi_core::OperationDirection;
|
||||
use komorebi_core::Rect;
|
||||
@@ -20,6 +21,8 @@ use crate::container::Container;
|
||||
use crate::ring::Ring;
|
||||
use crate::window::Window;
|
||||
use crate::windows_api::WindowsApi;
|
||||
use crate::NO_TITLEBAR;
|
||||
use crate::REMOVE_TITLEBARS;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Getters, CopyGetters, MutGetters, Setters)]
|
||||
pub struct Workspace {
|
||||
@@ -38,10 +41,10 @@ pub struct Workspace {
|
||||
maximized_window_restore_idx: Option<usize>,
|
||||
#[getset(get = "pub", get_mut = "pub")]
|
||||
floating_windows: Vec<Window>,
|
||||
#[getset(get = "pub", get_mut = "pub", set = "pub")]
|
||||
#[getset(get = "pub", set = "pub")]
|
||||
layout: Layout,
|
||||
#[getset(get_copy = "pub", set = "pub")]
|
||||
layout_flip: Option<Axis>,
|
||||
layout_flip: Option<Flip>,
|
||||
#[getset(get_copy = "pub", set = "pub")]
|
||||
workspace_padding: Option<i32>,
|
||||
#[getset(get_copy = "pub", set = "pub")]
|
||||
@@ -101,7 +104,7 @@ impl Workspace {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn restore(&mut self, mouse_follows_focus: bool) -> Result<()> {
|
||||
pub fn restore(&mut self) -> Result<()> {
|
||||
let idx = self.focused_container_idx();
|
||||
let mut to_focus = None;
|
||||
for (i, container) in self.containers_mut().iter_mut().enumerate() {
|
||||
@@ -132,7 +135,7 @@ impl Workspace {
|
||||
// Maximised windows should always be drawn at the top of the Z order
|
||||
if let Some(window) = to_focus {
|
||||
if self.maximized_window().is_none() {
|
||||
window.focus(mouse_follows_focus)?;
|
||||
window.focus()?;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,9 +187,18 @@ impl Workspace {
|
||||
self.resize_dimensions(),
|
||||
);
|
||||
|
||||
let should_remove_titlebars = REMOVE_TITLEBARS.load(Ordering::SeqCst);
|
||||
let no_titlebar = { NO_TITLEBAR.lock().clone() };
|
||||
|
||||
let windows = self.visible_windows_mut();
|
||||
for (i, window) in windows.into_iter().enumerate() {
|
||||
if let (Some(window), Some(layout)) = (window, layouts.get(i)) {
|
||||
if should_remove_titlebars && no_titlebar.contains(&window.exe()?) {
|
||||
window.remove_title_bar()?;
|
||||
} else if no_titlebar.contains(&window.exe()?) {
|
||||
window.add_title_bar()?;
|
||||
}
|
||||
|
||||
window.set_position(layout, invisible_borders, false)?;
|
||||
}
|
||||
}
|
||||
@@ -456,12 +468,10 @@ impl Workspace {
|
||||
if self.resize_dimensions().get(container_idx).is_some() {
|
||||
self.resize_dimensions_mut().remove(container_idx);
|
||||
}
|
||||
|
||||
self.focus_previous_container();
|
||||
} else {
|
||||
container.load_focused_window();
|
||||
}
|
||||
|
||||
self.focus_previous_container();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -473,13 +483,6 @@ impl Workspace {
|
||||
container
|
||||
}
|
||||
|
||||
pub fn remove_container(&mut self, idx: usize) -> Option<Container> {
|
||||
let container = self.remove_container_by_idx(idx);
|
||||
self.focus_previous_container();
|
||||
|
||||
container
|
||||
}
|
||||
|
||||
pub fn new_idx_for_direction(&self, direction: OperationDirection) -> Option<usize> {
|
||||
let len = NonZeroUsize::new(self.containers().len())?;
|
||||
|
||||
|
||||
@@ -28,20 +28,20 @@ Log() {
|
||||
Run, komorebic.exe log, , Hide
|
||||
}
|
||||
|
||||
QuickSaveResize() {
|
||||
Run, komorebic.exe quick-save-resize, , Hide
|
||||
QuickSave() {
|
||||
Run, komorebic.exe quick-save, , Hide
|
||||
}
|
||||
|
||||
QuickLoadResize() {
|
||||
Run, komorebic.exe quick-load-resize, , Hide
|
||||
QuickLoad() {
|
||||
Run, komorebic.exe quick-load, , Hide
|
||||
}
|
||||
|
||||
SaveResize(path) {
|
||||
Run, komorebic.exe save-resize %path%, , Hide
|
||||
Save(path) {
|
||||
Run, komorebic.exe save %path%, , Hide
|
||||
}
|
||||
|
||||
LoadResize(path) {
|
||||
Run, komorebic.exe load-resize %path%, , Hide
|
||||
Load(path) {
|
||||
Run, komorebic.exe load %path%, , Hide
|
||||
}
|
||||
|
||||
Focus(operation_direction) {
|
||||
@@ -68,10 +68,6 @@ 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
|
||||
}
|
||||
@@ -104,10 +100,6 @@ 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
|
||||
}
|
||||
@@ -116,18 +108,10 @@ 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
|
||||
}
|
||||
@@ -152,8 +136,8 @@ LoadCustomLayout(path) {
|
||||
Run, komorebic.exe load-custom-layout %path%, , Hide
|
||||
}
|
||||
|
||||
FlipLayout(axis) {
|
||||
Run, komorebic.exe flip-layout %axis%, , Hide
|
||||
FlipLayout(flip) {
|
||||
Run, komorebic.exe flip-layout %flip%, , Hide
|
||||
}
|
||||
|
||||
Promote() {
|
||||
@@ -192,10 +176,6 @@ 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
|
||||
}
|
||||
@@ -236,10 +216,6 @@ WatchConfiguration(boolean_state) {
|
||||
Run, komorebic.exe watch-configuration %boolean_state%, , Hide
|
||||
}
|
||||
|
||||
WindowHidingBehaviour(hiding_behaviour) {
|
||||
Run, komorebic.exe window-hiding-behaviour %hiding_behaviour%, , Hide
|
||||
}
|
||||
|
||||
FloatRule(identifier, id) {
|
||||
Run, komorebic.exe float-rule %identifier% %id%, , Hide
|
||||
}
|
||||
@@ -268,14 +244,6 @@ 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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "komorebic"
|
||||
version = "0.1.8"
|
||||
version = "0.1.6"
|
||||
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"]
|
||||
@@ -11,23 +11,17 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
bindings = { package = "bindings", path = "../bindings" }
|
||||
derive-ahk = { path = "../derive-ahk" }
|
||||
komorebi-core = { path = "../komorebi-core" }
|
||||
|
||||
clap = { version = "3", features = ["derive", "wrap_help"] }
|
||||
clap = "3.0.0-beta.4"
|
||||
color-eyre = "0.5"
|
||||
dirs = "4"
|
||||
fs-tail = "0.1"
|
||||
heck = "0.4"
|
||||
heck = "0.3"
|
||||
paste = "1"
|
||||
powershell_script = "0.2"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
uds_windows = "1"
|
||||
|
||||
[dependencies.windows]
|
||||
version = "0.30"
|
||||
features = [
|
||||
"Win32_Foundation",
|
||||
"Win32_UI_WindowsAndMessaging"
|
||||
]
|
||||
|
||||
@@ -12,27 +12,26 @@ use std::process::Command;
|
||||
|
||||
use clap::AppSettings;
|
||||
use clap::ArgEnum;
|
||||
use clap::Parser;
|
||||
use clap::Clap;
|
||||
use color_eyre::eyre::anyhow;
|
||||
use color_eyre::Result;
|
||||
use fs_tail::TailedFile;
|
||||
use heck::ToKebabCase;
|
||||
use heck::KebabCase;
|
||||
use paste::paste;
|
||||
use uds_windows::UnixListener;
|
||||
use uds_windows::UnixStream;
|
||||
use windows::Win32::Foundation::HWND;
|
||||
use windows::Win32::UI::WindowsAndMessaging::ShowWindow;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SHOW_WINDOW_CMD;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SW_RESTORE;
|
||||
|
||||
use bindings::Windows::Win32::Foundation::HWND;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::ShowWindow;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::SHOW_WINDOW_CMD;
|
||||
use bindings::Windows::Win32::UI::WindowsAndMessaging::SW_RESTORE;
|
||||
use derive_ahk::AhkFunction;
|
||||
use derive_ahk::AhkLibrary;
|
||||
use komorebi_core::ApplicationIdentifier;
|
||||
use komorebi_core::Axis;
|
||||
use komorebi_core::CycleDirection;
|
||||
use komorebi_core::DefaultLayout;
|
||||
use komorebi_core::Flip;
|
||||
use komorebi_core::FocusFollowsMouseImplementation;
|
||||
use komorebi_core::HidingBehaviour;
|
||||
use komorebi_core::OperationDirection;
|
||||
use komorebi_core::Rect;
|
||||
use komorebi_core::Sizing;
|
||||
@@ -47,7 +46,7 @@ trait AhkFunction {
|
||||
fn generate_ahk_function() -> String;
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, ArgEnum)]
|
||||
#[derive(ArgEnum)]
|
||||
enum BooleanState {
|
||||
Enable,
|
||||
Disable,
|
||||
@@ -67,7 +66,7 @@ macro_rules! gen_enum_subcommand_args {
|
||||
( $( $name:ident: $element:ty ),+ $(,)? ) => {
|
||||
$(
|
||||
paste! {
|
||||
#[derive(clap::Parser, derive_ahk::AhkFunction)]
|
||||
#[derive(clap::Clap, derive_ahk::AhkFunction)]
|
||||
pub struct $name {
|
||||
#[clap(arg_enum)]
|
||||
[<$element:snake>]: $element
|
||||
@@ -86,19 +85,17 @@ gen_enum_subcommand_args! {
|
||||
CycleWorkspace: CycleDirection,
|
||||
Stack: OperationDirection,
|
||||
CycleStack: CycleDirection,
|
||||
FlipLayout: Axis,
|
||||
FlipLayout: Flip,
|
||||
ChangeLayout: DefaultLayout,
|
||||
WatchConfiguration: BooleanState,
|
||||
MouseFollowsFocus: BooleanState,
|
||||
Query: StateQuery,
|
||||
WindowHidingBehaviour: HidingBehaviour,
|
||||
}
|
||||
|
||||
macro_rules! gen_target_subcommand_args {
|
||||
// SubCommand Pattern
|
||||
( $( $name:ident ),+ $(,)? ) => {
|
||||
$(
|
||||
#[derive(clap::Parser, derive_ahk::AhkFunction)]
|
||||
#[derive(clap::Clap, derive_ahk::AhkFunction)]
|
||||
pub struct $name {
|
||||
/// Target index (zero-indexed)
|
||||
target: usize,
|
||||
@@ -114,7 +111,6 @@ gen_target_subcommand_args! {
|
||||
SendToWorkspace,
|
||||
FocusMonitor,
|
||||
FocusWorkspace,
|
||||
MoveWorkspaceToMonitor,
|
||||
}
|
||||
|
||||
// Thanks to @danielhenrymantilla for showing me how to use cfg_attr with an optional argument like
|
||||
@@ -125,7 +121,7 @@ macro_rules! gen_workspace_subcommand_args {
|
||||
( $( $name:ident: $(#[enum] $(@$arg_enum:tt)?)? $value:ty ),+ $(,)? ) => (
|
||||
paste! {
|
||||
$(
|
||||
#[derive(clap::Parser, derive_ahk::AhkFunction)]
|
||||
#[derive(clap::Clap, derive_ahk::AhkFunction)]
|
||||
pub struct [<Workspace $name>] {
|
||||
/// Monitor index (zero-indexed)
|
||||
monitor: usize,
|
||||
@@ -151,7 +147,7 @@ gen_workspace_subcommand_args! {
|
||||
Tiling: #[enum] BooleanState,
|
||||
}
|
||||
|
||||
#[derive(Parser, AhkFunction)]
|
||||
#[derive(Clap, AhkFunction)]
|
||||
pub struct WorkspaceCustomLayout {
|
||||
/// Monitor index (zero-indexed)
|
||||
monitor: usize,
|
||||
@@ -163,7 +159,7 @@ pub struct WorkspaceCustomLayout {
|
||||
path: String,
|
||||
}
|
||||
|
||||
#[derive(Parser, AhkFunction)]
|
||||
#[derive(Clap, AhkFunction)]
|
||||
struct Resize {
|
||||
#[clap(arg_enum)]
|
||||
edge: OperationDirection,
|
||||
@@ -171,21 +167,7 @@ struct Resize {
|
||||
sizing: Sizing,
|
||||
}
|
||||
|
||||
#[derive(Parser, AhkFunction)]
|
||||
struct ResizeAxis {
|
||||
#[clap(arg_enum)]
|
||||
axis: Axis,
|
||||
#[clap(arg_enum)]
|
||||
sizing: Sizing,
|
||||
}
|
||||
|
||||
#[derive(Parser, AhkFunction)]
|
||||
struct ResizeDelta {
|
||||
/// The delta of pixels by which to increase or decrease window dimensions when resizing
|
||||
pixels: i32,
|
||||
}
|
||||
|
||||
#[derive(Parser, AhkFunction)]
|
||||
#[derive(Clap, AhkFunction)]
|
||||
struct InvisibleBorders {
|
||||
/// Size of the left invisible border
|
||||
left: i32,
|
||||
@@ -197,7 +179,7 @@ struct InvisibleBorders {
|
||||
bottom: i32,
|
||||
}
|
||||
|
||||
#[derive(Parser, AhkFunction)]
|
||||
#[derive(Clap, AhkFunction)]
|
||||
struct WorkAreaOffset {
|
||||
/// Size of the left work area offset (set right to left * 2 to maintain right padding)
|
||||
left: i32,
|
||||
@@ -209,7 +191,7 @@ struct WorkAreaOffset {
|
||||
bottom: i32,
|
||||
}
|
||||
|
||||
#[derive(Parser, AhkFunction)]
|
||||
#[derive(Clap, AhkFunction)]
|
||||
struct EnsureWorkspaces {
|
||||
/// Monitor index (zero-indexed)
|
||||
monitor: usize,
|
||||
@@ -217,19 +199,11 @@ struct EnsureWorkspaces {
|
||||
workspace_count: usize,
|
||||
}
|
||||
|
||||
#[derive(Parser, AhkFunction)]
|
||||
struct FocusMonitorWorkspace {
|
||||
/// Target monitor index (zero-indexed)
|
||||
target_monitor: usize,
|
||||
/// Workspace index on the target monitor (zero-indexed)
|
||||
target_workspace: usize,
|
||||
}
|
||||
|
||||
macro_rules! gen_padding_subcommand_args {
|
||||
// SubCommand Pattern
|
||||
( $( $name:ident ),+ $(,)? ) => {
|
||||
$(
|
||||
#[derive(clap::Parser, derive_ahk::AhkFunction)]
|
||||
#[derive(clap::Clap, derive_ahk::AhkFunction)]
|
||||
pub struct $name {
|
||||
/// Monitor index (zero-indexed)
|
||||
monitor: usize,
|
||||
@@ -251,7 +225,7 @@ macro_rules! gen_padding_adjustment_subcommand_args {
|
||||
// SubCommand Pattern
|
||||
( $( $name:ident ),+ $(,)? ) => {
|
||||
$(
|
||||
#[derive(clap::Parser, derive_ahk::AhkFunction)]
|
||||
#[derive(clap::Clap, derive_ahk::AhkFunction)]
|
||||
pub struct $name {
|
||||
#[clap(arg_enum)]
|
||||
sizing: Sizing,
|
||||
@@ -271,7 +245,7 @@ macro_rules! gen_application_target_subcommand_args {
|
||||
// SubCommand Pattern
|
||||
( $( $name:ident ),+ $(,)? ) => {
|
||||
$(
|
||||
#[derive(clap::Parser, derive_ahk::AhkFunction)]
|
||||
#[derive(clap::Clap, derive_ahk::AhkFunction)]
|
||||
pub struct $name {
|
||||
#[clap(arg_enum)]
|
||||
identifier: ApplicationIdentifier,
|
||||
@@ -287,9 +261,10 @@ gen_application_target_subcommand_args! {
|
||||
ManageRule,
|
||||
IdentifyTrayApplication,
|
||||
IdentifyBorderOverflow,
|
||||
RemoveTitleBar,
|
||||
}
|
||||
|
||||
#[derive(Parser, AhkFunction)]
|
||||
#[derive(Clap, AhkFunction)]
|
||||
struct WorkspaceRule {
|
||||
#[clap(arg_enum)]
|
||||
identifier: ApplicationIdentifier,
|
||||
@@ -301,13 +276,13 @@ struct WorkspaceRule {
|
||||
workspace: usize,
|
||||
}
|
||||
|
||||
#[derive(Parser, AhkFunction)]
|
||||
#[derive(Clap, AhkFunction)]
|
||||
struct ToggleFocusFollowsMouse {
|
||||
#[clap(arg_enum, short, long, default_value = "windows")]
|
||||
implementation: FocusFollowsMouseImplementation,
|
||||
}
|
||||
|
||||
#[derive(Parser, AhkFunction)]
|
||||
#[derive(Clap, AhkFunction)]
|
||||
struct FocusFollowsMouse {
|
||||
#[clap(arg_enum, short, long, default_value = "windows")]
|
||||
implementation: FocusFollowsMouseImplementation,
|
||||
@@ -315,51 +290,51 @@ struct FocusFollowsMouse {
|
||||
boolean_state: BooleanState,
|
||||
}
|
||||
|
||||
#[derive(Parser, AhkFunction)]
|
||||
#[derive(Clap, AhkFunction)]
|
||||
struct Start {
|
||||
/// Allow the use of komorebi's custom focus-follows-mouse implementation
|
||||
#[clap(long)]
|
||||
ffm: bool,
|
||||
}
|
||||
|
||||
#[derive(Parser, AhkFunction)]
|
||||
struct SaveResize {
|
||||
#[derive(Clap, AhkFunction)]
|
||||
struct Save {
|
||||
/// File to which the resize layout dimensions should be saved
|
||||
path: String,
|
||||
}
|
||||
|
||||
#[derive(Parser, AhkFunction)]
|
||||
struct LoadResize {
|
||||
#[derive(Clap, AhkFunction)]
|
||||
struct Load {
|
||||
/// File from which the resize layout dimensions should be loaded
|
||||
path: String,
|
||||
}
|
||||
|
||||
#[derive(Parser, AhkFunction)]
|
||||
#[derive(Clap, AhkFunction)]
|
||||
struct LoadCustomLayout {
|
||||
/// JSON or YAML file from which the custom layout definition should be loaded
|
||||
path: String,
|
||||
}
|
||||
|
||||
#[derive(Parser, AhkFunction)]
|
||||
#[derive(Clap, AhkFunction)]
|
||||
struct Subscribe {
|
||||
/// Name of the pipe to send event notifications to (without "\\.\pipe\" prepended)
|
||||
named_pipe: String,
|
||||
}
|
||||
|
||||
#[derive(Parser, AhkFunction)]
|
||||
#[derive(Clap, AhkFunction)]
|
||||
struct Unsubscribe {
|
||||
/// Name of the pipe to stop sending event notifications to (without "\\.\pipe\" prepended)
|
||||
named_pipe: String,
|
||||
}
|
||||
|
||||
#[derive(Parser)]
|
||||
#[derive(Clap)]
|
||||
#[clap(author, about, version, setting = AppSettings::DeriveDisplayOrder)]
|
||||
struct Opts {
|
||||
#[clap(subcommand)]
|
||||
subcmd: SubCommand,
|
||||
}
|
||||
|
||||
#[derive(Parser, AhkLibrary)]
|
||||
#[derive(Clap, AhkLibrary)]
|
||||
enum SubCommand {
|
||||
/// Start komorebi.exe as a background process
|
||||
Start(Start),
|
||||
@@ -379,19 +354,15 @@ enum SubCommand {
|
||||
/// Tail komorebi.exe's process logs (cancel with Ctrl-C)
|
||||
Log,
|
||||
/// Quicksave the current resize layout dimensions
|
||||
#[clap(alias = "quick-save")]
|
||||
QuickSaveResize,
|
||||
QuickSave,
|
||||
/// Load the last quicksaved resize layout dimensions
|
||||
#[clap(alias = "quick-load")]
|
||||
QuickLoadResize,
|
||||
QuickLoad,
|
||||
/// Save the current resize layout dimensions to a file
|
||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||
#[clap(alias = "save")]
|
||||
SaveResize(SaveResize),
|
||||
Save(Save),
|
||||
/// Load the resize layout dimensions from a file
|
||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||
#[clap(alias = "load")]
|
||||
LoadResize(LoadResize),
|
||||
Load(Load),
|
||||
/// Change focus to the window in the specified direction
|
||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||
Focus(Focus),
|
||||
@@ -409,11 +380,7 @@ enum SubCommand {
|
||||
Stack(Stack),
|
||||
/// Resize the focused window in the specified direction
|
||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||
#[clap(alias = "resize")]
|
||||
ResizeEdge(Resize),
|
||||
/// Resize the focused window or primary column along the specified axis
|
||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||
ResizeAxis(ResizeAxis),
|
||||
Resize(Resize),
|
||||
/// Unstack the focused window
|
||||
Unstack,
|
||||
/// Cycle the focused stack in the specified cycle direction
|
||||
@@ -437,23 +404,14 @@ enum SubCommand {
|
||||
/// Focus the specified workspace on the focused monitor
|
||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||
FocusWorkspace(FocusWorkspace),
|
||||
/// Focus the specified workspace on the target monitor
|
||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||
FocusMonitorWorkspace(FocusMonitorWorkspace),
|
||||
/// Focus the monitor in the given cycle direction
|
||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||
CycleMonitor(CycleMonitor),
|
||||
/// Focus the workspace in the given cycle direction
|
||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||
CycleWorkspace(CycleWorkspace),
|
||||
/// Move the focused workspace to the specified monitor
|
||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||
MoveWorkspaceToMonitor(MoveWorkspaceToMonitor),
|
||||
/// Create and append a new workspace on the focused monitor
|
||||
NewWorkspace,
|
||||
/// Set the resize delta (used by resize-edge and resize-axis)
|
||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||
ResizeDelta(ResizeDelta),
|
||||
/// Set the invisible border dimensions around each window
|
||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||
InvisibleBorders(InvisibleBorders),
|
||||
@@ -500,9 +458,7 @@ enum SubCommand {
|
||||
/// Set the workspace name for the specified workspace
|
||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||
WorkspaceName(WorkspaceName),
|
||||
/// Toggle the behaviour for new windows (stacking or dynamic tiling)
|
||||
ToggleWindowContainerBehaviour,
|
||||
/// Toggle window tiling on the focused workspace
|
||||
/// Toggle the window manager on and off across all monitors
|
||||
TogglePause,
|
||||
/// Toggle window tiling on the focused workspace
|
||||
ToggleTiling,
|
||||
@@ -523,9 +479,6 @@ enum SubCommand {
|
||||
/// Enable or disable watching of ~/komorebi.ahk (if it exists)
|
||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||
WatchConfiguration(WatchConfiguration),
|
||||
/// Set the window behaviour when switching workspaces / cycling stacks
|
||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||
WindowHidingBehaviour(WindowHidingBehaviour),
|
||||
/// Add a rule to always float the specified application
|
||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||
FloatRule(FloatRule),
|
||||
@@ -541,17 +494,17 @@ enum SubCommand {
|
||||
/// Identify an application that has overflowing borders
|
||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||
IdentifyBorderOverflow(IdentifyBorderOverflow),
|
||||
/// Whitelist an application for title bar removal
|
||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||
RemoveTitleBar(RemoveTitleBar),
|
||||
/// Toggle title bars for whitelisted applications
|
||||
ToggleTitleBars,
|
||||
/// Enable or disable focus follows mouse for the operating system
|
||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||
FocusFollowsMouse(FocusFollowsMouse),
|
||||
/// Toggle focus follows mouse for the operating system
|
||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||
ToggleFocusFollowsMouse(ToggleFocusFollowsMouse),
|
||||
/// Enable or disable mouse follows focus on all workspaces
|
||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||
MouseFollowsFocus(MouseFollowsFocus),
|
||||
/// Toggle mouse follows focus on all workspaces
|
||||
ToggleMouseFollowsFocus,
|
||||
/// Generate a library of AutoHotKey helper functions
|
||||
AhkLibrary,
|
||||
}
|
||||
@@ -637,9 +590,6 @@ fn main() -> Result<()> {
|
||||
SubCommand::SendToWorkspace(arg) => {
|
||||
send_message(&*SocketMessage::SendContainerToWorkspaceNumber(arg.target).as_bytes()?)?;
|
||||
}
|
||||
SubCommand::MoveWorkspaceToMonitor(arg) => {
|
||||
send_message(&*SocketMessage::MoveWorkspaceToMonitorNumber(arg.target).as_bytes()?)?;
|
||||
}
|
||||
SubCommand::InvisibleBorders(arg) => {
|
||||
send_message(
|
||||
&*SocketMessage::InvisibleBorders(Rect {
|
||||
@@ -807,7 +757,7 @@ fn main() -> Result<()> {
|
||||
)?;
|
||||
}
|
||||
SubCommand::FlipLayout(arg) => {
|
||||
send_message(&*SocketMessage::FlipLayout(arg.axis).as_bytes()?)?;
|
||||
send_message(&*SocketMessage::FlipLayout(arg.flip).as_bytes()?)?;
|
||||
}
|
||||
SubCommand::FocusMonitor(arg) => {
|
||||
send_message(&*SocketMessage::FocusMonitorNumber(arg.target).as_bytes()?)?;
|
||||
@@ -815,15 +765,6 @@ fn main() -> Result<()> {
|
||||
SubCommand::FocusWorkspace(arg) => {
|
||||
send_message(&*SocketMessage::FocusWorkspaceNumber(arg.target).as_bytes()?)?;
|
||||
}
|
||||
SubCommand::FocusMonitorWorkspace(arg) => {
|
||||
send_message(
|
||||
&*SocketMessage::FocusMonitorWorkspaceNumber(
|
||||
arg.target_monitor,
|
||||
arg.target_workspace,
|
||||
)
|
||||
.as_bytes()?,
|
||||
)?;
|
||||
}
|
||||
SubCommand::CycleMonitor(arg) => {
|
||||
send_message(&*SocketMessage::CycleFocusMonitor(arg.cycle_direction).as_bytes()?)?;
|
||||
}
|
||||
@@ -926,27 +867,28 @@ fn main() -> Result<()> {
|
||||
restore_window(HWND(hwnd));
|
||||
}
|
||||
}
|
||||
SubCommand::ResizeEdge(resize) => {
|
||||
send_message(
|
||||
&*SocketMessage::ResizeWindowEdge(resize.edge, resize.sizing).as_bytes()?,
|
||||
)?;
|
||||
}
|
||||
SubCommand::ResizeAxis(arg) => {
|
||||
send_message(&*SocketMessage::ResizeWindowAxis(arg.axis, arg.sizing).as_bytes()?)?;
|
||||
SubCommand::Resize(resize) => {
|
||||
send_message(&*SocketMessage::ResizeWindow(resize.edge, resize.sizing).as_bytes()?)?;
|
||||
}
|
||||
SubCommand::FocusFollowsMouse(arg) => {
|
||||
let enable = match arg.boolean_state {
|
||||
BooleanState::Enable => true,
|
||||
BooleanState::Disable => false,
|
||||
};
|
||||
|
||||
send_message(
|
||||
&*SocketMessage::FocusFollowsMouse(arg.implementation, arg.boolean_state.into())
|
||||
.as_bytes()?,
|
||||
&*SocketMessage::FocusFollowsMouse(arg.implementation, enable).as_bytes()?,
|
||||
)?;
|
||||
}
|
||||
SubCommand::ReloadConfiguration => {
|
||||
send_message(&*SocketMessage::ReloadConfiguration.as_bytes()?)?;
|
||||
}
|
||||
SubCommand::WatchConfiguration(arg) => {
|
||||
send_message(
|
||||
&*SocketMessage::WatchConfiguration(arg.boolean_state.into()).as_bytes()?,
|
||||
)?;
|
||||
let enable = match arg.boolean_state {
|
||||
BooleanState::Enable => true,
|
||||
BooleanState::Disable => false,
|
||||
};
|
||||
send_message(&*SocketMessage::WatchConfiguration(enable).as_bytes()?)?;
|
||||
}
|
||||
SubCommand::IdentifyTrayApplication(target) => {
|
||||
send_message(
|
||||
@@ -959,22 +901,39 @@ fn main() -> Result<()> {
|
||||
&*SocketMessage::IdentifyBorderOverflow(target.identifier, target.id).as_bytes()?,
|
||||
)?;
|
||||
}
|
||||
SubCommand::RemoveTitleBar(target) => {
|
||||
match target.identifier {
|
||||
ApplicationIdentifier::Exe => {}
|
||||
_ => {
|
||||
return Err(anyhow!(
|
||||
"this command requires applications to be identified by their exe"
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
send_message(
|
||||
&*SocketMessage::RemoveTitleBar(target.identifier, target.id).as_bytes()?,
|
||||
)?;
|
||||
}
|
||||
SubCommand::ToggleTitleBars => {
|
||||
send_message(&*SocketMessage::ToggleTitleBars.as_bytes()?)?;
|
||||
}
|
||||
SubCommand::Manage => {
|
||||
send_message(&*SocketMessage::ManageFocusedWindow.as_bytes()?)?;
|
||||
}
|
||||
SubCommand::Unmanage => {
|
||||
send_message(&*SocketMessage::UnmanageFocusedWindow.as_bytes()?)?;
|
||||
}
|
||||
SubCommand::QuickSaveResize => {
|
||||
SubCommand::QuickSave => {
|
||||
send_message(&*SocketMessage::QuickSave.as_bytes()?)?;
|
||||
}
|
||||
SubCommand::QuickLoadResize => {
|
||||
SubCommand::QuickLoad => {
|
||||
send_message(&*SocketMessage::QuickLoad.as_bytes()?)?;
|
||||
}
|
||||
SubCommand::SaveResize(arg) => {
|
||||
SubCommand::Save(arg) => {
|
||||
send_message(&*SocketMessage::Save(resolve_windows_path(&arg.path)?).as_bytes()?)?;
|
||||
}
|
||||
SubCommand::LoadResize(arg) => {
|
||||
SubCommand::Load(arg) => {
|
||||
send_message(&*SocketMessage::Load(resolve_windows_path(&arg.path)?).as_bytes()?)?;
|
||||
}
|
||||
SubCommand::Subscribe(arg) => {
|
||||
@@ -983,21 +942,6 @@ fn main() -> Result<()> {
|
||||
SubCommand::Unsubscribe(arg) => {
|
||||
send_message(&*SocketMessage::RemoveSubscriber(arg.named_pipe).as_bytes()?)?;
|
||||
}
|
||||
SubCommand::ToggleMouseFollowsFocus => {
|
||||
send_message(&*SocketMessage::ToggleMouseFollowsFocus.as_bytes()?)?;
|
||||
}
|
||||
SubCommand::MouseFollowsFocus(arg) => {
|
||||
send_message(&*SocketMessage::MouseFollowsFocus(arg.boolean_state.into()).as_bytes()?)?;
|
||||
}
|
||||
SubCommand::ResizeDelta(arg) => {
|
||||
send_message(&*SocketMessage::ResizeDelta(arg.pixels).as_bytes()?)?;
|
||||
}
|
||||
SubCommand::ToggleWindowContainerBehaviour => {
|
||||
send_message(&*SocketMessage::ToggleWindowContainerBehaviour.as_bytes()?)?;
|
||||
}
|
||||
SubCommand::WindowHidingBehaviour(arg) => {
|
||||
send_message(&*SocketMessage::WindowHidingBehaviour(arg.hiding_behaviour).as_bytes()?)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -1006,7 +950,7 @@ fn main() -> Result<()> {
|
||||
fn resolve_windows_path(raw_path: &str) -> Result<PathBuf> {
|
||||
let path = if raw_path.starts_with('~') {
|
||||
raw_path.replacen(
|
||||
'~',
|
||||
"~",
|
||||
&dirs::home_dir()
|
||||
.ok_or_else(|| anyhow!("there is no home directory"))?
|
||||
.display()
|
||||
|
||||
Reference in New Issue
Block a user