├── .clippy.toml ├── .github ├── copyright.sh └── workflows │ └── ci.yml ├── .gitignore ├── .taplo.toml ├── .typos.toml ├── AUTHORS ├── Cargo.lock ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── examples └── simple │ ├── Cargo.toml │ └── src │ └── main.rs ├── ui-events-winit ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md └── src │ ├── keyboard.rs │ ├── lib.rs │ └── pointer.rs ├── ui-events ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md └── src │ ├── keyboard │ ├── android.rs │ └── mod.rs │ ├── lib.rs │ ├── pointer │ ├── buttons.rs │ └── mod.rs │ └── scroll │ └── mod.rs └── ui-theme ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md └── src └── lib.rs /.clippy.toml: -------------------------------------------------------------------------------- 1 | # LINEBENDER LINT SET - .clippy.toml - v1 2 | # See https://linebender.org/wiki/canonical-lints/ 3 | 4 | # The default Clippy value is capped at 8 bytes, which was chosen to improve performance on 32-bit. 5 | # Given that we are building for the future and even low-end mobile phones have 64-bit CPUs, 6 | # it makes sense to optimize for 64-bit and accept the performance hits on 32-bit. 7 | # 16 bytes is the number of bytes that fits into two 64-bit CPU registers. 8 | trivial-copy-size-limit = 16 9 | 10 | # END LINEBENDER LINT SET 11 | -------------------------------------------------------------------------------- /.github/copyright.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # If there are new files with headers that can't match the conditions here, 4 | # then the files can be ignored by an additional glob argument via the -g flag. 5 | # For example: 6 | # -g "!src/special_file.rs" 7 | # -g "!src/special_directory" 8 | 9 | # Check all the standard Rust source files 10 | output=$(rg "^// Copyright (19|20)[\d]{2} (.+ and )?(the UI Events Authors|The Android Open Source Project)( and .+)?$\n^// SPDX-License-Identifier: Apache-2\.0 OR MIT$\n\n" --files-without-match --multiline -g "*.rs" .) 11 | 12 | if [ -n "$output" ]; then 13 | echo -e "The following files lack the correct copyright header:\n" 14 | echo $output 15 | echo -e "\n\nPlease add the following header:\n" 16 | echo "// Copyright $(date +%Y) the UI Events Authors" 17 | echo "// SPDX-License-Identifier: Apache-2.0 OR MIT" 18 | echo -e "\n... rest of the file ...\n" 19 | exit 1 20 | fi 21 | 22 | echo "All files have correct copyright headers." 23 | exit 0 24 | 25 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | env: 2 | # We aim to always test with the latest stable Rust toolchain, however we pin to a specific 3 | # version like 1.70. Note that we only specify MAJOR.MINOR and not PATCH so that bugfixes still 4 | # come automatically. If the version specified here is no longer the latest stable version, 5 | # then please feel free to submit a PR that adjusts it along with the potential clippy fixes. 6 | RUST_STABLE_VER: "1.87" # In quotes because otherwise (e.g.) 1.70 would be interpreted as 1.7 7 | # The purpose of checking with the minimum supported Rust toolchain is to detect its staleness. 8 | # If the compilation fails, then the version specified here needs to be bumped up to reality. 9 | # Be sure to also update the rust-version property in the workspace Cargo.toml file, 10 | # plus all the README.md files of the affected packages. 11 | RUST_MIN_VER: "1.73" 12 | # This crate has a different MSRV for no_std builds. 13 | RUST_MIN_NO_STD_VER: "1.81" 14 | # List of packages that will be checked with the minimum supported Rust version. 15 | # This should be limited to packages that are intended for publishing. 16 | RUST_MIN_VER_PKGS: "-p ui-events -p ui-events-winit -p ui-theme" 17 | # List of packages that will be checked for `no_std` builds. 18 | # This should be limited to packages that are intended for publishing. 19 | RUST_NO_STD_PKGS: "-p ui-events -p ui-theme" 20 | # List of features that depend on the standard library and will be excluded from no_std checks. 21 | FEATURES_DEPENDING_ON_STD: "std,default" 22 | 23 | 24 | # Rationale 25 | # 26 | # We don't run clippy with --all-targets because then even --lib and --bins are compiled with 27 | # dev dependencies enabled, which does not match how they would be compiled by users. 28 | # A dev dependency might enable a feature that we need for a regular dependency, 29 | # and checking with --all-targets would not find our feature requirements lacking. 30 | # This problem still applies to cargo resolver version 2. 31 | # Thus we split all the targets into two steps, one with --lib --bins 32 | # and another with --tests --benches --examples. 33 | # Also, we can't give --lib --bins explicitly because then cargo will error on binary-only packages. 34 | # Luckily the default behavior of cargo with no explicit targets is the same but without the error. 35 | # 36 | # We use cargo-hack for a similar reason. Cargo's --workspace will do feature unification across 37 | # the whole workspace. While cargo-hack will instead check each workspace package separately. 38 | # 39 | # Using cargo-hack also allows us to more easily test the feature matrix of our packages. 40 | # We use --each-feature & --optional-deps which will run a separate check for every feature. 41 | # 42 | # We use cargo-nextest, which has a faster concurrency model for running tests. 43 | # However cargo-nextest does not support running doc tests, so we also have a cargo test --doc step. 44 | # For more information see https://github.com/nextest-rs/nextest/issues/16 45 | # 46 | # The MSRV jobs run only cargo check because different clippy versions can disagree on goals and 47 | # running tests introduces dev dependencies which may require a higher MSRV than the bare package. 48 | # 49 | # For no_std checks we target x86_64-unknown-none, because this target doesn't support std 50 | # and as such will error out if our dependency tree accidentally tries to use std. 51 | # https://doc.rust-lang.org/stable/rustc/platform-support/x86_64-unknown-none.html 52 | # 53 | # We don't save caches in the merge-group cases, because those caches will never be re-used (apart 54 | # from the very rare cases where there are multiple PRs in the merge queue). 55 | # This is because GitHub doesn't share caches between merge queues and the main branch. 56 | 57 | name: CI 58 | 59 | on: 60 | pull_request: 61 | merge_group: 62 | # We run on push, even though the commit is the same as when we ran in merge_group. 63 | # This allows the cache to be primed. 64 | # See https://github.com/orgs/community/discussions/66430 65 | push: 66 | branches: 67 | - main 68 | 69 | jobs: 70 | fmt: 71 | name: formatting 72 | runs-on: ubuntu-latest 73 | steps: 74 | - uses: actions/checkout@v4 75 | 76 | - name: install stable toolchain 77 | uses: dtolnay/rust-toolchain@master 78 | with: 79 | toolchain: ${{ env.RUST_STABLE_VER }} 80 | components: rustfmt 81 | 82 | - name: cargo fmt 83 | run: cargo fmt --all --check 84 | 85 | - name: Install Taplo 86 | uses: uncenter/setup-taplo@09968a8ae38d66ddd3d23802c44bf6122d7aa991 # v1 87 | with: 88 | version: "0.9.3" 89 | 90 | - name: Run taplo fmt 91 | run: taplo fmt --check --diff 92 | 93 | - name: install ripgrep 94 | run: | 95 | sudo apt update 96 | sudo apt install ripgrep 97 | 98 | - name: check copyright headers 99 | run: bash .github/copyright.sh 100 | 101 | - name: install cargo-rdme 102 | uses: taiki-e/install-action@v2 103 | with: 104 | tool: cargo-rdme 105 | 106 | - name: cargo rdme (ui-events) 107 | # Ideally, we'd set heading-base-level=0 in the config file for cargo rdme, but that only 108 | # supports being placed at the top level, which we want to avoid cluttering. 109 | run: cargo rdme --workspace-project=ui-events --heading-base-level=0 --check 110 | 111 | - name: cargo rdme (ui-events-winit) 112 | run: cargo rdme --workspace-project=ui-events-winit --heading-base-level=0 --check 113 | 114 | - name: cargo rdme (ui-theme) 115 | run: cargo rdme --workspace-project=ui-theme --heading-base-level=0 --check 116 | 117 | clippy-stable: 118 | name: cargo clippy 119 | runs-on: ${{ matrix.os }} 120 | strategy: 121 | matrix: 122 | os: [windows-latest, macos-latest, ubuntu-latest] 123 | steps: 124 | - uses: actions/checkout@v4 125 | 126 | - name: install stable toolchain 127 | uses: dtolnay/rust-toolchain@master 128 | with: 129 | toolchain: ${{ env.RUST_STABLE_VER }} 130 | targets: x86_64-unknown-none 131 | components: clippy 132 | 133 | - name: install cargo-hack 134 | uses: taiki-e/install-action@v2 135 | with: 136 | tool: cargo-hack 137 | 138 | - name: restore cache 139 | uses: Swatinem/rust-cache@v2 140 | with: 141 | save-if: ${{ github.event_name != 'merge_group' }} 142 | 143 | - name: cargo clippy (no_std) 144 | run: cargo hack clippy ${{ env.RUST_NO_STD_PKGS }} --locked --optional-deps --each-feature --exclude-features ${{ env.FEATURES_DEPENDING_ON_STD }} --target x86_64-unknown-none -- -D warnings 145 | 146 | - name: cargo clippy 147 | run: cargo hack clippy --workspace --locked --optional-deps --each-feature --ignore-unknown-features --features std -- -D warnings 148 | 149 | - name: cargo clippy (auxiliary) 150 | run: cargo hack clippy --workspace --locked --optional-deps --each-feature --ignore-unknown-features --features std --tests --benches --examples -- -D warnings 151 | 152 | clippy-stable-wasm: 153 | name: cargo clippy (wasm32) 154 | runs-on: ubuntu-latest 155 | steps: 156 | - uses: actions/checkout@v4 157 | 158 | - name: install stable toolchain 159 | uses: dtolnay/rust-toolchain@master 160 | with: 161 | toolchain: ${{ env.RUST_STABLE_VER }} 162 | targets: wasm32-unknown-unknown 163 | components: clippy 164 | 165 | - name: install cargo-hack 166 | uses: taiki-e/install-action@v2 167 | with: 168 | tool: cargo-hack 169 | 170 | - name: restore cache 171 | uses: Swatinem/rust-cache@v2 172 | with: 173 | save-if: ${{ github.event_name != 'merge_group' }} 174 | 175 | - name: cargo clippy 176 | run: cargo hack clippy --workspace --locked --target wasm32-unknown-unknown --optional-deps --each-feature --ignore-unknown-features --features std -- -D warnings 177 | 178 | - name: cargo clippy (auxiliary) 179 | run: cargo hack clippy --workspace --locked --target wasm32-unknown-unknown --optional-deps --each-feature --ignore-unknown-features --features std --tests --benches --examples -- -D warnings 180 | 181 | test-stable: 182 | name: cargo test 183 | runs-on: ${{ matrix.os }} 184 | strategy: 185 | matrix: 186 | os: [windows-latest, macos-latest, ubuntu-latest] 187 | steps: 188 | - uses: actions/checkout@v4 189 | 190 | - name: install stable toolchain 191 | uses: dtolnay/rust-toolchain@master 192 | with: 193 | toolchain: ${{ env.RUST_STABLE_VER }} 194 | 195 | - name: install cargo-nextest 196 | uses: taiki-e/install-action@v2 197 | with: 198 | tool: cargo-nextest 199 | 200 | - name: restore cache 201 | uses: Swatinem/rust-cache@v2 202 | with: 203 | save-if: ${{ github.event_name != 'merge_group' }} 204 | 205 | - name: cargo nextest 206 | run: cargo nextest run --workspace --locked --all-features --no-fail-fast 207 | 208 | - name: cargo test --doc 209 | run: cargo test --doc --workspace --locked --all-features --no-fail-fast 210 | 211 | test-stable-wasm: 212 | name: cargo test (wasm32) 213 | runs-on: ubuntu-latest 214 | steps: 215 | - uses: actions/checkout@v4 216 | 217 | - name: install stable toolchain 218 | uses: dtolnay/rust-toolchain@master 219 | with: 220 | toolchain: ${{ env.RUST_STABLE_VER }} 221 | targets: wasm32-unknown-unknown 222 | 223 | - name: restore cache 224 | uses: Swatinem/rust-cache@v2 225 | with: 226 | save-if: ${{ github.event_name != 'merge_group' }} 227 | 228 | # TODO: Find a way to make tests work. Until then the tests are merely compiled. 229 | - name: cargo test compile 230 | run: cargo test --workspace --locked --target wasm32-unknown-unknown --all-features --no-run 231 | 232 | check-msrv: 233 | name: cargo check (msrv) 234 | runs-on: ${{ matrix.os }} 235 | strategy: 236 | matrix: 237 | os: [windows-latest, macos-latest, ubuntu-latest] 238 | steps: 239 | - uses: actions/checkout@v4 240 | 241 | - name: install msrv toolchain 242 | uses: dtolnay/rust-toolchain@master 243 | with: 244 | toolchain: ${{ env.RUST_MIN_VER }} 245 | targets: x86_64-unknown-none 246 | 247 | - name: install cargo-hack 248 | uses: taiki-e/install-action@v2 249 | with: 250 | tool: cargo-hack 251 | 252 | - name: restore cache 253 | uses: Swatinem/rust-cache@v2 254 | with: 255 | save-if: ${{ github.event_name != 'merge_group' }} 256 | 257 | - name: cargo check 258 | run: cargo hack check ${{ env.RUST_MIN_VER_PKGS }} --locked --optional-deps --each-feature --ignore-unknown-features --features std 259 | 260 | check-msrv-no-std: 261 | name: cargo check (msrv) 262 | runs-on: ${{ matrix.os }} 263 | strategy: 264 | matrix: 265 | os: [windows-latest, macos-latest, ubuntu-latest] 266 | steps: 267 | - uses: actions/checkout@v4 268 | 269 | - name: install msrv toolchain 270 | uses: dtolnay/rust-toolchain@master 271 | with: 272 | toolchain: ${{ env.RUST_MIN_NO_STD_VER }} 273 | targets: x86_64-unknown-none 274 | 275 | - name: install cargo-hack 276 | uses: taiki-e/install-action@v2 277 | with: 278 | tool: cargo-hack 279 | 280 | - name: restore cache 281 | uses: Swatinem/rust-cache@v2 282 | with: 283 | save-if: ${{ github.event_name != 'merge_group' }} 284 | 285 | - name: cargo check (no_std) 286 | run: cargo hack check ${{ env.RUST_NO_STD_PKGS }} --locked --optional-deps --each-feature --exclude-features ${{ env.FEATURES_DEPENDING_ON_STD }} --target x86_64-unknown-none 287 | 288 | check-msrv-wasm: 289 | name: cargo check (msrv) (wasm32) 290 | runs-on: ubuntu-latest 291 | steps: 292 | - uses: actions/checkout@v4 293 | 294 | - name: install msrv toolchain 295 | uses: dtolnay/rust-toolchain@master 296 | with: 297 | toolchain: ${{ env.RUST_MIN_VER }} 298 | targets: wasm32-unknown-unknown 299 | 300 | - name: install cargo-hack 301 | uses: taiki-e/install-action@v2 302 | with: 303 | tool: cargo-hack 304 | 305 | - name: restore cache 306 | uses: Swatinem/rust-cache@v2 307 | with: 308 | save-if: ${{ github.event_name != 'merge_group' }} 309 | 310 | - name: cargo check 311 | run: cargo hack check ${{ env.RUST_MIN_VER_PKGS }} --locked --target wasm32-unknown-unknown --optional-deps --each-feature --ignore-unknown-features --features std 312 | 313 | miri: 314 | name: cargo miri 315 | runs-on: ubuntu-latest 316 | steps: 317 | - uses: actions/checkout@v4 318 | 319 | - name: install nightly toolchain 320 | uses: dtolnay/rust-toolchain@master 321 | with: 322 | toolchain: nightly 323 | components: miri 324 | targets: s390x-unknown-linux-gnu 325 | 326 | - name: install cargo-hack 327 | uses: taiki-e/install-action@v2 328 | with: 329 | tool: cargo-hack 330 | 331 | - name: restore cache 332 | uses: Swatinem/rust-cache@v2 333 | with: 334 | save-if: ${{ github.event_name != 'merge_group' }} 335 | 336 | - name: cargo miri 337 | run: cargo miri test --workspace --locked --all-features --target s390x-unknown-linux-gnu --no-fail-fast 338 | 339 | doc: 340 | name: cargo doc 341 | # NOTE: We don't have any platform specific docs in this workspace, so we only run on Ubuntu. 342 | # If we get per-platform docs (win/macos/linux/wasm32/..) then doc jobs should match that. 343 | runs-on: ubuntu-latest 344 | steps: 345 | - uses: actions/checkout@v4 346 | 347 | - name: install nightly toolchain 348 | uses: dtolnay/rust-toolchain@nightly 349 | 350 | - name: restore cache 351 | uses: Swatinem/rust-cache@v2 352 | with: 353 | save-if: ${{ github.event_name != 'merge_group' }} 354 | 355 | # We test documentation using nightly to match docs.rs. 356 | - name: cargo doc 357 | run: cargo doc --workspace --locked --all-features --no-deps --document-private-items 358 | env: 359 | RUSTDOCFLAGS: '--cfg docsrs -D warnings' 360 | 361 | # If this fails, consider changing your text or adding something to .typos.toml. 362 | typos: 363 | runs-on: ubuntu-latest 364 | steps: 365 | - uses: actions/checkout@v4 366 | 367 | - name: check typos 368 | uses: crate-ci/typos@v1.32.0 369 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /.taplo.toml: -------------------------------------------------------------------------------- 1 | # See https://taplo.tamasfe.dev/configuration/file.html 2 | # and https://taplo.tamasfe.dev/configuration/formatter-options.html 3 | 4 | [formatting] 5 | # Aligning comments with the largest line creates 6 | # diff noise when neighboring lines are changed. 7 | align_comments = false 8 | 9 | # Matches how rustfmt formats Rust code 10 | column_width = 100 11 | indent_string = " " 12 | -------------------------------------------------------------------------------- /.typos.toml: -------------------------------------------------------------------------------- 1 | # See the configuration reference at 2 | # https://github.com/crate-ci/typos/blob/master/docs/reference.md 3 | 4 | # Corrections take the form of a key/value pair. The key is the incorrect word 5 | # and the value is the correct word. If the key and value are the same, the 6 | # word is treated as always correct. If the value is an empty string, the word 7 | # is treated as always incorrect. 8 | 9 | # Match Identifier - Case Sensitive 10 | [default.extend-identifiers] 11 | 12 | # Match Inside a Word - Case Insensitive 13 | [default.extend-words] 14 | 15 | [files] 16 | # Include .github, .cargo, etc. 17 | ignore-hidden = false 18 | extend-exclude = [ 19 | # /.git isn't in .gitignore, because git never tracks it. 20 | # Typos doesn't know that, though. 21 | "/.git", 22 | ] 23 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | # This is the list of UI Events' significant contributors. 2 | # 3 | # This does not necessarily list everyone who has contributed code, 4 | # especially since many employees of one corporation may be contributing. 5 | # To see the full list of contributors, see the revision history in 6 | # source control. 7 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "ab_glyph" 7 | version = "0.2.29" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "ec3672c180e71eeaaac3a541fbbc5f5ad4def8b747c595ad30d674e43049f7b0" 10 | dependencies = [ 11 | "ab_glyph_rasterizer", 12 | "owned_ttf_parser", 13 | ] 14 | 15 | [[package]] 16 | name = "ab_glyph_rasterizer" 17 | version = "0.1.8" 18 | source = "registry+https://github.com/rust-lang/crates.io-index" 19 | checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046" 20 | 21 | [[package]] 22 | name = "ahash" 23 | version = "0.8.11" 24 | source = "registry+https://github.com/rust-lang/crates.io-index" 25 | checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" 26 | dependencies = [ 27 | "cfg-if", 28 | "getrandom 0.2.16", 29 | "once_cell", 30 | "version_check", 31 | "zerocopy", 32 | ] 33 | 34 | [[package]] 35 | name = "android-activity" 36 | version = "0.6.0" 37 | source = "registry+https://github.com/rust-lang/crates.io-index" 38 | checksum = "ef6978589202a00cd7e118380c448a08b6ed394c3a8df3a430d0898e3a42d046" 39 | dependencies = [ 40 | "android-properties", 41 | "bitflags 2.9.0", 42 | "cc", 43 | "cesu8", 44 | "jni", 45 | "jni-sys", 46 | "libc", 47 | "log", 48 | "ndk", 49 | "ndk-context", 50 | "ndk-sys", 51 | "num_enum", 52 | "thiserror", 53 | ] 54 | 55 | [[package]] 56 | name = "android-properties" 57 | version = "0.2.2" 58 | source = "registry+https://github.com/rust-lang/crates.io-index" 59 | checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" 60 | 61 | [[package]] 62 | name = "anyhow" 63 | version = "1.0.98" 64 | source = "registry+https://github.com/rust-lang/crates.io-index" 65 | checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" 66 | 67 | [[package]] 68 | name = "arrayref" 69 | version = "0.3.9" 70 | source = "registry+https://github.com/rust-lang/crates.io-index" 71 | checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" 72 | 73 | [[package]] 74 | name = "arrayvec" 75 | version = "0.7.6" 76 | source = "registry+https://github.com/rust-lang/crates.io-index" 77 | checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" 78 | 79 | [[package]] 80 | name = "as-raw-xcb-connection" 81 | version = "1.0.1" 82 | source = "registry+https://github.com/rust-lang/crates.io-index" 83 | checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b" 84 | 85 | [[package]] 86 | name = "atomic-waker" 87 | version = "1.1.2" 88 | source = "registry+https://github.com/rust-lang/crates.io-index" 89 | checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" 90 | 91 | [[package]] 92 | name = "autocfg" 93 | version = "1.4.0" 94 | source = "registry+https://github.com/rust-lang/crates.io-index" 95 | checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" 96 | 97 | [[package]] 98 | name = "bitflags" 99 | version = "1.3.2" 100 | source = "registry+https://github.com/rust-lang/crates.io-index" 101 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 102 | 103 | [[package]] 104 | name = "bitflags" 105 | version = "2.9.0" 106 | source = "registry+https://github.com/rust-lang/crates.io-index" 107 | checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" 108 | 109 | [[package]] 110 | name = "block2" 111 | version = "0.5.1" 112 | source = "registry+https://github.com/rust-lang/crates.io-index" 113 | checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" 114 | dependencies = [ 115 | "objc2", 116 | ] 117 | 118 | [[package]] 119 | name = "bumpalo" 120 | version = "3.17.0" 121 | source = "registry+https://github.com/rust-lang/crates.io-index" 122 | checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" 123 | 124 | [[package]] 125 | name = "bytemuck" 126 | version = "1.23.0" 127 | source = "registry+https://github.com/rust-lang/crates.io-index" 128 | checksum = "9134a6ef01ce4b366b50689c94f82c14bc72bc5d0386829828a2e2752ef7958c" 129 | 130 | [[package]] 131 | name = "bytes" 132 | version = "1.10.1" 133 | source = "registry+https://github.com/rust-lang/crates.io-index" 134 | checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" 135 | 136 | [[package]] 137 | name = "calloop" 138 | version = "0.13.0" 139 | source = "registry+https://github.com/rust-lang/crates.io-index" 140 | checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" 141 | dependencies = [ 142 | "bitflags 2.9.0", 143 | "log", 144 | "polling", 145 | "rustix", 146 | "slab", 147 | "thiserror", 148 | ] 149 | 150 | [[package]] 151 | name = "calloop-wayland-source" 152 | version = "0.3.0" 153 | source = "registry+https://github.com/rust-lang/crates.io-index" 154 | checksum = "95a66a987056935f7efce4ab5668920b5d0dac4a7c99991a67395f13702ddd20" 155 | dependencies = [ 156 | "calloop", 157 | "rustix", 158 | "wayland-backend", 159 | "wayland-client", 160 | ] 161 | 162 | [[package]] 163 | name = "cc" 164 | version = "1.2.21" 165 | source = "registry+https://github.com/rust-lang/crates.io-index" 166 | checksum = "8691782945451c1c383942c4874dbe63814f61cb57ef773cda2972682b7bb3c0" 167 | dependencies = [ 168 | "jobserver", 169 | "libc", 170 | "shlex", 171 | ] 172 | 173 | [[package]] 174 | name = "cesu8" 175 | version = "1.1.0" 176 | source = "registry+https://github.com/rust-lang/crates.io-index" 177 | checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" 178 | 179 | [[package]] 180 | name = "cfg-if" 181 | version = "1.0.0" 182 | source = "registry+https://github.com/rust-lang/crates.io-index" 183 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 184 | 185 | [[package]] 186 | name = "cfg_aliases" 187 | version = "0.2.1" 188 | source = "registry+https://github.com/rust-lang/crates.io-index" 189 | checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" 190 | 191 | [[package]] 192 | name = "combine" 193 | version = "4.6.7" 194 | source = "registry+https://github.com/rust-lang/crates.io-index" 195 | checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" 196 | dependencies = [ 197 | "bytes", 198 | "memchr", 199 | ] 200 | 201 | [[package]] 202 | name = "concurrent-queue" 203 | version = "2.5.0" 204 | source = "registry+https://github.com/rust-lang/crates.io-index" 205 | checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" 206 | dependencies = [ 207 | "crossbeam-utils", 208 | ] 209 | 210 | [[package]] 211 | name = "core-foundation" 212 | version = "0.9.4" 213 | source = "registry+https://github.com/rust-lang/crates.io-index" 214 | checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" 215 | dependencies = [ 216 | "core-foundation-sys", 217 | "libc", 218 | ] 219 | 220 | [[package]] 221 | name = "core-foundation-sys" 222 | version = "0.8.7" 223 | source = "registry+https://github.com/rust-lang/crates.io-index" 224 | checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" 225 | 226 | [[package]] 227 | name = "core-graphics" 228 | version = "0.23.2" 229 | source = "registry+https://github.com/rust-lang/crates.io-index" 230 | checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" 231 | dependencies = [ 232 | "bitflags 1.3.2", 233 | "core-foundation", 234 | "core-graphics-types", 235 | "foreign-types", 236 | "libc", 237 | ] 238 | 239 | [[package]] 240 | name = "core-graphics-types" 241 | version = "0.1.3" 242 | source = "registry+https://github.com/rust-lang/crates.io-index" 243 | checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" 244 | dependencies = [ 245 | "bitflags 1.3.2", 246 | "core-foundation", 247 | "libc", 248 | ] 249 | 250 | [[package]] 251 | name = "crossbeam-utils" 252 | version = "0.8.21" 253 | source = "registry+https://github.com/rust-lang/crates.io-index" 254 | checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" 255 | 256 | [[package]] 257 | name = "cursor-icon" 258 | version = "1.1.0" 259 | source = "registry+https://github.com/rust-lang/crates.io-index" 260 | checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991" 261 | 262 | [[package]] 263 | name = "dispatch" 264 | version = "0.2.0" 265 | source = "registry+https://github.com/rust-lang/crates.io-index" 266 | checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" 267 | 268 | [[package]] 269 | name = "dlib" 270 | version = "0.5.2" 271 | source = "registry+https://github.com/rust-lang/crates.io-index" 272 | checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" 273 | dependencies = [ 274 | "libloading", 275 | ] 276 | 277 | [[package]] 278 | name = "downcast-rs" 279 | version = "1.2.1" 280 | source = "registry+https://github.com/rust-lang/crates.io-index" 281 | checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" 282 | 283 | [[package]] 284 | name = "dpi" 285 | version = "0.1.2" 286 | source = "registry+https://github.com/rust-lang/crates.io-index" 287 | checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" 288 | 289 | [[package]] 290 | name = "equivalent" 291 | version = "1.0.2" 292 | source = "registry+https://github.com/rust-lang/crates.io-index" 293 | checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" 294 | 295 | [[package]] 296 | name = "errno" 297 | version = "0.3.11" 298 | source = "registry+https://github.com/rust-lang/crates.io-index" 299 | checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" 300 | dependencies = [ 301 | "libc", 302 | "windows-sys 0.59.0", 303 | ] 304 | 305 | [[package]] 306 | name = "foreign-types" 307 | version = "0.5.0" 308 | source = "registry+https://github.com/rust-lang/crates.io-index" 309 | checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" 310 | dependencies = [ 311 | "foreign-types-macros", 312 | "foreign-types-shared", 313 | ] 314 | 315 | [[package]] 316 | name = "foreign-types-macros" 317 | version = "0.2.3" 318 | source = "registry+https://github.com/rust-lang/crates.io-index" 319 | checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" 320 | dependencies = [ 321 | "proc-macro2", 322 | "quote", 323 | "syn", 324 | ] 325 | 326 | [[package]] 327 | name = "foreign-types-shared" 328 | version = "0.3.1" 329 | source = "registry+https://github.com/rust-lang/crates.io-index" 330 | checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" 331 | 332 | [[package]] 333 | name = "gethostname" 334 | version = "0.4.3" 335 | source = "registry+https://github.com/rust-lang/crates.io-index" 336 | checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818" 337 | dependencies = [ 338 | "libc", 339 | "windows-targets 0.48.5", 340 | ] 341 | 342 | [[package]] 343 | name = "getrandom" 344 | version = "0.2.16" 345 | source = "registry+https://github.com/rust-lang/crates.io-index" 346 | checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" 347 | dependencies = [ 348 | "cfg-if", 349 | "libc", 350 | "wasi 0.11.0+wasi-snapshot-preview1", 351 | ] 352 | 353 | [[package]] 354 | name = "getrandom" 355 | version = "0.3.2" 356 | source = "registry+https://github.com/rust-lang/crates.io-index" 357 | checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" 358 | dependencies = [ 359 | "cfg-if", 360 | "libc", 361 | "r-efi", 362 | "wasi 0.14.2+wasi-0.2.4", 363 | ] 364 | 365 | [[package]] 366 | name = "hashbrown" 367 | version = "0.15.3" 368 | source = "registry+https://github.com/rust-lang/crates.io-index" 369 | checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3" 370 | 371 | [[package]] 372 | name = "hermit-abi" 373 | version = "0.4.0" 374 | source = "registry+https://github.com/rust-lang/crates.io-index" 375 | checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" 376 | 377 | [[package]] 378 | name = "indexmap" 379 | version = "2.9.0" 380 | source = "registry+https://github.com/rust-lang/crates.io-index" 381 | checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" 382 | dependencies = [ 383 | "equivalent", 384 | "hashbrown", 385 | ] 386 | 387 | [[package]] 388 | name = "jni" 389 | version = "0.21.1" 390 | source = "registry+https://github.com/rust-lang/crates.io-index" 391 | checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" 392 | dependencies = [ 393 | "cesu8", 394 | "cfg-if", 395 | "combine", 396 | "jni-sys", 397 | "log", 398 | "thiserror", 399 | "walkdir", 400 | "windows-sys 0.45.0", 401 | ] 402 | 403 | [[package]] 404 | name = "jni-sys" 405 | version = "0.3.0" 406 | source = "registry+https://github.com/rust-lang/crates.io-index" 407 | checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" 408 | 409 | [[package]] 410 | name = "jobserver" 411 | version = "0.1.33" 412 | source = "registry+https://github.com/rust-lang/crates.io-index" 413 | checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" 414 | dependencies = [ 415 | "getrandom 0.3.2", 416 | "libc", 417 | ] 418 | 419 | [[package]] 420 | name = "js-sys" 421 | version = "0.3.77" 422 | source = "registry+https://github.com/rust-lang/crates.io-index" 423 | checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" 424 | dependencies = [ 425 | "once_cell", 426 | "wasm-bindgen", 427 | ] 428 | 429 | [[package]] 430 | name = "keyboard-types" 431 | version = "0.8.0" 432 | source = "registry+https://github.com/rust-lang/crates.io-index" 433 | checksum = "fd6e0f18953c66af118a70064505bd3780a226d65b06553b7293fb8933067967" 434 | dependencies = [ 435 | "bitflags 2.9.0", 436 | "serde", 437 | ] 438 | 439 | [[package]] 440 | name = "libc" 441 | version = "0.2.172" 442 | source = "registry+https://github.com/rust-lang/crates.io-index" 443 | checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" 444 | 445 | [[package]] 446 | name = "libloading" 447 | version = "0.8.6" 448 | source = "registry+https://github.com/rust-lang/crates.io-index" 449 | checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" 450 | dependencies = [ 451 | "cfg-if", 452 | "windows-targets 0.52.6", 453 | ] 454 | 455 | [[package]] 456 | name = "libredox" 457 | version = "0.1.3" 458 | source = "registry+https://github.com/rust-lang/crates.io-index" 459 | checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" 460 | dependencies = [ 461 | "bitflags 2.9.0", 462 | "libc", 463 | "redox_syscall 0.5.12", 464 | ] 465 | 466 | [[package]] 467 | name = "linux-raw-sys" 468 | version = "0.4.15" 469 | source = "registry+https://github.com/rust-lang/crates.io-index" 470 | checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" 471 | 472 | [[package]] 473 | name = "log" 474 | version = "0.4.27" 475 | source = "registry+https://github.com/rust-lang/crates.io-index" 476 | checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" 477 | 478 | [[package]] 479 | name = "memchr" 480 | version = "2.7.4" 481 | source = "registry+https://github.com/rust-lang/crates.io-index" 482 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 483 | 484 | [[package]] 485 | name = "memmap2" 486 | version = "0.9.5" 487 | source = "registry+https://github.com/rust-lang/crates.io-index" 488 | checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" 489 | dependencies = [ 490 | "libc", 491 | ] 492 | 493 | [[package]] 494 | name = "ndk" 495 | version = "0.9.0" 496 | source = "registry+https://github.com/rust-lang/crates.io-index" 497 | checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" 498 | dependencies = [ 499 | "bitflags 2.9.0", 500 | "jni-sys", 501 | "log", 502 | "ndk-sys", 503 | "num_enum", 504 | "raw-window-handle", 505 | "thiserror", 506 | ] 507 | 508 | [[package]] 509 | name = "ndk-context" 510 | version = "0.1.1" 511 | source = "registry+https://github.com/rust-lang/crates.io-index" 512 | checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" 513 | 514 | [[package]] 515 | name = "ndk-sys" 516 | version = "0.6.0+11769913" 517 | source = "registry+https://github.com/rust-lang/crates.io-index" 518 | checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" 519 | dependencies = [ 520 | "jni-sys", 521 | ] 522 | 523 | [[package]] 524 | name = "num_enum" 525 | version = "0.7.3" 526 | source = "registry+https://github.com/rust-lang/crates.io-index" 527 | checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" 528 | dependencies = [ 529 | "num_enum_derive", 530 | ] 531 | 532 | [[package]] 533 | name = "num_enum_derive" 534 | version = "0.7.3" 535 | source = "registry+https://github.com/rust-lang/crates.io-index" 536 | checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" 537 | dependencies = [ 538 | "proc-macro-crate", 539 | "proc-macro2", 540 | "quote", 541 | "syn", 542 | ] 543 | 544 | [[package]] 545 | name = "objc-sys" 546 | version = "0.3.5" 547 | source = "registry+https://github.com/rust-lang/crates.io-index" 548 | checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" 549 | 550 | [[package]] 551 | name = "objc2" 552 | version = "0.5.2" 553 | source = "registry+https://github.com/rust-lang/crates.io-index" 554 | checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" 555 | dependencies = [ 556 | "objc-sys", 557 | "objc2-encode", 558 | ] 559 | 560 | [[package]] 561 | name = "objc2-app-kit" 562 | version = "0.2.2" 563 | source = "registry+https://github.com/rust-lang/crates.io-index" 564 | checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" 565 | dependencies = [ 566 | "bitflags 2.9.0", 567 | "block2", 568 | "libc", 569 | "objc2", 570 | "objc2-core-data", 571 | "objc2-core-image", 572 | "objc2-foundation", 573 | "objc2-quartz-core", 574 | ] 575 | 576 | [[package]] 577 | name = "objc2-cloud-kit" 578 | version = "0.2.2" 579 | source = "registry+https://github.com/rust-lang/crates.io-index" 580 | checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" 581 | dependencies = [ 582 | "bitflags 2.9.0", 583 | "block2", 584 | "objc2", 585 | "objc2-core-location", 586 | "objc2-foundation", 587 | ] 588 | 589 | [[package]] 590 | name = "objc2-contacts" 591 | version = "0.2.2" 592 | source = "registry+https://github.com/rust-lang/crates.io-index" 593 | checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" 594 | dependencies = [ 595 | "block2", 596 | "objc2", 597 | "objc2-foundation", 598 | ] 599 | 600 | [[package]] 601 | name = "objc2-core-data" 602 | version = "0.2.2" 603 | source = "registry+https://github.com/rust-lang/crates.io-index" 604 | checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" 605 | dependencies = [ 606 | "bitflags 2.9.0", 607 | "block2", 608 | "objc2", 609 | "objc2-foundation", 610 | ] 611 | 612 | [[package]] 613 | name = "objc2-core-image" 614 | version = "0.2.2" 615 | source = "registry+https://github.com/rust-lang/crates.io-index" 616 | checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" 617 | dependencies = [ 618 | "block2", 619 | "objc2", 620 | "objc2-foundation", 621 | "objc2-metal", 622 | ] 623 | 624 | [[package]] 625 | name = "objc2-core-location" 626 | version = "0.2.2" 627 | source = "registry+https://github.com/rust-lang/crates.io-index" 628 | checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" 629 | dependencies = [ 630 | "block2", 631 | "objc2", 632 | "objc2-contacts", 633 | "objc2-foundation", 634 | ] 635 | 636 | [[package]] 637 | name = "objc2-encode" 638 | version = "4.1.0" 639 | source = "registry+https://github.com/rust-lang/crates.io-index" 640 | checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" 641 | 642 | [[package]] 643 | name = "objc2-foundation" 644 | version = "0.2.2" 645 | source = "registry+https://github.com/rust-lang/crates.io-index" 646 | checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" 647 | dependencies = [ 648 | "bitflags 2.9.0", 649 | "block2", 650 | "dispatch", 651 | "libc", 652 | "objc2", 653 | ] 654 | 655 | [[package]] 656 | name = "objc2-link-presentation" 657 | version = "0.2.2" 658 | source = "registry+https://github.com/rust-lang/crates.io-index" 659 | checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" 660 | dependencies = [ 661 | "block2", 662 | "objc2", 663 | "objc2-app-kit", 664 | "objc2-foundation", 665 | ] 666 | 667 | [[package]] 668 | name = "objc2-metal" 669 | version = "0.2.2" 670 | source = "registry+https://github.com/rust-lang/crates.io-index" 671 | checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" 672 | dependencies = [ 673 | "bitflags 2.9.0", 674 | "block2", 675 | "objc2", 676 | "objc2-foundation", 677 | ] 678 | 679 | [[package]] 680 | name = "objc2-quartz-core" 681 | version = "0.2.2" 682 | source = "registry+https://github.com/rust-lang/crates.io-index" 683 | checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" 684 | dependencies = [ 685 | "bitflags 2.9.0", 686 | "block2", 687 | "objc2", 688 | "objc2-foundation", 689 | "objc2-metal", 690 | ] 691 | 692 | [[package]] 693 | name = "objc2-symbols" 694 | version = "0.2.2" 695 | source = "registry+https://github.com/rust-lang/crates.io-index" 696 | checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc" 697 | dependencies = [ 698 | "objc2", 699 | "objc2-foundation", 700 | ] 701 | 702 | [[package]] 703 | name = "objc2-ui-kit" 704 | version = "0.2.2" 705 | source = "registry+https://github.com/rust-lang/crates.io-index" 706 | checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" 707 | dependencies = [ 708 | "bitflags 2.9.0", 709 | "block2", 710 | "objc2", 711 | "objc2-cloud-kit", 712 | "objc2-core-data", 713 | "objc2-core-image", 714 | "objc2-core-location", 715 | "objc2-foundation", 716 | "objc2-link-presentation", 717 | "objc2-quartz-core", 718 | "objc2-symbols", 719 | "objc2-uniform-type-identifiers", 720 | "objc2-user-notifications", 721 | ] 722 | 723 | [[package]] 724 | name = "objc2-uniform-type-identifiers" 725 | version = "0.2.2" 726 | source = "registry+https://github.com/rust-lang/crates.io-index" 727 | checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" 728 | dependencies = [ 729 | "block2", 730 | "objc2", 731 | "objc2-foundation", 732 | ] 733 | 734 | [[package]] 735 | name = "objc2-user-notifications" 736 | version = "0.2.2" 737 | source = "registry+https://github.com/rust-lang/crates.io-index" 738 | checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" 739 | dependencies = [ 740 | "bitflags 2.9.0", 741 | "block2", 742 | "objc2", 743 | "objc2-core-location", 744 | "objc2-foundation", 745 | ] 746 | 747 | [[package]] 748 | name = "once_cell" 749 | version = "1.21.3" 750 | source = "registry+https://github.com/rust-lang/crates.io-index" 751 | checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" 752 | 753 | [[package]] 754 | name = "orbclient" 755 | version = "0.3.48" 756 | source = "registry+https://github.com/rust-lang/crates.io-index" 757 | checksum = "ba0b26cec2e24f08ed8bb31519a9333140a6599b867dac464bb150bdb796fd43" 758 | dependencies = [ 759 | "libredox", 760 | ] 761 | 762 | [[package]] 763 | name = "owned_ttf_parser" 764 | version = "0.25.0" 765 | source = "registry+https://github.com/rust-lang/crates.io-index" 766 | checksum = "22ec719bbf3b2a81c109a4e20b1f129b5566b7dce654bc3872f6a05abf82b2c4" 767 | dependencies = [ 768 | "ttf-parser", 769 | ] 770 | 771 | [[package]] 772 | name = "percent-encoding" 773 | version = "2.3.1" 774 | source = "registry+https://github.com/rust-lang/crates.io-index" 775 | checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" 776 | 777 | [[package]] 778 | name = "pin-project" 779 | version = "1.1.10" 780 | source = "registry+https://github.com/rust-lang/crates.io-index" 781 | checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" 782 | dependencies = [ 783 | "pin-project-internal", 784 | ] 785 | 786 | [[package]] 787 | name = "pin-project-internal" 788 | version = "1.1.10" 789 | source = "registry+https://github.com/rust-lang/crates.io-index" 790 | checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" 791 | dependencies = [ 792 | "proc-macro2", 793 | "quote", 794 | "syn", 795 | ] 796 | 797 | [[package]] 798 | name = "pin-project-lite" 799 | version = "0.2.16" 800 | source = "registry+https://github.com/rust-lang/crates.io-index" 801 | checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" 802 | 803 | [[package]] 804 | name = "pkg-config" 805 | version = "0.3.32" 806 | source = "registry+https://github.com/rust-lang/crates.io-index" 807 | checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" 808 | 809 | [[package]] 810 | name = "polling" 811 | version = "3.7.4" 812 | source = "registry+https://github.com/rust-lang/crates.io-index" 813 | checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f" 814 | dependencies = [ 815 | "cfg-if", 816 | "concurrent-queue", 817 | "hermit-abi", 818 | "pin-project-lite", 819 | "rustix", 820 | "tracing", 821 | "windows-sys 0.59.0", 822 | ] 823 | 824 | [[package]] 825 | name = "proc-macro-crate" 826 | version = "3.3.0" 827 | source = "registry+https://github.com/rust-lang/crates.io-index" 828 | checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" 829 | dependencies = [ 830 | "toml_edit", 831 | ] 832 | 833 | [[package]] 834 | name = "proc-macro2" 835 | version = "1.0.95" 836 | source = "registry+https://github.com/rust-lang/crates.io-index" 837 | checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" 838 | dependencies = [ 839 | "unicode-ident", 840 | ] 841 | 842 | [[package]] 843 | name = "quick-xml" 844 | version = "0.37.5" 845 | source = "registry+https://github.com/rust-lang/crates.io-index" 846 | checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb" 847 | dependencies = [ 848 | "memchr", 849 | ] 850 | 851 | [[package]] 852 | name = "quote" 853 | version = "1.0.40" 854 | source = "registry+https://github.com/rust-lang/crates.io-index" 855 | checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 856 | dependencies = [ 857 | "proc-macro2", 858 | ] 859 | 860 | [[package]] 861 | name = "r-efi" 862 | version = "5.2.0" 863 | source = "registry+https://github.com/rust-lang/crates.io-index" 864 | checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" 865 | 866 | [[package]] 867 | name = "raw-window-handle" 868 | version = "0.6.2" 869 | source = "registry+https://github.com/rust-lang/crates.io-index" 870 | checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" 871 | 872 | [[package]] 873 | name = "redox_syscall" 874 | version = "0.4.1" 875 | source = "registry+https://github.com/rust-lang/crates.io-index" 876 | checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" 877 | dependencies = [ 878 | "bitflags 1.3.2", 879 | ] 880 | 881 | [[package]] 882 | name = "redox_syscall" 883 | version = "0.5.12" 884 | source = "registry+https://github.com/rust-lang/crates.io-index" 885 | checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af" 886 | dependencies = [ 887 | "bitflags 2.9.0", 888 | ] 889 | 890 | [[package]] 891 | name = "rustix" 892 | version = "0.38.44" 893 | source = "registry+https://github.com/rust-lang/crates.io-index" 894 | checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" 895 | dependencies = [ 896 | "bitflags 2.9.0", 897 | "errno", 898 | "libc", 899 | "linux-raw-sys", 900 | "windows-sys 0.59.0", 901 | ] 902 | 903 | [[package]] 904 | name = "rustversion" 905 | version = "1.0.20" 906 | source = "registry+https://github.com/rust-lang/crates.io-index" 907 | checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" 908 | 909 | [[package]] 910 | name = "same-file" 911 | version = "1.0.6" 912 | source = "registry+https://github.com/rust-lang/crates.io-index" 913 | checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" 914 | dependencies = [ 915 | "winapi-util", 916 | ] 917 | 918 | [[package]] 919 | name = "scoped-tls" 920 | version = "1.0.1" 921 | source = "registry+https://github.com/rust-lang/crates.io-index" 922 | checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" 923 | 924 | [[package]] 925 | name = "sctk-adwaita" 926 | version = "0.10.1" 927 | source = "registry+https://github.com/rust-lang/crates.io-index" 928 | checksum = "b6277f0217056f77f1d8f49f2950ac6c278c0d607c45f5ee99328d792ede24ec" 929 | dependencies = [ 930 | "ab_glyph", 931 | "log", 932 | "memmap2", 933 | "smithay-client-toolkit", 934 | "tiny-skia", 935 | ] 936 | 937 | [[package]] 938 | name = "serde" 939 | version = "1.0.219" 940 | source = "registry+https://github.com/rust-lang/crates.io-index" 941 | checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" 942 | dependencies = [ 943 | "serde_derive", 944 | ] 945 | 946 | [[package]] 947 | name = "serde_derive" 948 | version = "1.0.219" 949 | source = "registry+https://github.com/rust-lang/crates.io-index" 950 | checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" 951 | dependencies = [ 952 | "proc-macro2", 953 | "quote", 954 | "syn", 955 | ] 956 | 957 | [[package]] 958 | name = "shlex" 959 | version = "1.3.0" 960 | source = "registry+https://github.com/rust-lang/crates.io-index" 961 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 962 | 963 | [[package]] 964 | name = "simple" 965 | version = "0.1.0" 966 | dependencies = [ 967 | "anyhow", 968 | "ui-events", 969 | ] 970 | 971 | [[package]] 972 | name = "slab" 973 | version = "0.4.9" 974 | source = "registry+https://github.com/rust-lang/crates.io-index" 975 | checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" 976 | dependencies = [ 977 | "autocfg", 978 | ] 979 | 980 | [[package]] 981 | name = "smallvec" 982 | version = "1.15.0" 983 | source = "registry+https://github.com/rust-lang/crates.io-index" 984 | checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" 985 | 986 | [[package]] 987 | name = "smithay-client-toolkit" 988 | version = "0.19.2" 989 | source = "registry+https://github.com/rust-lang/crates.io-index" 990 | checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" 991 | dependencies = [ 992 | "bitflags 2.9.0", 993 | "calloop", 994 | "calloop-wayland-source", 995 | "cursor-icon", 996 | "libc", 997 | "log", 998 | "memmap2", 999 | "rustix", 1000 | "thiserror", 1001 | "wayland-backend", 1002 | "wayland-client", 1003 | "wayland-csd-frame", 1004 | "wayland-cursor", 1005 | "wayland-protocols", 1006 | "wayland-protocols-wlr", 1007 | "wayland-scanner", 1008 | "xkeysym", 1009 | ] 1010 | 1011 | [[package]] 1012 | name = "smol_str" 1013 | version = "0.2.2" 1014 | source = "registry+https://github.com/rust-lang/crates.io-index" 1015 | checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead" 1016 | dependencies = [ 1017 | "serde", 1018 | ] 1019 | 1020 | [[package]] 1021 | name = "strict-num" 1022 | version = "0.1.1" 1023 | source = "registry+https://github.com/rust-lang/crates.io-index" 1024 | checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" 1025 | 1026 | [[package]] 1027 | name = "syn" 1028 | version = "2.0.101" 1029 | source = "registry+https://github.com/rust-lang/crates.io-index" 1030 | checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" 1031 | dependencies = [ 1032 | "proc-macro2", 1033 | "quote", 1034 | "unicode-ident", 1035 | ] 1036 | 1037 | [[package]] 1038 | name = "thiserror" 1039 | version = "1.0.69" 1040 | source = "registry+https://github.com/rust-lang/crates.io-index" 1041 | checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" 1042 | dependencies = [ 1043 | "thiserror-impl", 1044 | ] 1045 | 1046 | [[package]] 1047 | name = "thiserror-impl" 1048 | version = "1.0.69" 1049 | source = "registry+https://github.com/rust-lang/crates.io-index" 1050 | checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" 1051 | dependencies = [ 1052 | "proc-macro2", 1053 | "quote", 1054 | "syn", 1055 | ] 1056 | 1057 | [[package]] 1058 | name = "tiny-skia" 1059 | version = "0.11.4" 1060 | source = "registry+https://github.com/rust-lang/crates.io-index" 1061 | checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab" 1062 | dependencies = [ 1063 | "arrayref", 1064 | "arrayvec", 1065 | "bytemuck", 1066 | "cfg-if", 1067 | "log", 1068 | "tiny-skia-path", 1069 | ] 1070 | 1071 | [[package]] 1072 | name = "tiny-skia-path" 1073 | version = "0.11.4" 1074 | source = "registry+https://github.com/rust-lang/crates.io-index" 1075 | checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93" 1076 | dependencies = [ 1077 | "arrayref", 1078 | "bytemuck", 1079 | "strict-num", 1080 | ] 1081 | 1082 | [[package]] 1083 | name = "toml_datetime" 1084 | version = "0.6.9" 1085 | source = "registry+https://github.com/rust-lang/crates.io-index" 1086 | checksum = "3da5db5a963e24bc68be8b17b6fa82814bb22ee8660f192bb182771d498f09a3" 1087 | 1088 | [[package]] 1089 | name = "toml_edit" 1090 | version = "0.22.26" 1091 | source = "registry+https://github.com/rust-lang/crates.io-index" 1092 | checksum = "310068873db2c5b3e7659d2cc35d21855dbafa50d1ce336397c666e3cb08137e" 1093 | dependencies = [ 1094 | "indexmap", 1095 | "toml_datetime", 1096 | "winnow", 1097 | ] 1098 | 1099 | [[package]] 1100 | name = "tracing" 1101 | version = "0.1.41" 1102 | source = "registry+https://github.com/rust-lang/crates.io-index" 1103 | checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" 1104 | dependencies = [ 1105 | "pin-project-lite", 1106 | "tracing-core", 1107 | ] 1108 | 1109 | [[package]] 1110 | name = "tracing-core" 1111 | version = "0.1.33" 1112 | source = "registry+https://github.com/rust-lang/crates.io-index" 1113 | checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" 1114 | 1115 | [[package]] 1116 | name = "ttf-parser" 1117 | version = "0.25.1" 1118 | source = "registry+https://github.com/rust-lang/crates.io-index" 1119 | checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" 1120 | 1121 | [[package]] 1122 | name = "ui-events" 1123 | version = "0.1.0" 1124 | dependencies = [ 1125 | "dpi", 1126 | "keyboard-types", 1127 | ] 1128 | 1129 | [[package]] 1130 | name = "ui-events-winit" 1131 | version = "0.1.0" 1132 | dependencies = [ 1133 | "ui-events", 1134 | "winit", 1135 | ] 1136 | 1137 | [[package]] 1138 | name = "ui-theme" 1139 | version = "0.1.0" 1140 | 1141 | [[package]] 1142 | name = "unicode-ident" 1143 | version = "1.0.18" 1144 | source = "registry+https://github.com/rust-lang/crates.io-index" 1145 | checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 1146 | 1147 | [[package]] 1148 | name = "unicode-segmentation" 1149 | version = "1.12.0" 1150 | source = "registry+https://github.com/rust-lang/crates.io-index" 1151 | checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" 1152 | 1153 | [[package]] 1154 | name = "version_check" 1155 | version = "0.9.5" 1156 | source = "registry+https://github.com/rust-lang/crates.io-index" 1157 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 1158 | 1159 | [[package]] 1160 | name = "walkdir" 1161 | version = "2.5.0" 1162 | source = "registry+https://github.com/rust-lang/crates.io-index" 1163 | checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" 1164 | dependencies = [ 1165 | "same-file", 1166 | "winapi-util", 1167 | ] 1168 | 1169 | [[package]] 1170 | name = "wasi" 1171 | version = "0.11.0+wasi-snapshot-preview1" 1172 | source = "registry+https://github.com/rust-lang/crates.io-index" 1173 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 1174 | 1175 | [[package]] 1176 | name = "wasi" 1177 | version = "0.14.2+wasi-0.2.4" 1178 | source = "registry+https://github.com/rust-lang/crates.io-index" 1179 | checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" 1180 | dependencies = [ 1181 | "wit-bindgen-rt", 1182 | ] 1183 | 1184 | [[package]] 1185 | name = "wasm-bindgen" 1186 | version = "0.2.100" 1187 | source = "registry+https://github.com/rust-lang/crates.io-index" 1188 | checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" 1189 | dependencies = [ 1190 | "cfg-if", 1191 | "once_cell", 1192 | "rustversion", 1193 | "wasm-bindgen-macro", 1194 | ] 1195 | 1196 | [[package]] 1197 | name = "wasm-bindgen-backend" 1198 | version = "0.2.100" 1199 | source = "registry+https://github.com/rust-lang/crates.io-index" 1200 | checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" 1201 | dependencies = [ 1202 | "bumpalo", 1203 | "log", 1204 | "proc-macro2", 1205 | "quote", 1206 | "syn", 1207 | "wasm-bindgen-shared", 1208 | ] 1209 | 1210 | [[package]] 1211 | name = "wasm-bindgen-futures" 1212 | version = "0.4.50" 1213 | source = "registry+https://github.com/rust-lang/crates.io-index" 1214 | checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" 1215 | dependencies = [ 1216 | "cfg-if", 1217 | "js-sys", 1218 | "once_cell", 1219 | "wasm-bindgen", 1220 | "web-sys", 1221 | ] 1222 | 1223 | [[package]] 1224 | name = "wasm-bindgen-macro" 1225 | version = "0.2.100" 1226 | source = "registry+https://github.com/rust-lang/crates.io-index" 1227 | checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" 1228 | dependencies = [ 1229 | "quote", 1230 | "wasm-bindgen-macro-support", 1231 | ] 1232 | 1233 | [[package]] 1234 | name = "wasm-bindgen-macro-support" 1235 | version = "0.2.100" 1236 | source = "registry+https://github.com/rust-lang/crates.io-index" 1237 | checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" 1238 | dependencies = [ 1239 | "proc-macro2", 1240 | "quote", 1241 | "syn", 1242 | "wasm-bindgen-backend", 1243 | "wasm-bindgen-shared", 1244 | ] 1245 | 1246 | [[package]] 1247 | name = "wasm-bindgen-shared" 1248 | version = "0.2.100" 1249 | source = "registry+https://github.com/rust-lang/crates.io-index" 1250 | checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" 1251 | dependencies = [ 1252 | "unicode-ident", 1253 | ] 1254 | 1255 | [[package]] 1256 | name = "wayland-backend" 1257 | version = "0.3.10" 1258 | source = "registry+https://github.com/rust-lang/crates.io-index" 1259 | checksum = "fe770181423e5fc79d3e2a7f4410b7799d5aab1de4372853de3c6aa13ca24121" 1260 | dependencies = [ 1261 | "cc", 1262 | "downcast-rs", 1263 | "rustix", 1264 | "scoped-tls", 1265 | "smallvec", 1266 | "wayland-sys", 1267 | ] 1268 | 1269 | [[package]] 1270 | name = "wayland-client" 1271 | version = "0.31.10" 1272 | source = "registry+https://github.com/rust-lang/crates.io-index" 1273 | checksum = "978fa7c67b0847dbd6a9f350ca2569174974cd4082737054dbb7fbb79d7d9a61" 1274 | dependencies = [ 1275 | "bitflags 2.9.0", 1276 | "rustix", 1277 | "wayland-backend", 1278 | "wayland-scanner", 1279 | ] 1280 | 1281 | [[package]] 1282 | name = "wayland-csd-frame" 1283 | version = "0.3.0" 1284 | source = "registry+https://github.com/rust-lang/crates.io-index" 1285 | checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" 1286 | dependencies = [ 1287 | "bitflags 2.9.0", 1288 | "cursor-icon", 1289 | "wayland-backend", 1290 | ] 1291 | 1292 | [[package]] 1293 | name = "wayland-cursor" 1294 | version = "0.31.10" 1295 | source = "registry+https://github.com/rust-lang/crates.io-index" 1296 | checksum = "a65317158dec28d00416cb16705934070aef4f8393353d41126c54264ae0f182" 1297 | dependencies = [ 1298 | "rustix", 1299 | "wayland-client", 1300 | "xcursor", 1301 | ] 1302 | 1303 | [[package]] 1304 | name = "wayland-protocols" 1305 | version = "0.32.8" 1306 | source = "registry+https://github.com/rust-lang/crates.io-index" 1307 | checksum = "779075454e1e9a521794fed15886323ea0feda3f8b0fc1390f5398141310422a" 1308 | dependencies = [ 1309 | "bitflags 2.9.0", 1310 | "wayland-backend", 1311 | "wayland-client", 1312 | "wayland-scanner", 1313 | ] 1314 | 1315 | [[package]] 1316 | name = "wayland-protocols-plasma" 1317 | version = "0.3.8" 1318 | source = "registry+https://github.com/rust-lang/crates.io-index" 1319 | checksum = "4fd38cdad69b56ace413c6bcc1fbf5acc5e2ef4af9d5f8f1f9570c0c83eae175" 1320 | dependencies = [ 1321 | "bitflags 2.9.0", 1322 | "wayland-backend", 1323 | "wayland-client", 1324 | "wayland-protocols", 1325 | "wayland-scanner", 1326 | ] 1327 | 1328 | [[package]] 1329 | name = "wayland-protocols-wlr" 1330 | version = "0.3.8" 1331 | source = "registry+https://github.com/rust-lang/crates.io-index" 1332 | checksum = "1cb6cdc73399c0e06504c437fe3cf886f25568dd5454473d565085b36d6a8bbf" 1333 | dependencies = [ 1334 | "bitflags 2.9.0", 1335 | "wayland-backend", 1336 | "wayland-client", 1337 | "wayland-protocols", 1338 | "wayland-scanner", 1339 | ] 1340 | 1341 | [[package]] 1342 | name = "wayland-scanner" 1343 | version = "0.31.6" 1344 | source = "registry+https://github.com/rust-lang/crates.io-index" 1345 | checksum = "896fdafd5d28145fce7958917d69f2fd44469b1d4e861cb5961bcbeebc6d1484" 1346 | dependencies = [ 1347 | "proc-macro2", 1348 | "quick-xml", 1349 | "quote", 1350 | ] 1351 | 1352 | [[package]] 1353 | name = "wayland-sys" 1354 | version = "0.31.6" 1355 | source = "registry+https://github.com/rust-lang/crates.io-index" 1356 | checksum = "dbcebb399c77d5aa9fa5db874806ee7b4eba4e73650948e8f93963f128896615" 1357 | dependencies = [ 1358 | "dlib", 1359 | "log", 1360 | "once_cell", 1361 | "pkg-config", 1362 | ] 1363 | 1364 | [[package]] 1365 | name = "web-sys" 1366 | version = "0.3.77" 1367 | source = "registry+https://github.com/rust-lang/crates.io-index" 1368 | checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" 1369 | dependencies = [ 1370 | "js-sys", 1371 | "wasm-bindgen", 1372 | ] 1373 | 1374 | [[package]] 1375 | name = "web-time" 1376 | version = "1.1.0" 1377 | source = "registry+https://github.com/rust-lang/crates.io-index" 1378 | checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" 1379 | dependencies = [ 1380 | "js-sys", 1381 | "wasm-bindgen", 1382 | ] 1383 | 1384 | [[package]] 1385 | name = "winapi-util" 1386 | version = "0.1.9" 1387 | source = "registry+https://github.com/rust-lang/crates.io-index" 1388 | checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" 1389 | dependencies = [ 1390 | "windows-sys 0.59.0", 1391 | ] 1392 | 1393 | [[package]] 1394 | name = "windows-sys" 1395 | version = "0.45.0" 1396 | source = "registry+https://github.com/rust-lang/crates.io-index" 1397 | checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" 1398 | dependencies = [ 1399 | "windows-targets 0.42.2", 1400 | ] 1401 | 1402 | [[package]] 1403 | name = "windows-sys" 1404 | version = "0.52.0" 1405 | source = "registry+https://github.com/rust-lang/crates.io-index" 1406 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 1407 | dependencies = [ 1408 | "windows-targets 0.52.6", 1409 | ] 1410 | 1411 | [[package]] 1412 | name = "windows-sys" 1413 | version = "0.59.0" 1414 | source = "registry+https://github.com/rust-lang/crates.io-index" 1415 | checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" 1416 | dependencies = [ 1417 | "windows-targets 0.52.6", 1418 | ] 1419 | 1420 | [[package]] 1421 | name = "windows-targets" 1422 | version = "0.42.2" 1423 | source = "registry+https://github.com/rust-lang/crates.io-index" 1424 | checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" 1425 | dependencies = [ 1426 | "windows_aarch64_gnullvm 0.42.2", 1427 | "windows_aarch64_msvc 0.42.2", 1428 | "windows_i686_gnu 0.42.2", 1429 | "windows_i686_msvc 0.42.2", 1430 | "windows_x86_64_gnu 0.42.2", 1431 | "windows_x86_64_gnullvm 0.42.2", 1432 | "windows_x86_64_msvc 0.42.2", 1433 | ] 1434 | 1435 | [[package]] 1436 | name = "windows-targets" 1437 | version = "0.48.5" 1438 | source = "registry+https://github.com/rust-lang/crates.io-index" 1439 | checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" 1440 | dependencies = [ 1441 | "windows_aarch64_gnullvm 0.48.5", 1442 | "windows_aarch64_msvc 0.48.5", 1443 | "windows_i686_gnu 0.48.5", 1444 | "windows_i686_msvc 0.48.5", 1445 | "windows_x86_64_gnu 0.48.5", 1446 | "windows_x86_64_gnullvm 0.48.5", 1447 | "windows_x86_64_msvc 0.48.5", 1448 | ] 1449 | 1450 | [[package]] 1451 | name = "windows-targets" 1452 | version = "0.52.6" 1453 | source = "registry+https://github.com/rust-lang/crates.io-index" 1454 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 1455 | dependencies = [ 1456 | "windows_aarch64_gnullvm 0.52.6", 1457 | "windows_aarch64_msvc 0.52.6", 1458 | "windows_i686_gnu 0.52.6", 1459 | "windows_i686_gnullvm", 1460 | "windows_i686_msvc 0.52.6", 1461 | "windows_x86_64_gnu 0.52.6", 1462 | "windows_x86_64_gnullvm 0.52.6", 1463 | "windows_x86_64_msvc 0.52.6", 1464 | ] 1465 | 1466 | [[package]] 1467 | name = "windows_aarch64_gnullvm" 1468 | version = "0.42.2" 1469 | source = "registry+https://github.com/rust-lang/crates.io-index" 1470 | checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" 1471 | 1472 | [[package]] 1473 | name = "windows_aarch64_gnullvm" 1474 | version = "0.48.5" 1475 | source = "registry+https://github.com/rust-lang/crates.io-index" 1476 | checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" 1477 | 1478 | [[package]] 1479 | name = "windows_aarch64_gnullvm" 1480 | version = "0.52.6" 1481 | source = "registry+https://github.com/rust-lang/crates.io-index" 1482 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 1483 | 1484 | [[package]] 1485 | name = "windows_aarch64_msvc" 1486 | version = "0.42.2" 1487 | source = "registry+https://github.com/rust-lang/crates.io-index" 1488 | checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" 1489 | 1490 | [[package]] 1491 | name = "windows_aarch64_msvc" 1492 | version = "0.48.5" 1493 | source = "registry+https://github.com/rust-lang/crates.io-index" 1494 | checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" 1495 | 1496 | [[package]] 1497 | name = "windows_aarch64_msvc" 1498 | version = "0.52.6" 1499 | source = "registry+https://github.com/rust-lang/crates.io-index" 1500 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 1501 | 1502 | [[package]] 1503 | name = "windows_i686_gnu" 1504 | version = "0.42.2" 1505 | source = "registry+https://github.com/rust-lang/crates.io-index" 1506 | checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" 1507 | 1508 | [[package]] 1509 | name = "windows_i686_gnu" 1510 | version = "0.48.5" 1511 | source = "registry+https://github.com/rust-lang/crates.io-index" 1512 | checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" 1513 | 1514 | [[package]] 1515 | name = "windows_i686_gnu" 1516 | version = "0.52.6" 1517 | source = "registry+https://github.com/rust-lang/crates.io-index" 1518 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 1519 | 1520 | [[package]] 1521 | name = "windows_i686_gnullvm" 1522 | version = "0.52.6" 1523 | source = "registry+https://github.com/rust-lang/crates.io-index" 1524 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 1525 | 1526 | [[package]] 1527 | name = "windows_i686_msvc" 1528 | version = "0.42.2" 1529 | source = "registry+https://github.com/rust-lang/crates.io-index" 1530 | checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" 1531 | 1532 | [[package]] 1533 | name = "windows_i686_msvc" 1534 | version = "0.48.5" 1535 | source = "registry+https://github.com/rust-lang/crates.io-index" 1536 | checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" 1537 | 1538 | [[package]] 1539 | name = "windows_i686_msvc" 1540 | version = "0.52.6" 1541 | source = "registry+https://github.com/rust-lang/crates.io-index" 1542 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 1543 | 1544 | [[package]] 1545 | name = "windows_x86_64_gnu" 1546 | version = "0.42.2" 1547 | source = "registry+https://github.com/rust-lang/crates.io-index" 1548 | checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" 1549 | 1550 | [[package]] 1551 | name = "windows_x86_64_gnu" 1552 | version = "0.48.5" 1553 | source = "registry+https://github.com/rust-lang/crates.io-index" 1554 | checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" 1555 | 1556 | [[package]] 1557 | name = "windows_x86_64_gnu" 1558 | version = "0.52.6" 1559 | source = "registry+https://github.com/rust-lang/crates.io-index" 1560 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 1561 | 1562 | [[package]] 1563 | name = "windows_x86_64_gnullvm" 1564 | version = "0.42.2" 1565 | source = "registry+https://github.com/rust-lang/crates.io-index" 1566 | checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" 1567 | 1568 | [[package]] 1569 | name = "windows_x86_64_gnullvm" 1570 | version = "0.48.5" 1571 | source = "registry+https://github.com/rust-lang/crates.io-index" 1572 | checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" 1573 | 1574 | [[package]] 1575 | name = "windows_x86_64_gnullvm" 1576 | version = "0.52.6" 1577 | source = "registry+https://github.com/rust-lang/crates.io-index" 1578 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 1579 | 1580 | [[package]] 1581 | name = "windows_x86_64_msvc" 1582 | version = "0.42.2" 1583 | source = "registry+https://github.com/rust-lang/crates.io-index" 1584 | checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" 1585 | 1586 | [[package]] 1587 | name = "windows_x86_64_msvc" 1588 | version = "0.48.5" 1589 | source = "registry+https://github.com/rust-lang/crates.io-index" 1590 | checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" 1591 | 1592 | [[package]] 1593 | name = "windows_x86_64_msvc" 1594 | version = "0.52.6" 1595 | source = "registry+https://github.com/rust-lang/crates.io-index" 1596 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 1597 | 1598 | [[package]] 1599 | name = "winit" 1600 | version = "0.30.10" 1601 | source = "registry+https://github.com/rust-lang/crates.io-index" 1602 | checksum = "b0d05bd8908e14618c9609471db04007e644fd9cce6529756046cfc577f9155e" 1603 | dependencies = [ 1604 | "ahash", 1605 | "android-activity", 1606 | "atomic-waker", 1607 | "bitflags 2.9.0", 1608 | "block2", 1609 | "bytemuck", 1610 | "calloop", 1611 | "cfg_aliases", 1612 | "concurrent-queue", 1613 | "core-foundation", 1614 | "core-graphics", 1615 | "cursor-icon", 1616 | "dpi", 1617 | "js-sys", 1618 | "libc", 1619 | "memmap2", 1620 | "ndk", 1621 | "objc2", 1622 | "objc2-app-kit", 1623 | "objc2-foundation", 1624 | "objc2-ui-kit", 1625 | "orbclient", 1626 | "percent-encoding", 1627 | "pin-project", 1628 | "raw-window-handle", 1629 | "redox_syscall 0.4.1", 1630 | "rustix", 1631 | "sctk-adwaita", 1632 | "smithay-client-toolkit", 1633 | "smol_str", 1634 | "tracing", 1635 | "unicode-segmentation", 1636 | "wasm-bindgen", 1637 | "wasm-bindgen-futures", 1638 | "wayland-backend", 1639 | "wayland-client", 1640 | "wayland-protocols", 1641 | "wayland-protocols-plasma", 1642 | "web-sys", 1643 | "web-time", 1644 | "windows-sys 0.52.0", 1645 | "x11-dl", 1646 | "x11rb", 1647 | "xkbcommon-dl", 1648 | ] 1649 | 1650 | [[package]] 1651 | name = "winnow" 1652 | version = "0.7.10" 1653 | source = "registry+https://github.com/rust-lang/crates.io-index" 1654 | checksum = "c06928c8748d81b05c9be96aad92e1b6ff01833332f281e8cfca3be4b35fc9ec" 1655 | dependencies = [ 1656 | "memchr", 1657 | ] 1658 | 1659 | [[package]] 1660 | name = "wit-bindgen-rt" 1661 | version = "0.39.0" 1662 | source = "registry+https://github.com/rust-lang/crates.io-index" 1663 | checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" 1664 | dependencies = [ 1665 | "bitflags 2.9.0", 1666 | ] 1667 | 1668 | [[package]] 1669 | name = "x11-dl" 1670 | version = "2.21.0" 1671 | source = "registry+https://github.com/rust-lang/crates.io-index" 1672 | checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" 1673 | dependencies = [ 1674 | "libc", 1675 | "once_cell", 1676 | "pkg-config", 1677 | ] 1678 | 1679 | [[package]] 1680 | name = "x11rb" 1681 | version = "0.13.1" 1682 | source = "registry+https://github.com/rust-lang/crates.io-index" 1683 | checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12" 1684 | dependencies = [ 1685 | "as-raw-xcb-connection", 1686 | "gethostname", 1687 | "libc", 1688 | "libloading", 1689 | "once_cell", 1690 | "rustix", 1691 | "x11rb-protocol", 1692 | ] 1693 | 1694 | [[package]] 1695 | name = "x11rb-protocol" 1696 | version = "0.13.1" 1697 | source = "registry+https://github.com/rust-lang/crates.io-index" 1698 | checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d" 1699 | 1700 | [[package]] 1701 | name = "xcursor" 1702 | version = "0.3.8" 1703 | source = "registry+https://github.com/rust-lang/crates.io-index" 1704 | checksum = "0ef33da6b1660b4ddbfb3aef0ade110c8b8a781a3b6382fa5f2b5b040fd55f61" 1705 | 1706 | [[package]] 1707 | name = "xkbcommon-dl" 1708 | version = "0.4.2" 1709 | source = "registry+https://github.com/rust-lang/crates.io-index" 1710 | checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" 1711 | dependencies = [ 1712 | "bitflags 2.9.0", 1713 | "dlib", 1714 | "log", 1715 | "once_cell", 1716 | "xkeysym", 1717 | ] 1718 | 1719 | [[package]] 1720 | name = "xkeysym" 1721 | version = "0.2.1" 1722 | source = "registry+https://github.com/rust-lang/crates.io-index" 1723 | checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" 1724 | 1725 | [[package]] 1726 | name = "zerocopy" 1727 | version = "0.7.35" 1728 | source = "registry+https://github.com/rust-lang/crates.io-index" 1729 | checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" 1730 | dependencies = [ 1731 | "zerocopy-derive", 1732 | ] 1733 | 1734 | [[package]] 1735 | name = "zerocopy-derive" 1736 | version = "0.7.35" 1737 | source = "registry+https://github.com/rust-lang/crates.io-index" 1738 | checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" 1739 | dependencies = [ 1740 | "proc-macro2", 1741 | "quote", 1742 | "syn", 1743 | ] 1744 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | resolver = "2" 3 | members = ["ui-events", "ui-events-winit", "ui-theme", "examples/simple"] 4 | 5 | [workspace.package] 6 | # UI Events version, also used by other packages which want to mimic UI Events' version. 7 | # 8 | # NOTE: When bumping this, remember to also bump the aforementioned other packages' 9 | # version in the dependencies section at the bottom of this file. 10 | version = "0.1.0" 11 | 12 | edition = "2021" 13 | # Keep in sync with RUST_MIN_VER in .github/workflows/ci.yml, with the relevant README.md files 14 | # and with the MSRV in the `Unreleased` section of CHANGELOG.md. 15 | rust-version = "1.73" 16 | license = "Apache-2.0 OR MIT" 17 | repository = "https://github.com/endoli/ui-events" 18 | 19 | [workspace.lints] 20 | rust.unsafe_code = "deny" 21 | 22 | # LINEBENDER LINT SET - Cargo.toml - v6 23 | # See https://linebender.org/wiki/canonical-lints/ 24 | rust.keyword_idents_2024 = "forbid" 25 | rust.non_ascii_idents = "forbid" 26 | rust.non_local_definitions = "forbid" 27 | rust.unsafe_op_in_unsafe_fn = "forbid" 28 | 29 | rust.elided_lifetimes_in_paths = "warn" 30 | rust.missing_debug_implementations = "warn" 31 | rust.missing_docs = "warn" 32 | rust.trivial_numeric_casts = "warn" 33 | rust.unexpected_cfgs = "warn" 34 | rust.unnameable_types = "warn" 35 | rust.unreachable_pub = "warn" 36 | rust.unused_import_braces = "warn" 37 | rust.unused_lifetimes = "warn" 38 | rust.unused_macro_rules = "warn" 39 | 40 | clippy.too_many_arguments = "allow" 41 | 42 | clippy.allow_attributes_without_reason = "warn" 43 | clippy.cast_possible_truncation = "warn" 44 | clippy.collection_is_never_read = "warn" 45 | clippy.dbg_macro = "warn" 46 | clippy.debug_assert_with_mut_call = "warn" 47 | clippy.doc_markdown = "warn" 48 | clippy.fn_to_numeric_cast_any = "warn" 49 | clippy.infinite_loop = "warn" 50 | clippy.large_stack_arrays = "warn" 51 | clippy.mismatching_type_param_order = "warn" 52 | clippy.missing_assert_message = "warn" 53 | clippy.missing_fields_in_debug = "warn" 54 | clippy.same_functions_in_if_condition = "warn" 55 | clippy.semicolon_if_nothing_returned = "warn" 56 | clippy.should_panic_without_expect = "warn" 57 | clippy.todo = "warn" 58 | clippy.unseparated_literal_suffix = "warn" 59 | clippy.use_self = "warn" 60 | 61 | clippy.cargo_common_metadata = "warn" 62 | clippy.negative_feature_names = "warn" 63 | clippy.redundant_feature_names = "warn" 64 | clippy.wildcard_dependencies = "warn" 65 | # END LINEBENDER LINT SET 66 | 67 | [workspace.dependencies] 68 | dpi = { version = "0.1.2", default-features = false } 69 | ui-events = { version = "0.1.0", path = "ui-events", default-features = false } 70 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # UI Events 4 | 5 | A library for working with UI events and input types. 6 | 7 | [![Linebender Zulip, #general channel](https://img.shields.io/badge/Linebender-%23general-blue?logo=Zulip)](https://xi.zulipchat.com/#narrow/channel/147921-general) 8 | [![dependency status](https://deps.rs/repo/github/endoli/ui-events/status.svg)](https://deps.rs/repo/github/endoli/ui-events) 9 | [![Apache 2.0 or MIT license.](https://img.shields.io/badge/license-Apache--2.0_OR_MIT-blue.svg)](#license) 10 | [![Build status](https://github.com/endoli/ui-events/workflows/CI/badge.svg)](https://github.com/endoli/ui-events/actions) 11 | [![Crates.io](https://img.shields.io/crates/v/ui-events.svg)](https://crates.io/crates/ui-events) 12 | [![Docs](https://docs.rs/ui-events/badge.svg)](https://docs.rs/ui-events) 13 | 14 |
15 | 16 | The UI Events library provides functionality for working with UI events and input types. 17 | This library follows and is inspired by the relevant W3C specifications. 18 | 19 | ## Minimum supported Rust Version (MSRV) 20 | 21 | This version of UI Events has been verified to compile with **Rust 1.73** and later. 22 | 23 | Future versions of UI Events might increase the Rust version requirement. 24 | It will not be treated as a breaking change and as such can even happen with small patch releases. 25 | 26 |
27 | Click here if compiling fails. 28 | 29 | As time has passed, some of UI Events' dependencies could have released versions with a higher Rust requirement. 30 | If you encounter a compilation issue due to a dependency and don't want to upgrade your Rust toolchain, then you could downgrade the dependency. 31 | 32 | ```sh 33 | # Use the problematic dependency's name and version 34 | cargo update -p package_name --precise 0.1.1 35 | ``` 36 |
37 | 38 | ## Community 39 | 40 | [![Linebender Zulip](https://img.shields.io/badge/Xi%20Zulip-%23general-blue?logo=Zulip)](https://xi.zulipchat.com/#narrow/channel/147921-general) 41 | 42 | Discussion of UI Events development happens in the [Linebender Zulip](https://xi.zulipchat.com/), specifically the [#general channel](https://xi.zulipchat.com/#narrow/channel/147921-general). 43 | All public content can be read without logging in. 44 | 45 | ## License 46 | 47 | Licensed under either of 48 | 49 | - Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or ) 50 | - MIT license ([LICENSE-MIT](LICENSE-MIT) or ) 51 | 52 | at your option. 53 | 54 | ## Contribution 55 | 56 | Contributions are welcome by pull request. The [Rust code of conduct] applies. 57 | Please feel free to add your name to the [AUTHORS] file in any substantive pull request. 58 | 59 | Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be licensed as above, without any additional terms or conditions. 60 | 61 | [Rust Code of Conduct]: https://www.rust-lang.org/policies/code-of-conduct 62 | [AUTHORS]: ./AUTHORS 63 | -------------------------------------------------------------------------------- /examples/simple/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "simple" 3 | version.workspace = true 4 | edition.workspace = true 5 | rust-version.workspace = true 6 | license.workspace = true 7 | repository.workspace = true 8 | publish = false 9 | 10 | [dependencies] 11 | anyhow = "1.0.98" 12 | ui-events.workspace = true 13 | 14 | [lints] 15 | workspace = true 16 | -------------------------------------------------------------------------------- /examples/simple/src/main.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2025 the UI Events Authors 2 | // SPDX-License-Identifier: Apache-2.0 OR MIT 3 | 4 | //! Simple example. 5 | 6 | use anyhow::Result; 7 | 8 | fn main() -> Result<()> { 9 | // TODO: Implement 10 | Ok(()) 11 | } 12 | -------------------------------------------------------------------------------- /ui-events-winit/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 8 | 9 | # Changelog 10 | 11 | The latest published UI Events Winit release is [0.1.0](#010-2025-05-08) which was released on 2025-05-08. 12 | You can find its changes [documented below](#010-2025-05-08). 13 | 14 | ## [Unreleased] 15 | 16 | This release has an [MSRV][] of 1.73. 17 | 18 | ## [0.1.0][] - 2025-05-08 19 | 20 | This release has an [MSRV][] of 1.73. 21 | 22 | This is the initial release. 23 | 24 | [Unreleased]: https://github.com/endoli/ui-events/compare/v0.1.0...HEAD 25 | [0.1.0]: https://github.com/linebender/color/releases/tag/v0.1.0 26 | 27 | [MSRV]: README.md#minimum-supported-rust-version-msrv 28 | -------------------------------------------------------------------------------- /ui-events-winit/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ui-events-winit" 3 | version.workspace = true 4 | license.workspace = true 5 | edition.workspace = true 6 | description = "A library for bridging ui-events and winit" 7 | keywords = ["windowing", "input", "pointer"] 8 | categories = ["graphics", "gui"] 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | 12 | [package.metadata.docs.rs] 13 | all-features = true 14 | # There are no platform specific docs. 15 | default-target = "x86_64-unknown-linux-gnu" 16 | targets = [] 17 | 18 | [features] 19 | default = ["std"] 20 | std = [] 21 | 22 | [dependencies] 23 | ui-events = { workspace = true, features = ["std"] } 24 | winit = "0.30.10" 25 | 26 | [lints] 27 | workspace = true 28 | -------------------------------------------------------------------------------- /ui-events-winit/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | -------------------------------------------------------------------------------- /ui-events-winit/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /ui-events-winit/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # UI Events for Winit 4 | 5 | A library for bridging [`winit`] events into the [`ui-events`] model. 6 | 7 | [![Linebender Zulip, #general channel](https://img.shields.io/badge/Linebender-%23general-blue?logo=Zulip)](https://xi.zulipchat.com/#narrow/channel/147921-general) 8 | [![dependency status](https://deps.rs/repo/github/endoli/ui-events/status.svg)](https://deps.rs/repo/github/endoli/ui-events) 9 | [![Apache 2.0 or MIT license.](https://img.shields.io/badge/license-Apache--2.0_OR_MIT-blue.svg)](#license) 10 | [![Build status](https://github.com/endoli/ui-events/workflows/CI/badge.svg)](https://github.com/endoli/ui-events/actions) 11 | [![Crates.io](https://img.shields.io/crates/v/ui-events-winit.svg)](https://crates.io/crates/ui-events-winit) 12 | [![Docs](https://docs.rs/ui-events-winit/badge.svg)](https://docs.rs/ui-events-winit) 13 | 14 |
15 | 16 | 20 | 21 | 23 | [`ui-events`]: https://docs.rs/ui-events/ 24 | [`winit`]: https://docs.rs/winit/ 25 | [`WindowEventReducer`]: https://docs.rs/ui-events-winit/latest/ui_events_winit/struct.WindowEventReducer.html 26 | 27 | 28 | This crate bridges [`winit`]'s native input events (mouse, touch, keyboard, etc.) 29 | into the [`ui-events`] model. 30 | 31 | The primary entry point is [`WindowEventReducer`]. 32 | 33 | [`ui-events`]: https://docs.rs/ui-events/ 34 | 35 | 36 | 37 | ## Minimum supported Rust Version (MSRV) 38 | 39 | This version of UI Events for Winit has been verified to compile with **Rust 1.81** and later. 40 | 41 | Future versions of UI Events for Winit might increase the Rust version requirement. 42 | It will not be treated as a breaking change and as such can even happen with small patch releases. 43 | 44 |
45 | Click here if compiling fails. 46 | 47 | As time has passed, some of UI Events for Winit's dependencies could have released versions with a higher Rust requirement. 48 | If you encounter a compilation issue due to a dependency and don't want to upgrade your Rust toolchain, then you could downgrade the dependency. 49 | 50 | ```sh 51 | # Use the problematic dependency's name and version 52 | cargo update -p package_name --precise 0.1.1 53 | ``` 54 | 55 |
56 | 57 | ## Community 58 | 59 | [![Linebender Zulip](https://img.shields.io/badge/Xi%20Zulip-%23general-blue?logo=Zulip)](https://xi.zulipchat.com/#narrow/channel/147921-general) 60 | 61 | Discussion of UI Events for Winit development happens in the [Linebender Zulip](https://xi.zulipchat.com/), specifically the [#general channel](https://xi.zulipchat.com/#narrow/channel/147921-general). 62 | All public content can be read without logging in. 63 | 64 | ## License 65 | 66 | Licensed under either of 67 | 68 | - Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or ) 69 | - MIT license ([LICENSE-MIT](LICENSE-MIT) or ) 70 | 71 | at your option. 72 | 73 | ## Contribution 74 | 75 | Contributions are welcome by pull request. The [Rust code of conduct] applies. 76 | Please feel free to add your name to the [AUTHORS] file in any substantive pull request. 77 | 78 | Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be licensed as above, without any additional terms or conditions. 79 | 80 | [Rust Code of Conduct]: https://www.rust-lang.org/policies/code-of-conduct 81 | [AUTHORS]: ./AUTHORS 82 | -------------------------------------------------------------------------------- /ui-events-winit/src/keyboard.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2025 the UI Events Authors 2 | // SPDX-License-Identifier: Apache-2.0 OR MIT 3 | 4 | //! Support routines for converting keyboard data from [`winit`] 5 | 6 | use ui_events::keyboard::{Code, Key, KeyState, KeyboardEvent, Location, Modifiers, NamedKey}; 7 | use winit::keyboard::{KeyLocation, ModifiersState}; 8 | 9 | extern crate alloc; 10 | use alloc::string::String; 11 | 12 | /// Convert a [`winit::event::KeyEvent`] and [`winit::keyboard::ModifiersState`] to a [`KeyboardEvent`]. 13 | pub fn from_winit_keyboard_event( 14 | winit_event: winit::event::KeyEvent, 15 | mods: ModifiersState, 16 | ) -> KeyboardEvent { 17 | KeyboardEvent { 18 | key: from_winit_key(winit_event.logical_key), 19 | code: from_winit_code(winit_event.physical_key), 20 | modifiers: from_winit_modifier_state(mods), 21 | location: from_winit_location(winit_event.location), 22 | is_composing: false, 23 | repeat: winit_event.repeat, 24 | state: match winit_event.state { 25 | winit::event::ElementState::Pressed => KeyState::Down, 26 | winit::event::ElementState::Released => KeyState::Up, 27 | }, 28 | } 29 | } 30 | 31 | /// Convert a [`winit::keyboard::KeyLocation`] to a [`ui_events::keyboard::Location`]. 32 | pub fn from_winit_location(winit_location: KeyLocation) -> Location { 33 | match winit_location { 34 | KeyLocation::Standard => Location::Standard, 35 | KeyLocation::Left => Location::Left, 36 | KeyLocation::Right => Location::Right, 37 | KeyLocation::Numpad => Location::Numpad, 38 | } 39 | } 40 | 41 | /// Convert a [`winit::keyboard::ModifiersState`] to a [`ui_events::keyboard::Modifiers`]. 42 | pub fn from_winit_modifier_state(modifiers_state: ModifiersState) -> Modifiers { 43 | let mut modifiers = Modifiers::default(); 44 | if modifiers_state.control_key() { 45 | modifiers.insert(Modifiers::CONTROL); 46 | } 47 | if modifiers_state.alt_key() { 48 | modifiers.insert(Modifiers::ALT); 49 | } 50 | if modifiers_state.shift_key() { 51 | modifiers.insert(Modifiers::SHIFT); 52 | } 53 | if modifiers_state.super_key() { 54 | modifiers.insert(Modifiers::META); 55 | } 56 | modifiers 57 | } 58 | 59 | /// Convert a [`winit::keyboard::Key`] to a [`ui_events::keyboard::Key`]. 60 | pub fn from_winit_key(winit_key: winit::keyboard::Key) -> Key { 61 | use winit::keyboard::Key as WK; 62 | use winit::keyboard::NamedKey as WNK; 63 | match winit_key { 64 | WK::Character(c) => Key::Character(c.to_string()), 65 | WK::Unidentified(_) => Key::Named(NamedKey::Unidentified), 66 | WK::Dead(_) => Key::Named(NamedKey::Dead), 67 | WK::Named(WNK::Space) => Key::Character(String::from(" ")), 68 | WK::Named(k) => Key::Named(match k { 69 | WNK::Alt => NamedKey::Alt, 70 | WNK::AltGraph => NamedKey::AltGraph, 71 | WNK::CapsLock => NamedKey::CapsLock, 72 | WNK::Control => NamedKey::Control, 73 | WNK::Fn => NamedKey::Fn, 74 | WNK::FnLock => NamedKey::FnLock, 75 | WNK::NumLock => NamedKey::NumLock, 76 | WNK::ScrollLock => NamedKey::ScrollLock, 77 | WNK::Shift => NamedKey::Shift, 78 | WNK::Symbol => NamedKey::Symbol, 79 | WNK::SymbolLock => NamedKey::SymbolLock, 80 | #[allow(deprecated)] 81 | WNK::Meta => NamedKey::Super, 82 | #[allow(deprecated)] 83 | WNK::Hyper => NamedKey::Hyper, 84 | WNK::Super => NamedKey::Meta, 85 | WNK::Enter => NamedKey::Enter, 86 | WNK::Tab => NamedKey::Tab, 87 | WNK::ArrowDown => NamedKey::ArrowDown, 88 | WNK::ArrowLeft => NamedKey::ArrowLeft, 89 | WNK::ArrowRight => NamedKey::ArrowRight, 90 | WNK::ArrowUp => NamedKey::ArrowUp, 91 | WNK::End => NamedKey::End, 92 | WNK::Home => NamedKey::Home, 93 | WNK::PageDown => NamedKey::PageDown, 94 | WNK::PageUp => NamedKey::PageUp, 95 | WNK::Backspace => NamedKey::Backspace, 96 | WNK::Clear => NamedKey::Clear, 97 | WNK::Copy => NamedKey::Copy, 98 | WNK::CrSel => NamedKey::CrSel, 99 | WNK::Cut => NamedKey::Cut, 100 | WNK::Delete => NamedKey::Delete, 101 | WNK::EraseEof => NamedKey::EraseEof, 102 | WNK::ExSel => NamedKey::ExSel, 103 | WNK::Insert => NamedKey::Insert, 104 | WNK::Paste => NamedKey::Paste, 105 | WNK::Redo => NamedKey::Redo, 106 | WNK::Undo => NamedKey::Undo, 107 | WNK::Accept => NamedKey::Accept, 108 | WNK::Again => NamedKey::Again, 109 | WNK::Attn => NamedKey::Attn, 110 | WNK::Cancel => NamedKey::Cancel, 111 | WNK::ContextMenu => NamedKey::ContextMenu, 112 | WNK::Escape => NamedKey::Escape, 113 | WNK::Execute => NamedKey::Execute, 114 | WNK::Find => NamedKey::Find, 115 | WNK::Help => NamedKey::Help, 116 | WNK::Pause => NamedKey::Pause, 117 | WNK::Play => NamedKey::Play, 118 | WNK::Props => NamedKey::Props, 119 | WNK::Select => NamedKey::Select, 120 | WNK::ZoomIn => NamedKey::ZoomIn, 121 | WNK::ZoomOut => NamedKey::ZoomOut, 122 | WNK::BrightnessDown => NamedKey::BrightnessDown, 123 | WNK::BrightnessUp => NamedKey::BrightnessUp, 124 | WNK::Eject => NamedKey::Eject, 125 | WNK::LogOff => NamedKey::LogOff, 126 | WNK::Power => NamedKey::Power, 127 | WNK::PowerOff => NamedKey::PowerOff, 128 | WNK::PrintScreen => NamedKey::PrintScreen, 129 | WNK::Hibernate => NamedKey::Hibernate, 130 | WNK::Standby => NamedKey::Standby, 131 | WNK::WakeUp => NamedKey::WakeUp, 132 | WNK::AllCandidates => NamedKey::AllCandidates, 133 | WNK::Alphanumeric => NamedKey::Alphanumeric, 134 | WNK::CodeInput => NamedKey::CodeInput, 135 | WNK::Compose => NamedKey::Compose, 136 | WNK::Convert => NamedKey::Convert, 137 | WNK::FinalMode => NamedKey::FinalMode, 138 | WNK::GroupFirst => NamedKey::GroupFirst, 139 | WNK::GroupLast => NamedKey::GroupLast, 140 | WNK::GroupNext => NamedKey::GroupNext, 141 | WNK::GroupPrevious => NamedKey::GroupPrevious, 142 | WNK::ModeChange => NamedKey::ModeChange, 143 | WNK::NextCandidate => NamedKey::NextCandidate, 144 | WNK::NonConvert => NamedKey::NonConvert, 145 | WNK::PreviousCandidate => NamedKey::PreviousCandidate, 146 | WNK::Process => NamedKey::Process, 147 | WNK::SingleCandidate => NamedKey::SingleCandidate, 148 | WNK::HangulMode => NamedKey::HangulMode, 149 | WNK::HanjaMode => NamedKey::HanjaMode, 150 | WNK::JunjaMode => NamedKey::JunjaMode, 151 | WNK::Eisu => NamedKey::Eisu, 152 | WNK::Hankaku => NamedKey::Hankaku, 153 | WNK::Hiragana => NamedKey::Hiragana, 154 | WNK::HiraganaKatakana => NamedKey::HiraganaKatakana, 155 | WNK::KanaMode => NamedKey::KanaMode, 156 | WNK::KanjiMode => NamedKey::KanjiMode, 157 | WNK::Katakana => NamedKey::Katakana, 158 | WNK::Romaji => NamedKey::Romaji, 159 | WNK::Zenkaku => NamedKey::Zenkaku, 160 | WNK::ZenkakuHankaku => NamedKey::ZenkakuHankaku, 161 | WNK::Soft1 => NamedKey::Soft1, 162 | WNK::Soft2 => NamedKey::Soft2, 163 | WNK::Soft3 => NamedKey::Soft3, 164 | WNK::Soft4 => NamedKey::Soft4, 165 | WNK::ChannelDown => NamedKey::ChannelDown, 166 | WNK::ChannelUp => NamedKey::ChannelUp, 167 | WNK::Close => NamedKey::Close, 168 | WNK::MailForward => NamedKey::MailForward, 169 | WNK::MailReply => NamedKey::MailReply, 170 | WNK::MailSend => NamedKey::MailSend, 171 | WNK::MediaClose => NamedKey::MediaClose, 172 | WNK::MediaFastForward => NamedKey::MediaFastForward, 173 | WNK::MediaPause => NamedKey::MediaPause, 174 | WNK::MediaPlay => NamedKey::MediaPlay, 175 | WNK::MediaPlayPause => NamedKey::MediaPlayPause, 176 | WNK::MediaRecord => NamedKey::MediaRecord, 177 | WNK::MediaRewind => NamedKey::MediaRewind, 178 | WNK::MediaStop => NamedKey::MediaStop, 179 | WNK::MediaTrackNext => NamedKey::MediaTrackNext, 180 | WNK::MediaTrackPrevious => NamedKey::MediaTrackPrevious, 181 | WNK::New => NamedKey::New, 182 | WNK::Open => NamedKey::Open, 183 | WNK::Print => NamedKey::Print, 184 | WNK::Save => NamedKey::Save, 185 | WNK::SpellCheck => NamedKey::SpellCheck, 186 | WNK::Key11 => NamedKey::Key11, 187 | WNK::Key12 => NamedKey::Key12, 188 | WNK::AudioBalanceLeft => NamedKey::AudioBalanceLeft, 189 | WNK::AudioBalanceRight => NamedKey::AudioBalanceRight, 190 | WNK::AudioBassBoostDown => NamedKey::AudioBassBoostDown, 191 | WNK::AudioBassBoostToggle => NamedKey::AudioBassBoostToggle, 192 | WNK::AudioBassBoostUp => NamedKey::AudioBassBoostUp, 193 | WNK::AudioFaderFront => NamedKey::AudioFaderFront, 194 | WNK::AudioFaderRear => NamedKey::AudioFaderRear, 195 | WNK::AudioSurroundModeNext => NamedKey::AudioSurroundModeNext, 196 | WNK::AudioTrebleDown => NamedKey::AudioTrebleDown, 197 | WNK::AudioTrebleUp => NamedKey::AudioTrebleUp, 198 | WNK::AudioVolumeDown => NamedKey::AudioVolumeDown, 199 | WNK::AudioVolumeUp => NamedKey::AudioVolumeUp, 200 | WNK::AudioVolumeMute => NamedKey::AudioVolumeMute, 201 | WNK::MicrophoneToggle => NamedKey::MicrophoneToggle, 202 | WNK::MicrophoneVolumeDown => NamedKey::MicrophoneVolumeDown, 203 | WNK::MicrophoneVolumeUp => NamedKey::MicrophoneVolumeUp, 204 | WNK::MicrophoneVolumeMute => NamedKey::MicrophoneVolumeMute, 205 | WNK::SpeechCorrectionList => NamedKey::SpeechCorrectionList, 206 | WNK::SpeechInputToggle => NamedKey::SpeechInputToggle, 207 | WNK::LaunchApplication1 => NamedKey::LaunchApplication1, 208 | WNK::LaunchApplication2 => NamedKey::LaunchApplication2, 209 | WNK::LaunchCalendar => NamedKey::LaunchCalendar, 210 | WNK::LaunchContacts => NamedKey::LaunchContacts, 211 | WNK::LaunchMail => NamedKey::LaunchMail, 212 | WNK::LaunchMediaPlayer => NamedKey::LaunchMediaPlayer, 213 | WNK::LaunchMusicPlayer => NamedKey::LaunchMusicPlayer, 214 | WNK::LaunchPhone => NamedKey::LaunchPhone, 215 | WNK::LaunchScreenSaver => NamedKey::LaunchScreenSaver, 216 | WNK::LaunchSpreadsheet => NamedKey::LaunchSpreadsheet, 217 | WNK::LaunchWebBrowser => NamedKey::LaunchWebBrowser, 218 | WNK::LaunchWebCam => NamedKey::LaunchWebCam, 219 | WNK::LaunchWordProcessor => NamedKey::LaunchWordProcessor, 220 | WNK::BrowserBack => NamedKey::BrowserBack, 221 | WNK::BrowserFavorites => NamedKey::BrowserFavorites, 222 | WNK::BrowserForward => NamedKey::BrowserForward, 223 | WNK::BrowserHome => NamedKey::BrowserHome, 224 | WNK::BrowserRefresh => NamedKey::BrowserRefresh, 225 | WNK::BrowserSearch => NamedKey::BrowserSearch, 226 | WNK::BrowserStop => NamedKey::BrowserStop, 227 | WNK::AppSwitch => NamedKey::AppSwitch, 228 | WNK::Call => NamedKey::Call, 229 | WNK::Camera => NamedKey::Camera, 230 | WNK::CameraFocus => NamedKey::CameraFocus, 231 | WNK::EndCall => NamedKey::EndCall, 232 | WNK::GoBack => NamedKey::GoBack, 233 | WNK::GoHome => NamedKey::GoHome, 234 | WNK::HeadsetHook => NamedKey::HeadsetHook, 235 | WNK::LastNumberRedial => NamedKey::LastNumberRedial, 236 | WNK::Notification => NamedKey::Notification, 237 | WNK::MannerMode => NamedKey::MannerMode, 238 | WNK::VoiceDial => NamedKey::VoiceDial, 239 | WNK::TV => NamedKey::TV, 240 | WNK::TV3DMode => NamedKey::TV3DMode, 241 | WNK::TVAntennaCable => NamedKey::TVAntennaCable, 242 | WNK::TVAudioDescription => NamedKey::TVAudioDescription, 243 | WNK::TVAudioDescriptionMixDown => NamedKey::TVAudioDescriptionMixDown, 244 | WNK::TVAudioDescriptionMixUp => NamedKey::TVAudioDescriptionMixUp, 245 | WNK::TVContentsMenu => NamedKey::TVContentsMenu, 246 | WNK::TVDataService => NamedKey::TVDataService, 247 | WNK::TVInput => NamedKey::TVInput, 248 | WNK::TVInputComponent1 => NamedKey::TVInputComponent1, 249 | WNK::TVInputComponent2 => NamedKey::TVInputComponent2, 250 | WNK::TVInputComposite1 => NamedKey::TVInputComposite1, 251 | WNK::TVInputComposite2 => NamedKey::TVInputComposite2, 252 | WNK::TVInputHDMI1 => NamedKey::TVInputHDMI1, 253 | WNK::TVInputHDMI2 => NamedKey::TVInputHDMI2, 254 | WNK::TVInputHDMI3 => NamedKey::TVInputHDMI3, 255 | WNK::TVInputHDMI4 => NamedKey::TVInputHDMI4, 256 | WNK::TVInputVGA1 => NamedKey::TVInputVGA1, 257 | WNK::TVMediaContext => NamedKey::TVMediaContext, 258 | WNK::TVNetwork => NamedKey::TVNetwork, 259 | WNK::TVNumberEntry => NamedKey::TVNumberEntry, 260 | WNK::TVPower => NamedKey::TVPower, 261 | WNK::TVRadioService => NamedKey::TVRadioService, 262 | WNK::TVSatellite => NamedKey::TVSatellite, 263 | WNK::TVSatelliteBS => NamedKey::TVSatelliteBS, 264 | WNK::TVSatelliteCS => NamedKey::TVSatelliteCS, 265 | WNK::TVSatelliteToggle => NamedKey::TVSatelliteToggle, 266 | WNK::TVTerrestrialAnalog => NamedKey::TVTerrestrialAnalog, 267 | WNK::TVTerrestrialDigital => NamedKey::TVTerrestrialDigital, 268 | WNK::TVTimer => NamedKey::TVTimer, 269 | WNK::AVRInput => NamedKey::AVRInput, 270 | WNK::AVRPower => NamedKey::AVRPower, 271 | WNK::ColorF0Red => NamedKey::ColorF0Red, 272 | WNK::ColorF1Green => NamedKey::ColorF1Green, 273 | WNK::ColorF2Yellow => NamedKey::ColorF2Yellow, 274 | WNK::ColorF3Blue => NamedKey::ColorF3Blue, 275 | WNK::ColorF4Grey => NamedKey::ColorF4Grey, 276 | WNK::ColorF5Brown => NamedKey::ColorF5Brown, 277 | WNK::ClosedCaptionToggle => NamedKey::ClosedCaptionToggle, 278 | WNK::Dimmer => NamedKey::Dimmer, 279 | WNK::DisplaySwap => NamedKey::DisplaySwap, 280 | WNK::DVR => NamedKey::DVR, 281 | WNK::Exit => NamedKey::Exit, 282 | WNK::FavoriteClear0 => NamedKey::FavoriteClear0, 283 | WNK::FavoriteClear1 => NamedKey::FavoriteClear1, 284 | WNK::FavoriteClear2 => NamedKey::FavoriteClear2, 285 | WNK::FavoriteClear3 => NamedKey::FavoriteClear3, 286 | WNK::FavoriteRecall0 => NamedKey::FavoriteRecall0, 287 | WNK::FavoriteRecall1 => NamedKey::FavoriteRecall1, 288 | WNK::FavoriteRecall2 => NamedKey::FavoriteRecall2, 289 | WNK::FavoriteRecall3 => NamedKey::FavoriteRecall3, 290 | WNK::FavoriteStore0 => NamedKey::FavoriteStore0, 291 | WNK::FavoriteStore1 => NamedKey::FavoriteStore1, 292 | WNK::FavoriteStore2 => NamedKey::FavoriteStore2, 293 | WNK::FavoriteStore3 => NamedKey::FavoriteStore3, 294 | WNK::Guide => NamedKey::Guide, 295 | WNK::GuideNextDay => NamedKey::GuideNextDay, 296 | WNK::GuidePreviousDay => NamedKey::GuidePreviousDay, 297 | WNK::Info => NamedKey::Info, 298 | WNK::InstantReplay => NamedKey::InstantReplay, 299 | WNK::Link => NamedKey::Link, 300 | WNK::ListProgram => NamedKey::ListProgram, 301 | WNK::LiveContent => NamedKey::LiveContent, 302 | WNK::Lock => NamedKey::Lock, 303 | WNK::MediaApps => NamedKey::MediaApps, 304 | WNK::MediaAudioTrack => NamedKey::MediaAudioTrack, 305 | WNK::MediaLast => NamedKey::MediaLast, 306 | WNK::MediaSkipBackward => NamedKey::MediaSkipBackward, 307 | WNK::MediaSkipForward => NamedKey::MediaSkipForward, 308 | WNK::MediaStepBackward => NamedKey::MediaStepBackward, 309 | WNK::MediaStepForward => NamedKey::MediaStepForward, 310 | WNK::MediaTopMenu => NamedKey::MediaTopMenu, 311 | WNK::NavigateIn => NamedKey::NavigateIn, 312 | WNK::NavigateNext => NamedKey::NavigateNext, 313 | WNK::NavigateOut => NamedKey::NavigateOut, 314 | WNK::NavigatePrevious => NamedKey::NavigatePrevious, 315 | WNK::NextFavoriteChannel => NamedKey::NextFavoriteChannel, 316 | WNK::NextUserProfile => NamedKey::NextUserProfile, 317 | WNK::OnDemand => NamedKey::OnDemand, 318 | WNK::Pairing => NamedKey::Pairing, 319 | WNK::PinPDown => NamedKey::PinPDown, 320 | WNK::PinPMove => NamedKey::PinPMove, 321 | WNK::PinPToggle => NamedKey::PinPToggle, 322 | WNK::PinPUp => NamedKey::PinPUp, 323 | WNK::PlaySpeedDown => NamedKey::PlaySpeedDown, 324 | WNK::PlaySpeedReset => NamedKey::PlaySpeedReset, 325 | WNK::PlaySpeedUp => NamedKey::PlaySpeedUp, 326 | WNK::RandomToggle => NamedKey::RandomToggle, 327 | WNK::RcLowBattery => NamedKey::RcLowBattery, 328 | WNK::RecordSpeedNext => NamedKey::RecordSpeedNext, 329 | WNK::RfBypass => NamedKey::RfBypass, 330 | WNK::ScanChannelsToggle => NamedKey::ScanChannelsToggle, 331 | WNK::ScreenModeNext => NamedKey::ScreenModeNext, 332 | WNK::Settings => NamedKey::Settings, 333 | WNK::SplitScreenToggle => NamedKey::SplitScreenToggle, 334 | WNK::STBInput => NamedKey::STBInput, 335 | WNK::STBPower => NamedKey::STBPower, 336 | WNK::Subtitle => NamedKey::Subtitle, 337 | WNK::Teletext => NamedKey::Teletext, 338 | WNK::VideoModeNext => NamedKey::VideoModeNext, 339 | WNK::Wink => NamedKey::Wink, 340 | WNK::ZoomToggle => NamedKey::ZoomToggle, 341 | WNK::F1 => NamedKey::F1, 342 | WNK::F2 => NamedKey::F2, 343 | WNK::F3 => NamedKey::F3, 344 | WNK::F4 => NamedKey::F4, 345 | WNK::F5 => NamedKey::F5, 346 | WNK::F6 => NamedKey::F6, 347 | WNK::F7 => NamedKey::F7, 348 | WNK::F8 => NamedKey::F8, 349 | WNK::F9 => NamedKey::F9, 350 | WNK::F10 => NamedKey::F10, 351 | WNK::F11 => NamedKey::F11, 352 | WNK::F12 => NamedKey::F12, 353 | WNK::F13 => NamedKey::F13, 354 | WNK::F14 => NamedKey::F14, 355 | WNK::F15 => NamedKey::F15, 356 | WNK::F16 => NamedKey::F16, 357 | WNK::F17 => NamedKey::F17, 358 | WNK::F18 => NamedKey::F18, 359 | WNK::F19 => NamedKey::F19, 360 | WNK::F20 => NamedKey::F20, 361 | WNK::F21 => NamedKey::F21, 362 | WNK::F22 => NamedKey::F22, 363 | WNK::F23 => NamedKey::F23, 364 | WNK::F24 => NamedKey::F24, 365 | WNK::F25 => NamedKey::F25, 366 | WNK::F26 => NamedKey::F26, 367 | WNK::F27 => NamedKey::F27, 368 | WNK::F28 => NamedKey::F28, 369 | WNK::F29 => NamedKey::F29, 370 | WNK::F30 => NamedKey::F30, 371 | WNK::F31 => NamedKey::F31, 372 | WNK::F32 => NamedKey::F32, 373 | WNK::F33 => NamedKey::F33, 374 | WNK::F34 => NamedKey::F34, 375 | WNK::F35 => NamedKey::F35, 376 | _ => NamedKey::Unidentified, 377 | }), 378 | } 379 | } 380 | 381 | /// Convert a [`winit::keyboard::PhysicalKey`] to a [`ui_events::keyboard::Code`]. 382 | pub fn from_winit_code(physical_key: winit::keyboard::PhysicalKey) -> Code { 383 | use winit::keyboard::KeyCode as KC; 384 | use winit::keyboard::PhysicalKey; 385 | match physical_key { 386 | PhysicalKey::Unidentified(_) => Code::Unidentified, 387 | PhysicalKey::Code(key_code) => match key_code { 388 | // Variants that don't match 1:1 389 | // With winit 0.31, these are renamed to swap the meta and super to match the W3C specs. 390 | #[allow(deprecated)] 391 | KC::Meta => Code::Super, 392 | KC::SuperLeft => Code::MetaLeft, 393 | KC::SuperRight => Code::MetaRight, 394 | 395 | KC::Backquote => Code::Backquote, 396 | KC::Backslash => Code::Backslash, 397 | KC::BracketLeft => Code::BracketLeft, 398 | KC::BracketRight => Code::BracketRight, 399 | KC::Comma => Code::Comma, 400 | KC::Digit0 => Code::Digit0, 401 | KC::Digit1 => Code::Digit1, 402 | KC::Digit2 => Code::Digit2, 403 | KC::Digit3 => Code::Digit3, 404 | KC::Digit4 => Code::Digit4, 405 | KC::Digit5 => Code::Digit5, 406 | KC::Digit6 => Code::Digit6, 407 | KC::Digit7 => Code::Digit7, 408 | KC::Digit8 => Code::Digit8, 409 | KC::Digit9 => Code::Digit9, 410 | KC::Equal => Code::Equal, 411 | KC::IntlBackslash => Code::IntlBackslash, 412 | KC::IntlRo => Code::IntlRo, 413 | KC::IntlYen => Code::IntlYen, 414 | KC::KeyA => Code::KeyA, 415 | KC::KeyB => Code::KeyB, 416 | KC::KeyC => Code::KeyC, 417 | KC::KeyD => Code::KeyD, 418 | KC::KeyE => Code::KeyE, 419 | KC::KeyF => Code::KeyF, 420 | KC::KeyG => Code::KeyG, 421 | KC::KeyH => Code::KeyH, 422 | KC::KeyI => Code::KeyI, 423 | KC::KeyJ => Code::KeyJ, 424 | KC::KeyK => Code::KeyK, 425 | KC::KeyL => Code::KeyL, 426 | KC::KeyM => Code::KeyM, 427 | KC::KeyN => Code::KeyN, 428 | KC::KeyO => Code::KeyO, 429 | KC::KeyP => Code::KeyP, 430 | KC::KeyQ => Code::KeyQ, 431 | KC::KeyR => Code::KeyR, 432 | KC::KeyS => Code::KeyS, 433 | KC::KeyT => Code::KeyT, 434 | KC::KeyU => Code::KeyU, 435 | KC::KeyV => Code::KeyV, 436 | KC::KeyW => Code::KeyW, 437 | KC::KeyX => Code::KeyX, 438 | KC::KeyY => Code::KeyY, 439 | KC::KeyZ => Code::KeyZ, 440 | KC::Minus => Code::Minus, 441 | KC::Period => Code::Period, 442 | KC::Quote => Code::Quote, 443 | KC::Semicolon => Code::Semicolon, 444 | KC::Slash => Code::Slash, 445 | KC::AltLeft => Code::AltLeft, 446 | KC::AltRight => Code::AltRight, 447 | KC::Backspace => Code::Backspace, 448 | KC::CapsLock => Code::CapsLock, 449 | KC::ContextMenu => Code::ContextMenu, 450 | KC::ControlLeft => Code::ControlLeft, 451 | KC::ControlRight => Code::ControlRight, 452 | KC::Enter => Code::Enter, 453 | KC::ShiftLeft => Code::ShiftLeft, 454 | KC::ShiftRight => Code::ShiftRight, 455 | KC::Space => Code::Space, 456 | KC::Tab => Code::Tab, 457 | KC::Convert => Code::Convert, 458 | KC::KanaMode => Code::KanaMode, 459 | KC::Lang1 => Code::Lang1, 460 | KC::Lang2 => Code::Lang2, 461 | KC::Lang3 => Code::Lang3, 462 | KC::Lang4 => Code::Lang4, 463 | KC::Lang5 => Code::Lang5, 464 | KC::NonConvert => Code::NonConvert, 465 | KC::Delete => Code::Delete, 466 | KC::End => Code::End, 467 | KC::Help => Code::Help, 468 | KC::Home => Code::Home, 469 | KC::Insert => Code::Insert, 470 | KC::PageDown => Code::PageDown, 471 | KC::PageUp => Code::PageUp, 472 | KC::ArrowDown => Code::ArrowDown, 473 | KC::ArrowLeft => Code::ArrowLeft, 474 | KC::ArrowRight => Code::ArrowRight, 475 | KC::ArrowUp => Code::ArrowUp, 476 | KC::NumLock => Code::NumLock, 477 | KC::Numpad0 => Code::Numpad0, 478 | KC::Numpad1 => Code::Numpad1, 479 | KC::Numpad2 => Code::Numpad2, 480 | KC::Numpad3 => Code::Numpad3, 481 | KC::Numpad4 => Code::Numpad4, 482 | KC::Numpad5 => Code::Numpad5, 483 | KC::Numpad6 => Code::Numpad6, 484 | KC::Numpad7 => Code::Numpad7, 485 | KC::Numpad8 => Code::Numpad8, 486 | KC::Numpad9 => Code::Numpad9, 487 | KC::NumpadAdd => Code::NumpadAdd, 488 | KC::NumpadBackspace => Code::NumpadBackspace, 489 | KC::NumpadClear => Code::NumpadClear, 490 | KC::NumpadClearEntry => Code::NumpadClearEntry, 491 | KC::NumpadComma => Code::NumpadComma, 492 | KC::NumpadDecimal => Code::NumpadDecimal, 493 | KC::NumpadDivide => Code::NumpadDivide, 494 | KC::NumpadEnter => Code::NumpadEnter, 495 | KC::NumpadEqual => Code::NumpadEqual, 496 | KC::NumpadHash => Code::NumpadHash, 497 | KC::NumpadMemoryAdd => Code::NumpadMemoryAdd, 498 | KC::NumpadMemoryClear => Code::NumpadMemoryClear, 499 | KC::NumpadMemoryRecall => Code::NumpadMemoryRecall, 500 | KC::NumpadMemoryStore => Code::NumpadMemoryStore, 501 | KC::NumpadMemorySubtract => Code::NumpadMemorySubtract, 502 | KC::NumpadMultiply => Code::NumpadMultiply, 503 | KC::NumpadParenLeft => Code::NumpadParenLeft, 504 | KC::NumpadParenRight => Code::NumpadParenRight, 505 | KC::NumpadStar => Code::NumpadStar, 506 | KC::NumpadSubtract => Code::NumpadSubtract, 507 | KC::Escape => Code::Escape, 508 | KC::Fn => Code::Fn, 509 | KC::FnLock => Code::FnLock, 510 | KC::PrintScreen => Code::PrintScreen, 511 | KC::ScrollLock => Code::ScrollLock, 512 | KC::Pause => Code::Pause, 513 | KC::BrowserBack => Code::BrowserBack, 514 | KC::BrowserFavorites => Code::BrowserFavorites, 515 | KC::BrowserForward => Code::BrowserForward, 516 | KC::BrowserHome => Code::BrowserHome, 517 | KC::BrowserRefresh => Code::BrowserRefresh, 518 | KC::BrowserSearch => Code::BrowserSearch, 519 | KC::BrowserStop => Code::BrowserStop, 520 | KC::Eject => Code::Eject, 521 | KC::LaunchApp1 => Code::LaunchApp1, 522 | KC::LaunchApp2 => Code::LaunchApp2, 523 | KC::LaunchMail => Code::LaunchMail, 524 | KC::MediaPlayPause => Code::MediaPlayPause, 525 | KC::MediaSelect => Code::MediaSelect, 526 | KC::MediaStop => Code::MediaStop, 527 | KC::MediaTrackNext => Code::MediaTrackNext, 528 | KC::MediaTrackPrevious => Code::MediaTrackPrevious, 529 | KC::Power => Code::Power, 530 | KC::Sleep => Code::Sleep, 531 | KC::AudioVolumeDown => Code::AudioVolumeDown, 532 | KC::AudioVolumeMute => Code::AudioVolumeMute, 533 | KC::AudioVolumeUp => Code::AudioVolumeUp, 534 | KC::WakeUp => Code::WakeUp, 535 | #[allow(deprecated)] 536 | KC::Hyper => Code::Hyper, 537 | #[allow(deprecated)] 538 | KC::Turbo => Code::Turbo, 539 | KC::Abort => Code::Abort, 540 | KC::Resume => Code::Resume, 541 | KC::Suspend => Code::Suspend, 542 | KC::Again => Code::Again, 543 | KC::Copy => Code::Copy, 544 | KC::Cut => Code::Cut, 545 | KC::Find => Code::Find, 546 | KC::Open => Code::Open, 547 | KC::Paste => Code::Paste, 548 | KC::Props => Code::Props, 549 | KC::Select => Code::Select, 550 | KC::Undo => Code::Undo, 551 | KC::Hiragana => Code::Hiragana, 552 | KC::Katakana => Code::Katakana, 553 | KC::F1 => Code::F1, 554 | KC::F2 => Code::F2, 555 | KC::F3 => Code::F3, 556 | KC::F4 => Code::F4, 557 | KC::F5 => Code::F5, 558 | KC::F6 => Code::F6, 559 | KC::F7 => Code::F7, 560 | KC::F8 => Code::F8, 561 | KC::F9 => Code::F9, 562 | KC::F10 => Code::F10, 563 | KC::F11 => Code::F11, 564 | KC::F12 => Code::F12, 565 | KC::F13 => Code::F13, 566 | KC::F14 => Code::F14, 567 | KC::F15 => Code::F15, 568 | KC::F16 => Code::F16, 569 | KC::F17 => Code::F17, 570 | KC::F18 => Code::F18, 571 | KC::F19 => Code::F19, 572 | KC::F20 => Code::F20, 573 | KC::F21 => Code::F21, 574 | KC::F22 => Code::F22, 575 | KC::F23 => Code::F23, 576 | KC::F24 => Code::F24, 577 | KC::F25 => Code::F25, 578 | KC::F26 => Code::F26, 579 | KC::F27 => Code::F27, 580 | KC::F28 => Code::F28, 581 | KC::F29 => Code::F29, 582 | KC::F30 => Code::F30, 583 | KC::F31 => Code::F31, 584 | KC::F32 => Code::F32, 585 | KC::F33 => Code::F33, 586 | KC::F34 => Code::F34, 587 | KC::F35 => Code::F35, 588 | _ => Code::Unidentified, 589 | }, 590 | } 591 | } 592 | -------------------------------------------------------------------------------- /ui-events-winit/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2025 the UI Events Authors 2 | // SPDX-License-Identifier: Apache-2.0 OR MIT 3 | 4 | //! This crate bridges [`winit`]'s native input events (mouse, touch, keyboard, etc.) 5 | //! into the [`ui-events`] model. 6 | //! 7 | //! The primary entry point is [`WindowEventReducer`]. 8 | //! 9 | //! [`ui-events`]: https://docs.rs/ui-events/ 10 | 11 | // LINEBENDER LINT SET - lib.rs - v3 12 | // See https://linebender.org/wiki/canonical-lints/ 13 | // These lints shouldn't apply to examples or tests. 14 | #![cfg_attr(not(test), warn(unused_crate_dependencies))] 15 | // These lints shouldn't apply to examples. 16 | #![warn(clippy::print_stdout, clippy::print_stderr)] 17 | // Targeting e.g. 32-bit means structs containing usize can give false positives for 64-bit. 18 | #![cfg_attr(target_pointer_width = "64", warn(clippy::trivially_copy_pass_by_ref))] 19 | // END LINEBENDER LINT SET 20 | #![cfg_attr(docsrs, feature(doc_auto_cfg))] 21 | #![no_std] 22 | 23 | pub mod keyboard; 24 | pub mod pointer; 25 | 26 | extern crate alloc; 27 | use alloc::{vec, vec::Vec}; 28 | 29 | extern crate std; 30 | use std::time::Instant; 31 | 32 | use ui_events::{ 33 | keyboard::KeyboardEvent, 34 | pointer::{ 35 | PointerButtonEvent, PointerEvent, PointerId, PointerInfo, PointerScrollEvent, PointerState, 36 | PointerType, PointerUpdate, 37 | }, 38 | ScrollDelta, 39 | }; 40 | use winit::{ 41 | event::{ElementState, Force, MouseScrollDelta, Touch, TouchPhase, WindowEvent}, 42 | keyboard::ModifiersState, 43 | }; 44 | 45 | /// Manages stateful transformations of winit [`WindowEvent`]. 46 | /// 47 | /// Store a single instance of this per window, then call [`WindowEventReducer::reduce`] 48 | /// on each [`WindowEvent`] for that window. 49 | /// Use the [`WindowEventTranslation`] value to receive [`PointerEvent`]s and [`KeyboardEvent`]s. 50 | /// 51 | /// This handles: 52 | /// - [`ModifiersChanged`][`WindowEvent::ModifiersChanged`] 53 | /// - [`KeyboardInput`][`WindowEvent::KeyboardInput`] 54 | /// - [`Touch`][`WindowEvent::Touch`] 55 | /// - [`MouseInput`][`WindowEvent::MouseInput`] 56 | /// - [`MouseWheel`][`WindowEvent::MouseWheel`] 57 | /// - [`CursorMoved`][`WindowEvent::CursorMoved`] 58 | /// - [`CursorEntered`][`WindowEvent::CursorEntered`] 59 | /// - [`CursorLeft`][`WindowEvent::CursorLeft`] 60 | #[derive(Debug, Default)] 61 | pub struct WindowEventReducer { 62 | /// State of modifiers. 63 | modifiers: ModifiersState, 64 | /// State of the primary mouse pointer. 65 | primary_state: PointerState, 66 | /// Click and tap counter. 67 | counter: TapCounter, 68 | /// First time an event was received.. 69 | first_instant: Option, 70 | } 71 | 72 | #[allow(clippy::cast_possible_truncation)] 73 | impl WindowEventReducer { 74 | /// Process a [`WindowEvent`]. 75 | pub fn reduce(&mut self, we: &WindowEvent) -> Option { 76 | const PRIMARY_MOUSE: PointerInfo = PointerInfo { 77 | pointer_id: Some(PointerId::PRIMARY), 78 | // TODO: Maybe transmute device. 79 | persistent_device_id: None, 80 | pointer_type: PointerType::Mouse, 81 | }; 82 | 83 | let time = Instant::now() 84 | .duration_since(*self.first_instant.get_or_insert_with(Instant::now)) 85 | .as_nanos() as u64; 86 | 87 | self.primary_state.time = time; 88 | 89 | match we { 90 | WindowEvent::ModifiersChanged(m) => { 91 | self.modifiers = m.state(); 92 | self.primary_state.modifiers = keyboard::from_winit_modifier_state(self.modifiers); 93 | None 94 | } 95 | WindowEvent::KeyboardInput { event, .. } => Some(WindowEventTranslation::Keyboard( 96 | keyboard::from_winit_keyboard_event(event.clone(), self.modifiers), 97 | )), 98 | WindowEvent::CursorEntered { .. } => Some(WindowEventTranslation::Pointer( 99 | PointerEvent::Enter(PRIMARY_MOUSE), 100 | )), 101 | WindowEvent::CursorLeft { .. } => Some(WindowEventTranslation::Pointer( 102 | PointerEvent::Leave(PRIMARY_MOUSE), 103 | )), 104 | WindowEvent::CursorMoved { position, .. } => { 105 | self.primary_state.position = *position; 106 | 107 | Some(WindowEventTranslation::Pointer(self.counter.attach_count( 108 | PointerEvent::Move(PointerUpdate { 109 | pointer: PRIMARY_MOUSE, 110 | current: self.primary_state.clone(), 111 | coalesced: vec![], 112 | predicted: vec![], 113 | }), 114 | ))) 115 | } 116 | WindowEvent::MouseInput { 117 | state: ElementState::Pressed, 118 | button, 119 | .. 120 | } => { 121 | let button = pointer::try_from_winit_button(*button); 122 | if let Some(button) = button { 123 | self.primary_state.buttons.insert(button); 124 | } 125 | 126 | Some(WindowEventTranslation::Pointer(self.counter.attach_count( 127 | PointerEvent::Down(PointerButtonEvent { 128 | pointer: PRIMARY_MOUSE, 129 | button, 130 | state: self.primary_state.clone(), 131 | }), 132 | ))) 133 | } 134 | WindowEvent::MouseInput { 135 | state: ElementState::Released, 136 | button, 137 | .. 138 | } => { 139 | let button = pointer::try_from_winit_button(*button); 140 | if let Some(button) = button { 141 | self.primary_state.buttons.remove(button); 142 | } 143 | 144 | Some(WindowEventTranslation::Pointer(self.counter.attach_count( 145 | PointerEvent::Up(PointerButtonEvent { 146 | pointer: PRIMARY_MOUSE, 147 | button, 148 | state: self.primary_state.clone(), 149 | }), 150 | ))) 151 | } 152 | WindowEvent::MouseWheel { delta, .. } => Some(WindowEventTranslation::Pointer( 153 | PointerEvent::Scroll(PointerScrollEvent { 154 | pointer: PRIMARY_MOUSE, 155 | delta: match *delta { 156 | MouseScrollDelta::LineDelta(x, y) => ScrollDelta::LineDelta(x, y), 157 | MouseScrollDelta::PixelDelta(p) => ScrollDelta::PixelDelta(p), 158 | }, 159 | state: self.primary_state.clone(), 160 | }), 161 | )), 162 | WindowEvent::Touch(Touch { 163 | phase, 164 | id, 165 | location, 166 | force, 167 | .. 168 | }) => { 169 | let pointer = PointerInfo { 170 | pointer_id: PointerId::new(id.saturating_add(1)), 171 | pointer_type: PointerType::Touch, 172 | persistent_device_id: None, 173 | }; 174 | 175 | use TouchPhase::*; 176 | 177 | let state = PointerState { 178 | time, 179 | position: *location, 180 | modifiers: self.primary_state.modifiers, 181 | pressure: if matches!(phase, Ended | Cancelled) { 182 | 0.0 183 | } else { 184 | match force { 185 | Some(Force::Calibrated { force, .. }) => (force * 0.5) as f32, 186 | Some(Force::Normalized(q)) => *q as f32, 187 | _ => 0.5, 188 | } 189 | }, 190 | ..Default::default() 191 | }; 192 | 193 | Some(WindowEventTranslation::Pointer(self.counter.attach_count( 194 | match phase { 195 | Started => PointerEvent::Down(PointerButtonEvent { 196 | pointer, 197 | button: None, 198 | state, 199 | }), 200 | Moved => PointerEvent::Move(PointerUpdate { 201 | pointer, 202 | current: state, 203 | coalesced: vec![], 204 | predicted: vec![], 205 | }), 206 | Cancelled => PointerEvent::Cancel(pointer), 207 | Ended => PointerEvent::Up(PointerButtonEvent { 208 | pointer, 209 | button: None, 210 | state, 211 | }), 212 | }, 213 | ))) 214 | } 215 | _ => None, 216 | } 217 | } 218 | } 219 | 220 | /// Result of [`WindowEventReducer::reduce`]. 221 | #[derive(Debug)] 222 | pub enum WindowEventTranslation { 223 | /// Resulting [`KeyboardEvent`]. 224 | Keyboard(KeyboardEvent), 225 | /// Resulting [`PointerEvent`]. 226 | Pointer(PointerEvent), 227 | } 228 | 229 | #[derive(Clone, Debug)] 230 | struct TapState { 231 | /// Pointer ID used to attach tap counts to [`PointerEvent::Move`]. 232 | pointer_id: Option, 233 | /// Nanosecond timestamp when the tap went Down. 234 | down_time: u64, 235 | /// Nanosecond timestamp when the tap went Up. 236 | /// 237 | /// Resets to `down_time` when tap goes Down. 238 | up_time: u64, 239 | /// The local tap count as of the last Down phase. 240 | count: u8, 241 | /// x coordinate. 242 | x: f64, 243 | /// y coordinate. 244 | y: f64, 245 | } 246 | 247 | #[derive(Debug, Default)] 248 | struct TapCounter { 249 | taps: Vec, 250 | } 251 | 252 | impl TapCounter { 253 | /// Enhance a [`PointerEvent`] with a `count`. 254 | fn attach_count(&mut self, e: PointerEvent) -> PointerEvent { 255 | match e { 256 | PointerEvent::Down(mut event) => { 257 | let pointer_id = event.pointer.pointer_id; 258 | let position = event.state.position; 259 | let time = event.state.time; 260 | 261 | if let Some(tap) = 262 | self.taps.iter_mut().find(|TapState { x, y, up_time, .. }| { 263 | let dx = (x - position.x).abs(); 264 | let dy = (y - position.y).abs(); 265 | (dx * dx + dy * dy).sqrt() < 4.0 && (up_time + 500_000_000) > time 266 | }) 267 | { 268 | let count = tap.count + 1; 269 | event.state.count = count; 270 | tap.count = count; 271 | tap.pointer_id = pointer_id; 272 | tap.down_time = time; 273 | tap.up_time = time; 274 | tap.x = position.x; 275 | tap.y = position.y; 276 | } else { 277 | let s = TapState { 278 | pointer_id, 279 | down_time: time, 280 | up_time: time, 281 | count: 1, 282 | x: position.x, 283 | y: position.y, 284 | }; 285 | self.taps.push(s); 286 | event.state.count = 1; 287 | }; 288 | self.clear_expired(time); 289 | PointerEvent::Down(event) 290 | } 291 | PointerEvent::Up(mut event) => { 292 | let p_id = event.pointer.pointer_id; 293 | if let Some(tap) = self.taps.iter_mut().find(|state| state.pointer_id == p_id) { 294 | tap.up_time = event.state.time; 295 | event.state.count = tap.count; 296 | } 297 | PointerEvent::Up(event) 298 | } 299 | PointerEvent::Move(PointerUpdate { 300 | pointer, 301 | mut current, 302 | mut coalesced, 303 | mut predicted, 304 | }) => { 305 | if let Some(TapState { count, .. }) = self 306 | .taps 307 | .iter() 308 | .find( 309 | |TapState { 310 | pointer_id, 311 | down_time, 312 | up_time, 313 | .. 314 | }| { 315 | *pointer_id == pointer.pointer_id && down_time == up_time 316 | }, 317 | ) 318 | .cloned() 319 | { 320 | current.count = count; 321 | for event in coalesced.iter_mut() { 322 | event.count = count; 323 | } 324 | for event in predicted.iter_mut() { 325 | event.count = count; 326 | } 327 | PointerEvent::Move(PointerUpdate { 328 | pointer, 329 | current, 330 | coalesced, 331 | predicted, 332 | }) 333 | } else { 334 | PointerEvent::Move(PointerUpdate { 335 | pointer, 336 | current, 337 | coalesced, 338 | predicted, 339 | }) 340 | } 341 | } 342 | PointerEvent::Cancel(p) => { 343 | self.taps 344 | .retain(|TapState { pointer_id, .. }| *pointer_id != p.pointer_id); 345 | PointerEvent::Cancel(p) 346 | } 347 | PointerEvent::Leave(p) => { 348 | self.taps 349 | .retain(|TapState { pointer_id, .. }| *pointer_id != p.pointer_id); 350 | PointerEvent::Leave(p) 351 | } 352 | e @ (PointerEvent::Enter(..) | PointerEvent::Scroll(..)) => e, 353 | } 354 | } 355 | 356 | /// Clear expired taps. 357 | /// 358 | /// `t` is the time of the last received event. 359 | /// All events have the same time base on Android, so this is valid here. 360 | fn clear_expired(&mut self, t: u64) { 361 | self.taps.retain( 362 | |TapState { 363 | down_time, up_time, .. 364 | }| { down_time == up_time || (up_time + 500_000_000) > t }, 365 | ); 366 | } 367 | } 368 | 369 | #[cfg(test)] 370 | mod tests { 371 | // CI will fail unless cargo nextest can execute at least one test per workspace. 372 | // Delete this dummy test once we have an actual real test. 373 | #[test] 374 | fn dummy_test_until_we_have_a_real_test() {} 375 | } 376 | -------------------------------------------------------------------------------- /ui-events-winit/src/pointer.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2025 the UI Events Authors 2 | // SPDX-License-Identifier: Apache-2.0 OR MIT 3 | 4 | //! Support routines for converting pointer data from [`winit`]. 5 | 6 | use ui_events::pointer::PointerButton; 7 | use winit::event::MouseButton; 8 | 9 | /// Try to make a [`PointerButton`] from a [`MouseButton`]. 10 | /// 11 | /// Because values of [`MouseButton::Other`] can start at 0, they are mapped 12 | /// to the arbitrary buttons B7..B32. 13 | /// Values greater than 25 will not be mapped. 14 | pub fn try_from_winit_button(b: MouseButton) -> Option { 15 | Some(match b { 16 | MouseButton::Left => PointerButton::Primary, 17 | MouseButton::Right => PointerButton::Secondary, 18 | MouseButton::Middle => PointerButton::Auxiliary, 19 | MouseButton::Back => PointerButton::X1, 20 | MouseButton::Forward => PointerButton::X2, 21 | MouseButton::Other(u) => match u { 22 | 6 => PointerButton::B7, 23 | 7 => PointerButton::B8, 24 | 8 => PointerButton::B9, 25 | 9 => PointerButton::B10, 26 | 10 => PointerButton::B11, 27 | 11 => PointerButton::B12, 28 | 12 => PointerButton::B13, 29 | 13 => PointerButton::B14, 30 | 14 => PointerButton::B15, 31 | 15 => PointerButton::B16, 32 | 16 => PointerButton::B17, 33 | 17 => PointerButton::B18, 34 | 18 => PointerButton::B19, 35 | 19 => PointerButton::B20, 36 | 20 => PointerButton::B21, 37 | 21 => PointerButton::B22, 38 | 22 => PointerButton::B23, 39 | 23 => PointerButton::B24, 40 | 24 => PointerButton::B25, 41 | 25 => PointerButton::B26, 42 | 26 => PointerButton::B27, 43 | 27 => PointerButton::B28, 44 | 28 => PointerButton::B29, 45 | 29 => PointerButton::B30, 46 | 30 => PointerButton::B31, 47 | 31 => PointerButton::B32, 48 | _ => { 49 | return None; 50 | } 51 | }, 52 | }) 53 | } 54 | -------------------------------------------------------------------------------- /ui-events/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 8 | 9 | # Changelog 10 | 11 | The latest published UI Events release is [0.1.0](#010-2025-05-08) which was released on 2025-05-08. 12 | You can find its changes [documented below](#010-2025-05-08). 13 | 14 | ## [Unreleased] 15 | 16 | This release has an [MSRV][] of 1.73. 17 | 18 | ### Added 19 | 20 | * `PointerId`, `PointerInfo`, `PointerUpdate`, and `PointerEvent` now have a `is_primary_pointer` methhod. ([#54][] by [@waywardmonkeys][]) 21 | 22 | ## [0.1.0][] - 2025-05-08 23 | 24 | This release has an [MSRV][] of 1.73. 25 | 26 | This is the initial release. 27 | 28 | [@waywardmonkeys]: https://github.com/waywardmonkeys 29 | 30 | [#54]: https://github.com/endoli/ui-events/pull/54 31 | 32 | [Unreleased]: https://github.com/endoli/ui-events/compare/v0.1.0...HEAD 33 | [0.1.0]: https://github.com/linebender/color/releases/tag/v0.1.0 34 | 35 | [MSRV]: README.md#minimum-supported-rust-version-msrv 36 | -------------------------------------------------------------------------------- /ui-events/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ui-events" 3 | version.workspace = true 4 | license.workspace = true 5 | edition.workspace = true 6 | description = "A crate for working with UI events and input types." 7 | keywords = ["ui", "input", "pointer", "events"] 8 | categories = ["graphics", "gui"] 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | 12 | [package.metadata.docs.rs] 13 | all-features = true 14 | # There are no platform specific docs. 15 | default-target = "x86_64-unknown-linux-gnu" 16 | targets = [] 17 | 18 | [features] 19 | default = ["std"] 20 | std = ["dpi/std", "keyboard-types/std"] 21 | 22 | [dependencies] 23 | dpi = { workspace = true } 24 | keyboard-types = { version = "0.8.0", default-features = false } 25 | 26 | [lints] 27 | workspace = true 28 | -------------------------------------------------------------------------------- /ui-events/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | -------------------------------------------------------------------------------- /ui-events/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /ui-events/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # UI Events 4 | 5 | A library for working with UI events and input types. 6 | 7 | [![Linebender Zulip, #general channel](https://img.shields.io/badge/Linebender-%23general-blue?logo=Zulip)](https://xi.zulipchat.com/#narrow/channel/147921-general) 8 | [![dependency status](https://deps.rs/repo/github/endoli/ui-events/status.svg)](https://deps.rs/repo/github/endoli/ui-events) 9 | [![Apache 2.0 or MIT license.](https://img.shields.io/badge/license-Apache--2.0_OR_MIT-blue.svg)](#license) 10 | [![Build status](https://github.com/endoli/ui-events/workflows/CI/badge.svg)](https://github.com/endoli/ui-events/actions) 11 | [![Crates.io](https://img.shields.io/crates/v/ui-events.svg)](https://crates.io/crates/ui-events) 12 | [![Docs](https://docs.rs/ui-events/badge.svg)](https://docs.rs/ui-events) 13 | 14 |
15 | 16 | 20 | 21 | 23 | 24 | 25 | A cross-platform input event abstraction modeled after W3C UI Events specifications. 26 | 27 | Provides common vocabulary types for working with pointer events (mouse, touch, pen) and 28 | keyboard events in a platform-agnostic way. The crate aims to closely follow W3C standards 29 | while remaining practical for native application development. 30 | 31 | Includes support for: 32 | 33 | - Pointer events (down/move/up, pressure, tilt, etc.) 34 | - Keyboard events (key codes, modifiers, location) 35 | 36 | For integration with [`winit`], use the companion [`ui-events-winit`] adapter crate. 37 | 38 | ## Features 39 | 40 | - `std` (enabled by default): Use the Rust standard library. 41 | 42 | [`ui-events-winit`]: https://docs.rs/ui-events-winit/ 43 | [`winit`]: https://docs.rs/winit/ 44 | 45 | 46 | 47 | ## Minimum supported Rust Version (MSRV) 48 | 49 | This version of UI Events has been verified to compile with **Rust 1.73** and later. 50 | The `no_std` build of this library needs **Rust 1.81** and later. 51 | 52 | Future versions of UI Events might increase the Rust version requirement. 53 | It will not be treated as a breaking change and as such can even happen with small patch releases. 54 | 55 |
56 | Click here if compiling fails. 57 | 58 | As time has passed, some of UI Events' dependencies could have released versions with a higher Rust requirement. 59 | If you encounter a compilation issue due to a dependency and don't want to upgrade your Rust toolchain, then you could downgrade the dependency. 60 | 61 | ```sh 62 | # Use the problematic dependency's name and version 63 | cargo update -p package_name --precise 0.1.1 64 | ``` 65 | 66 |
67 | 68 | ## Community 69 | 70 | [![Linebender Zulip](https://img.shields.io/badge/Xi%20Zulip-%23general-blue?logo=Zulip)](https://xi.zulipchat.com/#narrow/channel/147921-general) 71 | 72 | Discussion of UI Events development happens in the [Linebender Zulip](https://xi.zulipchat.com/), specifically the [#general channel](https://xi.zulipchat.com/#narrow/channel/147921-general). 73 | All public content can be read without logging in. 74 | 75 | ## License 76 | 77 | Licensed under either of 78 | 79 | - Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or ) 80 | - MIT license ([LICENSE-MIT](LICENSE-MIT) or ) 81 | 82 | at your option. 83 | 84 | ## Contribution 85 | 86 | Contributions are welcome by pull request. The [Rust code of conduct] applies. 87 | Please feel free to add your name to the [AUTHORS] file in any substantive pull request. 88 | 89 | Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be licensed as above, without any additional terms or conditions. 90 | 91 | [Rust Code of Conduct]: https://www.rust-lang.org/policies/code-of-conduct 92 | [AUTHORS]: ./AUTHORS 93 | -------------------------------------------------------------------------------- /ui-events/src/keyboard/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2025 the UI Events Authors 2 | // SPDX-License-Identifier: Apache-2.0 OR MIT 3 | 4 | //! Keyboard Types 5 | 6 | pub use keyboard_types::*; 7 | 8 | #[cfg(target_os = "android")] 9 | pub mod android; 10 | -------------------------------------------------------------------------------- /ui-events/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2025 the UI Events Authors 2 | // SPDX-License-Identifier: Apache-2.0 OR MIT 3 | 4 | //! A cross-platform input event abstraction modeled after W3C UI Events specifications. 5 | //! 6 | //! Provides common vocabulary types for working with pointer events (mouse, touch, pen) and 7 | //! keyboard events in a platform-agnostic way. The crate aims to closely follow W3C standards 8 | //! while remaining practical for native application development. 9 | //! 10 | //! Includes support for: 11 | //! 12 | //! - Pointer events (down/move/up, pressure, tilt, etc.) 13 | //! - Keyboard events (key codes, modifiers, location) 14 | //! 15 | //! For integration with [`winit`], use the companion [`ui-events-winit`] adapter crate. 16 | //! 17 | //! ## Features 18 | //! 19 | //! - `std` (enabled by default): Use the Rust standard library. 20 | //! 21 | //! [`ui-events-winit`]: https://docs.rs/ui-events-winit/ 22 | //! [`winit`]: https://docs.rs/winit/ 23 | // LINEBENDER LINT SET - lib.rs - v3 24 | // See https://linebender.org/wiki/canonical-lints/ 25 | // These lints shouldn't apply to examples or tests. 26 | #![cfg_attr(not(test), warn(unused_crate_dependencies))] 27 | // These lints shouldn't apply to examples. 28 | #![warn(clippy::print_stdout, clippy::print_stderr)] 29 | // Targeting e.g. 32-bit means structs containing usize can give false positives for 64-bit. 30 | #![cfg_attr(target_pointer_width = "64", warn(clippy::trivially_copy_pass_by_ref))] 31 | // END LINEBENDER LINT SET 32 | #![cfg_attr(docsrs, feature(doc_auto_cfg))] 33 | #![no_std] 34 | 35 | pub mod keyboard; 36 | pub mod pointer; 37 | 38 | mod scroll; 39 | 40 | pub use scroll::ScrollDelta; 41 | -------------------------------------------------------------------------------- /ui-events/src/pointer/buttons.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2025 the UI Events Authors 2 | // SPDX-License-Identifier: Apache-2.0 OR MIT 3 | 4 | /// Describes a button of a pointer input device, such as a mouse or stylus pen. 5 | /// 6 | /// B7..B32 exist for the purpose of supporting pointer devices with 7 | /// large numbers of buttons. 8 | /// These exotic pointer buttons top out around the 24 buttons range 9 | /// in practice, and Windows doesn't support more than 32 mouse buttons 10 | /// in most APIs, therefore 32 was chosen as the upper limit. 11 | #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] 12 | #[repr(u32)] 13 | pub enum PointerButton { 14 | /// Primary button, commonly the left mouse button, touch contact, pen contact. 15 | Primary = 1, 16 | /// Secondary button, commonly the right mouse button, pen barrel button. 17 | Secondary = 1 << 1, 18 | /// Auxiliary button, commonly the middle mouse button. 19 | Auxiliary = 1 << 2, 20 | /// X1 (back) Mouse. 21 | X1 = 1 << 3, 22 | /// X2 (forward) Mouse. 23 | X2 = 1 << 4, 24 | /// Pen erase button. 25 | PenEraser = 1 << 5, 26 | /// Button 7. 27 | B7 = 1 << 6, 28 | /// Button 8. 29 | B8 = 1 << 7, 30 | /// Button 9. 31 | B9 = 1 << 8, 32 | /// Button 10. 33 | B10 = 1 << 9, 34 | /// Button 11. 35 | B11 = 1 << 10, 36 | /// Button 12. 37 | B12 = 1 << 11, 38 | /// Button 13. 39 | B13 = 1 << 12, 40 | /// Button 14. 41 | B14 = 1 << 13, 42 | /// Button 15. 43 | B15 = 1 << 14, 44 | /// Button 16. 45 | B16 = 1 << 15, 46 | /// Button 17. 47 | B17 = 1 << 16, 48 | /// Button 18. 49 | B18 = 1 << 17, 50 | /// Button 19. 51 | B19 = 1 << 18, 52 | /// Button 20. 53 | B20 = 1 << 19, 54 | /// Button 21. 55 | B21 = 1 << 20, 56 | /// Button 22. 57 | B22 = 1 << 21, 58 | /// Button 23. 59 | B23 = 1 << 22, 60 | /// Button 24. 61 | B24 = 1 << 23, 62 | /// Button 25. 63 | B25 = 1 << 24, 64 | /// Button 26. 65 | B26 = 1 << 25, 66 | /// Button 27. 67 | B27 = 1 << 26, 68 | /// Button 28. 69 | B28 = 1 << 27, 70 | /// Button 29. 71 | B29 = 1 << 28, 72 | /// Button 30. 73 | B30 = 1 << 29, 74 | /// Button 31. 75 | B31 = 1 << 30, 76 | /// Button 32. 77 | B32 = 1 << 31, 78 | } 79 | 80 | /// A set of [`PointerButton`]s. 81 | #[derive(Clone, Copy, Default, Eq, PartialEq)] 82 | pub struct PointerButtons(u32); 83 | 84 | impl PointerButtons { 85 | /// Create a new empty set. 86 | #[inline] 87 | pub fn new() -> Self { 88 | Self(0) 89 | } 90 | 91 | /// Add the `button` to the set. 92 | #[inline] 93 | pub fn insert(&mut self, button: PointerButton) { 94 | self.0 |= button as u32; 95 | } 96 | 97 | /// Remove the `button` from the set. 98 | #[inline] 99 | pub fn remove(&mut self, button: PointerButton) { 100 | self.0 &= !(button as u32); 101 | } 102 | 103 | /// Returns `true` if the `button` is in the set. 104 | #[inline] 105 | pub fn contains(self, button: PointerButton) -> bool { 106 | (self.0 & button as u32) != 0 107 | } 108 | 109 | /// Returns `true` if the set is empty. 110 | #[inline] 111 | pub fn is_empty(self) -> bool { 112 | self.0 == 0 113 | } 114 | 115 | /// Returns `true` if all the `buttons` are in the set. 116 | #[inline] 117 | pub fn contains_all(self, buttons: Self) -> bool { 118 | self.0 & buttons.0 == buttons.0 119 | } 120 | 121 | /// Adds all the `buttons` to the set. 122 | #[inline] 123 | pub fn extend(&mut self, buttons: Self) { 124 | self.0 |= buttons.0; 125 | } 126 | 127 | /// Clear the set. 128 | #[inline] 129 | pub fn clear(&mut self) { 130 | self.0 = 0; 131 | } 132 | 133 | /// Count the number of buttons in the set. 134 | #[inline] 135 | pub fn count(self) -> u32 { 136 | self.0.count_ones() 137 | } 138 | } 139 | 140 | const NONZERO_VARIANTS: [PointerButton; 32] = [ 141 | PointerButton::Primary, 142 | PointerButton::Secondary, 143 | PointerButton::Auxiliary, 144 | PointerButton::X1, 145 | PointerButton::X2, 146 | PointerButton::PenEraser, 147 | PointerButton::B7, 148 | PointerButton::B8, 149 | PointerButton::B9, 150 | PointerButton::B10, 151 | PointerButton::B11, 152 | PointerButton::B12, 153 | PointerButton::B13, 154 | PointerButton::B14, 155 | PointerButton::B15, 156 | PointerButton::B16, 157 | PointerButton::B17, 158 | PointerButton::B18, 159 | PointerButton::B19, 160 | PointerButton::B20, 161 | PointerButton::B21, 162 | PointerButton::B22, 163 | PointerButton::B23, 164 | PointerButton::B24, 165 | PointerButton::B25, 166 | PointerButton::B26, 167 | PointerButton::B27, 168 | PointerButton::B28, 169 | PointerButton::B29, 170 | PointerButton::B30, 171 | PointerButton::B31, 172 | PointerButton::B32, 173 | ]; 174 | 175 | impl core::fmt::Debug for PointerButtons { 176 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 177 | if self.is_empty() { 178 | return f.write_str("PointerButtons(None)"); 179 | } 180 | 181 | f.write_str("PointerButtons(")?; 182 | 183 | if f.alternate() && self.count() > 2 { 184 | f.write_str("\n ")?; 185 | } 186 | 187 | let mut first = true; 188 | for button in NONZERO_VARIANTS { 189 | if self.contains(button) { 190 | if !first { 191 | if f.alternate() && self.count() > 2 { 192 | f.write_str("\n | ")?; 193 | } else { 194 | f.write_str(" | ")?; 195 | } 196 | } 197 | first = false; 198 | button.fmt(f)?; 199 | } 200 | } 201 | 202 | if f.alternate() && self.count() > 2 { 203 | f.write_str("\n)") 204 | } else { 205 | f.write_str(")") 206 | } 207 | } 208 | } 209 | impl core::fmt::Binary for PointerButtons { 210 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 211 | core::fmt::Binary::fmt(&self.0, f) 212 | } 213 | } 214 | 215 | impl core::ops::BitOr for PointerButton { 216 | type Output = PointerButtons; 217 | 218 | fn bitor(self, rhs: Self) -> Self::Output { 219 | PointerButtons(self as u32 | rhs as u32) 220 | } 221 | } 222 | 223 | impl core::ops::BitOr for PointerButtons { 224 | type Output = Self; 225 | 226 | fn bitor(self, rhs: PointerButton) -> Self { 227 | Self(self.0 | rhs as u32) 228 | } 229 | } 230 | 231 | impl core::ops::BitOrAssign for PointerButtons { 232 | fn bitor_assign(&mut self, rhs: PointerButton) { 233 | self.0 |= rhs as u32; 234 | } 235 | } 236 | 237 | impl From for PointerButtons { 238 | fn from(button: PointerButton) -> Self { 239 | Self(button as u32) 240 | } 241 | } 242 | 243 | #[cfg(test)] 244 | mod tests { 245 | /// `PointerButtons` debug formatting behavior. 246 | #[test] 247 | fn debug_fmt() { 248 | use crate::pointer::{PointerButton, PointerButtons}; 249 | extern crate std; 250 | use std::format; 251 | 252 | assert_eq!( 253 | format!("{:?}", PointerButtons::default()), 254 | "PointerButtons(None)" 255 | ); 256 | assert_eq!( 257 | format!("{:?}", PointerButtons::from(PointerButton::Primary)), 258 | "PointerButtons(Primary)" 259 | ); 260 | assert_eq!( 261 | format!("{:?}", PointerButton::Primary | PointerButton::Auxiliary), 262 | "PointerButtons(Primary | Auxiliary)" 263 | ); 264 | assert_eq!( 265 | format!( 266 | "{:?}", 267 | PointerButton::Primary | PointerButton::Auxiliary | PointerButton::Secondary 268 | ), 269 | "PointerButtons(Primary | Secondary | Auxiliary)" 270 | ); 271 | assert_eq!( 272 | format!( 273 | "{:#?}", 274 | ( 275 | PointerButton::Primary | PointerButton::Auxiliary | PointerButton::Secondary, 276 | PointerButton::B7 | PointerButton::X2 277 | ) 278 | ), 279 | "( 280 | PointerButtons( 281 | Primary 282 | | Secondary 283 | | Auxiliary 284 | ), 285 | PointerButtons(X2 | B7), 286 | )" 287 | ); 288 | assert_eq!( 289 | format!("{:?}", PointerButton::B32 | PointerButton::Primary), 290 | "PointerButtons(Primary | B32)" 291 | ); 292 | } 293 | 294 | /// Verify `PointerButton` is same size as `Option`. 295 | #[test] 296 | fn option_niche_opt() { 297 | use crate::pointer::PointerButton; 298 | use core::mem::size_of; 299 | assert_eq!( 300 | size_of::>(), 301 | size_of::() 302 | ); 303 | } 304 | } 305 | -------------------------------------------------------------------------------- /ui-events/src/pointer/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2025 the UI Events Authors 2 | // SPDX-License-Identifier: Apache-2.0 OR MIT 3 | 4 | //! Pointer Event Types 5 | 6 | mod buttons; 7 | 8 | pub use buttons::{PointerButton, PointerButtons}; 9 | 10 | extern crate alloc; 11 | use alloc::vec::Vec; 12 | 13 | use core::num::NonZeroU64; 14 | 15 | use dpi::{PhysicalPosition, PhysicalSize}; 16 | use keyboard_types::Modifiers; 17 | 18 | use crate::ScrollDelta; 19 | 20 | /// A unique identifier for the pointer. 21 | /// 22 | /// PointerId(1) is reserved for the primary pointer. 23 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] 24 | pub struct PointerId(NonZeroU64); 25 | 26 | impl PointerId { 27 | /// The id of the primary pointer. 28 | pub const PRIMARY: Self = Self(NonZeroU64::MIN); 29 | 30 | /// Make a new `PointerId` from a `u64`. 31 | #[inline(always)] 32 | pub fn new(n: u64) -> Option { 33 | NonZeroU64::new(n).map(PointerId) 34 | } 35 | 36 | /// Return `true` if this is the primary `PointerId`. 37 | #[inline(always)] 38 | pub fn is_primary_pointer(self) -> bool { 39 | self == Self::PRIMARY 40 | } 41 | } 42 | 43 | /// An identifier for the pointing device that is stable across the session. 44 | /// 45 | /// PointerId(1) is reserved for the primary pointer. 46 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] 47 | pub struct PersistentDeviceId(NonZeroU64); 48 | 49 | impl PersistentDeviceId { 50 | /// Make a new `PersistentDeviceId` from a `u64`. 51 | #[inline(always)] 52 | pub fn new(n: u64) -> Option { 53 | NonZeroU64::new(n).map(PersistentDeviceId) 54 | } 55 | } 56 | 57 | /// The type of device that has generated a pointer event. 58 | #[non_exhaustive] 59 | #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)] 60 | #[repr(u8)] 61 | pub enum PointerType { 62 | /// The type of device could not be determined. 63 | #[default] 64 | Unknown, 65 | /// A mouse. 66 | Mouse, 67 | /// A pen or stylus. 68 | Pen, 69 | /// A touch contact. 70 | Touch, 71 | } 72 | 73 | /// Identifying information about a pointer, stable across states. 74 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] 75 | pub struct PointerInfo { 76 | /// Pointer ID. 77 | /// 78 | /// [`PointerId::PRIMARY`] is reserved for the primary pointer, 79 | /// so when converting platform pointer IDs on a platform that 80 | /// does not reserve this value, add an offset to avoid collision. 81 | /// 82 | /// `None` is for events not originating from a pointing device. 83 | pub pointer_id: Option, 84 | /// Persistent device ID. 85 | /// 86 | /// This should be set when the platform can identify a given pointing 87 | /// device during the whole session, and associate it with events. 88 | /// If this is not possible for the given event, it should be `None`. 89 | pub persistent_device_id: Option, 90 | /// Pointer type. 91 | pub pointer_type: PointerType, 92 | } 93 | 94 | impl PointerInfo { 95 | /// Returns `true` if this is the primary pointer. 96 | #[inline(always)] 97 | pub fn is_primary_pointer(&self) -> bool { 98 | self.pointer_id.is_some_and(PointerId::is_primary_pointer) 99 | } 100 | } 101 | 102 | /// Orientation of a pointer. 103 | #[derive(Clone, Copy, Debug, PartialEq)] 104 | pub struct PointerOrientation { 105 | /// Spherical altitude. 106 | /// 107 | /// 0 is parallel to the surface, π/2 is perpendicular. 108 | pub altitude: f32, 109 | /// Spherical azimuth. 110 | /// 111 | /// 0 is the positive x axis, π/2 is positive y. 112 | pub azimuth: f32, 113 | } 114 | 115 | impl Default for PointerOrientation { 116 | fn default() -> Self { 117 | Self { 118 | altitude: core::f32::consts::FRAC_PI_2, 119 | azimuth: core::f32::consts::FRAC_PI_2, 120 | } 121 | } 122 | } 123 | 124 | /// The size of an input, usually touch. 125 | /// 126 | /// If this is not provided by the underlying API, platform, or device, 127 | /// then it should be a single pixel. 128 | pub type ContactGeometry = PhysicalSize; 129 | 130 | /// A single pointer state. 131 | #[derive(Clone, Debug, PartialEq)] 132 | pub struct PointerState { 133 | /// `u64` nanoseconds real time. 134 | /// 135 | /// The base time is not important, except by convention, and should 136 | /// generally be the same at least for states originating from the 137 | /// same device. 138 | pub time: u64, 139 | /// Position. 140 | pub position: PhysicalPosition, 141 | /// Pressed buttons. 142 | pub buttons: PointerButtons, 143 | /// Modifiers state. 144 | pub modifiers: Modifiers, 145 | /// Click or tap count associated with the pointer. 146 | pub count: u8, 147 | /// The size of an input, usually touch. 148 | /// 149 | /// If this is not provided by the underlying API, platform, or device, 150 | /// then it should be a single pixel. 151 | pub contact_geometry: ContactGeometry, 152 | /// Orientation. 153 | pub orientation: PointerOrientation, 154 | /// Normalized pressure in range 0..1. 155 | /// 156 | /// Where pressure is not reported by the platform, it 157 | /// is always 0.5 when activated and 0.0 when not. 158 | pub pressure: f32, 159 | /// Normalized ‘tangential pressure’ in range -1..1. 160 | /// 161 | /// This is an arbitrary parameter and, despite its name, 162 | /// it may not originate from a pressure sensitive control. 163 | /// This is often controlled by something like a wheel on the 164 | /// barrel of an ‘airbrush’ style pen. 165 | pub tangential_pressure: f32, 166 | } 167 | 168 | impl Default for PointerState { 169 | fn default() -> Self { 170 | Self { 171 | time: 0, 172 | position: PhysicalPosition::::default(), 173 | buttons: PointerButtons::default(), 174 | modifiers: Modifiers::default(), 175 | count: 0, 176 | contact_geometry: ContactGeometry { 177 | width: 1.0, 178 | height: 1.0, 179 | }, 180 | orientation: PointerOrientation::default(), 181 | // No buttons pressed, therefore no pressure. 182 | pressure: 0.0, 183 | tangential_pressure: 0.0, 184 | } 185 | } 186 | } 187 | 188 | /// A pointer update, along with coalesced and predicted states. 189 | #[derive(Clone, Debug, PartialEq)] 190 | pub struct PointerUpdate { 191 | /// Identifying information about pointer. 192 | pub pointer: PointerInfo, 193 | /// Current state. 194 | pub current: PointerState, 195 | /// Coalesced states, ordered by `time`. 196 | /// 197 | /// Coalescing is application-specific. 198 | /// On the web, the browser does its own coalescing, whereas 199 | /// on other platforms you may do your own, or forego it 200 | /// altogether, delivering every state. 201 | pub coalesced: Vec, 202 | /// Predicted states, ordered by `time`. 203 | /// 204 | /// Some platforms provide predicted states directly, 205 | /// and you may choose to add your own predictor. 206 | pub predicted: Vec, 207 | } 208 | 209 | impl PointerUpdate { 210 | /// Returns `true` if this is the primary pointer. 211 | #[inline(always)] 212 | pub fn is_primary_pointer(&self) -> bool { 213 | self.pointer.is_primary_pointer() 214 | } 215 | } 216 | 217 | /// An event representing a [`PointerButton`] that was pressed or released. 218 | #[derive(Clone, Debug)] 219 | pub struct PointerButtonEvent { 220 | /// The [`PointerButton`] that was pressed. 221 | pub button: Option, 222 | /// Identity of the pointer. 223 | pub pointer: PointerInfo, 224 | /// The state of the pointer (i.e. position, pressure, etc.). 225 | pub state: PointerState, 226 | } 227 | 228 | /// An event representing a scroll 229 | #[derive(Clone, Debug)] 230 | pub struct PointerScrollEvent { 231 | /// Identity of the pointer. 232 | pub pointer: PointerInfo, 233 | /// The delta of the scroll. 234 | pub delta: ScrollDelta, 235 | /// The state of the pointer (i.e. position, pressure, etc.). 236 | pub state: PointerState, 237 | } 238 | 239 | /// A standard `PointerEvent`. 240 | /// 241 | /// This is intentionally limited to standard pointer events, 242 | /// and it is expected that applications and frameworks that 243 | /// support more event types will use this as a base and add 244 | /// what they need in a conversion. 245 | #[derive(Clone, Debug)] 246 | pub enum PointerEvent { 247 | /// A [`PointerButton`] was pressed. 248 | Down(PointerButtonEvent), 249 | /// A [`PointerButton`] was released. 250 | Up(PointerButtonEvent), 251 | /// Pointer moved. 252 | Move(PointerUpdate), 253 | /// Pointer motion was cancelled. 254 | /// 255 | /// Usually this is a touch which was taken over somewhere else. 256 | /// You should try to undo the effect of the gesture when you receive this. 257 | Cancel(PointerInfo), 258 | /// Pointer entered the area that receives this event. 259 | Enter(PointerInfo), 260 | /// Pointer left the area that receives these events. 261 | Leave(PointerInfo), 262 | /// A scroll was requested at the pointer location. 263 | /// 264 | /// Usually this is caused by a mouse wheel or a touchpad. 265 | Scroll(PointerScrollEvent), 266 | } 267 | 268 | impl PointerEvent { 269 | /// Returns `true` if this event is for the primary pointer. 270 | #[inline(always)] 271 | pub fn is_primary_pointer(&self) -> bool { 272 | match self { 273 | Self::Down(PointerButtonEvent { pointer, .. }) 274 | | Self::Up(PointerButtonEvent { pointer, .. }) 275 | | Self::Move(PointerUpdate { pointer, .. }) 276 | | Self::Cancel(pointer) 277 | | Self::Enter(pointer) 278 | | Self::Leave(pointer) 279 | | Self::Scroll(PointerScrollEvent { pointer, .. }) => pointer.is_primary_pointer(), 280 | } 281 | } 282 | } 283 | -------------------------------------------------------------------------------- /ui-events/src/scroll/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2025 the UI Events Authors 2 | // SPDX-License-Identifier: Apache-2.0 OR MIT 3 | 4 | #![allow(missing_docs)] 5 | 6 | use dpi::PhysicalPosition; 7 | 8 | /// Scroll delta. 9 | /// 10 | /// Deltas are in a Y-down coordinate system, and represent a ‘navigation’ 11 | /// direction; a positive Y value means that the viewport should move downward 12 | /// relative to the content. 13 | /// 14 | /// For mouse wheel events, only `LineDelta` and `PixelDelta` are typical. 15 | /// For scroll deltas generated by scrollbars or other elements, `PageDelta` 16 | /// may be used (for example, when clicking in the well of the scrollbar). 17 | #[derive(Clone, Copy, Debug, PartialEq)] 18 | pub enum ScrollDelta { 19 | PageDelta(f32, f32), 20 | 21 | LineDelta(f32, f32), 22 | 23 | PixelDelta(PhysicalPosition), 24 | } 25 | -------------------------------------------------------------------------------- /ui-theme/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 8 | 9 | # Changelog 10 | 11 | The latest published UI Theme release is [0.X.Y](#0XY-2025-01-01) which was released on 2025-01-01. 12 | You can find its changes [documented below](#0XY-2025-01-01). 13 | 14 | ## [Unreleased] 15 | 16 | This release has an [MSRV][] of 1.73. 17 | 18 | This is the initial release. 19 | 20 | [Unreleased]: https://github.com/endoli/ui-events/compare/v0.1.0...HEAD 21 | 22 | [MSRV]: README.md#minimum-supported-rust-version-msrv 23 | -------------------------------------------------------------------------------- /ui-theme/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ui-theme" 3 | version.workspace = true 4 | license.workspace = true 5 | edition.workspace = true 6 | description = "A crate for working with UI theme types." 7 | keywords = ["ui", "theme"] 8 | categories = ["graphics", "gui"] 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | 12 | [package.metadata.docs.rs] 13 | all-features = true 14 | # There are no platform specific docs. 15 | default-target = "x86_64-unknown-linux-gnu" 16 | targets = [] 17 | 18 | [features] 19 | default = ["std"] 20 | std = [] 21 | 22 | [dependencies] 23 | 24 | [lints] 25 | workspace = true 26 | -------------------------------------------------------------------------------- /ui-theme/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | -------------------------------------------------------------------------------- /ui-theme/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /ui-theme/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # UI Theme 4 | 5 | A library for working with UI theme types. 6 | 7 | [![Linebender Zulip, #general channel](https://img.shields.io/badge/Linebender-%23general-blue?logo=Zulip)](https://xi.zulipchat.com/#narrow/channel/147921-general) 8 | [![dependency status](https://deps.rs/repo/github/endoli/ui-events/status.svg)](https://deps.rs/repo/github/endoli/ui-events) 9 | [![Apache 2.0 or MIT license.](https://img.shields.io/badge/license-Apache--2.0_OR_MIT-blue.svg)](#license) 10 | [![Build status](https://github.com/endoli/ui-events/workflows/CI/badge.svg)](https://github.com/endoli/ui-events/actions) 11 | [![Crates.io](https://img.shields.io/crates/v/ui-theme.svg)](https://crates.io/crates/ui-theme) 12 | [![Docs](https://docs.rs/ui-theme/badge.svg)](https://docs.rs/ui-theme) 13 | 14 |
15 | 16 | 20 | 21 | 23 | 24 | 25 | UI Theme is a Rust crate which ... 26 | 27 | ## Features 28 | 29 | - `std` (enabled by default): Use the Rust standard library. 30 | 31 | 32 | 33 | ## Minimum supported Rust Version (MSRV) 34 | 35 | This version of UI Theme has been verified to compile with **Rust 1.73** and later. 36 | The `no_std` build of this library needs **Rust 1.81** and later. 37 | 38 | Future versions of UI Theme might increase the Rust version requirement. 39 | It will not be treated as a breaking change and as such can even happen with small patch releases. 40 | 41 |
42 | Click here if compiling fails. 43 | 44 | As time has passed, some of UI Theme's dependencies could have released versions with a higher Rust requirement. 45 | If you encounter a compilation issue due to a dependency and don't want to upgrade your Rust toolchain, then you could downgrade the dependency. 46 | 47 | ```sh 48 | # Use the problematic dependency's name and version 49 | cargo update -p package_name --precise 0.1.1 50 | ``` 51 | 52 |
53 | 54 | ## Community 55 | 56 | [![Linebender Zulip](https://img.shields.io/badge/Xi%20Zulip-%23general-blue?logo=Zulip)](https://xi.zulipchat.com/#narrow/channel/147921-general) 57 | 58 | Discussion of UI Theme development happens in the [Linebender Zulip](https://xi.zulipchat.com/), specifically the [#general channel](https://xi.zulipchat.com/#narrow/channel/147921-general). 59 | All public content can be read without logging in. 60 | 61 | ## License 62 | 63 | Licensed under either of 64 | 65 | - Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or ) 66 | - MIT license ([LICENSE-MIT](LICENSE-MIT) or ) 67 | 68 | at your option. 69 | 70 | ## Contribution 71 | 72 | Contributions are welcome by pull request. The [Rust code of conduct] applies. 73 | Please feel free to add your name to the [AUTHORS] file in any substantive pull request. 74 | 75 | Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be licensed as above, without any additional terms or conditions. 76 | 77 | [Rust Code of Conduct]: https://www.rust-lang.org/policies/code-of-conduct 78 | [AUTHORS]: ./AUTHORS 79 | -------------------------------------------------------------------------------- /ui-theme/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2025 the UI Events Authors 2 | // SPDX-License-Identifier: Apache-2.0 OR MIT 3 | 4 | //! UI Theme is a Rust crate which ... 5 | //! 6 | //! ## Features 7 | //! 8 | //! - `std` (enabled by default): Use the Rust standard library. 9 | // LINEBENDER LINT SET - lib.rs - v3 10 | // See https://linebender.org/wiki/canonical-lints/ 11 | // These lints shouldn't apply to examples or tests. 12 | #![cfg_attr(not(test), warn(unused_crate_dependencies))] 13 | // These lints shouldn't apply to examples. 14 | #![warn(clippy::print_stdout, clippy::print_stderr)] 15 | // Targeting e.g. 32-bit means structs containing usize can give false positives for 64-bit. 16 | #![cfg_attr(target_pointer_width = "64", warn(clippy::trivially_copy_pass_by_ref))] 17 | // END LINEBENDER LINT SET 18 | #![cfg_attr(docsrs, feature(doc_auto_cfg))] 19 | #![no_std] 20 | 21 | /// The light or dark mode theme. 22 | #[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd)] 23 | #[repr(i8)] 24 | pub enum ColorScheme { 25 | /// The light mode color scheme. 26 | #[default] 27 | Light, 28 | /// The dark mode color scheme. 29 | Dark, 30 | } 31 | --------------------------------------------------------------------------------