From be0f6da49519491d6957821d69518997b55a41b6 Mon Sep 17 00:00:00 2001 From: Airyzz <36567925+Airyzz@users.noreply.github.com> Date: Tue, 3 Nov 2026 19:36:44 +1030 Subject: [PATCH 1/7] add openvr as a backend --- Cargo.lock | 241 ++++++++++++++++++++++++++++++++++++- Cargo.toml | 1 + src/backend.rs | 5 +- src/backend/openvr.rs | 190 +++++++++++++++++++++++++++++ src/backend/wayland.rs | 10 +- src/backend/winit.rs | 8 +- src/lib.rs | 77 ++++++++---- src/main.rs | 2 - src/render/render_state.rs | 20 +-- src/widget.rs | 15 ++- 10 files changed, 519 insertions(+), 50 deletions(-) create mode 100644 src/backend/openvr.rs diff --git a/Cargo.lock b/Cargo.lock index e9a9b06..5c365ea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -37,6 +37,15 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "aho-corasick" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba" +dependencies = [ + "memchr", +] + [[package]] name = "aliasable" version = "0.1.3" @@ -186,7 +195,7 @@ dependencies = [ "anyhow", "arrayvec", "log", - "nom", + "nom 8.0.0", "num-rational", "v_frame", ] @@ -206,6 +215,26 @@ version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5" +[[package]] +name = "bindgen" +version = "0.71.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3" +dependencies = [ + "bitflags 2.13.2", + "cexpr", + "clang-sys", + "itertools 0.13.0", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex 1.3.0", + "syn 2.0.119", +] + [[package]] name = "bit_field" version = "0.10.3" @@ -351,7 +380,16 @@ dependencies = [ "find-msvc-tools", "jobserver", "libc", - "shlex", + "shlex 2.0.1", +] + +[[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]] @@ -379,6 +417,26 @@ dependencies = [ "windows-link", ] +[[package]] +name = "clang-sys" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "157a8ba7b480713b56f4c09fd13fc3e0a22a5dfab8097ba61cbc5feef950788a" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "cmake" +version = "0.1.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" +dependencies = [ + "cc", +] + [[package]] name = "color_quant" version = "1.1.0" @@ -519,6 +577,40 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f" +[[package]] +name = "darling" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "darling_macro" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.119", +] + [[package]] name = "dispatch" version = "0.2.0" @@ -614,6 +706,27 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee3f30eec840a3d5da1c6821cf4f5b5a96a619b2fd0f022fc688c8793b369168" +[[package]] +name = "enumset" +version = "1.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e6bd2d7c76d078cd7a460fa169f778c42c026fe16d90e37d7a45d37181bdce5" +dependencies = [ + "enumset_derive", +] + +[[package]] +name = "enumset_derive" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60587c2044cabd91c4d4c73e3912e9f1ea7d76905f31c7eec51869305dae044" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.119", +] + [[package]] name = "equator" version = "0.4.2" @@ -711,6 +824,12 @@ dependencies = [ "zlib-rs", ] +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + [[package]] name = "font-types" version = "0.7.3" @@ -827,6 +946,12 @@ dependencies = [ "weezl", ] +[[package]] +name = "glob" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4eba85ea1d0a966a983acd07deee566e67395d2d96b6fb39e62b5a833f1eb0b" + [[package]] name = "half" version = "2.7.1" @@ -874,6 +999,12 @@ dependencies = [ "cc", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "image" version = "0.24.9" @@ -958,6 +1089,15 @@ dependencies = [ "windows-sys 0.61.2", ] +[[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" @@ -1061,6 +1201,12 @@ dependencies = [ "arrayvec", ] +[[package]] +name = "lazy_static" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20870f649af7073d53e38067b2a84312175d56ea15217e1b15bc83506ec50afb" + [[package]] name = "lebe" version = "0.5.3" @@ -1190,6 +1336,12 @@ dependencies = [ "libc", ] +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.8.9" @@ -1265,6 +1417,16 @@ dependencies = [ "memchr", ] +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "nom" version = "8.0.0" @@ -1638,6 +1800,27 @@ version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" +[[package]] +name = "openvr" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "285c0efd5fbc219f6bd3a03ac60b2c6ccbb87b6c5917a6e4dd157fb4ae4f350a" +dependencies = [ + "enumset", + "lazy_static", + "openvr_sys", +] + +[[package]] +name = "openvr_sys" +version = "2.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53269d9fdd5d927ffd10287c3ac81303392476e84d9ad9af14fecf8c270d7c57" +dependencies = [ + "bindgen", + "cmake", +] + [[package]] name = "orbclient" version = "0.3.55" @@ -1656,6 +1839,7 @@ dependencies = [ "embed-file", "image 0.25.10", "log", + "openvr", "piet", "piet-tiny-skia", "serde", @@ -1824,6 +2008,16 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn 2.0.119", +] + [[package]] name = "proc-macro-crate" version = "3.5.0" @@ -1986,7 +2180,7 @@ dependencies = [ "built", "cfg-if", "interpolate_name", - "itertools", + "itertools 0.14.0", "libc", "libfuzzer-sys", "log", @@ -2098,12 +2292,47 @@ dependencies = [ "bitflags 2.13.2", ] +[[package]] +name = "regex" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" + [[package]] name = "rgb" version = "0.8.53" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47b34b781b31e5d73e9fbc8689c70551fd1ade9a19e3e28cfec8580a79290cc4" +[[package]] +name = "rustc-hash" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" + [[package]] name = "rustc_version" version = "0.4.1" @@ -2239,6 +2468,12 @@ dependencies = [ "zmij", ] +[[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" diff --git a/Cargo.toml b/Cargo.toml index 23adc65..6ec97db 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,7 @@ serde = {version = "1.0.229", features = ["derive"] } base64 = "0.23.1" image = "0.25.10" embed-file = "0.2.0" +openvr = "0.9.0" [target.'cfg(target_os = "windows")'.dependencies] windows = { version = "0.58", features = ["Win32_UI_WindowsAndMessaging"] } diff --git a/src/backend.rs b/src/backend.rs index 012ae42..8475bab 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -1,5 +1,6 @@ use crate::render::render_state::RenderState; +pub mod openvr; pub mod winit; #[cfg(target_os = "linux")] @@ -11,7 +12,7 @@ pub struct OverlayArgs { } pub trait OverlayBackend { - fn show(&self); + fn show(&mut self); fn run_event_queue(&mut self); @@ -20,4 +21,6 @@ pub trait OverlayBackend { fn draw(&mut self); fn make_render_state(&mut self) -> RenderState; + + fn dispose(&mut self); } diff --git a/src/backend/openvr.rs b/src/backend/openvr.rs new file mode 100644 index 0000000..f270f8c --- /dev/null +++ b/src/backend/openvr.rs @@ -0,0 +1,190 @@ +use core::panic; +use std::{thread, time::Duration}; + +use log::info; +use openvr::overlay::OverlayHandle; +use piet_tiny_skia::Cache; + +use crate::{ + backend::{OverlayArgs, OverlayBackend}, + render::render_state::RenderState, +}; + +pub struct OpenVRBackend { + buffer: Vec, + width: usize, + height: usize, + context: openvr::Context, + overlay: openvr::Overlay, + system: openvr::System, + handle: OverlayHandle, + cache: piet_tiny_skia::Cache, +} + +fn make_transform( + translation: [f32; 3], + rotation_radians: [f32; 3], + scale: [f32; 3], +) -> openvr::pose::Matrix3x4 { + let (sx, cx) = rotation_radians[0].sin_cos(); + let (sy, cy) = rotation_radians[1].sin_cos(); + let (sz, cz) = rotation_radians[2].sin_cos(); + + let r00 = cz * cy; + let r01 = cz * sy * sx - sz * cx; + let r02 = cz * sy * cx + sz * sx; + + let r10 = sz * cy; + let r11 = sz * sy * sx + cz * cx; + let r12 = sz * sy * cx - cz * sx; + + let r20 = -sy; + let r21 = cy * sx; + let r22 = cy * cx; + + openvr::pose::Matrix3x4 { + 0: [ + [ + r00 * scale[0], + r01 * scale[1], + r02 * scale[2], + translation[0], + ], + [ + r10 * scale[0], + r11 * scale[1], + r12 * scale[2], + translation[1], + ], + [ + r20 * scale[0], + r21 * scale[1], + r22 * scale[2], + translation[2], + ], + ], + } +} + +impl OpenVRBackend { + fn get_context() -> openvr::Context { + for i in 0..10 { + info!("Attempting to launch openvr"); + + unsafe { + match openvr::init(openvr::ApplicationType::Overlay) { + Ok(context) => { + info!("Got openvr context"); + return context; + } + Err(_) => { + info!("Failed (Attempt {})", i); + thread::sleep(Duration::from_secs(3)); + } + } + } + } + + panic!() + } + + pub fn new(args: &OverlayArgs) -> OpenVRBackend { + let context = Self::get_context(); + + let system = context.system().unwrap(); + + let mut overlay = context.overlay().unwrap(); + + let handle = overlay + .create_overlay("chat.commet\x00", "Commet Overlay\x00") + .expect("Failed to create overlay"); + + let controller_index = openvr::TrackedDeviceIndex(0); + + let transform = make_transform([-0.15, 0.05, -1.0], [0.3, 0.3, 0.0], [1.0, 1.0, 1.0]); + + overlay + .set_transform_tracked_device_relative(handle, controller_index, &transform) + .unwrap(); + + let width = args.width as usize; + let height = args.height as usize; + + let buffer = vec![0u8; width * height * 4]; + + overlay + .set_width(handle, 0.5) + .expect("Failed to set overlay width"); + + OpenVRBackend { + context, + overlay, + handle, + height, + width, + buffer, + system, + cache: Cache::new(), + } + } + + fn draw_overlay(&mut self, state: &RenderState) { + let mut pixmap = tiny_skia::PixmapMut::from_bytes( + &mut self.buffer, + self.width as u32, + self.height as u32, + ) + .ok_or("invalid pixmap") + .unwrap(); + + pixmap.fill(tiny_skia::Color::TRANSPARENT); + + let mut ctx = self.cache.render_context(pixmap); + + state.draw(&mut ctx); + + self.overlay + .set_raw_data(self.handle, &self.buffer, self.width, self.height, 4) + .expect("Failed to upload overlay pixels"); + } +} + +impl OverlayBackend for OpenVRBackend { + fn show(&mut self) { + self.overlay.set_visibility(self.handle, true).unwrap(); + } + + fn run_event_queue(&mut self) {} + + fn poll_event_queue(&mut self, state: &crate::render::render_state::RenderState) { + while let Some(event) = self.system.poll_next_event() { + info!("Received event: {:?}", event.event); + + match event.event { + openvr::system::Event::Quit(_) => { + info!("Acknowledging quit event"); + + self.system.acknowledge_quit_exiting(); + } + _ => (), + } + } + + if state.changed { + self.draw_overlay(state); + + self.show(); + } + } + + fn draw(&mut self) {} + + fn make_render_state(&mut self) -> RenderState { + let mut state = RenderState::new(&mut self.cache); + state.item_height = 32; + + state + } + + fn dispose(&mut self) {} +} diff --git a/src/backend/wayland.rs b/src/backend/wayland.rs index 78bbd40..2059281 100644 --- a/src/backend/wayland.rs +++ b/src/backend/wayland.rs @@ -23,7 +23,9 @@ use smithay_client_toolkit::{ }; use wayland_client::{ - Connection, EventQueue, QueueHandle, globals::registry_queue_init, protocol::{wl_output, wl_region::WlRegion, wl_shm, wl_surface}, + Connection, EventQueue, QueueHandle, + globals::registry_queue_init, + protocol::{wl_output, wl_region::WlRegion, wl_shm, wl_surface}, }; use crate::{ @@ -190,7 +192,7 @@ impl WaylandState { } impl OverlayBackend for WaylandBackend { - fn show(&self) {} + fn show(&mut self) {} fn run_event_queue(&mut self) { let mut state = self.make_render_state(); @@ -222,6 +224,10 @@ impl OverlayBackend for WaylandBackend { fn make_render_state(&mut self) -> RenderState { RenderState::new(&mut self.data.cache) } + + fn dispose(&mut self) { + self.event_queue.flush(); + } } impl CompositorHandler for WaylandState { diff --git a/src/backend/winit.rs b/src/backend/winit.rs index 4144a5c..f0b4fac 100644 --- a/src/backend/winit.rs +++ b/src/backend/winit.rs @@ -240,7 +240,7 @@ impl WinitData { } impl OverlayBackend for WinitBackend { - fn show(&self) {} + fn show(&mut self) {} fn run_event_queue(&mut self) { let event_loop = EventLoop::new().unwrap(); @@ -261,8 +261,12 @@ impl OverlayBackend for WinitBackend { let state = RenderState::new(&mut self.data.cache); self.data.draw(&state); } - + fn make_render_state(&mut self) -> RenderState { RenderState::new(&mut self.data.cache) } + + fn dispose(&mut self) { + self.data.window = None; + } } diff --git a/src/lib.rs b/src/lib.rs index 02700ae..d65a36b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,7 +8,7 @@ use serde_json::json; #[cfg(target_os = "windows")] use crate::backend::winit::WinitBackend; use crate::{ - backend::{OverlayArgs, OverlayBackend}, + backend::{OverlayArgs, OverlayBackend, openvr::OpenVRBackend, winit::WinitBackend}, render::render_state::{ImageState, RenderState}, widget::{Widget, WidgetMessage}, }; @@ -30,39 +30,50 @@ mod backend; mod render; mod widget; -pub fn pick_backend() -> Box { - let args = OverlayArgs { - width: 1024, - height: 1024, - }; +#[derive(PartialEq, Eq, Debug)] +pub enum BackendType { + Wayland, + Winit, + OpenVR, +} + +pub fn pick_backend_type() -> BackendType { + if openvr::is_hmd_present() && openvr::is_runtime_installed() { + return BackendType::OpenVR; + } #[cfg(target_os = "linux")] { let session = env::var("XDG_SESSION_TYPE").ok(); - match session.as_deref() { - Some("wayland") => { - info!("Starting with wayland backend"); - return Box::new(WaylandBackend::new(&args).unwrap()); - } - _ => { - use crate::backend::winit::WinitBackend; - - info!("Starting with winit backend"); - return Box::new(WinitBackend::new(&args)); - } - } + return match session.as_deref() { + Some("wayland") => BackendType::Wayland, + _ => return BackendType::Winit, + }; } #[cfg(target_os = "windows")] - return Box::new(WinitBackend::new(&args)); + return BackendType::Winit; +} + +pub fn start_backend(backend_type: &BackendType) -> Box { + let args = OverlayArgs { + width: 1024, + height: 1024, + }; + + return match backend_type { + BackendType::Wayland => Box::new(WaylandBackend::new(&args).unwrap()), + BackendType::Winit => Box::new(WinitBackend::new(&args)), + BackendType::OpenVR => Box::new(OpenVRBackend::new(&args)), + }; } pub enum Message { Line(String), } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct VoipMemberState { display_name: String, avatar_url: Option, @@ -84,7 +95,8 @@ pub fn run_overlay(dev_mode: bool) { info!("Starting overlay!"); - let mut overlay = pick_backend(); + let mut current_backend_type = pick_backend_type(); + let mut overlay = start_backend(¤t_backend_type); let (input_sender, input_receiver) = channel::(); @@ -92,15 +104,13 @@ pub fn run_overlay(dev_mode: bool) { let mut state = overlay.make_render_state(); - state.item_height = 16; - if dev_mode { state.users.insert( "@test:example.org".to_string(), VoipMemberState { avatar_url: None, display_name: "Luna".to_string(), - muted: false, + muted: true, talking: false, }, ); @@ -143,6 +153,25 @@ pub fn run_overlay(dev_mode: bool) { state.changed = false; + let new_type = pick_backend_type(); + + if new_type != current_backend_type { + info!("Hot swapping to different backend: ${:?}", new_type); + overlay.dispose(); + + let mut new_overlay = start_backend(&new_type); + let mut new_state = new_overlay.make_render_state(); + + for user in state.users.iter() { + new_state.users.insert(user.0.clone(), user.1.clone()); + } + + new_state.changed = true; + state = new_state; + overlay = new_overlay; + current_backend_type = new_type; + } + std::thread::sleep(Duration::from_millis(35)); } } diff --git a/src/main.rs b/src/main.rs index 96b0924..5e646f1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,5 @@ - use overlay::run_overlay; - pub fn main() { run_overlay(true); } diff --git a/src/render/render_state.rs b/src/render/render_state.rs index fd82545..95af7a3 100644 --- a/src/render/render_state.rs +++ b/src/render/render_state.rs @@ -7,7 +7,7 @@ use piet::{ }; use piet_tiny_skia::Cache; -use tiny_skia::{PixmapMut}; +use tiny_skia::PixmapMut; use crate::VoipMemberState; @@ -48,7 +48,7 @@ impl RenderState { return RenderState { iteration: 0, changed: true, - item_height: 32, + item_height: 16, images: BTreeMap::new(), users: BTreeMap::new(), mute_icon: mute_icon, @@ -96,7 +96,6 @@ impl RenderState { let show_mute_icon = entry.muted; - let name = ctx .text() .new_text_layout(text.clone()) @@ -166,14 +165,12 @@ impl RenderState { let radius = circle_radius * 0.8; if show_mute_icon { - row_end += (y_pad * 4.0) + radius; + row_end += (y_pad * 4.0) + radius; } - let icon_position = Point::new(row_end, y_position + (circle_radius / 2.0) + (y_pad * 1.5)); - let icon_rect = Rect { x0: icon_position.x - radius, x1: icon_position.x + radius, @@ -181,12 +178,10 @@ impl RenderState { y1: icon_position.y + radius, }; - if show_mute_icon { row_end = icon_position.x + radius; } - let bg_padding = text_size * 0.2; let bg_opacity = match entry.muted { @@ -195,8 +190,13 @@ impl RenderState { }; ctx.fill( - - RoundedRect::new(x - bg_padding, y_position - bg_padding, row_end + bg_padding, y_position + (bg_padding * 2.0) + text_size, 2.0), + RoundedRect::new( + x - bg_padding, + y_position - bg_padding, + row_end + bg_padding, + y_position + (bg_padding * 2.0) + text_size, + 2.0, + ), &Color::rgba8(12, 12, 12, bg_opacity), ); diff --git a/src/widget.rs b/src/widget.rs index a9da708..cc8f367 100644 --- a/src/widget.rs +++ b/src/widget.rs @@ -96,12 +96,15 @@ impl Widget { pub fn handle_message(&mut self, msg: &WidgetMessage) { match msg.action.as_str() { "capabilities" => { - self.send_response(msg, json!({ - "capabilities": [ - "org.matrix.msc4039.download_file", - "chat.commet.voip_overlay.voip_state" - ] - })); + self.send_response( + msg, + json!({ + "capabilities": [ + "org.matrix.msc4039.download_file", + "chat.commet.voip_overlay.voip_state" + ] + }), + ); } _ => {} } From ad7e2802448054a9490421a928e3ccc94bf6c841 Mon Sep 17 00:00:00 2001 From: Airyzz <36567925+Airyzz@users.noreply.github.com> Date: Tue, 3 Nov 2026 20:16:03 +1030 Subject: [PATCH 2/7] Create build.yml --- .github/workflows/build.yml | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100755 .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100755 index 0000000..fb1f2ec --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,34 @@ + +name: build + +on: + pull_request: + merge_group: + +jobs: + build-windows: + runs-on: windows-2022 + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + submodules: 'true' + + - name: Build + run: cargo build + + build-linux: + continue-on-error: true + strategy: + matrix: + os: [ubuntu-24.04-arm, ubuntu-24.04] + + runs-on: ${{ matrix.os }} + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + submodules: 'true' + + - name: Build + run: cargo build From 561db0f85e250130f2c5521ee80d463516a21e6b Mon Sep 17 00:00:00 2001 From: Airyzz <36567925+Airyzz@users.noreply.github.com> Date: Tue, 3 Nov 2026 20:42:42 +1030 Subject: [PATCH 3/7] Update build.yml --- .github/workflows/build.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fb1f2ec..e97113a 100755 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,6 +29,10 @@ jobs: uses: actions/checkout@v2 with: submodules: 'true' - + - name: Setup Tools + run: | + sudo apt-get update + sudo apt-get install -y pkg-config libxkbcommon-dev + - name: Build run: cargo build From 0cf6423e365f34f3d0dfdd6d8f53a578d36e24d7 Mon Sep 17 00:00:00 2001 From: Airyzz <36567925+Airyzz@users.noreply.github.com> Date: Tue, 3 Nov 2026 20:54:17 +1030 Subject: [PATCH 4/7] try to fix builds on arm --- Cargo.lock | 3 +-- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5c365ea..e83c9fd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1803,8 +1803,7 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "openvr" version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "285c0efd5fbc219f6bd3a03ac60b2c6ccbb87b6c5917a6e4dd157fb4ae4f350a" +source = "git+https://github.com/commetchat/rust-openvr.git?branch=char-type-fixes#34cbda8848825c2d72aac81a1853379d1185f723" dependencies = [ "enumset", "lazy_static", diff --git a/Cargo.toml b/Cargo.toml index 6ec97db..6795abf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ serde = {version = "1.0.229", features = ["derive"] } base64 = "0.23.1" image = "0.25.10" embed-file = "0.2.0" -openvr = "0.9.0" +openvr = { git = "https://github.com/commetchat/rust-openvr.git", branch = "char-type-fixes"} [target.'cfg(target_os = "windows")'.dependencies] windows = { version = "0.58", features = ["Win32_UI_WindowsAndMessaging"] } From 0fd26521be146257a1029ced90c6a8b9f656d37a Mon Sep 17 00:00:00 2001 From: Airyzz <36567925+Airyzz@users.noreply.github.com> Date: Tue, 3 Nov 2026 21:09:17 +1030 Subject: [PATCH 5/7] Update lib.rs --- src/lib.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index d65a36b..caf1915 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,6 +16,7 @@ use crate::{ #[cfg(all(target_os = "linux"))] use crate::backend::wayland::WaylandBackend; +use core::panic; #[cfg(all(target_os = "linux"))] use std::env; use std::{ @@ -63,7 +64,19 @@ pub fn start_backend(backend_type: &BackendType) -> Box { }; return match backend_type { - BackendType::Wayland => Box::new(WaylandBackend::new(&args).unwrap()), + BackendType::Wayland => { + #[cfg(target_os = "linux")] + { + return Box::new(WaylandBackend::new(&args).unwrap()); + } + + #[cfg(not(target_os = "linux"))] + { + use log::error; + error!("Cannot use 'Wayland' backend on a non-linux platform"); + panic!() + } + } BackendType::Winit => Box::new(WinitBackend::new(&args)), BackendType::OpenVR => Box::new(OpenVRBackend::new(&args)), }; From 7a43d42080f4f73a385a726d9818a6bdf8972839 Mon Sep 17 00:00:00 2001 From: Airyzz <36567925+Airyzz@users.noreply.github.com> Date: Tue, 3 Nov 2026 21:14:01 +1030 Subject: [PATCH 6/7] Update lib.rs --- src/lib.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index caf1915..7a2ecd8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,8 +5,6 @@ use piet::ImageBuf; use serde::{Deserialize, Serialize}; use serde_json::json; -#[cfg(target_os = "windows")] -use crate::backend::winit::WinitBackend; use crate::{ backend::{OverlayArgs, OverlayBackend, openvr::OpenVRBackend, winit::WinitBackend}, render::render_state::{ImageState, RenderState}, @@ -16,7 +14,7 @@ use crate::{ #[cfg(all(target_os = "linux"))] use crate::backend::wayland::WaylandBackend; -use core::panic; + #[cfg(all(target_os = "linux"))] use std::env; use std::{ From e1a00fff9acdb8059365cf6a0589150b9ff34e61 Mon Sep 17 00:00:00 2001 From: Airyzz <36567925+Airyzz@users.noreply.github.com> Date: Tue, 3 Nov 2026 22:13:41 +1030 Subject: [PATCH 7/7] Update openvr.rs --- src/backend/openvr.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backend/openvr.rs b/src/backend/openvr.rs index f270f8c..c9b9ccc 100644 --- a/src/backend/openvr.rs +++ b/src/backend/openvr.rs @@ -77,8 +77,8 @@ impl OpenVRBackend { info!("Got openvr context"); return context; } - Err(_) => { - info!("Failed (Attempt {})", i); + Err(e) => { + info!("Failed (Attempt {}) {:?}", i, e); thread::sleep(Duration::from_secs(3)); } }