├── .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 | [](https://xi.zulipchat.com/#narrow/channel/147921-general)
8 | [](https://deps.rs/repo/github/endoli/ui-events)
9 | [](#license)
10 | [](https://github.com/endoli/ui-events/actions)
11 | [](https://crates.io/crates/ui-events)
12 | [](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 | [](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 | [](https://xi.zulipchat.com/#narrow/channel/147921-general)
8 | [](https://deps.rs/repo/github/endoli/ui-events)
9 | [](#license)
10 | [](https://github.com/endoli/ui-events/actions)
11 | [](https://crates.io/crates/ui-events-winit)
12 | [](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 | [](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 | [](https://xi.zulipchat.com/#narrow/channel/147921-general)
8 | [](https://deps.rs/repo/github/endoli/ui-events)
9 | [](#license)
10 | [](https://github.com/endoli/ui-events/actions)
11 | [](https://crates.io/crates/ui-events)
12 | [](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 | [](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::