├── .github ├── FUNDING.yml ├── dependabot.yml ├── pull_request_template.md └── workflows │ └── windows.yaml ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── LICENSE.md ├── README.md ├── justfile ├── rust-toolchain.toml ├── rustfmt.toml ├── src └── main.rs └── wix ├── License.rtf └── main.wxs /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: LGUG2Z 2 | ko_fi: lgug2z 3 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | schedule: 6 | interval: "weekly" 7 | assignees: 8 | - "LGUG2Z" 9 | commit-message: 10 | prefix: chore 11 | include: scope 12 | 13 | - package-ecosystem: "cargo" 14 | directory: "/" 15 | schedule: 16 | interval: "weekly" 17 | assignees: 18 | - "LGUG2Z" 19 | commit-message: 20 | prefix: chore 21 | include: scope 22 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /.github/workflows/windows.yaml: -------------------------------------------------------------------------------- 1 | name: Windows 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - "*" 7 | push: 8 | branches: 9 | - master 10 | - feature/* 11 | - hotfix/* 12 | tags: 13 | - v* 14 | schedule: 15 | - cron: "30 0 * * 0" # Every day at 00:30 UTC 16 | workflow_dispatch: 17 | 18 | jobs: 19 | build: 20 | strategy: 21 | fail-fast: true 22 | matrix: 23 | platform: 24 | - os-name: Windows-x86_64 25 | runs-on: windows-latest 26 | target: x86_64-pc-windows-msvc 27 | - os-name: Windows-aarch64 28 | runs-on: windows-latest 29 | target: aarch64-pc-windows-msvc 30 | runs-on: ${{ matrix.platform.runs-on }} 31 | permissions: write-all 32 | env: 33 | RUSTFLAGS: -Ctarget-feature=+crt-static -Dwarnings 34 | GH_TOKEN: ${{ github.token }} 35 | steps: 36 | - uses: actions/checkout@v4 37 | with: 38 | fetch-depth: 0 39 | - run: rustup toolchain install stable --profile minimal 40 | - run: rustup toolchain install nightly --allow-downgrade -c rustfmt 41 | - uses: Swatinem/rust-cache@v2 42 | with: 43 | cache-on-failure: "true" 44 | cache-all-crates: "true" 45 | key: ${{ matrix.platform.target }} 46 | - run: cargo +nightly fmt --check 47 | - run: cargo clippy 48 | - uses: houseabsolute/actions-rust-cross@v1 49 | with: 50 | command: "build" 51 | target: ${{ matrix.platform.target }} 52 | args: "--locked --release" 53 | - run: | 54 | cargo install cargo-wix 55 | cargo wix --no-build --nocapture --target ${{ matrix.platform.target }} 56 | - uses: actions/upload-artifact@v4 57 | with: 58 | name: masir-${{ matrix.platform.target }}-${{ github.sha }} 59 | path: | 60 | target/${{ matrix.platform.target }}/release/*.exe 61 | target/${{ matrix.platform.target }}/release/*.pdb 62 | target/wix/masir-*.msi 63 | retention-days: 14 64 | 65 | release-dry-run: 66 | needs: build 67 | runs-on: windows-latest 68 | permissions: write-all 69 | if: ${{ github.ref == 'refs/heads/master' }} 70 | steps: 71 | - uses: actions/checkout@v4 72 | with: 73 | fetch-depth: 0 74 | - shell: bash 75 | run: | 76 | TAG=${{ github.ref_name }} 77 | echo "VERSION=${TAG#v}" >> $GITHUB_ENV 78 | - uses: actions/download-artifact@v4 79 | - shell: bash 80 | run: ls -R 81 | - run: | 82 | Compress-Archive -Force ./masir-x86_64-pc-windows-msvc-${{ github.sha }}/x86_64-pc-windows-msvc/release/*.exe masir-$Env:VERSION-x86_64-pc-windows-msvc.zip 83 | Copy-Item ./masir-x86_64-pc-windows-msvc-${{ github.sha }}/wix/*x86_64.msi -Destination ./masir-$Env:VERSION-x86_64.msi 84 | echo "$((Get-FileHash masir-$Env:VERSION-x86_64-pc-windows-msvc.zip).Hash.ToLower()) masir-$Env:VERSION-x86_64-pc-windows-msvc.zip" >checksums.txt 85 | 86 | Compress-Archive -Force ./masir-aarch64-pc-windows-msvc-${{ github.sha }}/aarch64-pc-windows-msvc/release/*.exe masir-$Env:VERSION-aarch64-pc-windows-msvc.zip 87 | Copy-Item ./masir-aarch64-pc-windows-msvc-${{ github.sha }}/wix/*aarch64.msi -Destination ./masir-$Env:VERSION-aarch64.msi 88 | echo "$((Get-FileHash masir-$Env:VERSION-aarch64-pc-windows-msvc.zip).Hash.ToLower()) masir-$Env:VERSION-aarch64-pc-windows-msvc.zip" >>checksums.txt 89 | - uses: Swatinem/rust-cache@v2 90 | with: 91 | cache-on-failure: "true" 92 | cache-all-crates: "true" 93 | - shell: bash 94 | run: | 95 | if ! type kokai >/dev/null; then cargo install --locked kokai --force; fi 96 | git tag -d nightly || true 97 | kokai release --no-emoji --add-links github:commits,issues --ref "${{ github.ref_name }}" >"CHANGELOG.md" 98 | - uses: softprops/action-gh-release@v2 99 | with: 100 | body_path: "CHANGELOG.md" 101 | draft: true 102 | files: | 103 | checksums.txt 104 | *.zip 105 | *.msi 106 | 107 | release: 108 | needs: build 109 | runs-on: windows-latest 110 | permissions: write-all 111 | if: startsWith(github.ref, 'refs/tags/v') 112 | env: 113 | GH_TOKEN: ${{ github.token }} 114 | steps: 115 | - uses: actions/checkout@v4 116 | with: 117 | fetch-depth: 0 118 | - shell: bash 119 | run: | 120 | TAG=${{ github.ref_name }} 121 | echo "VERSION=${TAG#v}" >> $GITHUB_ENV 122 | - uses: actions/download-artifact@v4 123 | - run: | 124 | Compress-Archive -Force ./masir-x86_64-pc-windows-msvc-${{ github.sha }}/x86_64-pc-windows-msvc/release/*.exe masir-$Env:VERSION-x86_64-pc-windows-msvc.zip 125 | Copy-Item ./masir-x86_64-pc-windows-msvc-${{ github.sha }}/wix/*x86_64.msi -Destination ./masir-$Env:VERSION-x86_64.msi 126 | echo "$((Get-FileHash masir-$Env:VERSION-x86_64-pc-windows-msvc.zip).Hash.ToLower()) masir-$Env:VERSION-x86_64-pc-windows-msvc.zip" >checksums.txt 127 | 128 | Compress-Archive -Force ./masir-aarch64-pc-windows-msvc-${{ github.sha }}/aarch64-pc-windows-msvc/release/*.exe masir-$Env:VERSION-aarch64-pc-windows-msvc.zip 129 | Copy-Item ./masir-aarch64-pc-windows-msvc-${{ github.sha }}/wix/*aarch64.msi -Destination ./masir-$Env:VERSION-aarch64.msi 130 | echo "$((Get-FileHash masir-$Env:VERSION-aarch64-pc-windows-msvc.zip).Hash.ToLower()) masir-$Env:VERSION-aarch64-pc-windows-msvc.zip" >>checksums.txt 131 | - uses: Swatinem/rust-cache@v2 132 | with: 133 | cache-on-failure: "true" 134 | cache-all-crates: "true" 135 | - shell: bash 136 | run: | 137 | if ! type kokai >/dev/null; then cargo install --locked kokai --force; fi 138 | git tag -d nightly || true 139 | kokai release --no-emoji --add-links github:commits,issues --ref "$(git tag --points-at HEAD)" >"CHANGELOG.md" 140 | - uses: softprops/action-gh-release@v2 141 | with: 142 | body_path: "CHANGELOG.md" 143 | files: | 144 | checksums.txt 145 | *.zip 146 | *.msi 147 | - if: startsWith(github.ref, 'refs/tags/v') 148 | uses: vedantmgoyal2009/winget-releaser@main 149 | with: 150 | identifier: LGUG2Z.masir 151 | token: ${{ secrets.WINGET_TOKEN }} 152 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "addr2line" 7 | version = "0.21.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" 10 | dependencies = [ 11 | "gimli", 12 | ] 13 | 14 | [[package]] 15 | name = "adler" 16 | version = "1.0.2" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" 19 | 20 | [[package]] 21 | name = "aho-corasick" 22 | version = "1.1.3" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" 25 | dependencies = [ 26 | "memchr", 27 | ] 28 | 29 | [[package]] 30 | name = "anstream" 31 | version = "0.6.18" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" 34 | dependencies = [ 35 | "anstyle", 36 | "anstyle-parse", 37 | "anstyle-query", 38 | "anstyle-wincon", 39 | "colorchoice", 40 | "is_terminal_polyfill", 41 | "utf8parse", 42 | ] 43 | 44 | [[package]] 45 | name = "anstyle" 46 | version = "1.0.10" 47 | source = "registry+https://github.com/rust-lang/crates.io-index" 48 | checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" 49 | 50 | [[package]] 51 | name = "anstyle-parse" 52 | version = "0.2.6" 53 | source = "registry+https://github.com/rust-lang/crates.io-index" 54 | checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" 55 | dependencies = [ 56 | "utf8parse", 57 | ] 58 | 59 | [[package]] 60 | name = "anstyle-query" 61 | version = "1.1.2" 62 | source = "registry+https://github.com/rust-lang/crates.io-index" 63 | checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" 64 | dependencies = [ 65 | "windows-sys", 66 | ] 67 | 68 | [[package]] 69 | name = "anstyle-wincon" 70 | version = "3.0.7" 71 | source = "registry+https://github.com/rust-lang/crates.io-index" 72 | checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" 73 | dependencies = [ 74 | "anstyle", 75 | "once_cell", 76 | "windows-sys", 77 | ] 78 | 79 | [[package]] 80 | name = "backtrace" 81 | version = "0.3.71" 82 | source = "registry+https://github.com/rust-lang/crates.io-index" 83 | checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" 84 | dependencies = [ 85 | "addr2line", 86 | "cc", 87 | "cfg-if", 88 | "libc", 89 | "miniz_oxide", 90 | "object", 91 | "rustc-demangle", 92 | ] 93 | 94 | [[package]] 95 | name = "bitflags" 96 | version = "2.8.0" 97 | source = "registry+https://github.com/rust-lang/crates.io-index" 98 | checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" 99 | 100 | [[package]] 101 | name = "cc" 102 | version = "1.2.9" 103 | source = "registry+https://github.com/rust-lang/crates.io-index" 104 | checksum = "c8293772165d9345bdaaa39b45b2109591e63fe5e6fbc23c6ff930a048aa310b" 105 | dependencies = [ 106 | "shlex", 107 | ] 108 | 109 | [[package]] 110 | name = "cfg-if" 111 | version = "1.0.0" 112 | source = "registry+https://github.com/rust-lang/crates.io-index" 113 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 114 | 115 | [[package]] 116 | name = "cfg_aliases" 117 | version = "0.2.1" 118 | source = "registry+https://github.com/rust-lang/crates.io-index" 119 | checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" 120 | 121 | [[package]] 122 | name = "clap" 123 | version = "4.5.37" 124 | source = "registry+https://github.com/rust-lang/crates.io-index" 125 | checksum = "eccb054f56cbd38340b380d4a8e69ef1f02f1af43db2f0cc817a4774d80ae071" 126 | dependencies = [ 127 | "clap_builder", 128 | "clap_derive", 129 | ] 130 | 131 | [[package]] 132 | name = "clap_builder" 133 | version = "4.5.37" 134 | source = "registry+https://github.com/rust-lang/crates.io-index" 135 | checksum = "efd9466fac8543255d3b1fcad4762c5e116ffe808c8a3043d4263cd4fd4862a2" 136 | dependencies = [ 137 | "anstream", 138 | "anstyle", 139 | "clap_lex", 140 | "strsim", 141 | ] 142 | 143 | [[package]] 144 | name = "clap_derive" 145 | version = "4.5.32" 146 | source = "registry+https://github.com/rust-lang/crates.io-index" 147 | checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" 148 | dependencies = [ 149 | "heck", 150 | "proc-macro2", 151 | "quote", 152 | "syn", 153 | ] 154 | 155 | [[package]] 156 | name = "clap_lex" 157 | version = "0.7.4" 158 | source = "registry+https://github.com/rust-lang/crates.io-index" 159 | checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" 160 | 161 | [[package]] 162 | name = "color-eyre" 163 | version = "0.6.3" 164 | source = "registry+https://github.com/rust-lang/crates.io-index" 165 | checksum = "55146f5e46f237f7423d74111267d4597b59b0dad0ffaf7303bce9945d843ad5" 166 | dependencies = [ 167 | "backtrace", 168 | "color-spantrace", 169 | "eyre", 170 | "indenter", 171 | "once_cell", 172 | "owo-colors", 173 | "tracing-error", 174 | ] 175 | 176 | [[package]] 177 | name = "color-spantrace" 178 | version = "0.2.1" 179 | source = "registry+https://github.com/rust-lang/crates.io-index" 180 | checksum = "cd6be1b2a7e382e2b98b43b2adcca6bb0e465af0bdd38123873ae61eb17a72c2" 181 | dependencies = [ 182 | "once_cell", 183 | "owo-colors", 184 | "tracing-core", 185 | "tracing-error", 186 | ] 187 | 188 | [[package]] 189 | name = "colorchoice" 190 | version = "1.0.3" 191 | source = "registry+https://github.com/rust-lang/crates.io-index" 192 | checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" 193 | 194 | [[package]] 195 | name = "ctrlc" 196 | version = "3.4.6" 197 | source = "registry+https://github.com/rust-lang/crates.io-index" 198 | checksum = "697b5419f348fd5ae2478e8018cb016c00a5881c7f46c717de98ffd135a5651c" 199 | dependencies = [ 200 | "nix", 201 | "windows-sys", 202 | ] 203 | 204 | [[package]] 205 | name = "dirs" 206 | version = "6.0.0" 207 | source = "registry+https://github.com/rust-lang/crates.io-index" 208 | checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" 209 | dependencies = [ 210 | "dirs-sys", 211 | ] 212 | 213 | [[package]] 214 | name = "dirs-sys" 215 | version = "0.5.0" 216 | source = "registry+https://github.com/rust-lang/crates.io-index" 217 | checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" 218 | dependencies = [ 219 | "libc", 220 | "option-ext", 221 | "redox_users", 222 | "windows-sys", 223 | ] 224 | 225 | [[package]] 226 | name = "eyre" 227 | version = "0.6.12" 228 | source = "registry+https://github.com/rust-lang/crates.io-index" 229 | checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" 230 | dependencies = [ 231 | "indenter", 232 | "once_cell", 233 | ] 234 | 235 | [[package]] 236 | name = "getrandom" 237 | version = "0.2.15" 238 | source = "registry+https://github.com/rust-lang/crates.io-index" 239 | checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" 240 | dependencies = [ 241 | "cfg-if", 242 | "libc", 243 | "wasi", 244 | ] 245 | 246 | [[package]] 247 | name = "gimli" 248 | version = "0.28.1" 249 | source = "registry+https://github.com/rust-lang/crates.io-index" 250 | checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" 251 | 252 | [[package]] 253 | name = "heck" 254 | version = "0.5.0" 255 | source = "registry+https://github.com/rust-lang/crates.io-index" 256 | checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" 257 | 258 | [[package]] 259 | name = "indenter" 260 | version = "0.3.3" 261 | source = "registry+https://github.com/rust-lang/crates.io-index" 262 | checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" 263 | 264 | [[package]] 265 | name = "is_terminal_polyfill" 266 | version = "1.70.1" 267 | source = "registry+https://github.com/rust-lang/crates.io-index" 268 | checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" 269 | 270 | [[package]] 271 | name = "lazy_static" 272 | version = "1.5.0" 273 | source = "registry+https://github.com/rust-lang/crates.io-index" 274 | checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" 275 | 276 | [[package]] 277 | name = "libc" 278 | version = "0.2.169" 279 | source = "registry+https://github.com/rust-lang/crates.io-index" 280 | checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" 281 | 282 | [[package]] 283 | name = "libredox" 284 | version = "0.1.3" 285 | source = "registry+https://github.com/rust-lang/crates.io-index" 286 | checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" 287 | dependencies = [ 288 | "bitflags", 289 | "libc", 290 | ] 291 | 292 | [[package]] 293 | name = "log" 294 | version = "0.4.25" 295 | source = "registry+https://github.com/rust-lang/crates.io-index" 296 | checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" 297 | 298 | [[package]] 299 | name = "masir" 300 | version = "0.1.2" 301 | dependencies = [ 302 | "clap", 303 | "color-eyre", 304 | "ctrlc", 305 | "dirs", 306 | "paste", 307 | "tracing", 308 | "tracing-subscriber", 309 | "windows", 310 | "windows-core", 311 | "winput", 312 | ] 313 | 314 | [[package]] 315 | name = "matchers" 316 | version = "0.1.0" 317 | source = "registry+https://github.com/rust-lang/crates.io-index" 318 | checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" 319 | dependencies = [ 320 | "regex-automata 0.1.10", 321 | ] 322 | 323 | [[package]] 324 | name = "memchr" 325 | version = "2.7.4" 326 | source = "registry+https://github.com/rust-lang/crates.io-index" 327 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 328 | 329 | [[package]] 330 | name = "miniz_oxide" 331 | version = "0.7.4" 332 | source = "registry+https://github.com/rust-lang/crates.io-index" 333 | checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" 334 | dependencies = [ 335 | "adler", 336 | ] 337 | 338 | [[package]] 339 | name = "nix" 340 | version = "0.29.0" 341 | source = "registry+https://github.com/rust-lang/crates.io-index" 342 | checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" 343 | dependencies = [ 344 | "bitflags", 345 | "cfg-if", 346 | "cfg_aliases", 347 | "libc", 348 | ] 349 | 350 | [[package]] 351 | name = "nu-ansi-term" 352 | version = "0.46.0" 353 | source = "registry+https://github.com/rust-lang/crates.io-index" 354 | checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" 355 | dependencies = [ 356 | "overload", 357 | "winapi", 358 | ] 359 | 360 | [[package]] 361 | name = "object" 362 | version = "0.32.2" 363 | source = "registry+https://github.com/rust-lang/crates.io-index" 364 | checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" 365 | dependencies = [ 366 | "memchr", 367 | ] 368 | 369 | [[package]] 370 | name = "once_cell" 371 | version = "1.20.2" 372 | source = "registry+https://github.com/rust-lang/crates.io-index" 373 | checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" 374 | 375 | [[package]] 376 | name = "option-ext" 377 | version = "0.2.0" 378 | source = "registry+https://github.com/rust-lang/crates.io-index" 379 | checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" 380 | 381 | [[package]] 382 | name = "overload" 383 | version = "0.1.1" 384 | source = "registry+https://github.com/rust-lang/crates.io-index" 385 | checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" 386 | 387 | [[package]] 388 | name = "owo-colors" 389 | version = "3.5.0" 390 | source = "registry+https://github.com/rust-lang/crates.io-index" 391 | checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" 392 | 393 | [[package]] 394 | name = "paste" 395 | version = "1.0.15" 396 | source = "registry+https://github.com/rust-lang/crates.io-index" 397 | checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" 398 | 399 | [[package]] 400 | name = "pin-project-lite" 401 | version = "0.2.16" 402 | source = "registry+https://github.com/rust-lang/crates.io-index" 403 | checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" 404 | 405 | [[package]] 406 | name = "proc-macro2" 407 | version = "1.0.93" 408 | source = "registry+https://github.com/rust-lang/crates.io-index" 409 | checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" 410 | dependencies = [ 411 | "unicode-ident", 412 | ] 413 | 414 | [[package]] 415 | name = "quote" 416 | version = "1.0.38" 417 | source = "registry+https://github.com/rust-lang/crates.io-index" 418 | checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" 419 | dependencies = [ 420 | "proc-macro2", 421 | ] 422 | 423 | [[package]] 424 | name = "redox_users" 425 | version = "0.5.0" 426 | source = "registry+https://github.com/rust-lang/crates.io-index" 427 | checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" 428 | dependencies = [ 429 | "getrandom", 430 | "libredox", 431 | "thiserror", 432 | ] 433 | 434 | [[package]] 435 | name = "regex" 436 | version = "1.11.1" 437 | source = "registry+https://github.com/rust-lang/crates.io-index" 438 | checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" 439 | dependencies = [ 440 | "aho-corasick", 441 | "memchr", 442 | "regex-automata 0.4.9", 443 | "regex-syntax 0.8.5", 444 | ] 445 | 446 | [[package]] 447 | name = "regex-automata" 448 | version = "0.1.10" 449 | source = "registry+https://github.com/rust-lang/crates.io-index" 450 | checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" 451 | dependencies = [ 452 | "regex-syntax 0.6.29", 453 | ] 454 | 455 | [[package]] 456 | name = "regex-automata" 457 | version = "0.4.9" 458 | source = "registry+https://github.com/rust-lang/crates.io-index" 459 | checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" 460 | dependencies = [ 461 | "aho-corasick", 462 | "memchr", 463 | "regex-syntax 0.8.5", 464 | ] 465 | 466 | [[package]] 467 | name = "regex-syntax" 468 | version = "0.6.29" 469 | source = "registry+https://github.com/rust-lang/crates.io-index" 470 | checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" 471 | 472 | [[package]] 473 | name = "regex-syntax" 474 | version = "0.8.5" 475 | source = "registry+https://github.com/rust-lang/crates.io-index" 476 | checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" 477 | 478 | [[package]] 479 | name = "rustc-demangle" 480 | version = "0.1.24" 481 | source = "registry+https://github.com/rust-lang/crates.io-index" 482 | checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" 483 | 484 | [[package]] 485 | name = "sharded-slab" 486 | version = "0.1.7" 487 | source = "registry+https://github.com/rust-lang/crates.io-index" 488 | checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" 489 | dependencies = [ 490 | "lazy_static", 491 | ] 492 | 493 | [[package]] 494 | name = "shlex" 495 | version = "1.3.0" 496 | source = "registry+https://github.com/rust-lang/crates.io-index" 497 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 498 | 499 | [[package]] 500 | name = "smallvec" 501 | version = "1.13.2" 502 | source = "registry+https://github.com/rust-lang/crates.io-index" 503 | checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" 504 | 505 | [[package]] 506 | name = "strsim" 507 | version = "0.11.1" 508 | source = "registry+https://github.com/rust-lang/crates.io-index" 509 | checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" 510 | 511 | [[package]] 512 | name = "syn" 513 | version = "2.0.96" 514 | source = "registry+https://github.com/rust-lang/crates.io-index" 515 | checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" 516 | dependencies = [ 517 | "proc-macro2", 518 | "quote", 519 | "unicode-ident", 520 | ] 521 | 522 | [[package]] 523 | name = "thiserror" 524 | version = "2.0.11" 525 | source = "registry+https://github.com/rust-lang/crates.io-index" 526 | checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" 527 | dependencies = [ 528 | "thiserror-impl", 529 | ] 530 | 531 | [[package]] 532 | name = "thiserror-impl" 533 | version = "2.0.11" 534 | source = "registry+https://github.com/rust-lang/crates.io-index" 535 | checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" 536 | dependencies = [ 537 | "proc-macro2", 538 | "quote", 539 | "syn", 540 | ] 541 | 542 | [[package]] 543 | name = "thread_local" 544 | version = "1.1.8" 545 | source = "registry+https://github.com/rust-lang/crates.io-index" 546 | checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" 547 | dependencies = [ 548 | "cfg-if", 549 | "once_cell", 550 | ] 551 | 552 | [[package]] 553 | name = "tracing" 554 | version = "0.1.41" 555 | source = "registry+https://github.com/rust-lang/crates.io-index" 556 | checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" 557 | dependencies = [ 558 | "pin-project-lite", 559 | "tracing-attributes", 560 | "tracing-core", 561 | ] 562 | 563 | [[package]] 564 | name = "tracing-attributes" 565 | version = "0.1.28" 566 | source = "registry+https://github.com/rust-lang/crates.io-index" 567 | checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" 568 | dependencies = [ 569 | "proc-macro2", 570 | "quote", 571 | "syn", 572 | ] 573 | 574 | [[package]] 575 | name = "tracing-core" 576 | version = "0.1.33" 577 | source = "registry+https://github.com/rust-lang/crates.io-index" 578 | checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" 579 | dependencies = [ 580 | "once_cell", 581 | "valuable", 582 | ] 583 | 584 | [[package]] 585 | name = "tracing-error" 586 | version = "0.2.1" 587 | source = "registry+https://github.com/rust-lang/crates.io-index" 588 | checksum = "8b1581020d7a273442f5b45074a6a57d5757ad0a47dac0e9f0bd57b81936f3db" 589 | dependencies = [ 590 | "tracing", 591 | "tracing-subscriber", 592 | ] 593 | 594 | [[package]] 595 | name = "tracing-log" 596 | version = "0.2.0" 597 | source = "registry+https://github.com/rust-lang/crates.io-index" 598 | checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" 599 | dependencies = [ 600 | "log", 601 | "once_cell", 602 | "tracing-core", 603 | ] 604 | 605 | [[package]] 606 | name = "tracing-subscriber" 607 | version = "0.3.19" 608 | source = "registry+https://github.com/rust-lang/crates.io-index" 609 | checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" 610 | dependencies = [ 611 | "matchers", 612 | "nu-ansi-term", 613 | "once_cell", 614 | "regex", 615 | "sharded-slab", 616 | "smallvec", 617 | "thread_local", 618 | "tracing", 619 | "tracing-core", 620 | "tracing-log", 621 | ] 622 | 623 | [[package]] 624 | name = "unicode-ident" 625 | version = "1.0.14" 626 | source = "registry+https://github.com/rust-lang/crates.io-index" 627 | checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" 628 | 629 | [[package]] 630 | name = "utf8parse" 631 | version = "0.2.2" 632 | source = "registry+https://github.com/rust-lang/crates.io-index" 633 | checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" 634 | 635 | [[package]] 636 | name = "valuable" 637 | version = "0.1.0" 638 | source = "registry+https://github.com/rust-lang/crates.io-index" 639 | checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" 640 | 641 | [[package]] 642 | name = "wasi" 643 | version = "0.11.0+wasi-snapshot-preview1" 644 | source = "registry+https://github.com/rust-lang/crates.io-index" 645 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 646 | 647 | [[package]] 648 | name = "winapi" 649 | version = "0.3.9" 650 | source = "registry+https://github.com/rust-lang/crates.io-index" 651 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 652 | dependencies = [ 653 | "winapi-i686-pc-windows-gnu", 654 | "winapi-x86_64-pc-windows-gnu", 655 | ] 656 | 657 | [[package]] 658 | name = "winapi-i686-pc-windows-gnu" 659 | version = "0.4.0" 660 | source = "registry+https://github.com/rust-lang/crates.io-index" 661 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 662 | 663 | [[package]] 664 | name = "winapi-x86_64-pc-windows-gnu" 665 | version = "0.4.0" 666 | source = "registry+https://github.com/rust-lang/crates.io-index" 667 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 668 | 669 | [[package]] 670 | name = "windows" 671 | version = "0.60.0" 672 | source = "registry+https://github.com/rust-lang/crates.io-index" 673 | checksum = "ddf874e74c7a99773e62b1c671427abf01a425e77c3d3fb9fb1e4883ea934529" 674 | dependencies = [ 675 | "windows-collections", 676 | "windows-core", 677 | "windows-future", 678 | "windows-link", 679 | "windows-numerics", 680 | ] 681 | 682 | [[package]] 683 | name = "windows-collections" 684 | version = "0.1.1" 685 | source = "registry+https://github.com/rust-lang/crates.io-index" 686 | checksum = "5467f79cc1ba3f52ebb2ed41dbb459b8e7db636cc3429458d9a852e15bc24dec" 687 | dependencies = [ 688 | "windows-core", 689 | ] 690 | 691 | [[package]] 692 | name = "windows-core" 693 | version = "0.60.1" 694 | source = "registry+https://github.com/rust-lang/crates.io-index" 695 | checksum = "ca21a92a9cae9bf4ccae5cf8368dce0837100ddf6e6d57936749e85f152f6247" 696 | dependencies = [ 697 | "windows-implement", 698 | "windows-interface", 699 | "windows-link", 700 | "windows-result", 701 | "windows-strings", 702 | ] 703 | 704 | [[package]] 705 | name = "windows-future" 706 | version = "0.1.1" 707 | source = "registry+https://github.com/rust-lang/crates.io-index" 708 | checksum = "a787db4595e7eb80239b74ce8babfb1363d8e343ab072f2ffe901400c03349f0" 709 | dependencies = [ 710 | "windows-core", 711 | "windows-link", 712 | ] 713 | 714 | [[package]] 715 | name = "windows-implement" 716 | version = "0.59.0" 717 | source = "registry+https://github.com/rust-lang/crates.io-index" 718 | checksum = "83577b051e2f49a058c308f17f273b570a6a758386fc291b5f6a934dd84e48c1" 719 | dependencies = [ 720 | "proc-macro2", 721 | "quote", 722 | "syn", 723 | ] 724 | 725 | [[package]] 726 | name = "windows-interface" 727 | version = "0.59.0" 728 | source = "registry+https://github.com/rust-lang/crates.io-index" 729 | checksum = "cb26fd936d991781ea39e87c3a27285081e3c0da5ca0fcbc02d368cc6f52ff01" 730 | dependencies = [ 731 | "proc-macro2", 732 | "quote", 733 | "syn", 734 | ] 735 | 736 | [[package]] 737 | name = "windows-link" 738 | version = "0.1.0" 739 | source = "registry+https://github.com/rust-lang/crates.io-index" 740 | checksum = "6dccfd733ce2b1753b03b6d3c65edf020262ea35e20ccdf3e288043e6dd620e3" 741 | 742 | [[package]] 743 | name = "windows-numerics" 744 | version = "0.1.1" 745 | source = "registry+https://github.com/rust-lang/crates.io-index" 746 | checksum = "005dea54e2f6499f2cee279b8f703b3cf3b5734a2d8d21867c8f44003182eeed" 747 | dependencies = [ 748 | "windows-core", 749 | "windows-link", 750 | ] 751 | 752 | [[package]] 753 | name = "windows-result" 754 | version = "0.3.1" 755 | source = "registry+https://github.com/rust-lang/crates.io-index" 756 | checksum = "06374efe858fab7e4f881500e6e86ec8bc28f9462c47e5a9941a0142ad86b189" 757 | dependencies = [ 758 | "windows-link", 759 | ] 760 | 761 | [[package]] 762 | name = "windows-strings" 763 | version = "0.3.1" 764 | source = "registry+https://github.com/rust-lang/crates.io-index" 765 | checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" 766 | dependencies = [ 767 | "windows-link", 768 | ] 769 | 770 | [[package]] 771 | name = "windows-sys" 772 | version = "0.59.0" 773 | source = "registry+https://github.com/rust-lang/crates.io-index" 774 | checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" 775 | dependencies = [ 776 | "windows-targets", 777 | ] 778 | 779 | [[package]] 780 | name = "windows-targets" 781 | version = "0.52.6" 782 | source = "registry+https://github.com/rust-lang/crates.io-index" 783 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 784 | dependencies = [ 785 | "windows_aarch64_gnullvm", 786 | "windows_aarch64_msvc", 787 | "windows_i686_gnu", 788 | "windows_i686_gnullvm", 789 | "windows_i686_msvc", 790 | "windows_x86_64_gnu", 791 | "windows_x86_64_gnullvm", 792 | "windows_x86_64_msvc", 793 | ] 794 | 795 | [[package]] 796 | name = "windows_aarch64_gnullvm" 797 | version = "0.52.6" 798 | source = "registry+https://github.com/rust-lang/crates.io-index" 799 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 800 | 801 | [[package]] 802 | name = "windows_aarch64_msvc" 803 | version = "0.52.6" 804 | source = "registry+https://github.com/rust-lang/crates.io-index" 805 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 806 | 807 | [[package]] 808 | name = "windows_i686_gnu" 809 | version = "0.52.6" 810 | source = "registry+https://github.com/rust-lang/crates.io-index" 811 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 812 | 813 | [[package]] 814 | name = "windows_i686_gnullvm" 815 | version = "0.52.6" 816 | source = "registry+https://github.com/rust-lang/crates.io-index" 817 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 818 | 819 | [[package]] 820 | name = "windows_i686_msvc" 821 | version = "0.52.6" 822 | source = "registry+https://github.com/rust-lang/crates.io-index" 823 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 824 | 825 | [[package]] 826 | name = "windows_x86_64_gnu" 827 | version = "0.52.6" 828 | source = "registry+https://github.com/rust-lang/crates.io-index" 829 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 830 | 831 | [[package]] 832 | name = "windows_x86_64_gnullvm" 833 | version = "0.52.6" 834 | source = "registry+https://github.com/rust-lang/crates.io-index" 835 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 836 | 837 | [[package]] 838 | name = "windows_x86_64_msvc" 839 | version = "0.52.6" 840 | source = "registry+https://github.com/rust-lang/crates.io-index" 841 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 842 | 843 | [[package]] 844 | name = "winput" 845 | version = "0.2.5" 846 | source = "registry+https://github.com/rust-lang/crates.io-index" 847 | checksum = "dd4bec39938e0ae68b300e2a4197b6437f13d53d1c146c6e297e346a71d5dde9" 848 | dependencies = [ 849 | "winapi", 850 | ] 851 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "masir" 3 | authors = ["LGUG2Z"] 4 | version = "0.1.2" 5 | edition = "2021" 6 | license-file = "LICENSE.md" 7 | 8 | [dependencies] 9 | winput = "0.2" 10 | color-eyre = "0.6" 11 | paste = "1" 12 | ctrlc = "3" 13 | tracing = "0.1" 14 | tracing-subscriber = { version = "0.3", features = ["env-filter"] } 15 | windows-core = "0.60" 16 | dirs = "6" 17 | clap = { version = "4", features = ["derive"] } 18 | 19 | [dependencies.windows] 20 | version = "0.60" 21 | features = [ 22 | "Win32_UI_WindowsAndMessaging", 23 | "Win32_UI_Input", 24 | "Win32_UI_Input_KeyboardAndMouse", 25 | ] 26 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # Komorebi License 2 | 3 | Version 2.0.0 4 | 5 | ## Acceptance 6 | 7 | In order to get any license under these terms, you must agree 8 | to them as both strict obligations and conditions to all 9 | your licenses. 10 | 11 | ## Copyright License 12 | 13 | The licensor grants you a copyright license for the software 14 | to do everything you might do with the software that would 15 | otherwise infringe the licensor's copyright in it for any 16 | permitted purpose. However, you may only distribute the source 17 | code of the software according to the [Distribution License]( 18 | #distribution-license), you may only make changes according 19 | to the [Changes License](#changes-license), and you may not 20 | otherwise distribute the software or new works based on the 21 | software. 22 | 23 | ## Distribution License 24 | 25 | The licensor grants you an additional copyright license to 26 | distribute copies of the source code of the software. Your 27 | license to distribute covers distributing the source code of 28 | the software with changes permitted by the [Changes License]( 29 | #changes-license). 30 | 31 | ## Changes License 32 | 33 | The licensor grants you an additional copyright license to 34 | make changes for any permitted purpose. 35 | 36 | ## Patent License 37 | 38 | The licensor grants you a patent license for the software that 39 | covers patent claims the licensor can license, or becomes able 40 | to license, that you would infringe by using the software. 41 | 42 | ## Personal Uses 43 | 44 | Personal use for research, experiment, and testing for 45 | the benefit of public knowledge, personal study, private 46 | entertainment, hobby projects, amateur pursuits, or religious 47 | observance, without any anticipated commercial application, 48 | is use for a permitted purpose. 49 | 50 | ## Fair Use 51 | 52 | You may have "fair use" rights for the software under the 53 | law. These terms do not limit them. 54 | 55 | ## No Other Rights 56 | 57 | These terms do not allow you to sublicense or transfer any of 58 | your licenses to anyone else, or prevent the licensor from 59 | granting licenses to anyone else. These terms do not imply 60 | any other licenses. 61 | 62 | ## Patent Defense 63 | 64 | If you make any written claim that the software infringes or 65 | contributes to infringement of any patent, your patent license 66 | for the software granted under these terms ends immediately. If 67 | your company makes such a claim, your patent license ends 68 | immediately for work on behalf of your company. 69 | 70 | ## Violations 71 | 72 | The first time you are notified in writing that you have 73 | violated any of these terms, or done anything with the software 74 | not covered by your licenses, your licenses can nonetheless 75 | continue if you come into full compliance with these terms, 76 | and take practical steps to correct past violations, within 77 | 32 days of receiving notice. Otherwise, all your licenses 78 | end immediately. 79 | 80 | ## No Liability 81 | 82 | ***As far as the law allows, the software comes as is, without 83 | any warranty or condition, and the licensor will not be liable 84 | to you for any damages arising out of these terms or the use 85 | or nature of the software, under any kind of legal claim.*** 86 | 87 | ## Definitions 88 | 89 | The **licensor** is the individual or entity offering these 90 | terms, and the **software** is the software the licensor makes 91 | available under these terms. 92 | 93 | **You** refers to the individual or entity agreeing to these 94 | terms. 95 | 96 | **Your company** is any legal entity, sole proprietorship, 97 | or other kind of organization that you work for, plus all 98 | organizations that have control over, are under the control of, 99 | or are under common control with that organization. **Control** 100 | means ownership of substantially all the assets of an entity, 101 | or the power to direct its management and policies by vote, 102 | contract, or otherwise. Control can be direct or indirect. 103 | 104 | **Your licenses** are all the licenses granted to you for the 105 | software under these terms. 106 | 107 | **Use** means anything you do with the software requiring one 108 | of your licenses. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # masir 2 | 3 | Focus Follows Mouse for Windows. 4 | 5 |

6 | 7 | Tech for Palestine 8 | 9 | GitHub Workflow Status 10 | GitHub all releases 11 | GitHub commits since latest release (by date) for a branch 12 | 13 | Discord 14 | 15 | 16 | GitHub Sponsors 17 | 18 | 19 | Ko-fi 20 | 21 | 22 | Notado Feed 23 | 24 | 25 | YouTube 26 | 27 |

28 | 29 | _masir_ is a focus follows mouse daemon for Microsoft Windows 11 and above. 30 | 31 | _masir_ allows you to focus an application window by moving your mouse over it, without requiring mouse clicks or 32 | touchpad taps. 33 | 34 | _masir_ does not have a dependency on any specific external software or tiling window manager. 35 | 36 | _masir_ has an additional integration with [komorebi](https://github.com/LGUG2Z/komorebi) to ensure that only windows 37 | managed by the tiling window manager are eligible to be focused. Integrations with other tiling window managers are 38 | welcome (["Integrations"](#integrations).) 39 | 40 | _masir_ is a free and educational source project, and one that encourages you to make charitable donations if you find 41 | the software to be useful and have the financial means. 42 | 43 | I encourage you to make a charitable donation to 44 | the [Palestine Children's Relief Fund](https://pcrf1.app.neoncrm.com/forms/gaza-recovery) or contributing to 45 | a [Gaza Funds campaign](https://gazafunds.com) before you consider sponsoring me on GitHub. 46 | 47 | [GitHub Sponsors is enabled for this project](https://github.com/sponsors/LGUG2Z). Unfortunately I don't have anything 48 | specific to offer besides my gratitude and shout outs at the end of _komorebi_ live development videos and tutorials. 49 | 50 | If you would like to tip or sponsor the project but are unable to use GitHub Sponsors, you may also sponsor 51 | through [Ko-fi](https://ko-fi.com/lgug2z). 52 | 53 | # Installation 54 | 55 | ```powershell 56 | winget install LGUG2Z.masir 57 | ``` 58 | 59 | `masir` can be run as a standalone process, or launched alongside `komorebi` 60 | using the `komorebic start` command with the `--masir` flag. 61 | 62 | # Contribution Guidelines 63 | 64 | If you would like to contribute to `masir` please take the time to carefully read the guidelines below. 65 | 66 | ## Commit hygiene 67 | 68 | - Flatten all `use` statements 69 | - Run `cargo +stable clippy` and ensure that all lints and suggestions have been addressed before committing 70 | - Run `cargo +nightly fmt --all` to ensure consistent formatting before committing 71 | - Use `git cz` with 72 | the [Commitizen CLI](https://github.com/commitizen/cz-cli#conventional-commit-messages-as-a-global-utility) to prepare 73 | commit messages 74 | - Provide **at least** one short sentence or paragraph in your commit message body to describe your thought process for the 75 | changes being committed 76 | 77 | ## License 78 | 79 | `masir` is licensed under the [Komorebi 2.0.0 license](./LICENSE.md), which 80 | is a fork of the [PolyForm Strict 1.0.0 81 | license](https://polyformproject.org/licenses/strict/1.0.0). On a high level 82 | this means that you are free to do whatever you want with `masir` for 83 | personal use other than redistribution, or distribution of new works (i.e. 84 | hard-forks) based on the software. 85 | 86 | Anyone is free to make their own fork of `masir` with changes intended 87 | either for personal use or for integration back upstream via pull requests. 88 | 89 | The [Komorebi 2.0.0 License](./LICENSE.md) does not permit any kind of 90 | commercial use. 91 | 92 | ### Contribution licensing 93 | 94 | Contributions are accepted with the following understanding: 95 | 96 | - Contributed content is licensed under the terms of the 0-BSD license 97 | - Contributors accept the terms of the project license at the time of contribution 98 | 99 | By making a contribution, you accept both the current project license terms, and that all contributions that you have 100 | made are provided under the terms of the 0-BSD license. 101 | 102 | #### Zero-Clause BSD 103 | 104 | ``` 105 | Permission to use, copy, modify, and/or distribute this software for 106 | any purpose with or without fee is hereby granted. 107 | 108 | THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL 109 | WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 110 | OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE 111 | FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY 112 | DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 113 | AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 114 | OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 115 | ``` 116 | 117 | # Integrations 118 | 119 | If you would like to create an integration between _masir_ and a tiling window manager, there is only one requirement: 120 | 121 | - An updated list of window HWNDs known to and managed by the tiling window manager written to a file in a known 122 | location. 123 | 124 | The path to this file of HWNDs can be passed with the `--hwnds` flag for testing purposes. 125 | 126 | _masir_ will check for the presence of the HWND under the mouse cursor in this file when deciding if the window is 127 | eligible to be focused. 128 | 129 | Once testing is complete, native support for checking this file without requiring the `--hwnds` argument can be added 130 | directly to `masir` (see `TODO: We can add checks for other window managers here` 131 | in [`main.rs`](https://github.com/LGUG2Z/masir/blob/a35754a4a29538323bf248b4491f726e366f68bd/src/main.rs#L53)). 132 | -------------------------------------------------------------------------------- /justfile: -------------------------------------------------------------------------------- 1 | set windows-shell := ["pwsh.exe", "-NoLogo", "-Command"] 2 | export RUST_BACKTRACE := "full" 3 | 4 | clean: 5 | cargo clean 6 | 7 | fmt: 8 | cargo +nightly fmt 9 | cargo +stable clippy 10 | prettier -w .github/ 11 | prettier -w README.md 12 | 13 | install: 14 | cargo +stable install --path . --locked 15 | 16 | run: 17 | cargo run --locked 18 | 19 | info $RUST_LOG="info": 20 | just run 21 | 22 | warn $RUST_LOG="warn": 23 | just run 24 | 25 | debug $RUST_LOG="debug": 26 | just run 27 | 28 | trace $RUST_LOG="trace": 29 | just run 30 | -------------------------------------------------------------------------------- /rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "stable" -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | imports_granularity = "Item" -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use clap::Parser; 2 | use color_eyre::Result; 3 | use std::collections::HashMap; 4 | use std::path::PathBuf; 5 | use std::time::Duration; 6 | use std::time::Instant; 7 | use windows::core::Result as WindowsCrateResult; 8 | use windows::Win32::Foundation::HWND; 9 | use windows::Win32::Foundation::POINT; 10 | use windows::Win32::UI::Input::KeyboardAndMouse::SendInput; 11 | use windows::Win32::UI::Input::KeyboardAndMouse::INPUT; 12 | use windows::Win32::UI::Input::KeyboardAndMouse::INPUT_MOUSE; 13 | use windows::Win32::UI::WindowsAndMessaging::GetAncestor; 14 | use windows::Win32::UI::WindowsAndMessaging::GetCursorPos; 15 | use windows::Win32::UI::WindowsAndMessaging::GetForegroundWindow; 16 | use windows::Win32::UI::WindowsAndMessaging::GetWindowLongW; 17 | use windows::Win32::UI::WindowsAndMessaging::RealGetWindowClassW; 18 | use windows::Win32::UI::WindowsAndMessaging::SetForegroundWindow; 19 | use windows::Win32::UI::WindowsAndMessaging::WindowFromPoint; 20 | use windows::Win32::UI::WindowsAndMessaging::GA_ROOT; 21 | use windows::Win32::UI::WindowsAndMessaging::GET_ANCESTOR_FLAGS; 22 | use windows::Win32::UI::WindowsAndMessaging::GWL_EXSTYLE; 23 | use windows::Win32::UI::WindowsAndMessaging::WINDOW_EX_STYLE; 24 | use windows::Win32::UI::WindowsAndMessaging::WS_EX_NOACTIVATE; 25 | use windows::Win32::UI::WindowsAndMessaging::WS_EX_TOOLWINDOW; 26 | use winput::message_loop; 27 | use winput::message_loop::Event; 28 | use winput::Action; 29 | 30 | const CLASS_IGNORELIST: [(&str, MatchingStrategy); 9] = [ 31 | ("SHELLDLL_DefView", MatchingStrategy::Equals), // desktop window 32 | ("Shell_TrayWnd", MatchingStrategy::Equals), // tray 33 | ("TrayNotifyWnd", MatchingStrategy::Equals), // tray 34 | ("MSTaskSwWClass", MatchingStrategy::Equals), // start bar icons 35 | ("Windows.UI.Core.CoreWindow", MatchingStrategy::Equals), // start menu 36 | ("XamlExplorerHostIslandWindow", MatchingStrategy::Equals), // task switcher 37 | ("ForegroundStaging", MatchingStrategy::Equals), // also task switcher 38 | ("Flow.Launcher", MatchingStrategy::Contains), 39 | ("PowerToys.PowerLauncher", MatchingStrategy::Contains), 40 | ]; 41 | 42 | #[derive(Debug, PartialEq, Eq)] 43 | enum MatchingStrategy { 44 | Contains, 45 | Equals, 46 | } 47 | 48 | #[derive(Parser)] 49 | #[clap(author, about, version)] 50 | struct Opts { 51 | /// Disable automatic integrations with tiling window managers (e.g. komorebi) 52 | #[clap(long)] 53 | disable_integrations: bool, 54 | /// Path to a file with known focus-able HWNDs (e.g. komorebi.hwnd.json) 55 | #[clap(long)] 56 | hwnds: Option, 57 | } 58 | 59 | fn main() -> Result<()> { 60 | let opts: Opts = Opts::parse(); 61 | 62 | let hwnds = match opts.hwnds { 63 | None if opts.disable_integrations => None, 64 | None => { 65 | let hwnds: PathBuf = dirs::data_local_dir() 66 | .expect("there is no local data directory") 67 | .join("komorebi") 68 | .join("komorebi.hwnd.json"); 69 | 70 | // TODO: We can add checks for other window managers here 71 | 72 | if hwnds.is_file() { 73 | Some(hwnds) 74 | } else { 75 | None 76 | } 77 | } 78 | Some(hwnds) => { 79 | if hwnds.is_file() { 80 | Some(hwnds) 81 | } else { 82 | None 83 | } 84 | } 85 | }; 86 | 87 | if std::env::var("RUST_LIB_BACKTRACE").is_err() { 88 | std::env::set_var("RUST_LIB_BACKTRACE", "1"); 89 | } 90 | 91 | color_eyre::install()?; 92 | 93 | if std::env::var("RUST_LOG").is_err() { 94 | std::env::set_var("RUST_LOG", "info"); 95 | } 96 | 97 | tracing::subscriber::set_global_default( 98 | tracing_subscriber::fmt::Subscriber::builder() 99 | .with_env_filter(tracing_subscriber::EnvFilter::from_default_env()) 100 | .finish(), 101 | )?; 102 | 103 | listen_for_movements(hwnds.clone()); 104 | 105 | match hwnds { 106 | None => tracing::info!("masir is now running"), 107 | Some(hwnds) => tracing::info!( 108 | "masir is now running, and additionally checking hwnds against {}", 109 | hwnds.display() 110 | ), 111 | } 112 | 113 | let (ctrlc_sender, ctrlc_receiver) = std::sync::mpsc::channel(); 114 | ctrlc::set_handler(move || { 115 | ctrlc_sender 116 | .send(()) 117 | .expect("could not send signal on ctrl-c channel"); 118 | })?; 119 | 120 | ctrlc_receiver 121 | .recv() 122 | .expect("could not receive signal on ctrl-c channel"); 123 | 124 | tracing::info!("received ctrl-c, exiting"); 125 | 126 | Ok(()) 127 | } 128 | 129 | fn listen_for_movements(hwnds: Option) { 130 | std::thread::spawn(move || { 131 | let receiver = message_loop::start().expect("could not start winput message loop"); 132 | 133 | let mut eligibility_cache = HashMap::new(); 134 | let mut class_cache: HashMap = HashMap::new(); 135 | let mut hwnd_pair_cache: HashMap = HashMap::new(); 136 | let mut root_hwnd_cache: HashMap = HashMap::new(); 137 | 138 | let mut cache_instantiation_time = Instant::now(); 139 | let max_cache_age = Duration::from_secs(60) * 10; // 10 minutes 140 | 141 | let mut is_mouse_down = false; 142 | 143 | loop { 144 | // clear our caches every 10 minutes 145 | if cache_instantiation_time.elapsed() > max_cache_age { 146 | tracing::info!("clearing caches, cache age is >10 minutes"); 147 | 148 | eligibility_cache = HashMap::new(); 149 | class_cache = HashMap::new(); 150 | hwnd_pair_cache = HashMap::new(); 151 | root_hwnd_cache = HashMap::new(); 152 | 153 | cache_instantiation_time = Instant::now(); 154 | } 155 | 156 | match receiver.next_event() { 157 | Event::MouseMoveRelative { .. } => { 158 | // resizing windows / dragging and dropping files fix 159 | if is_mouse_down { 160 | continue; 161 | } 162 | 163 | if let (Ok(cursor_pos_hwnd), Ok(foreground_hwnd)) = 164 | (window_at_cursor_pos(), foreground_window()) 165 | { 166 | if cursor_pos_hwnd == foreground_hwnd { 167 | continue; 168 | } 169 | 170 | let mut cursor_root_hwnd = root_hwnd_cache.get(&cursor_pos_hwnd).cloned(); 171 | 172 | // make syscalls if necessary and populate the root hwnd cache 173 | match &cursor_root_hwnd { 174 | None => { 175 | if let Ok(root_hwnd) = get_ancestor(cursor_pos_hwnd, GA_ROOT) { 176 | root_hwnd_cache.insert(cursor_pos_hwnd, root_hwnd); 177 | cursor_root_hwnd = Some(root_hwnd); 178 | } 179 | } 180 | Some(root_hwnd) => { 181 | tracing::debug!( 182 | "hwnd {cursor_pos_hwnd} root hwnd was found in the cache: {root_hwnd}" 183 | ); 184 | } 185 | } 186 | 187 | if let Some(cursor_root_hwnd) = cursor_root_hwnd { 188 | if cursor_root_hwnd == foreground_hwnd { 189 | continue; 190 | } 191 | 192 | if let Some(paired_hwnd) = hwnd_pair_cache.get(&cursor_root_hwnd) { 193 | if *paired_hwnd == foreground_hwnd { 194 | tracing::trace!("hwnds {cursor_root_hwnd} and {foreground_hwnd} are known to refer to the same application, skipping"); 195 | continue; 196 | } 197 | } 198 | 199 | let mut should_raise = false; 200 | 201 | // check our class cache to avoid syscalls 202 | let mut cursor_root_class = class_cache.get(&cursor_root_hwnd).cloned(); 203 | let mut foreground_class = class_cache.get(&foreground_hwnd).cloned(); 204 | 205 | // make syscalls if necessary and populate the class cache 206 | match &cursor_root_class { 207 | None => { 208 | if let Ok(class) = real_window_class_w(cursor_root_hwnd) { 209 | class_cache.insert(cursor_root_hwnd, class.clone()); 210 | cursor_root_class = Some(class); 211 | } 212 | } 213 | Some(class) => { 214 | tracing::debug!( 215 | "hwnd {cursor_root_hwnd} class was found in the cache: {class}" 216 | ); 217 | } 218 | } 219 | 220 | // make syscalls if necessary and populate the class cache 221 | match &foreground_class { 222 | None => { 223 | if let Ok(class) = real_window_class_w(foreground_hwnd) { 224 | class_cache.insert(foreground_hwnd, class.clone()); 225 | foreground_class = Some(class); 226 | } 227 | } 228 | Some(class) => { 229 | tracing::debug!( 230 | "hwnd {foreground_hwnd} class was found in the cache: {class}" 231 | ); 232 | } 233 | } 234 | 235 | if let (Some(cursor_root_class), Some(foreground_class)) = 236 | (&cursor_root_class, &foreground_class) 237 | { 238 | // steam fixes - populate the hwnd pair cache if necessary 239 | if cursor_root_class == "Chrome_RenderWidgetHostHWND" 240 | && foreground_class == "SDL_app" 241 | { 242 | hwnd_pair_cache.insert(cursor_root_hwnd, foreground_hwnd); 243 | continue; 244 | } 245 | } 246 | 247 | // check our eligibility caches 248 | if let (Some(cursor_root_is_eligible), Some(foreground_is_eligible)) = ( 249 | eligibility_cache.get(&cursor_root_hwnd), 250 | eligibility_cache.get(&foreground_hwnd), 251 | ) { 252 | if *cursor_root_is_eligible && *foreground_is_eligible { 253 | should_raise = true; 254 | tracing::debug!( 255 | "hwnds {cursor_root_hwnd} and {foreground_hwnd} were found as eligible in the cache" 256 | ); 257 | } 258 | } else if let Some(hwnds) = &hwnds { 259 | // use the hwnds file if twm integration is enabled 260 | if let Ok(raw_hwnds) = std::fs::read_to_string(hwnds) { 261 | let mut cursor_root_is_eligible = true; 262 | let mut foreground_is_eligible = true; 263 | 264 | // step one: test against the hwnds in the twm hwnds file 265 | cursor_root_is_eligible &= 266 | raw_hwnds.contains(&cursor_root_hwnd.to_string()); 267 | foreground_is_eligible &= 268 | raw_hwnds.contains(&foreground_hwnd.to_string()); 269 | 270 | // step two: test against known classes 271 | if let (Some(cursor_root_class), Some(foreground_class)) = 272 | (&cursor_root_class, &foreground_class) 273 | { 274 | for (class, strategy) in CLASS_IGNORELIST.iter() { 275 | let cursor_root_has_match = 276 | has_match(cursor_root_class, class, strategy); 277 | let foreground_has_match = 278 | has_match(foreground_class, class, strategy); 279 | 280 | cursor_root_is_eligible &= !cursor_root_has_match; 281 | foreground_is_eligible &= !foreground_has_match; 282 | } 283 | } 284 | 285 | // TODO: right now we just ignore the non-eligible case due to 286 | // potential delays with the twm writing to the hwnds file 287 | if cursor_root_is_eligible { 288 | eligibility_cache.insert(cursor_root_hwnd, true); 289 | } 290 | if foreground_is_eligible { 291 | eligibility_cache.insert(foreground_hwnd, true); 292 | } 293 | 294 | should_raise = 295 | cursor_root_is_eligible && foreground_is_eligible; 296 | } 297 | } else { 298 | let mut cursor_root_is_eligible = true; 299 | let mut foreground_is_eligible = true; 300 | 301 | // step one: test against known window styles 302 | cursor_root_is_eligible &= !has_filtered_style(cursor_root_hwnd); 303 | foreground_is_eligible &= !has_filtered_style(foreground_hwnd); 304 | 305 | // step two: test against known classes 306 | if let (Some(cursor_root_class), Some(foreground_class)) = 307 | (&cursor_root_class, &foreground_class) 308 | { 309 | for (class, strategy) in CLASS_IGNORELIST.iter() { 310 | let cursor_root_has_match = 311 | has_match(cursor_root_class, class, strategy); 312 | let foreground_has_match = 313 | has_match(foreground_class, class, strategy); 314 | 315 | cursor_root_is_eligible &= !cursor_root_has_match; 316 | foreground_is_eligible &= !foreground_has_match; 317 | } 318 | } 319 | 320 | eligibility_cache.insert(cursor_root_hwnd, cursor_root_is_eligible); 321 | eligibility_cache.insert(foreground_hwnd, foreground_is_eligible); 322 | 323 | should_raise = cursor_root_is_eligible && foreground_is_eligible; 324 | } 325 | 326 | if should_raise { 327 | match raise_and_focus_window(cursor_root_hwnd) { 328 | Ok(_) => { 329 | tracing::info!("raised hwnd: {cursor_root_hwnd}"); 330 | } 331 | Err(error) => { 332 | tracing::error!( 333 | "failed to raise hwnd {cursor_root_hwnd}: {error}" 334 | ); 335 | } 336 | } 337 | } 338 | } 339 | } 340 | } 341 | Event::MouseButton { action, .. } => match action { 342 | Action::Press => is_mouse_down = true, 343 | Action::Release => is_mouse_down = false, 344 | }, 345 | _ => {} 346 | } 347 | } 348 | }); 349 | } 350 | 351 | macro_rules! as_ptr { 352 | ($value:expr) => { 353 | $value as *mut core::ffi::c_void 354 | }; 355 | } 356 | 357 | enum WindowsResult { 358 | Err(E), 359 | Ok(T), 360 | } 361 | 362 | macro_rules! impl_from_integer_for_windows_result { 363 | ( $( $integer_type:ty ),+ ) => { 364 | $( 365 | impl From<$integer_type> for WindowsResult<$integer_type, color_eyre::eyre::Error> { 366 | fn from(return_value: $integer_type) -> Self { 367 | match return_value { 368 | 0 => Self::Err(std::io::Error::last_os_error().into()), 369 | _ => Self::Ok(return_value), 370 | } 371 | } 372 | } 373 | )+ 374 | }; 375 | } 376 | 377 | impl_from_integer_for_windows_result!(usize, isize, u16, u32, i32); 378 | 379 | impl From> for Result { 380 | fn from(result: WindowsResult) -> Self { 381 | match result { 382 | WindowsResult::Err(error) => Err(error), 383 | WindowsResult::Ok(ok) => Ok(ok), 384 | } 385 | } 386 | } 387 | 388 | trait ProcessWindowsCrateResult { 389 | fn process(self) -> Result; 390 | } 391 | 392 | macro_rules! impl_process_windows_crate_integer_wrapper_result { 393 | ( $($input:ty => $deref:ty),+ $(,)? ) => ( 394 | paste::paste! { 395 | $( 396 | impl ProcessWindowsCrateResult<$deref> for $input { 397 | fn process(self) -> Result<$deref> { 398 | if self == $input(std::ptr::null_mut()) { 399 | Err(std::io::Error::last_os_error().into()) 400 | } else { 401 | Ok(self.0 as $deref) 402 | } 403 | } 404 | } 405 | )+ 406 | } 407 | ); 408 | } 409 | 410 | impl_process_windows_crate_integer_wrapper_result!( 411 | HWND => isize, 412 | ); 413 | 414 | impl ProcessWindowsCrateResult for WindowsCrateResult { 415 | fn process(self) -> Result { 416 | match self { 417 | Ok(value) => Ok(value), 418 | Err(error) => Err(error.into()), 419 | } 420 | } 421 | } 422 | 423 | fn has_match(str1: &str, str2: &str, matching_strategy: &MatchingStrategy) -> bool { 424 | match matching_strategy { 425 | MatchingStrategy::Equals => str1 == str2, 426 | MatchingStrategy::Contains => str1.contains(str2), 427 | } 428 | } 429 | 430 | fn get_window_ex_style(hwnd: isize) -> WINDOW_EX_STYLE { 431 | unsafe { WINDOW_EX_STYLE(GetWindowLongW(HWND(as_ptr!(hwnd)), GWL_EXSTYLE) as u32) } 432 | } 433 | 434 | fn has_filtered_style(hwnd: isize) -> bool { 435 | let ex_style = get_window_ex_style(hwnd); 436 | 437 | ex_style.contains(WS_EX_TOOLWINDOW) || ex_style.contains(WS_EX_NOACTIVATE) 438 | } 439 | 440 | fn get_ancestor(hwnd: isize, gaflags: GET_ANCESTOR_FLAGS) -> Result { 441 | unsafe { GetAncestor(HWND(as_ptr!(hwnd)), gaflags) }.process() 442 | } 443 | 444 | fn window_from_point(point: POINT) -> Result { 445 | unsafe { WindowFromPoint(point) }.process() 446 | } 447 | 448 | fn window_at_cursor_pos() -> Result { 449 | window_from_point(cursor_pos()?) 450 | } 451 | 452 | fn foreground_window() -> Result { 453 | unsafe { GetForegroundWindow() }.process() 454 | } 455 | 456 | fn cursor_pos() -> Result { 457 | let mut cursor_pos = POINT::default(); 458 | unsafe { GetCursorPos(&mut cursor_pos) }.process()?; 459 | 460 | Ok(cursor_pos) 461 | } 462 | 463 | fn raise_and_focus_window(hwnd: isize) -> Result<()> { 464 | let event = [INPUT { 465 | r#type: INPUT_MOUSE, 466 | ..Default::default() 467 | }]; 468 | 469 | unsafe { 470 | // Send an input event to our own process first so that we pass the 471 | // foreground lock check 472 | SendInput(&event, size_of::() as i32); 473 | // Error ignored, as the operation is not always necessary. 474 | 475 | SetForegroundWindow(HWND(as_ptr!(hwnd))) 476 | } 477 | .ok() 478 | .process() 479 | } 480 | 481 | fn real_window_class_w(hwnd: isize) -> Result { 482 | const BUF_SIZE: usize = 512; 483 | let mut class: [u16; BUF_SIZE] = [0; BUF_SIZE]; 484 | 485 | let len = Result::from(WindowsResult::from(unsafe { 486 | RealGetWindowClassW(HWND(as_ptr!(hwnd)), &mut class) 487 | }))?; 488 | 489 | Ok(String::from_utf16(&class[0..len as usize])?) 490 | } 491 | -------------------------------------------------------------------------------- /wix/License.rtf: -------------------------------------------------------------------------------- 1 | {\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1033\deflangfe1033{\fonttbl{\f0\fswiss\fprq2\fcharset0 Arial;}} 2 | {\*\generator Riched20 10.0.22621}{\*\mmathPr\mdispDef1\mwrapIndent1440 }\viewkind4\uc1 3 | \pard\sa200\sl276\slmult1\f0\fs24\lang9 # Komorebi License\par 4 | \par 5 | Version 2.0.0\par 6 | \par 7 | ## Acceptance\par 8 | \par 9 | In order to get any license under these terms, you must agree\par 10 | to them as both strict obligations and conditions to all\par 11 | your licenses.\par 12 | \par 13 | ## Copyright License\par 14 | \par 15 | The licensor grants you a copyright license for the software\par 16 | to do everything you might do with the software that would\par 17 | otherwise infringe the licensor's copyright in it for any\par 18 | permitted purpose. However, you may only distribute the source\par 19 | code of the software according to the [Distribution License](\par 20 | #distribution-license), you may only make changes according\par 21 | to the [Changes License](#changes-license), and you may not\par 22 | otherwise distribute the software or new works based on the\par 23 | software.\par 24 | \par 25 | ## Distribution License\par 26 | \par 27 | The licensor grants you an additional copyright license to\par 28 | distribute copies of the source code of the software. Your\par 29 | license to distribute covers distributing the source code of\par 30 | the software with changes permitted by the [Changes License](\par 31 | #changes-license).\par 32 | \par 33 | ## Changes License\par 34 | \par 35 | The licensor grants you an additional copyright license to\par 36 | make changes for any permitted purpose.\par 37 | \par 38 | ## Patent License\par 39 | \par 40 | The licensor grants you a patent license for the software that\par 41 | covers patent claims the licensor can license, or becomes able\par 42 | to license, that you would infringe by using the software.\par 43 | \par 44 | ## Personal Uses\par 45 | \par 46 | Personal use for research, experiment, and testing for\par 47 | the benefit of public knowledge, personal study, private\par 48 | entertainment, hobby projects, amateur pursuits, or religious\par 49 | observance, without any anticipated commercial application,\par 50 | is use for a permitted purpose.\par 51 | \par 52 | ## Fair Use\par 53 | \par 54 | You may have "fair use" rights for the software under the\par 55 | law. These terms do not limit them.\par 56 | \par 57 | ## No Other Rights\par 58 | \par 59 | These terms do not allow you to sublicense or transfer any of\par 60 | your licenses to anyone else, or prevent the licensor from\par 61 | granting licenses to anyone else. These terms do not imply\par 62 | any other licenses.\par 63 | \par 64 | ## Patent Defense\par 65 | \par 66 | If you make any written claim that the software infringes or\par 67 | contributes to infringement of any patent, your patent license\par 68 | for the software granted under these terms ends immediately. If\par 69 | your company makes such a claim, your patent license ends\par 70 | immediately for work on behalf of your company.\par 71 | \par 72 | ## Violations\par 73 | \par 74 | The first time you are notified in writing that you have\par 75 | violated any of these terms, or done anything with the software\par 76 | not covered by your licenses, your licenses can nonetheless\par 77 | continue if you come into full compliance with these terms,\par 78 | and take practical steps to correct past violations, within\par 79 | 32 days of receiving notice. Otherwise, all your licenses\par 80 | end immediately.\par 81 | \par 82 | ## No Liability\par 83 | \par 84 | ***As far as the law allows, the software comes as is, without\par 85 | any warranty or condition, and the licensor will not be liable\par 86 | to you for any damages arising out of these terms or the use\par 87 | or nature of the software, under any kind of legal claim.***\par 88 | \par 89 | ## Definitions\par 90 | \par 91 | The **licensor** is the individual or entity offering these\par 92 | terms, and the **software** is the software the licensor makes\par 93 | available under these terms.\par 94 | \par 95 | **You** refers to the individual or entity agreeing to these\par 96 | terms.\par 97 | \par 98 | **Your company** is any legal entity, sole proprietorship,\par 99 | or other kind of organization that you work for, plus all\par 100 | organizations that have control over, are under the control of,\par 101 | or are under common control with that organization. **Control**\par 102 | means ownership of substantially all the assets of an entity,\par 103 | or the power to direct its management and policies by vote,\par 104 | contract, or otherwise. Control can be direct or indirect.\par 105 | \par 106 | **Your licenses** are all the licenses granted to you for the\par 107 | software under these terms.\par 108 | \par 109 | **Use** means anything you do with the software requiring one\par 110 | of your licenses.\par 111 | } 112 | -------------------------------------------------------------------------------- /wix/main.wxs: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 46 | 47 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 69 | 70 | 80 | 81 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 98 | 99 | 103 | 104 | 105 | 106 | 107 | 115 | 116 | 117 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 138 | 142 | 143 | 144 | 145 | 146 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 179 | 180 | 181 | 182 | 183 | 184 | 188 | 189 | 190 | 191 | 199 | 200 | 201 | 202 | 210 | 211 | 212 | 213 | 214 | 215 | --------------------------------------------------------------------------------