diff --git a/.github/workflows/desktop-check.yml b/.github/workflows/desktop-check.yml
new file mode 100644
index 0000000..5b835a6
--- /dev/null
+++ b/.github/workflows/desktop-check.yml
@@ -0,0 +1,74 @@
+name: Desktop compile check
+
+# Compile-checks the Tauri Rust app on all three desktop targets. This is the
+# verification loop for platform-specific capture code (Windows DXGI/WGC, Linux
+# PipeWire via xcap) that can't be built on a macOS dev machine.
+
+on:
+ push:
+ branches:
+ - 'feat/**'
+ - 'fix/**'
+ paths:
+ - 'src-tauri/**'
+ - '.github/workflows/desktop-check.yml'
+ pull_request:
+ branches: [develop, main, 'feat/**']
+ paths:
+ - 'src-tauri/**'
+ workflow_dispatch:
+
+jobs:
+ check:
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - os: ubuntu-24.04
+ - os: windows-latest
+ - os: macos-latest
+ runs-on: ${{ matrix.os }}
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Install Rust
+ uses: dtolnay/rust-toolchain@stable
+
+ - name: Cache cargo
+ uses: Swatinem/rust-cache@v2
+ with:
+ workspaces: src-tauri
+
+ # Tauri + xcap (PipeWire/Wayland/X11/dbus) system deps on Linux.
+ - name: Install Linux deps
+ if: matrix.os == 'ubuntu-24.04'
+ run: |
+ sudo apt-get update
+ sudo apt-get install -y \
+ libwebkit2gtk-4.1-dev \
+ libgtk-3-dev \
+ libayatana-appindicator3-dev \
+ librsvg2-dev \
+ libsoup-3.0-dev \
+ libdbus-1-dev \
+ libpipewire-0.3-dev \
+ libspa-0.2-dev \
+ libwayland-dev \
+ libxcb1-dev \
+ libxcb-randr0-dev \
+ libxcb-shm0-dev \
+ libclang-dev \
+ clang \
+ pkg-config
+
+ # generate_context! embeds the frontend dist at compile time; a stub is
+ # enough for a compile check (we don't need the real built assets here).
+ - name: Stub frontend dist
+ shell: bash
+ run: |
+ mkdir -p dist
+ echo '
stub' > dist/index.html
+
+ - name: cargo check (all targets)
+ working-directory: src-tauri
+ run: cargo check --all-targets
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 5d6ee48..4e90cb4 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -21,7 +21,7 @@ jobs:
- platform: windows-latest
args: ''
label: Windows
- - platform: ubuntu-22.04
+ - platform: ubuntu-24.04
args: ''
label: Linux
@@ -49,14 +49,24 @@ jobs:
workspaces: './src-tauri -> target'
- name: Install Linux system dependencies
- if: matrix.platform == 'ubuntu-22.04'
+ if: matrix.platform == 'ubuntu-24.04'
run: |
sudo apt-get update
sudo apt-get install -y \
libwebkit2gtk-4.1-dev \
libappindicator3-dev \
librsvg2-dev \
- patchelf
+ patchelf \
+ libdbus-1-dev \
+ libpipewire-0.3-dev \
+ libspa-0.2-dev \
+ libwayland-dev \
+ libxcb1-dev \
+ libxcb-randr0-dev \
+ libxcb-shm0-dev \
+ libclang-dev \
+ clang \
+ pkg-config
- name: Install npm dependencies
run: npm ci --legacy-peer-deps
diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock
index a4b9b27..9f85a7e 100644
--- a/src-tauri/Cargo.lock
+++ b/src-tauri/Cargo.lock
@@ -59,6 +59,22 @@ dependencies = [
"libc",
]
+[[package]]
+name = "annotate-snippets"
+version = "0.11.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "710e8eae58854cdc1790fcb56cca04d712a17be849eeb81da2a724bf4bae2bc4"
+dependencies = [
+ "anstyle",
+ "unicode-width",
+]
+
+[[package]]
+name = "anstyle"
+version = "1.0.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000"
+
[[package]]
name = "anyhow"
version = "1.0.103"
@@ -121,32 +137,16 @@ dependencies = [
"stable_deref_trait",
]
-[[package]]
-name = "ashpd"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "01992ad7774250d5b7fe214e2676cb99bf92564436d8135ab44fe815e71769a9"
-dependencies = [
- "async-fs 2.2.0",
- "async-net",
- "enumflags2",
- "futures-channel",
- "futures-util",
- "rand 0.8.7",
- "serde",
- "serde_repr",
- "url",
- "zbus",
-]
-
[[package]]
name = "async-broadcast"
-version = "0.5.1"
+version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7c48ccdbf6ca6b121e0f586cbc0e73ae440e56c67c30fa0873b4e110d9c26d2b"
+checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532"
dependencies = [
- "event-listener 2.5.3",
+ "event-listener",
+ "event-listener-strategy",
"futures-core",
+ "pin-project-lite",
]
[[package]]
@@ -169,55 +169,12 @@ checksum = "c96bf972d85afc50bf5ab8fe2d54d1586b4e0b46c97c50a0c9e71e2f7bcd812a"
dependencies = [
"async-task",
"concurrent-queue",
- "fastrand 2.4.1",
- "futures-lite 2.6.1",
+ "fastrand",
+ "futures-lite",
"pin-project-lite",
"slab",
]
-[[package]]
-name = "async-fs"
-version = "1.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "279cf904654eeebfa37ac9bb1598880884924aab82e290aa65c9e77a0e142e06"
-dependencies = [
- "async-lock 2.8.0",
- "autocfg",
- "blocking",
- "futures-lite 1.13.0",
-]
-
-[[package]]
-name = "async-fs"
-version = "2.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8034a681df4aed8b8edbd7fbe472401ecf009251c8b40556b304567052e294c5"
-dependencies = [
- "async-lock 3.4.2",
- "blocking",
- "futures-lite 2.6.1",
-]
-
-[[package]]
-name = "async-io"
-version = "1.13.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af"
-dependencies = [
- "async-lock 2.8.0",
- "autocfg",
- "cfg-if",
- "concurrent-queue",
- "futures-lite 1.13.0",
- "log",
- "parking",
- "polling 2.8.0",
- "rustix 0.37.28",
- "slab",
- "socket2 0.4.10",
- "waker-fn",
-]
-
[[package]]
name = "async-io"
version = "2.6.0"
@@ -228,60 +185,41 @@ dependencies = [
"cfg-if",
"concurrent-queue",
"futures-io",
- "futures-lite 2.6.1",
+ "futures-lite",
"parking",
- "polling 3.11.0",
+ "polling",
"rustix 1.1.4",
"slab",
"windows-sys 0.61.2",
]
-[[package]]
-name = "async-lock"
-version = "2.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b"
-dependencies = [
- "event-listener 2.5.3",
-]
-
[[package]]
name = "async-lock"
version = "3.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311"
dependencies = [
- "event-listener 5.4.1",
+ "event-listener",
"event-listener-strategy",
"pin-project-lite",
]
-[[package]]
-name = "async-net"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b948000fad4873c1c9339d60f2623323a0cfd3816e5181033c6a5cb68b2accf7"
-dependencies = [
- "async-io 2.6.0",
- "blocking",
- "futures-lite 2.6.1",
-]
-
[[package]]
name = "async-process"
-version = "1.8.1"
+version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea6438ba0a08d81529c69b36700fa2f95837bfe3e776ab39cde9c14d9149da88"
+checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75"
dependencies = [
- "async-io 1.13.0",
- "async-lock 2.8.0",
+ "async-channel",
+ "async-io",
+ "async-lock",
"async-signal",
+ "async-task",
"blocking",
"cfg-if",
- "event-listener 3.1.0",
- "futures-lite 1.13.0",
- "rustix 0.38.44",
- "windows-sys 0.48.0",
+ "event-listener",
+ "futures-lite",
+ "rustix 1.1.4",
]
[[package]]
@@ -301,8 +239,8 @@ version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52b5aaafa020cf5053a01f2a60e8ff5dccf550f0f77ec54a4e47285ac2bab485"
dependencies = [
- "async-io 2.6.0",
- "async-lock 3.4.2",
+ "async-io",
+ "async-lock",
"atomic-waker",
"cfg-if",
"futures-core",
@@ -350,7 +288,7 @@ dependencies = [
"glib-sys",
"gobject-sys",
"libc",
- "system-deps",
+ "system-deps 6.2.2",
]
[[package]]
@@ -394,7 +332,7 @@ dependencies = [
"anyhow",
"arrayvec",
"log",
- "nom",
+ "nom 8.0.0",
"num-rational",
"v_frame",
]
@@ -420,6 +358,25 @@ version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
+[[package]]
+name = "bindgen"
+version = "0.72.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895"
+dependencies = [
+ "annotate-snippets",
+ "bitflags 2.13.0",
+ "cexpr",
+ "clang-sys",
+ "itertools 0.13.0",
+ "proc-macro2",
+ "quote",
+ "regex",
+ "rustc-hash",
+ "shlex 1.3.0",
+ "syn 2.0.118",
+]
+
[[package]]
name = "bit-set"
version = "0.8.0"
@@ -498,7 +455,7 @@ dependencies = [
"async-channel",
"async-task",
"futures-io",
- "futures-lite 2.6.1",
+ "futures-lite",
"piper",
]
@@ -549,6 +506,20 @@ name = "bytemuck"
version = "1.25.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6aedf8ae72766347502cf3cb4f41cf5e9cc37d28bee90f1fdaaae15f9cf9424"
+dependencies = [
+ "bytemuck_derive",
+]
+
+[[package]]
+name = "bytemuck_derive"
+version = "1.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f65693059b6b9c588b9f62fed1cedbf0a8b805631457ea162d68f0de186f3de5"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.118",
+]
[[package]]
name = "byteorder"
@@ -593,7 +564,7 @@ checksum = "685c9fa8e590b8b3d678873528d83411db17242a73fccaed827770ea0fedda51"
dependencies = [
"glib-sys",
"libc",
- "system-deps",
+ "system-deps 6.2.2",
]
[[package]]
@@ -647,7 +618,7 @@ dependencies = [
"find-msvc-tools",
"jobserver",
"libc",
- "shlex",
+ "shlex 2.0.1",
]
[[package]]
@@ -656,6 +627,15 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c"
+[[package]]
+name = "cexpr"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
+dependencies = [
+ "nom 7.1.3",
+]
+
[[package]]
name = "cfb"
version = "0.7.3"
@@ -674,7 +654,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02"
dependencies = [
"smallvec",
- "target-lexicon",
+ "target-lexicon 0.12.16",
+]
+
+[[package]]
+name = "cfg-expr"
+version = "0.20.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fb693542bcafa528e198be0ebd9d3632ca5b7c93dbe7237460e199910835997c"
+dependencies = [
+ "smallvec",
+ "target-lexicon 0.13.5",
]
[[package]]
@@ -683,6 +673,17 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
+[[package]]
+name = "chacha20"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81"
+dependencies = [
+ "cfg-if",
+ "cpufeatures 0.3.0",
+ "rand_core 0.10.1",
+]
+
[[package]]
name = "chrono"
version = "0.4.45"
@@ -697,6 +698,17 @@ dependencies = [
"windows-link 0.2.1",
]
+[[package]]
+name = "clang-sys"
+version = "1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
+dependencies = [
+ "glob",
+ "libc",
+ "libloading 0.8.9",
+]
+
[[package]]
name = "clipboard-win"
version = "5.4.1"
@@ -771,6 +783,12 @@ dependencies = [
"version_check",
]
+[[package]]
+name = "cookie-factory"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9885fa71e26b8ab7855e2ec7cae6e9b380edff76cd052e07c683a0319d51b3a2"
+
[[package]]
name = "core-foundation"
version = "0.9.4"
@@ -854,6 +872,15 @@ dependencies = [
"libc",
]
+[[package]]
+name = "cpufeatures"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201"
+dependencies = [
+ "libc",
+]
+
[[package]]
name = "crc32fast"
version = "1.5.0"
@@ -1006,17 +1033,6 @@ dependencies = [
"serde_core",
]
-[[package]]
-name = "derivative"
-version = "2.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 1.0.109",
-]
-
[[package]]
name = "derive_arbitrary"
version = "1.4.2"
@@ -1103,6 +1119,15 @@ dependencies = [
"syn 2.0.118",
]
+[[package]]
+name = "dlib"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ab8ecd87370524b461f8557c119c405552c396ed91fc0a8eec68679eab26f94a"
+dependencies = [
+ "libloading 0.7.4",
+]
+
[[package]]
name = "dlopen2"
version = "0.8.2"
@@ -1156,6 +1181,61 @@ dependencies = [
"serde",
]
+[[package]]
+name = "drm"
+version = "0.14.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "80bc8c5c6c2941f70a55c15f8d9f00f9710ebda3ffda98075f996a0e6c92756f"
+dependencies = [
+ "bitflags 2.13.0",
+ "bytemuck",
+ "drm-ffi",
+ "drm-fourcc",
+ "libc",
+ "rustix 0.38.44",
+]
+
+[[package]]
+name = "drm"
+version = "0.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a41816e58f47f49acfd956651055ddcf137c4882c2098c30c448817af21183a"
+dependencies = [
+ "bitflags 2.13.0",
+ "bytemuck",
+ "bytemuck_derive",
+ "drm-ffi",
+ "drm-fourcc",
+ "libc",
+ "rustix 1.1.4",
+]
+
+[[package]]
+name = "drm-ffi"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51a91c9b32ac4e8105dec255e849e0d66e27d7c34d184364fb93e469db08f690"
+dependencies = [
+ "drm-sys",
+ "rustix 1.1.4",
+]
+
+[[package]]
+name = "drm-fourcc"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0aafbcdb8afc29c1a7ee5fbe53b5d62f4565b35a042a662ca9fecd0b54dae6f4"
+
+[[package]]
+name = "drm-sys"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ecc8e1361066d91f5ffccff060a3c3be9c3ecde15be2959c1937595f7a82a9f8"
+dependencies = [
+ "libc",
+ "linux-raw-sys 0.9.4",
+]
+
[[package]]
name = "dtoa"
version = "1.0.11"
@@ -1233,6 +1313,12 @@ dependencies = [
"cfg-if",
]
+[[package]]
+name = "endi"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099"
+
[[package]]
name = "enumflags2"
version = "0.7.12"
@@ -1307,23 +1393,6 @@ version = "3.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dea2df4cf52843e0452895c455a1a2cfbb842a1e7329671acf418fdc53ed4c59"
-[[package]]
-name = "event-listener"
-version = "2.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
-
-[[package]]
-name = "event-listener"
-version = "3.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d93877bcde0eb80ca09131a08d23f0a5c18a620b01db137dba666d18cd9b30c2"
-dependencies = [
- "concurrent-queue",
- "parking",
- "pin-project-lite",
-]
-
[[package]]
name = "event-listener"
version = "5.4.1"
@@ -1341,7 +1410,7 @@ version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93"
dependencies = [
- "event-listener 5.4.1",
+ "event-listener",
"pin-project-lite",
]
@@ -1362,15 +1431,6 @@ dependencies = [
"zune-inflate",
]
-[[package]]
-name = "fastrand"
-version = "1.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
-dependencies = [
- "instant",
-]
-
[[package]]
name = "fastrand"
version = "2.4.1"
@@ -1398,7 +1458,7 @@ version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f"
dependencies = [
- "memoffset 0.9.1",
+ "memoffset",
"rustc_version",
]
@@ -1520,28 +1580,13 @@ version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718"
-[[package]]
-name = "futures-lite"
-version = "1.13.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce"
-dependencies = [
- "fastrand 1.9.0",
- "futures-core",
- "futures-io",
- "memchr",
- "parking",
- "pin-project-lite",
- "waker-fn",
-]
-
[[package]]
name = "futures-lite"
version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad"
dependencies = [
- "fastrand 2.4.1",
+ "fastrand",
"futures-core",
"futures-io",
"parking",
@@ -1587,6 +1632,30 @@ dependencies = [
"slab",
]
+[[package]]
+name = "gbm"
+version = "0.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce852e998d3ca5e4a97014fb31c940dc5ef344ec7d364984525fd11e8a547e6a"
+dependencies = [
+ "bitflags 2.13.0",
+ "drm 0.14.1",
+ "drm-fourcc",
+ "gbm-sys",
+ "libc",
+ "wayland-backend",
+ "wayland-server",
+]
+
+[[package]]
+name = "gbm-sys"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c13a5f2acc785d8fb6bf6b7ab6bfb0ef5dad4f4d97e8e70bb8e470722312f76f"
+dependencies = [
+ "libc",
+]
+
[[package]]
name = "gdk"
version = "0.18.2"
@@ -1625,7 +1694,7 @@ dependencies = [
"glib-sys",
"gobject-sys",
"libc",
- "system-deps",
+ "system-deps 6.2.2",
]
[[package]]
@@ -1642,7 +1711,7 @@ dependencies = [
"libc",
"pango-sys",
"pkg-config",
- "system-deps",
+ "system-deps 6.2.2",
]
[[package]]
@@ -1656,7 +1725,7 @@ dependencies = [
"gobject-sys",
"libc",
"pkg-config",
- "system-deps",
+ "system-deps 6.2.2",
]
[[package]]
@@ -1682,7 +1751,7 @@ dependencies = [
"gdk-sys",
"glib-sys",
"libc",
- "system-deps",
+ "system-deps 6.2.2",
"x11",
]
@@ -1738,6 +1807,7 @@ dependencies = [
"cfg-if",
"libc",
"r-efi 6.0.0",
+ "rand_core 0.10.1",
]
[[package]]
@@ -1778,10 +1848,30 @@ dependencies = [
"glib-sys",
"gobject-sys",
"libc",
- "system-deps",
+ "system-deps 6.2.2",
"winapi",
]
+[[package]]
+name = "gl"
+version = "0.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a94edab108827d67608095e269cf862e60d920f144a5026d3dbcfd8b877fb404"
+dependencies = [
+ "gl_generator",
+]
+
+[[package]]
+name = "gl_generator"
+version = "0.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d"
+dependencies = [
+ "khronos_api",
+ "log",
+ "xml-rs",
+]
+
[[package]]
name = "glib"
version = "0.18.5"
@@ -1826,7 +1916,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "063ce2eb6a8d0ea93d2bf8ba1957e78dbab6be1c2220dd3daca57d5a9d869898"
dependencies = [
"libc",
- "system-deps",
+ "system-deps 6.2.2",
]
[[package]]
@@ -1861,14 +1951,13 @@ checksum = "0850127b514d1c4a4654ead6dedadb18198999985908e6ffe4436f53c785ce44"
dependencies = [
"glib-sys",
"libc",
- "system-deps",
+ "system-deps 6.2.2",
]
[[package]]
name = "goodwebtools"
version = "1.0.0"
dependencies = [
- "ashpd",
"chrono",
"cocoa",
"core-graphics 0.23.2",
@@ -1886,7 +1975,7 @@ dependencies = [
"tauri-plugin-shell",
"tauri-plugin-updater",
"tokio",
- "windows 0.54.0",
+ "xcap",
]
[[package]]
@@ -1925,7 +2014,7 @@ dependencies = [
"gobject-sys",
"libc",
"pango-sys",
- "system-deps",
+ "system-deps 6.2.2",
]
[[package]]
@@ -1985,12 +2074,6 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
-[[package]]
-name = "hermit-abi"
-version = "0.3.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
-
[[package]]
name = "hermit-abi"
version = "0.5.2"
@@ -2104,7 +2187,7 @@ dependencies = [
"libc",
"percent-encoding",
"pin-project-lite",
- "socket2 0.6.5",
+ "socket2",
"tokio",
"tower-service",
"tracing",
@@ -2325,15 +2408,6 @@ dependencies = [
"cfb",
]
-[[package]]
-name = "instant"
-version = "0.1.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222"
-dependencies = [
- "cfg-if",
-]
-
[[package]]
name = "interpolate_name"
version = "0.2.4"
@@ -2345,17 +2419,6 @@ dependencies = [
"syn 2.0.118",
]
-[[package]]
-name = "io-lifetimes"
-version = "1.0.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
-dependencies = [
- "hermit-abi 0.3.9",
- "libc",
- "windows-sys 0.48.0",
-]
-
[[package]]
name = "ipnet"
version = "2.12.0"
@@ -2381,6 +2444,15 @@ dependencies = [
"once_cell",
]
+[[package]]
+name = "itertools"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
+dependencies = [
+ "either",
+]
+
[[package]]
name = "itertools"
version = "0.14.0"
@@ -2416,7 +2488,7 @@ dependencies = [
"glib-sys",
"gobject-sys",
"libc",
- "system-deps",
+ "system-deps 6.2.2",
]
[[package]]
@@ -2547,6 +2619,22 @@ dependencies = [
"unicode-segmentation",
]
+[[package]]
+name = "khronos-egl"
+version = "6.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76"
+dependencies = [
+ "libc",
+ "pkg-config",
+]
+
+[[package]]
+name = "khronos_api"
+version = "3.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"
+
[[package]]
name = "lazy_static"
version = "1.5.0"
@@ -2579,7 +2667,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e9ec52138abedcc58dc17a7c6c0c00a2bdb4f3427c7f63fa97fd0d859155caf"
dependencies = [
"gtk-sys",
- "libloading",
+ "libloading 0.7.4",
"once_cell",
]
@@ -2618,6 +2706,16 @@ dependencies = [
"winapi",
]
+[[package]]
+name = "libloading"
+version = "0.8.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55"
+dependencies = [
+ "cfg-if",
+ "windows-link 0.2.1",
+]
+
[[package]]
name = "libm"
version = "0.2.16"
@@ -2634,10 +2732,52 @@ dependencies = [
]
[[package]]
-name = "linux-raw-sys"
-version = "0.3.8"
+name = "libspa"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2909f3be29d674e7f10604aff18d1bbe1bb03c4cd61c8a8ba19c0b1d162f7d4e"
+dependencies = [
+ "bitflags 2.13.0",
+ "cc",
+ "cookie-factory",
+ "libc",
+ "libspa-sys",
+ "nom 8.0.0",
+ "rustix 1.1.4",
+ "system-deps 7.0.8",
+]
+
+[[package]]
+name = "libspa-sys"
+version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
+checksum = "69ad52764fca54818486f3cf75afec844d1f1a1568c24dcee25d41b1ab007dda"
+dependencies = [
+ "bindgen",
+ "cc",
+ "system-deps 7.0.8",
+]
+
+[[package]]
+name = "libwayshot-xcap"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea8a46e4d016ef464e386e4970f5415fe0939c2d63abe0c2f539c05ef88c5fe5"
+dependencies = [
+ "drm 0.15.0",
+ "gbm",
+ "gl",
+ "image",
+ "khronos-egl",
+ "memmap2",
+ "rustix 1.1.4",
+ "thiserror 2.0.18",
+ "tracing",
+ "wayland-backend",
+ "wayland-client",
+ "wayland-protocols",
+ "wayland-protocols-wlr",
+]
[[package]]
name = "linux-raw-sys"
@@ -2645,6 +2785,12 @@ version = "0.4.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
+[[package]]
+name = "linux-raw-sys"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12"
+
[[package]]
name = "linux-raw-sys"
version = "0.12.1"
@@ -2718,12 +2864,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
[[package]]
-name = "memoffset"
-version = "0.7.1"
+name = "memmap2"
+version = "0.9.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
+checksum = "d1219ed1b7f229ee7104d281dd01d6802fe28bb6e95d292942c4daacdeb798c0"
dependencies = [
- "autocfg",
+ "libc",
]
[[package]]
@@ -2741,6 +2887,12 @@ version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
+[[package]]
+name = "minimal-lexical"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
+
[[package]]
name = "minisign-verify"
version = "0.2.5"
@@ -2830,24 +2982,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086"
[[package]]
-name = "nix"
-version = "0.26.4"
+name = "no_std_io2"
+version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b"
+checksum = "418abd1b6d34fbf6cae440dc874771b0525a604428704c76e48b29a5e67b8003"
dependencies = [
- "bitflags 1.3.2",
- "cfg-if",
- "libc",
- "memoffset 0.7.1",
+ "memchr",
]
[[package]]
-name = "no_std_io2"
-version = "0.9.4"
+name = "nom"
+version = "7.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "418abd1b6d34fbf6cae440dc874771b0525a604428704c76e48b29a5e67b8003"
+checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
dependencies = [
"memchr",
+ "minimal-lexical",
]
[[package]]
@@ -2980,9 +3130,48 @@ checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c"
dependencies = [
"bitflags 2.13.0",
"block2",
+ "libc",
+ "objc2",
+ "objc2-cloud-kit",
+ "objc2-core-data",
+ "objc2-core-foundation",
+ "objc2-core-graphics",
+ "objc2-core-image",
+ "objc2-core-text",
+ "objc2-core-video",
+ "objc2-foundation",
+ "objc2-quartz-core",
+]
+
+[[package]]
+name = "objc2-av-foundation"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "478ae33fcac9df0a18db8302387c666b8ef08a3e2d62b510ca4fc278a384b6c0"
+dependencies = [
+ "bitflags 2.13.0",
+ "block2",
+ "dispatch2",
"objc2",
+ "objc2-avf-audio",
+ "objc2-core-audio-types",
"objc2-core-foundation",
"objc2-core-graphics",
+ "objc2-core-image",
+ "objc2-core-video",
+ "objc2-foundation",
+ "objc2-image-io",
+ "objc2-media-toolbox",
+ "objc2-quartz-core",
+]
+
+[[package]]
+name = "objc2-avf-audio"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13a380031deed8e99db00065c45937da434ca987c034e13b87e4441f9e4090be"
+dependencies = [
+ "objc2",
"objc2-foundation",
]
@@ -2997,12 +3186,35 @@ dependencies = [
"objc2-foundation",
]
+[[package]]
+name = "objc2-core-audio"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e1eebcea8b0dbff5f7c8504f3107c68fc061a3eb44932051c8cf8a68d969c3b2"
+dependencies = [
+ "dispatch2",
+ "objc2",
+ "objc2-core-audio-types",
+ "objc2-core-foundation",
+]
+
+[[package]]
+name = "objc2-core-audio-types"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a89f2ec274a0cf4a32642b2991e8b351a404d290da87bb6a9a9d8632490bd1c"
+dependencies = [
+ "bitflags 2.13.0",
+ "objc2",
+]
+
[[package]]
name = "objc2-core-data"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa"
dependencies = [
+ "bitflags 2.13.0",
"objc2",
"objc2-foundation",
]
@@ -3014,7 +3226,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536"
dependencies = [
"bitflags 2.13.0",
+ "block2",
"dispatch2",
+ "libc",
"objc2",
]
@@ -3025,10 +3239,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807"
dependencies = [
"bitflags 2.13.0",
+ "block2",
"dispatch2",
+ "libc",
"objc2",
"objc2-core-foundation",
"objc2-io-surface",
+ "objc2-metal",
]
[[package]]
@@ -3051,6 +3268,22 @@ dependencies = [
"objc2-foundation",
]
+[[package]]
+name = "objc2-core-media"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05ec576860167a15dd9fce7fbee7512beb4e31f532159d3482d1f9c6caedf31d"
+dependencies = [
+ "bitflags 2.13.0",
+ "block2",
+ "dispatch2",
+ "objc2",
+ "objc2-core-audio",
+ "objc2-core-audio-types",
+ "objc2-core-foundation",
+ "objc2-core-video",
+]
+
[[package]]
name = "objc2-core-text"
version = "0.3.2"
@@ -3063,6 +3296,21 @@ dependencies = [
"objc2-core-graphics",
]
+[[package]]
+name = "objc2-core-video"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d425caf1df73233f29fd8a5c3e5edbc30d2d4307870f802d18f00d83dc5141a6"
+dependencies = [
+ "bitflags 2.13.0",
+ "block2",
+ "objc2",
+ "objc2-core-foundation",
+ "objc2-core-graphics",
+ "objc2-io-surface",
+ "objc2-metal",
+]
+
[[package]]
name = "objc2-encode"
version = "4.1.0"
@@ -3091,6 +3339,17 @@ dependencies = [
"objc2-core-foundation",
]
+[[package]]
+name = "objc2-image-io"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32b0446e98cf4a784cc7a0177715ff317eeaa8463841c616cfc78aa4f953c4ea"
+dependencies = [
+ "objc2",
+ "objc2-core-foundation",
+ "objc2-core-graphics",
+]
+
[[package]]
name = "objc2-io-surface"
version = "0.3.2"
@@ -3102,6 +3361,29 @@ dependencies = [
"objc2-core-foundation",
]
+[[package]]
+name = "objc2-media-toolbox"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "edd9fdde720df3da7046bb9097811000c1e7ab5cd579fa89d96b27d56781fb30"
+dependencies = [
+ "objc2",
+ "objc2-core-audio-types",
+ "objc2-core-foundation",
+ "objc2-core-media",
+]
+
+[[package]]
+name = "objc2-metal"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a0125f776a10d00af4152d74616409f0d4a2053a6f57fa5b7d6aa2854ac04794"
+dependencies = [
+ "bitflags 2.13.0",
+ "objc2",
+ "objc2-foundation",
+]
+
[[package]]
name = "objc2-osa-kit"
version = "0.3.2"
@@ -3256,7 +3538,7 @@ dependencies = [
"glib-sys",
"gobject-sys",
"libc",
- "system-deps",
+ "system-deps 6.2.2",
]
[[package]]
@@ -3344,7 +3626,7 @@ version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737"
dependencies = [
- "fastrand 2.4.1",
+ "fastrand",
"phf_shared",
]
@@ -3383,10 +3665,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1"
dependencies = [
"atomic-waker",
- "fastrand 2.4.1",
+ "fastrand",
"futures-io",
]
+[[package]]
+name = "pipewire"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8585aba8a52ad74ccc633b8e293c1dc4277976bd5d510b925533f34fd6685f38"
+dependencies = [
+ "bitflags 2.13.0",
+ "libc",
+ "libspa",
+ "libspa-sys",
+ "pipewire-sys",
+ "rustix 1.1.4",
+]
+
+[[package]]
+name = "pipewire-sys"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2089f245b548723e60325773c27f586b7a2372c79ea941b246cd0d654706adc"
+dependencies = [
+ "bindgen",
+ "libspa-sys",
+ "system-deps 7.0.8",
+]
+
[[package]]
name = "pkg-config"
version = "0.3.33"
@@ -3422,30 +3729,14 @@ dependencies = [
[[package]]
name = "png"
version = "0.18.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61"
-dependencies = [
- "bitflags 2.13.0",
- "crc32fast",
- "fdeflate",
- "flate2",
- "miniz_oxide",
-]
-
-[[package]]
-name = "polling"
-version = "2.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce"
-dependencies = [
- "autocfg",
- "bitflags 1.3.2",
- "cfg-if",
- "concurrent-queue",
- "libc",
- "log",
- "pin-project-lite",
- "windows-sys 0.48.0",
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61"
+dependencies = [
+ "bitflags 2.13.0",
+ "crc32fast",
+ "fdeflate",
+ "flate2",
+ "miniz_oxide",
]
[[package]]
@@ -3456,7 +3747,7 @@ checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218"
dependencies = [
"cfg-if",
"concurrent-queue",
- "hermit-abi 0.5.2",
+ "hermit-abi",
"pin-project-lite",
"rustix 1.1.4",
"windows-sys 0.61.2",
@@ -3617,6 +3908,15 @@ version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3"
+[[package]]
+name = "quick-xml"
+version = "0.30.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eff6510e86862b57b210fd8cbe8ed3f0d7d600b9c2863cd4549a2e033c66e956"
+dependencies = [
+ "memchr",
+]
+
[[package]]
name = "quick-xml"
version = "0.39.4"
@@ -3656,35 +3956,25 @@ version = "6.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
-[[package]]
-name = "rand"
-version = "0.8.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "22f6172bdec972074665ed81ed53b71da00bfc44b65a753cfde883ec4c702a1a"
-dependencies = [
- "libc",
- "rand_chacha 0.3.1",
- "rand_core 0.6.4",
-]
-
[[package]]
name = "rand"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41"
dependencies = [
- "rand_chacha 0.9.0",
+ "rand_chacha",
"rand_core 0.9.5",
]
[[package]]
-name = "rand_chacha"
-version = "0.3.1"
+name = "rand"
+version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80"
dependencies = [
- "ppv-lite86",
- "rand_core 0.6.4",
+ "chacha20",
+ "getrandom 0.4.3",
+ "rand_core 0.10.1",
]
[[package]]
@@ -3699,21 +3989,18 @@ dependencies = [
[[package]]
name = "rand_core"
-version = "0.6.4"
+version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c"
dependencies = [
- "getrandom 0.2.17",
+ "getrandom 0.3.4",
]
[[package]]
name = "rand_core"
-version = "0.9.5"
+version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c"
-dependencies = [
- "getrandom 0.3.4",
-]
+checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69"
[[package]]
name = "rav1e"
@@ -3731,7 +4018,7 @@ dependencies = [
"built",
"cfg-if",
"interpolate_name",
- "itertools",
+ "itertools 0.14.0",
"libc",
"libfuzzer-sys",
"log",
@@ -3743,7 +4030,7 @@ dependencies = [
"paste",
"profiling",
"rand 0.9.5",
- "rand_chacha 0.9.0",
+ "rand_chacha",
"simd_helpers",
"thiserror 2.0.18",
"v_frame",
@@ -3973,20 +4260,6 @@ dependencies = [
"semver",
]
-[[package]]
-name = "rustix"
-version = "0.37.28"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "519165d378b97752ca44bbe15047d5d3409e875f39327546b42ac81d7e18c1b6"
-dependencies = [
- "bitflags 1.3.2",
- "errno",
- "io-lifetimes",
- "libc",
- "linux-raw-sys 0.3.8",
- "windows-sys 0.48.0",
-]
-
[[package]]
name = "rustix"
version = "0.38.44"
@@ -4161,6 +4434,12 @@ dependencies = [
"syn 2.0.118",
]
+[[package]]
+name = "scoped-tls"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
+
[[package]]
name = "scopeguard"
version = "1.2.0"
@@ -4377,17 +4656,6 @@ dependencies = [
"stable_deref_trait",
]
-[[package]]
-name = "sha1"
-version = "0.10.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a978451301f4db1d02937a4ab3ccce137717b81826e79b7d49ffe3244a13c3b8"
-dependencies = [
- "cfg-if",
- "cpufeatures",
- "digest",
-]
-
[[package]]
name = "sha2"
version = "0.10.9"
@@ -4395,7 +4663,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
dependencies = [
"cfg-if",
- "cpufeatures",
+ "cpufeatures 0.2.17",
"digest",
]
@@ -4410,6 +4678,12 @@ dependencies = [
"windows-sys 0.60.2",
]
+[[package]]
+name = "shlex"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+
[[package]]
name = "shlex"
version = "2.0.1"
@@ -4496,16 +4770,6 @@ version = "1.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90"
-[[package]]
-name = "socket2"
-version = "0.4.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d"
-dependencies = [
- "libc",
- "winapi",
-]
-
[[package]]
name = "socket2"
version = "0.6.5"
@@ -4561,7 +4825,7 @@ dependencies = [
"glib-sys",
"gobject-sys",
"libc",
- "system-deps",
+ "system-deps 6.2.2",
]
[[package]]
@@ -4570,12 +4834,6 @@ version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
-[[package]]
-name = "static_assertions"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
-
[[package]]
name = "string_cache"
version = "0.9.0"
@@ -4630,7 +4888,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
- "quote",
"unicode-ident",
]
@@ -4671,13 +4928,26 @@ version = "6.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349"
dependencies = [
- "cfg-expr",
+ "cfg-expr 0.15.8",
"heck 0.5.0",
"pkg-config",
"toml 0.8.2",
"version-compare",
]
+[[package]]
+name = "system-deps"
+version = "7.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "396a35feb67335377e0251fcbc1092fc85c484bd4e3a7a54319399da127796e7"
+dependencies = [
+ "cfg-expr 0.20.8",
+ "heck 0.5.0",
+ "pkg-config",
+ "toml 1.1.3+spec-1.1.0",
+ "version-compare",
+]
+
[[package]]
name = "tao"
version = "0.35.3"
@@ -4746,6 +5016,12 @@ version = "0.12.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
+[[package]]
+name = "target-lexicon"
+version = "0.13.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
+
[[package]]
name = "tauri"
version = "2.11.5"
@@ -5107,7 +5383,7 @@ version = "3.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
dependencies = [
- "fastrand 2.4.1",
+ "fastrand",
"getrandom 0.4.3",
"once_cell",
"rustix 1.1.4",
@@ -5244,7 +5520,7 @@ dependencies = [
"parking_lot",
"pin-project-lite",
"signal-hook-registry",
- "socket2 0.6.5",
+ "socket2",
"tokio-macros",
"windows-sys 0.61.2",
]
@@ -5508,7 +5784,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8765b90061cba6c22b5831f675da109ae5561588290f9fa2317adab2714d5a6"
dependencies = [
"memchr",
- "nom",
+ "nom 8.0.0",
"petgraph",
]
@@ -5536,7 +5812,7 @@ version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e"
dependencies = [
- "memoffset 0.9.1",
+ "memoffset",
"tempfile",
"windows-sys 0.61.2",
]
@@ -5594,6 +5870,12 @@ version = "1.13.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8"
+[[package]]
+name = "unicode-width"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254"
+
[[package]]
name = "untrusted"
version = "0.9.0"
@@ -5686,12 +5968,6 @@ dependencies = [
"libc",
]
-[[package]]
-name = "waker-fn"
-version = "1.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7"
-
[[package]]
name = "walkdir"
version = "2.5.0"
@@ -5803,6 +6079,7 @@ dependencies = [
"cc",
"downcast-rs",
"rustix 1.1.4",
+ "scoped-tls",
"smallvec",
"wayland-sys",
]
@@ -5855,12 +6132,29 @@ dependencies = [
"quote",
]
+[[package]]
+name = "wayland-server"
+version = "0.31.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cc1846eb04c49182e04f4a099e2a830a2b745610bbc1d61246e206f29c7000a0"
+dependencies = [
+ "bitflags 2.13.0",
+ "downcast-rs",
+ "rustix 1.1.4",
+ "wayland-backend",
+ "wayland-scanner",
+]
+
[[package]]
name = "wayland-sys"
version = "0.31.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8eab23fefc9e41f8e841df4a9c707e8a8c4ed26e944ef69297184de2785e3be"
dependencies = [
+ "dlib",
+ "libc",
+ "log",
+ "memoffset",
"pkg-config",
]
@@ -5927,7 +6221,7 @@ dependencies = [
"libc",
"pkg-config",
"soup3-sys",
- "system-deps",
+ "system-deps 6.2.2",
]
[[package]]
@@ -5981,6 +6275,12 @@ version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88"
+[[package]]
+name = "widestring"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72069c3113ab32ab29e5584db3c6ec55d416895e60715417b5b883a357c3e471"
+
[[package]]
name = "winapi"
version = "0.3.9"
@@ -6029,25 +6329,27 @@ dependencies = [
[[package]]
name = "windows"
-version = "0.54.0"
+version = "0.61.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9252e5725dbed82865af151df558e754e4a3c2c30818359eb17465f1346a1b49"
+checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893"
dependencies = [
- "windows-core 0.54.0",
- "windows-targets 0.52.6",
+ "windows-collections 0.2.0",
+ "windows-core 0.61.2",
+ "windows-future 0.2.1",
+ "windows-link 0.1.3",
+ "windows-numerics 0.2.0",
]
[[package]]
name = "windows"
-version = "0.61.3"
+version = "0.62.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893"
+checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580"
dependencies = [
- "windows-collections",
- "windows-core 0.61.2",
- "windows-future",
- "windows-link 0.1.3",
- "windows-numerics",
+ "windows-collections 0.3.2",
+ "windows-core 0.62.2",
+ "windows-future 0.3.2",
+ "windows-numerics 0.3.1",
]
[[package]]
@@ -6060,13 +6362,12 @@ dependencies = [
]
[[package]]
-name = "windows-core"
-version = "0.54.0"
+name = "windows-collections"
+version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "12661b9c89351d684a50a8a643ce5f608e20243b9fb84687800163429f161d65"
+checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610"
dependencies = [
- "windows-result 0.1.2",
- "windows-targets 0.52.6",
+ "windows-core 0.62.2",
]
[[package]]
@@ -6103,7 +6404,18 @@ checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e"
dependencies = [
"windows-core 0.61.2",
"windows-link 0.1.3",
- "windows-threading",
+ "windows-threading 0.1.0",
+]
+
+[[package]]
+name = "windows-future"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb"
+dependencies = [
+ "windows-core 0.62.2",
+ "windows-link 0.2.1",
+ "windows-threading 0.2.1",
]
[[package]]
@@ -6151,12 +6463,13 @@ dependencies = [
]
[[package]]
-name = "windows-result"
-version = "0.1.2"
+name = "windows-numerics"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8"
+checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26"
dependencies = [
- "windows-targets 0.52.6",
+ "windows-core 0.62.2",
+ "windows-link 0.2.1",
]
[[package]]
@@ -6204,15 +6517,6 @@ dependencies = [
"windows-targets 0.42.2",
]
-[[package]]
-name = "windows-sys"
-version = "0.48.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
-dependencies = [
- "windows-targets 0.48.5",
-]
-
[[package]]
name = "windows-sys"
version = "0.52.0"
@@ -6264,21 +6568,6 @@ dependencies = [
"windows_x86_64_msvc 0.42.2",
]
-[[package]]
-name = "windows-targets"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
-dependencies = [
- "windows_aarch64_gnullvm 0.48.5",
- "windows_aarch64_msvc 0.48.5",
- "windows_i686_gnu 0.48.5",
- "windows_i686_msvc 0.48.5",
- "windows_x86_64_gnu 0.48.5",
- "windows_x86_64_gnullvm 0.48.5",
- "windows_x86_64_msvc 0.48.5",
-]
-
[[package]]
name = "windows-targets"
version = "0.52.6"
@@ -6321,6 +6610,15 @@ dependencies = [
"windows-link 0.1.3",
]
+[[package]]
+name = "windows-threading"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37"
+dependencies = [
+ "windows-link 0.2.1",
+]
+
[[package]]
name = "windows-version"
version = "0.1.7"
@@ -6336,12 +6634,6 @@ version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
-[[package]]
-name = "windows_aarch64_gnullvm"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
-
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
@@ -6360,12 +6652,6 @@ version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
-[[package]]
-name = "windows_aarch64_msvc"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
-
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
@@ -6384,12 +6670,6 @@ version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
-[[package]]
-name = "windows_i686_gnu"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
-
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
@@ -6420,12 +6700,6 @@ version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
-[[package]]
-name = "windows_i686_msvc"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
-
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
@@ -6444,12 +6718,6 @@ version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
-[[package]]
-name = "windows_x86_64_gnu"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
-
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
@@ -6468,12 +6736,6 @@ version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
-[[package]]
-name = "windows_x86_64_gnullvm"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
-
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
@@ -6492,12 +6754,6 @@ version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
-[[package]]
-name = "windows_x86_64_msvc"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
-
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
@@ -6667,13 +6923,45 @@ dependencies = [
]
[[package]]
-name = "xdg-home"
-version = "1.3.0"
+name = "xcap"
+version = "0.9.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b31c7f57ddfb14983525d9149eaed160de7d3973aaa546f3e19eb3394122b6b"
+dependencies = [
+ "dispatch2",
+ "image",
+ "libwayshot-xcap",
+ "log",
+ "objc2",
+ "objc2-app-kit",
+ "objc2-av-foundation",
+ "objc2-core-foundation",
+ "objc2-core-graphics",
+ "objc2-core-media",
+ "objc2-core-video",
+ "objc2-foundation",
+ "percent-encoding",
+ "pipewire",
+ "rand 0.10.2",
+ "scopeguard",
+ "serde",
+ "thiserror 2.0.18",
+ "url",
+ "widestring",
+ "windows 0.62.2",
+ "xcb",
+ "zbus",
+]
+
+[[package]]
+name = "xcb"
+version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec1cdab258fb55c0da61328dc52c8764709b249011b2cad0454c72f0bf10a1f6"
+checksum = "ee4c580d8205abb0a5cf4eb7e927bd664e425b6c3263f9c5310583da96970cf6"
dependencies = [
+ "bitflags 1.3.2",
"libc",
- "windows-sys 0.59.0",
+ "quick-xml 0.30.0",
]
[[package]]
@@ -6682,6 +6970,12 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56"
+[[package]]
+name = "xml-rs"
+version = "0.8.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f"
+
[[package]]
name = "y4m"
version = "0.8.0"
@@ -6713,40 +7007,34 @@ dependencies = [
[[package]]
name = "zbus"
-version = "3.15.2"
+version = "5.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "675d170b632a6ad49804c8cf2105d7c31eddd3312555cffd4b740e08e97c25e6"
+checksum = "fe18fb60dc696039e738717b76eaea21e7a4489bbb1885020b43c94236d7e98a"
dependencies = [
"async-broadcast",
"async-executor",
- "async-fs 1.6.0",
- "async-io 1.13.0",
- "async-lock 2.8.0",
+ "async-io",
+ "async-lock",
"async-process",
"async-recursion",
"async-task",
"async-trait",
"blocking",
- "byteorder",
- "derivative",
"enumflags2",
- "event-listener 2.5.3",
+ "event-listener",
"futures-core",
- "futures-sink",
- "futures-util",
+ "futures-lite",
"hex",
- "nix",
- "once_cell",
+ "libc",
"ordered-stream",
- "rand 0.8.7",
+ "rustix 1.1.4",
"serde",
"serde_repr",
- "sha1",
- "static_assertions",
"tracing",
"uds_windows",
- "winapi",
- "xdg-home",
+ "uuid",
+ "windows-sys 0.61.2",
+ "winnow 1.0.4",
"zbus_macros",
"zbus_names",
"zvariant",
@@ -6754,26 +7042,27 @@ dependencies = [
[[package]]
name = "zbus_macros"
-version = "3.15.2"
+version = "5.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7131497b0f887e8061b430c530240063d33bf9455fa34438f388a245da69e0a5"
+checksum = "fe96480bed92df2b442a1a30df364e12d08eed03aeb061f2b8dc6afb2be91119"
dependencies = [
- "proc-macro-crate 1.3.1",
+ "proc-macro-crate 3.5.0",
"proc-macro2",
"quote",
- "regex",
- "syn 1.0.109",
+ "syn 2.0.118",
+ "zbus_names",
+ "zvariant",
"zvariant_utils",
]
[[package]]
name = "zbus_names"
-version = "2.6.1"
+version = "4.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "437d738d3750bed6ca9b8d423ccc7a8eb284f6b1d6d4e225a0e4e6258d864c8d"
+checksum = "d8bf88b4a3ff53e883001e0e0115b297a9d53c31b9c1edd2bfdd853e3428624e"
dependencies = [
"serde",
- "static_assertions",
+ "winnow 1.0.4",
"zvariant",
]
@@ -6901,39 +7190,40 @@ dependencies = [
[[package]]
name = "zvariant"
-version = "3.15.2"
+version = "5.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4eef2be88ba09b358d3b58aca6e41cd853631d44787f319a1383ca83424fb2db"
+checksum = "bee2a0bcd2a907786a456fff45aaaaf54c9ba5f50b71ae9ec1a4edd200c94911"
dependencies = [
- "byteorder",
+ "endi",
"enumflags2",
- "libc",
"serde",
- "static_assertions",
- "url",
+ "winnow 1.0.4",
"zvariant_derive",
+ "zvariant_utils",
]
[[package]]
name = "zvariant_derive"
-version = "3.15.2"
+version = "5.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37c24dc0bed72f5f90d1f8bb5b07228cbf63b3c6e9f82d82559d4bae666e7ed9"
+checksum = "38a708216a18780796770bfe3f4739c7c83a3e8f789b755534bbbc06e4e23e12"
dependencies = [
- "proc-macro-crate 1.3.1",
+ "proc-macro-crate 3.5.0",
"proc-macro2",
"quote",
- "syn 1.0.109",
+ "syn 2.0.118",
"zvariant_utils",
]
[[package]]
name = "zvariant_utils"
-version = "1.0.1"
+version = "3.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7234f0d811589db492d16893e3f21e8e2fd282e6d01b0cddee310322062cc200"
+checksum = "90cb9383f9b45290407a1258b202d3f8f01db719eb60b4e4055c6375af4fc7c7"
dependencies = [
"proc-macro2",
"quote",
- "syn 1.0.109",
+ "serde",
+ "syn 2.0.118",
+ "winnow 1.0.4",
]
diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml
index a2f5ccd..662af26 100644
--- a/src-tauri/Cargo.toml
+++ b/src-tauri/Cargo.toml
@@ -21,18 +21,20 @@ serde_json = "1"
tokio = { version = "1", features = ["full"] }
chrono = "0.4"
lazy_static = "1.5"
+image = "0.25"
[target.'cfg(target_os = "macos")'.dependencies]
cocoa = "0.25"
objc = "0.2"
core-graphics = "0.23"
-image = "0.25"
+# Cross-platform screen capture (Windows DXGI/WGC, Linux PipeWire portal).
+# macOS keeps its hand-rolled core-graphics path; xcap backs Windows + Linux.
[target.'cfg(target_os = "windows")'.dependencies]
-windows = { version = "0.54", features = ["Graphics_Capture", "Foundation"] }
+xcap = { version = "0.9.4", features = ["wgc"] }
[target.'cfg(target_os = "linux")'.dependencies]
-ashpd = "0.7"
+xcap = "0.9.4"
[features]
default = ["custom-protocol"]
diff --git a/src-tauri/src/commands.rs b/src-tauri/src/commands.rs
index ecf6a0e..30b7427 100644
--- a/src-tauri/src/commands.rs
+++ b/src-tauri/src/commands.rs
@@ -156,7 +156,59 @@ pub fn capture_screen_fast(display_id: Option, fps: u32, bounds: Option= 60 {
+ 75
+ } else if fps >= 30 {
+ 85
+ } else {
+ 90
+ };
+
+ let mut output = Vec::new();
+ let mut encoder =
+ image::codecs::jpeg::JpegEncoder::new_with_quality(&mut output, jpeg_quality);
+ encoder
+ .encode(&rgb, rgb.width(), rgb.height(), image::ColorType::Rgb8.into())
+ .map_err(|e: image::ImageError| e.to_string())?;
+ return Ok(output);
+ }
+
+ #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "linux")))]
return Err("Platform not supported".to_string());
}
@@ -322,11 +374,41 @@ pub async fn capture_screen(options: CaptureOptions) -> Result 0.0 && scale < 1.0 {
+ let nw = ((img.width() as f32) * scale).round().max(1.0) as u32;
+ let nh = ((img.height() as f32) * scale).round().max(1.0) as u32;
+ img = image::imageops::resize(&img, nw, nh, image::imageops::FilterType::Triangle);
+ }
+ }
+
+ let format = options.format.as_deref().unwrap_or("png");
+ let mut output = Vec::new();
+ match format {
+ "jpg" | "jpeg" => {
+ let rgb = image::DynamicImage::ImageRgba8(img).to_rgb8();
+ let q = (options.quality.unwrap_or(0.92) * 100.0) as u8;
+ let mut encoder =
+ image::codecs::jpeg::JpegEncoder::new_with_quality(&mut output, q);
+ encoder
+ .encode(&rgb, rgb.width(), rgb.height(), image::ColorType::Rgb8.into())
+ .map_err(|e: image::ImageError| e.to_string())?;
+ }
+ _ => {
+ image::codecs::png::PngEncoder::new(&mut output)
+ .write_image(&img, img.width(), img.height(), image::ColorType::Rgba8.into())
+ .map_err(|e: image::ImageError| e.to_string())?;
+ }
+ }
+ return Ok(tauri::ipc::Response::new(output));
+ }
#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "linux")))]
return Err("Unsupported platform".to_string());
@@ -366,11 +448,29 @@ pub async fn list_displays() -> Result, String> {
return Ok(result);
}
- #[cfg(target_os = "windows")]
- return Err("Windows display enumeration not yet implemented".to_string());
-
- #[cfg(target_os = "linux")]
- return Err("Linux display enumeration not yet implemented".to_string());
+ #[cfg(any(target_os = "windows", target_os = "linux"))]
+ {
+ let monitors = xcap::Monitor::all().map_err(|e| e.to_string())?;
+ let mut result = Vec::new();
+ for (i, m) in monitors.iter().enumerate() {
+ let scale = m.scale_factor().unwrap_or(1.0).max(1.0);
+ let phys_w = m.width().unwrap_or(0);
+ let phys_h = m.height().unwrap_or(0);
+ result.push(DisplayInfo {
+ id: m.id().map(|v| v as i32).unwrap_or(i as i32),
+ name: m
+ .friendly_name()
+ .or_else(|_| m.name())
+ .unwrap_or_else(|_| format!("Display {}", i + 1)),
+ // Report logical dimensions (physical / scale) to match macOS,
+ // so the frontend's logical region coords scale correctly.
+ width: ((phys_w as f32) / scale).round() as u32,
+ height: ((phys_h as f32) / scale).round() as u32,
+ is_main: m.is_primary().unwrap_or(false),
+ });
+ }
+ return Ok(result);
+ }
#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "linux")))]
return Err("Unsupported platform".to_string());
@@ -393,6 +493,183 @@ pub async fn capture_region(bounds: Rectangle, display_id: Option) -> Resul
capture_screen_fast(target_display, 10, Some(bounds)).map(tauri::ipc::Response::new)
}
+// ── Held full-res captures for native region cropping (Phase D) ──────────────
+// The in-tool region flow captures the frozen full screen once (while the main
+// window is hidden), holds it in Rust, and crops server-side after the user
+// selects — so only the small crop crosses IPC, never the whole screen.
+
+// The held frame is stored as an RGBA image so cropping is one platform-agnostic
+// path (macOS core-graphics and Windows/Linux xcap both feed into it).
+struct HeldCapture {
+ image: image::RgbaImage, // physical pixels, RGBA
+ logical_width: u32,
+ logical_height: u32,
+}
+
+lazy_static::lazy_static! {
+ static ref HELD_CAPTURES: std::sync::Mutex> =
+ std::sync::Mutex::new(std::collections::HashMap::new());
+}
+
+static CAPTURE_SEQ: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(0);
+
+/// Map a logical-pixel selection rect to a clamped physical-pixel crop rect,
+/// applying the display's HiDPI scale. Pure — unit-tested.
+fn physical_crop_rect(
+ region: &Rectangle,
+ phys_w: u32,
+ phys_h: u32,
+ logical_w: u32,
+ logical_h: u32,
+) -> (u32, u32, u32, u32) {
+ if logical_w == 0 || logical_h == 0 || phys_w == 0 || phys_h == 0 {
+ return (0, 0, phys_w.max(1), phys_h.max(1));
+ }
+ let scale_x = phys_w as f64 / logical_w as f64;
+ let scale_y = phys_h as f64 / logical_h as f64;
+ let x = ((region.x as f64 * scale_x).max(0.0) as u32).min(phys_w.saturating_sub(1));
+ let y = ((region.y as f64 * scale_y).max(0.0) as u32).min(phys_h.saturating_sub(1));
+ let w = ((region.width as f64 * scale_x).round() as u32).clamp(1, phys_w - x);
+ let h = ((region.height as f64 * scale_y).round() as u32).clamp(1, phys_h - y);
+ (x, y, w, h)
+}
+
+/// Crop a physical RGBA frame to a logical selection rect. Pure — unit-tested.
+pub(crate) fn crop_rgba(
+ img: &image::RgbaImage,
+ region: &Rectangle,
+ logical_w: u32,
+ logical_h: u32,
+) -> image::RgbaImage {
+ let (x, y, w, h) = physical_crop_rect(region, img.width(), img.height(), logical_w, logical_h);
+ image::imageops::crop_imm(img, x, y, w, h).to_image()
+}
+
+fn store_held(held: HeldCapture) -> Result {
+ let id = format!(
+ "cap_{}",
+ CAPTURE_SEQ.fetch_add(1, std::sync::atomic::Ordering::Relaxed)
+ );
+ let mut map = HELD_CAPTURES.lock().map_err(|e| e.to_string())?;
+ map.clear(); // only one region capture is active at a time — bound memory
+ map.insert(id.clone(), held);
+ Ok(id)
+}
+
+/// xcap-backed full capture for Windows/Linux. Returns (physical RGBA, logical w, logical h).
+#[cfg(any(target_os = "windows", target_os = "linux"))]
+fn xcap_capture(display_id: Option) -> Result<(image::RgbaImage, u32, u32), String> {
+ let monitors = xcap::Monitor::all().map_err(|e| e.to_string())?;
+ let monitor = match display_id {
+ Some(id) => monitors
+ .into_iter()
+ .find(|m| m.id().map(|v| v as i32 == id).unwrap_or(false))
+ .ok_or_else(|| format!("Display {} not found", id))?,
+ None => monitors
+ .into_iter()
+ .find(|m| m.is_primary().unwrap_or(false))
+ .ok_or_else(|| "No primary monitor found".to_string())?,
+ };
+ let scale = monitor.scale_factor().unwrap_or(1.0).max(1.0);
+ let img = monitor.capture_image().map_err(|e| e.to_string())?;
+ let logical_w = ((img.width() as f32) / scale).round() as u32;
+ let logical_h = ((img.height() as f32) / scale).round() as u32;
+ Ok((img, logical_w.max(1), logical_h.max(1)))
+}
+
+/// Capture the full display and hold it in memory; returns an id for cropping.
+#[tauri::command]
+pub async fn capture_hold(display_id: Option) -> Result {
+ #[cfg(target_os = "macos")]
+ {
+ use core_graphics::display::{CGDisplay, CGMainDisplayID};
+ use image::{ImageBuffer, Rgba, RgbaImage};
+
+ let display = if let Some(id) = display_id {
+ CGDisplay::new(id as u32)
+ } else {
+ unsafe { CGDisplay::new(CGMainDisplayID()) }
+ };
+ let cg = display
+ .image()
+ .ok_or_else(|| "Failed to capture screen".to_string())?;
+
+ let phys_w = cg.width() as u32;
+ let phys_h = cg.height() as u32;
+ let bytes_per_row = cg.bytes_per_row();
+ let data = cg.data();
+
+ let mut buf: RgbaImage = ImageBuffer::new(phys_w, phys_h);
+ for y in 0..phys_h {
+ for x in 0..phys_w {
+ let offset = (y as usize * bytes_per_row) + (x as usize * 4); // BGRA
+ if offset + 3 < data.len() as usize {
+ let b = data[offset];
+ let g = data[offset + 1];
+ let r = data[offset + 2];
+ let a = data[offset + 3];
+ buf.put_pixel(x, y, Rgba([r, g, b, a]));
+ }
+ }
+ }
+
+ let id = store_held(HeldCapture {
+ image: buf,
+ logical_width: display.pixels_wide() as u32,
+ logical_height: display.pixels_high() as u32,
+ })?;
+ println!("[Capture] Held full-res frame {} ({}x{})", id, phys_w, phys_h);
+ return Ok(id);
+ }
+
+ #[cfg(any(target_os = "windows", target_os = "linux"))]
+ {
+ let (img, logical_w, logical_h) = xcap_capture(display_id)?;
+ let (pw, ph) = (img.width(), img.height());
+ let id = store_held(HeldCapture { image: img, logical_width: logical_w, logical_height: logical_h })?;
+ println!("[Capture] Held full-res frame {} ({}x{})", id, pw, ph);
+ return Ok(id);
+ }
+
+ #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "linux")))]
+ {
+ let _ = display_id;
+ return Err("Platform not supported".to_string());
+ }
+}
+
+/// Crop a previously-held capture to the selected region and return PNG bytes.
+/// One-shot: the held frame is dropped after cropping.
+#[tauri::command]
+pub async fn crop_held(capture_id: String, region: Rectangle) -> Result {
+ use image::ImageEncoder;
+
+ let held = {
+ let mut map = HELD_CAPTURES.lock().map_err(|e| e.to_string())?;
+ map.remove(&capture_id)
+ .ok_or_else(|| "Held capture not found (already used or expired)".to_string())?
+ };
+
+ let cropped = crop_rgba(&held.image, ®ion, held.logical_width, held.logical_height);
+
+ let mut png = Vec::new();
+ image::codecs::png::PngEncoder::new(&mut png)
+ .write_image(&cropped, cropped.width(), cropped.height(), image::ColorType::Rgba8.into())
+ .map_err(|e: image::ImageError| e.to_string())?;
+
+ println!("[Capture] Cropped held frame → {}x{} ({} bytes)", cropped.width(), cropped.height(), png.len());
+ Ok(tauri::ipc::Response::new(png))
+}
+
+/// Free a held capture without cropping (e.g. the user cancelled selection).
+#[tauri::command]
+pub async fn release_held(capture_id: String) -> Result<(), String> {
+ if let Ok(mut map) = HELD_CAPTURES.lock() {
+ map.remove(&capture_id);
+ }
+ Ok(())
+}
+
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RegionSelectorOptions {
@@ -649,3 +926,85 @@ pub fn get_cursor_position() -> Result<(f64, f64), String> {
Err("get_cursor_position not implemented for this platform".to_string())
}
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ fn rect(x: i32, y: i32, w: u32, h: u32) -> Rectangle {
+ Rectangle { x, y, width: w, height: h, display_id: None }
+ }
+
+ #[test]
+ fn crop_rect_non_hidpi_is_identity_scale() {
+ // logical == physical (scale 1.0)
+ let (x, y, w, h) = physical_crop_rect(&rect(10, 20, 100, 50), 1920, 1080, 1920, 1080);
+ assert_eq!((x, y, w, h), (10, 20, 100, 50));
+ }
+
+ #[test]
+ fn crop_rect_scales_for_2x_retina() {
+ // physical is 2x logical → coordinates double
+ let (x, y, w, h) = physical_crop_rect(&rect(10, 20, 100, 50), 2880, 1800, 1440, 900);
+ assert_eq!((x, y, w, h), (20, 40, 200, 100));
+ }
+
+ #[test]
+ fn crop_rect_clamps_to_physical_bounds() {
+ // a region running past the edge is clamped to the frame
+ let (x, y, w, h) = physical_crop_rect(&rect(1900, 1000, 500, 500), 1920, 1080, 1920, 1080);
+ assert_eq!(x, 1900);
+ assert_eq!(y, 1000);
+ assert_eq!(w, 20); // 1920 - 1900
+ assert_eq!(h, 80); // 1080 - 1000
+ }
+
+ #[test]
+ fn crop_rect_negative_origin_floored_to_zero() {
+ let (x, y, _, _) = physical_crop_rect(&rect(-50, -30, 100, 100), 1920, 1080, 1920, 1080);
+ assert_eq!((x, y), (0, 0));
+ }
+
+ #[test]
+ fn crop_rect_zero_dims_never_produce_empty_crop() {
+ // width/height always at least 1 so the PNG encoder never sees 0
+ let (_, _, w, h) = physical_crop_rect(&rect(0, 0, 0, 0), 1920, 1080, 1920, 1080);
+ assert!(w >= 1 && h >= 1);
+ }
+
+ #[test]
+ fn crop_rect_zero_logical_falls_back_to_full_frame() {
+ let (x, y, w, h) = physical_crop_rect(&rect(10, 10, 100, 100), 1920, 1080, 0, 0);
+ assert_eq!((x, y, w, h), (0, 0, 1920, 1080));
+ }
+
+ fn gradient(w: u32, h: u32) -> image::RgbaImage {
+ // Each pixel encodes its own (x, y) in the R and G channels.
+ let mut img = image::RgbaImage::new(w, h);
+ for y in 0..h {
+ for x in 0..w {
+ img.put_pixel(x, y, image::Rgba([x as u8, y as u8, 0, 255]));
+ }
+ }
+ img
+ }
+
+ #[test]
+ fn crop_rgba_extracts_region_at_scale_1() {
+ let img = gradient(4, 4);
+ let out = crop_rgba(&img, &rect(1, 1, 2, 2), 4, 4);
+ assert_eq!(out.dimensions(), (2, 2));
+ assert_eq!(out.get_pixel(0, 0), &image::Rgba([1, 1, 0, 255]));
+ assert_eq!(out.get_pixel(1, 1), &image::Rgba([2, 2, 0, 255]));
+ }
+
+ #[test]
+ fn crop_rgba_scales_logical_region_on_hidpi() {
+ // 8x8 physical, 4x4 logical (2x). Logical (1,1,2,2) → physical (2,2,4,4).
+ let img = gradient(8, 8);
+ let out = crop_rgba(&img, &rect(1, 1, 2, 2), 4, 4);
+ assert_eq!(out.dimensions(), (4, 4));
+ assert_eq!(out.get_pixel(0, 0), &image::Rgba([2, 2, 0, 255]));
+ assert_eq!(out.get_pixel(3, 3), &image::Rgba([5, 5, 0, 255]));
+ }
+}
diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs
index 0f5aade..8d06c75 100644
--- a/src-tauri/src/main.rs
+++ b/src-tauri/src/main.rs
@@ -29,6 +29,9 @@ fn main() {
commands::list_displays,
commands::capture_window,
commands::capture_region,
+ commands::capture_hold,
+ commands::crop_held,
+ commands::release_held,
commands::show_region_selector,
commands::close_region_selector,
commands::submit_region_selection,
diff --git a/src-tauri/src/recording.rs b/src-tauri/src/recording.rs
index b04739d..f1103a9 100644
--- a/src-tauri/src/recording.rs
+++ b/src-tauri/src/recording.rs
@@ -110,15 +110,21 @@ pub fn start_recording(options: RecordOptions) -> Result,
+ bounds: Option,
+ stop_flag: Arc>,
+ frames: Arc>>>,
+ duration_out: Arc>>,
+) {
+ use std::sync::mpsc::RecvTimeoutError;
+
+ // Resolve the target monitor.
+ let monitors = match xcap::Monitor::all() {
+ Ok(m) => m,
+ Err(e) => {
+ eprintln!("[Recording] xcap monitor enumeration failed: {}", e);
+ return;
+ }
+ };
+ let monitor = match display_id {
+ Some(id) => monitors
+ .into_iter()
+ .find(|m| m.id().map(|v| v as i32 == id).unwrap_or(false)),
+ None => monitors.into_iter().find(|m| m.is_primary().unwrap_or(false)),
+ };
+ let monitor = match monitor {
+ Some(m) => m,
+ None => {
+ eprintln!("[Recording] target monitor not found for recording");
+ return;
+ }
+ };
+ let scale = monitor.scale_factor().unwrap_or(1.0).max(1.0);
+
+ // One persistent capture stream — no per-frame portal round-trips.
+ let (recorder, rx) = match monitor.video_recorder() {
+ Ok(v) => v,
+ Err(e) => {
+ eprintln!("[Recording] xcap video_recorder init failed: {}", e);
+ return;
+ }
+ };
+ if let Err(e) = recorder.start() {
+ eprintln!("[Recording] xcap recorder start failed: {}", e);
+ return;
+ }
+ println!("[Recording] xcap capture stream started (target {}fps)", target_fps);
+
+ let normalized_fps = if target_fps == 35 { 30 } else { target_fps.max(1) };
+ let frame_interval = Duration::from_secs_f64(1.0 / normalized_fps as f64);
+ let jpeg_quality: u8 = if target_fps == 35 {
+ 95
+ } else if target_fps >= 60 {
+ 75
+ } else if target_fps >= 30 {
+ 85
+ } else {
+ 90
+ };
+
+ let start_time = Instant::now();
+ let mut last_kept: Option = None;
+ let mut frame_count = 0usize;
+
+ loop {
+ if stop_flag.lock().map(|f| *f).unwrap_or(true) {
+ break;
+ }
+
+ // Bounded wait so we can re-check the stop flag promptly.
+ let frame = match rx.recv_timeout(Duration::from_millis(200)) {
+ Ok(f) => f,
+ Err(RecvTimeoutError::Timeout) => continue,
+ Err(RecvTimeoutError::Disconnected) => break,
+ };
+
+ // Throttle the stream down to the target frame rate.
+ if let Some(prev) = last_kept {
+ if prev.elapsed() < frame_interval {
+ continue;
+ }
+ }
+ last_kept = Some(Instant::now());
+
+ // frame.raw is physical, tightly-packed RGBA.
+ let img = match image::RgbaImage::from_raw(frame.width, frame.height, frame.raw) {
+ Some(i) => i,
+ None => continue,
+ };
+
+ // Crop to the requested region (logical → physical) if any.
+ let logical_w = ((frame.width as f32) / scale).round() as u32;
+ let logical_h = ((frame.height as f32) / scale).round() as u32;
+ let rgba = match &bounds {
+ Some(rect) => {
+ crate::commands::crop_rgba(&img, rect, logical_w.max(1), logical_h.max(1))
+ }
+ None => img,
+ };
+
+ // Force even dimensions (H.264 requires them) — deterministic, so every
+ // frame in a recording ends up the same size for the encoder.
+ let ew = (rgba.width() - rgba.width() % 2).max(2);
+ let eh = (rgba.height() - rgba.height() % 2).max(2);
+ let rgba = if ew != rgba.width() || eh != rgba.height() {
+ image::imageops::crop_imm(&rgba, 0, 0, ew, eh).to_image()
+ } else {
+ rgba
+ };
+
+ // Encode to JPEG (the frame format stop_recording's encoder expects).
+ let rgb = image::DynamicImage::ImageRgba8(rgba).to_rgb8();
+ let mut buf = Vec::new();
+ let mut enc = image::codecs::jpeg::JpegEncoder::new_with_quality(&mut buf, jpeg_quality);
+ if enc
+ .encode(&rgb, rgb.width(), rgb.height(), image::ColorType::Rgb8.into())
+ .is_ok()
+ {
+ if let Ok(mut v) = frames.lock() {
+ v.push(buf);
+ frame_count += 1;
+ }
+ }
+ }
+
+ let _ = recorder.stop();
+ let total = start_time.elapsed();
+ if let Ok(mut d) = duration_out.lock() {
+ *d = Some(total);
+ }
+ println!(
+ "[Recording] xcap stream ended: {} frames in {:.2}s (~{:.1}fps)",
+ frame_count,
+ total.as_secs_f64(),
+ frame_count as f64 / total.as_secs_f64().max(0.001),
+ );
+}
+
pub fn stop_recording(handle_id: String) -> Result, String> {
println!("[Recording] Stopping recording: {}", handle_id);
diff --git a/src/islands/media/Screenshot.tsx b/src/islands/media/Screenshot.tsx
index b8affa0..4685a90 100644
--- a/src/islands/media/Screenshot.tsx
+++ b/src/islands/media/Screenshot.tsx
@@ -179,70 +179,30 @@ export default function Screenshot() {
// STEP 2: Show overlay window (user selects region)
const regionPromise = captureService.showRegionSelector(selectedDisplay);
- // STEP 3: Capture full-res screenshot in parallel for cropping
- const fullBlob = await captureService.captureScreen({
- format: 'png',
- displayId: selectedDisplay,
- });
-
- const fullDataUrl = await new Promise((resolve, reject) => {
- const reader2 = new FileReader();
- reader2.onload = () => resolve(reader2.result as string);
- reader2.onerror = reject;
- reader2.readAsDataURL(fullBlob);
- });
+ // STEP 3: Capture + HOLD the frozen full-res frame natively (in parallel
+ // with selection, while the main window is hidden). Only the final crop
+ // crosses IPC — never the whole screen — and the crop happens in Rust.
+ const { invoke } = await import('@tauri-apps/api/core');
+ const captureId = await invoke('capture_hold', { displayId: selectedDisplay });
// STEP 4: Wait for region selection
const region = await regionPromise;
- // Clean up overlay screenshot from localStorage
- localStorage.removeItem('overlay-screenshot');
-
if (!region) {
- // User cancelled
+ // User cancelled — free the held frame
+ await invoke('release_held', { captureId }).catch(() => {});
setCapturing(false);
return;
}
- // STEP 5: Load the full-res screenshot and crop to selected region
- const fullImg = new Image();
- await new Promise((resolve, reject) => {
- fullImg.onload = () => resolve();
- fullImg.onerror = () => reject(new Error('Failed to load screenshot'));
- fullImg.src = fullDataUrl; // Use full-res screenshot for cropping
- });
-
- // Calculate HiDPI scale factor (physical pixels / logical pixels)
- const targetDisplay = displays.find(d => d.id === selectedDisplay) || displays.find(d => d.isMain)!;
- const scaleX = fullImg.width / targetDisplay.width;
- const scaleY = fullImg.height / targetDisplay.height;
-
- console.log('[Screenshot] Scale factor:', scaleX, 'x', scaleY,
- '(logical:', targetDisplay.width, 'x', targetDisplay.height,
- 'physical:', fullImg.width, 'x', fullImg.height, ')');
- console.log('[Screenshot] Logical region:', region);
- console.log('[Screenshot] Physical region:',
- Math.round(region.x * scaleX), Math.round(region.y * scaleY),
- Math.round(region.width * scaleX), Math.round(region.height * scaleY));
-
- // Scale region coordinates to physical pixels
- const physicalX = Math.round(region.x * scaleX);
- const physicalY = Math.round(region.y * scaleY);
- const physicalWidth = Math.round(region.width * scaleX);
- const physicalHeight = Math.round(region.height * scaleY);
-
- // Create canvas with cropped region (in physical pixels)
+ // STEP 5: Crop the held frame natively (server-side HiDPI scaling) → PNG
+ const croppedBytes = await invoke('crop_held', { captureId, region });
+ const bmp = await createImageBitmap(new Blob([croppedBytes], { type: 'image/png' }));
const canvas = document.createElement('canvas');
- canvas.width = physicalWidth;
- canvas.height = physicalHeight;
- const ctx = canvas.getContext('2d')!;
-
- // Draw the selected region from the full screenshot (using physical pixel coordinates)
- ctx.drawImage(
- fullImg,
- physicalX, physicalY, physicalWidth, physicalHeight, // source (physical pixels)
- 0, 0, physicalWidth, physicalHeight // destination
- );
+ canvas.width = bmp.width;
+ canvas.height = bmp.height;
+ canvas.getContext('2d')!.drawImage(bmp, 0, 0);
+ bmp.close();
setShot(canvas);
setPreviewUrl(prev => {