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",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wlx-common"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"glam",
|
||||
"idmap",
|
||||
"idmap-derive",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wlx-overlay-s"
|
||||
version = "25.4.2"
|
||||
@@ -6902,6 +6913,7 @@ dependencies = [
|
||||
"wgui",
|
||||
"winit",
|
||||
"wlx-capture",
|
||||
"wlx-common",
|
||||
"xcb",
|
||||
"xdg 3.0.0",
|
||||
"xkbcommon 0.9.0",
|
||||
|
||||
10
Cargo.toml
10
Cargo.toml
@@ -10,13 +10,21 @@ inherits = "release"
|
||||
debug = true
|
||||
|
||||
[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"
|
||||
|
||||
[workspace.dependencies]
|
||||
anyhow = "1.0.100"
|
||||
glam = "0.30.7"
|
||||
idmap = "0.2.2"
|
||||
idmap-derive = "0.2.2"
|
||||
log = "0.4.28"
|
||||
regex = "1.11.3"
|
||||
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"
|
||||
glam = { workspace = true, features = ["mint", "serde"] }
|
||||
idmap = { workspace = true, features = ["serde"] }
|
||||
idmap-derive = "0.2.2"
|
||||
idmap-derive = { workspace = true }
|
||||
input-linux = "0.7.1"
|
||||
json = { version = "0.12.4", optional = true }
|
||||
json5 = "0.4.1"
|
||||
@@ -61,6 +61,7 @@ strum = { version = "0.27.2", features = ["derive"] }
|
||||
sysinfo = { version = "0.37" }
|
||||
thiserror = "2.0"
|
||||
wlx-capture = { path = "../wlx-capture" }
|
||||
wlx-common = { path = "../wlx-common" }
|
||||
libmonado = { version = "1.3.2", optional = true }
|
||||
winit = { version = "0.30.12", optional = true }
|
||||
xdg = "3.0"
|
||||
|
||||
@@ -4,14 +4,15 @@ use std::{collections::VecDeque, time::Instant};
|
||||
|
||||
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::state::{AppSession, AppState};
|
||||
use crate::subsystem::hid::WheelDelta;
|
||||
use crate::subsystem::input::KeyboardFocus;
|
||||
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 super::task::TaskType;
|
||||
@@ -705,7 +706,7 @@ where
|
||||
x => x,
|
||||
};
|
||||
|
||||
overlay_state.save_transform(app);
|
||||
window::save_transform(overlay_state, app);
|
||||
}
|
||||
|
||||
// Hide anchor
|
||||
|
||||
@@ -2,37 +2,38 @@ use std::{
|
||||
collections::VecDeque,
|
||||
ops::Add,
|
||||
sync::{
|
||||
atomic::{AtomicBool, AtomicUsize, Ordering},
|
||||
Arc,
|
||||
atomic::{AtomicBool, AtomicUsize, Ordering},
|
||||
},
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
use anyhow::{Result, anyhow};
|
||||
use ovr_overlay::{
|
||||
sys::{ETrackedDeviceProperty, EVRApplicationType, EVREventType},
|
||||
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::{
|
||||
backend::{
|
||||
BackendError,
|
||||
input::interact,
|
||||
openvr::{
|
||||
helpers::adjust_gain,
|
||||
input::{set_action_manifest, OpenVrInputSource},
|
||||
input::{OpenVrInputSource, set_action_manifest},
|
||||
lines::LinePool,
|
||||
manifest::{install_manifest, uninstall_manifest},
|
||||
overlay::OpenVrOverlayData,
|
||||
},
|
||||
task::{SystemTask, TaskType},
|
||||
BackendError,
|
||||
},
|
||||
config::save_state,
|
||||
graphics::{init_openvr_graphics, GpuFutures},
|
||||
graphics::{GpuFutures, init_openvr_graphics},
|
||||
overlays::{
|
||||
toast::{Toast, ToastTopic},
|
||||
watch::{watch_fade, WATCH_NAME},
|
||||
toast::Toast,
|
||||
watch::{WATCH_NAME, watch_fade},
|
||||
},
|
||||
state::AppState,
|
||||
subsystem::notifications::NotificationManager,
|
||||
|
||||
@@ -2,8 +2,8 @@ use std::{
|
||||
collections::VecDeque,
|
||||
ops::Add,
|
||||
sync::{
|
||||
atomic::{AtomicBool, AtomicUsize, Ordering},
|
||||
Arc,
|
||||
atomic::{AtomicBool, AtomicUsize, Ordering},
|
||||
},
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
@@ -14,19 +14,20 @@ use libmonado::Monado;
|
||||
use openxr as xr;
|
||||
use skybox::create_skybox;
|
||||
use vulkano::{Handle, VulkanObject};
|
||||
use wlx_common::overlays::ToastTopic;
|
||||
|
||||
use crate::{
|
||||
backend::{
|
||||
BackendError,
|
||||
input::interact,
|
||||
openxr::{lines::LinePool, overlay::OpenXrOverlayData},
|
||||
task::{SystemTask, TaskType},
|
||||
BackendError,
|
||||
},
|
||||
config::save_state,
|
||||
graphics::{init_openxr_graphics, GpuFutures},
|
||||
graphics::{GpuFutures, init_openxr_graphics},
|
||||
overlays::{
|
||||
toast::{Toast, ToastTopic},
|
||||
watch::{watch_fade, WATCH_NAME},
|
||||
toast::Toast,
|
||||
watch::{WATCH_NAME, watch_fade},
|
||||
},
|
||||
state::AppState,
|
||||
subsystem::notifications::NotificationManager,
|
||||
|
||||
@@ -1,360 +1,13 @@
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
||||
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 glam::{Affine3A, Quat, Vec3, vec3};
|
||||
use idmap::IdMap;
|
||||
use glam::{Quat, Vec3};
|
||||
use log::error;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
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
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
use std::path::PathBuf;
|
||||
use wlx_common::{
|
||||
common::LeftRight,
|
||||
config::{GeneralConfig, SerializedWindowSet},
|
||||
};
|
||||
|
||||
const FALLBACKS: [&str; 2] = [
|
||||
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)
|
||||
}
|
||||
|
||||
// Config that is saved from the settings panel
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct AutoSettings {
|
||||
pub watch_pos: Vec3,
|
||||
|
||||
@@ -9,6 +9,7 @@ use std::{
|
||||
};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use wlx_common::{common::LeftRight, config::GeneralConfig, windowing::Positioning};
|
||||
|
||||
use crate::{
|
||||
backend::{
|
||||
@@ -17,9 +18,7 @@ use crate::{
|
||||
},
|
||||
config::load_config_with_conf_d,
|
||||
config_io,
|
||||
overlays::wayvr::{executable_exists_in_path, WayVRData},
|
||||
state::LeftRight,
|
||||
windowing::window::Positioning,
|
||||
overlays::wayvr::{WayVRData, executable_exists_in_path},
|
||||
};
|
||||
|
||||
// Flat version of RelativeTo
|
||||
@@ -180,7 +179,7 @@ impl WayVRConfig {
|
||||
}
|
||||
|
||||
pub fn get_wayvr_config(
|
||||
config_general: &crate::config::GeneralConfig,
|
||||
config_general: &GeneralConfig,
|
||||
config_wayvr: &Self,
|
||||
) -> anyhow::Result<wayvr::Config> {
|
||||
Ok(wayvr::Config {
|
||||
@@ -199,7 +198,7 @@ impl WayVRConfig {
|
||||
|
||||
pub fn post_load(
|
||||
&self,
|
||||
config: &crate::config::GeneralConfig,
|
||||
config: &GeneralConfig,
|
||||
tasks: &mut TaskContainer,
|
||||
) -> anyhow::Result<Option<Rc<RefCell<WayVRData>>>> {
|
||||
let primary_count = self
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
use glam::{Affine3A, Quat, Vec3};
|
||||
use std::sync::{Arc, LazyLock};
|
||||
use wlx_common::windowing::{OverlayWindowState, Positioning};
|
||||
|
||||
use crate::gui::panel::GuiPanel;
|
||||
use crate::state::AppState;
|
||||
use crate::windowing::window::{OverlayWindowConfig, OverlayWindowState, Positioning};
|
||||
use crate::windowing::Z_ORDER_ANCHOR;
|
||||
use crate::windowing::window::OverlayWindowConfig;
|
||||
|
||||
pub static ANCHOR_NAME: LazyLock<Arc<str>> = LazyLock::new(|| Arc::from("anchor"));
|
||||
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use glam::{Affine3A, Quat, Vec3, vec3};
|
||||
use wlx_common::windowing::OverlayWindowState;
|
||||
|
||||
use crate::{
|
||||
gui::panel::GuiPanel,
|
||||
state::AppState,
|
||||
windowing::window::{OverlayWindowConfig, OverlayWindowState},
|
||||
};
|
||||
use crate::{gui::panel::GuiPanel, state::AppState, windowing::window::OverlayWindowConfig};
|
||||
|
||||
const SETTINGS_NAME: &str = "settings";
|
||||
|
||||
|
||||
@@ -5,11 +5,9 @@ use wgui::{
|
||||
parser::Fetchable, renderer_vk::text::custom_glyph::CustomGlyphData,
|
||||
widget::sprite::WidgetSprite,
|
||||
};
|
||||
use wlx_common::{common::LeftRight, windowing::Positioning};
|
||||
|
||||
use crate::{
|
||||
backend::task::OverlayTask, overlays::edit::EditModeWrapPanel, state::LeftRight,
|
||||
windowing::window::Positioning,
|
||||
};
|
||||
use crate::{backend::task::OverlayTask, overlays::edit::EditModeWrapPanel, windowing::window};
|
||||
|
||||
static POS_NAMES: [&str; 6] = ["static", "anchored", "floating", "hmd", "hand_l", "hand_r"];
|
||||
|
||||
@@ -98,7 +96,7 @@ impl PositioningHandler {
|
||||
Box::new(move |app, owc| {
|
||||
let state = owc.active_state.as_mut().unwrap(); //want panic
|
||||
state.positioning = pos;
|
||||
state.save_transform(app);
|
||||
window::save_transform(state, app);
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -17,12 +17,13 @@ use wgui::{
|
||||
util::WLength,
|
||||
},
|
||||
};
|
||||
use wlx_common::windowing::{OverlayWindowState, Positioning};
|
||||
|
||||
use crate::{
|
||||
gui::panel::GuiPanel,
|
||||
state::AppState,
|
||||
subsystem::hid::{ALT, CTRL, META, SHIFT, SUPER, XkbKeymap},
|
||||
windowing::window::{OverlayWindowConfig, OverlayWindowState, Positioning},
|
||||
windowing::window::OverlayWindowConfig,
|
||||
};
|
||||
|
||||
use super::{
|
||||
|
||||
@@ -5,7 +5,8 @@ use std::{
|
||||
|
||||
use futures::{Future, FutureExt};
|
||||
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::{
|
||||
backend::{
|
||||
@@ -15,12 +16,12 @@ use crate::{
|
||||
state::{AppSession, AppState},
|
||||
subsystem::hid::WheelDelta,
|
||||
windowing::{
|
||||
backend::{
|
||||
ui_transform, FrameMeta, OverlayBackend, OverlayEventData, RenderResources,
|
||||
ShouldRender,
|
||||
},
|
||||
window::{OverlayWindowConfig, OverlayWindowState},
|
||||
OverlaySelector,
|
||||
backend::{
|
||||
FrameMeta, OverlayBackend, OverlayEventData, RenderResources, ShouldRender,
|
||||
ui_transform,
|
||||
},
|
||||
window::OverlayWindowConfig,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -7,25 +7,26 @@ use vulkano::{
|
||||
command_buffer::CommandBufferUsage,
|
||||
device::Queue,
|
||||
format::Format,
|
||||
image::{sampler::Filter, view::ImageView, Image},
|
||||
image::{Image, sampler::Filter, view::ImageView},
|
||||
pipeline::graphics::color_blend::AttachmentBlend,
|
||||
};
|
||||
use wgui::gfx::{
|
||||
WGfx,
|
||||
cmd::WGfxClearMode,
|
||||
pass::WGfxPass,
|
||||
pipeline::{WGfxPipeline, WPipelineCreateInfo},
|
||||
WGfx,
|
||||
};
|
||||
use wlx_capture::{
|
||||
frame::{self as wlx_frame, DrmFormat, FrameFormat, MouseMeta, Transform, WlxFrame},
|
||||
WlxCapture,
|
||||
frame::{self as wlx_frame, DrmFormat, FrameFormat, MouseMeta, Transform, WlxFrame},
|
||||
};
|
||||
use wlx_common::config::GeneralConfig;
|
||||
|
||||
use crate::{
|
||||
config::GeneralConfig,
|
||||
graphics::{
|
||||
dmabuf::{fourcc_to_vk, WGfxDmabuf},
|
||||
upload_quad_vertices, Vert2Uv,
|
||||
Vert2Uv,
|
||||
dmabuf::{WGfxDmabuf, fourcc_to_vk},
|
||||
upload_quad_vertices,
|
||||
},
|
||||
state::AppState,
|
||||
windowing::backend::{FrameMeta, RenderResources},
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
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_common::windowing::{OverlayWindowState, Positioning};
|
||||
|
||||
use crate::{
|
||||
state::{AppSession, AppState, ScreenMeta},
|
||||
subsystem::{hid::XkbKeymap, input::KeyboardFocus},
|
||||
windowing::{
|
||||
backend::OverlayBackend,
|
||||
window::{OverlayWindowConfig, OverlayWindowState, Positioning},
|
||||
},
|
||||
windowing::{backend::OverlayBackend, window::OverlayWindowConfig},
|
||||
};
|
||||
|
||||
pub mod backend;
|
||||
|
||||
@@ -6,12 +6,9 @@ use wlx_capture::{
|
||||
pipewire::{PipewireCapture, PipewireSelectScreenResult},
|
||||
wayland::WlxOutput,
|
||||
};
|
||||
use wlx_common::config::{PwTokenMap, def_pw_tokens};
|
||||
|
||||
use crate::{
|
||||
config::{PwTokenMap, def_pw_tokens},
|
||||
config_io,
|
||||
state::AppState,
|
||||
};
|
||||
use crate::{config_io, state::AppState};
|
||||
|
||||
use super::{
|
||||
backend::ScreenBackend,
|
||||
|
||||
@@ -5,9 +5,9 @@ use wlx_capture::{
|
||||
wlr_dmabuf::WlrDmabufCapture,
|
||||
wlr_screencopy::WlrScreencopyCapture,
|
||||
};
|
||||
use wlx_common::{astr_containers::AStrMapExt, config::PwTokenMap};
|
||||
|
||||
use crate::{
|
||||
config::{AStrMapExt, PwTokenMap},
|
||||
overlays::screen::create_screen_from_backend,
|
||||
state::{AppState, ScreenMeta},
|
||||
};
|
||||
|
||||
@@ -35,9 +35,9 @@ impl ScreenBackend {
|
||||
pub fn create_screens_x11pw(app: &mut AppState) -> anyhow::Result<ScreenCreateData> {
|
||||
use glam::vec2;
|
||||
use wlx_capture::{pipewire::PipewireCapture, xshm::xshm_get_monitors};
|
||||
use wlx_common::{astr_containers::AStrMapExt, config::PwTokenMap};
|
||||
|
||||
use crate::{
|
||||
config::{AStrMapExt, PwTokenMap},
|
||||
overlays::screen::{
|
||||
create_screen_from_backend,
|
||||
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 idmap_derive::IntegerId;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use wgui::{
|
||||
i18n::Translation,
|
||||
parser::parse_color_hex,
|
||||
@@ -22,15 +20,17 @@ use wgui::{
|
||||
util::WLength,
|
||||
},
|
||||
};
|
||||
use wlx_common::{
|
||||
common::LeftRight,
|
||||
overlays::{ToastDisplayMethod, ToastTopic},
|
||||
windowing::{OverlayWindowState, Positioning},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
backend::task::TaskType,
|
||||
gui::panel::GuiPanel,
|
||||
state::{AppState, LeftRight},
|
||||
windowing::{
|
||||
OverlaySelector, Z_ORDER_TOAST,
|
||||
window::{OverlayWindowConfig, OverlayWindowState, Positioning},
|
||||
},
|
||||
state::AppState,
|
||||
windowing::{OverlaySelector, Z_ORDER_TOAST, window::OverlayWindowConfig},
|
||||
};
|
||||
|
||||
const FONT_SIZE: isize = 16;
|
||||
@@ -38,21 +38,6 @@ const PADDING: (f32, f32) = (25., 7.);
|
||||
const PIXELS_TO_METERS: f32 = 1. / 2000.;
|
||||
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 title: String,
|
||||
pub body: String,
|
||||
@@ -134,16 +119,16 @@ fn new_toast(toast: Toast, app: &mut AppState) -> Option<OverlayWindowConfig> {
|
||||
.toast_topics
|
||||
.get(toast.topic)
|
||||
.copied()
|
||||
.unwrap_or(DisplayMethod::Hide);
|
||||
.unwrap_or(ToastDisplayMethod::Hide);
|
||||
|
||||
let (spawn_point, spawn_rotation, positioning) = match current_method {
|
||||
DisplayMethod::Hide => return None,
|
||||
DisplayMethod::Center => (
|
||||
ToastDisplayMethod::Hide => return None,
|
||||
ToastDisplayMethod::Center => (
|
||||
vec3(0., -0.2, -0.5),
|
||||
Quat::IDENTITY,
|
||||
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_rot = app.session.config.watch_rot;
|
||||
let relative_to = match app.session.config.watch_hand {
|
||||
|
||||
@@ -6,6 +6,7 @@ use wgui::{
|
||||
event::{CallbackDataCommon, EventAlterables},
|
||||
parser::Fetchable,
|
||||
};
|
||||
use wlx_common::windowing::{OverlayWindowState, Positioning};
|
||||
|
||||
use crate::{
|
||||
gui::{
|
||||
@@ -14,9 +15,9 @@ use crate::{
|
||||
},
|
||||
state::AppState,
|
||||
windowing::{
|
||||
backend::OverlayEventData,
|
||||
window::{OverlayWindowConfig, OverlayWindowData, OverlayWindowState, Positioning},
|
||||
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 std::{cell::RefCell, collections::HashMap, rc::Rc, sync::Arc};
|
||||
use vulkano::{
|
||||
buffer::{BufferUsage, Subbuffer},
|
||||
command_buffer::CommandBufferUsage,
|
||||
format::Format,
|
||||
image::{view::ImageView, Image, ImageTiling, SubresourceLayout},
|
||||
image::{Image, ImageTiling, SubresourceLayout, view::ImageView},
|
||||
};
|
||||
use wayvr_ipc::packet_server::{self, PacketServer, WvrStateChanged};
|
||||
use wgui::gfx::{
|
||||
WGfx,
|
||||
pass::WGfxPass,
|
||||
pipeline::{WGfxPipeline, WPipelineCreateInfo},
|
||||
WGfx,
|
||||
};
|
||||
use wlx_capture::frame::{DmabufFrame, FourCC, FrameFormat, FramePlane};
|
||||
use wlx_common::windowing::OverlayWindowState;
|
||||
|
||||
use crate::{
|
||||
backend::{
|
||||
input::{self, HoverResult},
|
||||
task::TaskType,
|
||||
wayvr::{
|
||||
self, display,
|
||||
self, WayVR, WayVRAction, WayVRDisplayClickAction, display,
|
||||
server_ipc::{gen_args_vec, gen_env_vec},
|
||||
WayVR, WayVRAction, WayVRDisplayClickAction,
|
||||
},
|
||||
},
|
||||
config_wayvr,
|
||||
graphics::{dmabuf::WGfxDmabuf, Vert2Uv},
|
||||
graphics::{Vert2Uv, dmabuf::WGfxDmabuf},
|
||||
state::{self, AppState},
|
||||
subsystem::{hid::WheelDelta, input::KeyboardFocus},
|
||||
windowing::{
|
||||
OverlayID, OverlaySelector, Z_ORDER_DASHBOARD,
|
||||
backend::{
|
||||
ui_transform, FrameMeta, OverlayBackend, OverlayEventData, RenderResources,
|
||||
ShouldRender,
|
||||
FrameMeta, OverlayBackend, OverlayEventData, RenderResources, ShouldRender,
|
||||
ui_transform,
|
||||
},
|
||||
manager::OverlayWindowManager,
|
||||
window::{OverlayWindowConfig, OverlayWindowData, OverlayWindowState},
|
||||
OverlayID, OverlaySelector, Z_ORDER_DASHBOARD,
|
||||
window::{OverlayWindowConfig, OverlayWindowData},
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
use glam::Affine3A;
|
||||
use idmap::IdMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use smallvec::{SmallVec, smallvec};
|
||||
use std::sync::Arc;
|
||||
use wgui::{
|
||||
font_config::WguiFontConfig, gfx::WGfx, globals::WguiGlobals,
|
||||
renderer_vk::context::SharedContext as WSharedContext,
|
||||
};
|
||||
use wlx_common::{
|
||||
config::GeneralConfig,
|
||||
overlays::{ToastDisplayMethod, ToastTopic},
|
||||
};
|
||||
|
||||
#[cfg(feature = "wayvr")]
|
||||
use {
|
||||
@@ -20,11 +23,10 @@ use crate::subsystem::osc::OscSender;
|
||||
|
||||
use crate::{
|
||||
backend::{input::InputState, task::TaskContainer},
|
||||
config::GeneralConfig,
|
||||
config::load_general_config,
|
||||
config_io,
|
||||
graphics::WGfxExtras,
|
||||
gui,
|
||||
overlays::toast::{DisplayMethod, ToastTopic},
|
||||
subsystem::{audio::AudioOutput, input::HidWrapper},
|
||||
};
|
||||
|
||||
@@ -156,19 +158,19 @@ pub struct AppSession {
|
||||
#[cfg(feature = "wayvr")]
|
||||
pub wayvr_config: WayVRConfig,
|
||||
|
||||
pub toast_topics: IdMap<ToastTopic, DisplayMethod>,
|
||||
pub toast_topics: IdMap<ToastTopic, ToastDisplayMethod>,
|
||||
}
|
||||
|
||||
impl AppSession {
|
||||
pub fn load() -> Self {
|
||||
let config_root_path = config_io::ConfigRoot::Generic.ensure_dir();
|
||||
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();
|
||||
toast_topics.insert(ToastTopic::System, DisplayMethod::Center);
|
||||
toast_topics.insert(ToastTopic::DesktopNotification, DisplayMethod::Center);
|
||||
toast_topics.insert(ToastTopic::XSNotification, DisplayMethod::Center);
|
||||
toast_topics.insert(ToastTopic::System, ToastDisplayMethod::Center);
|
||||
toast_topics.insert(ToastTopic::DesktopNotification, ToastDisplayMethod::Center);
|
||||
toast_topics.insert(ToastTopic::XSNotification, ToastDisplayMethod::Center);
|
||||
|
||||
config.notification_topics.iter().for_each(|(k, v)| {
|
||||
toast_topics.insert(*k, *v);
|
||||
@@ -190,11 +192,3 @@ pub struct ScreenMeta {
|
||||
pub name: Arc<str>,
|
||||
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,
|
||||
};
|
||||
use wlx_common::overlays::ToastTopic;
|
||||
|
||||
use crate::{
|
||||
overlays::toast::{Toast, ToastTopic},
|
||||
state::AppState,
|
||||
};
|
||||
use crate::{overlays::toast::Toast, state::AppState};
|
||||
|
||||
pub struct NotificationManager {
|
||||
rx_toast: mpsc::Receiver<Toast>,
|
||||
|
||||
@@ -2,6 +2,7 @@ use std::collections::HashMap;
|
||||
|
||||
use glam::{Affine3A, Vec3, Vec3A};
|
||||
use slotmap::{HopSlotMap, Key, SecondaryMap};
|
||||
use wlx_common::config::SerializedWindowSet;
|
||||
|
||||
use crate::{
|
||||
overlays::{
|
||||
@@ -10,11 +11,8 @@ use crate::{
|
||||
},
|
||||
state::AppState,
|
||||
windowing::{
|
||||
backend::OverlayEventData,
|
||||
set::{OverlayWindowSet, SerializedWindowSet},
|
||||
snap_upright,
|
||||
OverlayID, OverlaySelector, backend::OverlayEventData, set::OverlayWindowSet, snap_upright,
|
||||
window::OverlayWindowData,
|
||||
OverlayID, OverlaySelector,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -1,18 +1,11 @@
|
||||
use std::{collections::HashMap, sync::Arc};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use slotmap::SecondaryMap;
|
||||
use std::sync::Arc;
|
||||
use wlx_common::windowing::OverlayWindowState;
|
||||
|
||||
use crate::windowing::{window::OverlayWindowState, OverlayID};
|
||||
use crate::windowing::OverlayID;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct OverlayWindowSet {
|
||||
pub(super) name: Arc<str>,
|
||||
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 serde::{Deserialize, Serialize};
|
||||
use std::{f32::consts::PI, sync::Arc};
|
||||
use wlx_common::windowing::{OverlayWindowState, Positioning};
|
||||
|
||||
use crate::{
|
||||
state::{AppState, LeftRight},
|
||||
state::AppState,
|
||||
subsystem::input::KeyboardFocus,
|
||||
windowing::{
|
||||
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 config: OverlayWindowConfig,
|
||||
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;
|
||||
}
|
||||
|
||||
// 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,
|
||||
pub fn save_transform(state: &mut OverlayWindowState, app: &mut AppState) -> bool {
|
||||
let parent_transform = match state.positioning {
|
||||
Positioning::Floating => snap_upright(app.input_state.hmd, Vec3A::Y),
|
||||
Positioning::FollowHead { .. } | Positioning::FollowHeadPaused { .. } => {
|
||||
app.input_state.hmd
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl OverlayWindowState {
|
||||
pub fn save_transform(&mut self, app: &mut AppState) -> bool {
|
||||
let parent_transform = match self.positioning {
|
||||
Positioning::Floating => snap_upright(app.input_state.hmd, Vec3A::Y),
|
||||
Positioning::FollowHead { .. } | Positioning::FollowHeadPaused { .. } => {
|
||||
app.input_state.hmd
|
||||
}
|
||||
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
|
||||
}
|
||||
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,
|
||||
};
|
||||
|
||||
state.saved_transform = Some(parent_transform.inverse() * state.transform);
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user