-
+
diff --git a/wlx-overlay-s/src/overlays/edit/lock.rs b/wlx-overlay-s/src/overlays/edit/lock.rs
index 0825095..6be7fa2 100644
--- a/wlx-overlay-s/src/overlays/edit/lock.rs
+++ b/wlx-overlay-s/src/overlays/edit/lock.rs
@@ -1,7 +1,10 @@
+use std::rc::Rc;
+
use anyhow::Context;
use glam::FloatExt;
use wgui::{
animation::{Animation, AnimationEasing},
+ components::button::ComponentButton,
event::CallbackDataCommon,
layout::WidgetID,
parser::Fetchable,
@@ -15,6 +18,7 @@ pub(super) struct InteractLockHandler {
id: WidgetID,
color: wgui::drawing::Color,
interactable: bool,
+ button: Option
>,
}
impl InteractLockHandler {
@@ -27,10 +31,13 @@ impl InteractLockHandler {
.get_as::(id)
.context("Element with id=\"shadow\" must be a ")?;
+ let button = panel.parser_state.fetch_component_as("top_lock")?;
+
Ok(Self {
id,
color: shadow_rect.params.color,
interactable: true,
+ button: Some(button),
})
}
@@ -42,6 +49,10 @@ impl InteractLockHandler {
.get_as::(self.id)
.unwrap(); // can only fail if set_up_rect has issues
+ if let Some(button) = self.button.as_ref() {
+ button.set_sticky_state(common, !interactable);
+ }
+
let globals = common.state.globals.get();
if interactable {
set_anim_color(&mut rect, 0.0, self.color, globals.defaults.danger_color);
@@ -60,6 +71,9 @@ impl InteractLockHandler {
let rect_color = self.color;
self.interactable = !self.interactable;
+ if let Some(button) = self.button.as_ref() {
+ button.set_sticky_state(common, !self.interactable);
+ }
let anim = if self.interactable {
Animation::new(
From 9ea9da18f59c23fd0681fe660ad81421e6760a7d Mon Sep 17 00:00:00 2001
From: Aleksander
Date: Mon, 22 Dec 2025 17:35:03 +0100
Subject: [PATCH 18/29] update translations, use gemma3:27b instead
[skip ci]
---
scripts/translator/run.sh | 2 +-
wlx-overlay-s/src/assets/lang/de.json | 11 +++++++++++
wlx-overlay-s/src/assets/lang/es.json | 11 +++++++++++
wlx-overlay-s/src/assets/lang/ja.json | 13 ++++++++++++-
wlx-overlay-s/src/assets/lang/pl.json | 11 +++++++++++
5 files changed, 46 insertions(+), 2 deletions(-)
diff --git a/scripts/translator/run.sh b/scripts/translator/run.sh
index 93261e6..ce09323 100755
--- a/scripts/translator/run.sh
+++ b/scripts/translator/run.sh
@@ -4,7 +4,7 @@ cd "$(dirname "$0")"
bun install
-export MODEL="gemma3:12b"
+export MODEL="gemma3:27b"
TEMPLATE="pl" bun main.ts
TEMPLATE="de" bun main.ts
diff --git a/wlx-overlay-s/src/assets/lang/de.json b/wlx-overlay-s/src/assets/lang/de.json
index 6e5cd4f..a0c07bb 100644
--- a/wlx-overlay-s/src/assets/lang/de.json
+++ b/wlx-overlay-s/src/assets/lang/de.json
@@ -72,5 +72,16 @@
"GRABBING_ANCHORED_EDIT": "Diese Overlay-Darstellung bleibt an der Mittelmarkierung verankert.",
"GRABBING_FLOATING": "Diese Overlay-Darstellung ist frei schwebend und bleibt an Ort und Stelle, es sei denn, sie wird neu zentriert.",
"GRABBING_FOLLOW": "Dieses Overlay wird dem Gerät folgen, an das es angehängt ist."
+ },
+ "TOAST": {
+ "DEFAULT_TITLE": "Benachrichtigung",
+ "ERROR": "Fehler",
+ "CANNOT_REMOVE_SET": "Satz kann nicht entfernt werden!",
+ "NO_SET_SELECTED": "Kein Set ausgewählt.",
+ "LAST_EXISTING_SET": "Dies ist das letzte vorhandene Set.",
+ "EMPTY_SET": "Leeres Set!",
+ "LETS_ADD_OVERLAYS": "Lass uns ein paar Overlays von der Uhr hinzufügen!",
+ "FIXING_FLOOR": "Boden wird in 5 Sekunden fixiert...",
+ "ONE_CONTROLLER_ON_FLOOR": "Lege einen Controller auf den Boden!"
}
}
\ No newline at end of file
diff --git a/wlx-overlay-s/src/assets/lang/es.json b/wlx-overlay-s/src/assets/lang/es.json
index 0a5ef4a..9864e7e 100644
--- a/wlx-overlay-s/src/assets/lang/es.json
+++ b/wlx-overlay-s/src/assets/lang/es.json
@@ -72,5 +72,16 @@
"GRABBING_ANCHORED_EDIT": "Esta superposición permanecerá anclada al marcador central.",
"GRABBING_FLOATING": "Esta superposición es flotante y permanecerá en su lugar a menos que se recentre.",
"GRABBING_FOLLOW": "Esta superposición seguirá el dispositivo al que está adjunta."
+ },
+ "TOAST": {
+ "DEFAULT_TITLE": "Notificación",
+ "ERROR": "Error",
+ "CANNOT_REMOVE_SET": "¡No se puede eliminar el conjunto!",
+ "NO_SET_SELECTED": "No se ha seleccionado ningún conjunto.",
+ "LAST_EXISTING_SET": "Este es el último conjunto existente.",
+ "EMPTY_SET": "¡Conjunto vacío!",
+ "LETS_ADD_OVERLAYS": "¡Añadamos algunos overlays desde el reloj!",
+ "FIXING_FLOOR": "Fijando el suelo en 5 segundos...",
+ "ONE_CONTROLLER_ON_FLOOR": "¡Coloca un mando en el suelo!"
}
}
\ No newline at end of file
diff --git a/wlx-overlay-s/src/assets/lang/ja.json b/wlx-overlay-s/src/assets/lang/ja.json
index 777e11f..3a90773 100644
--- a/wlx-overlay-s/src/assets/lang/ja.json
+++ b/wlx-overlay-s/src/assets/lang/ja.json
@@ -70,5 +70,16 @@
"GRABBING_ANCHORED_EDIT": "このオーバーレイは、センター・マーカーに固定されます。",
"GRABBING_FLOATING": "このオーバーレイはフローティングのため、リセンターまではその場所に留まります。",
"GRABBING_FOLLOW": "このオーバーレイは、接続されているデバイスに追従します。"
+ },
+ "TOAST": {
+ "DEFAULT_TITLE": "通知",
+ "ERROR": "エラー",
+ "CANNOT_REMOVE_SET": "セットを削除できません!",
+ "NO_SET_SELECTED": "セットが選択されていません。",
+ "LAST_EXISTING_SET": "これが最後の設定です。",
+ "EMPTY_SET": "空のセットです!",
+ "LETS_ADD_OVERLAYS": "ウォッチからオーバーレイを追加しましょう!",
+ "FIXING_FLOOR": "5秒後にフロアを固定します...",
+ "ONE_CONTROLLER_ON_FLOOR": "コントローラーを床に置いてください!"
}
-}
+}
\ No newline at end of file
diff --git a/wlx-overlay-s/src/assets/lang/pl.json b/wlx-overlay-s/src/assets/lang/pl.json
index 9f1775b..9e7f341 100644
--- a/wlx-overlay-s/src/assets/lang/pl.json
+++ b/wlx-overlay-s/src/assets/lang/pl.json
@@ -70,5 +70,16 @@
"GRABBING_ANCHORED_EDIT": "Ta nakładka pozostanie zakotwiczona do znacznika centralnego.",
"GRABBING_FLOATING": "Ta nakładka jest zawieszony i pozostanie na miejscu, chyba że zostanie wycentrowany.",
"GRABBING_FOLLOW": "Ta nakładka będzie śledzić urządzenie, do którego jest dołączona."
+ },
+ "TOAST": {
+ "DEFAULT_TITLE": "Powiadomienie",
+ "ERROR": "Błąd",
+ "CANNOT_REMOVE_SET": "Nie można usunąć zestawu!",
+ "NO_SET_SELECTED": "Nie wybrano żadnego zestawu.",
+ "LAST_EXISTING_SET": "To jest ostatni istniejący zestaw.",
+ "EMPTY_SET": "Pusty zestaw!",
+ "LETS_ADD_OVERLAYS": "Dodajmy kilka nakładek z zegarka!",
+ "FIXING_FLOOR": "Naprawianie podłogi za 5 sekund...",
+ "ONE_CONTROLLER_ON_FLOOR": "Umieść jeden kontroler na podłodze!"
}
}
\ No newline at end of file
From ccd75c047cda9867ea9b583f9221265ef20d2bf2 Mon Sep 17 00:00:00 2001
From: Aleksander
Date: Tue, 23 Dec 2025 03:50:03 +0100
Subject: [PATCH 19/29] Move wayvr-ipc to our workspace (#324)
---
Cargo.lock | 146 +++++++++-
Cargo.toml | 1 +
wayvr-ipc/Cargo.lock | 390 ++++++++++++++++++++++++++
wayvr-ipc/Cargo.toml | 21 ++
wayvr-ipc/LICENSE.txt | 21 ++
wayvr-ipc/README.md | 9 +
wayvr-ipc/rustfmt.toml | 2 +
wayvr-ipc/src/client.rs | 496 +++++++++++++++++++++++++++++++++
wayvr-ipc/src/ipc.rs | 42 +++
wayvr-ipc/src/lib.rs | 7 +
wayvr-ipc/src/packet_client.rs | 71 +++++
wayvr-ipc/src/packet_server.rs | 163 +++++++++++
wayvr-ipc/src/util/handle.rs | 173 ++++++++++++
wayvr-ipc/src/util/mod.rs | 4 +
wayvr-ipc/src/util/notifier.rs | 25 ++
wlx-overlay-s/Cargo.lock | 15 +-
wlx-overlay-s/Cargo.toml | 4 +-
17 files changed, 1570 insertions(+), 20 deletions(-)
create mode 100644 wayvr-ipc/Cargo.lock
create mode 100644 wayvr-ipc/Cargo.toml
create mode 100644 wayvr-ipc/LICENSE.txt
create mode 100644 wayvr-ipc/README.md
create mode 100644 wayvr-ipc/rustfmt.toml
create mode 100644 wayvr-ipc/src/client.rs
create mode 100644 wayvr-ipc/src/ipc.rs
create mode 100644 wayvr-ipc/src/lib.rs
create mode 100644 wayvr-ipc/src/packet_client.rs
create mode 100644 wayvr-ipc/src/packet_server.rs
create mode 100644 wayvr-ipc/src/util/handle.rs
create mode 100644 wayvr-ipc/src/util/mod.rs
create mode 100644 wayvr-ipc/src/util/notifier.rs
diff --git a/Cargo.lock b/Cargo.lock
index a2e6a7d..aceb10d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2889,8 +2889,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d941b405bd2322993887859a8ee6ac9134945a24ec5ec763a8a962fc64dfec2d"
dependencies = [
"doctest-file",
+ "futures-core",
"libc",
"recvmsg",
+ "tokio",
"widestring",
"windows-sys 0.52.0",
]
@@ -3342,6 +3344,17 @@ version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e53debba6bda7a793e5f99b8dacf19e626084f525f7829104ba9898f367d85ff"
+[[package]]
+name = "mio"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc"
+dependencies = [
+ "libc",
+ "wasi",
+ "windows-sys 0.61.2",
+]
+
[[package]]
name = "moveit"
version = "0.6.0"
@@ -5235,6 +5248,16 @@ dependencies = [
"serde",
]
+[[package]]
+name = "socket2"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881"
+dependencies = [
+ "libc",
+ "windows-sys 0.60.2",
+]
+
[[package]]
name = "stable_deref_trait"
version = "1.2.1"
@@ -5638,6 +5661,45 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
+[[package]]
+name = "tokio"
+version = "1.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408"
+dependencies = [
+ "bytes",
+ "libc",
+ "mio",
+ "pin-project-lite",
+ "socket2",
+ "tokio-macros",
+ "windows-sys 0.61.2",
+]
+
+[[package]]
+name = "tokio-macros"
+version = "2.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.111",
+]
+
+[[package]]
+name = "tokio-util"
+version = "0.7.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594"
+dependencies = [
+ "bytes",
+ "futures-core",
+ "futures-sink",
+ "pin-project-lite",
+ "tokio",
+]
+
[[package]]
name = "toml"
version = "0.8.2"
@@ -6297,16 +6359,18 @@ dependencies = [
]
[[package]]
-name = "wayvr_ipc"
+name = "wayvr-ipc"
version = "0.1.0"
-source = "git+https://github.com/olekolek1000/wayvr-ipc.git?rev=a72587d23f3bb8624d9aeb1f13c0a21e65350f51#a72587d23f3bb8624d9aeb1f13c0a21e65350f51"
dependencies = [
"anyhow",
"bytes",
+ "interprocess",
"log",
"serde",
"serde_json",
"smallvec",
+ "tokio",
+ "tokio-util",
]
[[package]]
@@ -6606,6 +6670,15 @@ dependencies = [
"windows-targets 0.52.6",
]
+[[package]]
+name = "windows-sys"
+version = "0.60.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
+dependencies = [
+ "windows-targets 0.53.5",
+]
+
[[package]]
name = "windows-sys"
version = "0.61.2"
@@ -6639,13 +6712,30 @@ dependencies = [
"windows_aarch64_gnullvm 0.52.6",
"windows_aarch64_msvc 0.52.6",
"windows_i686_gnu 0.52.6",
- "windows_i686_gnullvm",
+ "windows_i686_gnullvm 0.52.6",
"windows_i686_msvc 0.52.6",
"windows_x86_64_gnu 0.52.6",
"windows_x86_64_gnullvm 0.52.6",
"windows_x86_64_msvc 0.52.6",
]
+[[package]]
+name = "windows-targets"
+version = "0.53.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3"
+dependencies = [
+ "windows-link 0.2.1",
+ "windows_aarch64_gnullvm 0.53.1",
+ "windows_aarch64_msvc 0.53.1",
+ "windows_i686_gnu 0.53.1",
+ "windows_i686_gnullvm 0.53.1",
+ "windows_i686_msvc 0.53.1",
+ "windows_x86_64_gnu 0.53.1",
+ "windows_x86_64_gnullvm 0.53.1",
+ "windows_x86_64_msvc 0.53.1",
+]
+
[[package]]
name = "windows-threading"
version = "0.1.0"
@@ -6667,6 +6757,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53"
+
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.2"
@@ -6679,6 +6775,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006"
+
[[package]]
name = "windows_i686_gnu"
version = "0.42.2"
@@ -6691,12 +6793,24 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
+[[package]]
+name = "windows_i686_gnu"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3"
+
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c"
+
[[package]]
name = "windows_i686_msvc"
version = "0.42.2"
@@ -6709,6 +6823,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
+[[package]]
+name = "windows_i686_msvc"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2"
+
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.2"
@@ -6721,6 +6841,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499"
+
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.2"
@@ -6733,6 +6859,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1"
+
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.2"
@@ -6745,6 +6877,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.53.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
+
[[package]]
name = "winit"
version = "0.30.12"
@@ -6899,7 +7037,7 @@ dependencies = [
"vulkano-shaders",
"wayland-client",
"wayland-egl",
- "wayvr_ipc",
+ "wayvr-ipc",
"wgui",
"winit",
"wlx-capture",
diff --git a/Cargo.toml b/Cargo.toml
index 5c89cda..dd28db1 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -17,6 +17,7 @@ members = [
"wlx-overlay-s",
"wlx-capture",
"dash-frontend",
+ "wayvr-ipc",
]
resolver = "3"
diff --git a/wayvr-ipc/Cargo.lock b/wayvr-ipc/Cargo.lock
new file mode 100644
index 0000000..59143c9
--- /dev/null
+++ b/wayvr-ipc/Cargo.lock
@@ -0,0 +1,390 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "addr2line"
+version = "0.24.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
+dependencies = [
+ "gimli",
+]
+
+[[package]]
+name = "adler2"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
+
+[[package]]
+name = "anyhow"
+version = "1.0.95"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04"
+
+[[package]]
+name = "backtrace"
+version = "0.3.74"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a"
+dependencies = [
+ "addr2line",
+ "cfg-if",
+ "libc",
+ "miniz_oxide",
+ "object",
+ "rustc-demangle",
+ "windows-targets",
+]
+
+[[package]]
+name = "bytes"
+version = "1.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "doctest-file"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aac81fa3e28d21450aa4d2ac065992ba96a1d7303efbce51a95f4fd175b67562"
+
+[[package]]
+name = "futures-core"
+version = "0.3.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
+
+[[package]]
+name = "futures-sink"
+version = "0.3.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7"
+
+[[package]]
+name = "gimli"
+version = "0.31.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
+
+[[package]]
+name = "interprocess"
+version = "2.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "894148491d817cb36b6f778017b8ac46b17408d522dd90f539d677ea938362eb"
+dependencies = [
+ "doctest-file",
+ "futures-core",
+ "libc",
+ "recvmsg",
+ "tokio",
+ "widestring",
+ "windows-sys",
+]
+
+[[package]]
+name = "itoa"
+version = "1.0.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
+
+[[package]]
+name = "libc"
+version = "0.2.169"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
+
+[[package]]
+name = "log"
+version = "0.4.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
+
+[[package]]
+name = "memchr"
+version = "2.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
+
+[[package]]
+name = "miniz_oxide"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394"
+dependencies = [
+ "adler2",
+]
+
+[[package]]
+name = "mio"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
+dependencies = [
+ "libc",
+ "wasi",
+ "windows-sys",
+]
+
+[[package]]
+name = "object"
+version = "0.36.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "pin-project-lite"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.93"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.38"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "recvmsg"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3edd4d5d42c92f0a659926464d4cce56b562761267ecf0f469d85b7de384175"
+
+[[package]]
+name = "rustc-demangle"
+version = "0.1.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
+
+[[package]]
+name = "ryu"
+version = "1.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
+
+[[package]]
+name = "serde"
+version = "1.0.217"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.217"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.135"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9"
+dependencies = [
+ "itoa",
+ "memchr",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "smallvec"
+version = "1.13.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
+
+[[package]]
+name = "socket2"
+version = "0.5.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8"
+dependencies = [
+ "libc",
+ "windows-sys",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.96"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "tokio"
+version = "1.43.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e"
+dependencies = [
+ "backtrace",
+ "bytes",
+ "libc",
+ "mio",
+ "pin-project-lite",
+ "socket2",
+ "tokio-macros",
+ "windows-sys",
+]
+
+[[package]]
+name = "tokio-macros"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "tokio-util"
+version = "0.7.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078"
+dependencies = [
+ "bytes",
+ "futures-core",
+ "futures-sink",
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
+
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
+[[package]]
+name = "wayvr-ipc"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "bytes",
+ "interprocess",
+ "log",
+ "serde",
+ "serde_json",
+ "smallvec",
+ "tokio",
+ "tokio-util",
+]
+
+[[package]]
+name = "widestring"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311"
+
+[[package]]
+name = "windows-sys"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
diff --git a/wayvr-ipc/Cargo.toml b/wayvr-ipc/Cargo.toml
new file mode 100644
index 0000000..392a6f0
--- /dev/null
+++ b/wayvr-ipc/Cargo.toml
@@ -0,0 +1,21 @@
+[package]
+name = "wayvr-ipc"
+version = "0.1.0"
+edition = "2024"
+
+[dependencies]
+bytes = "1.9.0"
+smallvec = "1.13.2"
+serde = { version = "1", features = ["derive"] }
+anyhow = "1.0.93"
+log = "0.4.22"
+
+# client-only deps
+interprocess = { version = "2.2.2", features = ["tokio"], optional = true }
+tokio = { version = "1.42.0", features = ["macros"], optional = true }
+tokio-util = { version = "0.7.13", optional = true }
+serde_json = "1.0.135"
+
+[features]
+default = ["client"]
+client = ["dep:tokio", "dep:tokio-util", "dep:interprocess"]
diff --git a/wayvr-ipc/LICENSE.txt b/wayvr-ipc/LICENSE.txt
new file mode 100644
index 0000000..de54ca7
--- /dev/null
+++ b/wayvr-ipc/LICENSE.txt
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2025 Aleksander
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
diff --git a/wayvr-ipc/README.md b/wayvr-ipc/README.md
new file mode 100644
index 0000000..1b26803
--- /dev/null
+++ b/wayvr-ipc/README.md
@@ -0,0 +1,9 @@
+# WayVR Protocol Specification & Client Implementation
+
+This repository contains the IPC specification and client implementation for the WayVR Server protocol (which is used in wlx-overlay-s). The primary purpose is to enable communication between applications and the WayVR server, offering a range of API functions.
+
+[WayVR Server README](https://github.com/galister/wlx-overlay-s/tree/main/contrib/wayvr)
+
+## Usage
+
+[Example WayVR IPC Client usage in WayVR Dashboard](https://github.com/olekolek1000/wayvr-dashboard/blob/master/src-tauri/src/frontend_ipc.rs)
diff --git a/wayvr-ipc/rustfmt.toml b/wayvr-ipc/rustfmt.toml
new file mode 100644
index 0000000..39694dc
--- /dev/null
+++ b/wayvr-ipc/rustfmt.toml
@@ -0,0 +1,2 @@
+tab_spaces = 2
+hard_tabs = true
\ No newline at end of file
diff --git a/wayvr-ipc/src/client.rs b/wayvr-ipc/src/client.rs
new file mode 100644
index 0000000..46cd0d2
--- /dev/null
+++ b/wayvr-ipc/src/client.rs
@@ -0,0 +1,496 @@
+use bytes::BufMut;
+use interprocess::local_socket::{
+ self,
+ tokio::{prelude::*, Stream},
+ GenericNamespaced,
+};
+use serde::Serialize;
+use smallvec::SmallVec;
+use std::sync::{Arc, Weak};
+use tokio::{
+ io::{AsyncReadExt, AsyncWriteExt},
+ sync::Mutex,
+};
+use tokio_util::sync::CancellationToken;
+
+use crate::{
+ gen_id,
+ ipc::{self, Serial},
+ packet_client::{self, PacketClient},
+ packet_server::{self, PacketServer},
+ util::notifier::Notifier,
+};
+
+pub struct QueuedPacket {
+ notifier: Notifier,
+ serial: Serial,
+ packet: Option,
+}
+
+gen_id!(
+ QueuedPacketVec,
+ QueuedPacket,
+ QueuedPacketCell,
+ QueuedPacketHandle
+);
+
+#[derive(Debug, Serialize, Clone)]
+pub struct AuthInfo {
+ pub runtime: String,
+}
+
+type SignalFunc = Box bool + Send>;
+
+pub struct WayVRClient {
+ receiver: ReceiverMutex,
+ sender: SenderMutex,
+ cancel_token: CancellationToken,
+ exiting: bool,
+ queued_packets: QueuedPacketVec,
+ pub auth: Option, // Some if authenticated
+ pub on_signal: Option,
+}
+
+pub async fn send_packet(sender: &SenderMutex, data: &[u8]) -> anyhow::Result<()> {
+ let mut bytes = bytes::BytesMut::new();
+
+ // packet size
+ bytes.put_u32(data.len() as u32);
+
+ // packet data
+ bytes.put_slice(data);
+
+ sender.lock().await.write_all(&bytes).await?;
+
+ Ok(())
+}
+
+pub type WayVRClientMutex = Arc>;
+pub type WayVRClientWeak = Weak>;
+
+type ReceiverMutex = Arc>;
+type SenderMutex = Arc>;
+
+async fn client_runner(client: WayVRClientMutex) -> anyhow::Result<()> {
+ loop {
+ WayVRClient::tick(client.clone()).await?;
+ }
+}
+
+type Payload = SmallVec<[u8; 64]>;
+
+async fn read_payload(
+ conn: &mut local_socket::tokio::RecvHalf,
+ size: u32,
+) -> anyhow::Result {
+ let mut payload = Payload::new();
+ payload.resize(size as usize, 0);
+ conn.read_exact(&mut payload).await?;
+ Ok(payload)
+}
+
+macro_rules! bail_unexpected_response {
+ () => {
+ anyhow::bail!("unexpected response");
+ };
+}
+
+// Send and wait for a response from the server
+macro_rules! send_and_wait {
+ ($client_mtx:expr, $serial:expr, $packet_to_send:expr, $expected_response_type:ident) => {{
+ let result =
+ WayVRClient::queue_wait_packet($client_mtx, $serial, &ipc::data_encode($packet_to_send))
+ .await?;
+ if let PacketServer::$expected_response_type(_, res) = result {
+ res
+ } else {
+ bail_unexpected_response!();
+ }
+ }};
+}
+
+// Send without expecting any response
+macro_rules! send_only {
+ ($client_mtx:expr, $packet_to_send:expr) => {{
+ WayVRClient::send_payload($client_mtx, &ipc::data_encode($packet_to_send)).await?;
+ }};
+}
+
+impl WayVRClient {
+ pub fn set_signal_handler(&mut self, on_signal: SignalFunc) {
+ self.on_signal = Some(on_signal);
+ }
+
+ pub async fn new(client_name: &str) -> anyhow::Result {
+ let printname = "/tmp/wayvr_ipc.sock";
+ let name = printname.to_ns_name::()?;
+
+ let stream = match Stream::connect(name).await {
+ Ok(c) => c,
+ Err(e) => {
+ anyhow::bail!("Failed to connect to the WayVR IPC: {}", e)
+ }
+ };
+ let (receiver, sender) = stream.split();
+
+ let receiver = Arc::new(Mutex::new(receiver));
+ let sender = Arc::new(Mutex::new(sender));
+
+ let cancel_token = CancellationToken::new();
+
+ let client = Arc::new(Mutex::new(Self {
+ receiver,
+ sender: sender.clone(),
+ exiting: false,
+ cancel_token: cancel_token.clone(),
+ queued_packets: QueuedPacketVec::new(),
+ auth: None,
+ on_signal: None,
+ }));
+
+ WayVRClient::start_runner(client.clone(), cancel_token);
+
+ // Send handshake to the server
+ send_packet(
+ &sender,
+ &ipc::data_encode(&PacketClient::Handshake(packet_client::Handshake {
+ client_name: String::from(client_name),
+ magic: String::from(ipc::CONNECTION_MAGIC),
+ protocol_version: ipc::PROTOCOL_VERSION,
+ })),
+ )
+ .await?;
+
+ Ok(client)
+ }
+
+ fn start_runner(client: WayVRClientMutex, cancel_token: CancellationToken) {
+ tokio::spawn(async move {
+ tokio::select! {
+ _ = cancel_token.cancelled() => {
+ log::info!("Exiting IPC runner gracefully");
+ }
+ e = client_runner(client.clone()) => {
+ log::info!("IPC Runner failed: {:?}", e);
+ }
+ }
+ });
+ }
+
+ async fn tick(client_mtx: WayVRClientMutex) -> anyhow::Result<()> {
+ let receiver = {
+ let client = client_mtx.lock().await;
+ client.receiver.clone()
+ };
+
+ // read packet
+ let packet = {
+ let mut receiver = receiver.lock().await;
+ let packet_size = receiver.read_u32().await?;
+ log::trace!("packet size {}", packet_size);
+ if packet_size > 128 * 1024 {
+ anyhow::bail!("packet size too large (> 128 KiB)");
+ }
+ let payload = read_payload(&mut receiver, packet_size).await?;
+ let packet: PacketServer = ipc::data_decode(&payload)?;
+ packet
+ };
+
+ {
+ let mut client = client_mtx.lock().await;
+
+ if let PacketServer::HandshakeSuccess(success) = &packet {
+ if client.auth.is_some() {
+ anyhow::bail!("Got handshake response twice");
+ }
+
+ client.auth = Some(AuthInfo {
+ runtime: success.runtime.clone(),
+ });
+
+ log::info!(
+ "Authenticated. Server runtime name: \"{}\"",
+ success.runtime
+ );
+ }
+
+ if let PacketServer::Disconnect(disconnect) = &packet {
+ anyhow::bail!("Server disconnected us. Reason: {}", disconnect.reason);
+ }
+
+ if client.auth.is_none() {
+ anyhow::bail!(
+ "Server tried to send us a packet which is not a HandshakeSuccess or Disconnect"
+ );
+ }
+
+ if let PacketServer::WvrStateChanged(_) = &packet {
+ if let Some(on_signal) = &mut client.on_signal {
+ if (*on_signal)(&packet) {
+ // Signal consumed
+ return Ok(());
+ }
+ }
+ }
+
+ // queue packet to read if it contains a serial response
+ if let Some(serial) = packet.serial() {
+ for qpacket in &mut client.queued_packets.vec {
+ let Some(qpacket) = qpacket else {
+ continue;
+ };
+
+ let qpacket = &mut qpacket.obj;
+ if qpacket.serial != *serial {
+ continue; //skip
+ }
+
+ // found response serial, fill it and notify the receiver
+ qpacket.packet = Some(packet);
+ let notifier = qpacket.notifier.clone();
+
+ drop(client);
+ notifier.notify();
+ break;
+ }
+ }
+ }
+
+ Ok(())
+ }
+
+ // Send packet without feedback
+ async fn send_payload(client_mtx: WayVRClientMutex, payload: &[u8]) -> anyhow::Result<()> {
+ let client = client_mtx.lock().await;
+ let sender = client.sender.clone();
+ drop(client);
+ send_packet(&sender, payload).await?;
+ Ok(())
+ }
+
+ async fn queue_wait_packet(
+ client_mtx: WayVRClientMutex,
+ serial: Serial,
+ payload: &[u8],
+ ) -> anyhow::Result {
+ let notifier = Notifier::new();
+
+ // Send packet to the server
+ let queued_packet_handle = {
+ let mut client = client_mtx.lock().await;
+ let handle = client.queued_packets.add(QueuedPacket {
+ notifier: notifier.clone(),
+ packet: None, // will be filled after notify
+ serial,
+ });
+
+ let sender = client.sender.clone();
+
+ drop(client);
+
+ send_packet(&sender, payload).await?;
+ handle
+ };
+
+ // Wait for response message
+ notifier.wait().await;
+
+ // Fetch response packet
+ {
+ let mut client = client_mtx.lock().await;
+
+ let cell = client
+ .queued_packets
+ .get_mut(&queued_packet_handle)
+ .ok_or(anyhow::anyhow!(
+ "missing packet cell, this shouldn't happen"
+ ))?;
+
+ let Some(packet) = cell.packet.take() else {
+ anyhow::bail!("packet is None, this shouldn't happen");
+ };
+
+ client.queued_packets.remove(&queued_packet_handle);
+
+ Ok(packet)
+ }
+ }
+
+ pub async fn fn_wvr_display_list(
+ client: WayVRClientMutex,
+ serial: Serial,
+ ) -> anyhow::Result> {
+ Ok(
+ send_and_wait!(
+ client,
+ serial,
+ &PacketClient::WvrDisplayList(serial),
+ WvrDisplayListResponse
+ )
+ .list,
+ )
+ }
+
+ pub async fn fn_wvr_display_get(
+ client: WayVRClientMutex,
+ serial: Serial,
+ handle: packet_server::WvrDisplayHandle,
+ ) -> anyhow::Result