refactors & clippy recommendations

This commit is contained in:
galister
2025-04-07 00:47:57 +09:00
parent 3365aefc13
commit 1deae19f92
57 changed files with 1199 additions and 1316 deletions

View File

@@ -6,6 +6,12 @@ debug = true
name = "wlx-overlay-s" name = "wlx-overlay-s"
version = "25.4.0" version = "25.4.0"
edition = "2021" edition = "2021"
license = "GPL-3.0-only"
authors = ["galister"]
description = "Access your Wayland/X11 desktop from Monado/WiVRn/SteamVR. Now with Vulkan!"
repository = "https://github.com/galister/wlx-overlay-s"
keywords = ["linux", "openvr", "openxr", "x11", "wayland", "openvr-overlay", "openxr-overlay"]
categories = ["games"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -39,7 +45,7 @@ ovr_overlay = { features = [
"ovr_input", "ovr_input",
"ovr_system", "ovr_system",
], git = "https://github.com/galister/ovr_overlay_oyasumi", optional = true } ], git = "https://github.com/galister/ovr_overlay_oyasumi", optional = true }
regex = "1.10.4" regex = "1.11.1"
rodio = { version = "0.20.1", default-features = false, features = [ rodio = { version = "0.20.1", default-features = false, features = [
"wav", "wav",
"hound", "hound",
@@ -91,7 +97,7 @@ wayvr_ipc = { git = "https://github.com/olekolek1000/wayvr-ipc.git", rev = "a725
################################ ################################
[build-dependencies] [build-dependencies]
regex = { version = "*" } regex = { version = "1.11.1" }
[features] [features]
default = ["openvr", "openxr", "osc", "x11", "wayland", "wayvr"] default = ["openvr", "openxr", "osc", "x11", "wayland", "wayvr"]

View File

@@ -69,17 +69,17 @@ where
app.screens.clear(); app.screens.clear();
let data = if let Some(wl) = wl.as_mut() { let data = if let Some(wl) = wl.as_mut() {
keymap = get_keymap_wl() keymap = get_keymap_wl()
.map_err(|f| log::warn!("Could not load keyboard layout: {}", f)) .map_err(|f| log::warn!("Could not load keyboard layout: {f}"))
.ok(); .ok();
crate::overlays::screen::create_screens_wayland(wl, app)? crate::overlays::screen::create_screens_wayland(wl, app)
} else { } else {
keymap = get_keymap_x11() keymap = get_keymap_x11()
.map_err(|f| log::warn!("Could not load keyboard layout: {}", f)) .map_err(|f| log::warn!("Could not load keyboard layout: {f}"))
.ok(); .ok();
match crate::overlays::screen::create_screens_x11pw(app) { match crate::overlays::screen::create_screens_x11pw(app) {
Ok(data) => data, Ok(data) => data,
Err(e) => { Err(e) => {
log::info!("Will not use PipeWire capture: {:?}", e); log::info!("Will not use PipeWire capture: {e:?}");
crate::overlays::screen::create_screens_xshm(app)? crate::overlays::screen::create_screens_xshm(app)?
} }
} }
@@ -127,6 +127,8 @@ where
Ok(vec![]) Ok(vec![])
} }
#[cfg(feature = "wayland")] #[cfg(feature = "wayland")]
#[allow(clippy::too_many_lines, clippy::cognitive_complexity)]
#[allow(clippy::all, clippy::pedantic, clippy::nursery, clippy::cargo)]
pub fn update(&mut self, app: &mut AppState) -> anyhow::Result<Vec<OverlayData<T>>> { pub fn update(&mut self, app: &mut AppState) -> anyhow::Result<Vec<OverlayData<T>>> {
use crate::overlays::{ use crate::overlays::{
screen::{create_screen_interaction, create_screen_renderer_wl, load_pw_token_config}, screen::{create_screen_interaction, create_screen_renderer_wl, load_pw_token_config},
@@ -154,7 +156,7 @@ where
if create_ran { if create_ran {
continue; continue;
} }
let data = crate::overlays::screen::create_screens_wayland(wl, app)?; let data = crate::overlays::screen::create_screens_wayland(wl, app);
create_ran = true; create_ran = true;
for (meta, state, backend) in data.screens { for (meta, state, backend) in data.screens {
self.overlays.insert( self.overlays.insert(
@@ -337,7 +339,7 @@ where
if !any_shown && *o.state.name == *WATCH_NAME { if !any_shown && *o.state.name == *WATCH_NAME {
o.state.reset(app, true); o.state.reset(app, true);
} }
}) });
} }
} }

View File

@@ -50,7 +50,7 @@ impl InputState {
} }
} }
pub fn pre_update(&mut self) { pub const fn pre_update(&mut self) {
self.pointers[0].before = self.pointers[0].now; self.pointers[0].before = self.pointers[0].now;
self.pointers[1].before = self.pointers[1].now; self.pointers[1].before = self.pointers[1].now;
} }
@@ -58,50 +58,7 @@ impl InputState {
pub fn post_update(&mut self, session: &AppSession) { pub fn post_update(&mut self, session: &AppSession) {
for hand in &mut self.pointers { for hand in &mut self.pointers {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
{ debug_print_hand(hand);
if hand.now.click != hand.before.click {
log::debug!("Hand {}: click {}", hand.idx, hand.now.click);
}
if hand.now.grab != hand.before.grab {
log::debug!("Hand {}: grab {}", hand.idx, hand.now.grab);
}
if hand.now.alt_click != hand.before.alt_click {
log::debug!("Hand {}: alt_click {}", hand.idx, hand.now.alt_click);
}
if hand.now.show_hide != hand.before.show_hide {
log::debug!("Hand {}: show_hide {}", hand.idx, hand.now.show_hide);
}
if hand.now.toggle_dashboard != hand.before.toggle_dashboard {
log::debug!(
"Hand {}: toggle_dashboard {}",
hand.idx,
hand.now.toggle_dashboard
);
}
if hand.now.space_drag != hand.before.space_drag {
log::debug!("Hand {}: space_drag {}", hand.idx, hand.now.space_drag);
}
if hand.now.space_rotate != hand.before.space_rotate {
log::debug!("Hand {}: space_rotate {}", hand.idx, hand.now.space_rotate);
}
if hand.now.space_reset != hand.before.space_reset {
log::debug!("Hand {}: space_reset {}", hand.idx, hand.now.space_reset);
}
if hand.now.click_modifier_right != hand.before.click_modifier_right {
log::debug!(
"Hand {}: click_modifier_right {}",
hand.idx,
hand.now.click_modifier_right
);
}
if hand.now.click_modifier_middle != hand.before.click_modifier_middle {
log::debug!(
"Hand {}: click_modifier_middle {}",
hand.idx,
hand.now.click_modifier_middle
);
}
}
if hand.now.click { if hand.now.click {
hand.last_click = Instant::now(); hand.last_click = Instant::now();
@@ -118,8 +75,8 @@ impl InputState {
} }
let hmd_up = self.hmd.transform_vector3a(Vec3A::Y); let hmd_up = self.hmd.transform_vector3a(Vec3A::Y);
let dot = let dot = hmd_up.dot(hand.pose.transform_vector3a(Vec3A::X))
hmd_up.dot(hand.pose.transform_vector3a(Vec3A::X)) * (1.0 - 2.0 * hand.idx as f32); * 2.0f32.mul_add(-(hand.idx as f32), 1.0);
hand.interaction.mode = if dot < -0.85 { hand.interaction.mode = if dot < -0.85 {
PointerMode::Right PointerMode::Right
@@ -143,7 +100,7 @@ impl InputState {
} }
} }
_ => {} _ => {}
}; }
if hand.now.alt_click != hand.before.alt_click { if hand.now.alt_click != hand.before.alt_click {
// Reap previous processes // Reap previous processes
@@ -166,6 +123,54 @@ impl InputState {
} }
} }
#[cfg(debug_assertions)]
fn debug_print_hand(hand: &Pointer) {
{
if hand.now.click != hand.before.click {
log::debug!("Hand {}: click {}", hand.idx, hand.now.click);
}
if hand.now.grab != hand.before.grab {
log::debug!("Hand {}: grab {}", hand.idx, hand.now.grab);
}
if hand.now.alt_click != hand.before.alt_click {
log::debug!("Hand {}: alt_click {}", hand.idx, hand.now.alt_click);
}
if hand.now.show_hide != hand.before.show_hide {
log::debug!("Hand {}: show_hide {}", hand.idx, hand.now.show_hide);
}
if hand.now.toggle_dashboard != hand.before.toggle_dashboard {
log::debug!(
"Hand {}: toggle_dashboard {}",
hand.idx,
hand.now.toggle_dashboard
);
}
if hand.now.space_drag != hand.before.space_drag {
log::debug!("Hand {}: space_drag {}", hand.idx, hand.now.space_drag);
}
if hand.now.space_rotate != hand.before.space_rotate {
log::debug!("Hand {}: space_rotate {}", hand.idx, hand.now.space_rotate);
}
if hand.now.space_reset != hand.before.space_reset {
log::debug!("Hand {}: space_reset {}", hand.idx, hand.now.space_reset);
}
if hand.now.click_modifier_right != hand.before.click_modifier_right {
log::debug!(
"Hand {}: click_modifier_right {}",
hand.idx,
hand.now.click_modifier_right
);
}
if hand.now.click_modifier_middle != hand.before.click_modifier_middle {
log::debug!(
"Hand {}: click_modifier_middle {}",
hand.idx,
hand.now.click_modifier_middle
);
}
}
}
pub struct InteractionState { pub struct InteractionState {
pub mode: PointerMode, pub mode: PointerMode,
pub grabbed: Option<GrabData>, pub grabbed: Option<GrabData>,
@@ -207,10 +212,10 @@ impl Pointer {
idx, idx,
pose: Affine3A::IDENTITY, pose: Affine3A::IDENTITY,
raw_pose: Affine3A::IDENTITY, raw_pose: Affine3A::IDENTITY,
now: Default::default(), now: PointerState::default(),
before: Default::default(), before: PointerState::default(),
last_click: Instant::now(), last_click: Instant::now(),
interaction: Default::default(), interaction: InteractionState::default(),
} }
} }
} }
@@ -320,6 +325,7 @@ where
} }
} }
#[allow(clippy::too_many_lines, clippy::cognitive_complexity)]
fn interact_hand<O>( fn interact_hand<O>(
idx: usize, idx: usize,
overlays: &mut OverlayContainer<O>, overlays: &mut OverlayContainer<O>,
@@ -434,7 +440,7 @@ where
if can_curve { if can_curve {
let cur = hovered.state.curvature.unwrap_or(0.0); let cur = hovered.state.curvature.unwrap_or(0.0);
let new = (cur - scroll_y * 0.01).min(0.5); let new = scroll_y.mul_add(-0.01, cur).min(0.5);
if new <= f32::EPSILON { if new <= f32::EPSILON {
hovered.state.curvature = None; hovered.state.curvature = None;
} else { } else {
@@ -480,7 +486,7 @@ impl Pointer {
if let Some(hit) = self.ray_test( if let Some(hit) = self.ray_test(
overlay.state.id, overlay.state.id,
&overlay.state.transform, &overlay.state.transform,
&overlay.state.curvature, overlay.state.curvature.as_ref(),
) { ) {
if hit.dist.is_infinite() || hit.dist.is_nan() { if hit.dist.is_infinite() || hit.dist.is_nan() {
continue; continue;
@@ -491,7 +497,7 @@ impl Pointer {
hits.sort_by(|a, b| a.dist.total_cmp(&b.dist)); hits.sort_by(|a, b| a.dist.total_cmp(&b.dist));
for hit in hits.iter() { for hit in &hits {
let overlay = overlays.get_by_id(hit.overlay).unwrap(); // safe because we just got the id from the overlay let overlay = overlays.get_by_id(hit.overlay).unwrap(); // safe because we just got the id from the overlay
let uv = overlay let uv = overlay
@@ -573,7 +579,7 @@ impl Pointer {
.state .state
.transform .transform
.matrix3 .matrix3
.mul_scalar(1.0 - 0.025 * self.now.scroll_y); .mul_scalar(0.025f32.mul_add(-self.now.scroll_y, 1.0));
} else if config.allow_sliding && self.now.scroll_y.is_finite() { } else if config.allow_sliding && self.now.scroll_y.is_finite() {
grab_data.offset.z -= self.now.scroll_y * 0.05; grab_data.offset.z -= self.now.scroll_y * 0.05;
} }
@@ -620,12 +626,19 @@ impl Pointer {
&self, &self,
overlay: OverlayID, overlay: OverlayID,
transform: &Affine3A, transform: &Affine3A,
curvature: &Option<f32>, curvature: Option<&f32>,
) -> Option<RayHit> { ) -> Option<RayHit> {
let (dist, local_pos) = match curvature { let (dist, local_pos) = curvature.map_or_else(
Some(curvature) => raycast_cylinder(&self.pose, Vec3A::NEG_Z, transform, *curvature), || {
_ => raycast_plane(&self.pose, Vec3A::NEG_Z, transform, Vec3A::NEG_Z), Some(raycast_plane(
}?; &self.pose,
Vec3A::NEG_Z,
transform,
Vec3A::NEG_Z,
))
},
|curvature| raycast_cylinder(&self.pose, Vec3A::NEG_Z, transform, *curvature),
)?;
if dist < 0.0 { if dist < 0.0 {
// hit is behind us // hit is behind us
@@ -646,7 +659,7 @@ fn raycast_plane(
source_fwd: Vec3A, source_fwd: Vec3A,
plane: &Affine3A, plane: &Affine3A,
plane_norm: Vec3A, plane_norm: Vec3A,
) -> Option<(f32, Vec2)> { ) -> (f32, Vec2) {
let plane_normal = plane.transform_vector3a(plane_norm); let plane_normal = plane.transform_vector3a(plane_norm);
let ray_dir = source.transform_vector3a(source_fwd); let ray_dir = source.transform_vector3a(source_fwd);
@@ -658,7 +671,7 @@ fn raycast_plane(
.transform_point3a(source.translation + ray_dir * dist) .transform_point3a(source.translation + ray_dir * dist)
.xy(); .xy();
Some((dist, hit_local)) (dist, hit_local)
} }
fn raycast_cylinder( fn raycast_cylinder(
@@ -675,27 +688,27 @@ fn raycast_cylinder(
} }
.inverse(); .inverse();
let r = size / (2.0 * PI * curvature); let radius = size / (2.0 * PI * curvature);
let ray_dir = to_local.transform_vector3a(source.transform_vector3a(source_fwd)); let ray_dir = to_local.transform_vector3a(source.transform_vector3a(source_fwd));
let ray_origin = to_local.transform_point3a(source.translation) + Vec3A::NEG_Z * r; let ray_origin = to_local.transform_point3a(source.translation) + Vec3A::NEG_Z * radius;
let d = ray_dir.xz(); let v_dir = ray_dir.xz();
let s = ray_origin.xz(); let v_pos = ray_origin.xz();
let a = d.dot(d); let l_dir = v_dir.dot(v_dir);
let b = d.dot(s); let l_pos = v_dir.dot(v_pos);
let c = s.dot(s) - r * r; let c = radius.mul_add(-radius, v_pos.dot(v_pos));
let d = (b * b) - (a * c); let d = l_pos.mul_add(l_pos, -(l_dir * c));
if d < f32::EPSILON { if d < f32::EPSILON {
return None; return None;
} }
let sqrt_d = d.sqrt(); let sqrt_d = d.sqrt();
let t1 = (-b - sqrt_d) / a; let t1 = (-l_pos - sqrt_d) / l_dir;
let t2 = (-b + sqrt_d) / a; let t2 = (-l_pos + sqrt_d) / l_dir;
let t = t1.max(t2); let t = t1.max(t2);
@@ -709,8 +722,8 @@ fn raycast_cylinder(
return None; return None;
} }
let max_angle = 2.0 * (size / (2.0 * r)); let max_angle = 2.0 * (size / (2.0 * radius));
let x_angle = (hit_local.x / r).asin(); let x_angle = (hit_local.x / radius).asin();
hit_local.x = x_angle / max_angle; hit_local.x = x_angle / max_angle;
hit_local.y /= size; hit_local.y /= size;

View File

@@ -57,8 +57,7 @@ impl NotificationManager {
Ok(c) => c, Ok(c) => c,
Err(e) => { Err(e) => {
log::error!( log::error!(
"Failed to connect to dbus. Desktop notifications will not work. Cause: {:?}", "Failed to connect to dbus. Desktop notifications will not work. Cause: {e:?}"
e
); );
return; return;
} }
@@ -81,55 +80,50 @@ impl NotificationManager {
(vec![rule.match_str()], 0u32), (vec![rule.match_str()], 0u32),
); );
match result { if matches!(result, Ok(())) {
Ok(_) => { let sender = self.tx_toast.clone();
let sender = self.tx_toast.clone(); c.start_receive(
c.start_receive( rule,
rule, Box::new(move |msg, _| {
Box::new(move |msg, _| { if let Ok(toast) = parse_dbus(&msg) {
if let Ok(toast) = parse_dbus(&msg) { match sender.try_send(toast) {
match sender.try_send(toast) { Ok(()) => {}
Ok(_) => {}
Err(e) => {
log::error!("Failed to send notification: {:?}", e);
}
}
}
true
}),
);
log::info!("Listening to DBus notifications via BecomeMonitor.");
}
Err(_) => {
let rule_with_eavesdrop = {
let mut rule = rule.clone();
rule.eavesdrop = true;
rule
};
let sender2 = self.tx_toast.clone();
let result = c.add_match(rule_with_eavesdrop, move |_: (), _, msg| {
if let Ok(toast) = parse_dbus(msg) {
match sender2.try_send(toast) {
Ok(_) => {}
Err(e) => { Err(e) => {
log::error!("Failed to send notification: {:?}", e); log::error!("Failed to send notification: {e:?}");
} }
} }
} }
true true
}); }),
);
log::info!("Listening to DBus notifications via BecomeMonitor.");
} else {
let rule_with_eavesdrop = {
let mut rule = rule.clone();
rule.eavesdrop = true;
rule
};
match result { let sender2 = self.tx_toast.clone();
Ok(_) => { let result = c.add_match(rule_with_eavesdrop, move |(): (), _, msg| {
log::info!("Listening to DBus notifications via eavesdrop."); if let Ok(toast) = parse_dbus(msg) {
} match sender2.try_send(toast) {
Err(_) => { Ok(()) => {}
log::error!( Err(e) => {
"Failed to add DBus match. Desktop notifications will not work.", log::error!("Failed to send notification: {e:?}");
); }
} }
} }
true
});
match result {
Ok(_) => {
log::info!("Listening to DBus notifications via eavesdrop.");
}
Err(_) => {
log::error!("Failed to add DBus match. Desktop notifications will not work.",);
}
} }
} }
@@ -144,12 +138,12 @@ impl NotificationManager {
let socket = match std::net::UdpSocket::bind(addr) { let socket = match std::net::UdpSocket::bind(addr) {
Ok(s) => s, Ok(s) => s,
Err(e) => { Err(e) => {
log::error!("Failed to bind notification socket @ {}: {:?}", addr, e); log::error!("Failed to bind notification socket @ {addr}: {e:?}");
return; return;
} }
}; };
if let Err(err) = socket.set_read_timeout(Some(Duration::from_millis(200))) { if let Err(err) = socket.set_read_timeout(Some(Duration::from_millis(200))) {
log::error!("Failed to set read timeout: {:?}", err); log::error!("Failed to set read timeout: {err:?}");
} }
let mut buf = [0u8; 1024 * 16]; // vrcx embeds icons as b64 let mut buf = [0u8; 1024 * 16]; // vrcx embeds icons as b64
@@ -159,14 +153,14 @@ impl NotificationManager {
let json_str = match std::str::from_utf8(&buf[..num_bytes]) { let json_str = match std::str::from_utf8(&buf[..num_bytes]) {
Ok(s) => s, Ok(s) => s,
Err(e) => { Err(e) => {
log::error!("Failed to receive notification message: {:?}", e); log::error!("Failed to receive notification message: {e:?}");
continue; continue;
} }
}; };
let msg = match serde_json::from_str::<XsoMessage>(json_str) { let msg = match serde_json::from_str::<XsoMessage>(json_str) {
Ok(m) => m, Ok(m) => m,
Err(e) => { Err(e) => {
log::error!("Failed to parse notification message: {:?}", e); log::error!("Failed to parse notification message: {e:?}");
continue; continue;
} }
}; };
@@ -184,9 +178,9 @@ impl NotificationManager {
.with_sound(msg.volume.unwrap_or(-1.) >= 0.); // XSOverlay still plays at 0, .with_sound(msg.volume.unwrap_or(-1.) >= 0.); // XSOverlay still plays at 0,
match sender.try_send(toast) { match sender.try_send(toast) {
Ok(_) => {} Ok(()) => {}
Err(e) => { Err(e) => {
log::error!("Failed to send notification: {:?}", e); log::error!("Failed to send notification: {e:?}");
} }
} }
} }
@@ -278,6 +272,7 @@ fn parse_dbus(msg: &dbus::Message) -> anyhow::Result<Toast> {
// leave the audio part to the desktop env // leave the audio part to the desktop env
} }
#[allow(dead_code)]
#[allow(non_snake_case)] #[allow(non_snake_case)]
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
struct XsoMessage { struct XsoMessage {

View File

@@ -36,7 +36,7 @@ impl arg::AppendAll for OrgFreedesktopDBusPropertiesPropertiesChanged {
impl arg::ReadAll for OrgFreedesktopDBusPropertiesPropertiesChanged { impl arg::ReadAll for OrgFreedesktopDBusPropertiesPropertiesChanged {
fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> { fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> {
Ok(OrgFreedesktopDBusPropertiesPropertiesChanged { Ok(Self {
interface_name: i.read()?, interface_name: i.read()?,
changed_properties: i.read()?, changed_properties: i.read()?,
invalidated_properties: i.read()?, invalidated_properties: i.read()?,
@@ -158,7 +158,7 @@ impl arg::AppendAll for OrgFreedesktopNotificationsOnDndToggle {
impl arg::ReadAll for OrgFreedesktopNotificationsOnDndToggle { impl arg::ReadAll for OrgFreedesktopNotificationsOnDndToggle {
fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> { fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> {
Ok(OrgFreedesktopNotificationsOnDndToggle { dnd: i.read()? }) Ok(Self { dnd: i.read()? })
} }
} }
@@ -182,7 +182,7 @@ impl arg::AppendAll for OrgFreedesktopNotificationsNotificationClosed {
impl arg::ReadAll for OrgFreedesktopNotificationsNotificationClosed { impl arg::ReadAll for OrgFreedesktopNotificationsNotificationClosed {
fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> { fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> {
Ok(OrgFreedesktopNotificationsNotificationClosed { Ok(Self {
id: i.read()?, id: i.read()?,
reason: i.read()?, reason: i.read()?,
}) })
@@ -209,7 +209,7 @@ impl arg::AppendAll for OrgFreedesktopNotificationsActionInvoked {
impl arg::ReadAll for OrgFreedesktopNotificationsActionInvoked { impl arg::ReadAll for OrgFreedesktopNotificationsActionInvoked {
fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> { fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> {
Ok(OrgFreedesktopNotificationsActionInvoked { Ok(Self {
id: i.read()?, id: i.read()?,
action_key: i.read()?, action_key: i.read()?,
}) })
@@ -236,7 +236,7 @@ impl arg::AppendAll for OrgFreedesktopNotificationsNotificationReplied {
impl arg::ReadAll for OrgFreedesktopNotificationsNotificationReplied { impl arg::ReadAll for OrgFreedesktopNotificationsNotificationReplied {
fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> { fn read(i: &mut arg::Iter) -> Result<Self, arg::TypeMismatchError> {
Ok(OrgFreedesktopNotificationsNotificationReplied { Ok(Self {
id: i.read()?, id: i.read()?,
text: i.read()?, text: i.read()?,
}) })

View File

@@ -13,7 +13,7 @@ pub trait Affine3AConvert {
impl Affine3AConvert for Matrix3x4 { impl Affine3AConvert for Matrix3x4 {
fn from_affine(affine: &Affine3A) -> Self { fn from_affine(affine: &Affine3A) -> Self {
Matrix3x4([ Self([
[ [
affine.matrix3.x_axis.x, affine.matrix3.x_axis.x,
affine.matrix3.y_axis.x, affine.matrix3.y_axis.x,
@@ -47,7 +47,7 @@ impl Affine3AConvert for Matrix3x4 {
impl Affine3AConvert for HmdMatrix34_t { impl Affine3AConvert for HmdMatrix34_t {
fn from_affine(affine: &Affine3A) -> Self { fn from_affine(affine: &Affine3A) -> Self {
HmdMatrix34_t { Self {
m: [ m: [
[ [
affine.matrix3.x_axis.x, affine.matrix3.x_axis.x,
@@ -89,13 +89,13 @@ pub(super) enum OVRError {
impl From<ovr_overlay::errors::EVRInputError> for OVRError { impl From<ovr_overlay::errors::EVRInputError> for OVRError {
fn from(e: ovr_overlay::errors::EVRInputError) -> Self { fn from(e: ovr_overlay::errors::EVRInputError) -> Self {
OVRError::InputError(e.description()) Self::InputError(e.description())
} }
} }
impl From<OVRError> for BackendError { impl From<OVRError> for BackendError {
fn from(e: OVRError) -> Self { fn from(e: OVRError) -> Self {
BackendError::Fatal(anyhow::Error::new(e)) Self::Fatal(anyhow::Error::new(e))
} }
} }

View File

@@ -107,7 +107,8 @@ impl OpenVrInputSource {
haptics_hnd: haptics_hnd[i], haptics_hnd: haptics_hnd[i],
}); });
Ok(OpenVrInputSource { Ok(Self {
hands,
set_hnd, set_hnd,
click_hnd, click_hnd,
grab_hnd, grab_hnd,
@@ -120,14 +121,13 @@ impl OpenVrInputSource {
click_modifier_right_hnd, click_modifier_right_hnd,
click_modifier_middle_hnd, click_modifier_middle_hnd,
move_mouse_hnd, move_mouse_hnd,
hands,
}) })
} }
pub fn haptics(&mut self, input: &mut InputManager, hand: usize, haptics: &Haptics) { pub fn haptics(&mut self, input: &mut InputManager, hand: usize, haptics: &Haptics) {
let hnd = self.hands[hand].haptics_hnd; let action_handle = self.hands[hand].haptics_hnd;
let _ = input.trigger_haptic_vibration_action( let _ = input.trigger_haptic_vibration_action(
hnd, action_handle,
0.0, 0.0,
Duration::from_secs_f32(haptics.duration), Duration::from_secs_f32(haptics.duration),
haptics.frequency, haptics.frequency,
@@ -277,8 +277,8 @@ impl OpenVrInputSource {
} }
app.input_state.devices.sort_by(|a, b| { app.input_state.devices.sort_by(|a, b| {
(a.soc.is_none() as u8) u8::from(a.soc.is_none())
.cmp(&(b.soc.is_none() as u8)) .cmp(&u8::from(b.soc.is_none()))
.then((a.role as u8).cmp(&(b.role as u8))) .then((a.role as u8).cmp(&(b.role as u8)))
.then(a.soc.unwrap_or(999.).total_cmp(&b.soc.unwrap_or(999.))) .then(a.soc.unwrap_or(999.).total_cmp(&b.soc.unwrap_or(999.)))
}); });
@@ -332,7 +332,7 @@ pub fn set_action_manifest(input: &mut InputManager) -> anyhow::Result<()> {
if let Err(e) = File::create(&action_path) if let Err(e) = File::create(&action_path)
.and_then(|mut f| f.write_all(include_bytes!("../../res/actions.json"))) .and_then(|mut f| f.write_all(include_bytes!("../../res/actions.json")))
{ {
log::warn!("Could not write action manifest: {}", e); log::warn!("Could not write action manifest: {e}");
} }
let binding_path = config_io::get_config_root().join("actions_binding_knuckles.json"); let binding_path = config_io::get_config_root().join("actions_binding_knuckles.json");

View File

@@ -48,7 +48,7 @@ impl LinePool {
let view = ImageView::new_default(texture)?; let view = ImageView::new_default(texture)?;
Ok(LinePool { Ok(Self {
lines: IdMap::new(), lines: IdMap::new(),
view, view,
colors: [ colors: [
@@ -66,7 +66,7 @@ impl LinePool {
let mut data = OverlayData::<OpenVrOverlayData> { let mut data = OverlayData::<OpenVrOverlayData> {
state: OverlayState { state: OverlayState {
name: Arc::from(format!("wlx-line{}", id)), name: Arc::from(format!("wlx-line{id}")),
show_hide: true, show_hide: true,
..Default::default() ..Default::default()
}, },
@@ -132,15 +132,7 @@ impl LinePool {
data.state.transform = transform; data.state.transform = transform;
data.data.color = color; data.data.color = color;
} else { } else {
log::warn!("Line {} does not exist", id); log::warn!("Line {id} does not exist");
}
}
pub fn hide(&mut self, id: usize) {
if let Some(data) = self.lines.get_mut(id) {
data.state.want_visible = false;
} else {
log::warn!("Line {} does not exist", id);
} }
} }

View File

@@ -21,7 +21,7 @@ pub(super) fn install_manifest(app_mgr: &mut ApplicationsManager) -> anyhow::Res
.ok_or_else(|| anyhow::anyhow!("Invalid executable path"))?, .ok_or_else(|| anyhow::anyhow!("Invalid executable path"))?,
}; };
if let Ok(true) = app_mgr.is_application_installed(APP_KEY) { if app_mgr.is_application_installed(APP_KEY) == Ok(true) {
if let Ok(mut file) = File::open(&manifest_path) { if let Ok(mut file) = File::open(&manifest_path) {
let mut buf = String::new(); let mut buf = String::new();
if file.read_to_string(&mut buf).is_ok() { if file.read_to_string(&mut buf).is_ok() {
@@ -62,15 +62,15 @@ pub(super) fn install_manifest(app_mgr: &mut ApplicationsManager) -> anyhow::Res
manifest_path, manifest_path,
e e
); );
}; }
if let Err(e) = app_mgr.add_application_manifest(&manifest_path, false) { if let Err(e) = app_mgr.add_application_manifest(&manifest_path, false) {
bail!("Failed to add manifest to OpenVR: {}", e.description()); bail!("Failed to add manifest to OpenVR: {}", e.description());
}; }
if let Err(e) = app_mgr.set_application_auto_launch(APP_KEY, true) { if let Err(e) = app_mgr.set_application_auto_launch(APP_KEY, true) {
bail!("Failed to set auto launch: {}", e.description()); bail!("Failed to set auto launch: {}", e.description());
}; }
Ok(()) Ok(())
} }
@@ -78,10 +78,10 @@ pub(super) fn install_manifest(app_mgr: &mut ApplicationsManager) -> anyhow::Res
pub(super) fn uninstall_manifest(app_mgr: &mut ApplicationsManager) -> anyhow::Result<()> { pub(super) fn uninstall_manifest(app_mgr: &mut ApplicationsManager) -> anyhow::Result<()> {
let manifest_path = config_io::get_config_root().join("wlx-overlay-s.vrmanifest"); let manifest_path = config_io::get_config_root().join("wlx-overlay-s.vrmanifest");
if let Ok(true) = app_mgr.is_application_installed(APP_KEY) { if app_mgr.is_application_installed(APP_KEY) == Ok(true) {
if let Err(e) = app_mgr.remove_application_manifest(&manifest_path) { if let Err(e) = app_mgr.remove_application_manifest(&manifest_path) {
bail!("Failed to remove manifest from OpenVR: {}", e.description()); bail!("Failed to remove manifest from OpenVR: {}", e.description());
}; }
log::info!("Uninstalled manifest"); log::info!("Uninstalled manifest");
} }
Ok(()) Ok(())

View File

@@ -13,11 +13,7 @@ use ovr_overlay::{
sys::{ETrackedDeviceProperty, EVRApplicationType, EVREventType}, sys::{ETrackedDeviceProperty, EVRApplicationType, EVREventType},
TrackedDeviceIndex, TrackedDeviceIndex,
}; };
use vulkano::{ use vulkano::{device::physical::PhysicalDevice, Handle, VulkanObject};
device::{physical::PhysicalDevice, DeviceExtensions},
instance::InstanceExtensions,
Handle, VulkanObject,
};
use crate::{ use crate::{
backend::{ backend::{
@@ -65,6 +61,7 @@ pub fn openvr_uninstall() {
let _ = uninstall_manifest(&mut app_mgr); let _ = uninstall_manifest(&mut app_mgr);
} }
#[allow(clippy::too_many_lines, clippy::cognitive_complexity)]
pub fn openvr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(), BackendError> { pub fn openvr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(), BackendError> {
let app_type = EVRApplicationType::VRApplication_Overlay; let app_type = EVRApplicationType::VRApplication_Overlay;
let Ok(context) = ovr_overlay::Context::init(app_type) else { let Ok(context) = ovr_overlay::Context::init(app_type) else {
@@ -84,14 +81,13 @@ pub fn openvr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
let device_extensions_fn = |device: &PhysicalDevice| { let device_extensions_fn = |device: &PhysicalDevice| {
let names = compositor_mgr.get_vulkan_device_extensions_required(device.handle().as_raw()); let names = compositor_mgr.get_vulkan_device_extensions_required(device.handle().as_raw());
let ext = DeviceExtensions::from_iter(names.iter().map(|s| s.as_str())); names.iter().map(std::string::String::as_str).collect()
ext
}; };
let mut compositor_mngr = context.compositor_mngr(); let mut compositor_mgr = context.compositor_mngr();
let instance_extensions = { let instance_extensions = {
let names = compositor_mngr.get_vulkan_instance_extensions_required(); let names = compositor_mgr.get_vulkan_instance_extensions_required();
InstanceExtensions::from_iter(names.iter().map(|s| s.as_str())) names.iter().map(std::string::String::as_str).collect()
}; };
let mut state = { let mut state = {
@@ -103,7 +99,7 @@ pub fn openvr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
state.tasks.enqueue_at( state.tasks.enqueue_at(
TaskType::System(SystemTask::ShowHide), TaskType::System(SystemTask::ShowHide),
Instant::now().add(Duration::from_secs(1)), Instant::now().add(Duration::from_secs(1)),
) );
} }
if let Ok(ipd) = system_mgr.get_tracked_device_property::<f32>( if let Ok(ipd) = system_mgr.get_tracked_device_property::<f32>(
@@ -137,7 +133,7 @@ pub fn openvr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
))); )));
}; };
log::info!("HMD running @ {} Hz", refresh_rate); log::info!("HMD running @ {refresh_rate} Hz");
let watch_id = overlays.get_by_name(WATCH_NAME).unwrap().state.id; // want panic let watch_id = overlays.get_by_name(WATCH_NAME).unwrap().state.id; // want panic
@@ -188,7 +184,7 @@ pub fn openvr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
Toast::new( Toast::new(
ToastTopic::IpdChange, ToastTopic::IpdChange,
"IPD".into(), "IPD".into(),
format!("{:.1} mm", ipd).into(), format!("{ipd:.1} mm").into(),
) )
.submit(&mut state); .submit(&mut state);
} }
@@ -209,18 +205,17 @@ pub fn openvr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
state.tasks.retrieve_due(&mut due_tasks); state.tasks.retrieve_due(&mut due_tasks);
let mut removed_overlays = overlays.update(&mut state)?; let mut removed_overlays = overlays.update(&mut state)?;
for o in removed_overlays.iter_mut() { for o in &mut removed_overlays {
o.destroy(&mut overlay_mgr); o.destroy(&mut overlay_mgr);
} }
while let Some(task) = due_tasks.pop_front() { while let Some(task) = due_tasks.pop_front() {
match task { match task {
TaskType::Global(f) => f(&mut state),
TaskType::Overlay(sel, f) => { TaskType::Overlay(sel, f) => {
if let Some(o) = overlays.mut_by_selector(&sel) { if let Some(o) = overlays.mut_by_selector(&sel) {
f(&mut state, &mut o.state); f(&mut state, &mut o.state);
} else { } else {
log::warn!("Overlay not found for task: {:?}", sel); log::warn!("Overlay not found for task: {sel:?}");
} }
} }
TaskType::CreateOverlay(sel, f) => { TaskType::CreateOverlay(sel, f) => {
@@ -316,7 +311,7 @@ pub fn openvr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
&state.input_state.hmd, &state.input_state.hmd,
); );
if let Some(haptics) = haptics { if let Some(haptics) = haptics {
input_source.haptics(&mut input_mgr, idx, haptics) input_source.haptics(&mut input_mgr, idx, haptics);
} }
} }
@@ -332,13 +327,13 @@ pub fn openvr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
#[cfg(feature = "osc")] #[cfg(feature = "osc")]
if let Some(ref mut sender) = state.osc_sender { if let Some(ref mut sender) = state.osc_sender {
let _ = sender.send_params(&overlays, &state.input_state.devices); let _ = sender.send_params(&overlays, &state.input_state.devices);
}; }
#[cfg(feature = "wayvr")] #[cfg(feature = "wayvr")]
if let Err(e) = if let Err(e) =
crate::overlays::wayvr::tick_events::<OpenVrOverlayData>(&mut state, &mut overlays) crate::overlays::wayvr::tick_events::<OpenVrOverlayData>(&mut state, &mut overlays)
{ {
log::error!("WayVR tick_events failed: {:?}", e); log::error!("WayVR tick_events failed: {e:?}");
} }
log::trace!("Rendering frame"); log::trace!("Rendering frame");
@@ -365,7 +360,7 @@ pub fn openvr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
if let Some(mut future) = buffers.execute_now(state.graphics.queue.clone())? { if let Some(mut future) = buffers.execute_now(state.graphics.queue.clone())? {
if let Err(e) = future.flush() { if let Err(e) = future.flush() {
return Err(BackendError::Fatal(e.into())); return Err(BackendError::Fatal(e.into()));
}; }
future.cleanup_finished(); future.cleanup_finished();
} }

View File

@@ -9,11 +9,7 @@ use ovr_overlay::{
}; };
use vulkano::{image::view::ImageView, Handle, VulkanObject}; use vulkano::{image::view::ImageView, Handle, VulkanObject};
use crate::{ use crate::{backend::overlay::OverlayData, graphics::WlxGraphics, state::AppState};
backend::overlay::{OverlayData, RelativeTo},
graphics::WlxGraphics,
state::AppState,
};
use super::helpers::Affine3AConvert; use super::helpers::Affine3AConvert;
@@ -24,7 +20,6 @@ pub(super) struct OpenVrOverlayData {
pub(super) color: Vec4, pub(super) color: Vec4,
pub(crate) width: f32, pub(crate) width: f32,
pub(super) override_width: bool, pub(super) override_width: bool,
pub(super) relative_to: RelativeTo,
pub(super) image_view: Option<Arc<ImageView>>, pub(super) image_view: Option<Arc<ImageView>>,
pub(super) image_dirty: bool, pub(super) image_dirty: bool,
} }
@@ -40,7 +35,7 @@ impl OverlayData<OpenVrOverlayData> {
let handle = match overlay.create_overlay(&key, &key) { let handle = match overlay.create_overlay(&key, &key) {
Ok(handle) => handle, Ok(handle) => handle,
Err(e) => { Err(e) => {
panic!("Failed to create overlay: {}", e); panic!("Failed to create overlay: {e}");
} }
}; };
log::debug!("{}: initialize", self.state.name); log::debug!("{}: initialize", self.state.name);

View File

@@ -25,7 +25,7 @@ pub(super) struct PlayspaceMover {
} }
impl PlayspaceMover { impl PlayspaceMover {
pub fn new() -> Self { pub const fn new() -> Self {
Self { Self {
universe: ETrackingUniverseOrigin::TrackingUniverseRawAndUncalibrated, universe: ETrackingUniverseOrigin::TrackingUniverseRawAndUncalibrated,
drag: None, drag: None,
@@ -33,6 +33,7 @@ impl PlayspaceMover {
} }
} }
#[allow(clippy::too_many_lines, clippy::cognitive_complexity)]
pub fn update( pub fn update(
&mut self, &mut self,
chaperone_mgr: &mut ChaperoneSetupManager, chaperone_mgr: &mut ChaperoneSetupManager,
@@ -54,8 +55,8 @@ impl PlayspaceMover {
let dq = new_hand * data.hand_pose.conjugate(); let dq = new_hand * data.hand_pose.conjugate();
let rel_y = f32::atan2( let rel_y = f32::atan2(
2.0 * (dq.y * dq.w + dq.x * dq.z), 2.0 * dq.y.mul_add(dq.w, dq.x * dq.z),
(2.0 * (dq.w * dq.w + dq.x * dq.x)) - 1.0, 2.0f32.mul_add(dq.w.mul_add(dq.w, dq.x * dq.x), -1.0),
); );
let mut space_transform = Affine3A::from_rotation_y(rel_y); let mut space_transform = Affine3A::from_rotation_y(rel_y);
@@ -241,7 +242,7 @@ impl PlayspaceMover {
} }
} }
fn universe_str(universe: &ETrackingUniverseOrigin) -> &'static str { const fn universe_str(universe: &ETrackingUniverseOrigin) -> &'static str {
match universe { match universe {
ETrackingUniverseOrigin::TrackingUniverseSeated => "Seated", ETrackingUniverseOrigin::TrackingUniverseSeated => "Seated",
ETrackingUniverseOrigin::TrackingUniverseStanding => "Standing", ETrackingUniverseOrigin::TrackingUniverseStanding => "Standing",
@@ -271,31 +272,31 @@ fn set_working_copy(
let mat = HmdMatrix34_t::from_affine(mat); let mat = HmdMatrix34_t::from_affine(mat);
match universe { match universe {
ETrackingUniverseOrigin::TrackingUniverseStanding => { ETrackingUniverseOrigin::TrackingUniverseStanding => {
chaperone_mgr.set_working_standing_zero_pose_to_raw_tracking_pose(&mat) chaperone_mgr.set_working_standing_zero_pose_to_raw_tracking_pose(&mat);
} }
_ => chaperone_mgr.set_working_seated_zero_pose_to_raw_tracking_pose(&mat), _ => chaperone_mgr.set_working_seated_zero_pose_to_raw_tracking_pose(&mat),
}; }
} }
fn apply_chaperone_offset(offset: Vec3A, chaperone_mgr: &mut ChaperoneSetupManager) { fn apply_chaperone_offset(offset: Vec3A, chaperone_mgr: &mut ChaperoneSetupManager) {
let mut quads = chaperone_mgr.get_live_collision_bounds_info(); let mut quads = chaperone_mgr.get_live_collision_bounds_info();
quads.iter_mut().for_each(|quad| { for quad in &mut quads {
quad.vCorners.iter_mut().for_each(|corner| { quad.vCorners.iter_mut().for_each(|corner| {
corner.v[0] += offset.x; corner.v[0] += offset.x;
corner.v[2] += offset.z; corner.v[2] += offset.z;
}); });
}); }
chaperone_mgr.set_working_collision_bounds_info(quads.as_mut_slice()); chaperone_mgr.set_working_collision_bounds_info(quads.as_mut_slice());
} }
fn apply_chaperone_transform(transform: Affine3A, chaperone_mgr: &mut ChaperoneSetupManager) { fn apply_chaperone_transform(transform: Affine3A, chaperone_mgr: &mut ChaperoneSetupManager) {
let mut quads = chaperone_mgr.get_live_collision_bounds_info(); let mut quads = chaperone_mgr.get_live_collision_bounds_info();
quads.iter_mut().for_each(|quad| { for quad in &mut quads {
quad.vCorners.iter_mut().for_each(|corner| { quad.vCorners.iter_mut().for_each(|corner| {
let coord = transform.transform_point3a(Vec3A::from_slice(&corner.v)); let coord = transform.transform_point3a(Vec3A::from_slice(&corner.v));
corner.v[0] = coord.x; corner.v[0] = coord.x;
corner.v[2] = coord.z; corner.v[2] = coord.z;
}); });
}); }
chaperone_mgr.set_working_collision_bounds_info(quads.as_mut_slice()); chaperone_mgr.set_working_collision_bounds_info(quads.as_mut_slice());
} }

View File

@@ -1,6 +1,6 @@
use anyhow::{bail, ensure}; use anyhow::{bail, ensure};
use glam::{Affine3A, Quat, Vec3, Vec3A}; use glam::{Affine3A, Quat, Vec3, Vec3A};
use openxr as xr; use openxr::{self as xr, SessionCreateFlags};
use xr::OverlaySessionCreateFlagsEXTX; use xr::OverlaySessionCreateFlagsEXTX;
pub(super) fn init_xr() -> Result<(xr::Instance, xr::SystemId), anyhow::Error> { pub(super) fn init_xr() -> Result<(xr::Instance, xr::SystemId), anyhow::Error> {
@@ -110,7 +110,7 @@ pub(super) unsafe fn create_overlay_session(
}; };
let binding = xr::sys::GraphicsBindingVulkanKHR { let binding = xr::sys::GraphicsBindingVulkanKHR {
ty: xr::sys::GraphicsBindingVulkanKHR::TYPE, ty: xr::sys::GraphicsBindingVulkanKHR::TYPE,
next: &overlay as *const _ as *const _, next: (&raw const overlay).cast(),
instance: info.instance, instance: info.instance,
physical_device: info.physical_device, physical_device: info.physical_device,
device: info.device, device: info.device,
@@ -119,8 +119,8 @@ pub(super) unsafe fn create_overlay_session(
}; };
let info = xr::sys::SessionCreateInfo { let info = xr::sys::SessionCreateInfo {
ty: xr::sys::SessionCreateInfo::TYPE, ty: xr::sys::SessionCreateInfo::TYPE,
next: &binding as *const _ as *const _, next: (&raw const binding).cast(),
create_flags: Default::default(), create_flags: SessionCreateFlags::default(),
system_id: system, system_id: system,
}; };
let mut out = xr::sys::Session::NULL; let mut out = xr::sys::Session::NULL;

View File

@@ -17,16 +17,12 @@ use crate::{
use super::{helpers::posef_to_transform, XrState}; use super::{helpers::posef_to_transform, XrState};
type XrSession = xr::Session<xr::Vulkan>;
static CLICK_TIMES: [Duration; 3] = [ static CLICK_TIMES: [Duration; 3] = [
Duration::ZERO, Duration::ZERO,
Duration::from_millis(500), Duration::from_millis(500),
Duration::from_millis(750), Duration::from_millis(750),
]; ];
pub(super) struct OpenXrAction {}
pub(super) struct OpenXrInputSource { pub(super) struct OpenXrInputSource {
action_set: xr::ActionSet, action_set: xr::ActionSet,
hands: [OpenXrHand; 2], hands: [OpenXrHand; 2],
@@ -48,7 +44,7 @@ pub struct MultiClickHandler<const COUNT: usize> {
impl<const COUNT: usize> MultiClickHandler<COUNT> { impl<const COUNT: usize> MultiClickHandler<COUNT> {
fn new(action_set: &xr::ActionSet, action_name: &str, side: &str) -> anyhow::Result<Self> { fn new(action_set: &xr::ActionSet, action_name: &str, side: &str) -> anyhow::Result<Self> {
let name = format!("{}_{}-{}", side, COUNT, action_name); let name = format!("{side}_{COUNT}-{action_name}");
let name_f32 = format!("{}_value", &name); let name_f32 = format!("{}_value", &name);
let action_bool = action_set.create_action::<bool>(&name, &name, &[])?; let action_bool = action_set.create_action::<bool>(&name, &name, &[])?;
@@ -97,10 +93,10 @@ impl<const COUNT: usize> MultiClickHandler<COUNT> {
self.held_inactive = false; self.held_inactive = false;
// reset to no prior clicks // reset to no prior clicks
let long_ago = Instant::now() - Duration::from_secs(10); let long_ago = Instant::now().checked_sub(Duration::from_secs(10)).unwrap();
self.previous self.previous
.iter_mut() .iter_mut()
.for_each(|instant| *instant = long_ago) .for_each(|instant| *instant = long_ago);
} else if COUNT > 0 { } else if COUNT > 0 {
log::trace!("{}: rotate", self.name); log::trace!("{}: rotate", self.name);
self.previous.rotate_right(1); self.previous.rotate_right(1);
@@ -149,20 +145,20 @@ impl CustomClickAction {
} }
pub(super) struct OpenXrHandSource { pub(super) struct OpenXrHandSource {
action_pose: xr::Action<xr::Posef>, pose: xr::Action<xr::Posef>,
action_click: CustomClickAction, click: CustomClickAction,
action_grab: CustomClickAction, grab: CustomClickAction,
action_alt_click: CustomClickAction, alt_click: CustomClickAction,
action_show_hide: CustomClickAction, show_hide: CustomClickAction,
action_toggle_dashboard: CustomClickAction, toggle_dashboard: CustomClickAction,
action_space_drag: CustomClickAction, space_drag: CustomClickAction,
action_space_rotate: CustomClickAction, space_rotate: CustomClickAction,
action_space_reset: CustomClickAction, space_reset: CustomClickAction,
action_modifier_right: CustomClickAction, modifier_right: CustomClickAction,
action_modifier_middle: CustomClickAction, modifier_middle: CustomClickAction,
action_move_mouse: CustomClickAction, move_mouse: CustomClickAction,
action_scroll: xr::Action<Vector2f>, scroll: xr::Action<Vector2f>,
action_haptics: xr::Action<xr::Haptic>, haptics: xr::Action<xr::Haptic>,
} }
impl OpenXrInputSource { impl OpenXrInputSource {
@@ -175,7 +171,7 @@ impl OpenXrInputSource {
let left_source = OpenXrHandSource::new(&mut action_set, "left")?; let left_source = OpenXrHandSource::new(&mut action_set, "left")?;
let right_source = OpenXrHandSource::new(&mut action_set, "right")?; let right_source = OpenXrHandSource::new(&mut action_set, "right")?;
suggest_bindings(&xr.instance, &[&left_source, &right_source])?; suggest_bindings(&xr.instance, &[&left_source, &right_source]);
xr.session.attach_action_sets(&[&action_set])?; xr.session.attach_action_sets(&[&action_set])?;
@@ -189,9 +185,9 @@ impl OpenXrInputSource {
} }
pub fn haptics(&self, xr: &XrState, hand: usize, haptics: &Haptics) { pub fn haptics(&self, xr: &XrState, hand: usize, haptics: &Haptics) {
let action = &self.hands[hand].source.action_haptics; let action = &self.hands[hand].source.haptics;
let duration_nanos = (haptics.duration as f64) * 1_000_000_000.0; let duration_nanos = f64::from(haptics.duration) * 1_000_000_000.0;
let _ = action.apply_feedback( let _ = action.apply_feedback(
&xr.session, &xr.session,
@@ -251,7 +247,7 @@ impl OpenXrInputSource {
} }
} }
pub fn update_devices(&mut self, app: &mut AppState, monado: &mut mnd::Monado) { pub fn update_devices(app: &mut AppState, monado: &mut mnd::Monado) {
app.input_state.devices.clear(); app.input_state.devices.clear();
let roles = [ let roles = [
@@ -293,8 +289,8 @@ impl OpenXrInputSource {
} }
app.input_state.devices.sort_by(|a, b| { app.input_state.devices.sort_by(|a, b| {
(a.soc.is_none() as u8) u8::from(a.soc.is_none())
.cmp(&(b.soc.is_none() as u8)) .cmp(&u8::from(b.soc.is_none()))
.then((a.role as u8).cmp(&(b.role as u8))) .then((a.role as u8).cmp(&(b.role as u8)))
.then(a.soc.unwrap_or(999.).total_cmp(&b.soc.unwrap_or(999.))) .then(a.soc.unwrap_or(999.).total_cmp(&b.soc.unwrap_or(999.)))
}); });
@@ -303,11 +299,10 @@ impl OpenXrInputSource {
impl OpenXrHand { impl OpenXrHand {
pub(super) fn new(xr: &XrState, source: OpenXrHandSource) -> Result<Self, xr::sys::Result> { pub(super) fn new(xr: &XrState, source: OpenXrHandSource) -> Result<Self, xr::sys::Result> {
let space = source.action_pose.create_space( let space =
xr.session.clone(), source
xr::Path::NULL, .pose
xr::Posef::IDENTITY, .create_space(xr.session.clone(), xr::Path::NULL, xr::Posef::IDENTITY)?;
)?;
Ok(Self { source, space }) Ok(Self { source, space })
} }
@@ -340,19 +335,13 @@ impl OpenXrHand {
); );
} }
pointer.now.click = self pointer.now.click = self.source.click.state(pointer.before.click, xr, session)?;
.source
.action_click
.state(pointer.before.click, xr, session)?;
pointer.now.grab = self pointer.now.grab = self.source.grab.state(pointer.before.grab, xr, session)?;
.source
.action_grab
.state(pointer.before.grab, xr, session)?;
let scroll = self let scroll = self
.source .source
.action_scroll .scroll
.state(&xr.session, xr::Path::NULL)? .state(&xr.session, xr::Path::NULL)?
.current_state; .current_state;
@@ -361,50 +350,47 @@ impl OpenXrHand {
pointer.now.alt_click = pointer.now.alt_click =
self.source self.source
.action_alt_click .alt_click
.state(pointer.before.alt_click, xr, session)?; .state(pointer.before.alt_click, xr, session)?;
pointer.now.show_hide = pointer.now.show_hide =
self.source self.source
.action_show_hide .show_hide
.state(pointer.before.show_hide, xr, session)?; .state(pointer.before.show_hide, xr, session)?;
pointer.now.click_modifier_right = self.source.action_modifier_right.state( pointer.now.click_modifier_right =
pointer.before.click_modifier_right, self.source
xr, .modifier_right
session, .state(pointer.before.click_modifier_right, xr, session)?;
)?;
pointer.now.toggle_dashboard = self.source.action_toggle_dashboard.state( pointer.now.toggle_dashboard =
pointer.before.toggle_dashboard, self.source
xr, .toggle_dashboard
session, .state(pointer.before.toggle_dashboard, xr, session)?;
)?;
pointer.now.click_modifier_middle = self.source.action_modifier_middle.state( pointer.now.click_modifier_middle =
pointer.before.click_modifier_middle, self.source
xr, .modifier_middle
session, .state(pointer.before.click_modifier_middle, xr, session)?;
)?;
pointer.now.move_mouse = pointer.now.move_mouse =
self.source self.source
.action_move_mouse .move_mouse
.state(pointer.before.move_mouse, xr, session)?; .state(pointer.before.move_mouse, xr, session)?;
pointer.now.space_drag = pointer.now.space_drag =
self.source self.source
.action_space_drag .space_drag
.state(pointer.before.space_drag, xr, session)?; .state(pointer.before.space_drag, xr, session)?;
pointer.now.space_rotate = pointer.now.space_rotate =
self.source self.source
.action_space_rotate .space_rotate
.state(pointer.before.space_rotate, xr, session)?; .state(pointer.before.space_rotate, xr, session)?;
pointer.now.space_reset = pointer.now.space_reset =
self.source self.source
.action_space_reset .space_reset
.state(pointer.before.space_reset, xr, session)?; .state(pointer.before.space_reset, xr, session)?;
Ok(()) Ok(())
@@ -415,76 +401,66 @@ impl OpenXrHand {
impl OpenXrHandSource { impl OpenXrHandSource {
pub(super) fn new(action_set: &mut xr::ActionSet, side: &str) -> anyhow::Result<Self> { pub(super) fn new(action_set: &mut xr::ActionSet, side: &str) -> anyhow::Result<Self> {
let action_pose = action_set.create_action::<xr::Posef>( let action_pose = action_set.create_action::<xr::Posef>(
&format!("{}_hand", side), &format!("{side}_hand"),
&format!("{} hand pose", side), &format!("{side} hand pose"),
&[], &[],
)?; )?;
let action_scroll = action_set.create_action::<Vector2f>( let action_scroll = action_set.create_action::<Vector2f>(
&format!("{}_scroll", side), &format!("{side}_scroll"),
&format!("{} hand scroll", side), &format!("{side} hand scroll"),
&[], &[],
)?; )?;
let action_haptics = action_set.create_action::<xr::Haptic>( let action_haptics = action_set.create_action::<xr::Haptic>(
&format!("{}_haptics", side), &format!("{side}_haptics"),
&format!("{} hand haptics", side), &format!("{side} hand haptics"),
&[], &[],
)?; )?;
Ok(Self { Ok(Self {
action_pose, pose: action_pose,
action_click: CustomClickAction::new(action_set, "click", side)?, click: CustomClickAction::new(action_set, "click", side)?,
action_grab: CustomClickAction::new(action_set, "grab", side)?, grab: CustomClickAction::new(action_set, "grab", side)?,
action_scroll, scroll: action_scroll,
action_alt_click: CustomClickAction::new(action_set, "alt_click", side)?, alt_click: CustomClickAction::new(action_set, "alt_click", side)?,
action_show_hide: CustomClickAction::new(action_set, "show_hide", side)?, show_hide: CustomClickAction::new(action_set, "show_hide", side)?,
action_toggle_dashboard: CustomClickAction::new(action_set, "toggle_dashboard", side)?, toggle_dashboard: CustomClickAction::new(action_set, "toggle_dashboard", side)?,
action_space_drag: CustomClickAction::new(action_set, "space_drag", side)?, space_drag: CustomClickAction::new(action_set, "space_drag", side)?,
action_space_rotate: CustomClickAction::new(action_set, "space_rotate", side)?, space_rotate: CustomClickAction::new(action_set, "space_rotate", side)?,
action_space_reset: CustomClickAction::new(action_set, "space_reset", side)?, space_reset: CustomClickAction::new(action_set, "space_reset", side)?,
action_modifier_right: CustomClickAction::new( modifier_right: CustomClickAction::new(action_set, "click_modifier_right", side)?,
action_set, modifier_middle: CustomClickAction::new(action_set, "click_modifier_middle", side)?,
"click_modifier_right", move_mouse: CustomClickAction::new(action_set, "move_mouse", side)?,
side, haptics: action_haptics,
)?,
action_modifier_middle: CustomClickAction::new(
action_set,
"click_modifier_middle",
side,
)?,
action_move_mouse: CustomClickAction::new(action_set, "move_mouse", side)?,
action_haptics,
}) })
} }
} }
fn to_path(maybe_path_str: &Option<String>, instance: &xr::Instance) -> Option<xr::Path> { fn to_path(maybe_path_str: Option<&String>, instance: &xr::Instance) -> Option<xr::Path> {
maybe_path_str maybe_path_str.as_ref().and_then(|s| {
.as_ref() instance
.and_then(|s| match instance.string_to_path(s) { .string_to_path(s)
Ok(path) => Some(path), .inspect_err(|_| {
Err(_) => { log::warn!("Invalid binding path: {s}");
log::warn!("Invalid binding path: {}", s); })
None .ok()
} })
})
} }
fn is_bool(maybe_type_str: &Option<String>) -> bool { fn is_bool(maybe_type_str: Option<&String>) -> bool {
maybe_type_str maybe_type_str
.as_ref() .as_ref()
.unwrap() // want panic .unwrap() // want panic
.split('/') .split('/')
.next_back() .next_back()
.map(|last| matches!(last, "click" | "touch")) .is_some_and(|last| matches!(last, "click" | "touch"))
.unwrap_or(false)
} }
macro_rules! add_custom { macro_rules! add_custom {
($action:expr, $left:expr, $right:expr, $bindings:expr, $instance:expr) => { ($action:expr, $left:expr, $right:expr, $bindings:expr, $instance:expr) => {
if let Some(action) = $action.as_ref() { if let Some(action) = $action.as_ref() {
if let Some(p) = to_path(&action.left, $instance) { if let Some(p) = to_path(action.left.as_ref(), $instance) {
if is_bool(&action.left) { if is_bool(action.left.as_ref()) {
if action.triple_click.unwrap_or(false) { if action.triple_click.unwrap_or(false) {
$bindings.push(xr::Binding::new(&$left.triple.action_bool, p)); $bindings.push(xr::Binding::new(&$left.triple.action_bool, p));
} else if action.double_click.unwrap_or(false) { } else if action.double_click.unwrap_or(false) {
@@ -502,8 +478,8 @@ macro_rules! add_custom {
} }
} }
} }
if let Some(p) = to_path(&action.right, $instance) { if let Some(p) = to_path(action.right.as_ref(), $instance) {
if is_bool(&action.right) { if is_bool(action.right.as_ref()) {
if action.triple_click.unwrap_or(false) { if action.triple_click.unwrap_or(false) {
$bindings.push(xr::Binding::new(&$right.triple.action_bool, p)); $bindings.push(xr::Binding::new(&$right.triple.action_bool, p));
} else if action.double_click.unwrap_or(false) { } else if action.double_click.unwrap_or(false) {
@@ -525,8 +501,9 @@ macro_rules! add_custom {
}; };
} }
fn suggest_bindings(instance: &xr::Instance, hands: &[&OpenXrHandSource; 2]) -> anyhow::Result<()> { #[allow(clippy::too_many_lines, clippy::cognitive_complexity)]
let profiles = load_action_profiles()?; fn suggest_bindings(instance: &xr::Instance, hands: &[&OpenXrHandSource; 2]) {
let profiles = load_action_profiles();
for profile in profiles { for profile in profiles {
let Ok(profile_path) = instance.string_to_path(&profile.profile) else { let Ok(profile_path) = instance.string_to_path(&profile.profile) else {
@@ -537,116 +514,116 @@ fn suggest_bindings(instance: &xr::Instance, hands: &[&OpenXrHandSource; 2]) ->
let mut bindings: Vec<xr::Binding> = vec![]; let mut bindings: Vec<xr::Binding> = vec![];
if let Some(action) = profile.pose { if let Some(action) = profile.pose {
if let Some(p) = to_path(&action.left, instance) { if let Some(p) = to_path(action.left.as_ref(), instance) {
bindings.push(xr::Binding::new(&hands[0].action_pose, p)); bindings.push(xr::Binding::new(&hands[0].pose, p));
} }
if let Some(p) = to_path(&action.right, instance) { if let Some(p) = to_path(action.right.as_ref(), instance) {
bindings.push(xr::Binding::new(&hands[1].action_pose, p)); bindings.push(xr::Binding::new(&hands[1].pose, p));
} }
} }
if let Some(action) = profile.haptic { if let Some(action) = profile.haptic {
if let Some(p) = to_path(&action.left, instance) { if let Some(p) = to_path(action.left.as_ref(), instance) {
bindings.push(xr::Binding::new(&hands[0].action_haptics, p)); bindings.push(xr::Binding::new(&hands[0].haptics, p));
} }
if let Some(p) = to_path(&action.right, instance) { if let Some(p) = to_path(action.right.as_ref(), instance) {
bindings.push(xr::Binding::new(&hands[1].action_haptics, p)); bindings.push(xr::Binding::new(&hands[1].haptics, p));
} }
} }
if let Some(action) = profile.scroll { if let Some(action) = profile.scroll {
if let Some(p) = to_path(&action.left, instance) { if let Some(p) = to_path(action.left.as_ref(), instance) {
bindings.push(xr::Binding::new(&hands[0].action_scroll, p)); bindings.push(xr::Binding::new(&hands[0].scroll, p));
} }
if let Some(p) = to_path(&action.right, instance) { if let Some(p) = to_path(action.right.as_ref(), instance) {
bindings.push(xr::Binding::new(&hands[1].action_scroll, p)); bindings.push(xr::Binding::new(&hands[1].scroll, p));
} }
} }
add_custom!( add_custom!(
profile.click, profile.click,
hands[0].action_click, hands[0].click,
hands[1].action_click, hands[1].click,
bindings, bindings,
instance instance
); );
add_custom!( add_custom!(
profile.alt_click, profile.alt_click,
&hands[0].action_alt_click, &hands[0].alt_click,
&hands[1].action_alt_click, &hands[1].alt_click,
bindings, bindings,
instance instance
); );
add_custom!( add_custom!(
profile.grab, profile.grab,
&hands[0].action_grab, &hands[0].grab,
&hands[1].action_grab, &hands[1].grab,
bindings, bindings,
instance instance
); );
add_custom!( add_custom!(
profile.show_hide, profile.show_hide,
&hands[0].action_show_hide, &hands[0].show_hide,
&hands[1].action_show_hide, &hands[1].show_hide,
bindings, bindings,
instance instance
); );
add_custom!( add_custom!(
profile.toggle_dashboard, profile.toggle_dashboard,
&hands[0].action_toggle_dashboard, &hands[0].toggle_dashboard,
&hands[1].action_toggle_dashboard, &hands[1].toggle_dashboard,
bindings, bindings,
instance instance
); );
add_custom!( add_custom!(
profile.space_drag, profile.space_drag,
&hands[0].action_space_drag, &hands[0].space_drag,
&hands[1].action_space_drag, &hands[1].space_drag,
bindings, bindings,
instance instance
); );
add_custom!( add_custom!(
profile.space_rotate, profile.space_rotate,
&hands[0].action_space_rotate, &hands[0].space_rotate,
&hands[1].action_space_rotate, &hands[1].space_rotate,
bindings, bindings,
instance instance
); );
add_custom!( add_custom!(
profile.space_reset, profile.space_reset,
&hands[0].action_space_reset, &hands[0].space_reset,
&hands[1].action_space_reset, &hands[1].space_reset,
bindings, bindings,
instance instance
); );
add_custom!( add_custom!(
profile.click_modifier_right, profile.click_modifier_right,
&hands[0].action_modifier_right, &hands[0].modifier_right,
&hands[1].action_modifier_right, &hands[1].modifier_right,
bindings, bindings,
instance instance
); );
add_custom!( add_custom!(
profile.click_modifier_middle, profile.click_modifier_middle,
&hands[0].action_modifier_middle, &hands[0].modifier_middle,
&hands[1].action_modifier_middle, &hands[1].modifier_middle,
bindings, bindings,
instance instance
); );
add_custom!( add_custom!(
profile.move_mouse, profile.move_mouse,
&hands[0].action_move_mouse, &hands[0].move_mouse,
&hands[1].action_move_mouse, &hands[1].move_mouse,
bindings, bindings,
instance instance
); );
@@ -659,8 +636,6 @@ fn suggest_bindings(instance: &xr::Instance, hands: &[&OpenXrHandSource; 2]) ->
log::error!("Verify config: ~/.config/wlxoverlay/openxr_actions.json5"); log::error!("Verify config: ~/.config/wlxoverlay/openxr_actions.json5");
} }
} }
Ok(())
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
@@ -693,26 +668,26 @@ struct OpenXrActionConfProfile {
const DEFAULT_PROFILES: &str = include_str!("openxr_actions.json5"); const DEFAULT_PROFILES: &str = include_str!("openxr_actions.json5");
fn load_action_profiles() -> anyhow::Result<Vec<OpenXrActionConfProfile>> { fn load_action_profiles() -> Vec<OpenXrActionConfProfile> {
let mut profiles: Vec<OpenXrActionConfProfile> = let mut profiles: Vec<OpenXrActionConfProfile> =
serde_json5::from_str(DEFAULT_PROFILES).unwrap(); // want panic serde_json5::from_str(DEFAULT_PROFILES).unwrap(); // want panic
let Some(conf) = config_io::load("openxr_actions.json5") else { let Some(conf) = config_io::load("openxr_actions.json5") else {
return Ok(profiles); return profiles;
}; };
match serde_json5::from_str::<Vec<OpenXrActionConfProfile>>(&conf) { match serde_json5::from_str::<Vec<OpenXrActionConfProfile>>(&conf) {
Ok(override_profiles) => { Ok(override_profiles) => {
override_profiles.into_iter().for_each(|new| { for new in override_profiles {
if let Some(i) = profiles.iter().position(|old| old.profile == new.profile) { if let Some(i) = profiles.iter().position(|old| old.profile == new.profile) {
profiles[i] = new; profiles[i] = new;
} }
}); }
} }
Err(e) => { Err(e) => {
log::error!("Failed to load openxr_actions.json5: {}", e); log::error!("Failed to load openxr_actions.json5: {e}");
} }
} }
Ok(profiles) profiles
} }

View File

@@ -53,7 +53,7 @@ impl LinePool {
None, None,
)?; )?;
Ok(LinePool { Ok(Self {
lines: IdMap::new(), lines: IdMap::new(),
pipeline, pipeline,
}) })
@@ -92,7 +92,7 @@ impl LinePool {
debug_assert!(color < COLORS.len()); debug_assert!(color < COLORS.len());
let Some(line) = self.lines.get_mut(id) else { let Some(line) = self.lines.get_mut(id) else {
log::warn!("Line {} not found", id); log::warn!("Line {id} not found");
return; return;
}; };
@@ -184,14 +184,6 @@ impl LinePool {
Ok(quads) Ok(quads)
} }
/// the number of lines that are waiting to be drawn
pub(super) fn num_pending(&self) -> usize {
self.lines
.values()
.filter(|l| l.maybe_line.is_some())
.count()
}
} }
pub(super) struct Line { pub(super) struct Line {

View File

@@ -9,6 +9,7 @@ use std::{
}; };
use glam::{Affine3A, Vec3}; use glam::{Affine3A, Vec3};
use input::OpenXrInputSource;
use libmonado::Monado; use libmonado::Monado;
use openxr as xr; use openxr as xr;
use skybox::create_skybox; use skybox::create_skybox;
@@ -43,30 +44,28 @@ mod skybox;
mod swapchain; mod swapchain;
const VIEW_TYPE: xr::ViewConfigurationType = xr::ViewConfigurationType::PRIMARY_STEREO; const VIEW_TYPE: xr::ViewConfigurationType = xr::ViewConfigurationType::PRIMARY_STEREO;
const VIEW_COUNT: u32 = 2;
static FRAME_COUNTER: AtomicUsize = AtomicUsize::new(0); static FRAME_COUNTER: AtomicUsize = AtomicUsize::new(0);
struct XrState { struct XrState {
instance: xr::Instance, instance: xr::Instance,
system: xr::SystemId,
session: xr::Session<xr::Vulkan>, session: xr::Session<xr::Vulkan>,
predicted_display_time: xr::Time, predicted_display_time: xr::Time,
fps: f32, fps: f32,
stage: Arc<xr::Space>, stage: Arc<xr::Space>,
view: Arc<xr::Space>, view: Arc<xr::Space>,
stage_offset: Affine3A,
} }
#[allow(clippy::too_many_lines, clippy::cognitive_complexity)]
pub fn openxr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(), BackendError> { pub fn openxr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(), BackendError> {
let (xr_instance, system) = match helpers::init_xr() { let (xr_instance, system) = match helpers::init_xr() {
Ok((xr_instance, system)) => (xr_instance, system), Ok((xr_instance, system)) => (xr_instance, system),
Err(e) => { Err(e) => {
log::warn!("Will not use OpenXR: {}", e); log::warn!("Will not use OpenXR: {e}");
return Err(BackendError::NotSupported); return Err(BackendError::NotSupported);
} }
}; };
let mut app_state = { let mut app = {
let graphics = WlxGraphics::new_openxr(xr_instance.clone(), system)?; let graphics = WlxGraphics::new_openxr(xr_instance.clone(), system)?;
AppState::from_graphics(graphics)? AppState::from_graphics(graphics)?
}; };
@@ -74,24 +73,24 @@ pub fn openxr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
let environment_blend_mode = { let environment_blend_mode = {
let modes = xr_instance.enumerate_environment_blend_modes(system, VIEW_TYPE)?; let modes = xr_instance.enumerate_environment_blend_modes(system, VIEW_TYPE)?;
if modes.contains(&xr::EnvironmentBlendMode::ALPHA_BLEND) if modes.contains(&xr::EnvironmentBlendMode::ALPHA_BLEND)
&& app_state.session.config.use_passthrough && app.session.config.use_passthrough
{ {
xr::EnvironmentBlendMode::ALPHA_BLEND xr::EnvironmentBlendMode::ALPHA_BLEND
} else { } else {
modes[0] modes[0]
} }
}; };
log::info!("Using environment blend mode: {:?}", environment_blend_mode); log::info!("Using environment blend mode: {environment_blend_mode:?}");
if show_by_default { if show_by_default {
app_state.tasks.enqueue_at( app.tasks.enqueue_at(
TaskType::System(SystemTask::ShowHide), TaskType::System(SystemTask::ShowHide),
Instant::now().add(Duration::from_secs(1)), Instant::now().add(Duration::from_secs(1)),
) );
} }
let mut overlays = OverlayContainer::<OpenXrOverlayData>::new(&mut app_state)?; let mut overlays = OverlayContainer::<OpenXrOverlayData>::new(&mut app)?;
let mut lines = LinePool::new(app_state.graphics.clone())?; let mut lines = LinePool::new(app.graphics.clone())?;
let mut notifications = NotificationManager::new(); let mut notifications = NotificationManager::new();
notifications.run_dbus(); notifications.run_dbus();
@@ -100,12 +99,12 @@ pub fn openxr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
let mut delete_queue = vec![]; let mut delete_queue = vec![];
let mut monado = Monado::auto_connect() let mut monado = Monado::auto_connect()
.map_err(|e| log::warn!("Will not use libmonado: {}", e)) .map_err(|e| log::warn!("Will not use libmonado: {e}"))
.ok(); .ok();
let mut playspace = monado.as_mut().and_then(|m| { let mut playspace = monado.as_mut().and_then(|m| {
playspace::PlayspaceMover::new(m) playspace::PlayspaceMover::new(m)
.map_err(|e| log::warn!("Will not use Monado playspace mover: {}", e)) .map_err(|e| log::warn!("Will not use Monado playspace mover: {e}"))
.ok() .ok()
}); });
@@ -114,15 +113,10 @@ pub fn openxr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
&xr_instance, &xr_instance,
system, system,
&xr::vulkan::SessionCreateInfo { &xr::vulkan::SessionCreateInfo {
instance: app_state.graphics.instance.handle().as_raw() as _, instance: app.graphics.instance.handle().as_raw() as _,
physical_device: app_state physical_device: app.graphics.device.physical_device().handle().as_raw() as _,
.graphics device: app.graphics.device.handle().as_raw() as _,
.device queue_family_index: app.graphics.queue.queue_family_index(),
.physical_device()
.handle()
.as_raw() as _,
device: app_state.graphics.device.handle().as_raw() as _,
queue_family_index: app_state.graphics.queue.queue_family_index(),
queue_index: 0, queue_index: 0,
}, },
)?; )?;
@@ -136,24 +130,22 @@ pub fn openxr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
let mut xr_state = XrState { let mut xr_state = XrState {
instance: xr_instance, instance: xr_instance,
system,
session, session,
predicted_display_time: xr::Time::from_nanos(0), predicted_display_time: xr::Time::from_nanos(0),
fps: 30.0, fps: 30.0,
stage: Arc::new(stage), stage: Arc::new(stage),
view: Arc::new(view), view: Arc::new(view),
stage_offset: Affine3A::IDENTITY,
}; };
let mut skybox = if environment_blend_mode == xr::EnvironmentBlendMode::OPAQUE { let mut skybox = if environment_blend_mode == xr::EnvironmentBlendMode::OPAQUE {
create_skybox(&xr_state, &app_state) create_skybox(&xr_state, &app)
} else { } else {
None None
}; };
let pointer_lines = [ let pointer_lines = [
lines.allocate(&xr_state, app_state.graphics.clone())?, lines.allocate(&xr_state, app.graphics.clone())?,
lines.allocate(&xr_state, app_state.graphics.clone())?, lines.allocate(&xr_state, app.graphics.clone())?,
]; ];
let watch_id = overlays.get_by_name(WATCH_NAME).unwrap().state.id; // want panic let watch_id = overlays.get_by_name(WATCH_NAME).unwrap().state.id; // want panic
@@ -176,19 +168,18 @@ pub fn openxr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
if !running.load(Ordering::Relaxed) { if !running.load(Ordering::Relaxed) {
log::warn!("Received shutdown signal."); log::warn!("Received shutdown signal.");
match xr_state.session.request_exit() { match xr_state.session.request_exit() {
Ok(_) => log::info!("OpenXR session exit requested."), Ok(()) => log::info!("OpenXR session exit requested."),
Err(xr::sys::Result::ERROR_SESSION_NOT_RUNNING) => break 'main_loop, Err(xr::sys::Result::ERROR_SESSION_NOT_RUNNING) => break 'main_loop,
Err(e) => { Err(e) => {
log::error!("Failed to request OpenXR session exit: {}", e); log::error!("Failed to request OpenXR session exit: {e}");
break 'main_loop; break 'main_loop;
} }
} }
} }
while let Some(event) = xr_state.instance.poll_event(&mut event_storage)? { while let Some(event) = xr_state.instance.poll_event(&mut event_storage)? {
use xr::Event::*;
match event { match event {
SessionStateChanged(e) => { xr::Event::SessionStateChanged(e) => {
// Session state change is where we can begin and end sessions, as well as // Session state change is where we can begin and end sessions, as well as
// find quit messages! // find quit messages!
log::info!("entered state {:?}", e.state()); log::info!("entered state {:?}", e.state());
@@ -207,22 +198,22 @@ pub fn openxr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
_ => {} _ => {}
} }
} }
InstanceLossPending(_) => { xr::Event::InstanceLossPending(_) => {
break 'main_loop; break 'main_loop;
} }
EventsLost(e) => { xr::Event::EventsLost(e) => {
log::warn!("lost {} events", e.lost_event_count()); log::warn!("lost {} events", e.lost_event_count());
} }
MainSessionVisibilityChangedEXTX(e) => { xr::Event::MainSessionVisibilityChangedEXTX(e) => {
if main_session_visible != e.visible() { if main_session_visible != e.visible() {
main_session_visible = e.visible(); main_session_visible = e.visible();
log::info!("Main session visible: {}", main_session_visible); log::info!("Main session visible: {main_session_visible}");
if main_session_visible { if main_session_visible {
log::debug!("Destroying skybox."); log::debug!("Destroying skybox.");
skybox = None; skybox = None;
} else if environment_blend_mode == xr::EnvironmentBlendMode::OPAQUE { } else if environment_blend_mode == xr::EnvironmentBlendMode::OPAQUE {
log::debug!("Allocating skybox."); log::debug!("Allocating skybox.");
skybox = create_skybox(&xr_state, &app_state); skybox = create_skybox(&xr_state, &app);
} }
} }
} }
@@ -232,7 +223,7 @@ pub fn openxr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
if next_device_update <= Instant::now() { if next_device_update <= Instant::now() {
if let Some(monado) = &mut monado { if let Some(monado) = &mut monado {
input_source.update_devices(&mut app_state, monado); OpenXrInputSource::update_devices(&mut app, monado);
next_device_update = Instant::now() + Duration::from_secs(30); next_device_update = Instant::now() + Duration::from_secs(30);
} }
} }
@@ -259,8 +250,7 @@ pub fn openxr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
let total_elapsed = fps_counter let total_elapsed = fps_counter
.front() .front()
.map(|time| time.elapsed().as_secs_f32()) .map_or(0f32, |time| time.elapsed().as_secs_f32());
.unwrap_or(0f32);
fps_counter.len() as f32 / total_elapsed fps_counter.len() as f32 / total_elapsed
}; };
@@ -274,46 +264,46 @@ pub fn openxr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
continue 'main_loop; continue 'main_loop;
} }
app_state.input_state.pre_update(); app.input_state.pre_update();
input_source.update(&xr_state, &mut app_state)?; input_source.update(&xr_state, &mut app)?;
app_state.input_state.post_update(&app_state.session); app.input_state.post_update(&app.session);
if app_state if app
.input_state .input_state
.pointers .pointers
.iter() .iter()
.any(|p| p.now.show_hide && !p.before.show_hide) .any(|p| p.now.show_hide && !p.before.show_hide)
{ {
overlays.show_hide(&mut app_state); overlays.show_hide(&mut app);
} }
#[cfg(feature = "wayvr")] #[cfg(feature = "wayvr")]
if app_state if app
.input_state .input_state
.pointers .pointers
.iter() .iter()
.any(|p| p.now.toggle_dashboard && !p.before.toggle_dashboard) .any(|p| p.now.toggle_dashboard && !p.before.toggle_dashboard)
{ {
wayvr_action(&mut app_state, &mut overlays, &WayVRAction::ToggleDashboard); wayvr_action(&mut app, &mut overlays, &WayVRAction::ToggleDashboard);
} }
watch_fade(&mut app_state, overlays.mut_by_id(watch_id).unwrap()); // want panic watch_fade(&mut app, overlays.mut_by_id(watch_id).unwrap()); // want panic
if let Some(ref mut space_mover) = playspace { if let Some(ref mut space_mover) = playspace {
space_mover.update( space_mover.update(
&mut overlays, &mut overlays,
&app_state, &app,
monado.as_mut().unwrap(), // safe monado.as_mut().unwrap(), // safe
); );
} }
for o in overlays.iter_mut() { for o in overlays.iter_mut() {
o.after_input(&mut app_state)?; o.after_input(&mut app)?;
} }
#[cfg(feature = "osc")] #[cfg(feature = "osc")]
if let Some(ref mut sender) = app_state.osc_sender { if let Some(ref mut sender) = app.osc_sender {
let _ = sender.send_params(&overlays, &app_state.input_state.devices); let _ = sender.send_params(&overlays, &app.input_state.devices);
}; }
let (_, views) = xr_state.session.locate_views( let (_, views) = xr_state.session.locate_views(
VIEW_TYPE, VIEW_TYPE,
@@ -322,36 +312,36 @@ pub fn openxr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
)?; )?;
let ipd = helpers::ipd_from_views(&views); let ipd = helpers::ipd_from_views(&views);
if (app_state.input_state.ipd - ipd).abs() > 0.01 { if (app.input_state.ipd - ipd).abs() > 0.01 {
log::info!("IPD changed: {} -> {}", app_state.input_state.ipd, ipd); log::info!("IPD changed: {} -> {}", app.input_state.ipd, ipd);
app_state.input_state.ipd = ipd; app.input_state.ipd = ipd;
Toast::new( Toast::new(
ToastTopic::IpdChange, ToastTopic::IpdChange,
"IPD".into(), "IPD".into(),
format!("{:.1} mm", ipd).into(), format!("{ipd:.1} mm").into(),
) )
.submit(&mut app_state); .submit(&mut app);
} }
overlays overlays
.iter_mut() .iter_mut()
.for_each(|o| o.state.auto_movement(&mut app_state)); .for_each(|o| o.state.auto_movement(&mut app));
let lengths_haptics = interact(&mut overlays, &mut app_state); let lengths_haptics = interact(&mut overlays, &mut app);
for (idx, (len, haptics)) in lengths_haptics.iter().enumerate() { for (idx, (len, haptics)) in lengths_haptics.iter().enumerate() {
lines.draw_from( lines.draw_from(
pointer_lines[idx], pointer_lines[idx],
app_state.input_state.pointers[idx].pose, app.input_state.pointers[idx].pose,
*len, *len,
app_state.input_state.pointers[idx].interaction.mode as usize + 1, app.input_state.pointers[idx].interaction.mode as usize + 1,
&app_state.input_state.hmd, &app.input_state.hmd,
); );
if let Some(haptics) = haptics { if let Some(haptics) = haptics {
input_source.haptics(&xr_state, idx, haptics); input_source.haptics(&xr_state, idx, haptics);
} }
} }
app_state.hid_provider.commit(); app.hid_provider.commit();
let watch = overlays.mut_by_id(watch_id).unwrap(); // want panic let watch = overlays.mut_by_id(watch_id).unwrap(); // want panic
let watch_transform = watch.state.transform; let watch_transform = watch.state.transform;
@@ -366,9 +356,9 @@ pub fn openxr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
#[cfg(feature = "wayvr")] #[cfg(feature = "wayvr")]
if let Err(e) = if let Err(e) =
crate::overlays::wayvr::tick_events::<OpenXrOverlayData>(&mut app_state, &mut overlays) crate::overlays::wayvr::tick_events::<OpenXrOverlayData>(&mut app, &mut overlays)
{ {
log::error!("WayVR tick_events failed: {:?}", e); log::error!("WayVR tick_events failed: {e:?}");
} }
// Begin rendering // Begin rendering
@@ -376,7 +366,7 @@ pub fn openxr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
if !main_session_visible { if !main_session_visible {
if let Some(skybox) = skybox.as_mut() { if let Some(skybox) = skybox.as_mut() {
skybox.render(&xr_state, &app_state, &mut buffers)?; skybox.render(&xr_state, &app, &mut buffers)?;
} }
} }
@@ -387,22 +377,22 @@ pub fn openxr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
} }
if !o.data.init { if !o.data.init {
o.init(&mut app_state)?; o.init(&mut app)?;
o.data.init = true; o.data.init = true;
} }
let should_render = match o.should_render(&mut app_state)? { let should_render = match o.should_render(&mut app)? {
ShouldRender::Should => true, ShouldRender::Should => true,
ShouldRender::Can => o.data.last_alpha != o.state.alpha, ShouldRender::Can => (o.data.last_alpha - o.state.alpha).abs() > f32::EPSILON,
ShouldRender::Unable => false, //try show old image if exists ShouldRender::Unable => false, //try show old image if exists
}; };
if should_render { if should_render {
if !o.ensure_swapchain(&app_state, &xr_state)? { if !o.ensure_swapchain(&app, &xr_state)? {
continue; continue;
} }
let tgt = o.data.swapchain.as_mut().unwrap().acquire_wait_image()?; // want let tgt = o.data.swapchain.as_mut().unwrap().acquire_wait_image()?; // want
if !o.render(&mut app_state, tgt, &mut buffers, o.state.alpha)? { if !o.render(&mut app, tgt, &mut buffers, o.state.alpha)? {
o.data.swapchain.as_mut().unwrap().ensure_image_released()?; // want o.data.swapchain.as_mut().unwrap().ensure_image_released()?; // want
continue; continue;
} }
@@ -413,13 +403,13 @@ pub fn openxr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
o.data.cur_visible = true; o.data.cur_visible = true;
} }
lines.render(app_state.graphics.clone(), &mut buffers)?; lines.render(app.graphics.clone(), &mut buffers)?;
let future = buffers.execute_now(app_state.graphics.queue.clone())?; let future = buffers.execute_now(app.graphics.queue.clone())?;
if let Some(mut future) = future { if let Some(mut future) = future {
if let Err(e) = future.flush() { if let Err(e) = future.flush() {
return Err(BackendError::Fatal(e.into())); return Err(BackendError::Fatal(e.into()));
}; }
future.cleanup_finished(); future.cleanup_finished();
} }
// End rendering // End rendering
@@ -428,12 +418,8 @@ pub fn openxr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
let mut layers = vec![]; let mut layers = vec![];
if !main_session_visible { if !main_session_visible {
if let Some(skybox) = skybox.as_mut() { if let Some(skybox) = skybox.as_mut() {
for (idx, layer) in skybox for (idx, layer) in skybox.present(&xr_state, &app)?.into_iter().enumerate() {
.present(&xr_state, &app_state)? layers.push(((idx as f32).mul_add(-50.0, 200.0), layer));
.into_iter()
.enumerate()
{
layers.push((200.0 - 50.0 * (idx as f32), layer));
} }
} }
} }
@@ -442,7 +428,7 @@ pub fn openxr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
if !o.data.cur_visible { if !o.data.cur_visible {
continue; continue;
} }
let dist_sq = (app_state.input_state.hmd.translation - o.state.transform.translation) let dist_sq = (app.input_state.hmd.translation - o.state.transform.translation)
.length_squared() .length_squared()
+ (100f32 - o.state.z_order as f32); + (100f32 - o.state.z_order as f32);
if !dist_sq.is_normal() { if !dist_sq.is_normal() {
@@ -450,14 +436,14 @@ pub fn openxr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
continue; continue;
} }
let maybe_layer = o.present(&xr_state)?; let maybe_layer = o.present(&xr_state)?;
if let CompositionLayer::None = maybe_layer { if matches!(maybe_layer, CompositionLayer::None) {
continue; continue;
} }
layers.push((dist_sq, maybe_layer)); layers.push((dist_sq, maybe_layer));
} }
for maybe_layer in lines.present(&xr_state)? { for maybe_layer in lines.present(&xr_state)? {
if let CompositionLayer::None = maybe_layer { if matches!(maybe_layer, CompositionLayer::None) {
continue; continue;
} }
layers.push((0.0, maybe_layer)); layers.push((0.0, maybe_layer));
@@ -465,7 +451,7 @@ pub fn openxr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
// End layer composition // End layer composition
#[cfg(feature = "wayvr")] #[cfg(feature = "wayvr")]
if let Some(wayvr) = &app_state.wayvr { if let Some(wayvr) = &app.wayvr {
wayvr.borrow_mut().data.tick_finish()?; wayvr.borrow_mut().data.tick_finish()?;
} }
@@ -489,22 +475,21 @@ pub fn openxr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
)?; )?;
// End layer submit // End layer submit
let removed_overlays = overlays.update(&mut app_state)?; let removed_overlays = overlays.update(&mut app)?;
for o in removed_overlays { for o in removed_overlays {
delete_queue.push((o, cur_frame + 5)); delete_queue.push((o, cur_frame + 5));
} }
notifications.submit_pending(&mut app_state); notifications.submit_pending(&mut app);
app_state.tasks.retrieve_due(&mut due_tasks); app.tasks.retrieve_due(&mut due_tasks);
while let Some(task) = due_tasks.pop_front() { while let Some(task) = due_tasks.pop_front() {
match task { match task {
TaskType::Global(f) => f(&mut app_state),
TaskType::Overlay(sel, f) => { TaskType::Overlay(sel, f) => {
if let Some(o) = overlays.mut_by_selector(&sel) { if let Some(o) = overlays.mut_by_selector(&sel) {
f(&mut app_state, &mut o.state); f(&mut app, &mut o.state);
} else { } else {
log::warn!("Overlay not found for task: {:?}", sel); log::warn!("Overlay not found for task: {sel:?}");
} }
} }
TaskType::CreateOverlay(sel, f) => { TaskType::CreateOverlay(sel, f) => {
@@ -512,14 +497,14 @@ pub fn openxr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
continue; continue;
}; };
let Some((mut state, backend)) = f(&mut app_state) else { let Some((mut overlay_state, overlay_backend)) = f(&mut app) else {
continue; continue;
}; };
state.birthframe = cur_frame; overlay_state.birthframe = cur_frame;
overlays.add(OverlayData { overlays.add(OverlayData {
state, state: overlay_state,
backend, backend: overlay_backend,
..Default::default() ..Default::default()
}); });
} }
@@ -538,7 +523,7 @@ pub fn openxr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
SystemTask::FixFloor => { SystemTask::FixFloor => {
if let Some(ref mut playspace) = playspace { if let Some(ref mut playspace) = playspace {
playspace.fix_floor( playspace.fix_floor(
&app_state.input_state, &app.input_state,
monado.as_mut().unwrap(), // safe monado.as_mut().unwrap(), // safe
); );
} }
@@ -549,13 +534,13 @@ pub fn openxr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
} }
} }
SystemTask::ShowHide => { SystemTask::ShowHide => {
overlays.show_hide(&mut app_state); overlays.show_hide(&mut app);
} }
_ => {} _ => {}
}, },
#[cfg(feature = "wayvr")] #[cfg(feature = "wayvr")]
TaskType::WayVR(action) => { TaskType::WayVR(action) => {
wayvr_action(&mut app_state, &mut overlays, &action); wayvr_action(&mut app, &mut overlays, &action);
} }
} }
} }

View File

@@ -8,13 +8,6 @@ use crate::{
use super::overlay::OpenXrOverlayData; use super::overlay::OpenXrOverlayData;
#[repr(C)]
#[derive(Default, Debug)]
struct XrtPose {
orientation: [f32; 4],
position: [f32; 3],
}
struct MoverData<T> { struct MoverData<T> {
pose: Affine3A, pose: Affine3A,
hand: usize, hand: usize,
@@ -55,7 +48,7 @@ impl PlayspaceMover {
state: &AppState, state: &AppState,
monado: &mut Monado, monado: &mut Monado,
) { ) {
for pointer in state.input_state.pointers.iter() { for pointer in &state.input_state.pointers {
if pointer.now.space_reset { if pointer.now.space_reset {
if !pointer.before.space_reset { if !pointer.before.space_reset {
log::info!("Space reset"); log::info!("Space reset");
@@ -81,8 +74,8 @@ impl PlayspaceMover {
Affine3A::from_quat(dq) Affine3A::from_quat(dq)
} else { } else {
let rel_y = f32::atan2( let rel_y = f32::atan2(
2.0 * (dq.y * dq.w + dq.x * dq.z), 2.0 * dq.y.mul_add(dq.w, dq.x * dq.z),
(2.0 * (dq.w * dq.w + dq.x * dq.x)) - 1.0, 2.0f32.mul_add(dq.w.mul_add(dq.w, dq.x * dq.x), -1.0),
); );
Affine3A::from_rotation_y(rel_y) Affine3A::from_rotation_y(rel_y)
@@ -96,7 +89,7 @@ impl PlayspaceMover {
data.pose *= space_transform; data.pose *= space_transform;
data.hand_pose = new_hand; data.hand_pose = new_hand;
self.apply_offset(data.pose, monado); apply_offset(data.pose, monado);
self.rotate = Some(data); self.rotate = Some(data);
} else { } else {
for (i, pointer) in state.input_state.pointers.iter().enumerate() { for (i, pointer) in state.input_state.pointers.iter().enumerate() {
@@ -145,7 +138,7 @@ impl PlayspaceMover {
data.pose.translation += relative_pos; data.pose.translation += relative_pos;
data.hand_pose = new_hand; data.hand_pose = new_hand;
self.apply_offset(data.pose, monado); apply_offset(data.pose, monado);
self.drag = Some(data); self.drag = Some(data);
} else { } else {
for (i, pointer) in state.input_state.pointers.iter().enumerate() { for (i, pointer) in state.input_state.pointers.iter().enumerate() {
@@ -176,7 +169,7 @@ impl PlayspaceMover {
} }
self.last_transform = Affine3A::IDENTITY; self.last_transform = Affine3A::IDENTITY;
self.apply_offset(self.last_transform, monado); apply_offset(self.last_transform, monado);
} }
pub fn fix_floor(&mut self, input: &InputState, monado: &mut Monado) { pub fn fix_floor(&mut self, input: &InputState, monado: &mut Monado) {
@@ -193,14 +186,14 @@ impl PlayspaceMover {
let y2 = input.pointers[1].raw_pose.translation.y; let y2 = input.pointers[1].raw_pose.translation.y;
let delta = y1.min(y2) - 0.03; let delta = y1.min(y2) - 0.03;
self.last_transform.translation.y += delta; self.last_transform.translation.y += delta;
self.apply_offset(self.last_transform, monado); apply_offset(self.last_transform, monado);
}
fn apply_offset(&self, transform: Affine3A, monado: &mut Monado) {
let pose = Pose {
position: transform.translation.into(),
orientation: Quat::from_affine3(&transform).into(),
};
let _ = monado.set_reference_space_offset(ReferenceSpaceType::Stage, pose);
} }
} }
fn apply_offset(transform: Affine3A, monado: &mut Monado) {
let pose = Pose {
position: transform.translation.into(),
orientation: Quat::from_affine3(&transform).into(),
};
let _ = monado.set_reference_space_offset(ReferenceSpaceType::Stage, pose);
}

View File

@@ -56,7 +56,7 @@ impl Skybox {
"Could not use custom skybox texture at: {}", "Could not use custom skybox texture at: {}",
app.session.config.skybox_texture app.session.config.skybox_texture
); );
log::warn!("{:?}", e); log::warn!("{e:?}");
} }
} }
} }
@@ -181,6 +181,11 @@ impl Skybox {
xr: &'a XrState, xr: &'a XrState,
app: &AppState, app: &AppState,
) -> anyhow::Result<Vec<CompositionLayer<'a>>> { ) -> anyhow::Result<Vec<CompositionLayer<'a>>> {
// cover the entire sphere
const HORIZ_ANGLE: f32 = 2.0 * PI;
const HI_VERT_ANGLE: f32 = 0.5 * PI;
const LO_VERT_ANGLE: f32 = -0.5 * PI;
static GRID_POSE: Lazy<xr::Posef> = Lazy::new(|| { static GRID_POSE: Lazy<xr::Posef> = Lazy::new(|| {
translation_rotation_to_posef(Vec3A::ZERO, Quat::from_rotation_x(PI * -0.5)) translation_rotation_to_posef(Vec3A::ZERO, Quat::from_rotation_x(PI * -0.5))
}); });
@@ -194,11 +199,6 @@ impl Skybox {
}, },
}; };
// cover the entire sphere
const HORIZ_ANGLE: f32 = 2.0 * PI;
const HI_VERT_ANGLE: f32 = 0.5 * PI;
const LO_VERT_ANGLE: f32 = -0.5 * PI;
self.sky.as_mut().unwrap().ensure_image_released()?; self.sky.as_mut().unwrap().ensure_image_released()?;
let sky = xr::CompositionLayerEquirect2KHR::new() let sky = xr::CompositionLayerEquirect2KHR::new()

View File

@@ -20,9 +20,9 @@ pub(super) struct SwapchainOpts {
impl SwapchainOpts { impl SwapchainOpts {
pub fn new() -> Self { pub fn new() -> Self {
Default::default() Self::default()
} }
pub fn immutable(mut self) -> Self { pub const fn immutable(mut self) -> Self {
self.immutable = true; self.immutable = true;
self self
} }

View File

@@ -26,7 +26,7 @@ impl OscSender {
bail!("Failed to bind UDP socket - OSC will not function."); bail!("Failed to bind UDP socket - OSC will not function.");
}; };
let Ok(_) = upstream.connect(SocketAddr::new(ip, send_port)) else { let Ok(()) = upstream.connect(SocketAddr::new(ip, send_port)) else {
bail!("Failed to connect UDP socket - OSC will not function."); bail!("Failed to connect UDP socket - OSC will not function.");
}; };
@@ -75,7 +75,7 @@ impl OscSender {
KEYBOARD_NAME => has_keyboard = true, KEYBOARD_NAME => has_keyboard = true,
_ => { _ => {
if o.state.interactable { if o.state.interactable {
num_overlays += 1 num_overlays += 1;
} }
} }
} }
@@ -159,12 +159,12 @@ impl OscSender {
self.send_message( self.send_message(
String::from("/avatar/parameters/averageControllerBattery"), String::from("/avatar/parameters/averageControllerBattery"),
vec![OscType::Float( vec![OscType::Float(
controller_total_bat / controller_count as f32, controller_total_bat / f32::from(controller_count),
)], )],
)?; )?;
self.send_message( self.send_message(
String::from("/avatar/parameters/averageTrackerBattery"), String::from("/avatar/parameters/averageTrackerBattery"),
vec![OscType::Float(tracker_total_bat / tracker_count as f32)], vec![OscType::Float(tracker_total_bat / f32::from(tracker_count))],
)?; )?;
} }

View File

@@ -56,14 +56,13 @@ pub struct OverlayState {
pub saved_transform: Option<Affine3A>, pub saved_transform: Option<Affine3A>,
pub relative_to: RelativeTo, pub relative_to: RelativeTo,
pub curvature: Option<f32>, pub curvature: Option<f32>,
pub primary_pointer: Option<usize>,
pub interaction_transform: Affine2, pub interaction_transform: Affine2,
pub birthframe: usize, pub birthframe: usize,
} }
impl Default for OverlayState { impl Default for OverlayState {
fn default() -> Self { fn default() -> Self {
OverlayState { Self {
id: OverlayID(OVERLAY_AUTO_INCREMENT.fetch_add(1, Ordering::Relaxed)), id: OverlayID(OVERLAY_AUTO_INCREMENT.fetch_add(1, Ordering::Relaxed)),
name: Arc::from(""), name: Arc::from(""),
want_visible: false, want_visible: false,
@@ -83,7 +82,6 @@ impl Default for OverlayState {
spawn_rotation: Quat::IDENTITY, spawn_rotation: Quat::IDENTITY,
saved_transform: None, saved_transform: None,
transform: Affine3A::IDENTITY, transform: Affine3A::IDENTITY,
primary_pointer: None,
interaction_transform: Affine2::IDENTITY, interaction_transform: Affine2::IDENTITY,
birthframe: 0, birthframe: 0,
} }
@@ -105,8 +103,8 @@ where
T: Default, T: Default,
{ {
fn default() -> Self { fn default() -> Self {
OverlayData { Self {
state: Default::default(), state: OverlayState::default(),
backend: Box::<SplitOverlayBackend>::default(), backend: Box::<SplitOverlayBackend>::default(),
primary_pointer: None, primary_pointer: None,
data: Default::default(), data: Default::default(),
@@ -115,7 +113,7 @@ where
} }
impl OverlayState { impl OverlayState {
pub fn parent_transform(&self, app: &AppState) -> Option<Affine3A> { pub const fn parent_transform(&self, app: &AppState) -> Option<Affine3A> {
match self.relative_to { match self.relative_to {
RelativeTo::Head => Some(app.input_state.hmd), RelativeTo::Head => Some(app.input_state.hmd),
RelativeTo::Hand(idx) => Some(app.input_state.pointers[idx].pose), RelativeTo::Hand(idx) => Some(app.input_state.pointers[idx].pose),
@@ -123,7 +121,7 @@ impl OverlayState {
} }
} }
fn get_anchor(&self, app: &AppState) -> Affine3A { const fn get_anchor(&self, app: &AppState) -> Affine3A {
if self.anchored { if self.anchored {
app.anchor app.anchor
} else { } else {
@@ -211,12 +209,14 @@ where
T: Default, T: Default,
{ {
pub fn init(&mut self, app: &mut AppState) -> anyhow::Result<()> { pub fn init(&mut self, app: &mut AppState) -> anyhow::Result<()> {
self.state.curvature = app if self.state.curvature.is_none() {
.session self.state.curvature = app
.config .session
.curve_values .config
.arc_get(self.state.name.as_ref()) .curve_values
.copied(); .arc_get(self.state.name.as_ref())
.copied();
}
if matches!(self.state.relative_to, RelativeTo::None) { if matches!(self.state.relative_to, RelativeTo::None) {
let hard_reset; let hard_reset;
@@ -250,18 +250,6 @@ where
pub fn frame_meta(&mut self) -> Option<FrameMeta> { pub fn frame_meta(&mut self) -> Option<FrameMeta> {
self.backend.frame_meta() self.backend.frame_meta()
} }
pub fn set_visible(&mut self, app: &mut AppState, visible: bool) -> anyhow::Result<()> {
let old_visible = self.state.want_visible;
self.state.want_visible = visible;
if visible != old_visible {
if visible {
self.backend.resume(app)?;
} else {
self.backend.pause(app)?;
}
}
Ok(())
}
} }
#[derive(Default, Clone, Copy)] #[derive(Default, Clone, Copy)]
@@ -351,8 +339,8 @@ pub struct SplitOverlayBackend {
} }
impl Default for SplitOverlayBackend { impl Default for SplitOverlayBackend {
fn default() -> SplitOverlayBackend { fn default() -> Self {
SplitOverlayBackend { Self {
renderer: Box::new(FallbackRenderer), renderer: Box::new(FallbackRenderer),
interaction: Box::new(DummyInteractionHandler), interaction: Box::new(DummyInteractionHandler),
} }
@@ -409,7 +397,7 @@ impl InteractionHandler for SplitOverlayBackend {
} }
} }
pub fn ui_transform(extent: &[u32; 2]) -> Affine2 { pub fn ui_transform(extent: [u32; 2]) -> Affine2 {
let aspect = extent[0] as f32 / extent[1] as f32; let aspect = extent[0] as f32 / extent[1] as f32;
let scale = if aspect < 1.0 { let scale = if aspect < 1.0 {
Vec2 { Vec2 {

View File

@@ -25,12 +25,12 @@ struct AppTask {
pub task: TaskType, pub task: TaskType,
} }
impl PartialEq<AppTask> for AppTask { impl PartialEq<Self> for AppTask {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
self.cmp(other) == cmp::Ordering::Equal self.cmp(other) == cmp::Ordering::Equal
} }
} }
impl PartialOrd<AppTask> for AppTask { impl PartialOrd<Self> for AppTask {
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> { fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
Some(self.cmp(other)) Some(self.cmp(other))
} }
@@ -57,7 +57,6 @@ pub type CreateOverlayTask =
dyn FnOnce(&mut AppState) -> Option<(OverlayState, Box<dyn OverlayBackend>)> + Send; dyn FnOnce(&mut AppState) -> Option<(OverlayState, Box<dyn OverlayBackend>)> + Send;
pub enum TaskType { pub enum TaskType {
Global(Box<dyn FnOnce(&mut AppState) + Send>),
Overlay(OverlaySelector, Box<OverlayTask>), Overlay(OverlaySelector, Box<OverlayTask>),
CreateOverlay(OverlaySelector, Box<CreateOverlayTask>), CreateOverlay(OverlaySelector, Box<CreateOverlayTask>),
DropOverlay(OverlaySelector), DropOverlay(OverlaySelector),
@@ -79,7 +78,7 @@ pub struct TaskContainer {
} }
impl TaskContainer { impl TaskContainer {
pub fn new() -> Self { pub const fn new() -> Self {
Self { Self {
tasks: BinaryHeap::new(), tasks: BinaryHeap::new(),
} }

View File

@@ -3,7 +3,8 @@ use std::sync::Arc;
use vulkano::{ use vulkano::{
image::{view::ImageView, ImageUsage}, image::{view::ImageView, ImageUsage},
swapchain::{ swapchain::{
acquire_next_image, Surface, Swapchain, SwapchainCreateInfo, SwapchainPresentInfo, acquire_next_image, Surface, SurfaceInfo, Swapchain, SwapchainCreateInfo,
SwapchainPresentInfo,
}, },
sync::GpuFuture, sync::GpuFuture,
Validated, VulkanError, Validated, VulkanError,
@@ -67,13 +68,12 @@ impl PreviewState {
let inner_size = window.inner_size(); let inner_size = window.inner_size();
let swapchain_size = [inner_size.width, inner_size.height]; let swapchain_size = [inner_size.width, inner_size.height];
let (swapchain, images) = let (swapchain, images) = create_swapchain(&state.graphics, surface, swapchain_size)?;
create_swapchain(&state.graphics, surface.clone(), swapchain_size)?;
let mut canvas = modular_canvas(&config.size, &config.elements, state)?; let mut canvas = modular_canvas(config.size, &config.elements, state)?;
canvas.init(state)?; canvas.init(state)?;
Ok(PreviewState { Ok(Self {
canvas, canvas,
swapchain, swapchain,
images, images,
@@ -99,7 +99,7 @@ pub fn uidev_run(panel_name: &str) -> anyhow::Result<()> {
panel_name, panel_name,
)?); )?);
let watch_path = config_io::get_config_root().join(format!("{}.yaml", panel_name)); let watch_path = config_io::get_config_root().join(format!("{panel_name}.yaml"));
let mut path_last_modified = watch_path.metadata()?.modified()?; let mut path_last_modified = watch_path.metadata()?.modified()?;
let mut recreate = false; let mut recreate = false;
let mut last_draw = std::time::Instant::now(); let mut last_draw = std::time::Instant::now();
@@ -164,7 +164,7 @@ pub fn uidev_run(panel_name: &str) -> anyhow::Result<()> {
{ {
log::error!("failed to render canvas: {e}"); log::error!("failed to render canvas: {e}");
window.request_redraw(); window.request_redraw();
}; }
last_draw = std::time::Instant::now(); last_draw = std::time::Instant::now();
@@ -204,12 +204,12 @@ fn create_swapchain(
let surface_capabilities = graphics let surface_capabilities = graphics
.device .device
.physical_device() .physical_device()
.surface_capabilities(&surface, Default::default()) .surface_capabilities(&surface, SurfaceInfo::default())
.unwrap(); // want panic .unwrap(); // want panic
let (swapchain, images) = Swapchain::new( let (swapchain, images) = Swapchain::new(
graphics.device.clone(), graphics.device.clone(),
surface.clone(), surface,
SwapchainCreateInfo { SwapchainCreateInfo {
min_image_count: surface_capabilities.min_image_count.max(2), min_image_count: surface_capabilities.min_image_count.max(2),
image_format: graphics.native_format, image_format: graphics.native_format,

View File

@@ -36,7 +36,7 @@ pub struct WayVRCompositor {
} }
fn get_wayvr_env_from_pid(pid: i32) -> anyhow::Result<ProcessWayVREnv> { fn get_wayvr_env_from_pid(pid: i32) -> anyhow::Result<ProcessWayVREnv> {
let path = format!("/proc/{}/environ", pid); let path = format!("/proc/{pid}/environ");
let mut env_data = String::new(); let mut env_data = String::new();
std::fs::File::open(path)?.read_to_string(&mut env_data)?; std::fs::File::open(path)?.read_to_string(&mut env_data)?;
@@ -162,7 +162,7 @@ impl WayVRCompositor {
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
if let Some(stream) = self.listener.accept()? { if let Some(stream) = self.listener.accept()? {
if let Err(e) = self.accept_connection(stream, displays, processes) { if let Err(e) = self.accept_connection(stream, displays, processes) {
log::error!("Failed to accept connection: {}", e); log::error!("Failed to accept connection: {e}");
} }
} }
@@ -175,7 +175,7 @@ impl WayVRCompositor {
processes: &mut process::ProcessVec, processes: &mut process::ProcessVec,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
if let Err(e) = self.accept_connections(displays, processes) { if let Err(e) = self.accept_connections(displays, processes) {
log::error!("accept_connections failed: {}", e); log::error!("accept_connections failed: {e}");
} }
self.display.dispatch_clients(&mut self.state)?; self.display.dispatch_clients(&mut self.state)?;
@@ -184,7 +184,7 @@ impl WayVRCompositor {
let surf_count = self.state.xdg_shell.toplevel_surfaces().len() as u32; let surf_count = self.state.xdg_shell.toplevel_surfaces().len() as u32;
if surf_count != self.toplevel_surf_count { if surf_count != self.toplevel_surf_count {
self.toplevel_surf_count = surf_count; self.toplevel_surf_count = surf_count;
log::info!("Toplevel surface count changed: {}", surf_count); log::info!("Toplevel surface count changed: {surf_count}");
} }
Ok(()) Ok(())
@@ -211,11 +211,9 @@ impl WayVRCompositor {
const STARTING_WAYLAND_ADDR_IDX: u32 = 20; const STARTING_WAYLAND_ADDR_IDX: u32 = 20;
fn export_display_number(display_num: u32) -> anyhow::Result<()> { fn export_display_number(display_num: u32) -> anyhow::Result<()> {
let mut path = std::env::var("XDG_RUNTIME_DIR") let mut path = std::env::var("XDG_RUNTIME_DIR").map_or_else(|_| PathBuf::from("/tmp"), PathBuf::from);
.map(PathBuf::from)
.unwrap_or_else(|_| PathBuf::from("/tmp"));
path.push("wayvr.disp"); path.push("wayvr.disp");
std::fs::write(path, format!("{}\n", display_num))?; std::fs::write(path, format!("{display_num}\n"))?;
Ok(()) Ok(())
} }
@@ -227,17 +225,15 @@ fn create_wayland_listener() -> anyhow::Result<(super::WaylandEnv, wayland_serve
let listener = loop { let listener = loop {
let display_str = env.display_num_string(); let display_str = env.display_num_string();
log::debug!("Trying to open socket \"{}\"", display_str); log::debug!("Trying to open socket \"{display_str}\"");
match wayland_server::ListeningSocket::bind(display_str.as_str()) { match wayland_server::ListeningSocket::bind(display_str.as_str()) {
Ok(listener) => { Ok(listener) => {
log::debug!("Listening to {}", display_str); log::debug!("Listening to {display_str}");
break listener; break listener;
} }
Err(e) => { Err(e) => {
log::debug!( log::debug!(
"Failed to open socket \"{}\" (reason: {}), trying next...", "Failed to open socket \"{display_str}\" (reason: {e}), trying next..."
display_str,
e
); );
env.display_num += 1; env.display_num += 1;

View File

@@ -122,15 +122,13 @@ pub struct ClientState {
impl ClientData for ClientState { impl ClientData for ClientState {
fn initialized(&self, client_id: ClientId) { fn initialized(&self, client_id: ClientId) {
log::debug!("Client ID {:?} connected", client_id); log::debug!("Client ID {client_id:?} connected");
} }
fn disconnected(&self, client_id: ClientId, reason: DisconnectReason) { fn disconnected(&self, client_id: ClientId, reason: DisconnectReason) {
*self.disconnected.lock().unwrap() = true; *self.disconnected.lock().unwrap() = true;
log::debug!( log::debug!(
"Client ID {:?} disconnected. Reason: {:?}", "Client ID {client_id:?} disconnected. Reason: {reason:?}"
client_id,
reason
); );
} }
} }
@@ -202,7 +200,7 @@ impl DmabufHandler for Application {
notifier: ImportNotifier, notifier: ImportNotifier,
) { ) {
if self.gles_renderer.import_dmabuf(&dmabuf, None).is_ok() { if self.gles_renderer.import_dmabuf(&dmabuf, None).is_ok() {
let _ = notifier.successful::<Application>(); let _ = notifier.successful::<Self>();
} else { } else {
notifier.failed(); notifier.failed();
} }

View File

@@ -122,8 +122,8 @@ impl Display {
let tex_id = params.renderer.with_context(|gl| { let tex_id = params.renderer.with_context(|gl| {
smithay_wrapper::create_framebuffer_texture( smithay_wrapper::create_framebuffer_texture(
gl, gl,
params.width as u32, u32::from(params.width),
params.height as u32, u32::from(params.height),
tex_format, tex_format,
internal_format, internal_format,
) )
@@ -139,7 +139,7 @@ impl Display {
}; };
let opaque = false; let opaque = false;
let size = (params.width as i32, params.height as i32).into(); let size = (i32::from(params.width), i32::from(params.height)).into();
let gles_texture = unsafe { let gles_texture = unsafe {
GlesTexture::from_raw(params.renderer, Some(tex_format), opaque, tex_id, size) GlesTexture::from_raw(params.renderer, Some(tex_format), opaque, tex_id, size)
}; };
@@ -202,7 +202,7 @@ impl Display {
match &self.layout { match &self.layout {
packet_server::WvrDisplayWindowLayout::Tiling => { packet_server::WvrDisplayWindowLayout::Tiling => {
let mut i = 0; let mut i = 0;
for win in self.displayed_windows.iter_mut() { for win in &mut self.displayed_windows {
if let Some(window) = self.wm.borrow_mut().windows.get_mut(&win.window_handle) { if let Some(window) = self.wm.borrow_mut().windows.get_mut(&win.window_handle) {
if !window.visible { if !window.visible {
continue; continue;
@@ -210,21 +210,21 @@ impl Display {
let d_cur = i as f32 / window_count as f32; let d_cur = i as f32 / window_count as f32;
let d_next = (i + 1) as f32 / window_count as f32; let d_next = (i + 1) as f32 / window_count as f32;
let left = (d_cur * self.width as f32) as i32; let left = (d_cur * f32::from(self.width)) as i32;
let right = (d_next * self.width as f32) as i32; let right = (d_next * f32::from(self.width)) as i32;
window.set_pos(left, 0); window.set_pos(left, 0);
window.set_size((right - left) as u32, self.height as u32); window.set_size((right - left) as u32, u32::from(self.height));
i += 1; i += 1;
} }
} }
} }
packet_server::WvrDisplayWindowLayout::Stacking(opts) => { packet_server::WvrDisplayWindowLayout::Stacking(opts) => {
let do_margins = |margins: &packet_server::Margins, window: &mut window::Window| { let do_margins = |margins: &packet_server::Margins, window: &mut window::Window| {
let top = margins.top as i32; let top = i32::from(margins.top);
let bottom = self.height as i32 - margins.bottom as i32; let bottom = i32::from(self.height) - i32::from(margins.bottom);
let left = margins.left as i32; let left = i32::from(margins.left);
let right = self.width as i32 - margins.right as i32; let right = i32::from(self.width) - i32::from(margins.right);
let width = right - left; let width = right - left;
let height = bottom - top; let height = bottom - top;
if width < 0 || height < 0 { if width < 0 || height < 0 {
@@ -236,7 +236,7 @@ impl Display {
}; };
let mut i = 0; let mut i = 0;
for win in self.displayed_windows.iter_mut() { for win in &mut self.displayed_windows {
if let Some(window) = self.wm.borrow_mut().windows.get_mut(&win.window_handle) { if let Some(window) = self.wm.borrow_mut().windows.get_mut(&win.window_handle) {
if !window.visible { if !window.visible {
continue; continue;
@@ -267,7 +267,7 @@ impl Display {
self.no_windows_since = None; self.no_windows_since = None;
} else if let Some(auto_hide_delay) = config.auto_hide_delay { } else if let Some(auto_hide_delay) = config.auto_hide_delay {
if let Some(s) = self.no_windows_since { if let Some(s) = self.no_windows_since {
if s + (auto_hide_delay as u64) < get_millis() { if s + u64::from(auto_hide_delay) < get_millis() {
// Auto-hide after specific time // Auto-hide after specific time
signals.send(WayVRSignal::DisplayVisibility(*handle, false)); signals.send(WayVRSignal::DisplayVisibility(*handle, false));
} }
@@ -303,7 +303,7 @@ impl Display {
pub fn tick_render(&mut self, renderer: &mut GlesRenderer, time_ms: u64) -> anyhow::Result<()> { pub fn tick_render(&mut self, renderer: &mut GlesRenderer, time_ms: u64) -> anyhow::Result<()> {
renderer.bind(self.gles_texture.clone())?; renderer.bind(self.gles_texture.clone())?;
let size = Size::from((self.width as i32, self.height as i32)); let size = Size::from((i32::from(self.width), i32::from(self.height)));
let damage: Rectangle<i32, smithay::utils::Physical> = Rectangle::from_size(size); let damage: Rectangle<i32, smithay::utils::Physical> = Rectangle::from_size(size);
let elements: Vec<WaylandSurfaceRenderElement<GlesRenderer>> = self let elements: Vec<WaylandSurfaceRenderElement<GlesRenderer>> = self
@@ -358,8 +358,8 @@ impl Display {
gl.ReadPixels( gl.ReadPixels(
0, 0,
0, 0,
self.width as i32, i32::from(self.width),
self.height as i32, i32::from(self.height),
ffi::RGBA, ffi::RGBA,
ffi::UNSIGNED_BYTE, ffi::UNSIGNED_BYTE,
data.as_mut_ptr().cast(), data.as_mut_ptr().cast(),
@@ -401,7 +401,7 @@ impl Display {
None None
} }
pub fn trigger_rerender(&mut self) { pub const fn trigger_rerender(&mut self) {
self.wants_redraw = true; self.wants_redraw = true;
} }
@@ -435,7 +435,7 @@ impl Display {
y: u32, y: u32,
) { ) {
let current_ms = time::get_millis(); let current_ms = time::get_millis();
if self.last_pressed_time_ms + config.click_freeze_time_ms as u64 > current_ms { if self.last_pressed_time_ms + u64::from(config.click_freeze_time_ms) > current_ms {
return; return;
} }
@@ -444,8 +444,8 @@ impl Display {
if let Some(window) = wm.windows.get(&window_handle) { if let Some(window) = wm.windows.get(&window_handle) {
let surf = window.toplevel.wl_surface().clone(); let surf = window.toplevel.wl_surface().clone();
let point = Point::<f64, Logical>::from(( let point = Point::<f64, Logical>::from((
(x as i32 - window.pos_x) as f64, f64::from(x as i32 - window.pos_x),
(y as i32 - window.pos_y) as f64, f64::from(y as i32 - window.pos_y),
)); ));
manager.seat_pointer.motion( manager.seat_pointer.motion(
@@ -463,7 +463,7 @@ impl Display {
} }
} }
fn get_mouse_index_number(index: super::MouseIndex) -> u32 { const fn get_mouse_index_number(index: super::MouseIndex) -> u32 {
match index { match index {
super::MouseIndex::Left => 0x110, /* BTN_LEFT */ super::MouseIndex::Left => 0x110, /* BTN_LEFT */
super::MouseIndex::Center => 0x112, /* BTN_MIDDLE */ super::MouseIndex::Center => 0x112, /* BTN_MIDDLE */
@@ -505,7 +505,7 @@ impl Display {
manager.seat_pointer.frame(&mut manager.state); manager.seat_pointer.frame(&mut manager.state);
} }
pub fn send_mouse_up(&self, manager: &mut WayVRCompositor, index: super::MouseIndex) { pub fn send_mouse_up(manager: &mut WayVRCompositor, index: super::MouseIndex) {
manager.seat_pointer.button( manager.seat_pointer.button(
&mut manager.state, &mut manager.state,
&input::pointer::ButtonEvent { &input::pointer::ButtonEvent {
@@ -519,7 +519,7 @@ impl Display {
manager.seat_pointer.frame(&mut manager.state); manager.seat_pointer.frame(&mut manager.state);
} }
pub fn send_mouse_scroll(&self, manager: &mut WayVRCompositor, delta_y: f32, delta_x: f32) { pub fn send_mouse_scroll(manager: &mut WayVRCompositor, delta_y: f32, delta_x: f32) {
manager.seat_pointer.axis( manager.seat_pointer.axis(
&mut manager.state, &mut manager.state,
input::pointer::AxisFrame { input::pointer::AxisFrame {
@@ -529,7 +529,7 @@ impl Display {
smithay::backend::input::AxisRelativeDirection::Identical, smithay::backend::input::AxisRelativeDirection::Identical,
), ),
time: 0, time: 0,
axis: (delta_x as f64, -delta_y as f64), axis: (f64::from(delta_x), f64::from(-delta_y)),
v120: Some((0, (delta_y * -120.0) as i32)), v120: Some((0, (delta_y * -120.0) as i32)),
stop: (false, false), stop: (false, false),
}, },
@@ -549,7 +549,7 @@ impl Display {
args: &[&str], args: &[&str],
env: &[(&str, &str)], env: &[(&str, &str)],
) -> anyhow::Result<SpawnProcessResult> { ) -> anyhow::Result<SpawnProcessResult> {
log::info!("Spawning subprocess with exec path \"{}\"", exec_path); log::info!("Spawning subprocess with exec path \"{exec_path}\"");
let auth_key = generate_auth_key(); let auth_key = generate_auth_key();
@@ -577,14 +577,14 @@ impl Display {
gen_id!(DisplayVec, Display, DisplayCell, DisplayHandle); gen_id!(DisplayVec, Display, DisplayCell, DisplayHandle);
impl DisplayHandle { impl DisplayHandle {
pub fn from_packet(handle: packet_server::WvrDisplayHandle) -> Self { pub const fn from_packet(handle: packet_server::WvrDisplayHandle) -> Self {
Self { Self {
generation: handle.generation, generation: handle.generation,
idx: handle.idx, idx: handle.idx,
} }
} }
pub fn as_packet(&self) -> packet_server::WvrDisplayHandle { pub const fn as_packet(&self) -> packet_server::WvrDisplayHandle {
packet_server::WvrDisplayHandle { packet_server::WvrDisplayHandle {
idx: self.idx, idx: self.idx,
generation: self.generation, generation: self.generation,

View File

@@ -47,25 +47,25 @@ pub enum RenderData {
impl EGLData { impl EGLData {
pub fn load_func(&self, func_name: &str) -> anyhow::Result<extern "system" fn()> { pub fn load_func(&self, func_name: &str) -> anyhow::Result<extern "system" fn()> {
let raw_fn = self.egl.get_proc_address(func_name).ok_or(anyhow::anyhow!( let raw_fn = self
"Required EGL function {} not found", .egl
func_name .get_proc_address(func_name)
))?; .ok_or_else(|| anyhow::anyhow!("Required EGL function {} not found", func_name))?;
Ok(raw_fn) Ok(raw_fn)
} }
pub fn new() -> anyhow::Result<EGLData> { pub fn new() -> anyhow::Result<Self> {
unsafe { unsafe {
let egl = khronos_egl::Instance::new(khronos_egl::Static); let egl = khronos_egl::Instance::new(khronos_egl::Static);
let display = egl let display = egl
.get_display(khronos_egl::DEFAULT_DISPLAY) .get_display(khronos_egl::DEFAULT_DISPLAY)
.ok_or(anyhow!( .ok_or_else(|| anyhow!(
"eglGetDisplay failed. This shouldn't happen unless you don't have any display manager running. Cannot continue, check your EGL installation." "eglGetDisplay failed. This shouldn't happen unless you don't have any display manager running. Cannot continue, check your EGL installation."
))?; ))?;
let (major, minor) = egl.initialize(display)?; let (major, minor) = egl.initialize(display)?;
log::debug!("EGL version: {}.{}", major, minor); log::debug!("EGL version: {major}.{minor}");
let attrib_list = [ let attrib_list = [
khronos_egl::RED_SIZE, khronos_egl::RED_SIZE,
@@ -83,7 +83,7 @@ impl EGLData {
let config = egl let config = egl
.choose_first_config(display, &attrib_list)? .choose_first_config(display, &attrib_list)?
.ok_or(anyhow!("Failed to get EGL config"))?; .ok_or_else(|| anyhow!("Failed to get EGL config"))?;
egl.bind_api(khronos_egl::OPENGL_ES_API)?; egl.bind_api(khronos_egl::OPENGL_ES_API)?;
@@ -104,7 +104,7 @@ impl EGLData {
egl.make_current(display, None, None, Some(context))?; egl.make_current(display, None, None, Some(context))?;
Ok(EGLData { Ok(Self {
egl, egl,
display, display,
config, config,
@@ -114,7 +114,7 @@ impl EGLData {
} }
fn query_dmabuf_mod_info(&self) -> anyhow::Result<DMAbufModifierInfo> { fn query_dmabuf_mod_info(&self) -> anyhow::Result<DMAbufModifierInfo> {
let target_fourcc = 0x34324258; //XB24 let target_fourcc = 0x3432_4258; //XB24
unsafe { unsafe {
use egl_ex::PFNEGLQUERYDMABUFFORMATSEXTPROC; use egl_ex::PFNEGLQUERYDMABUFFORMATSEXTPROC;
@@ -187,13 +187,13 @@ impl EGLData {
&mut num_mods, &mut num_mods,
); );
if mods[0] == 0xFFFFFFFFFFFFFFFF { if mods[0] == 0xFFFF_FFFF_FFFF_FFFF {
anyhow::bail!("modifier is -1") anyhow::bail!("modifier is -1")
} }
log::trace!("Modifier list:"); log::trace!("Modifier list:");
for modifier in &mods { for modifier in &mods {
log::trace!("{:#x}", modifier); log::trace!("{modifier:#x}");
} }
// We should not change these modifier values. Passing all of them to the Vulkan dmabuf // We should not change these modifier values. Passing all of them to the Vulkan dmabuf
@@ -203,13 +203,13 @@ impl EGLData {
// If not, the full list of modifiers will be passed. Further testing is required. // If not, the full list of modifiers will be passed. Further testing is required.
// For now, it looks like only NAVI32-based gpus have this problem. // For now, it looks like only NAVI32-based gpus have this problem.
let mod_whitelist: [u64; 2] = [ let mod_whitelist: [u64; 2] = [
0x20000002086bf04, /* AMD RX 7800 XT, Navi32 */ 0x200_0000_2086_bf04, /* AMD RX 7800 XT, Navi32 */
0x20000001866bf04, /* AMD RX 7600 XT, Navi33 */ 0x200_0000_1866_bf04, /* AMD RX 7600 XT, Navi33 */
]; ];
for modifier in &mod_whitelist { for modifier in &mod_whitelist {
if mods.contains(modifier) { if mods.contains(modifier) {
log::warn!("Using whitelisted dmabuf tiling modifier: {:#x}", modifier); log::warn!("Using whitelisted dmabuf tiling modifier: {modifier:#x}");
mods = vec![*modifier, 0x0 /* also important (???) */]; mods = vec![*modifier, 0x0 /* also important (???) */];
break; break;
} }

View File

@@ -16,7 +16,7 @@ impl<DataType> SyncEventQueue<DataType> {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
data: Rc::new(RefCell::new(Data { data: Rc::new(RefCell::new(Data {
queue: Default::default(), queue: VecDeque::default(),
})), })),
} }
} }

View File

@@ -30,27 +30,27 @@ macro_rules! gen_id {
#[allow(dead_code)] #[allow(dead_code)]
impl $handle_name { impl $handle_name {
pub fn reset(&mut self) { pub const fn reset(&mut self) {
self.generation = 0; self.generation = 0;
} }
pub fn is_set(&self) -> bool { pub const fn is_set(&self) -> bool {
self.generation > 0 self.generation > 0
} }
pub fn id(&self) -> u32 { pub const fn id(&self) -> u32 {
self.idx self.idx
} }
pub fn new(idx: u32, generation: u64) -> Self { pub const fn new(idx: u32, generation: u64) -> Self {
Self { idx, generation } Self { idx, generation }
} }
} }
//ThingVec //ThingVec
#[allow(dead_code)] #[allow(dead_code, clippy::iter_not_returning_iterator)]
impl $container_name { impl $container_name {
pub fn new() -> Self { pub const fn new() -> Self {
Self { Self {
vec: Vec::new(), vec: Vec::new(),
cur_generation: 0, cur_generation: 0,
@@ -78,7 +78,7 @@ macro_rules! gen_id {
} }
} }
pub fn get_handle(cell: &$cell_name, idx: usize) -> $handle_name { pub const fn get_handle(cell: &$cell_name, idx: usize) -> $handle_name {
$handle_name { $handle_name {
idx: idx as u32, idx: idx as u32,
generation: cell.generation, generation: cell.generation,

View File

@@ -11,7 +11,7 @@ mod smithay_wrapper;
mod time; mod time;
mod window; mod window;
use comp::Application; use comp::Application;
use display::{DisplayInitParams, DisplayVec}; use display::{Display, DisplayInitParams, DisplayVec};
use event_queue::SyncEventQueue; use event_queue::SyncEventQueue;
use process::ProcessVec; use process::ProcessVec;
use server_ipc::WayVRServer; use server_ipc::WayVRServer;
@@ -21,7 +21,7 @@ use smithay::{
egl, egl,
renderer::{gles::GlesRenderer, ImportDma}, renderer::{gles::GlesRenderer, ImportDma},
}, },
input::SeatState, input::{keyboard::XkbConfig, SeatState},
output::{Mode, Output}, output::{Mode, Output},
reexports::wayland_server::{self, backend::ClientId}, reexports::wayland_server::{self, backend::ClientId},
wayland::{ wayland::{
@@ -43,7 +43,6 @@ use wayvr_ipc::{packet_client, packet_server};
use crate::{hid::MODS_TO_KEYS, state::AppState}; use crate::{hid::MODS_TO_KEYS, state::AppState};
const STR_INVALID_HANDLE_DISP: &str = "Invalid display handle"; const STR_INVALID_HANDLE_DISP: &str = "Invalid display handle";
const STR_INVALID_HANDLE_PROCESS: &str = "Invalid process handle";
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct WaylandEnv { pub struct WaylandEnv {
@@ -96,10 +95,10 @@ pub enum BlitMethod {
} }
impl BlitMethod { impl BlitMethod {
pub fn from_string(str: &str) -> Option<BlitMethod> { pub fn from_string(str: &str) -> Option<Self> {
match str { match str {
"dmabuf" => Some(BlitMethod::Dmabuf), "dmabuf" => Some(Self::Dmabuf),
"software" => Some(BlitMethod::Software), "software" => Some(Self::Software),
_ => None, _ => None,
} }
} }
@@ -150,6 +149,7 @@ pub enum TickTask {
} }
impl WayVR { impl WayVR {
#[allow(clippy::too_many_lines, clippy::cognitive_complexity)]
pub fn new(config: Config) -> anyhow::Result<Self> { pub fn new(config: Config) -> anyhow::Result<Self> {
log::info!("Initializing WayVR"); log::info!("Initializing WayVR");
let display: wayland_server::Display<Application> = wayland_server::Display::new()?; let display: wayland_server::Display<Application> = wayland_server::Display::new()?;
@@ -208,28 +208,32 @@ impl WayVR {
None None
} }
Err(err) => { Err(err) => {
log::warn!("dmabuf: Failed to get egl device for display: {}", err); log::warn!("dmabuf: Failed to get egl device for display: {err}");
None None
} }
}; };
let dmabuf_state = if let Some(default_feedback) = dmabuf_default_feedback { let dmabuf_state = dmabuf_default_feedback.map_or_else(
let mut dmabuf_state = DmabufState::new(); || {
let dmabuf_global = dmabuf_state.create_global_with_default_feedback::<Application>( let dmabuf_formats = gles_renderer.dmabuf_formats();
&display.handle(), let mut dmabuf_state = DmabufState::new();
&default_feedback, let dmabuf_global =
); dmabuf_state.create_global::<Application>(&display.handle(), dmabuf_formats);
(dmabuf_state, dmabuf_global, Some(default_feedback)) (dmabuf_state, dmabuf_global, None)
} else { },
let dmabuf_formats = gles_renderer.dmabuf_formats(); |default_feedback| {
let mut dmabuf_state = DmabufState::new(); let mut dmabuf_state = DmabufState::new();
let dmabuf_global = let dmabuf_global = dmabuf_state
dmabuf_state.create_global::<Application>(&display.handle(), dmabuf_formats); .create_global_with_default_feedback::<Application>(
(dmabuf_state, dmabuf_global, None) &display.handle(),
}; &default_feedback,
);
(dmabuf_state, dmabuf_global, Some(default_feedback))
},
);
let seat_keyboard = seat.add_keyboard( let seat_keyboard = seat.add_keyboard(
Default::default(), XkbConfig::default(),
config.keyboard_repeat_delay_ms as i32, config.keyboard_repeat_delay_ms as i32,
config.keyboard_repeat_rate as i32, config.keyboard_repeat_rate as i32,
)?; )?;
@@ -278,7 +282,7 @@ impl WayVR {
.state .state
.displays .displays
.get_mut(&display) .get_mut(&display)
.ok_or(anyhow::anyhow!(STR_INVALID_HANDLE_DISP))?; .ok_or_else(|| anyhow::anyhow!(STR_INVALID_HANDLE_DISP))?;
if !display.wants_redraw { if !display.wants_redraw {
// Nothing changed, do not render // Nothing changed, do not render
@@ -298,6 +302,7 @@ impl WayVR {
Ok(true) Ok(true)
} }
#[allow(clippy::too_many_lines, clippy::cognitive_complexity)]
pub fn tick_events(&mut self, app: &AppState) -> anyhow::Result<Vec<TickTask>> { pub fn tick_events(&mut self, app: &AppState) -> anyhow::Result<Vec<TickTask>> {
let mut tasks: Vec<TickTask> = Vec::new(); let mut tasks: Vec<TickTask> = Vec::new();
@@ -305,7 +310,7 @@ impl WayVR {
state: &mut self.state, state: &mut self.state,
tasks: &mut tasks, tasks: &mut tasks,
app, app,
})?; });
// Check for redraw events // Check for redraw events
self.state.displays.iter_mut(&mut |_, disp| { self.state.displays.iter_mut(&mut |_, disp| {
@@ -458,6 +463,7 @@ impl WayVR {
Ok(()) Ok(())
} }
#[allow(dead_code)]
pub fn get_primary_display(displays: &DisplayVec) -> Option<display::DisplayHandle> { pub fn get_primary_display(displays: &DisplayVec) -> Option<display::DisplayHandle> {
for (idx, cell) in displays.vec.iter().enumerate() { for (idx, cell) in displays.vec.iter().enumerate() {
if let Some(cell) = cell { if let Some(cell) = cell {
@@ -503,21 +509,12 @@ impl WayVRState {
} }
} }
pub fn send_mouse_up(&mut self, display: display::DisplayHandle, index: MouseIndex) { pub fn send_mouse_up(&mut self, index: MouseIndex) {
if let Some(display) = self.displays.get(&display) { Display::send_mouse_up(&mut self.manager, index);
display.send_mouse_up(&mut self.manager, index);
}
} }
pub fn send_mouse_scroll( pub fn send_mouse_scroll(&mut self, delta_y: f32, delta_x: f32) {
&mut self, Display::send_mouse_scroll(&mut self.manager, delta_y, delta_x);
display: display::DisplayHandle,
delta_y: f32,
delta_x: f32,
) {
if let Some(display) = self.displays.get(&display) {
display.send_mouse_scroll(&mut self.manager, delta_y, delta_x);
}
} }
pub fn send_key(&mut self, virtual_key: u32, down: bool) { pub fn send_key(&mut self, virtual_key: u32, down: bool) {
@@ -617,7 +614,7 @@ impl WayVRState {
self.manager.cleanup_clients(); self.manager.cleanup_clients();
for client in self.manager.clients.iter() { for client in &self.manager.clients {
if client.display_handle == handle { if client.display_handle == handle {
// This shouldn't happen, but make sure we are all set to destroy this display // This shouldn't happen, but make sure we are all set to destroy this display
anyhow::bail!("Wayland client still exists"); anyhow::bail!("Wayland client still exists");
@@ -684,8 +681,8 @@ impl WayVRState {
) -> process::ProcessHandle { ) -> process::ProcessHandle {
self.processes self.processes
.add(process::Process::External(process::ExternalProcess { .add(process::Process::External(process::ExternalProcess {
display_handle,
pid, pid,
display_handle,
})) }))
} }
@@ -700,7 +697,7 @@ impl WayVRState {
let display = self let display = self
.displays .displays
.get_mut(&display_handle) .get_mut(&display_handle)
.ok_or(anyhow::anyhow!(STR_INVALID_HANDLE_DISP))?; .ok_or_else(|| anyhow::anyhow!(STR_INVALID_HANDLE_DISP))?;
let res = display.spawn_process(exec_path, args, env)?; let res = display.spawn_process(exec_path, args, env)?;

View File

@@ -7,6 +7,7 @@ use crate::gen_id;
use super::display; use super::display;
#[derive(Debug)] #[derive(Debug)]
#[allow(dead_code)]
pub struct WayVRProcess { pub struct WayVRProcess {
pub auth_key: String, pub auth_key: String,
pub child: std::process::Child, pub child: std::process::Child,
@@ -32,45 +33,45 @@ pub enum Process {
} }
impl Process { impl Process {
pub fn display_handle(&self) -> display::DisplayHandle { pub const fn display_handle(&self) -> display::DisplayHandle {
match self { match self {
Process::Managed(p) => p.display_handle, Self::Managed(p) => p.display_handle,
Process::External(p) => p.display_handle, Self::External(p) => p.display_handle,
} }
} }
pub fn is_running(&mut self) -> bool { pub fn is_running(&mut self) -> bool {
match self { match self {
Process::Managed(p) => p.is_running(), Self::Managed(p) => p.is_running(),
Process::External(p) => p.is_running(), Self::External(p) => p.is_running(),
} }
} }
pub fn terminate(&mut self) { pub fn terminate(&mut self) {
match self { match self {
Process::Managed(p) => p.terminate(), Self::Managed(p) => p.terminate(),
Process::External(p) => p.terminate(), Self::External(p) => p.terminate(),
} }
} }
pub fn get_name(&self) -> String { pub fn get_name(&self) -> String {
match self { match self {
Process::Managed(p) => p.get_name().unwrap_or(String::from("unknown")), Self::Managed(p) => p.get_name().unwrap_or_else(|| String::from("unknown")),
Process::External(p) => p.get_name().unwrap_or(String::from("unknown")), Self::External(p) => p.get_name().unwrap_or_else(|| String::from("unknown")),
} }
} }
pub fn to_packet(&self, handle: ProcessHandle) -> packet_server::WvrProcess { pub fn to_packet(&self, handle: ProcessHandle) -> packet_server::WvrProcess {
match self { match self {
Process::Managed(p) => packet_server::WvrProcess { Self::Managed(p) => packet_server::WvrProcess {
name: p.get_name().unwrap_or(String::from("unknown")), name: p.get_name().unwrap_or_else(|| String::from("unknown")),
userdata: p.userdata.clone(), userdata: p.userdata.clone(),
display_handle: p.display_handle.as_packet(), display_handle: p.display_handle.as_packet(),
handle: handle.as_packet(), handle: handle.as_packet(),
}, },
Process::External(p) => packet_server::WvrProcess { Self::External(p) => packet_server::WvrProcess {
name: p.get_name().unwrap_or(String::from("unknown")), name: p.get_name().unwrap_or_else(|| String::from("unknown")),
userdata: Default::default(), userdata: HashMap::default(),
display_handle: p.display_handle.as_packet(), display_handle: p.display_handle.as_packet(),
handle: handle.as_packet(), handle: handle.as_packet(),
}, },
@@ -89,7 +90,7 @@ impl Drop for WayVRProcess {
} }
fn get_process_env_value(pid: i32, key: &str) -> anyhow::Result<Option<String>> { fn get_process_env_value(pid: i32, key: &str) -> anyhow::Result<Option<String>> {
let path = format!("/proc/{}/environ", pid); let path = format!("/proc/{pid}/environ");
let mut env_data = String::new(); let mut env_data = String::new();
std::fs::File::open(path)?.read_to_string(&mut env_data)?; std::fs::File::open(path)?.read_to_string(&mut env_data)?;
let lines: Vec<&str> = env_data.split('\0').filter(|s| !s.is_empty()).collect(); let lines: Vec<&str> = env_data.split('\0').filter(|s| !s.is_empty()).collect();
@@ -112,7 +113,7 @@ impl WayVRProcess {
Ok(None) => true, Ok(None) => true,
Err(e) => { Err(e) => {
// this shouldn't happen // this shouldn't happen
log::error!("Child::try_wait failed: {}", e); log::error!("Child::try_wait failed: {e}");
false false
} }
} }
@@ -131,7 +132,7 @@ impl WayVRProcess {
} }
fn get_exec_name_from_pid(pid: u32) -> Option<String> { fn get_exec_name_from_pid(pid: u32) -> Option<String> {
let path = format!("/proc/{}/exe", pid); let path = format!("/proc/{pid}/exe");
match std::fs::read_link(&path) { match std::fs::read_link(&path) {
Ok(buf) => { Ok(buf) => {
if let Some(process_name) = buf.file_name().and_then(|s| s.to_str()) { if let Some(process_name) = buf.file_name().and_then(|s| s.to_str()) {
@@ -170,7 +171,7 @@ impl ExternalProcess {
gen_id!(ProcessVec, Process, ProcessCell, ProcessHandle); gen_id!(ProcessVec, Process, ProcessCell, ProcessHandle);
pub fn find_by_pid(processes: &ProcessVec, pid: u32) -> Option<ProcessHandle> { pub fn find_by_pid(processes: &ProcessVec, pid: u32) -> Option<ProcessHandle> {
log::debug!("Finding process with PID {}", pid); log::debug!("Finding process with PID {pid}");
for (idx, cell) in processes.vec.iter().enumerate() { for (idx, cell) in processes.vec.iter().enumerate() {
let Some(cell) = cell else { let Some(cell) = cell else {
@@ -205,19 +206,19 @@ pub fn find_by_pid(processes: &ProcessVec, pid: u32) -> Option<ProcessHandle> {
} }
} }
log::debug!("Process find with PID {} failed", pid); log::debug!("Process find with PID {pid} failed");
None None
} }
impl ProcessHandle { impl ProcessHandle {
pub fn from_packet(handle: packet_server::WvrProcessHandle) -> Self { pub const fn from_packet(handle: packet_server::WvrProcessHandle) -> Self {
Self { Self {
generation: handle.generation, generation: handle.generation,
idx: handle.idx, idx: handle.idx,
} }
} }
pub fn as_packet(&self) -> packet_server::WvrProcessHandle { pub const fn as_packet(&self) -> packet_server::WvrProcessHandle {
packet_server::WvrProcessHandle { packet_server::WvrProcessHandle {
idx: self.idx, idx: self.idx,
generation: self.generation, generation: self.generation,

View File

@@ -44,11 +44,11 @@ fn read_check(expected_size: u32, res: std::io::Result<usize>) -> bool {
if count == 0 { if count == 0 {
return false; return false;
} }
if count as u32 != expected_size { if count as u32 == expected_size {
log::error!("count {} is not {}", count, expected_size);
false
} else {
true // read succeeded true // read succeeded
} else {
log::error!("count {count} is not {expected_size}");
false
} }
} }
Err(_e) => { Err(_e) => {
@@ -63,10 +63,10 @@ type Payload = SmallVec<[u8; 64]>;
fn read_payload(conn: &mut local_socket::Stream, size: u32) -> Option<Payload> { fn read_payload(conn: &mut local_socket::Stream, size: u32) -> Option<Payload> {
let mut payload = Payload::new(); let mut payload = Payload::new();
payload.resize(size as usize, 0); payload.resize(size as usize, 0);
if !read_check(size, conn.read(&mut payload)) { if read_check(size, conn.read(&mut payload)) {
None
} else {
Some(payload) Some(payload)
} else {
None
} }
} }
@@ -89,7 +89,7 @@ pub fn gen_env_vec(input: &[String]) -> Vec<(&str, &str)> {
} }
impl Connection { impl Connection {
fn new(conn: local_socket::Stream) -> Self { const fn new(conn: local_socket::Stream) -> Self {
Self { Self {
conn, conn,
alive: true, alive: true,
@@ -222,10 +222,9 @@ impl Connection {
false, false,
)?; )?;
params.tasks.push(TickTask::NewDisplay( params
packet_params.clone(), .tasks
Some(display_handle), .push(TickTask::NewDisplay(packet_params, Some(display_handle)));
));
send_packet( send_packet(
&mut self.conn, &mut self.conn,
@@ -246,7 +245,7 @@ impl Connection {
let res = params let res = params
.state .state
.destroy_display(display::DisplayHandle::from_packet(handle)) .destroy_display(display::DisplayHandle::from_packet(handle))
.map_err(|e| format!("{:?}", e)); .map_err(|e| format!("{e:?}"));
send_packet( send_packet(
&mut self.conn, &mut self.conn,
@@ -256,29 +255,25 @@ impl Connection {
} }
fn handle_wvr_display_set_visible( fn handle_wvr_display_set_visible(
&mut self,
params: &mut TickParams, params: &mut TickParams,
handle: packet_server::WvrDisplayHandle, handle: packet_server::WvrDisplayHandle,
visible: bool, visible: bool,
) -> anyhow::Result<()> { ) {
params.state.signals.send(WayVRSignal::DisplayVisibility( params.state.signals.send(WayVRSignal::DisplayVisibility(
display::DisplayHandle::from_packet(handle), display::DisplayHandle::from_packet(handle),
visible, visible,
)); ));
Ok(())
} }
fn handle_wvr_display_set_window_layout( fn handle_wvr_display_set_window_layout(
&mut self,
params: &mut TickParams, params: &mut TickParams,
handle: packet_server::WvrDisplayHandle, handle: packet_server::WvrDisplayHandle,
layout: packet_server::WvrDisplayWindowLayout, layout: packet_server::WvrDisplayWindowLayout,
) -> anyhow::Result<()> { ) {
params.state.signals.send(WayVRSignal::DisplayWindowLayout( params.state.signals.send(WayVRSignal::DisplayWindowLayout(
display::DisplayHandle::from_packet(handle), display::DisplayHandle::from_packet(handle),
layout, layout,
)); ));
Ok(())
} }
fn handle_wvr_display_window_list( fn handle_wvr_display_window_list(
@@ -331,11 +326,10 @@ impl Connection {
} }
fn handle_wvr_window_set_visible( fn handle_wvr_window_set_visible(
&mut self,
params: &mut TickParams, params: &mut TickParams,
handle: packet_server::WvrWindowHandle, handle: packet_server::WvrWindowHandle,
visible: bool, visible: bool,
) -> anyhow::Result<()> { ) {
let mut to_resize = None; let mut to_resize = None;
if let Some(window) = params if let Some(window) = params
@@ -355,8 +349,6 @@ impl Connection {
display.trigger_rerender(); display.trigger_rerender();
} }
} }
Ok(())
} }
fn handle_wvr_process_launch( fn handle_wvr_process_launch(
@@ -392,7 +384,7 @@ impl Connection {
serial: ipc::Serial, serial: ipc::Serial,
display_handle: packet_server::WvrDisplayHandle, display_handle: packet_server::WvrDisplayHandle,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
let native_handle = &display::DisplayHandle::from_packet(display_handle.clone()); let native_handle = &display::DisplayHandle::from_packet(display_handle);
let disp = params let disp = params
.state .state
.displays .displays
@@ -440,20 +432,17 @@ impl Connection {
// This request doesn't return anything to the client // This request doesn't return anything to the client
fn handle_wvr_process_terminate( fn handle_wvr_process_terminate(
&mut self,
params: &mut TickParams, params: &mut TickParams,
process_handle: packet_server::WvrProcessHandle, process_handle: packet_server::WvrProcessHandle,
) -> anyhow::Result<()> { ) {
let native_handle = &process::ProcessHandle::from_packet(process_handle.clone()); let native_handle = &process::ProcessHandle::from_packet(process_handle);
let process = params.state.processes.get_mut(native_handle); let process = params.state.processes.get_mut(native_handle);
let Some(process) = process else { let Some(process) = process else {
return Ok(()); return;
}; };
process.terminate(); process.terminate();
Ok(())
} }
fn handle_wvr_process_get( fn handle_wvr_process_get(
@@ -462,7 +451,7 @@ impl Connection {
serial: ipc::Serial, serial: ipc::Serial,
process_handle: packet_server::WvrProcessHandle, process_handle: packet_server::WvrProcessHandle,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
let native_handle = &process::ProcessHandle::from_packet(process_handle.clone()); let native_handle = &process::ProcessHandle::from_packet(process_handle);
let process = params let process = params
.state .state
.processes .processes
@@ -478,10 +467,9 @@ impl Connection {
} }
fn handle_wlx_haptics( fn handle_wlx_haptics(
&mut self,
params: &mut TickParams, params: &mut TickParams,
haptics_params: packet_client::WlxHapticsParams, haptics_params: packet_client::WlxHapticsParams,
) -> anyhow::Result<()> { ) {
params params
.state .state
.tasks .tasks
@@ -490,7 +478,6 @@ impl Connection {
frequency: haptics_params.frequency, frequency: haptics_params.frequency,
intensity: haptics_params.intensity, intensity: haptics_params.intensity,
})); }));
Ok(())
} }
fn process_payload(&mut self, params: &mut TickParams, payload: Payload) -> anyhow::Result<()> { fn process_payload(&mut self, params: &mut TickParams, payload: Payload) -> anyhow::Result<()> {
@@ -516,16 +503,16 @@ impl Connection {
self.handle_wvr_display_remove(params, serial, display_handle)?; self.handle_wvr_display_remove(params, serial, display_handle)?;
} }
PacketClient::WvrDisplaySetVisible(display_handle, visible) => { PacketClient::WvrDisplaySetVisible(display_handle, visible) => {
self.handle_wvr_display_set_visible(params, display_handle, visible)?; Self::handle_wvr_display_set_visible(params, display_handle, visible);
} }
PacketClient::WvrDisplaySetWindowLayout(display_handle, layout) => { PacketClient::WvrDisplaySetWindowLayout(display_handle, layout) => {
self.handle_wvr_display_set_window_layout(params, display_handle, layout)?; Self::handle_wvr_display_set_window_layout(params, display_handle, layout);
} }
PacketClient::WvrDisplayWindowList(serial, display_handle) => { PacketClient::WvrDisplayWindowList(serial, display_handle) => {
self.handle_wvr_display_window_list(params, serial, display_handle)?; self.handle_wvr_display_window_list(params, serial, display_handle)?;
} }
PacketClient::WvrWindowSetVisible(window_handle, visible) => { PacketClient::WvrWindowSetVisible(window_handle, visible) => {
self.handle_wvr_window_set_visible(params, window_handle, visible)?; Self::handle_wvr_window_set_visible(params, window_handle, visible);
} }
PacketClient::WvrProcessGet(serial, process_handle) => { PacketClient::WvrProcessGet(serial, process_handle) => {
self.handle_wvr_process_get(params, serial, process_handle)?; self.handle_wvr_process_get(params, serial, process_handle)?;
@@ -540,10 +527,10 @@ impl Connection {
self.handle_wvr_display_create(params, serial, packet_params)?; self.handle_wvr_display_create(params, serial, packet_params)?;
} }
PacketClient::WvrProcessTerminate(process_handle) => { PacketClient::WvrProcessTerminate(process_handle) => {
self.handle_wvr_process_terminate(params, process_handle)?; Self::handle_wvr_process_terminate(params, process_handle);
} }
PacketClient::WlxHaptics(haptics_params) => { PacketClient::WlxHaptics(haptics_params) => {
self.handle_wlx_haptics(params, haptics_params)?; Self::handle_wlx_haptics(params, haptics_params);
} }
} }
@@ -554,9 +541,9 @@ impl Connection {
log::debug!("payload size {}", payload.len()); log::debug!("payload size {}", payload.len());
if let Err(e) = self.process_payload(params, payload) { if let Err(e) = self.process_payload(params, payload) {
log::error!("Invalid payload from the client, closing connection: {}", e); log::error!("Invalid payload from the client, closing connection: {e}");
// send also error message directly to the client before disconnecting // send also error message directly to the client before disconnecting
self.kill(format!("{}", e).as_str()); self.kill(format!("{e}").as_str());
false false
} else { } else {
true true
@@ -589,8 +576,7 @@ impl Connection {
if payload_size > size_limit { if payload_size > size_limit {
// over 128 KiB? // over 128 KiB?
log::error!( log::error!(
"Client sent a packet header with the size over {} bytes, closing connection.", "Client sent a packet header with the size over {size_limit} bytes, closing connection."
size_limit
); );
self.kill("Too big packet received (over 128 KiB)"); self.kill("Too big packet received (over 128 KiB)");
return false; return false;
@@ -637,7 +623,7 @@ impl WayVRServer {
Err(e) => anyhow::bail!("Failed to start WayVRServer IPC listener. Reason: {}", e), Err(e) => anyhow::bail!("Failed to start WayVRServer IPC listener. Reason: {}", e),
}; };
log::info!("WayVRServer IPC running at {}", printname); log::info!("WayVRServer IPC running at {printname}");
Ok(Self { Ok(Self {
listener, listener,
@@ -662,16 +648,15 @@ impl WayVRServer {
self.connections.retain(|c| c.alive); self.connections.retain(|c| c.alive);
} }
pub fn tick(&mut self, params: &mut TickParams) -> anyhow::Result<()> { pub fn tick(&mut self, params: &mut TickParams) {
self.accept_connections(); self.accept_connections();
self.tick_connections(params); self.tick_connections(params);
Ok(())
} }
pub fn broadcast(&mut self, packet: packet_server::PacketServer) { pub fn broadcast(&mut self, packet: packet_server::PacketServer) {
for connection in &mut self.connections { for connection in &mut self.connections {
if let Err(e) = send_packet(&mut connection.conn, &ipc::data_encode(&packet)) { if let Err(e) = send_packet(&mut connection.conn, &ipc::data_encode(&packet)) {
log::error!("failed to broadcast packet: {:?}", e); log::error!("failed to broadcast packet: {e:?}");
} }
} }
} }

View File

@@ -29,7 +29,7 @@ impl Window {
} }
} }
pub fn set_pos(&mut self, pos_x: i32, pos_y: i32) { pub const fn set_pos(&mut self, pos_x: i32, pos_y: i32) {
self.pos_x = pos_x; self.pos_x = pos_x;
self.pos_y = pos_y; self.pos_y = pos_y;
} }
@@ -52,7 +52,7 @@ pub struct WindowManager {
} }
impl WindowManager { impl WindowManager {
pub fn new() -> Self { pub const fn new() -> Self {
Self { Self {
windows: WindowVec::new(), windows: WindowVec::new(),
} }
@@ -86,14 +86,14 @@ impl WindowManager {
gen_id!(WindowVec, Window, WindowCell, WindowHandle); gen_id!(WindowVec, Window, WindowCell, WindowHandle);
impl WindowHandle { impl WindowHandle {
pub fn from_packet(handle: packet_server::WvrWindowHandle) -> Self { pub const fn from_packet(handle: packet_server::WvrWindowHandle) -> Self {
Self { Self {
generation: handle.generation, generation: handle.generation,
idx: handle.idx, idx: handle.idx,
} }
} }
pub fn as_packet(&self) -> packet_server::WvrWindowHandle { pub const fn as_packet(&self) -> packet_server::WvrWindowHandle {
packet_server::WvrWindowHandle { packet_server::WvrWindowHandle {
idx: self.idx, idx: self.idx,
generation: self.generation, generation: self.generation,

View File

@@ -69,79 +69,76 @@ impl AStrSetExt for AStrSet {
fn arc_rm(&mut self, value: &str) -> bool { fn arc_rm(&mut self, value: &str) -> bool {
let index = self.iter().position(|v| v.as_ref().eq(value)); let index = self.iter().position(|v| v.as_ref().eq(value));
index index.is_some_and(|i| {
.map(|i| { self.remove(i);
self.remove(i); true
true })
})
.unwrap_or(false)
} }
} }
pub type PwTokenMap = AStrMap<String>; pub type PwTokenMap = AStrMap<String>;
pub fn def_watch_pos() -> Vec3A { pub const fn def_watch_pos() -> Vec3A {
vec3a(-0.03, -0.01, 0.125) vec3a(-0.03, -0.01, 0.125)
} }
pub fn def_watch_rot() -> Quat { pub const fn def_watch_rot() -> Quat {
Quat::from_xyzw(-0.7071066, 0.0007963618, 0.7071066, 0.0) Quat::from_xyzw(-0.707_106_6, 0.000_796_361_8, 0.707_106_6, 0.0)
} }
pub fn def_left() -> LeftRight { pub const fn def_left() -> LeftRight {
LeftRight::Left LeftRight::Left
} }
pub fn def_pw_tokens() -> PwTokenMap { pub const fn def_pw_tokens() -> PwTokenMap {
AStrMap::new() AStrMap::new()
} }
fn def_mouse_move_interval_ms() -> u32 { const fn def_mouse_move_interval_ms() -> u32 {
10 // 100fps 10 // 100fps
} }
fn def_click_freeze_time_ms() -> u32 { const fn def_click_freeze_time_ms() -> u32 {
300 300
} }
pub fn def_true() -> bool { pub const fn def_true() -> bool {
true true
} }
fn def_false() -> bool { const fn def_false() -> bool {
false false
} }
fn def_one() -> f32 { const fn def_one() -> f32 {
1.0 1.0
} }
pub fn def_half() -> f32 { pub const fn def_half() -> f32 {
0.5 0.5
} }
pub fn def_point7() -> f32 { pub const fn def_point7() -> f32 {
0.7 0.7
} }
pub fn def_point3() -> f32 { pub const fn def_point3() -> f32 {
0.3 0.3
} }
fn def_osc_port() -> u16 { const fn def_osc_port() -> u16 {
9000 9000
} }
fn def_empty_vec_string() -> Vec<String> { const fn def_empty_vec_string() -> Vec<String> {
Vec::new() Vec::new()
} }
fn def_timezones() -> Vec<String> { fn def_timezones() -> Vec<String> {
let offset = chrono::Local::now().offset().fix();
const EMEA: i32 = -60 * 60; // UTC-1 const EMEA: i32 = -60 * 60; // UTC-1
const APAC: i32 = 5 * 60 * 60; // UTC+5 const APAC: i32 = 5 * 60 * 60; // UTC+5
let offset = chrono::Local::now().offset().fix();
match offset.local_minus_utc() { match offset.local_minus_utc() {
i32::MIN..EMEA => vec!["Europe/Paris".into(), "Asia/Tokyo".into()], i32::MIN..EMEA => vec!["Europe/Paris".into(), "Asia/Tokyo".into()],
EMEA..APAC => vec!["America/New_York".into(), "Asia/Tokyo".into()], EMEA..APAC => vec!["America/New_York".into(), "Asia/Tokyo".into()],
@@ -149,15 +146,15 @@ fn def_timezones() -> Vec<String> {
} }
} }
fn def_screens() -> AStrSet { const fn def_screens() -> AStrSet {
AStrSet::new() AStrSet::new()
} }
fn def_curve_values() -> AStrMap<f32> { const fn def_curve_values() -> AStrMap<f32> {
AStrMap::new() AStrMap::new()
} }
fn def_transforms() -> AStrMap<Affine3A> { const fn def_transforms() -> AStrMap<Affine3A> {
AStrMap::new() AStrMap::new()
} }
@@ -177,7 +174,7 @@ fn def_font() -> Arc<str> {
"LiberationSans:style=Bold".into() "LiberationSans:style=Bold".into()
} }
fn def_max_height() -> u16 { const fn def_max_height() -> u16 {
1440 1440
} }
@@ -294,7 +291,7 @@ pub struct GeneralConfig {
#[serde(default = "def_max_height")] #[serde(default = "def_max_height")]
pub screen_max_height: u16, pub screen_max_height: u16,
#[serde(default = "def_true")] #[serde(default = "def_false")]
pub screen_render_down: bool, pub screen_render_down: bool,
#[serde(default = "def_point3")] #[serde(default = "def_point3")]
@@ -315,23 +312,21 @@ pub struct GeneralConfig {
impl GeneralConfig { impl GeneralConfig {
fn sanitize_range(name: &str, val: f32, from: f32, to: f32) { fn sanitize_range(name: &str, val: f32, from: f32, to: f32) {
if !val.is_normal() || val < from || val > to { assert!(
panic!( !(!val.is_normal() || val < from || val > to),
"GeneralConfig: {} needs to be between {} and {}", "GeneralConfig: {name} needs to be between {from} and {to}"
name, from, to );
);
}
} }
pub fn load_from_disk() -> GeneralConfig { pub fn load_from_disk() -> Self {
let config = load_general(); let config = load_general();
config.post_load(); config.post_load();
config config
} }
fn post_load(&self) { fn post_load(&self) {
GeneralConfig::sanitize_range("keyboard_scale", self.keyboard_scale, 0.05, 5.0); Self::sanitize_range("keyboard_scale", self.keyboard_scale, 0.05, 5.0);
GeneralConfig::sanitize_range("desktop_view_scale", self.desktop_view_scale, 0.05, 5.0); Self::sanitize_range("desktop_view_scale", self.desktop_view_scale, 0.05, 5.0);
} }
} }
@@ -374,8 +369,8 @@ where
match serde_yaml::from_str::<T>(yaml) { match serde_yaml::from_str::<T>(yaml) {
Ok(d) => return d, Ok(d) => return d,
Err(e) => { Err(e) => {
error!("Failed to parse {}, falling back to defaults.", file_name); error!("Failed to parse {file_name}, falling back to defaults.");
error!("{}", e); error!("{e}");
} }
} }
} }
@@ -384,7 +379,7 @@ where
} }
pub fn load_custom_ui(name: &str) -> anyhow::Result<ModularUiConfig> { pub fn load_custom_ui(name: &str) -> anyhow::Result<ModularUiConfig> {
let filename = format!("{}.yaml", name); let filename = format!("{name}.yaml");
let Some(yaml_data) = config_io::load(&filename) else { let Some(yaml_data) = config_io::load(&filename) else {
bail!("Could not read file at {}", &filename); bail!("Could not read file at {}", &filename);
}; };
@@ -416,13 +411,13 @@ where
.filter_map(|r| match r { .filter_map(|r| match r {
Ok(entry) => Some(entry), Ok(entry) => Some(entry),
Err(e) => { Err(e) => {
error!("Failed to read conf.d directory: {}", e); error!("Failed to read conf.d directory: {e}");
None None
} }
}) })
.collect(); .collect();
// Sort paths alphabetically // Sort paths alphabetically
paths.sort_by_key(|dir| dir.path()); paths.sort_by_key(std::fs::DirEntry::path);
for path in paths { for path in paths {
log::info!("Loading config file: {}", path.path().to_string_lossy()); log::info!("Loading config file: {}", path.path().to_string_lossy());
settings_builder = settings_builder.add_source(File::from(path.path())); settings_builder = settings_builder.add_source(File::from(path.path()));
@@ -433,11 +428,11 @@ where
Ok(settings) => match settings.try_deserialize::<ConfigData>() { Ok(settings) => match settings.try_deserialize::<ConfigData>() {
Ok(config) => config, Ok(config) => config,
Err(e) => { Err(e) => {
panic!("Failed to deserialize settings: {}", e); panic!("Failed to deserialize settings: {e}");
} }
}, },
Err(e) => { Err(e) => {
panic!("Failed to build settings: {}", e); panic!("Failed to build settings: {e}");
} }
} }
} }

View File

@@ -18,8 +18,7 @@ static CONFIG_ROOT_PATH: Lazy<PathBuf> = Lazy::new(|| {
} }
//Return fallback config path //Return fallback config path
error!( error!(
"Err: Failed to find config path, using {}", "Err: Failed to find config path, using {FALLBACK_CONFIG_PATH}"
FALLBACK_CONFIG_PATH
); );
PathBuf::from(FALLBACK_CONFIG_PATH) PathBuf::from(FALLBACK_CONFIG_PATH)
}); });
@@ -31,8 +30,8 @@ pub fn get_config_root() -> PathBuf {
impl ConfigRoot { impl ConfigRoot {
pub fn get_conf_d_path(&self) -> PathBuf { pub fn get_conf_d_path(&self) -> PathBuf {
get_config_root().join(match self { get_config_root().join(match self {
ConfigRoot::Generic => "conf.d", Self::Generic => "conf.d",
ConfigRoot::WayVR => "wayvr.conf.d", Self::WayVR => "wayvr.conf.d",
}) })
} }

View File

@@ -33,23 +33,23 @@ pub enum AttachTo {
} }
impl AttachTo { impl AttachTo {
pub fn get_relative_to(&self) -> RelativeTo { pub const fn get_relative_to(&self) -> RelativeTo {
match self { match self {
AttachTo::None => RelativeTo::None, Self::None => RelativeTo::None,
AttachTo::HandLeft => RelativeTo::Hand(0), Self::HandLeft => RelativeTo::Hand(0),
AttachTo::HandRight => RelativeTo::Hand(1), Self::HandRight => RelativeTo::Hand(1),
AttachTo::Stage => RelativeTo::Stage, Self::Stage => RelativeTo::Stage,
AttachTo::Head => RelativeTo::Head, Self::Head => RelativeTo::Head,
} }
} }
pub fn from_packet(input: &wayvr_ipc::packet_client::AttachTo) -> AttachTo { pub const fn from_packet(input: &wayvr_ipc::packet_client::AttachTo) -> Self {
match input { match input {
wayvr_ipc::packet_client::AttachTo::None => AttachTo::None, wayvr_ipc::packet_client::AttachTo::None => Self::None,
wayvr_ipc::packet_client::AttachTo::HandLeft => AttachTo::HandLeft, wayvr_ipc::packet_client::AttachTo::HandLeft => Self::HandLeft,
wayvr_ipc::packet_client::AttachTo::HandRight => AttachTo::HandRight, wayvr_ipc::packet_client::AttachTo::HandRight => Self::HandRight,
wayvr_ipc::packet_client::AttachTo::Head => AttachTo::Head, wayvr_ipc::packet_client::AttachTo::Head => Self::Head,
wayvr_ipc::packet_client::AttachTo::Stage => AttachTo::Stage, wayvr_ipc::packet_client::AttachTo::Stage => Self::Stage,
} }
} }
} }
@@ -92,23 +92,23 @@ impl WayVRCatalog {
} }
} }
fn def_false() -> bool { const fn def_false() -> bool {
false false
} }
fn def_true() -> bool { const fn def_true() -> bool {
true true
} }
fn def_autohide_delay() -> u32 { const fn def_autohide_delay() -> u32 {
750 750
} }
fn def_keyboard_repeat_delay() -> u32 { const fn def_keyboard_repeat_delay() -> u32 {
200 200
} }
fn def_keyboard_repeat_rate() -> u32 { const fn def_keyboard_repeat_rate() -> u32 {
50 50
} }
@@ -173,14 +173,14 @@ impl WayVRConfig {
pub fn get_wayvr_config( pub fn get_wayvr_config(
config_general: &crate::config::GeneralConfig, config_general: &crate::config::GeneralConfig,
config_wayvr: &crate::config_wayvr::WayVRConfig, config_wayvr: &Self,
) -> anyhow::Result<wayvr::Config> { ) -> anyhow::Result<wayvr::Config> {
Ok(wayvr::Config { Ok(wayvr::Config {
click_freeze_time_ms: config_general.click_freeze_time_ms, click_freeze_time_ms: config_general.click_freeze_time_ms,
keyboard_repeat_delay_ms: config_wayvr.keyboard_repeat_delay, keyboard_repeat_delay_ms: config_wayvr.keyboard_repeat_delay,
keyboard_repeat_rate: config_wayvr.keyboard_repeat_rate, keyboard_repeat_rate: config_wayvr.keyboard_repeat_rate,
blit_method: wayvr::BlitMethod::from_string(&config_wayvr.blit_method) blit_method: wayvr::BlitMethod::from_string(&config_wayvr.blit_method)
.ok_or(anyhow::anyhow!("Unknown blit method"))?, .ok_or_else(|| anyhow::anyhow!("Unknown blit method"))?,
auto_hide_delay: if config_wayvr.auto_hide { auto_hide_delay: if config_wayvr.auto_hide {
Some(config_wayvr.auto_hide_delay) Some(config_wayvr.auto_hide_delay)
} else { } else {
@@ -235,7 +235,7 @@ impl WayVRConfig {
pub fn load_wayvr() -> WayVRConfig { pub fn load_wayvr() -> WayVRConfig {
let config_root_path = config_io::ConfigRoot::WayVR.ensure_dir(); let config_root_path = config_io::ConfigRoot::WayVR.ensure_dir();
log::info!("WayVR Config root path: {:?}", config_root_path); log::info!("WayVR Config root path: {config_root_path:?}");
log::info!( log::info!(
"WayVR conf.d path: {:?}", "WayVR conf.d path: {:?}",
config_io::ConfigRoot::WayVR.get_conf_d_path() config_io::ConfigRoot::WayVR.get_conf_d_path()

View File

@@ -1,4 +1,4 @@
pub(crate) mod dds; pub mod dds;
use std::{ use std::{
collections::HashMap, collections::HashMap,
@@ -128,7 +128,7 @@ pub struct WlxGraphics {
pub shared_shaders: RwLock<HashMap<&'static str, Arc<ShaderModule>>>, pub shared_shaders: RwLock<HashMap<&'static str, Arc<ShaderModule>>>,
} }
fn get_dmabuf_extensions() -> DeviceExtensions { const fn get_dmabuf_extensions() -> DeviceExtensions {
DeviceExtensions { DeviceExtensions {
khr_external_memory: true, khr_external_memory: true,
khr_external_memory_fd: true, khr_external_memory_fd: true,
@@ -155,14 +155,17 @@ unsafe extern "system" fn get_instance_proc_addr(
impl WlxGraphics { impl WlxGraphics {
#[cfg(feature = "openxr")] #[cfg(feature = "openxr")]
#[allow(clippy::too_many_lines)]
pub fn new_openxr( pub fn new_openxr(
xr_instance: openxr::Instance, xr_instance: openxr::Instance,
system: openxr::SystemId, system: openxr::SystemId,
) -> anyhow::Result<Arc<Self>> { ) -> anyhow::Result<Arc<Self>> {
use std::ffi::{self, c_char, CString}; use std::ffi::{self, CString};
use ash::vk::PhysicalDeviceDynamicRenderingFeatures; use ash::vk::PhysicalDeviceDynamicRenderingFeatures;
use vulkano::{Handle, Version}; use vulkano::{
descriptor_set::allocator::StandardDescriptorSetAllocatorCreateInfo, Handle, Version,
};
let instance_extensions = InstanceExtensions { let instance_extensions = InstanceExtensions {
khr_get_physical_device_properties2: true, khr_get_physical_device_properties2: true,
@@ -173,7 +176,7 @@ impl WlxGraphics {
.into_iter() .into_iter()
.filter_map(|(name, enabled)| { .filter_map(|(name, enabled)| {
if enabled { if enabled {
Some(ffi::CString::new(name).unwrap().into_raw() as *const c_char) Some(ffi::CString::new(name).unwrap().into_raw().cast_const())
// want panic // want panic
} else { } else {
None None
@@ -195,10 +198,12 @@ impl WlxGraphics {
.create_vulkan_instance( .create_vulkan_instance(
system, system,
get_instance_proc_addr, get_instance_proc_addr,
&vk::InstanceCreateInfo::builder() std::ptr::from_ref(
.application_info(&vk_app_info_raw) &vk::InstanceCreateInfo::builder()
.enabled_extension_names(&instance_extensions_raw) .application_info(&vk_app_info_raw)
as *const _ as *const _, .enabled_extension_names(&instance_extensions_raw),
)
.cast(),
) )
.expect("XR error creating Vulkan instance") .expect("XR error creating Vulkan instance")
.map_err(vk::Result::from_raw) .map_err(vk::Result::from_raw)
@@ -228,12 +233,10 @@ impl WlxGraphics {
}?; }?;
let vk_device_properties = physical_device.properties(); let vk_device_properties = physical_device.properties();
if vk_device_properties.api_version < target_version { assert!(
panic!( (vk_device_properties.api_version >= target_version),
"Vulkan physical device doesn't support Vulkan {}", "Vulkan physical device doesn't support Vulkan {target_version}"
target_version );
);
}
log::info!( log::info!(
"Using vkPhysicalDevice: {}", "Using vkPhysicalDevice: {}",
@@ -268,7 +271,7 @@ impl WlxGraphics {
.into_iter() .into_iter()
.filter_map(|(name, enabled)| { .filter_map(|(name, enabled)| {
if enabled { if enabled {
Some(ffi::CString::new(name).unwrap().into_raw() as *const c_char) Some(ffi::CString::new(name).unwrap().into_raw().cast_const())
// want panic // want panic
} else { } else {
None None
@@ -296,8 +299,8 @@ impl WlxGraphics {
let mut dynamic_rendering = let mut dynamic_rendering =
PhysicalDeviceDynamicRenderingFeatures::builder().dynamic_rendering(true); PhysicalDeviceDynamicRenderingFeatures::builder().dynamic_rendering(true);
dynamic_rendering.p_next = device_create_info.p_next as _; dynamic_rendering.p_next = device_create_info.p_next.cast_mut();
device_create_info.p_next = (&mut dynamic_rendering) as *const _ as *const c_void; device_create_info.p_next = &raw mut dynamic_rendering as *const c_void;
let texture_filtering = if physical_device.supported_extensions().ext_filter_cubic { let texture_filtering = if physical_device.supported_extensions().ext_filter_cubic {
Filter::Cubic Filter::Cubic
@@ -311,7 +314,7 @@ impl WlxGraphics {
system, system,
get_instance_proc_addr, get_instance_proc_addr,
physical_device.handle().as_raw() as _, physical_device.handle().as_raw() as _,
(&device_create_info) as *const _ as *const _, (&raw const device_create_info).cast(),
) )
.expect("XR error creating Vulkan device") .expect("XR error creating Vulkan device")
.map_err(vk::Result::from_raw) .map_err(vk::Result::from_raw)
@@ -346,7 +349,7 @@ impl WlxGraphics {
device_extensions_raw device_extensions_raw
.into_iter() .into_iter()
.for_each(|c_string| unsafe { .for_each(|c_string| unsafe {
let _ = CString::from_raw(c_string as _); let _ = CString::from_raw(c_string.cast_mut());
}); });
let queue = queues let queue = queues
@@ -363,7 +366,7 @@ impl WlxGraphics {
)); ));
let descriptor_set_allocator = Arc::new(StandardDescriptorSetAllocator::new( let descriptor_set_allocator = Arc::new(StandardDescriptorSetAllocator::new(
device.clone(), device.clone(),
Default::default(), StandardDescriptorSetAllocatorCreateInfo::default(),
)); ));
let (quad_verts, quad_indices) = Self::default_quad(memory_allocator.clone())?; let (quad_verts, quad_indices) = Self::default_quad(memory_allocator.clone())?;
@@ -385,6 +388,7 @@ impl WlxGraphics {
Ok(Arc::new(me)) Ok(Arc::new(me))
} }
#[allow(clippy::too_many_lines)]
#[cfg(feature = "openvr")] #[cfg(feature = "openvr")]
pub fn new_openvr( pub fn new_openvr(
mut vk_instance_extensions: InstanceExtensions, mut vk_instance_extensions: InstanceExtensions,
@@ -394,6 +398,8 @@ impl WlxGraphics {
//let layers = vec!["VK_LAYER_KHRONOS_validation".to_owned()]; //let layers = vec!["VK_LAYER_KHRONOS_validation".to_owned()];
//#[cfg(not(debug_assertions))] //#[cfg(not(debug_assertions))]
use vulkano::descriptor_set::allocator::StandardDescriptorSetAllocatorCreateInfo;
let layers = vec![]; let layers = vec![];
log::debug!("Instance exts for runtime: {:?}", &vk_instance_extensions); log::debug!("Instance exts for runtime: {:?}", &vk_instance_extensions);
@@ -424,7 +430,7 @@ impl WlxGraphics {
); );
for (ext, missing) in p.supported_extensions().difference(&my_extensions) { for (ext, missing) in p.supported_extensions().difference(&my_extensions) {
if missing { if missing {
log::debug!(" {}", ext); log::debug!(" {ext}");
} }
} }
return None; return None;
@@ -514,7 +520,7 @@ impl WlxGraphics {
)); ));
let descriptor_set_allocator = Arc::new(StandardDescriptorSetAllocator::new( let descriptor_set_allocator = Arc::new(StandardDescriptorSetAllocator::new(
device.clone(), device.clone(),
Default::default(), StandardDescriptorSetAllocatorCreateInfo::default(),
)); ));
let (quad_verts, quad_indices) = Self::default_quad(memory_allocator.clone())?; let (quad_verts, quad_indices) = Self::default_quad(memory_allocator.clone())?;
@@ -536,8 +542,8 @@ impl WlxGraphics {
Ok(Arc::new(me)) Ok(Arc::new(me))
} }
#[allow(clippy::type_complexity)]
#[cfg(feature = "uidev")] #[cfg(feature = "uidev")]
#[allow(clippy::type_complexity, clippy::too_many_lines)]
pub fn new_window() -> anyhow::Result<( pub fn new_window() -> anyhow::Result<(
Arc<Self>, Arc<Self>,
winit::event_loop::EventLoop<()>, winit::event_loop::EventLoop<()>,
@@ -545,7 +551,10 @@ impl WlxGraphics {
Arc<vulkano::swapchain::Surface>, Arc<vulkano::swapchain::Surface>,
)> { )> {
use vulkano::{ use vulkano::{
device::physical::PhysicalDeviceType, instance::InstanceCreateFlags, swapchain::Surface, descriptor_set::allocator::StandardDescriptorSetAllocatorCreateInfo,
device::physical::PhysicalDeviceType,
instance::InstanceCreateFlags,
swapchain::{Surface, SurfaceInfo},
}; };
use winit::{event_loop::EventLoop, window::Window}; use winit::{event_loop::EventLoop, window::Window};
@@ -588,7 +597,7 @@ impl WlxGraphics {
); );
for (ext, missing) in p.supported_extensions().difference(&device_extensions) { for (ext, missing) in p.supported_extensions().difference(&device_extensions) {
if missing { if missing {
log::debug!(" {}", ext); log::debug!(" {ext}");
} }
} }
None None
@@ -635,10 +644,10 @@ impl WlxGraphics {
let native_format = device let native_format = device
.physical_device() .physical_device()
.surface_formats(&surface, Default::default()) .surface_formats(&surface, SurfaceInfo::default())
.unwrap()[0] // want panic .unwrap()[0] // want panic
.0; .0;
log::info!("Using surface format: {:?}", native_format); log::info!("Using surface format: {native_format:?}");
let queue = queues let queue = queues
.next() .next()
@@ -654,7 +663,7 @@ impl WlxGraphics {
)); ));
let descriptor_set_allocator = Arc::new(StandardDescriptorSetAllocator::new( let descriptor_set_allocator = Arc::new(StandardDescriptorSetAllocator::new(
device.clone(), device.clone(),
Default::default(), StandardDescriptorSetAllocatorCreateInfo::default(),
)); ));
let (quad_verts, quad_indices) = Self::default_quad(memory_allocator.clone())?; let (quad_verts, quad_indices) = Self::default_quad(memory_allocator.clone())?;
@@ -721,7 +730,7 @@ impl WlxGraphics {
| MemoryTypeFilter::HOST_SEQUENTIAL_WRITE, | MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
..Default::default() ..Default::default()
}, },
INDICES.iter().cloned(), INDICES.iter().copied(),
)?; )?;
Ok((quad_verts, quad_indices)) Ok((quad_verts, quad_indices))
@@ -874,7 +883,7 @@ impl WlxGraphics {
(0..frame.num_planes).for_each(|i| { (0..frame.num_planes).for_each(|i| {
let plane = &frame.planes[i]; let plane = &frame.planes[i];
layouts.push(SubresourceLayout { layouts.push(SubresourceLayout {
offset: plane.offset as _, offset: plane.offset.into(),
size: 0, size: 0,
row_pitch: plane.stride as _, row_pitch: plane.stride as _,
array_pitch: None, array_pitch: None,
@@ -883,7 +892,7 @@ impl WlxGraphics {
modifiers.push(frame.format.modifier); modifiers.push(frame.format.modifier);
}); });
tiling = ImageTiling::DrmFormatModifier; tiling = ImageTiling::DrmFormatModifier;
}; }
self.dmabuf_texture_ex(frame, tiling, layouts, &modifiers) self.dmabuf_texture_ex(frame, tiling, layouts, &modifiers)
} }
@@ -1023,7 +1032,7 @@ impl WlxCommandBuffer {
load_op: AttachmentLoadOp::Clear, load_op: AttachmentLoadOp::Clear,
store_op: AttachmentStoreOp::Store, store_op: AttachmentStoreOp::Store,
clear_value: Some([0.0, 0.0, 0.0, 0.0].into()), clear_value: Some([0.0, 0.0, 0.0, 0.0].into()),
..RenderingAttachmentInfo::image_view(render_target.clone()) ..RenderingAttachmentInfo::image_view(render_target)
})], })],
..Default::default() ..Default::default()
})?; })?;
@@ -1157,7 +1166,7 @@ impl WlxPipeline {
}], }],
..Default::default() ..Default::default()
}), }),
dynamic_state: [DynamicState::Viewport].into_iter().collect(), dynamic_state: std::iter::once(DynamicState::Viewport).collect(),
subpass: Some(subpass.into()), subpass: Some(subpass.into()),
..GraphicsPipelineCreateInfo::layout(layout) ..GraphicsPipelineCreateInfo::layout(layout)
}, },
@@ -1279,7 +1288,7 @@ impl WlxPass {
extent: dimensions, extent: dimensions,
depth_range: 0.0..=1.0, depth_range: 0.0..=1.0,
}; };
let pipeline_inner = pipeline.inner().clone(); let pipeline_inner = pipeline.inner();
let mut command_buffer = RecordingCommandBuffer::new( let mut command_buffer = RecordingCommandBuffer::new(
pipeline.graphics.command_buffer_allocator.clone(), pipeline.graphics.command_buffer_allocator.clone(),
pipeline.graphics.queue.queue_family_index(), pipeline.graphics.queue.queue_family_index(),
@@ -1307,9 +1316,9 @@ impl WlxPass {
PipelineBindPoint::Graphics, PipelineBindPoint::Graphics,
pipeline.inner().layout().clone(), pipeline.inner().layout().clone(),
0, 0,
descriptor_sets.clone(), descriptor_sets,
)? )?
.bind_vertex_buffers(0, vertex_buffer.clone())? .bind_vertex_buffers(0, vertex_buffer)?
.bind_index_buffer(index_buffer.clone())? .bind_index_buffer(index_buffer.clone())?
.draw_indexed(index_buffer.len() as u32, 1, 0, 0, 0)? .draw_indexed(index_buffer.len() as u32, 1, 0, 0, 0)?
}; };
@@ -1335,7 +1344,7 @@ impl CommandBuffers {
return Ok(None); return Ok(None);
}; };
let future = first.execute(queue.clone())?; let future = first.execute(queue)?;
let mut future: Box<dyn GpuFuture> = Box::new(future); let mut future: Box<dyn GpuFuture> = Box::new(future);
for buf in buffers { for buf in buffers {
@@ -1368,12 +1377,9 @@ impl CommandBuffers {
pub fn fourcc_to_vk(fourcc: FourCC) -> anyhow::Result<Format> { pub fn fourcc_to_vk(fourcc: FourCC) -> anyhow::Result<Format> {
match fourcc.value { match fourcc.value {
DRM_FORMAT_ABGR8888 => Ok(Format::R8G8B8A8_UNORM), DRM_FORMAT_ABGR8888 | DRM_FORMAT_XBGR8888 => Ok(Format::R8G8B8A8_UNORM),
DRM_FORMAT_XBGR8888 => Ok(Format::R8G8B8A8_UNORM), DRM_FORMAT_ARGB8888 | DRM_FORMAT_XRGB8888 => Ok(Format::B8G8R8A8_UNORM),
DRM_FORMAT_ARGB8888 => Ok(Format::B8G8R8A8_UNORM), DRM_FORMAT_ABGR2101010 | DRM_FORMAT_XBGR2101010 => Ok(Format::A2B10G10R10_UNORM_PACK32),
DRM_FORMAT_XRGB8888 => Ok(Format::B8G8R8A8_UNORM),
DRM_FORMAT_ABGR2101010 => Ok(Format::A2B10G10R10_UNORM_PACK32),
DRM_FORMAT_XBGR2101010 => Ok(Format::A2B10G10R10_UNORM_PACK32),
_ => bail!("Unsupported format {}", fourcc), _ => bail!("Unsupported format {}", fourcc),
} }
} }

View File

@@ -196,7 +196,7 @@ impl<D, S> CanvasBuilder<D, S> {
h, h,
}; };
let rect1 = Rect { let rect1 = Rect {
x: x + w * 0.5 + 12., x: w.mul_add(0.5, x) + 12.,
y: y + h - (self.font_size as f32) + 8., y: y + h - (self.font_size as f32) + 8.,
w, w,
h, h,
@@ -213,7 +213,7 @@ impl<D, S> CanvasBuilder<D, S> {
}; };
let rect1 = Rect { let rect1 = Rect {
x, x,
y: y + h * 0.5 + 2.0, y: h.mul_add(0.5, y) + 2.0,
w, w,
h: h * 0.5, h: h * 0.5,
}; };
@@ -234,7 +234,7 @@ impl<D, S> CanvasBuilder<D, S> {
h, h,
}; };
let rect2 = Rect { let rect2 = Rect {
x: x + w * 0.5 + 8., x: w.mul_add(0.5, x) + 8.,
y: y + h - (self.font_size as f32) + 4., y: y + h - (self.font_size as f32) + 4.,
w, w,
h, h,

View File

@@ -20,7 +20,7 @@ pub type ControlRendererHl<D, S> = fn(
) -> anyhow::Result<()>; ) -> anyhow::Result<()>;
#[allow(clippy::type_complexity)] #[allow(clippy::type_complexity)]
pub(crate) struct Control<D, S> { pub struct Control<D, S> {
pub state: Option<S>, pub state: Option<S>,
pub rect: Rect, pub rect: Rect,
pub corner_radius: f32, pub corner_radius: f32,
@@ -74,7 +74,6 @@ impl<D, S> Control<D, S> {
} }
} }
#[inline(always)]
pub fn set_text(&mut self, text: &str) { pub fn set_text(&mut self, text: &str) {
if *self.text == *text { if *self.text == *text {
return; return;
@@ -83,13 +82,11 @@ impl<D, S> Control<D, S> {
self.fg_dirty = true; self.fg_dirty = true;
} }
#[inline(always)]
pub fn set_sprite(&mut self, sprite: Arc<ImageView>) { pub fn set_sprite(&mut self, sprite: Arc<ImageView>) {
self.sprite.replace(sprite); self.sprite.replace(sprite);
self.bg_dirty = true; self.bg_dirty = true;
} }
#[inline(always)]
pub fn set_sprite_st(&mut self, sprite_st: Vec4) { pub fn set_sprite_st(&mut self, sprite_st: Vec4) {
if self.sprite_st == sprite_st { if self.sprite_st == sprite_st {
return; return;
@@ -98,7 +95,6 @@ impl<D, S> Control<D, S> {
self.bg_dirty = true; self.bg_dirty = true;
} }
#[inline(always)]
pub fn set_fg_color(&mut self, color: GuiColor) { pub fn set_fg_color(&mut self, color: GuiColor) {
if self.fg_color == color { if self.fg_color == color {
return; return;
@@ -190,7 +186,7 @@ impl<D, S> Control<D, S> {
let pass = canvas.pipeline_hl_color.create_pass( let pass = canvas.pipeline_hl_color.create_pass(
[canvas.width as _, canvas.height as _], [canvas.width as _, canvas.height as _],
vertex_buffer.clone(), vertex_buffer,
canvas.graphics.quad_indices.clone(), canvas.graphics.quad_indices.clone(),
vec![set0], vec![set0],
)?; )?;
@@ -253,9 +249,10 @@ impl<D, S> Control<D, S> {
.fc .fc
.get_text_size(&self.text, self.size, canvas.graphics.clone())?; .get_text_size(&self.text, self.size, canvas.graphics.clone())?;
let mut cur_y = self.rect.y + (self.rect.h) - (h * 0.5) - (self.size as f32 * 0.25); let mut cur_y =
(self.size as f32).mul_add(-0.25, h.mul_add(-0.5, self.rect.y + (self.rect.h)));
for line in self.text.lines() { for line in self.text.lines() {
let mut cur_x = self.rect.x + (self.rect.w * 0.5) - (w * 0.5); let mut cur_x = w.mul_add(-0.5, self.rect.w.mul_add(0.5, self.rect.x));
for glyph in app for glyph in app
.fc .fc
.get_glyphs(line, self.size, canvas.graphics.clone())? .get_glyphs(line, self.size, canvas.graphics.clone())?

View File

@@ -1,5 +1,5 @@
pub(crate) mod builder; pub mod builder;
pub(crate) mod control; pub mod control;
use std::sync::Arc; use std::sync::Arc;
@@ -40,7 +40,7 @@ pub struct CanvasData<D> {
pub struct Canvas<D, S> { pub struct Canvas<D, S> {
controls: Vec<control::Control<D, S>>, controls: Vec<control::Control<D, S>>,
canvas: CanvasData<D>, data: CanvasData<D>,
hover_controls: [Option<usize>; 2], hover_controls: [Option<usize>; 2],
pressed_controls: [Option<usize>; 2], pressed_controls: [Option<usize>; 2],
@@ -51,14 +51,14 @@ pub struct Canvas<D, S> {
pipeline_final: Arc<WlxPipeline>, pipeline_final: Arc<WlxPipeline>,
view_fg: Arc<ImageView>, view_fore: Arc<ImageView>,
view_bg: Arc<ImageView>, view_back: Arc<ImageView>,
format: Format, format: Format,
bg_dirty: bool, back_dirty: bool,
hl_dirty: bool, high_dirty: bool,
fg_dirty: bool, fore_dirty: bool,
} }
impl<D, S> Canvas<D, S> { impl<D, S> Canvas<D, S> {
@@ -69,11 +69,11 @@ impl<D, S> Canvas<D, S> {
format: Format, format: Format,
data: D, data: D,
) -> anyhow::Result<Self> { ) -> anyhow::Result<Self> {
let tex_fg = graphics.render_texture(width as _, height as _, format)?; let tex_fore = graphics.render_texture(width as _, height as _, format)?;
let tex_bg = graphics.render_texture(width as _, height as _, format)?; let tex_back = graphics.render_texture(width as _, height as _, format)?;
let view_fg = ImageView::new_default(tex_fg.clone())?; let view_fore = ImageView::new_default(tex_fore)?;
let view_bg = ImageView::new_default(tex_bg.clone())?; let view_back = ImageView::new_default(tex_back)?;
let Ok(shaders) = graphics.shared_shaders.read() else { let Ok(shaders) = graphics.shared_shaders.read() else {
anyhow::bail!("Failed to lock shared shaders for reading"); anyhow::bail!("Failed to lock shared shaders for reading");
@@ -117,7 +117,7 @@ impl<D, S> Canvas<D, S> {
)?; )?;
let pipeline_final = graphics.create_pipeline( let pipeline_final = graphics.create_pipeline(
vert.clone(), vert,
shaders.get("frag_srgb").unwrap().clone(), // want panic shaders.get("frag_srgb").unwrap().clone(), // want panic
SWAPCHAIN_FORMAT, SWAPCHAIN_FORMAT,
Some(BLEND_ALPHA), Some(BLEND_ALPHA),
@@ -127,7 +127,7 @@ impl<D, S> Canvas<D, S> {
let rows = height / RES_DIVIDER; let rows = height / RES_DIVIDER;
Ok(Self { Ok(Self {
canvas: CanvasData { data: CanvasData {
data, data,
width, width,
height, height,
@@ -145,12 +145,12 @@ impl<D, S> Canvas<D, S> {
interact_stride: stride, interact_stride: stride,
interact_rows: rows, interact_rows: rows,
pipeline_final, pipeline_final,
view_fg, view_fore,
view_bg, view_back,
format, format,
bg_dirty: false, back_dirty: false,
hl_dirty: false, high_dirty: false,
fg_dirty: false, fore_dirty: false,
}) })
} }
@@ -170,27 +170,27 @@ impl<D, S> Canvas<D, S> {
} }
fn interactive_get_idx(&self, uv: Vec2) -> Option<usize> { fn interactive_get_idx(&self, uv: Vec2) -> Option<usize> {
let x = (uv.x * self.canvas.width as f32) as usize; let x = (uv.x * self.data.width as f32) as usize;
let y = (uv.y * self.canvas.height as f32) as usize; let y = (uv.y * self.data.height as f32) as usize;
let x = (x / RES_DIVIDER).max(0).min(self.interact_stride - 1); let x = (x / RES_DIVIDER).max(0).min(self.interact_stride - 1);
let y = (y / RES_DIVIDER).max(0).min(self.interact_rows - 1); let y = (y / RES_DIVIDER).max(0).min(self.interact_rows - 1);
self.interact_map[y * self.interact_stride + x].map(|x| x as usize) self.interact_map[y * self.interact_stride + x].map(|x| x as usize)
} }
pub fn data_mut(&mut self) -> &mut D { pub const fn data_mut(&mut self) -> &mut D {
&mut self.canvas.data &mut self.data.data
} }
} }
impl<D, S> InteractionHandler for Canvas<D, S> { impl<D, S> InteractionHandler for Canvas<D, S> {
fn on_left(&mut self, _app: &mut AppState, pointer: usize) { fn on_left(&mut self, _app: &mut AppState, pointer: usize) {
self.hl_dirty = true; self.high_dirty = true;
self.hover_controls[pointer] = None; self.hover_controls[pointer] = None;
} }
fn on_hover(&mut self, _app: &mut AppState, hit: &PointerHit) -> Option<Haptics> { fn on_hover(&mut self, _app: &mut AppState, hit: &PointerHit) -> Option<Haptics> {
// render on every frame if we are being hovered // render on every frame if we are being hovered
self.hl_dirty = true; self.high_dirty = true;
let old = self.hover_controls[hit.pointer]; let old = self.hover_controls[hit.pointer];
if let Some(i) = self.interactive_get_idx(hit.uv) { if let Some(i) = self.interactive_get_idx(hit.uv) {
@@ -198,14 +198,14 @@ impl<D, S> InteractionHandler for Canvas<D, S> {
} else { } else {
self.hover_controls[hit.pointer] = None; self.hover_controls[hit.pointer] = None;
} }
if old != self.hover_controls[hit.pointer] { if old == self.hover_controls[hit.pointer] {
None
} else {
Some(Haptics { Some(Haptics {
intensity: 0.1, intensity: 0.1,
duration: 0.01, duration: 0.01,
frequency: 5.0, frequency: 5.0,
}) })
} else {
None
} }
} }
fn on_pointer(&mut self, app: &mut AppState, hit: &PointerHit, pressed: bool) { fn on_pointer(&mut self, app: &mut AppState, hit: &PointerHit, pressed: bool) {
@@ -220,11 +220,11 @@ impl<D, S> InteractionHandler for Canvas<D, S> {
if pressed { if pressed {
if let Some(ref mut f) = c.on_press { if let Some(ref mut f) = c.on_press {
self.pressed_controls[hit.pointer] = Some(idx); self.pressed_controls[hit.pointer] = Some(idx);
f(c, &mut self.canvas.data, app, hit.mode); f(c, &mut self.data.data, app, hit.mode);
} }
} else if let Some(ref mut f) = c.on_release { } else if let Some(ref mut f) = c.on_release {
self.pressed_controls[hit.pointer] = None; self.pressed_controls[hit.pointer] = None;
f(c, &mut self.canvas.data, app); f(c, &mut self.data.data, app);
} }
} }
} }
@@ -234,7 +234,7 @@ impl<D, S> InteractionHandler for Canvas<D, S> {
if let Some(idx) = idx { if let Some(idx) = idx {
let c = &mut self.controls[idx]; let c = &mut self.controls[idx];
if let Some(ref mut f) = c.on_scroll { if let Some(ref mut f) = c.on_scroll {
f(c, &mut self.canvas.data, app, delta_y, delta_x); f(c, &mut self.data.data, app, delta_y, delta_x);
} }
} }
} }
@@ -251,21 +251,21 @@ impl<D, S> OverlayRenderer for Canvas<D, S> {
Ok(()) Ok(())
} }
fn should_render(&mut self, app: &mut AppState) -> anyhow::Result<ShouldRender> { fn should_render(&mut self, app: &mut AppState) -> anyhow::Result<ShouldRender> {
for c in self.controls.iter_mut() { for c in &mut self.controls {
if let Some(fun) = c.on_update { if let Some(fun) = c.on_update {
fun(c, &mut self.canvas.data, app); fun(c, &mut self.data.data, app);
} }
if c.fg_dirty { if c.fg_dirty {
self.fg_dirty = true; self.fore_dirty = true;
c.fg_dirty = false; c.fg_dirty = false;
} }
if c.bg_dirty { if c.bg_dirty {
self.bg_dirty = true; self.back_dirty = true;
c.bg_dirty = false; c.bg_dirty = false;
} }
} }
if self.bg_dirty || self.fg_dirty || self.hl_dirty { if self.back_dirty || self.fore_dirty || self.high_dirty {
Ok(ShouldRender::Should) Ok(ShouldRender::Should)
} else { } else {
Ok(ShouldRender::Can) Ok(ShouldRender::Can)
@@ -278,68 +278,68 @@ impl<D, S> OverlayRenderer for Canvas<D, S> {
buf: &mut CommandBuffers, buf: &mut CommandBuffers,
alpha: f32, alpha: f32,
) -> anyhow::Result<bool> { ) -> anyhow::Result<bool> {
self.hl_dirty = false; self.high_dirty = false;
let mut cmd_buffer = self let mut cmd_buffer = self
.canvas .data
.graphics .graphics
.create_command_buffer(CommandBufferUsage::OneTimeSubmit)?; .create_command_buffer(CommandBufferUsage::OneTimeSubmit)?;
if self.bg_dirty { if self.back_dirty {
cmd_buffer.begin_rendering(self.view_bg.clone())?; cmd_buffer.begin_rendering(self.view_back.clone())?;
for c in self.controls.iter_mut() { for c in &mut self.controls {
if let Some(fun) = c.on_render_bg { if let Some(fun) = c.on_render_bg {
fun(c, &self.canvas, app, &mut cmd_buffer)?; fun(c, &self.data, app, &mut cmd_buffer)?;
} }
} }
cmd_buffer.end_rendering()?; cmd_buffer.end_rendering()?;
self.bg_dirty = false; self.back_dirty = false;
} }
if self.fg_dirty { if self.fore_dirty {
cmd_buffer.begin_rendering(self.view_fg.clone())?; cmd_buffer.begin_rendering(self.view_fore.clone())?;
for c in self.controls.iter_mut() { for c in &mut self.controls {
if let Some(fun) = c.on_render_fg { if let Some(fun) = c.on_render_fg {
fun(c, &self.canvas, app, &mut cmd_buffer)?; fun(c, &self.data, app, &mut cmd_buffer)?;
} }
} }
cmd_buffer.end_rendering()?; cmd_buffer.end_rendering()?;
self.fg_dirty = false; self.fore_dirty = false;
} }
let set0_fg = self.pipeline_final.uniform_sampler( let set0_fg = self.pipeline_final.uniform_sampler(
0, 0,
self.view_fg.clone(), self.view_fore.clone(),
app.graphics.texture_filtering, app.graphics.texture_filtering,
)?; )?;
let set0_bg = self.pipeline_final.uniform_sampler( let set0_bg = self.pipeline_final.uniform_sampler(
0, 0,
self.view_bg.clone(), self.view_back.clone(),
app.graphics.texture_filtering, app.graphics.texture_filtering,
)?; )?;
let set1 = self.pipeline_final.uniform_buffer(1, vec![alpha])?; let set1 = self.pipeline_final.uniform_buffer(1, vec![alpha])?;
let pass_fg = self let pass_fore = self
.pipeline_final .pipeline_final
.create_pass_for_target(tgt.clone(), vec![set0_fg, set1.clone()])?; .create_pass_for_target(tgt.clone(), vec![set0_fg, set1.clone()])?;
let pass_bg = self let pass_back = self
.pipeline_final .pipeline_final
.create_pass_for_target(tgt.clone(), vec![set0_bg, set1])?; .create_pass_for_target(tgt.clone(), vec![set0_bg, set1])?;
cmd_buffer.begin_rendering(tgt.clone())?; cmd_buffer.begin_rendering(tgt)?;
cmd_buffer.run_ref(&pass_bg)?; cmd_buffer.run_ref(&pass_back)?;
for (i, c) in self.controls.iter_mut().enumerate() { for (i, c) in self.controls.iter_mut().enumerate() {
if let Some(render) = c.on_render_hl { if let Some(render) = c.on_render_hl {
if let Some(test) = c.test_highlight { if let Some(test) = c.test_highlight {
if let Some(hl_color) = test(c, &mut self.canvas.data, app) { if let Some(hl_color) = test(c, &mut self.data.data, app) {
render(c, &self.canvas, app, &mut cmd_buffer, hl_color)?; render(c, &self.data, app, &mut cmd_buffer, hl_color)?;
} }
} }
if self.hover_controls.contains(&Some(i)) { if self.hover_controls.contains(&Some(i)) {
render( render(
c, c,
&self.canvas, &self.data,
app, app,
&mut cmd_buffer, &mut cmd_buffer,
Vec4::new(1., 1., 1., 0.3), Vec4::new(1., 1., 1., 0.3),
@@ -349,7 +349,7 @@ impl<D, S> OverlayRenderer for Canvas<D, S> {
} }
// mostly static text // mostly static text
cmd_buffer.run_ref(&pass_fg)?; cmd_buffer.run_ref(&pass_fore)?;
cmd_buffer.end_rendering()?; cmd_buffer.end_rendering()?;
buf.push(cmd_buffer.build()?); buf.push(cmd_buffer.build()?);
@@ -358,7 +358,7 @@ impl<D, S> OverlayRenderer for Canvas<D, S> {
fn frame_meta(&mut self) -> Option<FrameMeta> { fn frame_meta(&mut self) -> Option<FrameMeta> {
Some(FrameMeta { Some(FrameMeta {
extent: [self.canvas.width as _, self.canvas.height as _, 1], extent: [self.data.width as _, self.data.height as _, 1],
format: self.format, format: self.format,
..Default::default() ..Default::default()
}) })

View File

@@ -39,7 +39,7 @@ impl FontCache {
let ft = Library::init()?; let ft = Library::init()?;
let fc = FontConfig::default(); let fc = FontConfig::default();
Ok(FontCache { Ok(Self {
primary_font, primary_font,
fc, fc,
ft, ft,
@@ -55,7 +55,7 @@ impl FontCache {
) -> anyhow::Result<(f32, f32)> { ) -> anyhow::Result<(f32, f32)> {
let sizef = size as f32; let sizef = size as f32;
let height = sizef + ((text.lines().count() as f32) - 1f32) * (sizef * 1.5); let height = ((text.lines().count() as f32) - 1f32).mul_add(sizef * 1.5, sizef);
let mut cmd_buffer = None; let mut cmd_buffer = None;
let mut max_w = sizef * 0.33; let mut max_w = sizef * 0.33;
@@ -143,26 +143,26 @@ impl FontCache {
if let Some(path) = pattern.filename() { if let Some(path) = pattern.filename() {
let name = pattern.name().unwrap_or(path); let name = pattern.name().unwrap_or(path);
log::debug!("Loading font: {} {}pt", name, size); log::debug!("Loading font: {name} {size}pt");
let font_idx = pattern.face_index().unwrap_or(0); let font_idx = pattern.face_index().unwrap_or(0);
let face = match self.ft.new_face(path, font_idx as _) { let face = match self.ft.new_face(path, font_idx as _) {
Ok(face) => face, Ok(face) => face,
Err(e) => { Err(e) => {
log::warn!("Failed to load font at {}: {:?}", path, e); log::warn!("Failed to load font at {path}: {e:?}");
coll.cp_map.insert(cp, 0); coll.cp_map.insert(cp, 0);
return 0; return 0;
} }
}; };
match face.set_char_size(size << 6, size << 6, 96, 96) { match face.set_char_size(size << 6, size << 6, 96, 96) {
Ok(_) => {} Ok(()) => {}
Err(e) => { Err(e) => {
log::warn!("Failed to set font size: {:?}", e); log::warn!("Failed to set font size: {e:?}");
coll.cp_map.insert(cp, 0); coll.cp_map.insert(cp, 0);
return 0; return 0;
} }
}; }
let idx = coll.fonts.len(); let idx = coll.fonts.len();
for (cp, _) in face.chars() { for (cp, _) in face.chars() {

View File

@@ -6,7 +6,7 @@ pub mod font;
pub mod modular; pub mod modular;
pub type GuiColor = Vec4; pub type GuiColor = Vec4;
pub(super) static FALLBACK_COLOR: Lazy<GuiColor> = Lazy::new(|| Vec4::new(1., 0., 1., 1.)); pub static FALLBACK_COLOR: Lazy<GuiColor> = Lazy::new(|| Vec4::new(1., 0., 1., 1.));
// Parses a color from a HTML hex string // Parses a color from a HTML hex string
pub fn color_parse(html_hex: &str) -> anyhow::Result<GuiColor> { pub fn color_parse(html_hex: &str) -> anyhow::Result<GuiColor> {
@@ -17,9 +17,9 @@ pub fn color_parse(html_hex: &str) -> anyhow::Result<GuiColor> {
u8::from_str_radix(&html_hex[5..7], 16), u8::from_str_radix(&html_hex[5..7], 16),
) { ) {
return Ok(Vec4::new( return Ok(Vec4::new(
r as f32 / 255., f32::from(r) / 255.,
g as f32 / 255., f32::from(g) / 255.,
b as f32 / 255., f32::from(b) / 255.,
1., 1.,
)); ));
} }
@@ -31,10 +31,10 @@ pub fn color_parse(html_hex: &str) -> anyhow::Result<GuiColor> {
u8::from_str_radix(&html_hex[7..9], 16), u8::from_str_radix(&html_hex[7..9], 16),
) { ) {
return Ok(Vec4::new( return Ok(Vec4::new(
r as f32 / 255., f32::from(r) / 255.,
g as f32 / 255., f32::from(g) / 255.,
b as f32 / 255., f32::from(b) / 255.,
a as f32 / 255., f32::from(a) / 255.,
)); ));
} }
} }

View File

@@ -379,7 +379,7 @@ fn modular_button_highlight(
fn handle_action(action: &ButtonAction, press: &mut PressData, app: &mut AppState) { fn handle_action(action: &ButtonAction, press: &mut PressData, app: &mut AppState) {
match action { match action {
ButtonAction::Exec { command, toast } => run_exec(command, toast, press, app), ButtonAction::Exec { command, toast } => run_exec(command, toast.clone(), press, app),
ButtonAction::Watch { action } => run_watch(action, app), ButtonAction::Watch { action } => run_watch(action, app),
ButtonAction::Overlay { target, action } => run_overlay(target, action, app), ButtonAction::Overlay { target, action } => run_overlay(target, action, app),
ButtonAction::Window { target, action } => run_window(target, action, app), ButtonAction::Window { target, action } => run_window(target, action, app),
@@ -439,7 +439,7 @@ fn handle_action(action: &ButtonAction, press: &mut PressData, app: &mut AppStat
let _ = sender.send_single_param(parameter.to_string(), converted); let _ = sender.send_single_param(parameter.to_string(), converted);
audio_thump(app); // play sound for feedback audio_thump(app); // play sound for feedback
}; }
#[cfg(not(feature = "osc"))] #[cfg(not(feature = "osc"))]
{ {
@@ -453,6 +453,7 @@ fn handle_action(action: &ButtonAction, press: &mut PressData, app: &mut AppStat
const ENABLED_DISABLED: [&str; 2] = ["enabled", "disabled"]; const ENABLED_DISABLED: [&str; 2] = ["enabled", "disabled"];
#[allow(clippy::too_many_lines)]
fn run_system(action: &SystemAction, app: &mut AppState) { fn run_system(action: &SystemAction, app: &mut AppState) {
match action { match action {
SystemAction::ToggleAllowSliding => { SystemAction::ToggleAllowSliding => {
@@ -461,7 +462,7 @@ fn run_system(action: &SystemAction, app: &mut AppState) {
ToastTopic::System, ToastTopic::System,
format!( format!(
"Sliding is {}.", "Sliding is {}.",
ENABLED_DISABLED[app.session.config.allow_sliding as usize] ENABLED_DISABLED[usize::from(app.session.config.allow_sliding)]
) )
.into(), .into(),
"".into(), "".into(),
@@ -474,7 +475,7 @@ fn run_system(action: &SystemAction, app: &mut AppState) {
ToastTopic::System, ToastTopic::System,
format!( format!(
"Auto realign is {}.", "Auto realign is {}.",
ENABLED_DISABLED[app.session.config.realign_on_showhide as usize] ENABLED_DISABLED[usize::from(app.session.config.realign_on_showhide)]
) )
.into(), .into(),
"".into(), "".into(),
@@ -487,7 +488,7 @@ fn run_system(action: &SystemAction, app: &mut AppState) {
ToastTopic::System, ToastTopic::System,
format!( format!(
"Space rotate axis lock now {}.", "Space rotate axis lock now {}.",
ENABLED_DISABLED[!app.session.config.space_rotate_unlocked as usize] ENABLED_DISABLED[usize::from(!app.session.config.space_rotate_unlocked)]
) )
.into(), .into(),
"".into(), "".into(),
@@ -506,7 +507,7 @@ fn run_system(action: &SystemAction, app: &mut AppState) {
let display = 5 - i; let display = 5 - i;
Toast::new( Toast::new(
ToastTopic::System, ToastTopic::System,
format!("Fixing floor in {}", display).into(), format!("Fixing floor in {display}").into(),
"Place either controller on the floor.".into(), "Place either controller on the floor.".into(),
) )
.with_timeout(1.0) .with_timeout(1.0)
@@ -524,7 +525,7 @@ fn run_system(action: &SystemAction, app: &mut AppState) {
ToastTopic::System, ToastTopic::System,
format!( format!(
"Notifications are {}.", "Notifications are {}.",
ENABLED_DISABLED[app.session.config.notifications_enabled as usize] ENABLED_DISABLED[usize::from(app.session.config.notifications_enabled)]
) )
.into(), .into(),
"".into(), "".into(),
@@ -538,7 +539,7 @@ fn run_system(action: &SystemAction, app: &mut AppState) {
ToastTopic::System, ToastTopic::System,
format!( format!(
"Notification sounds are {}.", "Notification sounds are {}.",
ENABLED_DISABLED[app.session.config.notifications_sound_enabled as usize] ENABLED_DISABLED[usize::from(app.session.config.notifications_sound_enabled)]
) )
.into(), .into(),
"".into(), "".into(),
@@ -558,7 +559,7 @@ fn run_system(action: &SystemAction, app: &mut AppState) {
} }
} }
fn run_exec(args: &ExecArgs, toast: &Option<Arc<str>>, press: &mut PressData, app: &mut AppState) { fn run_exec(args: &ExecArgs, toast: Option<Arc<str>>, press: &mut PressData, app: &mut AppState) {
if let Some(proc) = press.child.as_mut() { if let Some(proc) = press.child.as_mut() {
match proc.try_wait() { match proc.try_wait() {
Ok(Some(code)) => { Ok(Some(code)) => {
@@ -577,7 +578,10 @@ fn run_exec(args: &ExecArgs, toast: &Option<Arc<str>>, press: &mut PressData, ap
} }
} }
} }
let args = args.iter().map(|s| s.as_ref()).collect::<Vec<&str>>(); let args = args
.iter()
.map(std::convert::AsRef::as_ref)
.collect::<Vec<&str>>();
match process::Command::new(args[0]).args(&args[1..]).spawn() { match process::Command::new(args[0]).args(&args[1..]).spawn() {
Ok(proc) => { Ok(proc) => {
press.child = Some(proc); press.child = Some(proc);
@@ -586,11 +590,12 @@ fn run_exec(args: &ExecArgs, toast: &Option<Arc<str>>, press: &mut PressData, ap
} }
} }
Err(e) => { Err(e) => {
error_toast(app, &format!("Failed to spawn process {:?}", args), e); error_toast(app, &format!("Failed to spawn process {args:?}"), e);
} }
}; }
} }
#[allow(clippy::too_many_lines)]
fn run_watch(data: &WatchAction, app: &mut AppState) { fn run_watch(data: &WatchAction, app: &mut AppState) {
match data { match data {
WatchAction::Hide => { WatchAction::Hide => {
@@ -621,7 +626,7 @@ fn run_watch(data: &WatchAction, app: &mut AppState) {
app.tasks.enqueue(TaskType::Overlay( app.tasks.enqueue(TaskType::Overlay(
OverlaySelector::Name(WATCH_NAME.into()), OverlaySelector::Name(WATCH_NAME.into()),
Box::new(|app, o| { Box::new(|app, o| {
if let RelativeTo::Hand(0) = o.relative_to { if matches!(o.relative_to, RelativeTo::Hand(0)) {
o.relative_to = RelativeTo::Hand(1); o.relative_to = RelativeTo::Hand(1);
o.spawn_rotation = app.session.config.watch_rot o.spawn_rotation = app.session.config.watch_rot
* Quat::from_rotation_x(PI) * Quat::from_rotation_x(PI)
@@ -701,6 +706,7 @@ fn run_watch(data: &WatchAction, app: &mut AppState) {
} }
} }
#[allow(clippy::too_many_lines)]
fn run_overlay(overlay: &OverlaySelector, action: &OverlayAction, app: &mut AppState) { fn run_overlay(overlay: &OverlaySelector, action: &OverlayAction, app: &mut AppState) {
match action { match action {
OverlayAction::Reset => { OverlayAction::Reset => {
@@ -736,7 +742,7 @@ fn run_overlay(overlay: &OverlaySelector, action: &OverlayAction, app: &mut AppS
if state_dirty { if state_dirty {
match save_layout(&app.session.config) { match save_layout(&app.session.config) {
Ok(_) => log::debug!("Saved state"), Ok(()) => log::debug!("Saved state"),
Err(e) => { Err(e) => {
error_toast(app, "Failed to save state", e); error_toast(app, "Failed to save state", e);
} }
@@ -752,17 +758,17 @@ fn run_overlay(overlay: &OverlaySelector, action: &OverlayAction, app: &mut AppS
o.recenter = !o.recenter; o.recenter = !o.recenter;
o.grabbable = o.recenter; o.grabbable = o.recenter;
o.show_hide = o.recenter; o.show_hide = o.recenter;
if !o.recenter { if o.recenter {
Toast::new( Toast::new(
ToastTopic::System, ToastTopic::System,
format!("{} is now locked in place!", o.name).into(), format!("{} is now unlocked!", o.name).into(),
"".into(), "".into(),
) )
.submit(app); .submit(app);
} else { } else {
Toast::new( Toast::new(
ToastTopic::System, ToastTopic::System,
format!("{} is now unlocked!", o.name).into(), format!("{} is now locked in place!", o.name).into(),
"".into(), "".into(),
) )
.submit(app); .submit(app);
@@ -776,17 +782,17 @@ fn run_overlay(overlay: &OverlaySelector, action: &OverlayAction, app: &mut AppS
overlay.clone(), overlay.clone(),
Box::new(|app, o| { Box::new(|app, o| {
o.interactable = !o.interactable; o.interactable = !o.interactable;
if !o.interactable { if o.interactable {
Toast::new( Toast::new(
ToastTopic::System, ToastTopic::System,
format!("{} is now non-interactable!", o.name).into(), format!("{} is now interactable!", o.name).into(),
"".into(), "".into(),
) )
.submit(app); .submit(app);
} else { } else {
Toast::new( Toast::new(
ToastTopic::System, ToastTopic::System,
format!("{} is now interactable!", o.name).into(), format!("{} is now non-interactable!", o.name).into(),
"".into(), "".into(),
) )
.submit(app); .submit(app);
@@ -827,7 +833,11 @@ fn run_window(window: &Arc<str>, action: &WindowAction, app: &mut AppState) {
) )
.with_sound(true) .with_sound(true)
.submit(app); .submit(app);
crate::overlays::mirror::new_mirror(name.clone(), false, &app.session) Some(crate::overlays::mirror::new_mirror(
name,
false,
&app.session,
))
} }
}), }),
)); ));

View File

@@ -100,15 +100,14 @@ pub fn modular_label_init(label: &mut ModularControl, content: &LabelContent, ap
}), }),
LabelContent::Clock { format, timezone } => { LabelContent::Clock { format, timezone } => {
let tz_str = match timezone { let tz_str = match timezone {
Some(TimezoneDef::Idx(idx)) => { Some(TimezoneDef::Idx(idx)) => app.session.config.timezones.get(*idx).map_or_else(
if let Some(tz) = app.session.config.timezones.get(*idx) { || {
Some(tz.as_str()) log::error!("Timezone index out of range '{idx}'");
} else {
log::error!("Timezone index out of range '{}'", idx);
label.set_fg_color(*FALLBACK_COLOR); label.set_fg_color(*FALLBACK_COLOR);
None None
} },
} |tz| Some(tz.as_str()),
),
Some(TimezoneDef::Str(tz_str)) => Some(tz_str.as_ref()), Some(TimezoneDef::Str(tz_str)) => Some(tz_str.as_ref()),
None => None, None => None,
}; };
@@ -127,14 +126,13 @@ pub fn modular_label_init(label: &mut ModularControl, content: &LabelContent, ap
} }
LabelContent::Timezone { timezone } => { LabelContent::Timezone { timezone } => {
if let Some(tz) = app.session.config.timezones.get(*timezone) { if let Some(tz) = app.session.config.timezones.get(*timezone) {
let pretty_tz = tz.split('/').next_back().map(|x| x.replace("_", " ")); let pretty_tz = tz.split('/').next_back().map(|x| x.replace('_', " "));
if let Some(pretty_tz) = pretty_tz { if let Some(pretty_tz) = pretty_tz {
label.set_text(&pretty_tz); label.set_text(&pretty_tz);
return; return;
} else {
log::error!("Timezone name not valid '{}'", &tz);
} }
log::error!("Timezone name not valid '{}'", &tz);
} else { } else {
log::error!("Timezone index out of range '{}'", &timezone); log::error!("Timezone index out of range '{}'", &timezone);
} }
@@ -166,6 +164,7 @@ pub fn modular_label_init(label: &mut ModularControl, content: &LabelContent, ap
} }
} }
#[allow(clippy::too_many_lines)]
pub(super) fn label_update(control: &mut ModularControl, _: &mut (), app: &mut AppState) { pub(super) fn label_update(control: &mut ModularControl, _: &mut (), app: &mut AppState) {
// want panic // want panic
let ModularData::Label(data) = control.state.as_mut().unwrap() else { let ModularData::Label(data) = control.state.as_mut().unwrap() else {
@@ -184,9 +183,9 @@ pub(super) fn label_update(control: &mut ModularControl, _: &mut (), app: &mut A
let tags = ["", "H", "L", "R", "T"]; let tags = ["", "H", "L", "R", "T"];
if let Some(device) = device { if let Some(device) = device {
let (text, color) = device let (text, color) = device.soc.map_or_else(
.soc || (String::new(), Vec4::ZERO),
.map(|soc| { |soc| {
let text = format!( let text = format!(
"{}{}", "{}{}",
tags[device.role as usize], tags[device.role as usize],
@@ -200,8 +199,8 @@ pub(super) fn label_update(control: &mut ModularControl, _: &mut (), app: &mut A
*normal_color *normal_color
}; };
(text, color) (text, color)
}) },
.unwrap_or_else(|| ("".into(), Vec4::ZERO)); );
control.set_text(&text); control.set_text(&text);
control.set_fg_color(color); control.set_fg_color(color);
@@ -212,11 +211,11 @@ pub(super) fn label_update(control: &mut ModularControl, _: &mut (), app: &mut A
LabelData::Clock { format, timezone } => { LabelData::Clock { format, timezone } => {
let format = format.clone(); let format = format.clone();
if let Some(tz) = timezone { if let Some(tz) = timezone {
let date = Local::now().with_timezone(tz); let date_time = Local::now().with_timezone(tz);
control.set_text(&format!("{}", &date.format(&format))); control.set_text(&format!("{}", &date_time.format(&format)));
} else { } else {
let date = Local::now(); let date_time = Local::now();
control.set_text(&format!("{}", &date.format(&format))); control.set_text(&format!("{}", &date_time.format(&format)));
} }
} }
LabelData::Timer { format, start } => { LabelData::Timer { format, start } => {
@@ -236,13 +235,7 @@ pub(super) fn label_update(control: &mut ModularControl, _: &mut (), app: &mut A
if let Some(mut proc) = child.take() { if let Some(mut proc) = child.take() {
match proc.try_wait() { match proc.try_wait() {
Ok(Some(code)) => { Ok(Some(code)) => {
if !code.success() { if code.success() {
error_toast(
app,
"LabelData::Exec: Child process exited with code",
code,
);
} else {
if let Some(mut stdout) = proc.stdout.take() { if let Some(mut stdout) = proc.stdout.take() {
let mut buf = String::new(); let mut buf = String::new();
if stdout.read_to_string(&mut buf).is_ok() { if stdout.read_to_string(&mut buf).is_ok() {
@@ -259,6 +252,7 @@ pub(super) fn label_update(control: &mut ModularControl, _: &mut (), app: &mut A
log::error!("No stdout for child process"); log::error!("No stdout for child process");
return; return;
} }
error_toast(app, "LabelData::Exec: Child process exited with code", code);
} }
Ok(None) => { Ok(None) => {
*child = Some(proc); *child = Some(proc);
@@ -281,7 +275,7 @@ pub(super) fn label_update(control: &mut ModularControl, _: &mut (), app: &mut A
*last_exec = Instant::now(); *last_exec = Instant::now();
let args = command let args = command
.iter() .iter()
.map(|s| s.as_ref()) .map(std::convert::AsRef::as_ref)
.collect::<SmallVec<[&str; 8]>>(); .collect::<SmallVec<[&str; 8]>>();
match process::Command::new(args[0]) match process::Command::new(args[0])
@@ -293,9 +287,9 @@ pub(super) fn label_update(control: &mut ModularControl, _: &mut (), app: &mut A
*child = Some(proc); *child = Some(proc);
} }
Err(e) => { Err(e) => {
error_toast(app, &format!("Failed to spawn process {:?}", args), e); error_toast(app, &format!("Failed to spawn process {args:?}"), e);
} }
}; }
} }
} }
LabelData::Ipd { last_ipd } => { LabelData::Ipd { last_ipd } => {

View File

@@ -149,8 +149,9 @@ pub enum ModularData {
Button(Box<ButtonData>), Button(Box<ButtonData>),
} }
#[allow(clippy::too_many_lines, clippy::many_single_char_names)]
pub fn modular_canvas( pub fn modular_canvas(
size: &[u32; 2], size: [u32; 2],
elements: &[ModularElement], elements: &[ModularElement],
state: &mut AppState, state: &mut AppState,
) -> anyhow::Result<Canvas<(), ModularData>> { ) -> anyhow::Result<Canvas<(), ModularData>> {
@@ -162,7 +163,7 @@ pub fn modular_canvas(
(), (),
)?; )?;
let empty_str: Arc<str> = Arc::from(""); let empty_str: Arc<str> = Arc::from("");
for elem in elements.iter() { for elem in elements {
match elem { match elem {
ModularElement::Panel { ModularElement::Panel {
rect: [x, y, w, h], rect: [x, y, w, h],
@@ -226,7 +227,7 @@ pub fn modular_canvas(
sprite.set_sprite_st(st); sprite.set_sprite_st(st);
} }
Err(e) => { Err(e) => {
log::warn!("Could not load custom UI sprite: {:?}", e); log::warn!("Could not load custom UI sprite: {e:?}");
} }
}, },
ModularElement::Button { ModularElement::Button {
@@ -326,7 +327,7 @@ pub fn modular_canvas(
canvas.fg_color = color_parse(fg_color).unwrap_or(*FALLBACK_COLOR); canvas.fg_color = color_parse(fg_color).unwrap_or(*FALLBACK_COLOR);
canvas.font_size = *font_size; canvas.font_size = *font_size;
for screen in state.screens.iter() { for screen in &state.screens {
let button = canvas.button( let button = canvas.button(
button_x + 2., button_x + 2.,
button_y + 2., button_y + 2.,
@@ -465,7 +466,7 @@ pub fn modular_canvas(
button_x += button_w; button_x += button_w;
} }
} else { } else {
log::error!("WayVR catalog \"{}\" not found", catalog_name); log::error!("WayVR catalog \"{catalog_name}\" not found");
} }
} }
#[cfg(not(feature = "wayvr"))] #[cfg(not(feature = "wayvr"))]
@@ -535,7 +536,7 @@ pub fn modular_canvas(
pub fn color_parse_or_default(color: &str) -> GuiColor { pub fn color_parse_or_default(color: &str) -> GuiColor {
color_parse(color).unwrap_or_else(|e| { color_parse(color).unwrap_or_else(|e| {
log::error!("Failed to parse color '{}': {}", color, e); log::error!("Failed to parse color '{color}': {e}");
*FALLBACK_COLOR *FALLBACK_COLOR
}) })
} }

View File

@@ -34,10 +34,7 @@ pub fn initialize() -> Box<dyn HidProvider> {
log::error!("Could not create uinput provider. Keyboard/Mouse input will not work!"); log::error!("Could not create uinput provider. Keyboard/Mouse input will not work!");
log::error!("To check if you're in input group, run: id -nG"); log::error!("To check if you're in input group, run: id -nG");
if let Ok(user) = std::env::var("USER") { if let Ok(user) = std::env::var("USER") {
log::error!( log::error!("To add yourself to the input group, run: sudo usermod -aG input {user}");
"To add yourself to the input group, run: sudo usermod -aG input {}",
user
);
log::error!("After adding yourself to the input group, you will need to reboot."); log::error!("After adding yourself to the input group, you will need to reboot.");
} }
Box::new(DummyProvider {}) Box::new(DummyProvider {})
@@ -163,28 +160,28 @@ impl UInputProvider {
.create(&mouse_id, mouse_name, 0, &abs_info) .create(&mouse_id, mouse_name, 0, &abs_info)
.ok()?; .ok()?;
Some(UInputProvider { Some(Self {
keyboard_handle, keyboard_handle,
mouse_handle, mouse_handle,
desktop_extent: Vec2::ZERO, desktop_extent: Vec2::ZERO,
desktop_origin: Vec2::ZERO, desktop_origin: Vec2::ZERO,
current_action: Default::default(), current_action: MouseAction::default(),
cur_modifiers: 0, cur_modifiers: 0,
}) })
} }
fn send_button_internal(&self, button: u16, down: bool) { fn send_button_internal(&self, button: u16, down: bool) {
let time = get_time(); let time = get_time();
let events = [ let events = [
new_event(time, EV_KEY, button, down as _), new_event(time, EV_KEY, button, down.into()),
new_event(time, EV_SYN, 0, 0), new_event(time, EV_SYN, 0, 0),
]; ];
if let Err(res) = self.mouse_handle.write(&events) { if let Err(res) = self.mouse_handle.write(&events) {
log::error!("send_button: {}", res.to_string()); log::error!("send_button: {res}");
} }
} }
fn mouse_move_internal(&mut self, pos: Vec2) { fn mouse_move_internal(&mut self, pos: Vec2) {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
log::trace!("Mouse move: {:?}", pos); log::trace!("Mouse move: {pos:?}");
let pos = (pos - self.desktop_origin) * (MOUSE_EXTENT / self.desktop_extent); let pos = (pos - self.desktop_origin) * (MOUSE_EXTENT / self.desktop_extent);
@@ -195,7 +192,7 @@ impl UInputProvider {
new_event(time, EV_SYN, 0, 0), new_event(time, EV_SYN, 0, 0),
]; ];
if let Err(res) = self.mouse_handle.write(&events) { if let Err(res) = self.mouse_handle.write(&events) {
log::error!("{}", res.to_string()); log::error!("{res}");
} }
} }
fn wheel_internal(&self, delta_y: i32, delta_x: i32) { fn wheel_internal(&self, delta_y: i32, delta_x: i32) {
@@ -211,7 +208,7 @@ impl UInputProvider {
new_event(time, EV_SYN, 0, 0), new_event(time, EV_SYN, 0, 0),
]; ];
if let Err(res) = self.mouse_handle.write(&events) { if let Err(res) = self.mouse_handle.write(&events) {
log::error!("wheel: {}", res.to_string()); log::error!("wheel: {res}");
} }
} }
} }
@@ -231,15 +228,15 @@ impl HidProvider for UInputProvider {
} }
fn send_key(&self, key: VirtualKey, down: bool) { fn send_key(&self, key: VirtualKey, down: bool) {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
log::trace!("send_key: {:?} {}", key, down); log::trace!("send_key: {key:?} {down}");
let time = get_time(); let time = get_time();
let events = [ let events = [
new_event(time, EV_KEY, (key as u16) - 8, down as _), new_event(time, EV_KEY, (key as u16) - 8, down.into()),
new_event(time, EV_SYN, 0, 0), new_event(time, EV_SYN, 0, 0),
]; ];
if let Err(res) = self.keyboard_handle.write(&events) { if let Err(res) = self.keyboard_handle.write(&events) {
log::error!("send_key: {}", res.to_string()); log::error!("send_key: {res}");
} }
} }
fn set_desktop_extent(&mut self, extent: Vec2) { fn set_desktop_extent(&mut self, extent: Vec2) {
@@ -303,7 +300,7 @@ fn get_time() -> timeval {
} }
#[inline] #[inline]
fn new_event(time: timeval, type_: u16, code: u16, value: i32) -> input_event { const fn new_event(time: timeval, type_: u16, code: u16, value: i32) -> input_event {
input_event { input_event {
time, time,
type_, type_,
@@ -323,7 +320,7 @@ pub const META: KeyModifier = 0x80;
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
#[repr(u16)] #[repr(u16)]
#[derive(Debug, Deserialize, PartialEq, Clone, Copy, IntegerId, EnumString, EnumIter)] #[derive(Debug, Deserialize, PartialEq, Eq, Clone, Copy, IntegerId, EnumString, EnumIter)]
pub enum VirtualKey { pub enum VirtualKey {
Escape = 9, Escape = 9,
N1, // number row N1, // number row
@@ -524,7 +521,7 @@ macro_rules! key_is {
}; };
} }
pub fn get_key_type(key: VirtualKey) -> KeyType { pub const fn get_key_type(key: VirtualKey) -> KeyType {
if key_between!(key, VirtualKey::N1, VirtualKey::Plus) if key_between!(key, VirtualKey::N1, VirtualKey::Plus)
|| key_between!(key, VirtualKey::Q, VirtualKey::Oem6) || key_between!(key, VirtualKey::Q, VirtualKey::Oem6)
|| key_between!(key, VirtualKey::A, VirtualKey::Oem3) || key_between!(key, VirtualKey::A, VirtualKey::Oem3)

View File

@@ -46,11 +46,9 @@ pub fn get_keymap_wl() -> anyhow::Result<XkbKeymap> {
// this gets us the wl_keyboard // this gets us the wl_keyboard
let _ = queue.blocking_dispatch(&mut me); let _ = queue.blocking_dispatch(&mut me);
if let Some(keymap) = me.keymap.take() { me.keymap
Ok(keymap) .take()
} else { .ok_or_else(|| anyhow::anyhow!("Could not load keymap"))
Err(anyhow::anyhow!("Could not load keymap"))
}
} }
impl Dispatch<WlRegistry, GlobalListContents> for WlKeymapHandler { impl Dispatch<WlRegistry, GlobalListContents> for WlKeymapHandler {
@@ -84,7 +82,7 @@ impl Dispatch<WlSeat, ()> for WlKeymapHandler {
} }
} }
wl_seat::Event::Name { name } => { wl_seat::Event::Name { name } => {
log::debug!("Using WlSeat: {}", name); log::debug!("Using WlSeat: {name}");
} }
_ => {} _ => {}
} }
@@ -127,14 +125,14 @@ impl Dispatch<WlKeyboard, ()> for WlKeymapHandler {
log::error!("Default layout will be used."); log::error!("Default layout will be used.");
} }
Err(err) => { Err(err) => {
log::error!("Could not load keymap: {}", err); log::error!("Could not load keymap: {err}");
log::error!("Default layout will be used."); log::error!("Default layout will be used.");
} }
} }
} }
} }
wl_keyboard::Event::RepeatInfo { rate, delay } => { wl_keyboard::Event::RepeatInfo { rate, delay } => {
log::debug!("WlKeyboard RepeatInfo rate: {}, delay: {}", rate, delay); log::debug!("WlKeyboard RepeatInfo rate: {rate}, delay: {delay}");
} }
_ => {} _ => {}
} }

View File

@@ -1,4 +1,18 @@
#[allow(dead_code)] #![warn(clippy::all, clippy::pedantic, clippy::nursery, clippy::cargo)]
#![allow(
dead_code,
clippy::cast_precision_loss,
clippy::cast_possible_truncation,
clippy::cast_sign_loss,
clippy::cast_possible_wrap,
clippy::cast_lossless,
clippy::match_wildcard_for_single_variants,
clippy::doc_markdown,
clippy::struct_excessive_bools,
clippy::needless_pass_by_value,
clippy::needless_pass_by_ref_mut,
clippy::multiple_crate_versions
)]
mod backend; mod backend;
mod config; mod config;
mod config_io; mod config_io;
@@ -65,6 +79,7 @@ struct Args {
uidev: Option<String>, uidev: Option<String>,
} }
#[allow(clippy::unnecessary_wraps)]
fn main() -> Result<(), Box<dyn std::error::Error>> { fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut args = if std::env::args().skip(1).any(|a| !a.is_empty()) { let mut args = if std::env::args().skip(1).any(|a| !a.is_empty()) {
Args::parse() Args::parse()
@@ -78,7 +93,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
return Ok(()); return Ok(());
} }
logging_init(&mut args)?; logging_init(&mut args);
log::info!( log::info!(
"Welcome to {} version {}!", "Welcome to {} version {}!",
@@ -122,23 +137,23 @@ fn auto_run(running: Arc<AtomicBool>, args: Args) {
Ok(()) => return, Ok(()) => return,
Err(BackendError::NotSupported) => (), Err(BackendError::NotSupported) => (),
Err(e) => { Err(e) => {
log::error!("{}", e.to_string()); log::error!("{e}");
return; return;
} }
}; }
} }
#[cfg(feature = "openvr")] #[cfg(feature = "openvr")]
if !args_get_openxr(&args) { if !args_get_openxr(&args) {
use crate::backend::openvr::openvr_run; use crate::backend::openvr::openvr_run;
match openvr_run(running.clone(), args.show) { match openvr_run(running, args.show) {
Ok(()) => return, Ok(()) => return,
Err(BackendError::NotSupported) => (), Err(BackendError::NotSupported) => (),
Err(e) => { Err(e) => {
log::error!("{}", e.to_string()); log::error!("{e}");
return; return;
} }
}; }
} }
log::error!("No more backends to try"); log::error!("No more backends to try");
@@ -151,9 +166,9 @@ fn auto_run(running: Arc<AtomicBool>, args: Args) {
} }
#[allow(dead_code)] #[allow(dead_code)]
fn args_get_openvr(_args: &Args) -> bool { const fn args_get_openvr(args: &Args) -> bool {
#[cfg(feature = "openvr")] #[cfg(feature = "openvr")]
let ret = _args.openvr; let ret = args.openvr;
#[cfg(not(feature = "openvr"))] #[cfg(not(feature = "openvr"))]
let ret = false; let ret = false;
@@ -162,9 +177,9 @@ fn args_get_openvr(_args: &Args) -> bool {
} }
#[allow(dead_code)] #[allow(dead_code)]
fn args_get_openxr(_args: &Args) -> bool { const fn args_get_openxr(args: &Args) -> bool {
#[cfg(feature = "openxr")] #[cfg(feature = "openxr")]
let ret = _args.openxr; let ret = args.openxr;
#[cfg(not(feature = "openxr"))] #[cfg(not(feature = "openxr"))]
let ret = false; let ret = false;
@@ -172,12 +187,12 @@ fn args_get_openxr(_args: &Args) -> bool {
ret ret
} }
fn logging_init(args: &mut Args) -> anyhow::Result<()> { fn logging_init(args: &mut Args) {
let log_file_path = args let log_file_path = args
.log_to .log_to
.take() .take()
.or_else(|| std::env::var("WLX_LOGFILE").ok()) .or_else(|| std::env::var("WLX_LOGFILE").ok())
.unwrap_or(String::from("/tmp/wlx.log")); .unwrap_or_else(|| String::from("/tmp/wlx.log"));
let file_writer = match std::fs::OpenOptions::new() let file_writer = match std::fs::OpenOptions::new()
.write(true) .write(true)
@@ -189,7 +204,7 @@ fn logging_init(args: &mut Args) -> anyhow::Result<()> {
Some(file) Some(file)
} }
Err(e) => { Err(e) => {
println!("Failed to open log file (path: {:?}): {}", e, log_file_path); println!("Failed to open log file (path: {e:?}): {log_file_path}");
None None
} }
}; };
@@ -225,13 +240,11 @@ fn logging_init(args: &mut Args) -> anyhow::Result<()> {
} }
log_panics::init(); log_panics::init();
Ok(())
} }
fn ensure_single_instance(replace: bool) -> bool { fn ensure_single_instance(replace: bool) -> bool {
let mut path = std::env::var("XDG_RUNTIME_DIR") let mut path =
.map(PathBuf::from) std::env::var("XDG_RUNTIME_DIR").map_or_else(|_| PathBuf::from("/tmp"), PathBuf::from);
.unwrap_or_else(|_| PathBuf::from("/tmp"));
path.push("wlx-overlay-s.pid"); path.push("wlx-overlay-s.pid");
if path.exists() { if path.exists() {

View File

@@ -27,7 +27,7 @@ where
relative_to: RelativeTo::Stage, relative_to: RelativeTo::Stage,
..Default::default() ..Default::default()
}, },
backend: Box::new(modular_canvas(&config.size, &config.elements, state)?), backend: Box::new(modular_canvas(config.size, &config.elements, state)?),
..Default::default() ..Default::default()
}) })
} }

View File

@@ -21,28 +21,28 @@ pub fn create_custom(
match load_custom_ui(&name) { match load_custom_ui(&name) {
Ok(config) => config, Ok(config) => config,
Err(e) => { Err(e) => {
log::error!("Failed to load custom UI config for {}: {:?}", name, e); log::error!("Failed to load custom UI config for {name}: {e:?}");
return None; return None;
} }
} }
}; };
let canvas = match modular_canvas(&config.size, &config.elements, state) { let canvas = match modular_canvas(config.size, &config.elements, state) {
Ok(canvas) => canvas, Ok(canvas) => canvas,
Err(e) => { Err(e) => {
log::error!("Failed to create canvas for {}: {:?}", name, e); log::error!("Failed to create canvas for {name}: {e:?}");
return None; return None;
} }
}; };
let state = OverlayState { let state = OverlayState {
name: name.clone(), name,
want_visible: true, want_visible: true,
interactable: true, interactable: true,
grabbable: true, grabbable: true,
spawn_scale: config.width, spawn_scale: config.width,
spawn_point: Vec3A::from_array(config.spawn_pos.unwrap_or([0., 0., -0.5])), spawn_point: Vec3A::from_array(config.spawn_pos.unwrap_or([0., 0., -0.5])),
interaction_transform: ui_transform(&config.size), interaction_transform: ui_transform(config.size),
..Default::default() ..Default::default()
}; };
let backend = Box::new(canvas); let backend = Box::new(canvas);

View File

@@ -66,6 +66,7 @@ fn set_modifiers(app: &mut AppState, mods: u8) {
} }
} }
#[allow(clippy::too_many_lines)]
pub fn create_keyboard<O>( pub fn create_keyboard<O>(
app: &AppState, app: &AppState,
mut keymap: Option<XkbKeymap>, mut keymap: Option<XkbKeymap>,
@@ -106,23 +107,25 @@ where
canvas.fg_color = color_parse("#cad3f5").unwrap(); //safe canvas.fg_color = color_parse("#cad3f5").unwrap(); //safe
canvas.bg_color = color_parse("#1e2030").unwrap(); //safe canvas.bg_color = color_parse("#1e2030").unwrap(); //safe
let has_altgr = keymap.as_ref().is_some_and(|k| k.has_altgr()); let has_altgr = keymap
.as_ref()
.is_some_and(super::super::hid::XkbKeymap::has_altgr);
if !LAYOUT.auto_labels.unwrap_or(true) { if !LAYOUT.auto_labels.unwrap_or(true) {
keymap = None; keymap = None;
} }
let unit_size = size.x / LAYOUT.row_size; let unit_size = size.x / LAYOUT.row_size;
let h = unit_size - 2. * BUTTON_PADDING; let h = 2.0f32.mul_add(-BUTTON_PADDING, unit_size);
for row in 0..LAYOUT.key_sizes.len() { for row in 0..LAYOUT.key_sizes.len() {
let y = unit_size * (row as f32) + BUTTON_PADDING; let y = unit_size.mul_add(row as f32, BUTTON_PADDING);
let mut sum_size = 0f32; let mut sum_size = 0f32;
for col in 0..LAYOUT.key_sizes[row].len() { for col in 0..LAYOUT.key_sizes[row].len() {
let my_size = LAYOUT.key_sizes[row][col]; let my_size = LAYOUT.key_sizes[row][col];
let x = unit_size * sum_size + BUTTON_PADDING; let x = unit_size.mul_add(sum_size, BUTTON_PADDING);
let w = unit_size * my_size - 2. * BUTTON_PADDING; let w = unit_size.mul_add(my_size, -(2. * BUTTON_PADDING));
if let Some(key) = LAYOUT.main_layout[row][col].as_ref() { if let Some(key) = LAYOUT.main_layout[row][col].as_ref() {
let mut label = Vec::with_capacity(2); let mut label = Vec::with_capacity(2);
@@ -136,7 +139,7 @@ where
let label0 = keymap.label_for_key(vk, 0); let label0 = keymap.label_for_key(vk, 0);
let label1 = keymap.label_for_key(vk, SHIFT); let label1 = keymap.label_for_key(vk, SHIFT);
if label0.chars().next().is_some_and(|f| f.is_alphabetic()) { if label0.chars().next().is_some_and(char::is_alphabetic) {
label.push(label1); label.push(label1);
if has_altgr { if has_altgr {
cap_type = KeyCapType::RegularAltGr; cap_type = KeyCapType::RegularAltGr;
@@ -176,7 +179,7 @@ where
}); });
} else if let Some(exec_args) = LAYOUT.exec_commands.get(key) { } else if let Some(exec_args) = LAYOUT.exec_commands.get(key) {
if exec_args.is_empty() { if exec_args.is_empty() {
log::error!("Keyboard: EXEC args empty for {}", key); log::error!("Keyboard: EXEC args empty for {key}");
continue; continue;
} }
let mut iter = exec_args.iter().cloned(); let mut iter = exec_args.iter().cloned();
@@ -186,10 +189,10 @@ where
args: iter.by_ref().take_while(|arg| arg[..] != *"null").collect(), args: iter.by_ref().take_while(|arg| arg[..] != *"null").collect(),
release_program: iter.next(), release_program: iter.next(),
release_args: iter.collect(), release_args: iter.collect(),
}) });
}; }
} else { } else {
log::error!("Unknown key: {}", key); log::error!("Unknown key: {key}");
} }
if let Some(state) = maybe_state { if let Some(state) = maybe_state {
@@ -240,7 +243,7 @@ fn key_press(
) { ) {
match control.state.as_mut() { match control.state.as_mut() {
Some(KeyButtonData::Key { vk, pressed }) => { Some(KeyButtonData::Key { vk, pressed }) => {
data.key_click(app); key_click(app);
data.modifiers |= match mode { data.modifiers |= match mode {
PointerMode::Right => SHIFT, PointerMode::Right => SHIFT,
@@ -256,11 +259,11 @@ fn key_press(
Some(KeyButtonData::Modifier { modifier, sticky }) => { Some(KeyButtonData::Modifier { modifier, sticky }) => {
*sticky = data.modifiers & *modifier == 0; *sticky = data.modifiers & *modifier == 0;
data.modifiers |= *modifier; data.modifiers |= *modifier;
data.key_click(app); key_click(app);
set_modifiers(app, data.modifiers); set_modifiers(app, data.modifiers);
} }
Some(KeyButtonData::Macro { verbs }) => { Some(KeyButtonData::Macro { verbs }) => {
data.key_click(app); key_click(app);
for (vk, press) in verbs { for (vk, press) in verbs {
send_key(app, *vk, *press); send_key(app, *vk, *press);
} }
@@ -270,7 +273,7 @@ fn key_press(
data.processes data.processes
.retain_mut(|child| !matches!(child.try_wait(), Ok(Some(_)))); .retain_mut(|child| !matches!(child.try_wait(), Ok(Some(_))));
data.key_click(app); key_click(app);
if let Ok(child) = Command::new(program).args(args).spawn() { if let Ok(child) = Command::new(program).args(args).spawn() {
data.processes.push(child); data.processes.push(child);
} }
@@ -289,7 +292,7 @@ fn key_release(
send_key(app, *vk, false); send_key(app, *vk, false);
*pressed = false; *pressed = false;
for m in AUTO_RELEASE_MODS.iter() { for m in &AUTO_RELEASE_MODS {
if data.modifiers & *m != 0 { if data.modifiers & *m != 0 {
data.modifiers &= !*m; data.modifiers &= !*m;
set_modifiers(app, data.modifiers); set_modifiers(app, data.modifiers);
@@ -349,11 +352,9 @@ struct KeyboardData {
const KEY_AUDIO_WAV: &[u8] = include_bytes!("../res/421581.wav"); const KEY_AUDIO_WAV: &[u8] = include_bytes!("../res/421581.wav");
impl KeyboardData { fn key_click(app: &mut AppState) {
fn key_click(&mut self, app: &mut AppState) { if app.session.config.keyboard_sound_enabled {
if app.session.config.keyboard_sound_enabled { app.audio.play(KEY_AUDIO_WAV);
app.audio.play(KEY_AUDIO_WAV);
}
} }
} }
@@ -395,6 +396,7 @@ pub enum AltModifier {
} }
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize)]
#[allow(clippy::struct_field_names)]
pub struct Layout { pub struct Layout {
name: String, name: String,
row_size: f32, row_size: f32,
@@ -408,8 +410,8 @@ pub struct Layout {
} }
impl Layout { impl Layout {
fn load_from_disk() -> Layout { fn load_from_disk() -> Self {
let mut layout = config::load_known_yaml::<Layout>(ConfigType::Keyboard); let mut layout = config::load_known_yaml::<Self>(ConfigType::Keyboard);
layout.post_load(); layout.post_load();
layout layout
} }
@@ -418,25 +420,25 @@ impl Layout {
for i in 0..self.key_sizes.len() { for i in 0..self.key_sizes.len() {
let row = &self.key_sizes[i]; let row = &self.key_sizes[i];
let width: f32 = row.iter().sum(); let width: f32 = row.iter().sum();
if (width - self.row_size).abs() > 0.001 { assert!(
panic!( (width - self.row_size).abs() < 0.001,
"Row {} has a width of {}, but the row size is {}", "Row {} has a width of {}, but the row size is {}",
i, width, self.row_size i,
); width,
} self.row_size
);
} }
for i in 0..self.main_layout.len() { for i in 0..self.main_layout.len() {
let row = &self.main_layout[i]; let row = &self.main_layout[i];
let width = row.len(); let width = row.len();
if width != self.key_sizes[i].len() { assert!(
panic!( (width == self.key_sizes[i].len()),
"Row {} has {} keys, needs to have {} according to key_sizes", "Row {} has {} keys, needs to have {} according to key_sizes",
i, i,
width, width,
self.key_sizes[i].len() self.key_sizes[i].len()
); );
}
} }
} }
@@ -456,10 +458,7 @@ impl Layout {
} }
if key.contains('_') { if key.contains('_') {
key = key.split('_').next().unwrap_or_else(|| { key = key.split('_').next().unwrap_or_else(|| {
log::error!( log::error!("keyboard.yaml: Key '{key}' must not start or end with '_'!");
"keyboard.yaml: Key '{}' must not start or end with '_'!",
key
);
"???" "???"
}); });
} }
@@ -507,10 +506,10 @@ struct KeyboardBackend {
impl OverlayBackend for KeyboardBackend { impl OverlayBackend for KeyboardBackend {
fn set_interaction(&mut self, interaction: Box<dyn crate::backend::input::InteractionHandler>) { fn set_interaction(&mut self, interaction: Box<dyn crate::backend::input::InteractionHandler>) {
self.canvas.set_interaction(interaction) self.canvas.set_interaction(interaction);
} }
fn set_renderer(&mut self, renderer: Box<dyn crate::backend::overlay::OverlayRenderer>) { fn set_renderer(&mut self, renderer: Box<dyn crate::backend::overlay::OverlayRenderer>) {
self.canvas.set_renderer(renderer) self.canvas.set_renderer(renderer);
} }
} }
@@ -521,7 +520,7 @@ impl InteractionHandler for KeyboardBackend {
hit: &crate::backend::input::PointerHit, hit: &crate::backend::input::PointerHit,
pressed: bool, pressed: bool,
) { ) {
self.canvas.on_pointer(app, hit, pressed) self.canvas.on_pointer(app, hit, pressed);
} }
fn on_scroll( fn on_scroll(
&mut self, &mut self,
@@ -530,10 +529,10 @@ impl InteractionHandler for KeyboardBackend {
delta_y: f32, delta_y: f32,
delta_x: f32, delta_x: f32,
) { ) {
self.canvas.on_scroll(app, hit, delta_y, delta_x) self.canvas.on_scroll(app, hit, delta_y, delta_x);
} }
fn on_left(&mut self, app: &mut AppState, pointer: usize) { fn on_left(&mut self, app: &mut AppState, pointer: usize) {
self.canvas.on_left(app, pointer) self.canvas.on_left(app, pointer);
} }
fn on_hover( fn on_hover(
&mut self, &mut self,

View File

@@ -50,8 +50,7 @@ impl OverlayRenderer for MirrorRenderer {
fn should_render(&mut self, app: &mut AppState) -> anyhow::Result<ShouldRender> { fn should_render(&mut self, app: &mut AppState) -> anyhow::Result<ShouldRender> {
self.renderer self.renderer
.as_mut() .as_mut()
.map(|r| r.should_render(app)) .map_or(Ok(ShouldRender::Unable), |r| r.should_render(app))
.unwrap_or(Ok(ShouldRender::Unable))
} }
fn render( fn render(
&mut self, &mut self,
@@ -90,7 +89,7 @@ impl OverlayRenderer for MirrorRenderer {
)); ));
} }
Err(e) => { Err(e) => {
log::warn!("Failed to create mirror due to PipeWire error: {:?}", e); log::warn!("Failed to create mirror due to PipeWire error: {e:?}");
self.renderer = None; self.renderer = None;
// drop self // drop self
app.tasks app.tasks
@@ -112,7 +111,7 @@ impl OverlayRenderer for MirrorRenderer {
app.tasks.enqueue(TaskType::Overlay( app.tasks.enqueue(TaskType::Overlay(
OverlaySelector::Name(self.name.clone()), OverlaySelector::Name(self.name.clone()),
Box::new(move |_app, o| { Box::new(move |_app, o| {
o.interaction_transform = ui_transform(&[extent[0], extent[1]]); o.interaction_transform = ui_transform([extent[0], extent[1]]);
}), }),
)); ));
} }
@@ -146,7 +145,7 @@ pub fn new_mirror(
name: Arc<str>, name: Arc<str>,
show_hide: bool, show_hide: bool,
session: &AppSession, session: &AppSession,
) -> Option<(OverlayState, Box<dyn OverlayBackend>)> { ) -> (OverlayState, Box<dyn OverlayBackend>) {
let state = OverlayState { let state = OverlayState {
name: name.clone(), name: name.clone(),
show_hide, show_hide,
@@ -159,5 +158,5 @@ pub fn new_mirror(
..Default::default() ..Default::default()
}); });
Some((state, backend)) (state, backend)
} }

View File

@@ -9,6 +9,7 @@ use std::{
}; };
use vulkano::{ use vulkano::{
command_buffer::CommandBufferUsage, command_buffer::CommandBufferUsage,
format::Format,
image::{sampler::Filter, view::ImageView, Image}, image::{sampler::Filter, view::ImageView, Image},
pipeline::graphics::color_blend::AttachmentBlend, pipeline::graphics::color_blend::AttachmentBlend,
}; };
@@ -26,7 +27,7 @@ use wlx_capture::{
use { use {
crate::config_io, crate::config_io,
std::error::Error, std::error::Error,
std::{ops::Deref, path::PathBuf, task}, std::{path::PathBuf, task},
wlx_capture::pipewire::PipewireCapture, wlx_capture::pipewire::PipewireCapture,
wlx_capture::pipewire::PipewireSelectScreenResult, wlx_capture::pipewire::PipewireSelectScreenResult,
}; };
@@ -64,7 +65,7 @@ use crate::{
}; };
#[cfg(feature = "wayland")] #[cfg(feature = "wayland")]
pub(crate) type WlxClientAlias = wlx_capture::wayland::WlxClient; pub type WlxClientAlias = wlx_capture::wayland::WlxClient;
#[cfg(not(feature = "wayland"))] #[cfg(not(feature = "wayland"))]
pub(crate) type WlxClientAlias = (); pub(crate) type WlxClientAlias = ();
@@ -91,7 +92,7 @@ pub struct ScreenInteractionHandler {
mouse_transform: Affine2, mouse_transform: Affine2,
} }
impl ScreenInteractionHandler { impl ScreenInteractionHandler {
fn new(pos: Vec2, size: Vec2, transform: Transform) -> ScreenInteractionHandler { fn new(pos: Vec2, size: Vec2, transform: Transform) -> Self {
let transform = match transform { let transform = match transform {
Transform::_90 | Transform::Flipped90 => Affine2::from_cols( Transform::_90 | Transform::Flipped90 => Affine2::from_cols(
vec2(0., size.y), vec2(0., size.y),
@@ -111,7 +112,7 @@ impl ScreenInteractionHandler {
_ => Affine2::from_cols(vec2(size.x, 0.), vec2(0., size.y), pos), _ => Affine2::from_cols(vec2(size.x, 0.), vec2(0., size.y), pos),
}; };
ScreenInteractionHandler { Self {
mouse_transform: transform, mouse_transform: transform,
} }
} }
@@ -127,7 +128,7 @@ impl InteractionHandler for ScreenInteractionHandler {
{ {
let pos = self.mouse_transform.transform_point2(hit.uv); let pos = self.mouse_transform.transform_point2(hit.uv);
app.hid_provider.mouse_move(pos); app.hid_provider.mouse_move(pos);
set_next_move(app.session.config.mouse_move_interval_ms as u64); set_next_move(u64::from(app.session.config.mouse_move_interval_ms));
} }
None None
} }
@@ -139,7 +140,7 @@ impl InteractionHandler for ScreenInteractionHandler {
}; };
if pressed { if pressed {
set_next_move(app.session.config.click_freeze_time_ms as u64); set_next_move(u64::from(app.session.config.click_freeze_time_ms));
} }
app.hid_provider.send_button(btn, pressed); app.hid_provider.send_button(btn, pressed);
@@ -152,7 +153,7 @@ impl InteractionHandler for ScreenInteractionHandler {
} }
fn on_scroll(&mut self, app: &mut AppState, _hit: &PointerHit, delta_y: f32, delta_x: f32) { fn on_scroll(&mut self, app: &mut AppState, _hit: &PointerHit, delta_y: f32, delta_x: f32) {
app.hid_provider app.hid_provider
.wheel((delta_y * 64.) as i32, (delta_x * 64.) as i32) .wheel((delta_y * 64.) as i32, (delta_x * 64.) as i32);
} }
fn on_left(&mut self, _app: &mut AppState, _hand: usize) {} fn on_left(&mut self, _app: &mut AppState, _hand: usize) {}
} }
@@ -165,7 +166,7 @@ struct ScreenPipeline {
} }
impl ScreenPipeline { impl ScreenPipeline {
fn new(extent: &[u32; 3], app: &mut AppState) -> anyhow::Result<ScreenPipeline> { fn new(extent: &[u32; 3], app: &mut AppState) -> anyhow::Result<Self> {
let Ok(shaders) = app.graphics.shared_shaders.read() else { let Ok(shaders) = app.graphics.shared_shaders.read() else {
return Err(anyhow::anyhow!("Could not lock shared shaders for reading")); return Err(anyhow::anyhow!("Could not lock shared shaders for reading"));
}; };
@@ -179,7 +180,7 @@ impl ScreenPipeline {
let extentf = [extent[0] as f32, extent[1] as f32]; let extentf = [extent[0] as f32, extent[1] as f32];
Ok(ScreenPipeline { Ok(Self {
mouse: None, mouse: None,
pipeline, pipeline,
extentf, extentf,
@@ -236,15 +237,15 @@ impl ScreenPipeline {
let vertex_buffer = app.graphics.upload_verts( let vertex_buffer = app.graphics.upload_verts(
self.extentf[0], self.extentf[0],
self.extentf[1], self.extentf[1],
mouse.x * self.extentf[0] - half_size, mouse.x.mul_add(self.extentf[0], -half_size),
mouse.y * self.extentf[1] - half_size, mouse.y.mul_add(self.extentf[1], -half_size),
size, size,
size, size,
)?; )?;
let set0 = self let set0 = self
.pipeline .pipeline
.uniform_sampler(0, mouse_view.clone(), Filter::Nearest)?; .uniform_sampler(0, mouse_view, Filter::Nearest)?;
let pass = self.pipeline.create_pass( let pass = self.pipeline.create_pass(
self.extentf, self.extentf,
@@ -275,8 +276,8 @@ impl ScreenRenderer {
pub fn new_raw( pub fn new_raw(
name: Arc<str>, name: Arc<str>,
capture: Box<dyn WlxCapture<WlxCaptureIn, WlxCaptureOut>>, capture: Box<dyn WlxCapture<WlxCaptureIn, WlxCaptureOut>>,
) -> ScreenRenderer { ) -> Self {
ScreenRenderer { Self {
name, name,
capture, capture,
pipeline: None, pipeline: None,
@@ -286,11 +287,11 @@ impl ScreenRenderer {
} }
#[cfg(feature = "wayland")] #[cfg(feature = "wayland")]
pub fn new_wlr_dmabuf(output: &WlxOutput) -> Option<ScreenRenderer> { pub fn new_wlr_dmabuf(output: &WlxOutput) -> Option<Self> {
let client = WlxClient::new()?; let client = WlxClient::new()?;
let capture = WlrDmabufCapture::new(client, output.id); let capture = WlrDmabufCapture::new(client, output.id);
Some(ScreenRenderer { Some(Self {
name: output.name.clone(), name: output.name.clone(),
capture: Box::new(capture), capture: Box::new(capture),
pipeline: None, pipeline: None,
@@ -300,11 +301,11 @@ impl ScreenRenderer {
} }
#[cfg(feature = "wayland")] #[cfg(feature = "wayland")]
pub fn new_wlr_screencopy(output: &WlxOutput) -> Option<ScreenRenderer> { pub fn new_wlr_screencopy(output: &WlxOutput) -> Option<Self> {
let client = WlxClient::new()?; let client = WlxClient::new()?;
let capture = WlrScreencopyCapture::new(client, output.id); let capture = WlrScreencopyCapture::new(client, output.id);
Some(ScreenRenderer { Some(Self {
name: output.name.clone(), name: output.name.clone(),
capture: Box::new(capture), capture: Box::new(capture),
pipeline: None, pipeline: None,
@@ -318,10 +319,7 @@ impl ScreenRenderer {
output: &WlxOutput, output: &WlxOutput,
token: Option<&str>, token: Option<&str>,
session: &AppSession, session: &AppSession,
) -> anyhow::Result<( ) -> anyhow::Result<(Self, Option<String> /* pipewire restore token */)> {
ScreenRenderer,
Option<String>, /* pipewire restore token */
)> {
let name = output.name.clone(); let name = output.name.clone();
let embed_mouse = !session.config.double_cursor_fix; let embed_mouse = !session.config.double_cursor_fix;
@@ -346,7 +344,7 @@ impl ScreenRenderer {
let capture = PipewireCapture::new(name, node_id); let capture = PipewireCapture::new(name, node_id);
Ok(( Ok((
ScreenRenderer { Self {
name: output.name.clone(), name: output.name.clone(),
capture: Box::new(capture), capture: Box::new(capture),
pipeline: None, pipeline: None,
@@ -358,10 +356,10 @@ impl ScreenRenderer {
} }
#[cfg(feature = "x11")] #[cfg(feature = "x11")]
pub fn new_xshm(screen: Arc<XshmScreen>) -> ScreenRenderer { pub fn new_xshm(screen: Arc<XshmScreen>) -> Self {
let capture = XshmCapture::new(screen.clone()); let capture = XshmCapture::new(screen.clone());
ScreenRenderer { Self {
name: screen.name.clone(), name: screen.name.clone(),
capture: Box::new(capture), capture: Box::new(capture),
pipeline: None, pipeline: None,
@@ -384,6 +382,39 @@ pub struct WlxCaptureOut {
mouse: Option<MouseMeta>, mouse: Option<MouseMeta>,
} }
fn upload_image(
me: &WlxCaptureIn,
width: u32,
height: u32,
format: Format,
data: &[u8],
) -> Option<Arc<Image>> {
let mut upload = match me
.graphics
.create_command_buffer(CommandBufferUsage::OneTimeSubmit)
{
Ok(x) => x,
Err(e) => {
log::error!("{}: Could not create vkCommandBuffer: {:?}", me.name, e);
return None;
}
};
let image = match upload.texture2d_raw(width, height, format, data) {
Ok(x) => x,
Err(e) => {
log::error!("{}: Could not create vkImage: {:?}", me.name, e);
return None;
}
};
if let Err(e) = upload.build_and_execute_now() {
log::error!("{}: Could not execute upload: {:?}", me.name, e);
return None;
}
Some(image)
}
fn receive_callback(me: &WlxCaptureIn, frame: wlx_frame::WlxFrame) -> Option<WlxCaptureOut> { fn receive_callback(me: &WlxCaptureIn, frame: wlx_frame::WlxFrame) -> Option<WlxCaptureOut> {
match frame { match frame {
WlxFrame::Dmabuf(frame) => { WlxFrame::Dmabuf(frame) => {
@@ -400,11 +431,7 @@ fn receive_callback(me: &WlxCaptureIn, frame: wlx_frame::WlxFrame) -> Option<Wlx
mouse: None, mouse: None,
}), }),
Err(e) => { Err(e) => {
log::error!( log::error!("{}: Failed to create DMA-buf vkImage: {}", me.name, e);
"{}: Failed to create DMA-buf vkImage: {}",
me.name,
e.to_string()
);
None None
} }
} }
@@ -424,7 +451,7 @@ fn receive_callback(me: &WlxCaptureIn, frame: wlx_frame::WlxFrame) -> Option<Wlx
}; };
let len = frame.plane.stride as usize * frame.format.height as usize; let len = frame.plane.stride as usize * frame.format.height as usize;
let offset = frame.plane.offset as i64; let offset = i64::from(frame.plane.offset);
let map = unsafe { let map = unsafe {
libc::mmap( libc::mmap(
@@ -437,35 +464,15 @@ fn receive_callback(me: &WlxCaptureIn, frame: wlx_frame::WlxFrame) -> Option<Wlx
) )
} as *const u8; } as *const u8;
let pixels = unsafe { slice::from_raw_parts(map, len) }; let data = unsafe { slice::from_raw_parts(map, len) };
let mut upload = match me let image = {
.graphics let maybe_image =
.create_command_buffer(CommandBufferUsage::OneTimeSubmit) upload_image(me, frame.format.width, frame.format.height, format, data);
{
Ok(x) => x,
Err(e) => {
log::error!("{}: Could not create vkCommandBuffer: {:?}", me.name, e);
return None;
}
};
let image = unsafe { libc::munmap(map as *mut _, len) };
match upload.texture2d_raw(frame.format.width, frame.format.height, format, pixels) maybe_image
{ }?;
Ok(x) => x,
Err(e) => {
log::error!("{}: Could not create vkImage: {:?}", me.name, e);
return None;
}
};
if let Err(e) = upload.build_and_execute_now() {
log::error!("{}: Could not execute upload: {:?}", me.name, e);
return None;
}
unsafe { libc::munmap(map as *mut _, len) };
Some(WlxCaptureOut { Some(WlxCaptureOut {
image, image,
@@ -484,33 +491,8 @@ fn receive_callback(me: &WlxCaptureIn, frame: wlx_frame::WlxFrame) -> Option<Wlx
} }
}; };
let mut upload = match me let data = unsafe { slice::from_raw_parts(frame.ptr as *const u8, frame.size) };
.graphics let image = upload_image(me, frame.format.width, frame.format.height, format, data)?;
.create_command_buffer(CommandBufferUsage::OneTimeSubmit)
{
Ok(x) => x,
Err(e) => {
log::error!("{}: Could not create vkCommandBuffer: {:?}", me.name, e);
return None;
}
};
let pixels = unsafe { slice::from_raw_parts(frame.ptr as *const u8, frame.size) };
let image =
match upload.texture2d_raw(frame.format.width, frame.format.height, format, pixels)
{
Ok(x) => x,
Err(e) => {
log::error!("{}: Could not create vkImage: {:?}", me.name, e);
return None;
}
};
if let Err(e) = upload.build_and_execute_now() {
log::error!("{}: Could not execute upload: {:?}", me.name, e);
return None;
}
Some(WlxCaptureOut { Some(WlxCaptureOut {
image, image,
@@ -547,7 +529,7 @@ impl OverlayRenderer for ScreenRenderer {
return vec![]; return vec![];
} }
if !allow_dmabuf { if !allow_dmabuf {
log::info!("Not using DMA-buf capture due to {}", capture_method); log::info!("Not using DMA-buf capture due to {capture_method}");
return vec![]; return vec![];
} }
log::warn!("Using DMA-buf capture. If screens are blank for you, switch to SHM using:"); log::warn!("Using DMA-buf capture. If screens are blank for you, switch to SHM using:");
@@ -604,7 +586,7 @@ impl OverlayRenderer for ScreenRenderer {
return Ok(ShouldRender::Unable); return Ok(ShouldRender::Unable);
} }
for frame in self.capture.receive().into_iter() { if let Some(frame) = self.capture.receive() {
self.cur_frame = Some(frame); self.cur_frame = Some(frame);
} }
@@ -623,7 +605,7 @@ impl OverlayRenderer for ScreenRenderer {
upload.build_and_execute_now()?; upload.build_and_execute_now()?;
pipeline pipeline
}); });
}; }
if self.cur_frame.is_some() { if self.cur_frame.is_some() {
Ok(ShouldRender::Should) Ok(ShouldRender::Should)
@@ -669,6 +651,7 @@ impl OverlayRenderer for ScreenRenderer {
} }
#[cfg(feature = "wayland")] #[cfg(feature = "wayland")]
#[allow(clippy::useless_let_if_seq)]
pub fn create_screen_renderer_wl( pub fn create_screen_renderer_wl(
output: &WlxOutput, output: &WlxOutput,
has_wlr_dmabuf: bool, has_wlr_dmabuf: bool,
@@ -690,17 +673,15 @@ pub fn create_screen_renderer_wl(
if capture.is_none() { if capture.is_none() {
log::info!("{}: Using Pipewire capture", &output.name); log::info!("{}: Using Pipewire capture", &output.name);
let display_name = output.name.deref(); let display_name = &*output.name;
// Find existing token by display // Find existing token by display
let token = pw_token_store.arc_get(display_name).map(|s| s.as_str()); let token = pw_token_store
.arc_get(display_name)
.map(std::string::String::as_str);
if let Some(t) = token { if let Some(t) = token {
log::info!( log::info!("Found existing Pipewire token for display {display_name}: {t}");
"Found existing Pipewire token for display {}: {}",
display_name,
t
);
} }
match ScreenRenderer::new_pw(output, token, session) { match ScreenRenderer::new_pw(output, token, session) {
@@ -709,7 +690,7 @@ pub fn create_screen_renderer_wl(
if let Some(token) = restore_token { if let Some(token) = restore_token {
if pw_token_store.arc_set(display_name.into(), token.clone()) { if pw_token_store.arc_set(display_name.into(), token.clone()) {
log::info!("Adding Pipewire token {}", token); log::info!("Adding Pipewire token {token}");
} }
} }
} }
@@ -773,7 +754,7 @@ fn create_screen_state(
}; };
OverlayState { OverlayState {
name: name.clone(), name,
keyboard_focus: Some(KeyboardFocus::PhysicalScreen), keyboard_focus: Some(KeyboardFocus::PhysicalScreen),
grabbable: true, grabbable: true,
recenter: true, recenter: true,
@@ -816,23 +797,19 @@ pub fn load_pw_token_config() -> Result<PwTokenMap, Box<dyn Error>> {
Ok(conf.pw_tokens) Ok(conf.pw_tokens)
} }
pub(crate) struct ScreenCreateData { pub struct ScreenCreateData {
pub screens: Vec<(ScreenMeta, OverlayState, Box<SplitOverlayBackend>)>, pub screens: Vec<(ScreenMeta, OverlayState, Box<SplitOverlayBackend>)>,
} }
#[cfg(not(feature = "wayland"))] #[cfg(not(feature = "wayland"))]
pub fn create_screens_wayland( pub fn create_screens_wayland(_wl: &mut WlxClientAlias, _app: &AppState) -> ScreenCreateData {
_wl: &mut WlxClientAlias, ScreenCreateData {
_app: &AppState, screens: Vec::default(),
) -> anyhow::Result<ScreenCreateData> { }
anyhow::bail!("Wayland support not enabled")
} }
#[cfg(feature = "wayland")] #[cfg(feature = "wayland")]
pub fn create_screens_wayland( pub fn create_screens_wayland(wl: &mut WlxClientAlias, app: &mut AppState) -> ScreenCreateData {
wl: &mut WlxClientAlias,
app: &mut AppState,
) -> anyhow::Result<ScreenCreateData> {
let mut screens = vec![]; let mut screens = vec![];
// Load existing Pipewire tokens from file // Load existing Pipewire tokens from file
@@ -842,7 +819,7 @@ pub fn create_screens_wayland(
let has_wlr_dmabuf = wl.maybe_wlr_dmabuf_mgr.is_some(); let has_wlr_dmabuf = wl.maybe_wlr_dmabuf_mgr.is_some();
let has_wlr_screencopy = wl.maybe_wlr_screencopy_mgr.is_some(); let has_wlr_screencopy = wl.maybe_wlr_screencopy_mgr.is_some();
for (id, output) in wl.outputs.iter() { for (id, output) in &wl.outputs {
if app.screens.iter().any(|s| s.name == output.name) { if app.screens.iter().any(|s| s.name == output.name) {
continue; continue;
} }
@@ -886,7 +863,7 @@ pub fn create_screens_wayland(
if pw_tokens_copy != pw_tokens { if pw_tokens_copy != pw_tokens {
// Token list changed, re-create token config file // Token list changed, re-create token config file
if let Err(err) = save_pw_token_config(pw_tokens) { if let Err(err) = save_pw_token_config(pw_tokens) {
log::error!("Failed to save Pipewire token config: {}", err); log::error!("Failed to save Pipewire token config: {err}");
} }
} }
@@ -898,7 +875,7 @@ pub fn create_screens_wayland(
app.hid_provider app.hid_provider
.set_desktop_origin(vec2(origin.0 as f32, origin.1 as f32)); .set_desktop_origin(vec2(origin.0 as f32, origin.1 as f32));
Ok(ScreenCreateData { screens }) ScreenCreateData { screens }
} }
#[cfg(not(feature = "x11"))] #[cfg(not(feature = "x11"))]
@@ -918,7 +895,7 @@ pub fn create_screens_x11pw(app: &mut AppState) -> anyhow::Result<ScreenCreateDa
// Load existing Pipewire tokens from file // Load existing Pipewire tokens from file
let mut pw_tokens: PwTokenMap = load_pw_token_config().unwrap_or_default(); let mut pw_tokens: PwTokenMap = load_pw_token_config().unwrap_or_default();
let pw_tokens_copy = pw_tokens.clone(); let pw_tokens_copy = pw_tokens.clone();
let token = pw_tokens.arc_get("x11").map(|s| s.as_str()); let token = pw_tokens.arc_get("x11").map(std::string::String::as_str);
let embed_mouse = !app.session.config.double_cursor_fix; let embed_mouse = !app.session.config.double_cursor_fix;
let select_screen_result = select_pw_screen( let select_screen_result = select_pw_screen(
@@ -932,13 +909,13 @@ pub fn create_screens_x11pw(app: &mut AppState) -> anyhow::Result<ScreenCreateDa
if let Some(restore_token) = select_screen_result.restore_token { if let Some(restore_token) = select_screen_result.restore_token {
if pw_tokens.arc_set("x11".into(), restore_token.clone()) { if pw_tokens.arc_set("x11".into(), restore_token.clone()) {
log::info!("Adding Pipewire token {}", restore_token); log::info!("Adding Pipewire token {restore_token}");
} }
} }
if pw_tokens_copy != pw_tokens { if pw_tokens_copy != pw_tokens {
// Token list changed, re-create token config file // Token list changed, re-create token config file
if let Err(err) = save_pw_token_config(pw_tokens) { if let Err(err) = save_pw_token_config(pw_tokens) {
log::error!("Failed to save Pipewire token config: {}", err); log::error!("Failed to save Pipewire token config: {err}");
} }
} }
@@ -1064,6 +1041,7 @@ pub enum Transform {
_90, _90,
_180, _180,
_270, _270,
Flipped,
Flipped90, Flipped90,
Flipped180, Flipped180,
Flipped270, Flipped270,
@@ -1071,17 +1049,16 @@ pub enum Transform {
#[cfg(feature = "wayland")] #[cfg(feature = "wayland")]
impl From<wl_output::Transform> for Transform { impl From<wl_output::Transform> for Transform {
fn from(t: wl_output::Transform) -> Transform { fn from(t: wl_output::Transform) -> Self {
match t { match t {
wl_output::Transform::Normal => Transform::Normal, wl_output::Transform::_90 => Self::_90,
wl_output::Transform::_90 => Transform::_90, wl_output::Transform::_180 => Self::_180,
wl_output::Transform::_180 => Transform::_180, wl_output::Transform::_270 => Self::_270,
wl_output::Transform::_270 => Transform::_270, wl_output::Transform::Flipped => Self::Flipped,
wl_output::Transform::Flipped => Transform::Flipped180, wl_output::Transform::Flipped90 => Self::Flipped90,
wl_output::Transform::Flipped90 => Transform::Flipped90, wl_output::Transform::Flipped180 => Self::Flipped180,
wl_output::Transform::Flipped180 => Transform::Flipped180, wl_output::Transform::Flipped270 => Self::Flipped270,
wl_output::Transform::Flipped270 => Transform::Flipped270, _ => Self::Normal,
_ => Transform::Normal,
} }
} }
} }
@@ -1093,7 +1070,7 @@ fn extent_from_format(fmt: FrameFormat, config: &GeneralConfig) -> [u32; 3] {
fn extent_from_res(width: u32, height: u32, config: &GeneralConfig) -> [u32; 3] { fn extent_from_res(width: u32, height: u32, config: &GeneralConfig) -> [u32; 3] {
// screens above a certain resolution will have severe aliasing // screens above a certain resolution will have severe aliasing
let height_limit = if config.screen_render_down { let height_limit = if config.screen_render_down {
config.screen_max_height.min(2560) as u32 u32::from(config.screen_max_height.min(2560))
} else { } else {
2560 2560
}; };
@@ -1111,7 +1088,6 @@ fn affine_from_format(format: &FrameFormat) -> Affine3A {
}; };
match format.transform { match format.transform {
wlx_frame::Transform::Normal => Affine3A::IDENTITY,
wlx_frame::Transform::Rotated90 => Affine3A::from_rotation_z(-PI / 2.0), wlx_frame::Transform::Rotated90 => Affine3A::from_rotation_z(-PI / 2.0),
wlx_frame::Transform::Rotated180 => Affine3A::from_rotation_z(PI), wlx_frame::Transform::Rotated180 => Affine3A::from_rotation_z(PI),
wlx_frame::Transform::Rotated270 => Affine3A::from_rotation_z(PI / 2.0), wlx_frame::Transform::Rotated270 => Affine3A::from_rotation_z(PI / 2.0),
@@ -1125,7 +1101,7 @@ fn affine_from_format(format: &FrameFormat) -> Affine3A {
wlx_frame::Transform::Flipped270 => { wlx_frame::Transform::Flipped270 => {
Affine3A::from_scale(FLIP_X) * Affine3A::from_rotation_z(PI / 2.0) Affine3A::from_scale(FLIP_X) * Affine3A::from_rotation_z(PI / 2.0)
} }
wlx_frame::Transform::Undefined => Affine3A::IDENTITY, _ => Affine3A::IDENTITY,
} }
} }
@@ -1141,9 +1117,9 @@ fn best_match<'a>(
return best; return best;
}; };
let mut best_dist = best let mut best_dist = best.map_or(i32::MAX, |b| {
.map(|b| (b.monitor.x() - position.0).abs() + (b.monitor.y() - position.1).abs()) (b.monitor.x() - position.0).abs() + (b.monitor.y() - position.1).abs()
.unwrap_or(i32::MAX); });
for stream in streams { for stream in streams {
log::debug!("checking: {:?}", stream.monitor); log::debug!("checking: {:?}", stream.monitor);
let dist = let dist =
@@ -1158,6 +1134,7 @@ fn best_match<'a>(
} }
#[cfg(feature = "pipewire")] #[cfg(feature = "pipewire")]
#[allow(clippy::fn_params_excessive_bools)]
fn select_pw_screen( fn select_pw_screen(
instructions: &str, instructions: &str,
token: Option<&str>, token: Option<&str>,
@@ -1181,7 +1158,7 @@ fn select_pw_screen(
task::Poll::Ready(result) => return result, task::Poll::Ready(result) => return result,
task::Poll::Pending => { task::Poll::Pending => {
if Instant::now() >= print_at { if Instant::now() >= print_at {
log::info!("{}", instructions); log::info!("{instructions}");
if let Ok(sender) = DbusNotificationSender::new() { if let Ok(sender) = DbusNotificationSender::new() {
if let Ok(id) = sender.notify_send(instructions, "", 2, 0, 0, true) { if let Ok(id) = sender.notify_send(instructions, "", 2, 0, 0, true) {
notify = Some((sender, id)); notify = Some((sender, id));
@@ -1193,7 +1170,6 @@ fn select_pw_screen(
std::thread::sleep(Duration::from_millis(10)); std::thread::sleep(Duration::from_millis(10));
}) })
.await; .await;
continue;
} }
} }
} }

View File

@@ -46,8 +46,8 @@ pub struct Toast {
#[allow(dead_code)] #[allow(dead_code)]
impl Toast { impl Toast {
pub fn new(topic: ToastTopic, title: Arc<str>, body: Arc<str>) -> Self { pub const fn new(topic: ToastTopic, title: Arc<str>, body: Arc<str>) -> Self {
Toast { Self {
title, title,
body, body,
opacity: 1.0, opacity: 1.0,
@@ -56,15 +56,15 @@ impl Toast {
topic, topic,
} }
} }
pub fn with_timeout(mut self, timeout: f32) -> Self { pub const fn with_timeout(mut self, timeout: f32) -> Self {
self.timeout = timeout; self.timeout = timeout;
self self
} }
pub fn with_opacity(mut self, opacity: f32) -> Self { pub const fn with_opacity(mut self, opacity: f32) -> Self {
self.opacity = opacity; self.opacity = opacity;
self self
} }
pub fn with_sound(mut self, sound: bool) -> Self { pub const fn with_sound(mut self, sound: bool) -> Self {
self.sound = sound; self.sound = sound;
self self
} }
@@ -93,7 +93,7 @@ impl Toast {
// frame, only the first one gets created // frame, only the first one gets created
app.tasks.enqueue_at( app.tasks.enqueue_at(
TaskType::CreateOverlay( TaskType::CreateOverlay(
selector.clone(), selector,
Box::new(move |app| { Box::new(move |app| {
let mut maybe_toast = new_toast(self, app); let mut maybe_toast = new_toast(self, app);
if let Some((state, _)) = maybe_toast.as_mut() { if let Some((state, _)) = maybe_toast.as_mut() {
@@ -139,13 +139,19 @@ fn new_toast(toast: Toast, app: &mut AppState) -> Option<(OverlayState, Box<dyn
} }
}; };
let title = if !toast.title.is_empty() { let title = if toast.title.is_empty() {
toast.title
} else {
"Notification".into() "Notification".into()
} else {
toast.title
}; };
let mut size = if !toast.body.is_empty() { let mut size = if toast.body.is_empty() {
let (w, h) = app
.fc
.get_text_size(&title, FONT_SIZE, app.graphics.clone())
.ok()?;
(w, h + 20.)
} else {
let (w0, _) = app let (w0, _) = app
.fc .fc
.get_text_size(&title, FONT_SIZE, app.graphics.clone()) .get_text_size(&title, FONT_SIZE, app.graphics.clone())
@@ -155,12 +161,6 @@ fn new_toast(toast: Toast, app: &mut AppState) -> Option<(OverlayState, Box<dyn
.get_text_size(&toast.body, FONT_SIZE, app.graphics.clone()) .get_text_size(&toast.body, FONT_SIZE, app.graphics.clone())
.ok()?; .ok()?;
(w0.max(w1), h1 + 50.) (w0.max(w1), h1 + 50.)
} else {
let (w, h) = app
.fc
.get_text_size(&title, FONT_SIZE, app.graphics.clone())
.ok()?;
(w, h + 20.)
}; };
let og_width = size.0; let og_width = size.0;
@@ -180,15 +180,15 @@ fn new_toast(toast: Toast, app: &mut AppState) -> Option<(OverlayState, Box<dyn
canvas.bg_color = color_parse("#1e2030").unwrap(); // want panic canvas.bg_color = color_parse("#1e2030").unwrap(); // want panic
canvas.panel(0., 0., size.0, size.1, 16.); canvas.panel(0., 0., size.0, size.1, 16.);
if !toast.body.is_empty() { if toast.body.is_empty() {
canvas.label_centered(PADDING.0, 0., og_width, size.1, 16., title);
} else {
canvas.label(PADDING.0, 54., og_width, size.1 - 54., 3., toast.body); canvas.label(PADDING.0, 54., og_width, size.1 - 54., 3., toast.body);
canvas.fg_color = color_parse("#b8c0e0").unwrap(); // want panic canvas.fg_color = color_parse("#b8c0e0").unwrap(); // want panic
canvas.bg_color = color_parse("#24273a").unwrap(); // want panic canvas.bg_color = color_parse("#24273a").unwrap(); // want panic
canvas.panel(0., 0., size.0, 30., 16.); canvas.panel(0., 0., size.0, 30., 16.);
canvas.label_centered(PADDING.0, 16., og_width, FONT_SIZE as f32 + 2., 16., title); canvas.label_centered(PADDING.0, 16., og_width, FONT_SIZE as f32 + 2., 16., title);
} else {
canvas.label_centered(PADDING.0, 0., og_width, size.1, 16., title);
} }
let state = OverlayState { let state = OverlayState {
@@ -218,13 +218,13 @@ pub fn error_toast<ErrorType>(app: &mut AppState, title: &str, err: ErrorType)
where where
ErrorType: std::fmt::Display + std::fmt::Debug, ErrorType: std::fmt::Display + std::fmt::Debug,
{ {
log::error!("{}: {:?}", title, err); // More detailed version (use Debug) log::error!("{title}: {err:?}"); // More detailed version (use Debug)
// Brief version (use Display) // Brief version (use Display)
msg_err(app, &format!("{}: {}", title, err)); msg_err(app, &format!("{title}: {err}"));
} }
pub fn error_toast_str(app: &mut AppState, message: &str) { pub fn error_toast_str(app: &mut AppState, message: &str) {
log::error!("{}", message); log::error!("{message}");
msg_err(app, message); msg_err(app, message);
} }

View File

@@ -29,7 +29,7 @@ where
spawn_scale: config.width, spawn_scale: config.width,
spawn_point: state.session.config.watch_pos, spawn_point: state.session.config.watch_pos,
spawn_rotation: state.session.config.watch_rot, spawn_rotation: state.session.config.watch_rot,
interaction_transform: ui_transform(&config.size), interaction_transform: ui_transform(config.size),
relative_to, relative_to,
..Default::default() ..Default::default()
}, },
@@ -44,7 +44,7 @@ pub fn create_watch_canvas(
) -> anyhow::Result<Canvas<(), ModularData>> { ) -> anyhow::Result<Canvas<(), ModularData>> {
let config = config.unwrap_or_else(|| load_known_yaml::<ModularUiConfig>(ConfigType::Watch)); let config = config.unwrap_or_else(|| load_known_yaml::<ModularUiConfig>(ConfigType::Watch));
modular_canvas(&config.size, &config.elements, state) modular_canvas(config.size, &config.elements, state)
} }
pub fn watch_fade<D>(app: &mut AppState, watch: &mut OverlayData<D>) pub fn watch_fade<D>(app: &mut AppState, watch: &mut OverlayData<D>)

View File

@@ -41,14 +41,11 @@ pub struct WayVRContext {
} }
impl WayVRContext { impl WayVRContext {
pub fn new( pub const fn new(wvr: Rc<RefCell<WayVRData>>, display: wayvr::display::DisplayHandle) -> Self {
wvr: Rc<RefCell<WayVRData>>, Self {
display: wayvr::display::DisplayHandle, wayvr: wvr,
) -> anyhow::Result<Self> {
Ok(Self {
wayvr: wvr.clone(),
display, display,
}) }
} }
} }
@@ -67,7 +64,7 @@ pub struct WayVRData {
impl WayVRData { impl WayVRData {
pub fn new(config: wayvr::Config) -> anyhow::Result<Self> { pub fn new(config: wayvr::Config) -> anyhow::Result<Self> {
Ok(Self { Ok(Self {
display_handle_map: Default::default(), display_handle_map: HashMap::default(),
data: WayVR::new(config)?, data: WayVR::new(config)?,
overlays_to_create: Vec::new(), overlays_to_create: Vec::new(),
dashboard_executed: false, dashboard_executed: false,
@@ -87,7 +84,7 @@ impl WayVRData {
.any(|d| d.obj.name == candidate) .any(|d| d.obj.name == candidate)
{ {
if num > 0 { if num > 0 {
candidate = format!("{} ({})", candidate, num); candidate = format!("{candidate} ({num})");
} }
num += 1; num += 1;
} }
@@ -102,7 +99,7 @@ pub struct WayVRInteractionHandler {
} }
impl WayVRInteractionHandler { impl WayVRInteractionHandler {
pub fn new(context: Rc<RefCell<WayVRContext>>, mouse_transform: Affine2) -> Self { pub const fn new(context: Rc<RefCell<WayVRContext>>, mouse_transform: Affine2) -> Self {
Self { Self {
context, context,
mouse_transform, mouse_transform,
@@ -122,8 +119,8 @@ impl InteractionHandler for WayVRInteractionHandler {
if let Some(disp) = wayvr.state.displays.get(&ctx.display) { if let Some(disp) = wayvr.state.displays.get(&ctx.display) {
let pos = self.mouse_transform.transform_point2(hit.uv); let pos = self.mouse_transform.transform_point2(hit.uv);
let x = ((pos.x * disp.width as f32) as i32).max(0); let x = ((pos.x * f32::from(disp.width)) as i32).max(0);
let y = ((pos.y * disp.height as f32) as i32).max(0); let y = ((pos.y * f32::from(disp.height)) as i32).max(0);
let ctx = self.context.borrow(); let ctx = self.context.borrow();
wayvr.state.send_mouse_move(ctx.display, x as u32, y as u32); wayvr.state.send_mouse_move(ctx.display, x as u32, y as u32);
@@ -151,7 +148,7 @@ impl InteractionHandler for WayVRInteractionHandler {
if pressed { if pressed {
wayvr.state.send_mouse_down(ctx.display, index); wayvr.state.send_mouse_down(ctx.display, index);
} else { } else {
wayvr.state.send_mouse_up(ctx.display, index); wayvr.state.send_mouse_up(index);
} }
} }
} }
@@ -168,7 +165,7 @@ impl InteractionHandler for WayVRInteractionHandler {
.borrow_mut() .borrow_mut()
.data .data
.state .state
.send_mouse_scroll(ctx.display, delta_y, delta_x); .send_mouse_scroll(delta_y, delta_x);
} }
} }
@@ -199,7 +196,7 @@ impl WayVRRenderer {
Ok(Self { Ok(Self {
pipeline, pipeline,
context: Rc::new(RefCell::new(WayVRContext::new(wvr, display)?)), context: Rc::new(RefCell::new(WayVRContext::new(wvr, display))),
vk_image: None, vk_image: None,
vk_image_view: None, vk_image_view: None,
graphics: app.graphics.clone(), graphics: app.graphics.clone(),
@@ -220,10 +217,7 @@ fn get_or_create_display_by_name(
.session .session
.wayvr_config .wayvr_config
.get_display(disp_name) .get_display(disp_name)
.ok_or(anyhow::anyhow!( .ok_or_else(|| anyhow::anyhow!("Cannot find display named \"{}\"", disp_name))?
"Cannot find display named \"{}\"",
disp_name
))?
.clone(); .clone();
let disp_handle = wayvr.data.state.create_display( let disp_handle = wayvr.data.state.create_display(
@@ -302,6 +296,7 @@ where
}, },
)?; )?;
overlay.state.curvature = Some(0.15);
overlay.state.want_visible = true; overlay.state.want_visible = true;
overlay.state.spawn_scale = 2.0; overlay.state.spawn_scale = 2.0;
overlay.state.spawn_point = vec3a(0.0, -0.35, -1.75); overlay.state.spawn_point = vec3a(0.0, -0.35, -1.75);
@@ -312,25 +307,17 @@ where
unreachable!(); /* safe, not possible to trigger */ unreachable!(); /* safe, not possible to trigger */
}; };
// FIXME: overlay curvature needs to be dispatched for some unknown reason, this value is not set otherwise
app.tasks.enqueue(TaskType::Overlay(
OverlaySelector::Id(overlay.state.id),
Box::new(move |_app, o| {
o.curvature = Some(0.15);
}),
));
overlays.add(overlay); overlays.add(overlay);
let args_vec = match &conf_dash.args { let args_vec = &conf_dash
Some(args) => gen_args_vec(args), .args
None => vec![], .as_ref()
}; .map_or_else(Vec::new, |args| gen_args_vec(args.as_str()));
let env_vec = match &conf_dash.env { let env_vec = &conf_dash
Some(env) => gen_env_vec(env), .env
None => vec![], .as_ref()
}; .map_or_else(Vec::new, |env| gen_env_vec(env));
let mut userdata = HashMap::new(); let mut userdata = HashMap::new();
userdata.insert(String::from("type"), String::from("dashboard")); userdata.insert(String::from("type"), String::from("dashboard"));
@@ -339,8 +326,8 @@ where
let _process_handle_unused = wayvr.data.state.spawn_process( let _process_handle_unused = wayvr.data.state.spawn_process(
disp_handle, disp_handle,
&conf_dash.exec, &conf_dash.exec,
&args_vec, args_vec,
&env_vec, env_vec,
userdata, userdata,
)?; )?;
@@ -446,6 +433,7 @@ where
Ok(()) Ok(())
} }
#[allow(clippy::too_many_lines)]
pub fn tick_events<O>(app: &mut AppState, overlays: &mut OverlayContainer<O>) -> anyhow::Result<()> pub fn tick_events<O>(app: &mut AppState, overlays: &mut OverlayContainer<O>) -> anyhow::Result<()>
where where
O: Default, O: Default,
@@ -490,36 +478,42 @@ where
for result in res { for result in res {
match result { match result {
wayvr::TickTask::NewExternalProcess(req) => { wayvr::TickTask::NewExternalProcess(request) => {
let config = &app.session.wayvr_config; let config = &app.session.wayvr_config;
let disp_name = if let Some(display_name) = req.env.display_name { let disp_name = request.env.display_name.map_or_else(
config || {
.get_display(display_name.as_str()) config
.map(|_| display_name) .get_default_display()
} else { .map(|(display_name, _)| display_name)
config },
.get_default_display() |display_name| {
.map(|(display_name, _)| display_name) config
}; .get_display(display_name.as_str())
.map(|_| display_name)
},
);
if let Some(disp_name) = disp_name { if let Some(disp_name) = disp_name {
let mut wayvr = r_wayvr.borrow_mut(); let mut wayvr = r_wayvr.borrow_mut();
log::info!("Registering external process with PID {}", req.pid); log::info!("Registering external process with PID {}", request.pid);
let disp_handle = get_or_create_display_by_name(app, &mut wayvr, &disp_name)?; let disp_handle = get_or_create_display_by_name(app, &mut wayvr, &disp_name)?;
wayvr.data.state.add_external_process(disp_handle, req.pid); wayvr
.data
.state
.add_external_process(disp_handle, request.pid);
wayvr wayvr
.data .data
.state .state
.manager .manager
.add_client(wayvr::client::WayVRClient { .add_client(wayvr::client::WayVRClient {
client: req.client, client: request.client,
display_handle: disp_handle, display_handle: disp_handle,
pid: req.pid, pid: request.pid,
}); });
} }
} }
@@ -576,8 +570,8 @@ impl WayVRRenderer {
.create_command_buffer(CommandBufferUsage::OneTimeSubmit)?; .create_command_buffer(CommandBufferUsage::OneTimeSubmit)?;
let tex = upload.texture2d_raw( let tex = upload.texture2d_raw(
data.width as u32, u32::from(data.width),
data.height as u32, u32::from(data.height),
vulkano::format::Format::R8G8B8A8_UNORM, vulkano::format::Format::R8G8B8A8_UNORM,
&data.data, &data.data,
)?; )?;
@@ -615,8 +609,8 @@ impl WayVRRenderer {
let frame = DmabufFrame { let frame = DmabufFrame {
format: FrameFormat { format: FrameFormat {
width: disp.width as u32, width: u32::from(disp.width),
height: disp.height as u32, height: u32::from(disp.height),
fourcc: FourCC { fourcc: FourCC {
value: data.mod_info.fourcc, value: data.mod_info.fourcc,
}, },
@@ -674,7 +668,7 @@ impl OverlayRenderer for WayVRRenderer {
let redrawn = match wayvr.data.tick_display(ctx.display) { let redrawn = match wayvr.data.tick_display(ctx.display) {
Ok(r) => r, Ok(r) => r,
Err(e) => { Err(e) => {
log::error!("tick_display failed: {}", e); log::error!("tick_display failed: {e}");
return Ok(ShouldRender::Unable); return Ok(ShouldRender::Unable);
} }
}; };
@@ -699,7 +693,7 @@ impl OverlayRenderer for WayVRRenderer {
.data .data
.state .state
.get_render_data(ctx.display) .get_render_data(ctx.display)
.ok_or(anyhow::anyhow!("Failed to fetch render data"))? .ok_or_else(|| anyhow::anyhow!("Failed to fetch render data"))?
.clone(); .clone();
drop(wayvr); drop(wayvr);
@@ -712,7 +706,7 @@ impl OverlayRenderer for WayVRRenderer {
} }
wayvr::egl_data::RenderData::Software(data) => { wayvr::egl_data::RenderData::Software(data) => {
if let Some(new_frame) = &data { if let Some(new_frame) = &data {
self.ensure_software_data(new_frame)? self.ensure_software_data(new_frame)?;
} }
} }
} }
@@ -762,10 +756,10 @@ pub fn create_wayvr_display_overlay<O>(
where where
O: Default, O: Default,
{ {
let transform = ui_transform(&[display_width as u32, display_height as u32]); let transform = ui_transform([u32::from(display_width), u32::from(display_height)]);
let state = OverlayState { let state = OverlayState {
name: format!("WayVR - {}", name).into(), name: format!("WayVR - {name}").into(),
keyboard_focus: Some(KeyboardFocus::WayVR), keyboard_focus: Some(KeyboardFocus::WayVR),
want_visible: true, want_visible: true,
interactable: true, interactable: true,
@@ -817,16 +811,13 @@ fn action_app_click<O>(
where where
O: Default, O: Default,
{ {
let wayvr = app.get_wayvr()?.clone(); let wayvr = app.get_wayvr()?;
let catalog = app let catalog = app
.session .session
.wayvr_config .wayvr_config
.get_catalog(catalog_name) .get_catalog(catalog_name)
.ok_or(anyhow::anyhow!( .ok_or_else(|| anyhow::anyhow!("Failed to get catalog \"{}\"", catalog_name))?
"Failed to get catalog \"{}\"",
catalog_name
))?
.clone(); .clone();
if let Some(app_entry) = catalog.get_app(app_name) { if let Some(app_entry) = catalog.get_app(app_name) {
@@ -838,22 +829,22 @@ where
&app_entry.target_display.to_lowercase(), &app_entry.target_display.to_lowercase(),
)?; )?;
let args_vec = match &app_entry.args { let args_vec = &app_entry
Some(args) => gen_args_vec(args), .args
None => vec![], .as_ref()
}; .map_or_else(Vec::new, |args| gen_args_vec(args.as_str()));
let env_vec = match &app_entry.env { let env_vec = &app_entry
Some(env) => gen_env_vec(env), .env
None => vec![], .as_ref()
}; .map_or_else(Vec::new, |env| gen_env_vec(env));
// Terminate existing process if required // Terminate existing process if required
if let Some(process_handle) = if let Some(process_handle) =
wayvr wayvr
.data .data
.state .state
.process_query(disp_handle, &app_entry.exec, &args_vec, &env_vec) .process_query(disp_handle, &app_entry.exec, args_vec, env_vec)
{ {
// Terminate process // Terminate process
wayvr.data.terminate_process(process_handle); wayvr.data.terminate_process(process_handle);
@@ -862,9 +853,9 @@ where
wayvr.data.state.spawn_process( wayvr.data.state.spawn_process(
disp_handle, disp_handle,
&app_entry.exec, &app_entry.exec,
&args_vec, args_vec,
&env_vec, env_vec,
Default::default(), HashMap::default(),
)?; )?;
show_display::<O>(&mut wayvr, overlays, app_entry.target_display.as_str()); show_display::<O>(&mut wayvr, overlays, app_entry.target_display.as_str());

View File

@@ -118,12 +118,12 @@ impl AppState {
#[cfg(feature = "osc")] #[cfg(feature = "osc")]
let osc_sender = crate::backend::osc::OscSender::new(session.config.osc_out_port).ok(); let osc_sender = crate::backend::osc::OscSender::new(session.config.osc_out_port).ok();
let toast_sound_wav = AppState::try_load_bytes( let toast_sound_wav = Self::try_load_bytes(
&session.config.notification_sound, &session.config.notification_sound,
include_bytes!("res/557297.wav"), include_bytes!("res/557297.wav"),
); );
Ok(AppState { Ok(Self {
fc: FontCache::new(session.config.primary_font.clone())?, fc: FontCache::new(session.config.primary_font.clone())?,
session, session,
tasks, tasks,
@@ -167,16 +167,16 @@ impl AppState {
let real_path = config_io::get_config_root().join(path); let real_path = config_io::get_config_root().join(path);
if std::fs::File::open(real_path.clone()).is_err() { if std::fs::File::open(real_path.clone()).is_err() {
log::warn!("Could not open file at: {}", path); log::warn!("Could not open file at: {path}");
return fallback_data; return fallback_data;
}; }
match std::fs::read(real_path.clone()) { match std::fs::read(real_path) {
// Box is used here to work around `f`'s limited lifetime // Box is used here to work around `f`'s limited lifetime
Ok(f) => Box::leak(Box::new(f)).as_slice(), Ok(f) => Box::leak(Box::new(f)).as_slice(),
Err(e) => { Err(e) => {
log::warn!("Failed to read file at: {}", path); log::warn!("Failed to read file at: {path}");
log::warn!("{:?}", e); log::warn!("{e:?}");
fallback_data fallback_data
} }
} }
@@ -195,7 +195,7 @@ pub struct AppSession {
impl AppSession { impl AppSession {
pub fn load() -> Self { pub fn load() -> Self {
let config_root_path = config_io::ConfigRoot::Generic.ensure_dir(); let config_root_path = config_io::ConfigRoot::Generic.ensure_dir();
log::info!("Config root path: {:?}", config_root_path); log::info!("Config root path: {config_root_path:?}");
let config = GeneralConfig::load_from_disk(); let config = GeneralConfig::load_from_disk();
let mut toast_topics = IdMap::new(); let mut toast_topics = IdMap::new();
@@ -210,11 +210,11 @@ impl AppSession {
#[cfg(feature = "wayvr")] #[cfg(feature = "wayvr")]
let wayvr_config = config_wayvr::load_wayvr(); let wayvr_config = config_wayvr::load_wayvr();
AppSession { Self {
config, config,
toast_topics,
#[cfg(feature = "wayvr")] #[cfg(feature = "wayvr")]
wayvr_config, wayvr_config,
toast_topics,
} }
} }
} }
@@ -225,8 +225,8 @@ pub struct AudioOutput {
} }
impl AudioOutput { impl AudioOutput {
pub fn new() -> Self { pub const fn new() -> Self {
AudioOutput { Self {
audio_stream: None, audio_stream: None,
first_try: true, first_try: true,
} }
@@ -253,7 +253,7 @@ impl AudioOutput {
let source = match Decoder::new_wav(cursor) { let source = match Decoder::new_wav(cursor) {
Ok(source) => source, Ok(source) => source,
Err(e) => { Err(e) => {
log::error!("Failed to play sound: {:?}", e); log::error!("Failed to play sound: {e:?}");
return; return;
} }
}; };