config_io: Support wayvr.conf.d directory, refactoring (#139)

This commit is contained in:
Aleksander
2025-01-20 15:26:17 +01:00
committed by GitHub
parent b209f79188
commit 3c792608e7
10 changed files with 86 additions and 54 deletions

View File

@@ -13,7 +13,7 @@ use ovr_overlay::{
use crate::{ use crate::{
backend::input::{Haptics, TrackedDevice, TrackedDeviceRole}, backend::input::{Haptics, TrackedDevice, TrackedDeviceRole},
config_io::CONFIG_ROOT_PATH, config_io,
state::AppState, state::AppState,
}; };
@@ -325,7 +325,7 @@ fn get_tracked_device(
} }
pub fn set_action_manifest(input: &mut InputManager) -> anyhow::Result<()> { pub fn set_action_manifest(input: &mut InputManager) -> anyhow::Result<()> {
let action_path = CONFIG_ROOT_PATH.join("actions.json"); let action_path = config_io::get_config_root().join("actions.json");
if let Err(e) = File::create(&action_path) if let Err(e) = File::create(&action_path)
.and_then(|mut f| f.write_all(include_bytes!("../../res/actions.json"))) .and_then(|mut f| f.write_all(include_bytes!("../../res/actions.json")))
@@ -333,19 +333,19 @@ pub fn set_action_manifest(input: &mut InputManager) -> anyhow::Result<()> {
log::warn!("Could not write action manifest: {}", e); log::warn!("Could not write action manifest: {}", e);
} }
let binding_path = CONFIG_ROOT_PATH.join("actions_binding_knuckles.json"); let binding_path = config_io::get_config_root().join("actions_binding_knuckles.json");
if !binding_path.is_file() { if !binding_path.is_file() {
File::create(&binding_path)? File::create(&binding_path)?
.write_all(include_bytes!("../../res/actions_binding_knuckles.json"))?; .write_all(include_bytes!("../../res/actions_binding_knuckles.json"))?;
} }
let binding_path = CONFIG_ROOT_PATH.join("actions_binding_vive.json"); let binding_path = config_io::get_config_root().join("actions_binding_vive.json");
if !binding_path.is_file() { if !binding_path.is_file() {
File::create(&binding_path)? File::create(&binding_path)?
.write_all(include_bytes!("../../res/actions_binding_vive.json"))?; .write_all(include_bytes!("../../res/actions_binding_vive.json"))?;
} }
let binding_path = CONFIG_ROOT_PATH.join("actions_binding_oculus.json"); let binding_path = config_io::get_config_root().join("actions_binding_oculus.json");
if !binding_path.is_file() { if !binding_path.is_file() {
File::create(&binding_path)? File::create(&binding_path)?
.write_all(include_bytes!("../../res/actions_binding_oculus.json"))?; .write_all(include_bytes!("../../res/actions_binding_oculus.json"))?;

View File

@@ -4,12 +4,12 @@ use anyhow::bail;
use json::{array, object}; use json::{array, object};
use ovr_overlay::applications::ApplicationsManager; use ovr_overlay::applications::ApplicationsManager;
use crate::config_io::CONFIG_ROOT_PATH; use crate::config_io;
const APP_KEY: &str = "galister.wlxoverlay-s"; const APP_KEY: &str = "galister.wlxoverlay-s";
pub(super) fn install_manifest(app_mgr: &mut ApplicationsManager) -> anyhow::Result<()> { pub(super) fn install_manifest(app_mgr: &mut ApplicationsManager) -> anyhow::Result<()> {
let manifest_path = CONFIG_ROOT_PATH.join("wlx-overlay-s.vrmanifest"); let manifest_path = config_io::get_config_root().join("wlx-overlay-s.vrmanifest");
let appimage_path = std::env::var("APPIMAGE"); let appimage_path = std::env::var("APPIMAGE");
let executable_pathbuf = std::env::current_exe()?; let executable_pathbuf = std::env::current_exe()?;
@@ -76,7 +76,7 @@ pub(super) fn install_manifest(app_mgr: &mut ApplicationsManager) -> anyhow::Res
} }
pub(super) fn uninstall_manifest(app_mgr: &mut ApplicationsManager) -> anyhow::Result<()> { pub(super) fn uninstall_manifest(app_mgr: &mut ApplicationsManager) -> anyhow::Result<()> {
let manifest_path = CONFIG_ROOT_PATH.join("wlx-overlay-s.vrmanifest"); let manifest_path = config_io::get_config_root().join("wlx-overlay-s.vrmanifest");
if let Ok(true) = app_mgr.is_application_installed(APP_KEY) { if let Ok(true) = app_mgr.is_application_installed(APP_KEY) {
if let Err(e) = app_mgr.remove_application_manifest(&manifest_path) { if let Err(e) = app_mgr.remove_application_manifest(&manifest_path) {

View File

@@ -7,7 +7,7 @@ use vulkano::{command_buffer::CommandBufferUsage, image::view::ImageView};
use crate::{ use crate::{
backend::openxr::{helpers::translation_rotation_to_posef, swapchain::SwapchainOpts}, backend::openxr::{helpers::translation_rotation_to_posef, swapchain::SwapchainOpts},
config_io::CONFIG_ROOT_PATH, config_io,
graphics::{dds::WlxCommandBufferDds, format_is_srgb, WlxCommandBuffer}, graphics::{dds::WlxCommandBufferDds, format_is_srgb, WlxCommandBuffer},
state::AppState, state::AppState,
}; };
@@ -35,7 +35,7 @@ impl Skybox {
break 'custom_tex; break 'custom_tex;
} }
let real_path = CONFIG_ROOT_PATH.join(&*app.session.config.skybox_texture); let real_path = config_io::get_config_root().join(&*app.session.config.skybox_texture);
let Ok(f) = File::open(real_path) else { let Ok(f) = File::open(real_path) else {
log::warn!( log::warn!(
"Could not open custom skybox texture at: {}", "Could not open custom skybox texture at: {}",

View File

@@ -2,8 +2,6 @@ use std::path::PathBuf;
use std::sync::Arc; use std::sync::Arc;
use crate::config_io; use crate::config_io;
use crate::config_io::get_conf_d_path;
use crate::config_io::CONFIG_ROOT_PATH;
use crate::gui::modular::ModularUiConfig; use crate::gui::modular::ModularUiConfig;
use crate::overlays::toast::DisplayMethod; use crate::overlays::toast::DisplayMethod;
use crate::overlays::toast::ToastTopic; use crate::overlays::toast::ToastTopic;
@@ -390,14 +388,20 @@ pub fn load_custom_ui(name: &str) -> anyhow::Result<ModularUiConfig> {
Ok(serde_yaml::from_str(&yaml_data)?) Ok(serde_yaml::from_str(&yaml_data)?)
} }
pub fn load_general() -> GeneralConfig { pub fn load_config_with_conf_d<ConfigData>(
root_config_filename: &str,
ctype: config_io::ConfigRoot,
) -> ConfigData
where
ConfigData: for<'de> Deserialize<'de>,
{
let mut settings_builder = Config::builder(); let mut settings_builder = Config::builder();
// Add files from conf.d directory // Add files from conf.d directory
let path_conf_d = get_conf_d_path(); let path_conf_d = ctype.get_conf_d_path();
for mut base_conf in [CONFIG_ROOT_PATH.clone(), path_conf_d.clone()] { for mut base_conf in [config_io::get_config_root(), path_conf_d.clone()] {
base_conf.push("config.yaml"); base_conf.push(root_config_filename);
if base_conf.exists() { if base_conf.exists() {
log::info!("Loading config file: {}", base_conf.to_string_lossy()); log::info!("Loading config file: {}", base_conf.to_string_lossy());
settings_builder = settings_builder.add_source(File::from(base_conf)); settings_builder = settings_builder.add_source(File::from(base_conf));
@@ -423,7 +427,7 @@ pub fn load_general() -> GeneralConfig {
} }
match settings_builder.build() { match settings_builder.build() {
Ok(settings) => match settings.try_deserialize::<GeneralConfig>() { Ok(settings) => match settings.try_deserialize::<ConfigData>() {
Ok(config) => config, Ok(config) => config,
Err(e) => { Err(e) => {
panic!("Failed to deserialize settings: {}", e); panic!("Failed to deserialize settings: {}", e);
@@ -435,6 +439,10 @@ pub fn load_general() -> GeneralConfig {
} }
} }
pub fn load_general() -> GeneralConfig {
load_config_with_conf_d::<GeneralConfig>("config.yaml", config_io::ConfigRoot::Generic)
}
// Config that is saved from the settings panel // Config that is saved from the settings panel
#[derive(Serialize)] #[derive(Serialize)]
@@ -452,10 +460,11 @@ pub struct AutoSettings {
} }
fn get_settings_path() -> PathBuf { fn get_settings_path() -> PathBuf {
let mut path = config_io::get_conf_d_path(); config_io::ConfigRoot::Generic
path.push("zz-saved-config.json5"); .get_conf_d_path()
path .join("zz-saved-config.json5")
} }
pub fn save_settings(config: &GeneralConfig) -> anyhow::Result<()> { pub fn save_settings(config: &GeneralConfig) -> anyhow::Result<()> {
let conf = AutoSettings { let conf = AutoSettings {
watch_pos: config.watch_pos, watch_pos: config.watch_pos,
@@ -486,9 +495,9 @@ pub struct AutoState {
} }
fn get_state_path() -> PathBuf { fn get_state_path() -> PathBuf {
let mut path = config_io::get_conf_d_path(); config_io::ConfigRoot::Generic
path.push("zz-saved-state.json5"); .get_conf_d_path()
path .join("zz-saved-state.json5")
} }
pub fn save_layout(config: &GeneralConfig) -> anyhow::Result<()> { pub fn save_layout(config: &GeneralConfig) -> anyhow::Result<()> {

View File

@@ -1,13 +1,16 @@
use log::error; use log::error;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use std::{ use std::path::PathBuf;
fs::{self, create_dir},
path::PathBuf, pub enum ConfigRoot {
}; Generic,
#[allow(dead_code)]
WayVR,
}
const FALLBACK_CONFIG_PATH: &str = "/tmp/wlxoverlay"; const FALLBACK_CONFIG_PATH: &str = "/tmp/wlxoverlay";
pub static CONFIG_ROOT_PATH: Lazy<PathBuf> = Lazy::new(|| { static CONFIG_ROOT_PATH: Lazy<PathBuf> = Lazy::new(|| {
if let Ok(xdg_dirs) = xdg::BaseDirectories::new() { if let Ok(xdg_dirs) = xdg::BaseDirectories::new() {
let mut dir = xdg_dirs.get_config_home(); let mut dir = xdg_dirs.get_config_home();
dir.push("wlxoverlay"); dir.push("wlxoverlay");
@@ -21,33 +24,38 @@ pub static CONFIG_ROOT_PATH: Lazy<PathBuf> = Lazy::new(|| {
PathBuf::from(FALLBACK_CONFIG_PATH) PathBuf::from(FALLBACK_CONFIG_PATH)
}); });
pub fn get_conf_d_path() -> PathBuf { pub fn get_config_root() -> PathBuf {
let mut config_root = CONFIG_ROOT_PATH.clone(); CONFIG_ROOT_PATH.clone()
config_root.push("conf.d"); }
config_root
impl ConfigRoot {
pub fn get_conf_d_path(&self) -> PathBuf {
get_config_root().join(match self {
ConfigRoot::Generic => "conf.d",
ConfigRoot::WayVR => "wayvr.conf.d",
})
} }
// Make sure config directory is present and return root config path // Make sure config directory is present and return root config path
pub fn ensure_config_root() -> PathBuf { pub fn ensure_dir(&self) -> PathBuf {
let path = CONFIG_ROOT_PATH.clone(); let path = get_config_root();
let _ = create_dir(&path); let _ = std::fs::create_dir(&path);
let path_conf_d = get_conf_d_path(); let path_conf_d = self.get_conf_d_path();
let _ = create_dir(path_conf_d); let _ = std::fs::create_dir(path_conf_d);
path path
} }
}
fn get_config_file_path(filename: &str) -> PathBuf { pub fn get_config_file_path(filename: &str) -> PathBuf {
let mut config_root = CONFIG_ROOT_PATH.clone(); get_config_root().join(filename)
config_root.push(filename);
config_root
} }
pub fn load(filename: &str) -> Option<String> { pub fn load(filename: &str) -> Option<String> {
let path = get_config_file_path(filename); let path = get_config_file_path(filename);
log::info!("Loading config {}", path.to_string_lossy()); log::info!("Loading config: {}", path.to_string_lossy());
if let Ok(data) = fs::read_to_string(path) { if let Ok(data) = std::fs::read_to_string(path) {
Some(data) Some(data)
} else { } else {
None None

View File

@@ -16,7 +16,8 @@ use crate::{
task::{TaskContainer, TaskType}, task::{TaskContainer, TaskType},
wayvr, wayvr,
}, },
config::{load_known_yaml, ConfigType}, config::load_config_with_conf_d,
config_io,
gui::modular::button::WayVRAction, gui::modular::button::WayVRAction,
overlays::wayvr::WayVRData, overlays::wayvr::WayVRData,
}; };
@@ -120,7 +121,7 @@ pub struct WayVRConfig {
pub run_compositor_at_start: bool, pub run_compositor_at_start: bool,
pub catalogs: HashMap<String, WayVRCatalog>, pub catalogs: HashMap<String, WayVRCatalog>,
pub displays: BTreeMap<String, WayVRDisplay>, // sorted alphabetically pub displays: BTreeMap<String, WayVRDisplay>, // sorted alphabetically
pub dashboard: WayVRDashboard, pub dashboard: Option<WayVRDashboard>,
#[serde(default = "def_true")] #[serde(default = "def_true")]
pub auto_hide: bool, pub auto_hide: bool,
@@ -212,7 +213,15 @@ impl WayVRConfig {
} }
pub fn load_wayvr() -> WayVRConfig { pub fn load_wayvr() -> WayVRConfig {
let config = load_known_yaml::<WayVRConfig>(ConfigType::WayVR); let config_root_path = config_io::ConfigRoot::WayVR.ensure_dir();
log::info!("WayVR Config root path: {:?}", config_root_path);
log::info!(
"WayVR conf.d path: {:?}",
config_io::ConfigRoot::WayVR.get_conf_d_path()
);
let config = load_config_with_conf_d::<WayVRConfig>("wayvr.yaml", config_io::ConfigRoot::WayVR);
if config.version != 1 { if config.version != 1 {
panic!("WayVR config version {} is not supported", config.version); panic!("WayVR config version {} is not supported", config.version);
} }

View File

@@ -11,7 +11,7 @@ use serde::Deserialize;
use vulkano::{command_buffer::CommandBufferUsage, image::view::ImageView}; use vulkano::{command_buffer::CommandBufferUsage, image::view::ImageView};
use crate::{ use crate::{
backend::common::OverlaySelector, config::AStrMapExt, config_io::CONFIG_ROOT_PATH, backend::common::OverlaySelector, config::AStrMapExt, config_io,
graphics::dds::WlxCommandBufferDds, state::AppState, graphics::dds::WlxCommandBufferDds, state::AppState,
}; };
@@ -545,7 +545,7 @@ fn sprite_from_path(path: Arc<str>, app: &mut AppState) -> anyhow::Result<Arc<Im
return Ok(view.clone()); return Ok(view.clone());
} }
let real_path = CONFIG_ROOT_PATH.join(&*path); let real_path = config_io::get_config_root().join(&*path);
let Ok(f) = File::open(real_path) else { let Ok(f) = File::open(real_path) else {
anyhow::bail!("Could not open custom sprite at: {}", path); anyhow::bail!("Could not open custom sprite at: {}", path);

View File

@@ -751,7 +751,7 @@ pub struct TokenConf {
#[cfg(feature = "pipewire")] #[cfg(feature = "pipewire")]
fn get_pw_token_path() -> PathBuf { fn get_pw_token_path() -> PathBuf {
let mut path = config_io::get_conf_d_path(); let mut path = config_io::ConfigRoot::Generic.get_conf_d_path();
path.push("pw_tokens.yaml"); path.push("pw_tokens.yaml");
path path
} }

View File

@@ -244,6 +244,10 @@ where
{ {
let conf_dash = &app.session.wayvr_config.dashboard; let conf_dash = &app.session.wayvr_config.dashboard;
let Some(conf_dash) = &conf_dash else {
anyhow::bail!("Dashboard is not configured");
};
if !wayvr.dashboard_executed && !executable_exists_in_path(&conf_dash.exec) { if !wayvr.dashboard_executed && !executable_exists_in_path(&conf_dash.exec) {
anyhow::bail!("Executable \"{}\" not found", &conf_dash.exec); anyhow::bail!("Executable \"{}\" not found", &conf_dash.exec);
} }
@@ -280,7 +284,9 @@ where
overlay.state.z_order = Z_ORDER_DASHBOARD; overlay.state.z_order = Z_ORDER_DASHBOARD;
overlay.state.reset(app, true); overlay.state.reset(app, true);
let conf_dash = &app.session.wayvr_config.dashboard; let Some(conf_dash) = &app.session.wayvr_config.dashboard else {
unreachable!(); /* safe, not possible to trigger */
};
// FIXME: overlay curvature needs to be dispatched for some unknown reason, this value is not set otherwise // FIXME: overlay curvature needs to be dispatched for some unknown reason, this value is not set otherwise
app.tasks.enqueue(TaskType::Overlay( app.tasks.enqueue(TaskType::Overlay(

View File

@@ -146,8 +146,8 @@ pub struct AppSession {
impl AppSession { impl AppSession {
pub fn load() -> Self { pub fn load() -> Self {
let config_root_path = config_io::ensure_config_root(); let config_root_path = config_io::ConfigRoot::Generic.ensure_dir();
log::info!("Config root path: {}", config_root_path.to_string_lossy()); log::info!("Config root path: {:?}", config_root_path);
let config = GeneralConfig::load_from_disk(); let config = GeneralConfig::load_from_disk();
let mut toast_topics = IdMap::new(); let mut toast_topics = IdMap::new();