add wlx-common lib, move GeneralConfig into it
This commit is contained in:
12
Cargo.lock
generated
12
Cargo.lock
generated
@@ -6847,6 +6847,17 @@ dependencies = [
|
|||||||
"wayland-protocols",
|
"wayland-protocols",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wlx-common"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"chrono",
|
||||||
|
"glam",
|
||||||
|
"idmap",
|
||||||
|
"idmap-derive",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wlx-overlay-s"
|
name = "wlx-overlay-s"
|
||||||
version = "25.4.2"
|
version = "25.4.2"
|
||||||
@@ -6902,6 +6913,7 @@ dependencies = [
|
|||||||
"wgui",
|
"wgui",
|
||||||
"winit",
|
"winit",
|
||||||
"wlx-capture",
|
"wlx-capture",
|
||||||
|
"wlx-common",
|
||||||
"xcb",
|
"xcb",
|
||||||
"xdg 3.0.0",
|
"xdg 3.0.0",
|
||||||
"xkbcommon 0.9.0",
|
"xkbcommon 0.9.0",
|
||||||
|
|||||||
10
Cargo.toml
10
Cargo.toml
@@ -10,13 +10,21 @@ inherits = "release"
|
|||||||
debug = true
|
debug = true
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
members = ["uidev", "wgui", "wlx-overlay-s", "wlx-capture", "dash-frontend"]
|
members = [
|
||||||
|
"uidev",
|
||||||
|
"wgui",
|
||||||
|
"wlx-common",
|
||||||
|
"wlx-overlay-s",
|
||||||
|
"wlx-capture",
|
||||||
|
"dash-frontend",
|
||||||
|
]
|
||||||
resolver = "3"
|
resolver = "3"
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
anyhow = "1.0.100"
|
anyhow = "1.0.100"
|
||||||
glam = "0.30.7"
|
glam = "0.30.7"
|
||||||
idmap = "0.2.2"
|
idmap = "0.2.2"
|
||||||
|
idmap-derive = "0.2.2"
|
||||||
log = "0.4.28"
|
log = "0.4.28"
|
||||||
regex = "1.11.3"
|
regex = "1.11.3"
|
||||||
rust-embed = "8.7.2"
|
rust-embed = "8.7.2"
|
||||||
|
|||||||
8
wlx-common/.editorconfig
Normal file
8
wlx-common/.editorconfig
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*.rs]
|
||||||
|
indent_style = tab
|
||||||
|
indent_size = 2
|
||||||
|
charset = utf-8
|
||||||
|
trim_trailing_whitespace = false
|
||||||
|
insert_final_newline = false
|
||||||
12
wlx-common/Cargo.toml
Normal file
12
wlx-common/Cargo.toml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
[package]
|
||||||
|
name = "wlx-common"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
serde = { version = "1.0.228", features = ["derive"] }
|
||||||
|
glam = { workspace = true }
|
||||||
|
chrono = "0.4.42"
|
||||||
|
idmap = { workspace = true, features = ["serde"] }
|
||||||
|
idmap-derive = { workspace = true }
|
||||||
3
wlx-common/rustfmt.toml
Normal file
3
wlx-common/rustfmt.toml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
tab_spaces = 2
|
||||||
|
hard_tabs = true
|
||||||
|
max_width = 120
|
||||||
59
wlx-common/src/astr_containers.rs
Normal file
59
wlx-common/src/astr_containers.rs
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
pub type AStrMap<V> = Vec<(Arc<str>, V)>;
|
||||||
|
|
||||||
|
pub trait AStrMapExt<V> {
|
||||||
|
fn arc_set(&mut self, key: Arc<str>, value: V) -> bool;
|
||||||
|
fn arc_get(&self, key: &str) -> Option<&V>;
|
||||||
|
fn arc_rm(&mut self, key: &str) -> Option<V>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V> AStrMapExt<V> for AStrMap<V> {
|
||||||
|
fn arc_set(&mut self, key: Arc<str>, value: V) -> bool {
|
||||||
|
let index = self.iter().position(|(k, _)| k.as_ref().eq(key.as_ref()));
|
||||||
|
index.map(|i| self.remove(i).1);
|
||||||
|
self.push((key, value));
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn arc_get(&self, key: &str) -> Option<&V> {
|
||||||
|
self
|
||||||
|
.iter()
|
||||||
|
.find_map(|(k, v)| if k.as_ref().eq(key) { Some(v) } else { None })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn arc_rm(&mut self, key: &str) -> Option<V> {
|
||||||
|
let index = self.iter().position(|(k, _)| k.as_ref().eq(key));
|
||||||
|
index.map(|i| self.remove(i).1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type AStrSet = Vec<Arc<str>>;
|
||||||
|
|
||||||
|
pub trait AStrSetExt {
|
||||||
|
fn arc_set(&mut self, value: Arc<str>) -> bool;
|
||||||
|
fn arc_get(&self, value: &str) -> bool;
|
||||||
|
fn arc_rm(&mut self, value: &str) -> bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AStrSetExt for AStrSet {
|
||||||
|
fn arc_set(&mut self, value: Arc<str>) -> bool {
|
||||||
|
if self.iter().any(|v| v.as_ref().eq(value.as_ref())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
self.push(value);
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn arc_get(&self, value: &str) -> bool {
|
||||||
|
self.iter().any(|v| v.as_ref().eq(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn arc_rm(&mut self, value: &str) -> bool {
|
||||||
|
let index = self.iter().position(|v| v.as_ref().eq(value));
|
||||||
|
index.is_some_and(|i| {
|
||||||
|
self.remove(i);
|
||||||
|
true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
9
wlx-common/src/common.rs
Normal file
9
wlx-common/src/common.rs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone, Copy, Default)]
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum LeftRight {
|
||||||
|
#[default]
|
||||||
|
Left,
|
||||||
|
Right,
|
||||||
|
}
|
||||||
285
wlx-common/src/config.rs
Normal file
285
wlx-common/src/config.rs
Normal file
@@ -0,0 +1,285 @@
|
|||||||
|
use std::{collections::HashMap, sync::Arc};
|
||||||
|
|
||||||
|
use chrono::Offset;
|
||||||
|
use glam::{Affine3A, Quat, Vec3, vec3};
|
||||||
|
use idmap::IdMap;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
astr_containers::{AStrMap, AStrSet},
|
||||||
|
common::LeftRight,
|
||||||
|
overlays::{ToastDisplayMethod, ToastTopic},
|
||||||
|
windowing::OverlayWindowState,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub type PwTokenMap = AStrMap<String>;
|
||||||
|
|
||||||
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
|
pub struct SerializedWindowSet {
|
||||||
|
pub name: Arc<str>,
|
||||||
|
pub overlays: HashMap<Arc<str>, OverlayWindowState>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn def_watch_pos() -> Vec3 {
|
||||||
|
vec3(-0.03, -0.01, 0.125)
|
||||||
|
}
|
||||||
|
|
||||||
|
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 const fn def_left() -> LeftRight {
|
||||||
|
LeftRight::Left
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn def_pw_tokens() -> PwTokenMap {
|
||||||
|
AStrMap::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn def_mouse_move_interval_ms() -> u32 {
|
||||||
|
10 // 100fps
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn def_click_freeze_time_ms() -> u32 {
|
||||||
|
300
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn def_true() -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn def_false() -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn def_one() -> f32 {
|
||||||
|
1.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn def_half() -> f32 {
|
||||||
|
0.5
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn def_point7() -> f32 {
|
||||||
|
0.7
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn def_point3() -> f32 {
|
||||||
|
0.3
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn def_osc_port() -> u16 {
|
||||||
|
9000
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn def_empty_vec_string() -> Vec<String> {
|
||||||
|
Vec::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn def_sets() -> Vec<SerializedWindowSet> {
|
||||||
|
Vec::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn def_zero_u32() -> u32 {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn def_timezones() -> Vec<String> {
|
||||||
|
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()],
|
||||||
|
APAC..=i32::MAX => vec!["Europe/Paris".into(), "America/New_York".into()],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn def_screens() -> AStrSet {
|
||||||
|
AStrSet::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn def_curve_values() -> AStrMap<f32> {
|
||||||
|
AStrMap::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn def_transforms() -> AStrMap<Affine3A> {
|
||||||
|
AStrMap::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn def_auto() -> Arc<str> {
|
||||||
|
"auto".into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn def_empty() -> Arc<str> {
|
||||||
|
"".into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn def_toast_topics() -> IdMap<ToastTopic, ToastDisplayMethod> {
|
||||||
|
IdMap::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn def_font() -> Arc<str> {
|
||||||
|
"LiberationSans:style=Bold".into()
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn def_max_height() -> u16 {
|
||||||
|
1440
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize)]
|
||||||
|
pub struct GeneralConfig {
|
||||||
|
#[serde(default = "def_watch_pos")]
|
||||||
|
pub watch_pos: Vec3,
|
||||||
|
|
||||||
|
#[serde(default = "def_watch_rot")]
|
||||||
|
pub watch_rot: Quat,
|
||||||
|
|
||||||
|
#[serde(default = "def_left")]
|
||||||
|
pub watch_hand: LeftRight,
|
||||||
|
|
||||||
|
#[serde(default = "def_click_freeze_time_ms")]
|
||||||
|
pub click_freeze_time_ms: u32,
|
||||||
|
|
||||||
|
#[serde(default = "def_false")]
|
||||||
|
pub invert_scroll_direction_x: bool,
|
||||||
|
|
||||||
|
#[serde(default = "def_false")]
|
||||||
|
pub invert_scroll_direction_y: bool,
|
||||||
|
|
||||||
|
#[serde(default = "def_one")]
|
||||||
|
pub scroll_speed: f32,
|
||||||
|
|
||||||
|
#[serde(default = "def_mouse_move_interval_ms")]
|
||||||
|
pub mouse_move_interval_ms: u32,
|
||||||
|
|
||||||
|
#[serde(default = "def_true")]
|
||||||
|
pub notifications_enabled: bool,
|
||||||
|
|
||||||
|
#[serde(default = "def_true")]
|
||||||
|
pub notifications_sound_enabled: bool,
|
||||||
|
|
||||||
|
#[serde(default = "def_toast_topics")]
|
||||||
|
pub notification_topics: IdMap<ToastTopic, ToastDisplayMethod>,
|
||||||
|
|
||||||
|
#[serde(default = "def_empty")]
|
||||||
|
pub notification_sound: Arc<str>,
|
||||||
|
|
||||||
|
#[serde(default = "def_true")]
|
||||||
|
pub keyboard_sound_enabled: bool,
|
||||||
|
|
||||||
|
#[serde(default = "def_one")]
|
||||||
|
pub keyboard_scale: f32,
|
||||||
|
|
||||||
|
#[serde(default = "def_one")]
|
||||||
|
pub desktop_view_scale: f32,
|
||||||
|
|
||||||
|
#[serde(default = "def_half")]
|
||||||
|
pub watch_view_angle_min: f32,
|
||||||
|
|
||||||
|
#[serde(default = "def_point7")]
|
||||||
|
pub watch_view_angle_max: f32,
|
||||||
|
|
||||||
|
#[serde(default = "def_one")]
|
||||||
|
pub long_press_duration: f32,
|
||||||
|
|
||||||
|
#[serde(default = "def_osc_port")]
|
||||||
|
pub osc_out_port: u16,
|
||||||
|
|
||||||
|
#[serde(default = "def_false")]
|
||||||
|
pub upright_screen_fix: bool,
|
||||||
|
|
||||||
|
#[serde(default = "def_false")]
|
||||||
|
pub double_cursor_fix: bool,
|
||||||
|
|
||||||
|
#[serde(default = "def_screens")]
|
||||||
|
pub show_screens: AStrSet,
|
||||||
|
|
||||||
|
#[serde(default = "def_curve_values")]
|
||||||
|
pub curve_values: AStrMap<f32>,
|
||||||
|
|
||||||
|
#[serde(default = "def_transforms")]
|
||||||
|
pub transform_values: AStrMap<Affine3A>,
|
||||||
|
|
||||||
|
#[serde(default = "def_auto")]
|
||||||
|
pub capture_method: Arc<str>,
|
||||||
|
|
||||||
|
#[serde(default = "def_point7")]
|
||||||
|
pub xr_grab_sensitivity: f32,
|
||||||
|
|
||||||
|
#[serde(default = "def_point7")]
|
||||||
|
pub xr_click_sensitivity: f32,
|
||||||
|
|
||||||
|
#[serde(default = "def_point7")]
|
||||||
|
pub xr_alt_click_sensitivity: f32,
|
||||||
|
|
||||||
|
#[serde(default = "def_half")]
|
||||||
|
pub xr_grab_sensitivity_release: f32,
|
||||||
|
|
||||||
|
#[serde(default = "def_half")]
|
||||||
|
pub xr_click_sensitivity_release: f32,
|
||||||
|
|
||||||
|
#[serde(default = "def_half")]
|
||||||
|
pub xr_alt_click_sensitivity_release: f32,
|
||||||
|
|
||||||
|
#[serde(default = "def_true")]
|
||||||
|
pub allow_sliding: bool,
|
||||||
|
|
||||||
|
#[serde(default = "def_true")]
|
||||||
|
pub realign_on_showhide: bool,
|
||||||
|
|
||||||
|
#[serde(default = "def_false")]
|
||||||
|
pub focus_follows_mouse_mode: bool,
|
||||||
|
|
||||||
|
#[serde(default = "def_false")]
|
||||||
|
pub block_game_input: bool,
|
||||||
|
|
||||||
|
#[serde(default = "def_true")]
|
||||||
|
pub block_game_input_ignore_watch: bool,
|
||||||
|
|
||||||
|
#[serde(default = "def_font")]
|
||||||
|
pub primary_font: Arc<str>,
|
||||||
|
|
||||||
|
#[serde(default = "def_one")]
|
||||||
|
pub space_drag_multiplier: f32,
|
||||||
|
|
||||||
|
#[serde(default = "def_empty")]
|
||||||
|
pub skybox_texture: Arc<str>,
|
||||||
|
|
||||||
|
#[serde(default = "def_true")]
|
||||||
|
pub use_skybox: bool,
|
||||||
|
|
||||||
|
#[serde(default = "def_true")]
|
||||||
|
pub use_passthrough: bool,
|
||||||
|
|
||||||
|
#[serde(default = "def_max_height")]
|
||||||
|
pub screen_max_height: u16,
|
||||||
|
|
||||||
|
#[serde(default = "def_false")]
|
||||||
|
pub screen_render_down: bool,
|
||||||
|
|
||||||
|
#[serde(default = "def_point3")]
|
||||||
|
pub pointer_lerp_factor: f32,
|
||||||
|
|
||||||
|
#[serde(default = "def_false")]
|
||||||
|
pub space_rotate_unlocked: bool,
|
||||||
|
|
||||||
|
#[serde(default = "def_empty_vec_string")]
|
||||||
|
pub alt_click_down: Vec<String>,
|
||||||
|
|
||||||
|
#[serde(default = "def_empty_vec_string")]
|
||||||
|
pub alt_click_up: Vec<String>,
|
||||||
|
|
||||||
|
#[serde(default = "def_timezones")]
|
||||||
|
pub timezones: Vec<String>,
|
||||||
|
|
||||||
|
#[serde(default = "def_false")]
|
||||||
|
pub clock_12h: bool,
|
||||||
|
|
||||||
|
#[serde(default = "def_sets")]
|
||||||
|
pub sets: Vec<SerializedWindowSet>,
|
||||||
|
|
||||||
|
#[serde(default = "def_zero_u32")]
|
||||||
|
pub last_set: u32,
|
||||||
|
}
|
||||||
5
wlx-common/src/lib.rs
Normal file
5
wlx-common/src/lib.rs
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
pub mod astr_containers;
|
||||||
|
pub mod common;
|
||||||
|
pub mod config;
|
||||||
|
pub mod overlays;
|
||||||
|
pub mod windowing;
|
||||||
17
wlx-common/src/overlays.rs
Normal file
17
wlx-common/src/overlays.rs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
use idmap_derive::IntegerId;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, IntegerId, Serialize, Deserialize)]
|
||||||
|
pub enum ToastTopic {
|
||||||
|
System,
|
||||||
|
DesktopNotification,
|
||||||
|
XSNotification,
|
||||||
|
IpdChange,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
||||||
|
pub enum ToastDisplayMethod {
|
||||||
|
Hide,
|
||||||
|
Center,
|
||||||
|
Watch,
|
||||||
|
}
|
||||||
60
wlx-common/src/windowing.rs
Normal file
60
wlx-common/src/windowing.rs
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
use glam::Affine3A;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::common::LeftRight;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize)]
|
||||||
|
pub enum Positioning {
|
||||||
|
/// Stays in place, recenters relative to HMD
|
||||||
|
#[default]
|
||||||
|
Floating,
|
||||||
|
/// Stays in place, recenters relative to anchor. Follows anchor during anchor grab.
|
||||||
|
Anchored,
|
||||||
|
/// Same as anchor but paused due to interaction
|
||||||
|
AnchoredPaused,
|
||||||
|
/// Stays in place, no recentering
|
||||||
|
Static,
|
||||||
|
/// Following HMD
|
||||||
|
FollowHead { lerp: f32 },
|
||||||
|
/// Normally follows HMD, but paused due to interaction
|
||||||
|
FollowHeadPaused { lerp: f32 },
|
||||||
|
/// Following hand
|
||||||
|
FollowHand { hand: LeftRight, lerp: f32 },
|
||||||
|
/// Normally follows hand, but paused due to interaction
|
||||||
|
FollowHandPaused { hand: LeftRight, lerp: f32 },
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Positioning {
|
||||||
|
pub const fn moves_with_space(self) -> bool {
|
||||||
|
matches!(self, Self::Floating | Self::Anchored | Self::Static)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contains the window state for a given set
|
||||||
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
|
#[serde(default)]
|
||||||
|
pub struct OverlayWindowState {
|
||||||
|
pub transform: Affine3A,
|
||||||
|
pub alpha: f32,
|
||||||
|
pub grabbable: bool,
|
||||||
|
pub interactable: bool,
|
||||||
|
pub positioning: Positioning,
|
||||||
|
pub curvature: Option<f32>,
|
||||||
|
pub additive: bool,
|
||||||
|
pub saved_transform: Option<Affine3A>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for OverlayWindowState {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
grabbable: false,
|
||||||
|
interactable: false,
|
||||||
|
alpha: 1.0,
|
||||||
|
positioning: Positioning::Floating,
|
||||||
|
curvature: None,
|
||||||
|
transform: Affine3A::IDENTITY,
|
||||||
|
additive: false,
|
||||||
|
saved_transform: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -31,7 +31,7 @@ dbus = { version = "0.9.9" }
|
|||||||
futures = "0.3.31"
|
futures = "0.3.31"
|
||||||
glam = { workspace = true, features = ["mint", "serde"] }
|
glam = { workspace = true, features = ["mint", "serde"] }
|
||||||
idmap = { workspace = true, features = ["serde"] }
|
idmap = { workspace = true, features = ["serde"] }
|
||||||
idmap-derive = "0.2.2"
|
idmap-derive = { workspace = true }
|
||||||
input-linux = "0.7.1"
|
input-linux = "0.7.1"
|
||||||
json = { version = "0.12.4", optional = true }
|
json = { version = "0.12.4", optional = true }
|
||||||
json5 = "0.4.1"
|
json5 = "0.4.1"
|
||||||
@@ -61,6 +61,7 @@ strum = { version = "0.27.2", features = ["derive"] }
|
|||||||
sysinfo = { version = "0.37" }
|
sysinfo = { version = "0.37" }
|
||||||
thiserror = "2.0"
|
thiserror = "2.0"
|
||||||
wlx-capture = { path = "../wlx-capture" }
|
wlx-capture = { path = "../wlx-capture" }
|
||||||
|
wlx-common = { path = "../wlx-common" }
|
||||||
libmonado = { version = "1.3.2", optional = true }
|
libmonado = { version = "1.3.2", optional = true }
|
||||||
winit = { version = "0.30.12", optional = true }
|
winit = { version = "0.30.12", optional = true }
|
||||||
xdg = "3.0"
|
xdg = "3.0"
|
||||||
|
|||||||
@@ -4,14 +4,15 @@ use std::{collections::VecDeque, time::Instant};
|
|||||||
|
|
||||||
use glam::{Affine3A, Vec2, Vec3A, Vec3Swizzles};
|
use glam::{Affine3A, Vec2, Vec3A, Vec3Swizzles};
|
||||||
|
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{SmallVec, smallvec};
|
||||||
|
use wlx_common::windowing::{OverlayWindowState, Positioning};
|
||||||
|
|
||||||
use crate::overlays::anchor::ANCHOR_NAME;
|
use crate::overlays::anchor::ANCHOR_NAME;
|
||||||
use crate::state::{AppSession, AppState};
|
use crate::state::{AppSession, AppState};
|
||||||
use crate::subsystem::hid::WheelDelta;
|
use crate::subsystem::hid::WheelDelta;
|
||||||
use crate::subsystem::input::KeyboardFocus;
|
use crate::subsystem::input::KeyboardFocus;
|
||||||
use crate::windowing::manager::OverlayWindowManager;
|
use crate::windowing::manager::OverlayWindowManager;
|
||||||
use crate::windowing::window::{realign, OverlayWindowData, OverlayWindowState, Positioning};
|
use crate::windowing::window::{self, OverlayWindowData, realign};
|
||||||
use crate::windowing::{OverlayID, OverlaySelector};
|
use crate::windowing::{OverlayID, OverlaySelector};
|
||||||
|
|
||||||
use super::task::TaskType;
|
use super::task::TaskType;
|
||||||
@@ -705,7 +706,7 @@ where
|
|||||||
x => x,
|
x => x,
|
||||||
};
|
};
|
||||||
|
|
||||||
overlay_state.save_transform(app);
|
window::save_transform(overlay_state, app);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hide anchor
|
// Hide anchor
|
||||||
|
|||||||
@@ -2,37 +2,38 @@ use std::{
|
|||||||
collections::VecDeque,
|
collections::VecDeque,
|
||||||
ops::Add,
|
ops::Add,
|
||||||
sync::{
|
sync::{
|
||||||
atomic::{AtomicBool, AtomicUsize, Ordering},
|
|
||||||
Arc,
|
Arc,
|
||||||
|
atomic::{AtomicBool, AtomicUsize, Ordering},
|
||||||
},
|
},
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{Result, anyhow};
|
||||||
use ovr_overlay::{
|
use ovr_overlay::{
|
||||||
sys::{ETrackedDeviceProperty, EVRApplicationType, EVREventType},
|
|
||||||
TrackedDeviceIndex,
|
TrackedDeviceIndex,
|
||||||
|
sys::{ETrackedDeviceProperty, EVRApplicationType, EVREventType},
|
||||||
};
|
};
|
||||||
use vulkano::{device::physical::PhysicalDevice, Handle, VulkanObject};
|
use vulkano::{Handle, VulkanObject, device::physical::PhysicalDevice};
|
||||||
|
use wlx_common::overlays::ToastTopic;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{
|
backend::{
|
||||||
|
BackendError,
|
||||||
input::interact,
|
input::interact,
|
||||||
openvr::{
|
openvr::{
|
||||||
helpers::adjust_gain,
|
helpers::adjust_gain,
|
||||||
input::{set_action_manifest, OpenVrInputSource},
|
input::{OpenVrInputSource, set_action_manifest},
|
||||||
lines::LinePool,
|
lines::LinePool,
|
||||||
manifest::{install_manifest, uninstall_manifest},
|
manifest::{install_manifest, uninstall_manifest},
|
||||||
overlay::OpenVrOverlayData,
|
overlay::OpenVrOverlayData,
|
||||||
},
|
},
|
||||||
task::{SystemTask, TaskType},
|
task::{SystemTask, TaskType},
|
||||||
BackendError,
|
|
||||||
},
|
},
|
||||||
config::save_state,
|
config::save_state,
|
||||||
graphics::{init_openvr_graphics, GpuFutures},
|
graphics::{GpuFutures, init_openvr_graphics},
|
||||||
overlays::{
|
overlays::{
|
||||||
toast::{Toast, ToastTopic},
|
toast::Toast,
|
||||||
watch::{watch_fade, WATCH_NAME},
|
watch::{WATCH_NAME, watch_fade},
|
||||||
},
|
},
|
||||||
state::AppState,
|
state::AppState,
|
||||||
subsystem::notifications::NotificationManager,
|
subsystem::notifications::NotificationManager,
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ use std::{
|
|||||||
collections::VecDeque,
|
collections::VecDeque,
|
||||||
ops::Add,
|
ops::Add,
|
||||||
sync::{
|
sync::{
|
||||||
atomic::{AtomicBool, AtomicUsize, Ordering},
|
|
||||||
Arc,
|
Arc,
|
||||||
|
atomic::{AtomicBool, AtomicUsize, Ordering},
|
||||||
},
|
},
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
@@ -14,19 +14,20 @@ use libmonado::Monado;
|
|||||||
use openxr as xr;
|
use openxr as xr;
|
||||||
use skybox::create_skybox;
|
use skybox::create_skybox;
|
||||||
use vulkano::{Handle, VulkanObject};
|
use vulkano::{Handle, VulkanObject};
|
||||||
|
use wlx_common::overlays::ToastTopic;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{
|
backend::{
|
||||||
|
BackendError,
|
||||||
input::interact,
|
input::interact,
|
||||||
openxr::{lines::LinePool, overlay::OpenXrOverlayData},
|
openxr::{lines::LinePool, overlay::OpenXrOverlayData},
|
||||||
task::{SystemTask, TaskType},
|
task::{SystemTask, TaskType},
|
||||||
BackendError,
|
|
||||||
},
|
},
|
||||||
config::save_state,
|
config::save_state,
|
||||||
graphics::{init_openxr_graphics, GpuFutures},
|
graphics::{GpuFutures, init_openxr_graphics},
|
||||||
overlays::{
|
overlays::{
|
||||||
toast::{Toast, ToastTopic},
|
toast::Toast,
|
||||||
watch::{watch_fade, WATCH_NAME},
|
watch::{WATCH_NAME, watch_fade},
|
||||||
},
|
},
|
||||||
state::AppState,
|
state::AppState,
|
||||||
subsystem::notifications::NotificationManager,
|
subsystem::notifications::NotificationManager,
|
||||||
|
|||||||
@@ -1,360 +1,13 @@
|
|||||||
use std::path::PathBuf;
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use crate::config_io;
|
use crate::config_io;
|
||||||
use crate::overlays::toast::{DisplayMethod, ToastTopic};
|
|
||||||
use crate::state::LeftRight;
|
|
||||||
use crate::windowing::set::SerializedWindowSet;
|
|
||||||
use chrono::Offset;
|
|
||||||
use config::{Config, File};
|
use config::{Config, File};
|
||||||
use glam::{Affine3A, Quat, Vec3, vec3};
|
use glam::{Quat, Vec3};
|
||||||
use idmap::IdMap;
|
|
||||||
use log::error;
|
use log::error;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::path::PathBuf;
|
||||||
pub type AStrMap<V> = Vec<(Arc<str>, V)>;
|
use wlx_common::{
|
||||||
|
common::LeftRight,
|
||||||
pub trait AStrMapExt<V> {
|
config::{GeneralConfig, SerializedWindowSet},
|
||||||
fn arc_set(&mut self, key: Arc<str>, value: V) -> bool;
|
};
|
||||||
fn arc_get(&self, key: &str) -> Option<&V>;
|
|
||||||
fn arc_rm(&mut self, key: &str) -> Option<V>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<V> AStrMapExt<V> for AStrMap<V> {
|
|
||||||
fn arc_set(&mut self, key: Arc<str>, value: V) -> bool {
|
|
||||||
let index = self.iter().position(|(k, _)| k.as_ref().eq(key.as_ref()));
|
|
||||||
index.map(|i| self.remove(i).1);
|
|
||||||
self.push((key, value));
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
fn arc_get(&self, key: &str) -> Option<&V> {
|
|
||||||
self.iter()
|
|
||||||
.find_map(|(k, v)| if k.as_ref().eq(key) { Some(v) } else { None })
|
|
||||||
}
|
|
||||||
|
|
||||||
fn arc_rm(&mut self, key: &str) -> Option<V> {
|
|
||||||
let index = self.iter().position(|(k, _)| k.as_ref().eq(key));
|
|
||||||
index.map(|i| self.remove(i).1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type AStrSet = Vec<Arc<str>>;
|
|
||||||
|
|
||||||
pub trait AStrSetExt {
|
|
||||||
fn arc_set(&mut self, value: Arc<str>) -> bool;
|
|
||||||
fn arc_get(&self, value: &str) -> bool;
|
|
||||||
fn arc_rm(&mut self, value: &str) -> bool;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AStrSetExt for AStrSet {
|
|
||||||
fn arc_set(&mut self, value: Arc<str>) -> bool {
|
|
||||||
if self.iter().any(|v| v.as_ref().eq(value.as_ref())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
self.push(value);
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
fn arc_get(&self, value: &str) -> bool {
|
|
||||||
self.iter().any(|v| v.as_ref().eq(value))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn arc_rm(&mut self, value: &str) -> bool {
|
|
||||||
let index = self.iter().position(|v| v.as_ref().eq(value));
|
|
||||||
index.is_some_and(|i| {
|
|
||||||
self.remove(i);
|
|
||||||
true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type PwTokenMap = AStrMap<String>;
|
|
||||||
|
|
||||||
pub const fn def_watch_pos() -> Vec3 {
|
|
||||||
vec3(-0.03, -0.01, 0.125)
|
|
||||||
}
|
|
||||||
|
|
||||||
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 const fn def_left() -> LeftRight {
|
|
||||||
LeftRight::Left
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn def_pw_tokens() -> PwTokenMap {
|
|
||||||
AStrMap::new()
|
|
||||||
}
|
|
||||||
|
|
||||||
const fn def_mouse_move_interval_ms() -> u32 {
|
|
||||||
10 // 100fps
|
|
||||||
}
|
|
||||||
|
|
||||||
const fn def_click_freeze_time_ms() -> u32 {
|
|
||||||
300
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn def_true() -> bool {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
const fn def_false() -> bool {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
const fn def_one() -> f32 {
|
|
||||||
1.0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn def_half() -> f32 {
|
|
||||||
0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn def_point7() -> f32 {
|
|
||||||
0.7
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn def_point3() -> f32 {
|
|
||||||
0.3
|
|
||||||
}
|
|
||||||
|
|
||||||
const fn def_osc_port() -> u16 {
|
|
||||||
9000
|
|
||||||
}
|
|
||||||
|
|
||||||
const fn def_empty_vec_string() -> Vec<String> {
|
|
||||||
Vec::new()
|
|
||||||
}
|
|
||||||
|
|
||||||
const fn def_sets() -> Vec<SerializedWindowSet> {
|
|
||||||
Vec::new()
|
|
||||||
}
|
|
||||||
|
|
||||||
const fn def_zero_u32() -> u32 {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
|
|
||||||
fn def_timezones() -> Vec<String> {
|
|
||||||
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()],
|
|
||||||
APAC..=i32::MAX => vec!["Europe/Paris".into(), "America/New_York".into()],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const fn def_screens() -> AStrSet {
|
|
||||||
AStrSet::new()
|
|
||||||
}
|
|
||||||
|
|
||||||
const fn def_curve_values() -> AStrMap<f32> {
|
|
||||||
AStrMap::new()
|
|
||||||
}
|
|
||||||
|
|
||||||
const fn def_transforms() -> AStrMap<Affine3A> {
|
|
||||||
AStrMap::new()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn def_auto() -> Arc<str> {
|
|
||||||
"auto".into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn def_empty() -> Arc<str> {
|
|
||||||
"".into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn def_toast_topics() -> IdMap<ToastTopic, DisplayMethod> {
|
|
||||||
IdMap::new()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn def_font() -> Arc<str> {
|
|
||||||
"LiberationSans:style=Bold".into()
|
|
||||||
}
|
|
||||||
|
|
||||||
const fn def_max_height() -> u16 {
|
|
||||||
1440
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize)]
|
|
||||||
pub struct GeneralConfig {
|
|
||||||
#[serde(default = "def_watch_pos")]
|
|
||||||
pub watch_pos: Vec3,
|
|
||||||
|
|
||||||
#[serde(default = "def_watch_rot")]
|
|
||||||
pub watch_rot: Quat,
|
|
||||||
|
|
||||||
#[serde(default = "def_left")]
|
|
||||||
pub watch_hand: LeftRight,
|
|
||||||
|
|
||||||
#[serde(default = "def_click_freeze_time_ms")]
|
|
||||||
pub click_freeze_time_ms: u32,
|
|
||||||
|
|
||||||
#[serde(default = "def_false")]
|
|
||||||
pub invert_scroll_direction_x: bool,
|
|
||||||
|
|
||||||
#[serde(default = "def_false")]
|
|
||||||
pub invert_scroll_direction_y: bool,
|
|
||||||
|
|
||||||
#[serde(default = "def_one")]
|
|
||||||
pub scroll_speed: f32,
|
|
||||||
|
|
||||||
#[serde(default = "def_mouse_move_interval_ms")]
|
|
||||||
pub mouse_move_interval_ms: u32,
|
|
||||||
|
|
||||||
#[serde(default = "def_true")]
|
|
||||||
pub notifications_enabled: bool,
|
|
||||||
|
|
||||||
#[serde(default = "def_true")]
|
|
||||||
pub notifications_sound_enabled: bool,
|
|
||||||
|
|
||||||
#[serde(default = "def_toast_topics")]
|
|
||||||
pub notification_topics: IdMap<ToastTopic, DisplayMethod>,
|
|
||||||
|
|
||||||
#[serde(default = "def_empty")]
|
|
||||||
pub notification_sound: Arc<str>,
|
|
||||||
|
|
||||||
#[serde(default = "def_true")]
|
|
||||||
pub keyboard_sound_enabled: bool,
|
|
||||||
|
|
||||||
#[serde(default = "def_one")]
|
|
||||||
pub keyboard_scale: f32,
|
|
||||||
|
|
||||||
#[serde(default = "def_one")]
|
|
||||||
pub desktop_view_scale: f32,
|
|
||||||
|
|
||||||
#[serde(default = "def_half")]
|
|
||||||
pub watch_view_angle_min: f32,
|
|
||||||
|
|
||||||
#[serde(default = "def_point7")]
|
|
||||||
pub watch_view_angle_max: f32,
|
|
||||||
|
|
||||||
#[serde(default = "def_one")]
|
|
||||||
pub long_press_duration: f32,
|
|
||||||
|
|
||||||
#[serde(default = "def_osc_port")]
|
|
||||||
pub osc_out_port: u16,
|
|
||||||
|
|
||||||
#[serde(default = "def_false")]
|
|
||||||
pub upright_screen_fix: bool,
|
|
||||||
|
|
||||||
#[serde(default = "def_false")]
|
|
||||||
pub double_cursor_fix: bool,
|
|
||||||
|
|
||||||
#[serde(default = "def_screens")]
|
|
||||||
pub show_screens: AStrSet,
|
|
||||||
|
|
||||||
#[serde(default = "def_curve_values")]
|
|
||||||
pub curve_values: AStrMap<f32>,
|
|
||||||
|
|
||||||
#[serde(default = "def_transforms")]
|
|
||||||
pub transform_values: AStrMap<Affine3A>,
|
|
||||||
|
|
||||||
#[serde(default = "def_auto")]
|
|
||||||
pub capture_method: Arc<str>,
|
|
||||||
|
|
||||||
#[serde(default = "def_point7")]
|
|
||||||
pub xr_grab_sensitivity: f32,
|
|
||||||
|
|
||||||
#[serde(default = "def_point7")]
|
|
||||||
pub xr_click_sensitivity: f32,
|
|
||||||
|
|
||||||
#[serde(default = "def_point7")]
|
|
||||||
pub xr_alt_click_sensitivity: f32,
|
|
||||||
|
|
||||||
#[serde(default = "def_half")]
|
|
||||||
pub xr_grab_sensitivity_release: f32,
|
|
||||||
|
|
||||||
#[serde(default = "def_half")]
|
|
||||||
pub xr_click_sensitivity_release: f32,
|
|
||||||
|
|
||||||
#[serde(default = "def_half")]
|
|
||||||
pub xr_alt_click_sensitivity_release: f32,
|
|
||||||
|
|
||||||
#[serde(default = "def_true")]
|
|
||||||
pub allow_sliding: bool,
|
|
||||||
|
|
||||||
#[serde(default = "def_true")]
|
|
||||||
pub realign_on_showhide: bool,
|
|
||||||
|
|
||||||
#[serde(default = "def_false")]
|
|
||||||
pub focus_follows_mouse_mode: bool,
|
|
||||||
|
|
||||||
#[serde(default = "def_false")]
|
|
||||||
pub block_game_input: bool,
|
|
||||||
|
|
||||||
#[serde(default = "def_true")]
|
|
||||||
pub block_game_input_ignore_watch: bool,
|
|
||||||
|
|
||||||
#[serde(default = "def_font")]
|
|
||||||
pub primary_font: Arc<str>,
|
|
||||||
|
|
||||||
#[serde(default = "def_one")]
|
|
||||||
pub space_drag_multiplier: f32,
|
|
||||||
|
|
||||||
#[serde(default = "def_empty")]
|
|
||||||
pub skybox_texture: Arc<str>,
|
|
||||||
|
|
||||||
#[serde(default = "def_true")]
|
|
||||||
pub use_skybox: bool,
|
|
||||||
|
|
||||||
#[serde(default = "def_true")]
|
|
||||||
pub use_passthrough: bool,
|
|
||||||
|
|
||||||
#[serde(default = "def_max_height")]
|
|
||||||
pub screen_max_height: u16,
|
|
||||||
|
|
||||||
#[serde(default = "def_false")]
|
|
||||||
pub screen_render_down: bool,
|
|
||||||
|
|
||||||
#[serde(default = "def_point3")]
|
|
||||||
pub pointer_lerp_factor: f32,
|
|
||||||
|
|
||||||
#[serde(default = "def_false")]
|
|
||||||
pub space_rotate_unlocked: bool,
|
|
||||||
|
|
||||||
#[serde(default = "def_empty_vec_string")]
|
|
||||||
pub alt_click_down: Vec<String>,
|
|
||||||
|
|
||||||
#[serde(default = "def_empty_vec_string")]
|
|
||||||
pub alt_click_up: Vec<String>,
|
|
||||||
|
|
||||||
#[serde(default = "def_timezones")]
|
|
||||||
pub timezones: Vec<String>,
|
|
||||||
|
|
||||||
#[serde(default = "def_false")]
|
|
||||||
pub clock_12h: bool,
|
|
||||||
|
|
||||||
#[serde(default = "def_sets")]
|
|
||||||
pub sets: Vec<SerializedWindowSet>,
|
|
||||||
|
|
||||||
#[serde(default = "def_zero_u32")]
|
|
||||||
pub last_set: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GeneralConfig {
|
|
||||||
fn sanitize_range(name: &str, val: f32, from: f32, to: f32) {
|
|
||||||
assert!(
|
|
||||||
!(!val.is_normal() || val < from || val > to),
|
|
||||||
"GeneralConfig: {name} needs to be between {from} and {to}"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn load_from_disk() -> Self {
|
|
||||||
let config = load_general();
|
|
||||||
config.post_load();
|
|
||||||
config
|
|
||||||
}
|
|
||||||
|
|
||||||
fn post_load(&self) {
|
|
||||||
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);
|
|
||||||
Self::sanitize_range("scroll_speed", self.scroll_speed, 0.01, 10.0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const FALLBACKS: [&str; 2] = [
|
const FALLBACKS: [&str; 2] = [
|
||||||
include_str!("res/keyboard.yaml"),
|
include_str!("res/keyboard.yaml"),
|
||||||
@@ -446,12 +99,10 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_general() -> GeneralConfig {
|
pub fn load_general_config() -> GeneralConfig {
|
||||||
load_config_with_conf_d::<GeneralConfig>("config.yaml", config_io::ConfigRoot::Generic)
|
load_config_with_conf_d::<GeneralConfig>("config.yaml", config_io::ConfigRoot::Generic)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Config that is saved from the settings panel
|
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
pub struct AutoSettings {
|
pub struct AutoSettings {
|
||||||
pub watch_pos: Vec3,
|
pub watch_pos: Vec3,
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use wlx_common::{common::LeftRight, config::GeneralConfig, windowing::Positioning};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{
|
backend::{
|
||||||
@@ -17,9 +18,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
config::load_config_with_conf_d,
|
config::load_config_with_conf_d,
|
||||||
config_io,
|
config_io,
|
||||||
overlays::wayvr::{executable_exists_in_path, WayVRData},
|
overlays::wayvr::{WayVRData, executable_exists_in_path},
|
||||||
state::LeftRight,
|
|
||||||
windowing::window::Positioning,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Flat version of RelativeTo
|
// Flat version of RelativeTo
|
||||||
@@ -180,7 +179,7 @@ impl WayVRConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_wayvr_config(
|
pub fn get_wayvr_config(
|
||||||
config_general: &crate::config::GeneralConfig,
|
config_general: &GeneralConfig,
|
||||||
config_wayvr: &Self,
|
config_wayvr: &Self,
|
||||||
) -> anyhow::Result<wayvr::Config> {
|
) -> anyhow::Result<wayvr::Config> {
|
||||||
Ok(wayvr::Config {
|
Ok(wayvr::Config {
|
||||||
@@ -199,7 +198,7 @@ impl WayVRConfig {
|
|||||||
|
|
||||||
pub fn post_load(
|
pub fn post_load(
|
||||||
&self,
|
&self,
|
||||||
config: &crate::config::GeneralConfig,
|
config: &GeneralConfig,
|
||||||
tasks: &mut TaskContainer,
|
tasks: &mut TaskContainer,
|
||||||
) -> anyhow::Result<Option<Rc<RefCell<WayVRData>>>> {
|
) -> anyhow::Result<Option<Rc<RefCell<WayVRData>>>> {
|
||||||
let primary_count = self
|
let primary_count = self
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
use glam::{Affine3A, Quat, Vec3};
|
use glam::{Affine3A, Quat, Vec3};
|
||||||
use std::sync::{Arc, LazyLock};
|
use std::sync::{Arc, LazyLock};
|
||||||
|
use wlx_common::windowing::{OverlayWindowState, Positioning};
|
||||||
|
|
||||||
use crate::gui::panel::GuiPanel;
|
use crate::gui::panel::GuiPanel;
|
||||||
use crate::state::AppState;
|
use crate::state::AppState;
|
||||||
use crate::windowing::window::{OverlayWindowConfig, OverlayWindowState, Positioning};
|
|
||||||
use crate::windowing::Z_ORDER_ANCHOR;
|
use crate::windowing::Z_ORDER_ANCHOR;
|
||||||
|
use crate::windowing::window::OverlayWindowConfig;
|
||||||
|
|
||||||
pub static ANCHOR_NAME: LazyLock<Arc<str>> = LazyLock::new(|| Arc::from("anchor"));
|
pub static ANCHOR_NAME: LazyLock<Arc<str>> = LazyLock::new(|| Arc::from("anchor"));
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,9 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use glam::{Affine3A, Quat, Vec3, vec3};
|
use glam::{Affine3A, Quat, Vec3, vec3};
|
||||||
|
use wlx_common::windowing::OverlayWindowState;
|
||||||
|
|
||||||
use crate::{
|
use crate::{gui::panel::GuiPanel, state::AppState, windowing::window::OverlayWindowConfig};
|
||||||
gui::panel::GuiPanel,
|
|
||||||
state::AppState,
|
|
||||||
windowing::window::{OverlayWindowConfig, OverlayWindowState},
|
|
||||||
};
|
|
||||||
|
|
||||||
const SETTINGS_NAME: &str = "settings";
|
const SETTINGS_NAME: &str = "settings";
|
||||||
|
|
||||||
|
|||||||
@@ -5,11 +5,9 @@ use wgui::{
|
|||||||
parser::Fetchable, renderer_vk::text::custom_glyph::CustomGlyphData,
|
parser::Fetchable, renderer_vk::text::custom_glyph::CustomGlyphData,
|
||||||
widget::sprite::WidgetSprite,
|
widget::sprite::WidgetSprite,
|
||||||
};
|
};
|
||||||
|
use wlx_common::{common::LeftRight, windowing::Positioning};
|
||||||
|
|
||||||
use crate::{
|
use crate::{backend::task::OverlayTask, overlays::edit::EditModeWrapPanel, windowing::window};
|
||||||
backend::task::OverlayTask, overlays::edit::EditModeWrapPanel, state::LeftRight,
|
|
||||||
windowing::window::Positioning,
|
|
||||||
};
|
|
||||||
|
|
||||||
static POS_NAMES: [&str; 6] = ["static", "anchored", "floating", "hmd", "hand_l", "hand_r"];
|
static POS_NAMES: [&str; 6] = ["static", "anchored", "floating", "hmd", "hand_l", "hand_r"];
|
||||||
|
|
||||||
@@ -98,7 +96,7 @@ impl PositioningHandler {
|
|||||||
Box::new(move |app, owc| {
|
Box::new(move |app, owc| {
|
||||||
let state = owc.active_state.as_mut().unwrap(); //want panic
|
let state = owc.active_state.as_mut().unwrap(); //want panic
|
||||||
state.positioning = pos;
|
state.positioning = pos;
|
||||||
state.save_transform(app);
|
window::save_transform(state, app);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,12 +17,13 @@ use wgui::{
|
|||||||
util::WLength,
|
util::WLength,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
use wlx_common::windowing::{OverlayWindowState, Positioning};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
gui::panel::GuiPanel,
|
gui::panel::GuiPanel,
|
||||||
state::AppState,
|
state::AppState,
|
||||||
subsystem::hid::{ALT, CTRL, META, SHIFT, SUPER, XkbKeymap},
|
subsystem::hid::{ALT, CTRL, META, SHIFT, SUPER, XkbKeymap},
|
||||||
windowing::window::{OverlayWindowConfig, OverlayWindowState, Positioning},
|
windowing::window::OverlayWindowConfig,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ use std::{
|
|||||||
|
|
||||||
use futures::{Future, FutureExt};
|
use futures::{Future, FutureExt};
|
||||||
use glam::{Affine2, Affine3A, Vec3};
|
use glam::{Affine2, Affine3A, Vec3};
|
||||||
use wlx_capture::pipewire::{pipewire_select_screen, PipewireCapture, PipewireSelectScreenResult};
|
use wlx_capture::pipewire::{PipewireCapture, PipewireSelectScreenResult, pipewire_select_screen};
|
||||||
|
use wlx_common::windowing::OverlayWindowState;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{
|
backend::{
|
||||||
@@ -15,12 +16,12 @@ use crate::{
|
|||||||
state::{AppSession, AppState},
|
state::{AppSession, AppState},
|
||||||
subsystem::hid::WheelDelta,
|
subsystem::hid::WheelDelta,
|
||||||
windowing::{
|
windowing::{
|
||||||
backend::{
|
|
||||||
ui_transform, FrameMeta, OverlayBackend, OverlayEventData, RenderResources,
|
|
||||||
ShouldRender,
|
|
||||||
},
|
|
||||||
window::{OverlayWindowConfig, OverlayWindowState},
|
|
||||||
OverlaySelector,
|
OverlaySelector,
|
||||||
|
backend::{
|
||||||
|
FrameMeta, OverlayBackend, OverlayEventData, RenderResources, ShouldRender,
|
||||||
|
ui_transform,
|
||||||
|
},
|
||||||
|
window::OverlayWindowConfig,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -7,25 +7,26 @@ use vulkano::{
|
|||||||
command_buffer::CommandBufferUsage,
|
command_buffer::CommandBufferUsage,
|
||||||
device::Queue,
|
device::Queue,
|
||||||
format::Format,
|
format::Format,
|
||||||
image::{sampler::Filter, view::ImageView, Image},
|
image::{Image, sampler::Filter, view::ImageView},
|
||||||
pipeline::graphics::color_blend::AttachmentBlend,
|
pipeline::graphics::color_blend::AttachmentBlend,
|
||||||
};
|
};
|
||||||
use wgui::gfx::{
|
use wgui::gfx::{
|
||||||
|
WGfx,
|
||||||
cmd::WGfxClearMode,
|
cmd::WGfxClearMode,
|
||||||
pass::WGfxPass,
|
pass::WGfxPass,
|
||||||
pipeline::{WGfxPipeline, WPipelineCreateInfo},
|
pipeline::{WGfxPipeline, WPipelineCreateInfo},
|
||||||
WGfx,
|
|
||||||
};
|
};
|
||||||
use wlx_capture::{
|
use wlx_capture::{
|
||||||
frame::{self as wlx_frame, DrmFormat, FrameFormat, MouseMeta, Transform, WlxFrame},
|
|
||||||
WlxCapture,
|
WlxCapture,
|
||||||
|
frame::{self as wlx_frame, DrmFormat, FrameFormat, MouseMeta, Transform, WlxFrame},
|
||||||
};
|
};
|
||||||
|
use wlx_common::config::GeneralConfig;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::GeneralConfig,
|
|
||||||
graphics::{
|
graphics::{
|
||||||
dmabuf::{fourcc_to_vk, WGfxDmabuf},
|
Vert2Uv,
|
||||||
upload_quad_vertices, Vert2Uv,
|
dmabuf::{WGfxDmabuf, fourcc_to_vk},
|
||||||
|
upload_quad_vertices,
|
||||||
},
|
},
|
||||||
state::AppState,
|
state::AppState,
|
||||||
windowing::backend::{FrameMeta, RenderResources},
|
windowing::backend::{FrameMeta, RenderResources},
|
||||||
|
|||||||
@@ -1,15 +1,13 @@
|
|||||||
use std::{f32::consts::PI, sync::Arc};
|
use std::{f32::consts::PI, sync::Arc};
|
||||||
|
|
||||||
use glam::{vec3, Affine3A, Quat, Vec3};
|
use glam::{Affine3A, Quat, Vec3, vec3};
|
||||||
use wlx_capture::frame::Transform;
|
use wlx_capture::frame::Transform;
|
||||||
|
use wlx_common::windowing::{OverlayWindowState, Positioning};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
state::{AppSession, AppState, ScreenMeta},
|
state::{AppSession, AppState, ScreenMeta},
|
||||||
subsystem::{hid::XkbKeymap, input::KeyboardFocus},
|
subsystem::{hid::XkbKeymap, input::KeyboardFocus},
|
||||||
windowing::{
|
windowing::{backend::OverlayBackend, window::OverlayWindowConfig},
|
||||||
backend::OverlayBackend,
|
|
||||||
window::{OverlayWindowConfig, OverlayWindowState, Positioning},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod backend;
|
pub mod backend;
|
||||||
|
|||||||
@@ -6,12 +6,9 @@ use wlx_capture::{
|
|||||||
pipewire::{PipewireCapture, PipewireSelectScreenResult},
|
pipewire::{PipewireCapture, PipewireSelectScreenResult},
|
||||||
wayland::WlxOutput,
|
wayland::WlxOutput,
|
||||||
};
|
};
|
||||||
|
use wlx_common::config::{PwTokenMap, def_pw_tokens};
|
||||||
|
|
||||||
use crate::{
|
use crate::{config_io, state::AppState};
|
||||||
config::{PwTokenMap, def_pw_tokens},
|
|
||||||
config_io,
|
|
||||||
state::AppState,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
backend::ScreenBackend,
|
backend::ScreenBackend,
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ use wlx_capture::{
|
|||||||
wlr_dmabuf::WlrDmabufCapture,
|
wlr_dmabuf::WlrDmabufCapture,
|
||||||
wlr_screencopy::WlrScreencopyCapture,
|
wlr_screencopy::WlrScreencopyCapture,
|
||||||
};
|
};
|
||||||
|
use wlx_common::{astr_containers::AStrMapExt, config::PwTokenMap};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::{AStrMapExt, PwTokenMap},
|
|
||||||
overlays::screen::create_screen_from_backend,
|
overlays::screen::create_screen_from_backend,
|
||||||
state::{AppState, ScreenMeta},
|
state::{AppState, ScreenMeta},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -35,9 +35,9 @@ impl ScreenBackend {
|
|||||||
pub fn create_screens_x11pw(app: &mut AppState) -> anyhow::Result<ScreenCreateData> {
|
pub fn create_screens_x11pw(app: &mut AppState) -> anyhow::Result<ScreenCreateData> {
|
||||||
use glam::vec2;
|
use glam::vec2;
|
||||||
use wlx_capture::{pipewire::PipewireCapture, xshm::xshm_get_monitors};
|
use wlx_capture::{pipewire::PipewireCapture, xshm::xshm_get_monitors};
|
||||||
|
use wlx_common::{astr_containers::AStrMapExt, config::PwTokenMap};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::{AStrMapExt, PwTokenMap},
|
|
||||||
overlays::screen::{
|
overlays::screen::{
|
||||||
create_screen_from_backend,
|
create_screen_from_backend,
|
||||||
pw::{load_pw_token_config, save_pw_token_config, select_pw_screen},
|
pw::{load_pw_token_config, save_pw_token_config, select_pw_screen},
|
||||||
|
|||||||
@@ -6,8 +6,6 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use glam::{Affine3A, Quat, Vec3, vec3};
|
use glam::{Affine3A, Quat, Vec3, vec3};
|
||||||
use idmap_derive::IntegerId;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use wgui::{
|
use wgui::{
|
||||||
i18n::Translation,
|
i18n::Translation,
|
||||||
parser::parse_color_hex,
|
parser::parse_color_hex,
|
||||||
@@ -22,15 +20,17 @@ use wgui::{
|
|||||||
util::WLength,
|
util::WLength,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
use wlx_common::{
|
||||||
|
common::LeftRight,
|
||||||
|
overlays::{ToastDisplayMethod, ToastTopic},
|
||||||
|
windowing::{OverlayWindowState, Positioning},
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::task::TaskType,
|
backend::task::TaskType,
|
||||||
gui::panel::GuiPanel,
|
gui::panel::GuiPanel,
|
||||||
state::{AppState, LeftRight},
|
state::AppState,
|
||||||
windowing::{
|
windowing::{OverlaySelector, Z_ORDER_TOAST, window::OverlayWindowConfig},
|
||||||
OverlaySelector, Z_ORDER_TOAST,
|
|
||||||
window::{OverlayWindowConfig, OverlayWindowState, Positioning},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const FONT_SIZE: isize = 16;
|
const FONT_SIZE: isize = 16;
|
||||||
@@ -38,21 +38,6 @@ const PADDING: (f32, f32) = (25., 7.);
|
|||||||
const PIXELS_TO_METERS: f32 = 1. / 2000.;
|
const PIXELS_TO_METERS: f32 = 1. / 2000.;
|
||||||
static TOAST_NAME: LazyLock<Arc<str>> = LazyLock::new(|| "toast".into());
|
static TOAST_NAME: LazyLock<Arc<str>> = LazyLock::new(|| "toast".into());
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
|
||||||
pub enum DisplayMethod {
|
|
||||||
Hide,
|
|
||||||
Center,
|
|
||||||
Watch,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, IntegerId, Serialize, Deserialize)]
|
|
||||||
pub enum ToastTopic {
|
|
||||||
System,
|
|
||||||
DesktopNotification,
|
|
||||||
XSNotification,
|
|
||||||
IpdChange,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Toast {
|
pub struct Toast {
|
||||||
pub title: String,
|
pub title: String,
|
||||||
pub body: String,
|
pub body: String,
|
||||||
@@ -134,16 +119,16 @@ fn new_toast(toast: Toast, app: &mut AppState) -> Option<OverlayWindowConfig> {
|
|||||||
.toast_topics
|
.toast_topics
|
||||||
.get(toast.topic)
|
.get(toast.topic)
|
||||||
.copied()
|
.copied()
|
||||||
.unwrap_or(DisplayMethod::Hide);
|
.unwrap_or(ToastDisplayMethod::Hide);
|
||||||
|
|
||||||
let (spawn_point, spawn_rotation, positioning) = match current_method {
|
let (spawn_point, spawn_rotation, positioning) = match current_method {
|
||||||
DisplayMethod::Hide => return None,
|
ToastDisplayMethod::Hide => return None,
|
||||||
DisplayMethod::Center => (
|
ToastDisplayMethod::Center => (
|
||||||
vec3(0., -0.2, -0.5),
|
vec3(0., -0.2, -0.5),
|
||||||
Quat::IDENTITY,
|
Quat::IDENTITY,
|
||||||
Positioning::FollowHead { lerp: 0.1 },
|
Positioning::FollowHead { lerp: 0.1 },
|
||||||
),
|
),
|
||||||
DisplayMethod::Watch => {
|
ToastDisplayMethod::Watch => {
|
||||||
let mut watch_pos = app.session.config.watch_pos + vec3(-0.005, -0.05, 0.02);
|
let mut watch_pos = app.session.config.watch_pos + vec3(-0.005, -0.05, 0.02);
|
||||||
let mut watch_rot = app.session.config.watch_rot;
|
let mut watch_rot = app.session.config.watch_rot;
|
||||||
let relative_to = match app.session.config.watch_hand {
|
let relative_to = match app.session.config.watch_hand {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use wgui::{
|
|||||||
event::{CallbackDataCommon, EventAlterables},
|
event::{CallbackDataCommon, EventAlterables},
|
||||||
parser::Fetchable,
|
parser::Fetchable,
|
||||||
};
|
};
|
||||||
|
use wlx_common::windowing::{OverlayWindowState, Positioning};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
gui::{
|
gui::{
|
||||||
@@ -14,9 +15,9 @@ use crate::{
|
|||||||
},
|
},
|
||||||
state::AppState,
|
state::AppState,
|
||||||
windowing::{
|
windowing::{
|
||||||
backend::OverlayEventData,
|
|
||||||
window::{OverlayWindowConfig, OverlayWindowData, OverlayWindowState, Positioning},
|
|
||||||
Z_ORDER_WATCH,
|
Z_ORDER_WATCH,
|
||||||
|
backend::OverlayEventData,
|
||||||
|
window::{OverlayWindowConfig, OverlayWindowData},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,42 +1,42 @@
|
|||||||
use glam::{vec3, Affine2, Affine3A, Quat, Vec3};
|
use glam::{Affine2, Affine3A, Quat, Vec3, vec3};
|
||||||
use smallvec::smallvec;
|
use smallvec::smallvec;
|
||||||
use std::{cell::RefCell, collections::HashMap, rc::Rc, sync::Arc};
|
use std::{cell::RefCell, collections::HashMap, rc::Rc, sync::Arc};
|
||||||
use vulkano::{
|
use vulkano::{
|
||||||
buffer::{BufferUsage, Subbuffer},
|
buffer::{BufferUsage, Subbuffer},
|
||||||
command_buffer::CommandBufferUsage,
|
command_buffer::CommandBufferUsage,
|
||||||
format::Format,
|
format::Format,
|
||||||
image::{view::ImageView, Image, ImageTiling, SubresourceLayout},
|
image::{Image, ImageTiling, SubresourceLayout, view::ImageView},
|
||||||
};
|
};
|
||||||
use wayvr_ipc::packet_server::{self, PacketServer, WvrStateChanged};
|
use wayvr_ipc::packet_server::{self, PacketServer, WvrStateChanged};
|
||||||
use wgui::gfx::{
|
use wgui::gfx::{
|
||||||
|
WGfx,
|
||||||
pass::WGfxPass,
|
pass::WGfxPass,
|
||||||
pipeline::{WGfxPipeline, WPipelineCreateInfo},
|
pipeline::{WGfxPipeline, WPipelineCreateInfo},
|
||||||
WGfx,
|
|
||||||
};
|
};
|
||||||
use wlx_capture::frame::{DmabufFrame, FourCC, FrameFormat, FramePlane};
|
use wlx_capture::frame::{DmabufFrame, FourCC, FrameFormat, FramePlane};
|
||||||
|
use wlx_common::windowing::OverlayWindowState;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{
|
backend::{
|
||||||
input::{self, HoverResult},
|
input::{self, HoverResult},
|
||||||
task::TaskType,
|
task::TaskType,
|
||||||
wayvr::{
|
wayvr::{
|
||||||
self, display,
|
self, WayVR, WayVRAction, WayVRDisplayClickAction, display,
|
||||||
server_ipc::{gen_args_vec, gen_env_vec},
|
server_ipc::{gen_args_vec, gen_env_vec},
|
||||||
WayVR, WayVRAction, WayVRDisplayClickAction,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
config_wayvr,
|
config_wayvr,
|
||||||
graphics::{dmabuf::WGfxDmabuf, Vert2Uv},
|
graphics::{Vert2Uv, dmabuf::WGfxDmabuf},
|
||||||
state::{self, AppState},
|
state::{self, AppState},
|
||||||
subsystem::{hid::WheelDelta, input::KeyboardFocus},
|
subsystem::{hid::WheelDelta, input::KeyboardFocus},
|
||||||
windowing::{
|
windowing::{
|
||||||
|
OverlayID, OverlaySelector, Z_ORDER_DASHBOARD,
|
||||||
backend::{
|
backend::{
|
||||||
ui_transform, FrameMeta, OverlayBackend, OverlayEventData, RenderResources,
|
FrameMeta, OverlayBackend, OverlayEventData, RenderResources, ShouldRender,
|
||||||
ShouldRender,
|
ui_transform,
|
||||||
},
|
},
|
||||||
manager::OverlayWindowManager,
|
manager::OverlayWindowManager,
|
||||||
window::{OverlayWindowConfig, OverlayWindowData, OverlayWindowState},
|
window::{OverlayWindowConfig, OverlayWindowData},
|
||||||
OverlayID, OverlaySelector, Z_ORDER_DASHBOARD,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
use glam::Affine3A;
|
use glam::Affine3A;
|
||||||
use idmap::IdMap;
|
use idmap::IdMap;
|
||||||
use serde::{Deserialize, Serialize};
|
use smallvec::{SmallVec, smallvec};
|
||||||
use smallvec::{smallvec, SmallVec};
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use wgui::{
|
use wgui::{
|
||||||
font_config::WguiFontConfig, gfx::WGfx, globals::WguiGlobals,
|
font_config::WguiFontConfig, gfx::WGfx, globals::WguiGlobals,
|
||||||
renderer_vk::context::SharedContext as WSharedContext,
|
renderer_vk::context::SharedContext as WSharedContext,
|
||||||
};
|
};
|
||||||
|
use wlx_common::{
|
||||||
|
config::GeneralConfig,
|
||||||
|
overlays::{ToastDisplayMethod, ToastTopic},
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(feature = "wayvr")]
|
#[cfg(feature = "wayvr")]
|
||||||
use {
|
use {
|
||||||
@@ -20,11 +23,10 @@ use crate::subsystem::osc::OscSender;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{input::InputState, task::TaskContainer},
|
backend::{input::InputState, task::TaskContainer},
|
||||||
config::GeneralConfig,
|
config::load_general_config,
|
||||||
config_io,
|
config_io,
|
||||||
graphics::WGfxExtras,
|
graphics::WGfxExtras,
|
||||||
gui,
|
gui,
|
||||||
overlays::toast::{DisplayMethod, ToastTopic},
|
|
||||||
subsystem::{audio::AudioOutput, input::HidWrapper},
|
subsystem::{audio::AudioOutput, input::HidWrapper},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -156,19 +158,19 @@ pub struct AppSession {
|
|||||||
#[cfg(feature = "wayvr")]
|
#[cfg(feature = "wayvr")]
|
||||||
pub wayvr_config: WayVRConfig,
|
pub wayvr_config: WayVRConfig,
|
||||||
|
|
||||||
pub toast_topics: IdMap<ToastTopic, DisplayMethod>,
|
pub toast_topics: IdMap<ToastTopic, ToastDisplayMethod>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AppSession {
|
impl AppSession {
|
||||||
pub fn load() -> Self {
|
pub fn load() -> Self {
|
||||||
let config_root_path = config_io::ConfigRoot::Generic.ensure_dir();
|
let config_root_path = config_io::ConfigRoot::Generic.ensure_dir();
|
||||||
log::info!("Config root path: {}", config_root_path.display());
|
log::info!("Config root path: {}", config_root_path.display());
|
||||||
let config = GeneralConfig::load_from_disk();
|
let config = load_general_config();
|
||||||
|
|
||||||
let mut toast_topics = IdMap::new();
|
let mut toast_topics = IdMap::new();
|
||||||
toast_topics.insert(ToastTopic::System, DisplayMethod::Center);
|
toast_topics.insert(ToastTopic::System, ToastDisplayMethod::Center);
|
||||||
toast_topics.insert(ToastTopic::DesktopNotification, DisplayMethod::Center);
|
toast_topics.insert(ToastTopic::DesktopNotification, ToastDisplayMethod::Center);
|
||||||
toast_topics.insert(ToastTopic::XSNotification, DisplayMethod::Center);
|
toast_topics.insert(ToastTopic::XSNotification, ToastDisplayMethod::Center);
|
||||||
|
|
||||||
config.notification_topics.iter().for_each(|(k, v)| {
|
config.notification_topics.iter().for_each(|(k, v)| {
|
||||||
toast_topics.insert(*k, *v);
|
toast_topics.insert(*k, *v);
|
||||||
@@ -190,11 +192,3 @@ pub struct ScreenMeta {
|
|||||||
pub name: Arc<str>,
|
pub name: Arc<str>,
|
||||||
pub native_handle: u32,
|
pub native_handle: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone, Copy, Default)]
|
|
||||||
#[repr(u8)]
|
|
||||||
pub enum LeftRight {
|
|
||||||
#[default]
|
|
||||||
Left,
|
|
||||||
Right,
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -17,11 +17,9 @@ use std::{
|
|||||||
},
|
},
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
use wlx_common::overlays::ToastTopic;
|
||||||
|
|
||||||
use crate::{
|
use crate::{overlays::toast::Toast, state::AppState};
|
||||||
overlays::toast::{Toast, ToastTopic},
|
|
||||||
state::AppState,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct NotificationManager {
|
pub struct NotificationManager {
|
||||||
rx_toast: mpsc::Receiver<Toast>,
|
rx_toast: mpsc::Receiver<Toast>,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ use std::collections::HashMap;
|
|||||||
|
|
||||||
use glam::{Affine3A, Vec3, Vec3A};
|
use glam::{Affine3A, Vec3, Vec3A};
|
||||||
use slotmap::{HopSlotMap, Key, SecondaryMap};
|
use slotmap::{HopSlotMap, Key, SecondaryMap};
|
||||||
|
use wlx_common::config::SerializedWindowSet;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
overlays::{
|
overlays::{
|
||||||
@@ -10,11 +11,8 @@ use crate::{
|
|||||||
},
|
},
|
||||||
state::AppState,
|
state::AppState,
|
||||||
windowing::{
|
windowing::{
|
||||||
backend::OverlayEventData,
|
OverlayID, OverlaySelector, backend::OverlayEventData, set::OverlayWindowSet, snap_upright,
|
||||||
set::{OverlayWindowSet, SerializedWindowSet},
|
|
||||||
snap_upright,
|
|
||||||
window::OverlayWindowData,
|
window::OverlayWindowData,
|
||||||
OverlayID, OverlaySelector,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,11 @@
|
|||||||
use std::{collections::HashMap, sync::Arc};
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use slotmap::SecondaryMap;
|
use slotmap::SecondaryMap;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use wlx_common::windowing::OverlayWindowState;
|
||||||
|
|
||||||
use crate::windowing::{window::OverlayWindowState, OverlayID};
|
use crate::windowing::OverlayID;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct OverlayWindowSet {
|
pub struct OverlayWindowSet {
|
||||||
pub(super) name: Arc<str>,
|
pub(super) name: Arc<str>,
|
||||||
pub(super) overlays: SecondaryMap<OverlayID, OverlayWindowState>,
|
pub(super) overlays: SecondaryMap<OverlayID, OverlayWindowState>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Serialize, Deserialize)]
|
|
||||||
pub struct SerializedWindowSet {
|
|
||||||
pub name: Arc<str>,
|
|
||||||
pub overlays: HashMap<Arc<str>, OverlayWindowState>,
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
use glam::{Affine3A, Mat3A, Quat, Vec3, Vec3A};
|
use glam::{Affine3A, Mat3A, Quat, Vec3, Vec3A};
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use std::{f32::consts::PI, sync::Arc};
|
use std::{f32::consts::PI, sync::Arc};
|
||||||
|
use wlx_common::windowing::{OverlayWindowState, Positioning};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
state::{AppState, LeftRight},
|
state::AppState,
|
||||||
subsystem::input::KeyboardFocus,
|
subsystem::input::KeyboardFocus,
|
||||||
windowing::{
|
windowing::{
|
||||||
backend::{FrameMeta, OverlayBackend, RenderResources, ShouldRender},
|
backend::{FrameMeta, OverlayBackend, RenderResources, ShouldRender},
|
||||||
@@ -11,33 +11,6 @@ use crate::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize)]
|
|
||||||
pub enum Positioning {
|
|
||||||
/// Stays in place, recenters relative to HMD
|
|
||||||
#[default]
|
|
||||||
Floating,
|
|
||||||
/// Stays in place, recenters relative to anchor. Follows anchor during anchor grab.
|
|
||||||
Anchored,
|
|
||||||
/// Same as anchor but paused due to interaction
|
|
||||||
AnchoredPaused,
|
|
||||||
/// Stays in place, no recentering
|
|
||||||
Static,
|
|
||||||
/// Following HMD
|
|
||||||
FollowHead { lerp: f32 },
|
|
||||||
/// Normally follows HMD, but paused due to interaction
|
|
||||||
FollowHeadPaused { lerp: f32 },
|
|
||||||
/// Following hand
|
|
||||||
FollowHand { hand: LeftRight, lerp: f32 },
|
|
||||||
/// Normally follows hand, but paused due to interaction
|
|
||||||
FollowHandPaused { hand: LeftRight, lerp: f32 },
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Positioning {
|
|
||||||
pub const fn moves_with_space(self) -> bool {
|
|
||||||
matches!(self, Self::Floating | Self::Anchored | Self::Static)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct OverlayWindowData<T> {
|
pub struct OverlayWindowData<T> {
|
||||||
pub config: OverlayWindowConfig,
|
pub config: OverlayWindowConfig,
|
||||||
pub data: T,
|
pub data: T,
|
||||||
@@ -261,53 +234,20 @@ pub fn realign(transform: &mut Affine3A, hmd: &Affine3A) {
|
|||||||
transform.matrix3 = Mat3A::from_cols(col_x, col_y, col_z).mul_scalar(scale) * rot;
|
transform.matrix3 = Mat3A::from_cols(col_x, col_y, col_z).mul_scalar(scale) * rot;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Contains the window state for a given set
|
pub fn save_transform(state: &mut OverlayWindowState, app: &mut AppState) -> bool {
|
||||||
#[derive(Clone, Serialize, Deserialize)]
|
let parent_transform = match state.positioning {
|
||||||
#[serde(default)]
|
Positioning::Floating => snap_upright(app.input_state.hmd, Vec3A::Y),
|
||||||
pub struct OverlayWindowState {
|
Positioning::FollowHead { .. } | Positioning::FollowHeadPaused { .. } => {
|
||||||
pub transform: Affine3A,
|
app.input_state.hmd
|
||||||
pub alpha: f32,
|
|
||||||
pub grabbable: bool,
|
|
||||||
pub interactable: bool,
|
|
||||||
pub positioning: Positioning,
|
|
||||||
pub curvature: Option<f32>,
|
|
||||||
pub additive: bool,
|
|
||||||
pub saved_transform: Option<Affine3A>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for OverlayWindowState {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
grabbable: false,
|
|
||||||
interactable: false,
|
|
||||||
alpha: 1.0,
|
|
||||||
positioning: Positioning::Floating,
|
|
||||||
curvature: None,
|
|
||||||
transform: Affine3A::IDENTITY,
|
|
||||||
additive: false,
|
|
||||||
saved_transform: None,
|
|
||||||
}
|
}
|
||||||
}
|
Positioning::FollowHand { hand, .. } | Positioning::FollowHandPaused { hand, .. } => {
|
||||||
}
|
app.input_state.pointers[hand as usize].pose
|
||||||
|
}
|
||||||
impl OverlayWindowState {
|
Positioning::Anchored | Positioning::AnchoredPaused => snap_upright(app.anchor, Vec3A::Y),
|
||||||
pub fn save_transform(&mut self, app: &mut AppState) -> bool {
|
Positioning::Static => return false,
|
||||||
let parent_transform = match self.positioning {
|
};
|
||||||
Positioning::Floating => snap_upright(app.input_state.hmd, Vec3A::Y),
|
|
||||||
Positioning::FollowHead { .. } | Positioning::FollowHeadPaused { .. } => {
|
state.saved_transform = Some(parent_transform.inverse() * state.transform);
|
||||||
app.input_state.hmd
|
|
||||||
}
|
true
|
||||||
Positioning::FollowHand { hand, .. } | Positioning::FollowHandPaused { hand, .. } => {
|
|
||||||
app.input_state.pointers[hand as usize].pose
|
|
||||||
}
|
|
||||||
Positioning::Anchored | Positioning::AnchoredPaused => {
|
|
||||||
snap_upright(app.anchor, Vec3A::Y)
|
|
||||||
}
|
|
||||||
Positioning::Static => return false,
|
|
||||||
};
|
|
||||||
|
|
||||||
self.saved_transform = Some(parent_transform.inverse() * self.transform);
|
|
||||||
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user