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"
version = "25.4.0"
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
@@ -39,7 +45,7 @@ ovr_overlay = { features = [
"ovr_input",
"ovr_system",
], 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 = [
"wav",
"hound",
@@ -91,7 +97,7 @@ wayvr_ipc = { git = "https://github.com/olekolek1000/wayvr-ipc.git", rev = "a725
################################
[build-dependencies]
regex = { version = "*" }
regex = { version = "1.11.1" }
[features]
default = ["openvr", "openxr", "osc", "x11", "wayland", "wayvr"]

View File

@@ -69,17 +69,17 @@ where
app.screens.clear();
let data = if let Some(wl) = wl.as_mut() {
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();
crate::overlays::screen::create_screens_wayland(wl, app)?
crate::overlays::screen::create_screens_wayland(wl, app)
} else {
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();
match crate::overlays::screen::create_screens_x11pw(app) {
Ok(data) => data,
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)?
}
}
@@ -127,6 +127,8 @@ where
Ok(vec![])
}
#[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>>> {
use crate::overlays::{
screen::{create_screen_interaction, create_screen_renderer_wl, load_pw_token_config},
@@ -154,7 +156,7 @@ where
if create_ran {
continue;
}
let data = crate::overlays::screen::create_screens_wayland(wl, app)?;
let data = crate::overlays::screen::create_screens_wayland(wl, app);
create_ran = true;
for (meta, state, backend) in data.screens {
self.overlays.insert(
@@ -337,7 +339,7 @@ where
if !any_shown && *o.state.name == *WATCH_NAME {
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[1].before = self.pointers[1].now;
}
@@ -58,6 +58,73 @@ impl InputState {
pub fn post_update(&mut self, session: &AppSession) {
for hand in &mut self.pointers {
#[cfg(debug_assertions)]
debug_print_hand(hand);
if hand.now.click {
hand.last_click = Instant::now();
}
if hand.now.click_modifier_right {
hand.interaction.mode = PointerMode::Right;
continue;
}
if hand.now.click_modifier_middle {
hand.interaction.mode = PointerMode::Middle;
continue;
}
let hmd_up = self.hmd.transform_vector3a(Vec3A::Y);
let dot = hmd_up.dot(hand.pose.transform_vector3a(Vec3A::X))
* 2.0f32.mul_add(-(hand.idx as f32), 1.0);
hand.interaction.mode = if dot < -0.85 {
PointerMode::Right
} else if dot > 0.7 {
PointerMode::Middle
} else {
PointerMode::Left
};
let middle_click_orientation = false;
let right_click_orientation = false;
match hand.interaction.mode {
PointerMode::Middle => {
if !middle_click_orientation {
hand.interaction.mode = PointerMode::Left;
}
}
PointerMode::Right => {
if !right_click_orientation {
hand.interaction.mode = PointerMode::Left;
}
}
_ => {}
}
if hand.now.alt_click != hand.before.alt_click {
// Reap previous processes
self.processes
.retain_mut(|child| !matches!(child.try_wait(), Ok(Some(_))));
let mut args = if hand.now.alt_click {
session.config.alt_click_down.iter()
} else {
session.config.alt_click_up.iter()
};
if let Some(program) = args.next() {
if let Ok(child) = Command::new(program).args(args).spawn() {
self.processes.push(child);
}
}
}
}
}
}
#[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);
@@ -102,68 +169,6 @@ impl InputState {
);
}
}
if hand.now.click {
hand.last_click = Instant::now();
}
if hand.now.click_modifier_right {
hand.interaction.mode = PointerMode::Right;
continue;
}
if hand.now.click_modifier_middle {
hand.interaction.mode = PointerMode::Middle;
continue;
}
let hmd_up = self.hmd.transform_vector3a(Vec3A::Y);
let dot =
hmd_up.dot(hand.pose.transform_vector3a(Vec3A::X)) * (1.0 - 2.0 * hand.idx as f32);
hand.interaction.mode = if dot < -0.85 {
PointerMode::Right
} else if dot > 0.7 {
PointerMode::Middle
} else {
PointerMode::Left
};
let middle_click_orientation = false;
let right_click_orientation = false;
match hand.interaction.mode {
PointerMode::Middle => {
if !middle_click_orientation {
hand.interaction.mode = PointerMode::Left;
}
}
PointerMode::Right => {
if !right_click_orientation {
hand.interaction.mode = PointerMode::Left;
}
}
_ => {}
};
if hand.now.alt_click != hand.before.alt_click {
// Reap previous processes
self.processes
.retain_mut(|child| !matches!(child.try_wait(), Ok(Some(_))));
let mut args = if hand.now.alt_click {
session.config.alt_click_down.iter()
} else {
session.config.alt_click_up.iter()
};
if let Some(program) = args.next() {
if let Ok(child) = Command::new(program).args(args).spawn() {
self.processes.push(child);
}
}
}
}
}
}
pub struct InteractionState {
@@ -207,10 +212,10 @@ impl Pointer {
idx,
pose: Affine3A::IDENTITY,
raw_pose: Affine3A::IDENTITY,
now: Default::default(),
before: Default::default(),
now: PointerState::default(),
before: PointerState::default(),
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>(
idx: usize,
overlays: &mut OverlayContainer<O>,
@@ -434,7 +440,7 @@ where
if can_curve {
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 {
hovered.state.curvature = None;
} else {
@@ -480,7 +486,7 @@ impl Pointer {
if let Some(hit) = self.ray_test(
overlay.state.id,
&overlay.state.transform,
&overlay.state.curvature,
overlay.state.curvature.as_ref(),
) {
if hit.dist.is_infinite() || hit.dist.is_nan() {
continue;
@@ -491,7 +497,7 @@ impl Pointer {
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 uv = overlay
@@ -573,7 +579,7 @@ impl Pointer {
.state
.transform
.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() {
grab_data.offset.z -= self.now.scroll_y * 0.05;
}
@@ -620,12 +626,19 @@ impl Pointer {
&self,
overlay: OverlayID,
transform: &Affine3A,
curvature: &Option<f32>,
curvature: Option<&f32>,
) -> Option<RayHit> {
let (dist, local_pos) = match curvature {
Some(curvature) => raycast_cylinder(&self.pose, Vec3A::NEG_Z, transform, *curvature),
_ => raycast_plane(&self.pose, Vec3A::NEG_Z, transform, Vec3A::NEG_Z),
}?;
let (dist, local_pos) = curvature.map_or_else(
|| {
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 {
// hit is behind us
@@ -646,7 +659,7 @@ fn raycast_plane(
source_fwd: Vec3A,
plane: &Affine3A,
plane_norm: Vec3A,
) -> Option<(f32, Vec2)> {
) -> (f32, Vec2) {
let plane_normal = plane.transform_vector3a(plane_norm);
let ray_dir = source.transform_vector3a(source_fwd);
@@ -658,7 +671,7 @@ fn raycast_plane(
.transform_point3a(source.translation + ray_dir * dist)
.xy();
Some((dist, hit_local))
(dist, hit_local)
}
fn raycast_cylinder(
@@ -675,27 +688,27 @@ fn raycast_cylinder(
}
.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_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 s = ray_origin.xz();
let v_dir = ray_dir.xz();
let v_pos = ray_origin.xz();
let a = d.dot(d);
let b = d.dot(s);
let c = s.dot(s) - r * r;
let l_dir = v_dir.dot(v_dir);
let l_pos = v_dir.dot(v_pos);
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 {
return None;
}
let sqrt_d = d.sqrt();
let t1 = (-b - sqrt_d) / a;
let t2 = (-b + sqrt_d) / a;
let t1 = (-l_pos - sqrt_d) / l_dir;
let t2 = (-l_pos + sqrt_d) / l_dir;
let t = t1.max(t2);
@@ -709,8 +722,8 @@ fn raycast_cylinder(
return None;
}
let max_angle = 2.0 * (size / (2.0 * r));
let x_angle = (hit_local.x / r).asin();
let max_angle = 2.0 * (size / (2.0 * radius));
let x_angle = (hit_local.x / radius).asin();
hit_local.x = x_angle / max_angle;
hit_local.y /= size;

View File

@@ -57,8 +57,7 @@ impl NotificationManager {
Ok(c) => c,
Err(e) => {
log::error!(
"Failed to connect to dbus. Desktop notifications will not work. Cause: {:?}",
e
"Failed to connect to dbus. Desktop notifications will not work. Cause: {e:?}"
);
return;
}
@@ -81,17 +80,16 @@ impl NotificationManager {
(vec![rule.match_str()], 0u32),
);
match result {
Ok(_) => {
if matches!(result, Ok(())) {
let sender = self.tx_toast.clone();
c.start_receive(
rule,
Box::new(move |msg, _| {
if let Ok(toast) = parse_dbus(&msg) {
match sender.try_send(toast) {
Ok(_) => {}
Ok(()) => {}
Err(e) => {
log::error!("Failed to send notification: {:?}", e);
log::error!("Failed to send notification: {e:?}");
}
}
}
@@ -99,8 +97,7 @@ impl NotificationManager {
}),
);
log::info!("Listening to DBus notifications via BecomeMonitor.");
}
Err(_) => {
} else {
let rule_with_eavesdrop = {
let mut rule = rule.clone();
rule.eavesdrop = true;
@@ -108,12 +105,12 @@ impl NotificationManager {
};
let sender2 = self.tx_toast.clone();
let result = c.add_match(rule_with_eavesdrop, move |_: (), _, msg| {
let result = c.add_match(rule_with_eavesdrop, move |(): (), _, msg| {
if let Ok(toast) = parse_dbus(msg) {
match sender2.try_send(toast) {
Ok(_) => {}
Ok(()) => {}
Err(e) => {
log::error!("Failed to send notification: {:?}", e);
log::error!("Failed to send notification: {e:?}");
}
}
}
@@ -125,10 +122,7 @@ impl NotificationManager {
log::info!("Listening to DBus notifications via eavesdrop.");
}
Err(_) => {
log::error!(
"Failed to add DBus match. Desktop notifications will not work.",
);
}
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) {
Ok(s) => s,
Err(e) => {
log::error!("Failed to bind notification socket @ {}: {:?}", addr, e);
log::error!("Failed to bind notification socket @ {addr}: {e:?}");
return;
}
};
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
@@ -159,14 +153,14 @@ impl NotificationManager {
let json_str = match std::str::from_utf8(&buf[..num_bytes]) {
Ok(s) => s,
Err(e) => {
log::error!("Failed to receive notification message: {:?}", e);
log::error!("Failed to receive notification message: {e:?}");
continue;
}
};
let msg = match serde_json::from_str::<XsoMessage>(json_str) {
Ok(m) => m,
Err(e) => {
log::error!("Failed to parse notification message: {:?}", e);
log::error!("Failed to parse notification message: {e:?}");
continue;
}
};
@@ -184,9 +178,9 @@ impl NotificationManager {
.with_sound(msg.volume.unwrap_or(-1.) >= 0.); // XSOverlay still plays at 0,
match sender.try_send(toast) {
Ok(_) => {}
Ok(()) => {}
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
}
#[allow(dead_code)]
#[allow(non_snake_case)]
#[derive(Debug, Deserialize)]
struct XsoMessage {

View File

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

View File

@@ -13,7 +13,7 @@ pub trait Affine3AConvert {
impl Affine3AConvert for Matrix3x4 {
fn from_affine(affine: &Affine3A) -> Self {
Matrix3x4([
Self([
[
affine.matrix3.x_axis.x,
affine.matrix3.y_axis.x,
@@ -47,7 +47,7 @@ impl Affine3AConvert for Matrix3x4 {
impl Affine3AConvert for HmdMatrix34_t {
fn from_affine(affine: &Affine3A) -> Self {
HmdMatrix34_t {
Self {
m: [
[
affine.matrix3.x_axis.x,
@@ -89,13 +89,13 @@ pub(super) enum OVRError {
impl From<ovr_overlay::errors::EVRInputError> for OVRError {
fn from(e: ovr_overlay::errors::EVRInputError) -> Self {
OVRError::InputError(e.description())
Self::InputError(e.description())
}
}
impl From<OVRError> for BackendError {
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],
});
Ok(OpenVrInputSource {
Ok(Self {
hands,
set_hnd,
click_hnd,
grab_hnd,
@@ -120,14 +121,13 @@ impl OpenVrInputSource {
click_modifier_right_hnd,
click_modifier_middle_hnd,
move_mouse_hnd,
hands,
})
}
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(
hnd,
action_handle,
0.0,
Duration::from_secs_f32(haptics.duration),
haptics.frequency,
@@ -277,8 +277,8 @@ impl OpenVrInputSource {
}
app.input_state.devices.sort_by(|a, b| {
(a.soc.is_none() as u8)
.cmp(&(b.soc.is_none() as u8))
u8::from(a.soc.is_none())
.cmp(&u8::from(b.soc.is_none()))
.then((a.role as u8).cmp(&(b.role as u8)))
.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)
.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");

View File

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

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"))?,
};
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) {
let mut buf = String::new();
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,
e
);
};
}
if let Err(e) = app_mgr.add_application_manifest(&manifest_path, false) {
bail!("Failed to add manifest to OpenVR: {}", e.description());
};
}
if let Err(e) = app_mgr.set_application_auto_launch(APP_KEY, true) {
bail!("Failed to set auto launch: {}", e.description());
};
}
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<()> {
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) {
bail!("Failed to remove manifest from OpenVR: {}", e.description());
};
}
log::info!("Uninstalled manifest");
}
Ok(())

View File

@@ -13,11 +13,7 @@ use ovr_overlay::{
sys::{ETrackedDeviceProperty, EVRApplicationType, EVREventType},
TrackedDeviceIndex,
};
use vulkano::{
device::{physical::PhysicalDevice, DeviceExtensions},
instance::InstanceExtensions,
Handle, VulkanObject,
};
use vulkano::{device::physical::PhysicalDevice, Handle, VulkanObject};
use crate::{
backend::{
@@ -65,6 +61,7 @@ pub fn openvr_uninstall() {
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> {
let app_type = EVRApplicationType::VRApplication_Overlay;
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 names = compositor_mgr.get_vulkan_device_extensions_required(device.handle().as_raw());
let ext = DeviceExtensions::from_iter(names.iter().map(|s| s.as_str()));
ext
names.iter().map(std::string::String::as_str).collect()
};
let mut compositor_mngr = context.compositor_mngr();
let mut compositor_mgr = context.compositor_mngr();
let instance_extensions = {
let names = compositor_mngr.get_vulkan_instance_extensions_required();
InstanceExtensions::from_iter(names.iter().map(|s| s.as_str()))
let names = compositor_mgr.get_vulkan_instance_extensions_required();
names.iter().map(std::string::String::as_str).collect()
};
let mut state = {
@@ -103,7 +99,7 @@ pub fn openvr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
state.tasks.enqueue_at(
TaskType::System(SystemTask::ShowHide),
Instant::now().add(Duration::from_secs(1)),
)
);
}
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
@@ -188,7 +184,7 @@ pub fn openvr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
Toast::new(
ToastTopic::IpdChange,
"IPD".into(),
format!("{:.1} mm", ipd).into(),
format!("{ipd:.1} mm").into(),
)
.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);
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);
}
while let Some(task) = due_tasks.pop_front() {
match task {
TaskType::Global(f) => f(&mut state),
TaskType::Overlay(sel, f) => {
if let Some(o) = overlays.mut_by_selector(&sel) {
f(&mut state, &mut o.state);
} else {
log::warn!("Overlay not found for task: {:?}", sel);
log::warn!("Overlay not found for task: {sel:?}");
}
}
TaskType::CreateOverlay(sel, f) => {
@@ -316,7 +311,7 @@ pub fn openvr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
&state.input_state.hmd,
);
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")]
if let Some(ref mut sender) = state.osc_sender {
let _ = sender.send_params(&overlays, &state.input_state.devices);
};
}
#[cfg(feature = "wayvr")]
if let Err(e) =
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");
@@ -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 Err(e) = future.flush() {
return Err(BackendError::Fatal(e.into()));
};
}
future.cleanup_finished();
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -9,6 +9,7 @@ use std::{
};
use glam::{Affine3A, Vec3};
use input::OpenXrInputSource;
use libmonado::Monado;
use openxr as xr;
use skybox::create_skybox;
@@ -43,30 +44,28 @@ mod skybox;
mod swapchain;
const VIEW_TYPE: xr::ViewConfigurationType = xr::ViewConfigurationType::PRIMARY_STEREO;
const VIEW_COUNT: u32 = 2;
static FRAME_COUNTER: AtomicUsize = AtomicUsize::new(0);
struct XrState {
instance: xr::Instance,
system: xr::SystemId,
session: xr::Session<xr::Vulkan>,
predicted_display_time: xr::Time,
fps: f32,
stage: 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> {
let (xr_instance, system) = match helpers::init_xr() {
Ok((xr_instance, system)) => (xr_instance, system),
Err(e) => {
log::warn!("Will not use OpenXR: {}", e);
log::warn!("Will not use OpenXR: {e}");
return Err(BackendError::NotSupported);
}
};
let mut app_state = {
let mut app = {
let graphics = WlxGraphics::new_openxr(xr_instance.clone(), system)?;
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 modes = xr_instance.enumerate_environment_blend_modes(system, VIEW_TYPE)?;
if modes.contains(&xr::EnvironmentBlendMode::ALPHA_BLEND)
&& app_state.session.config.use_passthrough
&& app.session.config.use_passthrough
{
xr::EnvironmentBlendMode::ALPHA_BLEND
} else {
modes[0]
}
};
log::info!("Using environment blend mode: {:?}", environment_blend_mode);
log::info!("Using environment blend mode: {environment_blend_mode:?}");
if show_by_default {
app_state.tasks.enqueue_at(
app.tasks.enqueue_at(
TaskType::System(SystemTask::ShowHide),
Instant::now().add(Duration::from_secs(1)),
)
);
}
let mut overlays = OverlayContainer::<OpenXrOverlayData>::new(&mut app_state)?;
let mut lines = LinePool::new(app_state.graphics.clone())?;
let mut overlays = OverlayContainer::<OpenXrOverlayData>::new(&mut app)?;
let mut lines = LinePool::new(app.graphics.clone())?;
let mut notifications = NotificationManager::new();
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 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();
let mut playspace = monado.as_mut().and_then(|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()
});
@@ -114,15 +113,10 @@ pub fn openxr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
&xr_instance,
system,
&xr::vulkan::SessionCreateInfo {
instance: app_state.graphics.instance.handle().as_raw() as _,
physical_device: app_state
.graphics
.device
.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(),
instance: app.graphics.instance.handle().as_raw() as _,
physical_device: app.graphics.device.physical_device().handle().as_raw() as _,
device: app.graphics.device.handle().as_raw() as _,
queue_family_index: app.graphics.queue.queue_family_index(),
queue_index: 0,
},
)?;
@@ -136,24 +130,22 @@ pub fn openxr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
let mut xr_state = XrState {
instance: xr_instance,
system,
session,
predicted_display_time: xr::Time::from_nanos(0),
fps: 30.0,
stage: Arc::new(stage),
view: Arc::new(view),
stage_offset: Affine3A::IDENTITY,
};
let mut skybox = if environment_blend_mode == xr::EnvironmentBlendMode::OPAQUE {
create_skybox(&xr_state, &app_state)
create_skybox(&xr_state, &app)
} else {
None
};
let pointer_lines = [
lines.allocate(&xr_state, app_state.graphics.clone())?,
lines.allocate(&xr_state, app_state.graphics.clone())?,
lines.allocate(&xr_state, app.graphics.clone())?,
lines.allocate(&xr_state, app.graphics.clone())?,
];
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) {
log::warn!("Received shutdown signal.");
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(e) => {
log::error!("Failed to request OpenXR session exit: {}", e);
log::error!("Failed to request OpenXR session exit: {e}");
break 'main_loop;
}
}
}
while let Some(event) = xr_state.instance.poll_event(&mut event_storage)? {
use xr::Event::*;
match event {
SessionStateChanged(e) => {
xr::Event::SessionStateChanged(e) => {
// Session state change is where we can begin and end sessions, as well as
// find quit messages!
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;
}
EventsLost(e) => {
xr::Event::EventsLost(e) => {
log::warn!("lost {} events", e.lost_event_count());
}
MainSessionVisibilityChangedEXTX(e) => {
xr::Event::MainSessionVisibilityChangedEXTX(e) => {
if 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 {
log::debug!("Destroying skybox.");
skybox = None;
} else if environment_blend_mode == xr::EnvironmentBlendMode::OPAQUE {
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 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);
}
}
@@ -259,8 +250,7 @@ pub fn openxr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
let total_elapsed = fps_counter
.front()
.map(|time| time.elapsed().as_secs_f32())
.unwrap_or(0f32);
.map_or(0f32, |time| time.elapsed().as_secs_f32());
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;
}
app_state.input_state.pre_update();
input_source.update(&xr_state, &mut app_state)?;
app_state.input_state.post_update(&app_state.session);
app.input_state.pre_update();
input_source.update(&xr_state, &mut app)?;
app.input_state.post_update(&app.session);
if app_state
if app
.input_state
.pointers
.iter()
.any(|p| p.now.show_hide && !p.before.show_hide)
{
overlays.show_hide(&mut app_state);
overlays.show_hide(&mut app);
}
#[cfg(feature = "wayvr")]
if app_state
if app
.input_state
.pointers
.iter()
.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 {
space_mover.update(
&mut overlays,
&app_state,
&app,
monado.as_mut().unwrap(), // safe
);
}
for o in overlays.iter_mut() {
o.after_input(&mut app_state)?;
o.after_input(&mut app)?;
}
#[cfg(feature = "osc")]
if let Some(ref mut sender) = app_state.osc_sender {
let _ = sender.send_params(&overlays, &app_state.input_state.devices);
};
if let Some(ref mut sender) = app.osc_sender {
let _ = sender.send_params(&overlays, &app.input_state.devices);
}
let (_, views) = xr_state.session.locate_views(
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);
if (app_state.input_state.ipd - ipd).abs() > 0.01 {
log::info!("IPD changed: {} -> {}", app_state.input_state.ipd, ipd);
app_state.input_state.ipd = ipd;
if (app.input_state.ipd - ipd).abs() > 0.01 {
log::info!("IPD changed: {} -> {}", app.input_state.ipd, ipd);
app.input_state.ipd = ipd;
Toast::new(
ToastTopic::IpdChange,
"IPD".into(),
format!("{:.1} mm", ipd).into(),
format!("{ipd:.1} mm").into(),
)
.submit(&mut app_state);
.submit(&mut app);
}
overlays
.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() {
lines.draw_from(
pointer_lines[idx],
app_state.input_state.pointers[idx].pose,
app.input_state.pointers[idx].pose,
*len,
app_state.input_state.pointers[idx].interaction.mode as usize + 1,
&app_state.input_state.hmd,
app.input_state.pointers[idx].interaction.mode as usize + 1,
&app.input_state.hmd,
);
if let Some(haptics) = 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_transform = watch.state.transform;
@@ -366,9 +356,9 @@ pub fn openxr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
#[cfg(feature = "wayvr")]
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
@@ -376,7 +366,7 @@ pub fn openxr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
if !main_session_visible {
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 {
o.init(&mut app_state)?;
o.init(&mut app)?;
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::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
};
if should_render {
if !o.ensure_swapchain(&app_state, &xr_state)? {
if !o.ensure_swapchain(&app, &xr_state)? {
continue;
}
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
continue;
}
@@ -413,13 +403,13 @@ pub fn openxr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
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 Err(e) = future.flush() {
return Err(BackendError::Fatal(e.into()));
};
}
future.cleanup_finished();
}
// End rendering
@@ -428,12 +418,8 @@ pub fn openxr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
let mut layers = vec![];
if !main_session_visible {
if let Some(skybox) = skybox.as_mut() {
for (idx, layer) in skybox
.present(&xr_state, &app_state)?
.into_iter()
.enumerate()
{
layers.push((200.0 - 50.0 * (idx as f32), layer));
for (idx, layer) in skybox.present(&xr_state, &app)?.into_iter().enumerate() {
layers.push(((idx as f32).mul_add(-50.0, 200.0), layer));
}
}
}
@@ -442,7 +428,7 @@ pub fn openxr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
if !o.data.cur_visible {
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()
+ (100f32 - o.state.z_order as f32);
if !dist_sq.is_normal() {
@@ -450,14 +436,14 @@ pub fn openxr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
continue;
}
let maybe_layer = o.present(&xr_state)?;
if let CompositionLayer::None = maybe_layer {
if matches!(maybe_layer, CompositionLayer::None) {
continue;
}
layers.push((dist_sq, maybe_layer));
}
for maybe_layer in lines.present(&xr_state)? {
if let CompositionLayer::None = maybe_layer {
if matches!(maybe_layer, CompositionLayer::None) {
continue;
}
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
#[cfg(feature = "wayvr")]
if let Some(wayvr) = &app_state.wayvr {
if let Some(wayvr) = &app.wayvr {
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
let removed_overlays = overlays.update(&mut app_state)?;
let removed_overlays = overlays.update(&mut app)?;
for o in removed_overlays {
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() {
match task {
TaskType::Global(f) => f(&mut app_state),
TaskType::Overlay(sel, f) => {
if let Some(o) = overlays.mut_by_selector(&sel) {
f(&mut app_state, &mut o.state);
f(&mut app, &mut o.state);
} else {
log::warn!("Overlay not found for task: {:?}", sel);
log::warn!("Overlay not found for task: {sel:?}");
}
}
TaskType::CreateOverlay(sel, f) => {
@@ -512,14 +497,14 @@ pub fn openxr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
continue;
};
let Some((mut state, backend)) = f(&mut app_state) else {
let Some((mut overlay_state, overlay_backend)) = f(&mut app) else {
continue;
};
state.birthframe = cur_frame;
overlay_state.birthframe = cur_frame;
overlays.add(OverlayData {
state,
backend,
state: overlay_state,
backend: overlay_backend,
..Default::default()
});
}
@@ -538,7 +523,7 @@ pub fn openxr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
SystemTask::FixFloor => {
if let Some(ref mut playspace) = playspace {
playspace.fix_floor(
&app_state.input_state,
&app.input_state,
monado.as_mut().unwrap(), // safe
);
}
@@ -549,13 +534,13 @@ pub fn openxr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
}
}
SystemTask::ShowHide => {
overlays.show_hide(&mut app_state);
overlays.show_hide(&mut app);
}
_ => {}
},
#[cfg(feature = "wayvr")]
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;
#[repr(C)]
#[derive(Default, Debug)]
struct XrtPose {
orientation: [f32; 4],
position: [f32; 3],
}
struct MoverData<T> {
pose: Affine3A,
hand: usize,
@@ -55,7 +48,7 @@ impl PlayspaceMover {
state: &AppState,
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.before.space_reset {
log::info!("Space reset");
@@ -81,8 +74,8 @@ impl PlayspaceMover {
Affine3A::from_quat(dq)
} else {
let rel_y = f32::atan2(
2.0 * (dq.y * dq.w + dq.x * dq.z),
(2.0 * (dq.w * dq.w + dq.x * dq.x)) - 1.0,
2.0 * dq.y.mul_add(dq.w, dq.x * dq.z),
2.0f32.mul_add(dq.w.mul_add(dq.w, dq.x * dq.x), -1.0),
);
Affine3A::from_rotation_y(rel_y)
@@ -96,7 +89,7 @@ impl PlayspaceMover {
data.pose *= space_transform;
data.hand_pose = new_hand;
self.apply_offset(data.pose, monado);
apply_offset(data.pose, monado);
self.rotate = Some(data);
} else {
for (i, pointer) in state.input_state.pointers.iter().enumerate() {
@@ -145,7 +138,7 @@ impl PlayspaceMover {
data.pose.translation += relative_pos;
data.hand_pose = new_hand;
self.apply_offset(data.pose, monado);
apply_offset(data.pose, monado);
self.drag = Some(data);
} else {
for (i, pointer) in state.input_state.pointers.iter().enumerate() {
@@ -176,7 +169,7 @@ impl PlayspaceMover {
}
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) {
@@ -193,14 +186,14 @@ impl PlayspaceMover {
let y2 = input.pointers[1].raw_pose.translation.y;
let delta = y1.min(y2) - 0.03;
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) {
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: {}",
app.session.config.skybox_texture
);
log::warn!("{:?}", e);
log::warn!("{e:?}");
}
}
}
@@ -181,6 +181,11 @@ impl Skybox {
xr: &'a XrState,
app: &AppState,
) -> 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(|| {
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()?;
let sky = xr::CompositionLayerEquirect2KHR::new()

View File

@@ -20,9 +20,9 @@ pub(super) struct SwapchainOpts {
impl SwapchainOpts {
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
}

View File

@@ -26,7 +26,7 @@ impl OscSender {
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.");
};
@@ -75,7 +75,7 @@ impl OscSender {
KEYBOARD_NAME => has_keyboard = true,
_ => {
if o.state.interactable {
num_overlays += 1
num_overlays += 1;
}
}
}
@@ -159,12 +159,12 @@ impl OscSender {
self.send_message(
String::from("/avatar/parameters/averageControllerBattery"),
vec![OscType::Float(
controller_total_bat / controller_count as f32,
controller_total_bat / f32::from(controller_count),
)],
)?;
self.send_message(
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 relative_to: RelativeTo,
pub curvature: Option<f32>,
pub primary_pointer: Option<usize>,
pub interaction_transform: Affine2,
pub birthframe: usize,
}
impl Default for OverlayState {
fn default() -> Self {
OverlayState {
Self {
id: OverlayID(OVERLAY_AUTO_INCREMENT.fetch_add(1, Ordering::Relaxed)),
name: Arc::from(""),
want_visible: false,
@@ -83,7 +82,6 @@ impl Default for OverlayState {
spawn_rotation: Quat::IDENTITY,
saved_transform: None,
transform: Affine3A::IDENTITY,
primary_pointer: None,
interaction_transform: Affine2::IDENTITY,
birthframe: 0,
}
@@ -105,8 +103,8 @@ where
T: Default,
{
fn default() -> Self {
OverlayData {
state: Default::default(),
Self {
state: OverlayState::default(),
backend: Box::<SplitOverlayBackend>::default(),
primary_pointer: None,
data: Default::default(),
@@ -115,7 +113,7 @@ where
}
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 {
RelativeTo::Head => Some(app.input_state.hmd),
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 {
app.anchor
} else {
@@ -211,12 +209,14 @@ where
T: Default,
{
pub fn init(&mut self, app: &mut AppState) -> anyhow::Result<()> {
if self.state.curvature.is_none() {
self.state.curvature = app
.session
.config
.curve_values
.arc_get(self.state.name.as_ref())
.copied();
}
if matches!(self.state.relative_to, RelativeTo::None) {
let hard_reset;
@@ -250,18 +250,6 @@ where
pub fn frame_meta(&mut self) -> Option<FrameMeta> {
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)]
@@ -351,8 +339,8 @@ pub struct SplitOverlayBackend {
}
impl Default for SplitOverlayBackend {
fn default() -> SplitOverlayBackend {
SplitOverlayBackend {
fn default() -> Self {
Self {
renderer: Box::new(FallbackRenderer),
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 scale = if aspect < 1.0 {
Vec2 {

View File

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

View File

@@ -3,7 +3,8 @@ use std::sync::Arc;
use vulkano::{
image::{view::ImageView, ImageUsage},
swapchain::{
acquire_next_image, Surface, Swapchain, SwapchainCreateInfo, SwapchainPresentInfo,
acquire_next_image, Surface, SurfaceInfo, Swapchain, SwapchainCreateInfo,
SwapchainPresentInfo,
},
sync::GpuFuture,
Validated, VulkanError,
@@ -67,13 +68,12 @@ impl PreviewState {
let inner_size = window.inner_size();
let swapchain_size = [inner_size.width, inner_size.height];
let (swapchain, images) =
create_swapchain(&state.graphics, surface.clone(), swapchain_size)?;
let (swapchain, images) = create_swapchain(&state.graphics, surface, 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)?;
Ok(PreviewState {
Ok(Self {
canvas,
swapchain,
images,
@@ -99,7 +99,7 @@ pub fn uidev_run(panel_name: &str) -> anyhow::Result<()> {
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 recreate = false;
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}");
window.request_redraw();
};
}
last_draw = std::time::Instant::now();
@@ -204,12 +204,12 @@ fn create_swapchain(
let surface_capabilities = graphics
.device
.physical_device()
.surface_capabilities(&surface, Default::default())
.surface_capabilities(&surface, SurfaceInfo::default())
.unwrap(); // want panic
let (swapchain, images) = Swapchain::new(
graphics.device.clone(),
surface.clone(),
surface,
SwapchainCreateInfo {
min_image_count: surface_capabilities.min_image_count.max(2),
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> {
let path = format!("/proc/{}/environ", pid);
let path = format!("/proc/{pid}/environ");
let mut env_data = String::new();
std::fs::File::open(path)?.read_to_string(&mut env_data)?;
@@ -162,7 +162,7 @@ impl WayVRCompositor {
) -> anyhow::Result<()> {
if let Some(stream) = self.listener.accept()? {
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,
) -> anyhow::Result<()> {
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)?;
@@ -184,7 +184,7 @@ impl WayVRCompositor {
let surf_count = self.state.xdg_shell.toplevel_surfaces().len() as u32;
if surf_count != self.toplevel_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(())
@@ -211,11 +211,9 @@ impl WayVRCompositor {
const STARTING_WAYLAND_ADDR_IDX: u32 = 20;
fn export_display_number(display_num: u32) -> anyhow::Result<()> {
let mut path = std::env::var("XDG_RUNTIME_DIR")
.map(PathBuf::from)
.unwrap_or_else(|_| PathBuf::from("/tmp"));
let mut path = std::env::var("XDG_RUNTIME_DIR").map_or_else(|_| PathBuf::from("/tmp"), PathBuf::from);
path.push("wayvr.disp");
std::fs::write(path, format!("{}\n", display_num))?;
std::fs::write(path, format!("{display_num}\n"))?;
Ok(())
}
@@ -227,17 +225,15 @@ fn create_wayland_listener() -> anyhow::Result<(super::WaylandEnv, wayland_serve
let listener = loop {
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()) {
Ok(listener) => {
log::debug!("Listening to {}", display_str);
log::debug!("Listening to {display_str}");
break listener;
}
Err(e) => {
log::debug!(
"Failed to open socket \"{}\" (reason: {}), trying next...",
display_str,
e
"Failed to open socket \"{display_str}\" (reason: {e}), trying next..."
);
env.display_num += 1;

View File

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

View File

@@ -122,8 +122,8 @@ impl Display {
let tex_id = params.renderer.with_context(|gl| {
smithay_wrapper::create_framebuffer_texture(
gl,
params.width as u32,
params.height as u32,
u32::from(params.width),
u32::from(params.height),
tex_format,
internal_format,
)
@@ -139,7 +139,7 @@ impl Display {
};
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 {
GlesTexture::from_raw(params.renderer, Some(tex_format), opaque, tex_id, size)
};
@@ -202,7 +202,7 @@ impl Display {
match &self.layout {
packet_server::WvrDisplayWindowLayout::Tiling => {
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 !window.visible {
continue;
@@ -210,21 +210,21 @@ impl Display {
let d_cur = i 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 right = (d_next * self.width as f32) as i32;
let left = (d_cur * f32::from(self.width)) as i32;
let right = (d_next * f32::from(self.width)) as i32;
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;
}
}
}
packet_server::WvrDisplayWindowLayout::Stacking(opts) => {
let do_margins = |margins: &packet_server::Margins, window: &mut window::Window| {
let top = margins.top as i32;
let bottom = self.height as i32 - margins.bottom as i32;
let left = margins.left as i32;
let right = self.width as i32 - margins.right as i32;
let top = i32::from(margins.top);
let bottom = i32::from(self.height) - i32::from(margins.bottom);
let left = i32::from(margins.left);
let right = i32::from(self.width) - i32::from(margins.right);
let width = right - left;
let height = bottom - top;
if width < 0 || height < 0 {
@@ -236,7 +236,7 @@ impl Display {
};
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 !window.visible {
continue;
@@ -267,7 +267,7 @@ impl Display {
self.no_windows_since = None;
} else if let Some(auto_hide_delay) = config.auto_hide_delay {
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
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<()> {
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 elements: Vec<WaylandSurfaceRenderElement<GlesRenderer>> = self
@@ -358,8 +358,8 @@ impl Display {
gl.ReadPixels(
0,
0,
self.width as i32,
self.height as i32,
i32::from(self.width),
i32::from(self.height),
ffi::RGBA,
ffi::UNSIGNED_BYTE,
data.as_mut_ptr().cast(),
@@ -401,7 +401,7 @@ impl Display {
None
}
pub fn trigger_rerender(&mut self) {
pub const fn trigger_rerender(&mut self) {
self.wants_redraw = true;
}
@@ -435,7 +435,7 @@ impl Display {
y: u32,
) {
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;
}
@@ -444,8 +444,8 @@ impl Display {
if let Some(window) = wm.windows.get(&window_handle) {
let surf = window.toplevel.wl_surface().clone();
let point = Point::<f64, Logical>::from((
(x as i32 - window.pos_x) as f64,
(y as i32 - window.pos_y) as f64,
f64::from(x as i32 - window.pos_x),
f64::from(y as i32 - window.pos_y),
));
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 {
super::MouseIndex::Left => 0x110, /* BTN_LEFT */
super::MouseIndex::Center => 0x112, /* BTN_MIDDLE */
@@ -505,7 +505,7 @@ impl Display {
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(
&mut manager.state,
&input::pointer::ButtonEvent {
@@ -519,7 +519,7 @@ impl Display {
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(
&mut manager.state,
input::pointer::AxisFrame {
@@ -529,7 +529,7 @@ impl Display {
smithay::backend::input::AxisRelativeDirection::Identical,
),
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)),
stop: (false, false),
},
@@ -549,7 +549,7 @@ impl Display {
args: &[&str],
env: &[(&str, &str)],
) -> 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();
@@ -577,14 +577,14 @@ impl Display {
gen_id!(DisplayVec, Display, DisplayCell, DisplayHandle);
impl DisplayHandle {
pub fn from_packet(handle: packet_server::WvrDisplayHandle) -> Self {
pub const fn from_packet(handle: packet_server::WvrDisplayHandle) -> Self {
Self {
generation: handle.generation,
idx: handle.idx,
}
}
pub fn as_packet(&self) -> packet_server::WvrDisplayHandle {
pub const fn as_packet(&self) -> packet_server::WvrDisplayHandle {
packet_server::WvrDisplayHandle {
idx: self.idx,
generation: self.generation,

View File

@@ -47,25 +47,25 @@ pub enum RenderData {
impl EGLData {
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!(
"Required EGL function {} not found",
func_name
))?;
let raw_fn = self
.egl
.get_proc_address(func_name)
.ok_or_else(|| anyhow::anyhow!("Required EGL function {} not found", func_name))?;
Ok(raw_fn)
}
pub fn new() -> anyhow::Result<EGLData> {
pub fn new() -> anyhow::Result<Self> {
unsafe {
let egl = khronos_egl::Instance::new(khronos_egl::Static);
let display = egl
.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."
))?;
let (major, minor) = egl.initialize(display)?;
log::debug!("EGL version: {}.{}", major, minor);
log::debug!("EGL version: {major}.{minor}");
let attrib_list = [
khronos_egl::RED_SIZE,
@@ -83,7 +83,7 @@ impl EGLData {
let config = egl
.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)?;
@@ -104,7 +104,7 @@ impl EGLData {
egl.make_current(display, None, None, Some(context))?;
Ok(EGLData {
Ok(Self {
egl,
display,
config,
@@ -114,7 +114,7 @@ impl EGLData {
}
fn query_dmabuf_mod_info(&self) -> anyhow::Result<DMAbufModifierInfo> {
let target_fourcc = 0x34324258; //XB24
let target_fourcc = 0x3432_4258; //XB24
unsafe {
use egl_ex::PFNEGLQUERYDMABUFFORMATSEXTPROC;
@@ -187,13 +187,13 @@ impl EGLData {
&mut num_mods,
);
if mods[0] == 0xFFFFFFFFFFFFFFFF {
if mods[0] == 0xFFFF_FFFF_FFFF_FFFF {
anyhow::bail!("modifier is -1")
}
log::trace!("Modifier list:");
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
@@ -203,13 +203,13 @@ impl EGLData {
// 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.
let mod_whitelist: [u64; 2] = [
0x20000002086bf04, /* AMD RX 7800 XT, Navi32 */
0x20000001866bf04, /* AMD RX 7600 XT, Navi33 */
0x200_0000_2086_bf04, /* AMD RX 7800 XT, Navi32 */
0x200_0000_1866_bf04, /* AMD RX 7600 XT, Navi33 */
];
for modifier in &mod_whitelist {
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 (???) */];
break;
}

View File

@@ -16,7 +16,7 @@ impl<DataType> SyncEventQueue<DataType> {
pub fn new() -> Self {
Self {
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)]
impl $handle_name {
pub fn reset(&mut self) {
pub const fn reset(&mut self) {
self.generation = 0;
}
pub fn is_set(&self) -> bool {
pub const fn is_set(&self) -> bool {
self.generation > 0
}
pub fn id(&self) -> u32 {
pub const fn id(&self) -> u32 {
self.idx
}
pub fn new(idx: u32, generation: u64) -> Self {
pub const fn new(idx: u32, generation: u64) -> Self {
Self { idx, generation }
}
}
//ThingVec
#[allow(dead_code)]
#[allow(dead_code, clippy::iter_not_returning_iterator)]
impl $container_name {
pub fn new() -> Self {
pub const fn new() -> Self {
Self {
vec: Vec::new(),
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 {
idx: idx as u32,
generation: cell.generation,

View File

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

View File

@@ -7,6 +7,7 @@ use crate::gen_id;
use super::display;
#[derive(Debug)]
#[allow(dead_code)]
pub struct WayVRProcess {
pub auth_key: String,
pub child: std::process::Child,
@@ -32,45 +33,45 @@ pub enum Process {
}
impl Process {
pub fn display_handle(&self) -> display::DisplayHandle {
pub const fn display_handle(&self) -> display::DisplayHandle {
match self {
Process::Managed(p) => p.display_handle,
Process::External(p) => p.display_handle,
Self::Managed(p) => p.display_handle,
Self::External(p) => p.display_handle,
}
}
pub fn is_running(&mut self) -> bool {
match self {
Process::Managed(p) => p.is_running(),
Process::External(p) => p.is_running(),
Self::Managed(p) => p.is_running(),
Self::External(p) => p.is_running(),
}
}
pub fn terminate(&mut self) {
match self {
Process::Managed(p) => p.terminate(),
Process::External(p) => p.terminate(),
Self::Managed(p) => p.terminate(),
Self::External(p) => p.terminate(),
}
}
pub fn get_name(&self) -> String {
match self {
Process::Managed(p) => p.get_name().unwrap_or(String::from("unknown")),
Process::External(p) => p.get_name().unwrap_or(String::from("unknown")),
Self::Managed(p) => p.get_name().unwrap_or_else(|| 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 {
match self {
Process::Managed(p) => packet_server::WvrProcess {
name: p.get_name().unwrap_or(String::from("unknown")),
Self::Managed(p) => packet_server::WvrProcess {
name: p.get_name().unwrap_or_else(|| String::from("unknown")),
userdata: p.userdata.clone(),
display_handle: p.display_handle.as_packet(),
handle: handle.as_packet(),
},
Process::External(p) => packet_server::WvrProcess {
name: p.get_name().unwrap_or(String::from("unknown")),
userdata: Default::default(),
Self::External(p) => packet_server::WvrProcess {
name: p.get_name().unwrap_or_else(|| String::from("unknown")),
userdata: HashMap::default(),
display_handle: p.display_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>> {
let path = format!("/proc/{}/environ", pid);
let path = format!("/proc/{pid}/environ");
let mut env_data = String::new();
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();
@@ -112,7 +113,7 @@ impl WayVRProcess {
Ok(None) => true,
Err(e) => {
// this shouldn't happen
log::error!("Child::try_wait failed: {}", e);
log::error!("Child::try_wait failed: {e}");
false
}
}
@@ -131,7 +132,7 @@ impl WayVRProcess {
}
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) {
Ok(buf) => {
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);
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() {
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
}
impl ProcessHandle {
pub fn from_packet(handle: packet_server::WvrProcessHandle) -> Self {
pub const fn from_packet(handle: packet_server::WvrProcessHandle) -> Self {
Self {
generation: handle.generation,
idx: handle.idx,
}
}
pub fn as_packet(&self) -> packet_server::WvrProcessHandle {
pub const fn as_packet(&self) -> packet_server::WvrProcessHandle {
packet_server::WvrProcessHandle {
idx: self.idx,
generation: self.generation,

View File

@@ -44,11 +44,11 @@ fn read_check(expected_size: u32, res: std::io::Result<usize>) -> bool {
if count == 0 {
return false;
}
if count as u32 != expected_size {
log::error!("count {} is not {}", count, expected_size);
false
} else {
if count as u32 == expected_size {
true // read succeeded
} else {
log::error!("count {count} is not {expected_size}");
false
}
}
Err(_e) => {
@@ -63,10 +63,10 @@ type Payload = SmallVec<[u8; 64]>;
fn read_payload(conn: &mut local_socket::Stream, size: u32) -> Option<Payload> {
let mut payload = Payload::new();
payload.resize(size as usize, 0);
if !read_check(size, conn.read(&mut payload)) {
None
} else {
if read_check(size, conn.read(&mut payload)) {
Some(payload)
} else {
None
}
}
@@ -89,7 +89,7 @@ pub fn gen_env_vec(input: &[String]) -> Vec<(&str, &str)> {
}
impl Connection {
fn new(conn: local_socket::Stream) -> Self {
const fn new(conn: local_socket::Stream) -> Self {
Self {
conn,
alive: true,
@@ -222,10 +222,9 @@ impl Connection {
false,
)?;
params.tasks.push(TickTask::NewDisplay(
packet_params.clone(),
Some(display_handle),
));
params
.tasks
.push(TickTask::NewDisplay(packet_params, Some(display_handle)));
send_packet(
&mut self.conn,
@@ -246,7 +245,7 @@ impl Connection {
let res = params
.state
.destroy_display(display::DisplayHandle::from_packet(handle))
.map_err(|e| format!("{:?}", e));
.map_err(|e| format!("{e:?}"));
send_packet(
&mut self.conn,
@@ -256,29 +255,25 @@ impl Connection {
}
fn handle_wvr_display_set_visible(
&mut self,
params: &mut TickParams,
handle: packet_server::WvrDisplayHandle,
visible: bool,
) -> anyhow::Result<()> {
) {
params.state.signals.send(WayVRSignal::DisplayVisibility(
display::DisplayHandle::from_packet(handle),
visible,
));
Ok(())
}
fn handle_wvr_display_set_window_layout(
&mut self,
params: &mut TickParams,
handle: packet_server::WvrDisplayHandle,
layout: packet_server::WvrDisplayWindowLayout,
) -> anyhow::Result<()> {
) {
params.state.signals.send(WayVRSignal::DisplayWindowLayout(
display::DisplayHandle::from_packet(handle),
layout,
));
Ok(())
}
fn handle_wvr_display_window_list(
@@ -331,11 +326,10 @@ impl Connection {
}
fn handle_wvr_window_set_visible(
&mut self,
params: &mut TickParams,
handle: packet_server::WvrWindowHandle,
visible: bool,
) -> anyhow::Result<()> {
) {
let mut to_resize = None;
if let Some(window) = params
@@ -355,8 +349,6 @@ impl Connection {
display.trigger_rerender();
}
}
Ok(())
}
fn handle_wvr_process_launch(
@@ -392,7 +384,7 @@ impl Connection {
serial: ipc::Serial,
display_handle: packet_server::WvrDisplayHandle,
) -> anyhow::Result<()> {
let native_handle = &display::DisplayHandle::from_packet(display_handle.clone());
let native_handle = &display::DisplayHandle::from_packet(display_handle);
let disp = params
.state
.displays
@@ -440,20 +432,17 @@ impl Connection {
// This request doesn't return anything to the client
fn handle_wvr_process_terminate(
&mut self,
params: &mut TickParams,
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 Some(process) = process else {
return Ok(());
return;
};
process.terminate();
Ok(())
}
fn handle_wvr_process_get(
@@ -462,7 +451,7 @@ impl Connection {
serial: ipc::Serial,
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
@@ -478,10 +467,9 @@ impl Connection {
}
fn handle_wlx_haptics(
&mut self,
params: &mut TickParams,
haptics_params: packet_client::WlxHapticsParams,
) -> anyhow::Result<()> {
) {
params
.state
.tasks
@@ -490,7 +478,6 @@ impl Connection {
frequency: haptics_params.frequency,
intensity: haptics_params.intensity,
}));
Ok(())
}
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)?;
}
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) => {
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) => {
self.handle_wvr_display_window_list(params, serial, display_handle)?;
}
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) => {
self.handle_wvr_process_get(params, serial, process_handle)?;
@@ -540,10 +527,10 @@ impl Connection {
self.handle_wvr_display_create(params, serial, packet_params)?;
}
PacketClient::WvrProcessTerminate(process_handle) => {
self.handle_wvr_process_terminate(params, process_handle)?;
Self::handle_wvr_process_terminate(params, process_handle);
}
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());
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
self.kill(format!("{}", e).as_str());
self.kill(format!("{e}").as_str());
false
} else {
true
@@ -589,8 +576,7 @@ impl Connection {
if payload_size > size_limit {
// over 128 KiB?
log::error!(
"Client sent a packet header with the size over {} bytes, closing connection.",
size_limit
"Client sent a packet header with the size over {size_limit} bytes, closing connection."
);
self.kill("Too big packet received (over 128 KiB)");
return false;
@@ -637,7 +623,7 @@ impl WayVRServer {
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 {
listener,
@@ -662,16 +648,15 @@ impl WayVRServer {
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.tick_connections(params);
Ok(())
}
pub fn broadcast(&mut self, packet: packet_server::PacketServer) {
for connection in &mut self.connections {
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_y = pos_y;
}
@@ -52,7 +52,7 @@ pub struct WindowManager {
}
impl WindowManager {
pub fn new() -> Self {
pub const fn new() -> Self {
Self {
windows: WindowVec::new(),
}
@@ -86,14 +86,14 @@ impl WindowManager {
gen_id!(WindowVec, Window, WindowCell, WindowHandle);
impl WindowHandle {
pub fn from_packet(handle: packet_server::WvrWindowHandle) -> Self {
pub const fn from_packet(handle: packet_server::WvrWindowHandle) -> Self {
Self {
generation: handle.generation,
idx: handle.idx,
}
}
pub fn as_packet(&self) -> packet_server::WvrWindowHandle {
pub const fn as_packet(&self) -> packet_server::WvrWindowHandle {
packet_server::WvrWindowHandle {
idx: self.idx,
generation: self.generation,

View File

@@ -69,79 +69,76 @@ impl AStrSetExt for AStrSet {
fn arc_rm(&mut self, value: &str) -> bool {
let index = self.iter().position(|v| v.as_ref().eq(value));
index
.map(|i| {
index.is_some_and(|i| {
self.remove(i);
true
})
.unwrap_or(false)
}
}
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)
}
pub fn def_watch_rot() -> Quat {
Quat::from_xyzw(-0.7071066, 0.0007963618, 0.7071066, 0.0)
pub const fn def_watch_rot() -> Quat {
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
}
pub fn def_pw_tokens() -> PwTokenMap {
pub const fn def_pw_tokens() -> PwTokenMap {
AStrMap::new()
}
fn def_mouse_move_interval_ms() -> u32 {
const fn def_mouse_move_interval_ms() -> u32 {
10 // 100fps
}
fn def_click_freeze_time_ms() -> u32 {
const fn def_click_freeze_time_ms() -> u32 {
300
}
pub fn def_true() -> bool {
pub const fn def_true() -> bool {
true
}
fn def_false() -> bool {
const fn def_false() -> bool {
false
}
fn def_one() -> f32 {
const fn def_one() -> f32 {
1.0
}
pub fn def_half() -> f32 {
pub const fn def_half() -> f32 {
0.5
}
pub fn def_point7() -> f32 {
pub const fn def_point7() -> f32 {
0.7
}
pub fn def_point3() -> f32 {
pub const fn def_point3() -> f32 {
0.3
}
fn def_osc_port() -> u16 {
const fn def_osc_port() -> u16 {
9000
}
fn def_empty_vec_string() -> Vec<String> {
const fn def_empty_vec_string() -> Vec<String> {
Vec::new()
}
fn def_timezones() -> Vec<String> {
let offset = chrono::Local::now().offset().fix();
const EMEA: i32 = -60 * 60; // UTC-1
const APAC: i32 = 5 * 60 * 60; // UTC+5
let offset = chrono::Local::now().offset().fix();
match offset.local_minus_utc() {
i32::MIN..EMEA => vec!["Europe/Paris".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()
}
fn def_curve_values() -> AStrMap<f32> {
const fn def_curve_values() -> AStrMap<f32> {
AStrMap::new()
}
fn def_transforms() -> AStrMap<Affine3A> {
const fn def_transforms() -> AStrMap<Affine3A> {
AStrMap::new()
}
@@ -177,7 +174,7 @@ fn def_font() -> Arc<str> {
"LiberationSans:style=Bold".into()
}
fn def_max_height() -> u16 {
const fn def_max_height() -> u16 {
1440
}
@@ -294,7 +291,7 @@ pub struct GeneralConfig {
#[serde(default = "def_max_height")]
pub screen_max_height: u16,
#[serde(default = "def_true")]
#[serde(default = "def_false")]
pub screen_render_down: bool,
#[serde(default = "def_point3")]
@@ -315,23 +312,21 @@ pub struct GeneralConfig {
impl GeneralConfig {
fn sanitize_range(name: &str, val: f32, from: f32, to: f32) {
if !val.is_normal() || val < from || val > to {
panic!(
"GeneralConfig: {} needs to be between {} and {}",
name, from, to
assert!(
!(!val.is_normal() || val < from || val > to),
"GeneralConfig: {name} needs to be between {from} and {to}"
);
}
}
pub fn load_from_disk() -> GeneralConfig {
pub fn load_from_disk() -> Self {
let config = load_general();
config.post_load();
config
}
fn post_load(&self) {
GeneralConfig::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("keyboard_scale", self.keyboard_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) {
Ok(d) => return d,
Err(e) => {
error!("Failed to parse {}, falling back to defaults.", file_name);
error!("{}", e);
error!("Failed to parse {file_name}, falling back to defaults.");
error!("{e}");
}
}
}
@@ -384,7 +379,7 @@ where
}
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 {
bail!("Could not read file at {}", &filename);
};
@@ -416,13 +411,13 @@ where
.filter_map(|r| match r {
Ok(entry) => Some(entry),
Err(e) => {
error!("Failed to read conf.d directory: {}", e);
error!("Failed to read conf.d directory: {e}");
None
}
})
.collect();
// Sort paths alphabetically
paths.sort_by_key(|dir| dir.path());
paths.sort_by_key(std::fs::DirEntry::path);
for path in paths {
log::info!("Loading config file: {}", path.path().to_string_lossy());
settings_builder = settings_builder.add_source(File::from(path.path()));
@@ -433,11 +428,11 @@ where
Ok(settings) => match settings.try_deserialize::<ConfigData>() {
Ok(config) => config,
Err(e) => {
panic!("Failed to deserialize settings: {}", e);
panic!("Failed to deserialize settings: {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
error!(
"Err: Failed to find config path, using {}",
FALLBACK_CONFIG_PATH
"Err: Failed to find config path, using {FALLBACK_CONFIG_PATH}"
);
PathBuf::from(FALLBACK_CONFIG_PATH)
});
@@ -31,8 +30,8 @@ pub fn get_config_root() -> PathBuf {
impl ConfigRoot {
pub fn get_conf_d_path(&self) -> PathBuf {
get_config_root().join(match self {
ConfigRoot::Generic => "conf.d",
ConfigRoot::WayVR => "wayvr.conf.d",
Self::Generic => "conf.d",
Self::WayVR => "wayvr.conf.d",
})
}

View File

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

View File

@@ -196,7 +196,7 @@ impl<D, S> CanvasBuilder<D, S> {
h,
};
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.,
w,
h,
@@ -213,7 +213,7 @@ impl<D, S> CanvasBuilder<D, S> {
};
let rect1 = Rect {
x,
y: y + h * 0.5 + 2.0,
y: h.mul_add(0.5, y) + 2.0,
w,
h: h * 0.5,
};
@@ -234,7 +234,7 @@ impl<D, S> CanvasBuilder<D, S> {
h,
};
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.,
w,
h,

View File

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

View File

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

View File

@@ -39,7 +39,7 @@ impl FontCache {
let ft = Library::init()?;
let fc = FontConfig::default();
Ok(FontCache {
Ok(Self {
primary_font,
fc,
ft,
@@ -55,7 +55,7 @@ impl FontCache {
) -> anyhow::Result<(f32, 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 max_w = sizef * 0.33;
@@ -143,26 +143,26 @@ impl FontCache {
if let Some(path) = pattern.filename() {
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 face = match self.ft.new_face(path, font_idx as _) {
Ok(face) => face,
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);
return 0;
}
};
match face.set_char_size(size << 6, size << 6, 96, 96) {
Ok(_) => {}
Ok(()) => {}
Err(e) => {
log::warn!("Failed to set font size: {:?}", e);
log::warn!("Failed to set font size: {e:?}");
coll.cp_map.insert(cp, 0);
return 0;
}
};
}
let idx = coll.fonts.len();
for (cp, _) in face.chars() {

View File

@@ -6,7 +6,7 @@ pub mod font;
pub mod modular;
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
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),
) {
return Ok(Vec4::new(
r as f32 / 255.,
g as f32 / 255.,
b as f32 / 255.,
f32::from(r) / 255.,
f32::from(g) / 255.,
f32::from(b) / 255.,
1.,
));
}
@@ -31,10 +31,10 @@ pub fn color_parse(html_hex: &str) -> anyhow::Result<GuiColor> {
u8::from_str_radix(&html_hex[7..9], 16),
) {
return Ok(Vec4::new(
r as f32 / 255.,
g as f32 / 255.,
b as f32 / 255.,
a as f32 / 255.,
f32::from(r) / 255.,
f32::from(g) / 255.,
f32::from(b) / 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) {
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::Overlay { target, action } => run_overlay(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);
audio_thump(app); // play sound for feedback
};
}
#[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"];
#[allow(clippy::too_many_lines)]
fn run_system(action: &SystemAction, app: &mut AppState) {
match action {
SystemAction::ToggleAllowSliding => {
@@ -461,7 +462,7 @@ fn run_system(action: &SystemAction, app: &mut AppState) {
ToastTopic::System,
format!(
"Sliding is {}.",
ENABLED_DISABLED[app.session.config.allow_sliding as usize]
ENABLED_DISABLED[usize::from(app.session.config.allow_sliding)]
)
.into(),
"".into(),
@@ -474,7 +475,7 @@ fn run_system(action: &SystemAction, app: &mut AppState) {
ToastTopic::System,
format!(
"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(),
@@ -487,7 +488,7 @@ fn run_system(action: &SystemAction, app: &mut AppState) {
ToastTopic::System,
format!(
"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(),
@@ -506,7 +507,7 @@ fn run_system(action: &SystemAction, app: &mut AppState) {
let display = 5 - i;
Toast::new(
ToastTopic::System,
format!("Fixing floor in {}", display).into(),
format!("Fixing floor in {display}").into(),
"Place either controller on the floor.".into(),
)
.with_timeout(1.0)
@@ -524,7 +525,7 @@ fn run_system(action: &SystemAction, app: &mut AppState) {
ToastTopic::System,
format!(
"Notifications are {}.",
ENABLED_DISABLED[app.session.config.notifications_enabled as usize]
ENABLED_DISABLED[usize::from(app.session.config.notifications_enabled)]
)
.into(),
"".into(),
@@ -538,7 +539,7 @@ fn run_system(action: &SystemAction, app: &mut AppState) {
ToastTopic::System,
format!(
"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(),
@@ -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() {
match proc.try_wait() {
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() {
Ok(proc) => {
press.child = Some(proc);
@@ -586,11 +590,12 @@ fn run_exec(args: &ExecArgs, toast: &Option<Arc<str>>, press: &mut PressData, ap
}
}
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) {
match data {
WatchAction::Hide => {
@@ -621,7 +626,7 @@ fn run_watch(data: &WatchAction, app: &mut AppState) {
app.tasks.enqueue(TaskType::Overlay(
OverlaySelector::Name(WATCH_NAME.into()),
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.spawn_rotation = app.session.config.watch_rot
* 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) {
match action {
OverlayAction::Reset => {
@@ -736,7 +742,7 @@ fn run_overlay(overlay: &OverlaySelector, action: &OverlayAction, app: &mut AppS
if state_dirty {
match save_layout(&app.session.config) {
Ok(_) => log::debug!("Saved state"),
Ok(()) => log::debug!("Saved state"),
Err(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.grabbable = o.recenter;
o.show_hide = o.recenter;
if !o.recenter {
if o.recenter {
Toast::new(
ToastTopic::System,
format!("{} is now locked in place!", o.name).into(),
format!("{} is now unlocked!", o.name).into(),
"".into(),
)
.submit(app);
} else {
Toast::new(
ToastTopic::System,
format!("{} is now unlocked!", o.name).into(),
format!("{} is now locked in place!", o.name).into(),
"".into(),
)
.submit(app);
@@ -776,17 +782,17 @@ fn run_overlay(overlay: &OverlaySelector, action: &OverlayAction, app: &mut AppS
overlay.clone(),
Box::new(|app, o| {
o.interactable = !o.interactable;
if !o.interactable {
if o.interactable {
Toast::new(
ToastTopic::System,
format!("{} is now non-interactable!", o.name).into(),
format!("{} is now interactable!", o.name).into(),
"".into(),
)
.submit(app);
} else {
Toast::new(
ToastTopic::System,
format!("{} is now interactable!", o.name).into(),
format!("{} is now non-interactable!", o.name).into(),
"".into(),
)
.submit(app);
@@ -827,7 +833,11 @@ fn run_window(window: &Arc<str>, action: &WindowAction, app: &mut AppState) {
)
.with_sound(true)
.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 } => {
let tz_str = match timezone {
Some(TimezoneDef::Idx(idx)) => {
if let Some(tz) = app.session.config.timezones.get(*idx) {
Some(tz.as_str())
} else {
log::error!("Timezone index out of range '{}'", idx);
Some(TimezoneDef::Idx(idx)) => app.session.config.timezones.get(*idx).map_or_else(
|| {
log::error!("Timezone index out of range '{idx}'");
label.set_fg_color(*FALLBACK_COLOR);
None
}
}
},
|tz| Some(tz.as_str()),
),
Some(TimezoneDef::Str(tz_str)) => Some(tz_str.as_ref()),
None => None,
};
@@ -127,14 +126,13 @@ pub fn modular_label_init(label: &mut ModularControl, content: &LabelContent, ap
}
LabelContent::Timezone { 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 {
label.set_text(&pretty_tz);
return;
} else {
log::error!("Timezone name not valid '{}'", &tz);
}
log::error!("Timezone name not valid '{}'", &tz);
} else {
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) {
// want panic
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"];
if let Some(device) = device {
let (text, color) = device
.soc
.map(|soc| {
let (text, color) = device.soc.map_or_else(
|| (String::new(), Vec4::ZERO),
|soc| {
let text = format!(
"{}{}",
tags[device.role as usize],
@@ -200,8 +199,8 @@ pub(super) fn label_update(control: &mut ModularControl, _: &mut (), app: &mut A
*normal_color
};
(text, color)
})
.unwrap_or_else(|| ("".into(), Vec4::ZERO));
},
);
control.set_text(&text);
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 } => {
let format = format.clone();
if let Some(tz) = timezone {
let date = Local::now().with_timezone(tz);
control.set_text(&format!("{}", &date.format(&format)));
let date_time = Local::now().with_timezone(tz);
control.set_text(&format!("{}", &date_time.format(&format)));
} else {
let date = Local::now();
control.set_text(&format!("{}", &date.format(&format)));
let date_time = Local::now();
control.set_text(&format!("{}", &date_time.format(&format)));
}
}
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() {
match proc.try_wait() {
Ok(Some(code)) => {
if !code.success() {
error_toast(
app,
"LabelData::Exec: Child process exited with code",
code,
);
} else {
if code.success() {
if let Some(mut stdout) = proc.stdout.take() {
let mut buf = String::new();
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");
return;
}
error_toast(app, "LabelData::Exec: Child process exited with code", code);
}
Ok(None) => {
*child = Some(proc);
@@ -281,7 +275,7 @@ pub(super) fn label_update(control: &mut ModularControl, _: &mut (), app: &mut A
*last_exec = Instant::now();
let args = command
.iter()
.map(|s| s.as_ref())
.map(std::convert::AsRef::as_ref)
.collect::<SmallVec<[&str; 8]>>();
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);
}
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 } => {

View File

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

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!("To check if you're in input group, run: id -nG");
if let Ok(user) = std::env::var("USER") {
log::error!(
"To add yourself to the input group, run: sudo usermod -aG input {}",
user
);
log::error!("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.");
}
Box::new(DummyProvider {})
@@ -163,28 +160,28 @@ impl UInputProvider {
.create(&mouse_id, mouse_name, 0, &abs_info)
.ok()?;
Some(UInputProvider {
Some(Self {
keyboard_handle,
mouse_handle,
desktop_extent: Vec2::ZERO,
desktop_origin: Vec2::ZERO,
current_action: Default::default(),
current_action: MouseAction::default(),
cur_modifiers: 0,
})
}
fn send_button_internal(&self, button: u16, down: bool) {
let time = get_time();
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),
];
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) {
#[cfg(debug_assertions)]
log::trace!("Mouse move: {:?}", pos);
log::trace!("Mouse move: {pos:?}");
let pos = (pos - self.desktop_origin) * (MOUSE_EXTENT / self.desktop_extent);
@@ -195,7 +192,7 @@ impl UInputProvider {
new_event(time, EV_SYN, 0, 0),
];
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) {
@@ -211,7 +208,7 @@ impl UInputProvider {
new_event(time, EV_SYN, 0, 0),
];
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) {
#[cfg(debug_assertions)]
log::trace!("send_key: {:?} {}", key, down);
log::trace!("send_key: {key:?} {down}");
let time = get_time();
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),
];
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) {
@@ -303,7 +300,7 @@ fn get_time() -> timeval {
}
#[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 {
time,
type_,
@@ -323,7 +320,7 @@ pub const META: KeyModifier = 0x80;
#[allow(non_camel_case_types)]
#[repr(u16)]
#[derive(Debug, Deserialize, PartialEq, Clone, Copy, IntegerId, EnumString, EnumIter)]
#[derive(Debug, Deserialize, PartialEq, Eq, Clone, Copy, IntegerId, EnumString, EnumIter)]
pub enum VirtualKey {
Escape = 9,
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)
|| key_between!(key, VirtualKey::Q, VirtualKey::Oem6)
|| 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
let _ = queue.blocking_dispatch(&mut me);
if let Some(keymap) = me.keymap.take() {
Ok(keymap)
} else {
Err(anyhow::anyhow!("Could not load keymap"))
}
me.keymap
.take()
.ok_or_else(|| anyhow::anyhow!("Could not load keymap"))
}
impl Dispatch<WlRegistry, GlobalListContents> for WlKeymapHandler {
@@ -84,7 +82,7 @@ impl Dispatch<WlSeat, ()> for WlKeymapHandler {
}
}
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.");
}
Err(err) => {
log::error!("Could not load keymap: {}", err);
log::error!("Could not load keymap: {err}");
log::error!("Default layout will be used.");
}
}
}
}
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 config;
mod config_io;
@@ -65,6 +79,7 @@ struct Args {
uidev: Option<String>,
}
#[allow(clippy::unnecessary_wraps)]
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut args = if std::env::args().skip(1).any(|a| !a.is_empty()) {
Args::parse()
@@ -78,7 +93,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
return Ok(());
}
logging_init(&mut args)?;
logging_init(&mut args);
log::info!(
"Welcome to {} version {}!",
@@ -122,23 +137,23 @@ fn auto_run(running: Arc<AtomicBool>, args: Args) {
Ok(()) => return,
Err(BackendError::NotSupported) => (),
Err(e) => {
log::error!("{}", e.to_string());
log::error!("{e}");
return;
}
};
}
}
#[cfg(feature = "openvr")]
if !args_get_openxr(&args) {
use crate::backend::openvr::openvr_run;
match openvr_run(running.clone(), args.show) {
match openvr_run(running, args.show) {
Ok(()) => return,
Err(BackendError::NotSupported) => (),
Err(e) => {
log::error!("{}", e.to_string());
log::error!("{e}");
return;
}
};
}
}
log::error!("No more backends to try");
@@ -151,9 +166,9 @@ fn auto_run(running: Arc<AtomicBool>, args: Args) {
}
#[allow(dead_code)]
fn args_get_openvr(_args: &Args) -> bool {
const fn args_get_openvr(args: &Args) -> bool {
#[cfg(feature = "openvr")]
let ret = _args.openvr;
let ret = args.openvr;
#[cfg(not(feature = "openvr"))]
let ret = false;
@@ -162,9 +177,9 @@ fn args_get_openvr(_args: &Args) -> bool {
}
#[allow(dead_code)]
fn args_get_openxr(_args: &Args) -> bool {
const fn args_get_openxr(args: &Args) -> bool {
#[cfg(feature = "openxr")]
let ret = _args.openxr;
let ret = args.openxr;
#[cfg(not(feature = "openxr"))]
let ret = false;
@@ -172,12 +187,12 @@ fn args_get_openxr(_args: &Args) -> bool {
ret
}
fn logging_init(args: &mut Args) -> anyhow::Result<()> {
fn logging_init(args: &mut Args) {
let log_file_path = args
.log_to
.take()
.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()
.write(true)
@@ -189,7 +204,7 @@ fn logging_init(args: &mut Args) -> anyhow::Result<()> {
Some(file)
}
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
}
};
@@ -225,13 +240,11 @@ fn logging_init(args: &mut Args) -> anyhow::Result<()> {
}
log_panics::init();
Ok(())
}
fn ensure_single_instance(replace: bool) -> bool {
let mut path = std::env::var("XDG_RUNTIME_DIR")
.map(PathBuf::from)
.unwrap_or_else(|_| PathBuf::from("/tmp"));
let mut path =
std::env::var("XDG_RUNTIME_DIR").map_or_else(|_| PathBuf::from("/tmp"), PathBuf::from);
path.push("wlx-overlay-s.pid");
if path.exists() {

View File

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

View File

@@ -21,28 +21,28 @@ pub fn create_custom(
match load_custom_ui(&name) {
Ok(config) => config,
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;
}
}
};
let canvas = match modular_canvas(&config.size, &config.elements, state) {
let canvas = match modular_canvas(config.size, &config.elements, state) {
Ok(canvas) => canvas,
Err(e) => {
log::error!("Failed to create canvas for {}: {:?}", name, e);
log::error!("Failed to create canvas for {name}: {e:?}");
return None;
}
};
let state = OverlayState {
name: name.clone(),
name,
want_visible: true,
interactable: true,
grabbable: true,
spawn_scale: config.width,
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()
};
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>(
app: &AppState,
mut keymap: Option<XkbKeymap>,
@@ -106,23 +107,25 @@ where
canvas.fg_color = color_parse("#cad3f5").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) {
keymap = None;
}
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() {
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;
for col in 0..LAYOUT.key_sizes[row].len() {
let my_size = LAYOUT.key_sizes[row][col];
let x = unit_size * sum_size + BUTTON_PADDING;
let w = unit_size * my_size - 2. * BUTTON_PADDING;
let x = unit_size.mul_add(sum_size, BUTTON_PADDING);
let w = unit_size.mul_add(my_size, -(2. * BUTTON_PADDING));
if let Some(key) = LAYOUT.main_layout[row][col].as_ref() {
let mut label = Vec::with_capacity(2);
@@ -136,7 +139,7 @@ where
let label0 = keymap.label_for_key(vk, 0);
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);
if has_altgr {
cap_type = KeyCapType::RegularAltGr;
@@ -176,7 +179,7 @@ where
});
} else if let Some(exec_args) = LAYOUT.exec_commands.get(key) {
if exec_args.is_empty() {
log::error!("Keyboard: EXEC args empty for {}", key);
log::error!("Keyboard: EXEC args empty for {key}");
continue;
}
let mut iter = exec_args.iter().cloned();
@@ -186,10 +189,10 @@ where
args: iter.by_ref().take_while(|arg| arg[..] != *"null").collect(),
release_program: iter.next(),
release_args: iter.collect(),
})
};
});
}
} else {
log::error!("Unknown key: {}", key);
log::error!("Unknown key: {key}");
}
if let Some(state) = maybe_state {
@@ -240,7 +243,7 @@ fn key_press(
) {
match control.state.as_mut() {
Some(KeyButtonData::Key { vk, pressed }) => {
data.key_click(app);
key_click(app);
data.modifiers |= match mode {
PointerMode::Right => SHIFT,
@@ -256,11 +259,11 @@ fn key_press(
Some(KeyButtonData::Modifier { modifier, sticky }) => {
*sticky = data.modifiers & *modifier == 0;
data.modifiers |= *modifier;
data.key_click(app);
key_click(app);
set_modifiers(app, data.modifiers);
}
Some(KeyButtonData::Macro { verbs }) => {
data.key_click(app);
key_click(app);
for (vk, press) in verbs {
send_key(app, *vk, *press);
}
@@ -270,7 +273,7 @@ fn key_press(
data.processes
.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() {
data.processes.push(child);
}
@@ -289,7 +292,7 @@ fn key_release(
send_key(app, *vk, false);
*pressed = false;
for m in AUTO_RELEASE_MODS.iter() {
for m in &AUTO_RELEASE_MODS {
if data.modifiers & *m != 0 {
data.modifiers &= !*m;
set_modifiers(app, data.modifiers);
@@ -349,13 +352,11 @@ struct KeyboardData {
const KEY_AUDIO_WAV: &[u8] = include_bytes!("../res/421581.wav");
impl KeyboardData {
fn key_click(&mut self, app: &mut AppState) {
fn key_click(app: &mut AppState) {
if app.session.config.keyboard_sound_enabled {
app.audio.play(KEY_AUDIO_WAV);
}
}
}
enum KeyButtonData {
Key {
@@ -395,6 +396,7 @@ pub enum AltModifier {
}
#[derive(Debug, Deserialize, Serialize)]
#[allow(clippy::struct_field_names)]
pub struct Layout {
name: String,
row_size: f32,
@@ -408,8 +410,8 @@ pub struct Layout {
}
impl Layout {
fn load_from_disk() -> Layout {
let mut layout = config::load_known_yaml::<Layout>(ConfigType::Keyboard);
fn load_from_disk() -> Self {
let mut layout = config::load_known_yaml::<Self>(ConfigType::Keyboard);
layout.post_load();
layout
}
@@ -418,19 +420,20 @@ impl Layout {
for i in 0..self.key_sizes.len() {
let row = &self.key_sizes[i];
let width: f32 = row.iter().sum();
if (width - self.row_size).abs() > 0.001 {
panic!(
assert!(
(width - self.row_size).abs() < 0.001,
"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() {
let row = &self.main_layout[i];
let width = row.len();
if width != self.key_sizes[i].len() {
panic!(
assert!(
(width == self.key_sizes[i].len()),
"Row {} has {} keys, needs to have {} according to key_sizes",
i,
width,
@@ -438,7 +441,6 @@ impl Layout {
);
}
}
}
fn label_for_key(&self, key: &str) -> Vec<String> {
if let Some(label) = self.labels.get(key) {
@@ -456,10 +458,7 @@ impl Layout {
}
if key.contains('_') {
key = key.split('_').next().unwrap_or_else(|| {
log::error!(
"keyboard.yaml: Key '{}' must not start or end with '_'!",
key
);
log::error!("keyboard.yaml: Key '{key}' must not start or end with '_'!");
"???"
});
}
@@ -507,10 +506,10 @@ struct KeyboardBackend {
impl OverlayBackend for KeyboardBackend {
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>) {
self.canvas.set_renderer(renderer)
self.canvas.set_renderer(renderer);
}
}
@@ -521,7 +520,7 @@ impl InteractionHandler for KeyboardBackend {
hit: &crate::backend::input::PointerHit,
pressed: bool,
) {
self.canvas.on_pointer(app, hit, pressed)
self.canvas.on_pointer(app, hit, pressed);
}
fn on_scroll(
&mut self,
@@ -530,10 +529,10 @@ impl InteractionHandler for KeyboardBackend {
delta_y: 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) {
self.canvas.on_left(app, pointer)
self.canvas.on_left(app, pointer);
}
fn on_hover(
&mut self,

View File

@@ -50,8 +50,7 @@ impl OverlayRenderer for MirrorRenderer {
fn should_render(&mut self, app: &mut AppState) -> anyhow::Result<ShouldRender> {
self.renderer
.as_mut()
.map(|r| r.should_render(app))
.unwrap_or(Ok(ShouldRender::Unable))
.map_or(Ok(ShouldRender::Unable), |r| r.should_render(app))
}
fn render(
&mut self,
@@ -90,7 +89,7 @@ impl OverlayRenderer for MirrorRenderer {
));
}
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;
// drop self
app.tasks
@@ -112,7 +111,7 @@ impl OverlayRenderer for MirrorRenderer {
app.tasks.enqueue(TaskType::Overlay(
OverlaySelector::Name(self.name.clone()),
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>,
show_hide: bool,
session: &AppSession,
) -> Option<(OverlayState, Box<dyn OverlayBackend>)> {
) -> (OverlayState, Box<dyn OverlayBackend>) {
let state = OverlayState {
name: name.clone(),
show_hide,
@@ -159,5 +158,5 @@ pub fn new_mirror(
..Default::default()
});
Some((state, backend))
(state, backend)
}

View File

@@ -9,6 +9,7 @@ use std::{
};
use vulkano::{
command_buffer::CommandBufferUsage,
format::Format,
image::{sampler::Filter, view::ImageView, Image},
pipeline::graphics::color_blend::AttachmentBlend,
};
@@ -26,7 +27,7 @@ use wlx_capture::{
use {
crate::config_io,
std::error::Error,
std::{ops::Deref, path::PathBuf, task},
std::{path::PathBuf, task},
wlx_capture::pipewire::PipewireCapture,
wlx_capture::pipewire::PipewireSelectScreenResult,
};
@@ -64,7 +65,7 @@ use crate::{
};
#[cfg(feature = "wayland")]
pub(crate) type WlxClientAlias = wlx_capture::wayland::WlxClient;
pub type WlxClientAlias = wlx_capture::wayland::WlxClient;
#[cfg(not(feature = "wayland"))]
pub(crate) type WlxClientAlias = ();
@@ -91,7 +92,7 @@ pub struct ScreenInteractionHandler {
mouse_transform: Affine2,
}
impl ScreenInteractionHandler {
fn new(pos: Vec2, size: Vec2, transform: Transform) -> ScreenInteractionHandler {
fn new(pos: Vec2, size: Vec2, transform: Transform) -> Self {
let transform = match transform {
Transform::_90 | Transform::Flipped90 => Affine2::from_cols(
vec2(0., size.y),
@@ -111,7 +112,7 @@ impl ScreenInteractionHandler {
_ => Affine2::from_cols(vec2(size.x, 0.), vec2(0., size.y), pos),
};
ScreenInteractionHandler {
Self {
mouse_transform: transform,
}
}
@@ -127,7 +128,7 @@ impl InteractionHandler for ScreenInteractionHandler {
{
let pos = self.mouse_transform.transform_point2(hit.uv);
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
}
@@ -139,7 +140,7 @@ impl InteractionHandler for ScreenInteractionHandler {
};
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);
@@ -152,7 +153,7 @@ impl InteractionHandler for ScreenInteractionHandler {
}
fn on_scroll(&mut self, app: &mut AppState, _hit: &PointerHit, delta_y: f32, delta_x: f32) {
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) {}
}
@@ -165,7 +166,7 @@ struct 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 {
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];
Ok(ScreenPipeline {
Ok(Self {
mouse: None,
pipeline,
extentf,
@@ -236,15 +237,15 @@ impl ScreenPipeline {
let vertex_buffer = app.graphics.upload_verts(
self.extentf[0],
self.extentf[1],
mouse.x * self.extentf[0] - half_size,
mouse.y * self.extentf[1] - half_size,
mouse.x.mul_add(self.extentf[0], -half_size),
mouse.y.mul_add(self.extentf[1], -half_size),
size,
size,
)?;
let set0 = self
.pipeline
.uniform_sampler(0, mouse_view.clone(), Filter::Nearest)?;
.uniform_sampler(0, mouse_view, Filter::Nearest)?;
let pass = self.pipeline.create_pass(
self.extentf,
@@ -275,8 +276,8 @@ impl ScreenRenderer {
pub fn new_raw(
name: Arc<str>,
capture: Box<dyn WlxCapture<WlxCaptureIn, WlxCaptureOut>>,
) -> ScreenRenderer {
ScreenRenderer {
) -> Self {
Self {
name,
capture,
pipeline: None,
@@ -286,11 +287,11 @@ impl ScreenRenderer {
}
#[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 capture = WlrDmabufCapture::new(client, output.id);
Some(ScreenRenderer {
Some(Self {
name: output.name.clone(),
capture: Box::new(capture),
pipeline: None,
@@ -300,11 +301,11 @@ impl ScreenRenderer {
}
#[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 capture = WlrScreencopyCapture::new(client, output.id);
Some(ScreenRenderer {
Some(Self {
name: output.name.clone(),
capture: Box::new(capture),
pipeline: None,
@@ -318,10 +319,7 @@ impl ScreenRenderer {
output: &WlxOutput,
token: Option<&str>,
session: &AppSession,
) -> anyhow::Result<(
ScreenRenderer,
Option<String>, /* pipewire restore token */
)> {
) -> anyhow::Result<(Self, Option<String> /* pipewire restore token */)> {
let name = output.name.clone();
let embed_mouse = !session.config.double_cursor_fix;
@@ -346,7 +344,7 @@ impl ScreenRenderer {
let capture = PipewireCapture::new(name, node_id);
Ok((
ScreenRenderer {
Self {
name: output.name.clone(),
capture: Box::new(capture),
pipeline: None,
@@ -358,10 +356,10 @@ impl ScreenRenderer {
}
#[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());
ScreenRenderer {
Self {
name: screen.name.clone(),
capture: Box::new(capture),
pipeline: None,
@@ -384,6 +382,39 @@ pub struct WlxCaptureOut {
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> {
match frame {
WlxFrame::Dmabuf(frame) => {
@@ -400,11 +431,7 @@ fn receive_callback(me: &WlxCaptureIn, frame: wlx_frame::WlxFrame) -> Option<Wlx
mouse: None,
}),
Err(e) => {
log::error!(
"{}: Failed to create DMA-buf vkImage: {}",
me.name,
e.to_string()
);
log::error!("{}: Failed to create DMA-buf vkImage: {}", me.name, e);
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 offset = frame.plane.offset as i64;
let offset = i64::from(frame.plane.offset);
let map = unsafe {
libc::mmap(
@@ -437,35 +464,15 @@ fn receive_callback(me: &WlxCaptureIn, frame: wlx_frame::WlxFrame) -> Option<Wlx
)
} 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
.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(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;
}
let image = {
let maybe_image =
upload_image(me, frame.format.width, frame.format.height, format, data);
unsafe { libc::munmap(map as *mut _, len) };
maybe_image
}?;
Some(WlxCaptureOut {
image,
@@ -484,33 +491,8 @@ fn receive_callback(me: &WlxCaptureIn, frame: wlx_frame::WlxFrame) -> Option<Wlx
}
};
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 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;
}
let data = unsafe { slice::from_raw_parts(frame.ptr as *const u8, frame.size) };
let image = upload_image(me, frame.format.width, frame.format.height, format, data)?;
Some(WlxCaptureOut {
image,
@@ -547,7 +529,7 @@ impl OverlayRenderer for ScreenRenderer {
return vec![];
}
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![];
}
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);
}
for frame in self.capture.receive().into_iter() {
if let Some(frame) = self.capture.receive() {
self.cur_frame = Some(frame);
}
@@ -623,7 +605,7 @@ impl OverlayRenderer for ScreenRenderer {
upload.build_and_execute_now()?;
pipeline
});
};
}
if self.cur_frame.is_some() {
Ok(ShouldRender::Should)
@@ -669,6 +651,7 @@ impl OverlayRenderer for ScreenRenderer {
}
#[cfg(feature = "wayland")]
#[allow(clippy::useless_let_if_seq)]
pub fn create_screen_renderer_wl(
output: &WlxOutput,
has_wlr_dmabuf: bool,
@@ -690,17 +673,15 @@ pub fn create_screen_renderer_wl(
if capture.is_none() {
log::info!("{}: Using Pipewire capture", &output.name);
let display_name = output.name.deref();
let display_name = &*output.name;
// 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 {
log::info!(
"Found existing Pipewire token for display {}: {}",
display_name,
t
);
log::info!("Found existing Pipewire token for display {display_name}: {t}");
}
match ScreenRenderer::new_pw(output, token, session) {
@@ -709,7 +690,7 @@ pub fn create_screen_renderer_wl(
if let Some(token) = restore_token {
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 {
name: name.clone(),
name,
keyboard_focus: Some(KeyboardFocus::PhysicalScreen),
grabbable: true,
recenter: true,
@@ -816,23 +797,19 @@ pub fn load_pw_token_config() -> Result<PwTokenMap, Box<dyn Error>> {
Ok(conf.pw_tokens)
}
pub(crate) struct ScreenCreateData {
pub struct ScreenCreateData {
pub screens: Vec<(ScreenMeta, OverlayState, Box<SplitOverlayBackend>)>,
}
#[cfg(not(feature = "wayland"))]
pub fn create_screens_wayland(
_wl: &mut WlxClientAlias,
_app: &AppState,
) -> anyhow::Result<ScreenCreateData> {
anyhow::bail!("Wayland support not enabled")
pub fn create_screens_wayland(_wl: &mut WlxClientAlias, _app: &AppState) -> ScreenCreateData {
ScreenCreateData {
screens: Vec::default(),
}
}
#[cfg(feature = "wayland")]
pub fn create_screens_wayland(
wl: &mut WlxClientAlias,
app: &mut AppState,
) -> anyhow::Result<ScreenCreateData> {
pub fn create_screens_wayland(wl: &mut WlxClientAlias, app: &mut AppState) -> ScreenCreateData {
let mut screens = vec![];
// 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_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) {
continue;
}
@@ -886,7 +863,7 @@ pub fn create_screens_wayland(
if pw_tokens_copy != pw_tokens {
// Token list changed, re-create token config file
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
.set_desktop_origin(vec2(origin.0 as f32, origin.1 as f32));
Ok(ScreenCreateData { screens })
ScreenCreateData { screens }
}
#[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
let mut pw_tokens: PwTokenMap = load_pw_token_config().unwrap_or_default();
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 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 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 {
// Token list changed, re-create token config file
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,
_180,
_270,
Flipped,
Flipped90,
Flipped180,
Flipped270,
@@ -1071,17 +1049,16 @@ pub enum Transform {
#[cfg(feature = "wayland")]
impl From<wl_output::Transform> for Transform {
fn from(t: wl_output::Transform) -> Transform {
fn from(t: wl_output::Transform) -> Self {
match t {
wl_output::Transform::Normal => Transform::Normal,
wl_output::Transform::_90 => Transform::_90,
wl_output::Transform::_180 => Transform::_180,
wl_output::Transform::_270 => Transform::_270,
wl_output::Transform::Flipped => Transform::Flipped180,
wl_output::Transform::Flipped90 => Transform::Flipped90,
wl_output::Transform::Flipped180 => Transform::Flipped180,
wl_output::Transform::Flipped270 => Transform::Flipped270,
_ => Transform::Normal,
wl_output::Transform::_90 => Self::_90,
wl_output::Transform::_180 => Self::_180,
wl_output::Transform::_270 => Self::_270,
wl_output::Transform::Flipped => Self::Flipped,
wl_output::Transform::Flipped90 => Self::Flipped90,
wl_output::Transform::Flipped180 => Self::Flipped180,
wl_output::Transform::Flipped270 => Self::Flipped270,
_ => Self::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] {
// screens above a certain resolution will have severe aliasing
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 {
2560
};
@@ -1111,7 +1088,6 @@ fn affine_from_format(format: &FrameFormat) -> Affine3A {
};
match format.transform {
wlx_frame::Transform::Normal => Affine3A::IDENTITY,
wlx_frame::Transform::Rotated90 => Affine3A::from_rotation_z(-PI / 2.0),
wlx_frame::Transform::Rotated180 => Affine3A::from_rotation_z(PI),
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 => {
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;
};
let mut best_dist = best
.map(|b| (b.monitor.x() - position.0).abs() + (b.monitor.y() - position.1).abs())
.unwrap_or(i32::MAX);
let mut best_dist = best.map_or(i32::MAX, |b| {
(b.monitor.x() - position.0).abs() + (b.monitor.y() - position.1).abs()
});
for stream in streams {
log::debug!("checking: {:?}", stream.monitor);
let dist =
@@ -1158,6 +1134,7 @@ fn best_match<'a>(
}
#[cfg(feature = "pipewire")]
#[allow(clippy::fn_params_excessive_bools)]
fn select_pw_screen(
instructions: &str,
token: Option<&str>,
@@ -1181,7 +1158,7 @@ fn select_pw_screen(
task::Poll::Ready(result) => return result,
task::Poll::Pending => {
if Instant::now() >= print_at {
log::info!("{}", instructions);
log::info!("{instructions}");
if let Ok(sender) = DbusNotificationSender::new() {
if let Ok(id) = sender.notify_send(instructions, "", 2, 0, 0, true) {
notify = Some((sender, id));
@@ -1193,7 +1170,6 @@ fn select_pw_screen(
std::thread::sleep(Duration::from_millis(10));
})
.await;
continue;
}
}
}

View File

@@ -46,8 +46,8 @@ pub struct Toast {
#[allow(dead_code)]
impl Toast {
pub fn new(topic: ToastTopic, title: Arc<str>, body: Arc<str>) -> Self {
Toast {
pub const fn new(topic: ToastTopic, title: Arc<str>, body: Arc<str>) -> Self {
Self {
title,
body,
opacity: 1.0,
@@ -56,15 +56,15 @@ impl Toast {
topic,
}
}
pub fn with_timeout(mut self, timeout: f32) -> Self {
pub const fn with_timeout(mut self, timeout: f32) -> Self {
self.timeout = timeout;
self
}
pub fn with_opacity(mut self, opacity: f32) -> Self {
pub const fn with_opacity(mut self, opacity: f32) -> Self {
self.opacity = opacity;
self
}
pub fn with_sound(mut self, sound: bool) -> Self {
pub const fn with_sound(mut self, sound: bool) -> Self {
self.sound = sound;
self
}
@@ -93,7 +93,7 @@ impl Toast {
// frame, only the first one gets created
app.tasks.enqueue_at(
TaskType::CreateOverlay(
selector.clone(),
selector,
Box::new(move |app| {
let mut maybe_toast = new_toast(self, app);
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() {
toast.title
} else {
let title = if toast.title.is_empty() {
"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
.fc
.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())
.ok()?;
(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;
@@ -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.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.fg_color = color_parse("#b8c0e0").unwrap(); // want panic
canvas.bg_color = color_parse("#24273a").unwrap(); // want panic
canvas.panel(0., 0., size.0, 30., 16.);
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 {
@@ -218,13 +218,13 @@ pub fn error_toast<ErrorType>(app: &mut AppState, title: &str, err: ErrorType)
where
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)
msg_err(app, &format!("{}: {}", title, err));
msg_err(app, &format!("{title}: {err}"));
}
pub fn error_toast_str(app: &mut AppState, message: &str) {
log::error!("{}", message);
log::error!("{message}");
msg_err(app, message);
}

View File

@@ -29,7 +29,7 @@ where
spawn_scale: config.width,
spawn_point: state.session.config.watch_pos,
spawn_rotation: state.session.config.watch_rot,
interaction_transform: ui_transform(&config.size),
interaction_transform: ui_transform(config.size),
relative_to,
..Default::default()
},
@@ -44,7 +44,7 @@ pub fn create_watch_canvas(
) -> anyhow::Result<Canvas<(), ModularData>> {
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>)

View File

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

View File

@@ -118,12 +118,12 @@ impl AppState {
#[cfg(feature = "osc")]
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,
include_bytes!("res/557297.wav"),
);
Ok(AppState {
Ok(Self {
fc: FontCache::new(session.config.primary_font.clone())?,
session,
tasks,
@@ -167,16 +167,16 @@ impl AppState {
let real_path = config_io::get_config_root().join(path);
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;
};
}
match std::fs::read(real_path.clone()) {
match std::fs::read(real_path) {
// Box is used here to work around `f`'s limited lifetime
Ok(f) => Box::leak(Box::new(f)).as_slice(),
Err(e) => {
log::warn!("Failed to read file at: {}", path);
log::warn!("{:?}", e);
log::warn!("Failed to read file at: {path}");
log::warn!("{e:?}");
fallback_data
}
}
@@ -195,7 +195,7 @@ pub struct AppSession {
impl AppSession {
pub fn load() -> Self {
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 mut toast_topics = IdMap::new();
@@ -210,11 +210,11 @@ impl AppSession {
#[cfg(feature = "wayvr")]
let wayvr_config = config_wayvr::load_wayvr();
AppSession {
Self {
config,
toast_topics,
#[cfg(feature = "wayvr")]
wayvr_config,
toast_topics,
}
}
}
@@ -225,8 +225,8 @@ pub struct AudioOutput {
}
impl AudioOutput {
pub fn new() -> Self {
AudioOutput {
pub const fn new() -> Self {
Self {
audio_stream: None,
first_try: true,
}
@@ -253,7 +253,7 @@ impl AudioOutput {
let source = match Decoder::new_wav(cursor) {
Ok(source) => source,
Err(e) => {
log::error!("Failed to play sound: {:?}", e);
log::error!("Failed to play sound: {e:?}");
return;
}
};