From e087eb37434d235c02ae5e08d74188acbd0812f1 Mon Sep 17 00:00:00 2001 From: Aleksander Date: Wed, 5 Nov 2025 22:37:07 +0100 Subject: [PATCH] settings gui PoC --- Cargo.lock | 14 +++--- dash-frontend/Cargo.toml | 2 + dash-frontend/assets/gui/dashboard.xml | 2 +- dash-frontend/assets/gui/t_group_box.xml | 24 ++++++++++ dash-frontend/assets/gui/tab/settings.xml | 54 +++++++++++++++++++++++ dash-frontend/assets/lang/de.json | 24 +++++++++- dash-frontend/assets/lang/en.json | 24 +++++++++- dash-frontend/assets/lang/es.json | 24 +++++++++- dash-frontend/assets/lang/ja.json | 24 +++++++++- dash-frontend/assets/lang/pl.json | 38 ++++++++++++---- dash-frontend/src/frontend.rs | 11 ++++- dash-frontend/src/lib.rs | 1 + dash-frontend/src/settings.rs | 41 +++++++++++++++++ scripts/translator/description.txt | 2 + uidev/src/testbed/testbed_dashboard.rs | 4 +- wgui/src/components/button.rs | 7 +-- wgui/src/components/checkbox.rs | 14 +++++- wgui/src/components/slider.rs | 4 +- 18 files changed, 285 insertions(+), 29 deletions(-) create mode 100644 dash-frontend/assets/gui/t_group_box.xml create mode 100644 dash-frontend/src/settings.rs diff --git a/Cargo.lock b/Cargo.lock index 5f07720..c7a1e2c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1429,6 +1429,8 @@ dependencies = [ "gtk", "log", "rust-embed", + "serde", + "serde_json", "wgui", ] @@ -4790,9 +4792,9 @@ checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" [[package]] name = "serde" -version = "1.0.225" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6c24dee235d0da097043389623fb913daddf92c76e9f5a1db88607a0bcbd1d" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ "serde_core", "serde_derive", @@ -4812,18 +4814,18 @@ dependencies = [ [[package]] name = "serde_core" -version = "1.0.225" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "659356f9a0cb1e529b24c01e43ad2bdf520ec4ceaf83047b83ddcc2251f96383" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.225" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ea936adf78b1f766949a4977b91d2f5595825bd6ec079aa9543ad2685fc4516" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", diff --git a/dash-frontend/Cargo.toml b/dash-frontend/Cargo.toml index b90d900..8f7a67c 100644 --- a/dash-frontend/Cargo.toml +++ b/dash-frontend/Cargo.toml @@ -12,3 +12,5 @@ rust-embed = { workspace = true } chrono = "0.4.42" gio = "0.21.2" gtk = "0.18.2" +serde = { version = "1.0.228", features = ["derive"] } +serde_json = "1.0.145" diff --git a/dash-frontend/assets/gui/dashboard.xml b/dash-frontend/assets/gui/dashboard.xml index 76f51aa..4f80849 100644 --- a/dash-frontend/assets/gui/dashboard.xml +++ b/dash-frontend/assets/gui/dashboard.xml @@ -79,9 +79,9 @@ gradient="radial" color="#44BBFF22" color2="#00000000" />
+ + + + + + + \ No newline at end of file diff --git a/dash-frontend/assets/gui/tab/settings.xml b/dash-frontend/assets/gui/tab/settings.xml index a3c31fe..7bc36f8 100644 --- a/dash-frontend/assets/gui/tab/settings.xml +++ b/dash-frontend/assets/gui/tab/settings.xml @@ -1,7 +1,61 @@ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + +
\ No newline at end of file diff --git a/dash-frontend/assets/lang/de.json b/dash-frontend/assets/lang/de.json index 418be81..9a8f739 100644 --- a/dash-frontend/assets/lang/de.json +++ b/dash-frontend/assets/lang/de.json @@ -5,5 +5,27 @@ "GAMES": "Spiele", "SETTINGS": "Einstellungen", "PROCESSES": "Prozesse", - "HELLO_USER": "Hallo, {USER}!" + "HELLO_USER": "Hallo, {USER}!", + "GENERAL_SETTINGS": "Allgemeine Einstellungen", + "APPLICATION_LAUNCHER": "Anwendung Launcher", + "APP_SETTINGS": { + "HIDE_USERNAME": "Benutzernamen ausblenden", + "12_HOUR_CLOCK": "12-Stunden-Uhr", + "OPAQUE_BACKGROUND": "Undurchsichtiger Hintergrund", + "RUN_IN_XWAYLAND_MODE_BY_DEFAULT": "Standardmäßig in XWayland-Modus ausführen", + "WLX_OVERLAY_S_SETTINGS": "WlxOverlay-S Einstellungen", + "HEADSET_SETTINGS": "Headset-Einstellungen", + "BRIGHTNESS": "Helligkeit", + "WLX": { + "NOTIFICATIONS_ENABLED": "Benachrichtigungen aktiviert", + "NOTIFICATIONS_SOUND_ENABLED": "Benachrichtigungssound aktiviert", + "KEYBOARD_SOUND_ENABLED": "Tastaturgeräusch aktiviert", + "BLOCK_GAME_INPUT": "Spielsteuerung blockieren", + "SPACE_DRAG_MULTIPLIER": "Raum-Drag-Multiplikator", + "SPACE_DRAG_ROTATION_ENABLED": "Rotation im Space-Drag aktivieren", + "SHOW_SKYBOX": "Skybox anzeigen", + "ENABLE_PASSTHROUGH": "Passthrough aktivieren" + }, + "RESTART_SOFTWARE": "Software neu starten" + } } \ No newline at end of file diff --git a/dash-frontend/assets/lang/en.json b/dash-frontend/assets/lang/en.json index d51ce4d..774669e 100644 --- a/dash-frontend/assets/lang/en.json +++ b/dash-frontend/assets/lang/en.json @@ -5,5 +5,27 @@ "GAMES": "Games", "SETTINGS": "Settings", "PROCESSES": "Processes", - "HELLO_USER": "Hello, {USER}!" + "HELLO_USER": "Hello, {USER}!", + "GENERAL_SETTINGS": "General settings", + "APPLICATION_LAUNCHER": "Application launcher", + "APP_SETTINGS": { + "RESTART_SOFTWARE": "Restart software", + "HIDE_USERNAME": "Hide username", + "12_HOUR_CLOCK": "12-hour clock", + "OPAQUE_BACKGROUND": "Opaque background", + "RUN_IN_XWAYLAND_MODE_BY_DEFAULT": "Run in XWayland mode by default", + "WLX_OVERLAY_S_SETTINGS": "WlxOverlay-S settings", + "HEADSET_SETTINGS": "Headset settings", + "BRIGHTNESS": "Brightness", + "WLX": { + "NOTIFICATIONS_ENABLED": "Notifications enabled", + "NOTIFICATIONS_SOUND_ENABLED": "Notifications sound enabled", + "KEYBOARD_SOUND_ENABLED": "Keyboard sound enabled", + "BLOCK_GAME_INPUT": "Block game input", + "SPACE_DRAG_MULTIPLIER": "Space-drag multiplier", + "SPACE_DRAG_ROTATION_ENABLED": "Enable rotation in space-drag", + "SHOW_SKYBOX": "Show skybox", + "ENABLE_PASSTHROUGH": "Enable passthrough" + } + } } diff --git a/dash-frontend/assets/lang/es.json b/dash-frontend/assets/lang/es.json index 74f2571..1c9536c 100644 --- a/dash-frontend/assets/lang/es.json +++ b/dash-frontend/assets/lang/es.json @@ -5,5 +5,27 @@ "GAMES": "Juegos", "SETTINGS": "Ajustes", "PROCESSES": "Procesos", - "HELLO_USER": "¡Hola, {USER}!" + "HELLO_USER": "¡Hola, {USER}!", + "GENERAL_SETTINGS": "Ajustes generales", + "APPLICATION_LAUNCHER": "Lanzador de aplicaciones", + "APP_SETTINGS": { + "HIDE_USERNAME": "Ocultar nombre de usuario", + "12_HOUR_CLOCK": "Reloj de 12 horas", + "OPAQUE_BACKGROUND": "Fondo opaco", + "RUN_IN_XWAYLAND_MODE_BY_DEFAULT": "Ejecutar en modo XWayland por defecto", + "WLX_OVERLAY_S_SETTINGS": "Configuración de WlxOverlay-S", + "HEADSET_SETTINGS": "Configuración del casco", + "BRIGHTNESS": "Brillo", + "WLX": { + "NOTIFICATIONS_ENABLED": "Notificaciones activadas", + "NOTIFICATIONS_SOUND_ENABLED": "Sonido de notificaciones activado", + "KEYBOARD_SOUND_ENABLED": "Sonido del teclado activado", + "BLOCK_GAME_INPUT": "Bloquear entrada del juego", + "SPACE_DRAG_MULTIPLIER": "Multiplicador de movimiento por arrastre", + "SPACE_DRAG_ROTATION_ENABLED": "Habilitar rotación en space-drag", + "SHOW_SKYBOX": "Mostrar cielo", + "ENABLE_PASSTHROUGH": "Habilitar Passthrough" + }, + "RESTART_SOFTWARE": "Reiniciar software" + } } \ No newline at end of file diff --git a/dash-frontend/assets/lang/ja.json b/dash-frontend/assets/lang/ja.json index 4ee2402..d49bdc0 100644 --- a/dash-frontend/assets/lang/ja.json +++ b/dash-frontend/assets/lang/ja.json @@ -5,5 +5,27 @@ "GAMES": "ゲーム", "SETTINGS": "設定", "PROCESSES": "プロセス", - "HELLO_USER": "こんにちは、{USER}!" + "HELLO_USER": "こんにちは、{USER}!", + "GENERAL_SETTINGS": "全般設定", + "APPLICATION_LAUNCHER": "アプリケーションランチャー", + "APP_SETTINGS": { + "HIDE_USERNAME": "ユーザー名を表示しない", + "12_HOUR_CLOCK": "12時間表示", + "OPAQUE_BACKGROUND": "不透明な背景", + "RUN_IN_XWAYLAND_MODE_BY_DEFAULT": "XWaylandモードでデフォルトで実行する", + "WLX_OVERLAY_S_SETTINGS": "WlxOverlay-Sの設定", + "HEADSET_SETTINGS": "ヘッドセット設定", + "BRIGHTNESS": "明るさ", + "WLX": { + "NOTIFICATIONS_ENABLED": "通知が有効", + "NOTIFICATIONS_SOUND_ENABLED": "通知音を有効にする", + "KEYBOARD_SOUND_ENABLED": "キーボード音を有効にする", + "BLOCK_GAME_INPUT": "ゲーム入力をブロック", + "SPACE_DRAG_MULTIPLIER": "スペースドラッグ乗数", + "SPACE_DRAG_ROTATION_ENABLED": "スペースドラッグでの回転を有効にする", + "SHOW_SKYBOX": "スカイボックスを表示", + "ENABLE_PASSTHROUGH": "Passthroughを有効にする" + }, + "RESTART_SOFTWARE": "ソフトウェアを再起動" + } } \ No newline at end of file diff --git a/dash-frontend/assets/lang/pl.json b/dash-frontend/assets/lang/pl.json index 0f0db08..0bec637 100644 --- a/dash-frontend/assets/lang/pl.json +++ b/dash-frontend/assets/lang/pl.json @@ -1,9 +1,31 @@ { - "HOME_SCREEN": "Ekran główny", - "MONADO_RUNTIME": "„Monado” środowisko uruchomieniowe", - "APPLICATIONS": "Aplikacje", - "GAMES": "Gry", - "SETTINGS": "Ustawienia", - "PROCESSES": "Procesy", - "HELLO_USER": "Witaj, {USER}!" -} \ No newline at end of file + "HOME_SCREEN": "Ekran główny", + "MONADO_RUNTIME": "„Monado” środowisko uruchomieniowe", + "APPLICATIONS": "Aplikacje", + "GAMES": "Gry", + "SETTINGS": "Ustawienia", + "PROCESSES": "Procesy", + "HELLO_USER": "Witaj, {USER}!", + "GENERAL_SETTINGS": "Ustawienia ogólne", + "APPLICATION_LAUNCHER": "Uruchamiacz aplikacji", + "APP_SETTINGS": { + "HIDE_USERNAME": "Ukryj nazwę użytkownika", + "12_HOUR_CLOCK": "12-godzinny zegar", + "OPAQUE_BACKGROUND": "Nieprzezroczysty tło", + "RUN_IN_XWAYLAND_MODE_BY_DEFAULT": "Uruchom domyślnie w trybie XWayland", + "WLX_OVERLAY_S_SETTINGS": "Ustawienia wlx-overlay-s", + "HEADSET_SETTINGS": "Ustawienia głośności", + "BRIGHTNESS": "Jasność", + "WLX": { + "NOTIFICATIONS_ENABLED": "Powiadomienia", + "NOTIFICATIONS_SOUND_ENABLED": "Dźwięk powiadomień", + "KEYBOARD_SOUND_ENABLED": "Dźwięki klawiatury", + "BLOCK_GAME_INPUT": "Zablokuj sterowanie grą podczas używania Wlx", + "SPACE_DRAG_MULTIPLIER": "Mnożnik space-drag", + "SPACE_DRAG_ROTATION_ENABLED": "Włącz rotację w space-drag", + "SHOW_SKYBOX": "Pokaż skybox", + "ENABLE_PASSTHROUGH": "Włącz passthrough" + }, + "RESTART_SOFTWARE": "Uruchom ponownie oprogramowanie" + } +} diff --git a/dash-frontend/src/frontend.rs b/dash-frontend/src/frontend.rs index ea4c391..a2fd8db 100644 --- a/dash-frontend/src/frontend.rs +++ b/dash-frontend/src/frontend.rs @@ -14,7 +14,7 @@ use wgui::{ }; use crate::{ - assets, + assets, settings, tab::{ Tab, TabParams, TabType, apps::TabApps, games::TabGames, home::TabHome, monado::TabMonado, processes::TabProcesses, settings::TabSettings, @@ -25,6 +25,8 @@ pub struct Frontend { pub layout: RcLayout, globals: WguiGlobals, + settings: settings::Settings, + #[allow(dead_code)] state: ParserState, @@ -37,6 +39,10 @@ pub struct Frontend { label_time_id: WidgetID, } +pub struct InitParams { + pub settings: settings::Settings, +} + pub type RcFrontend = Rc>; pub enum FrontendTask { @@ -44,7 +50,7 @@ pub enum FrontendTask { } impl Frontend { - pub fn new() -> anyhow::Result<(RcFrontend, RcLayout)> { + pub fn new(params: InitParams) -> anyhow::Result<(RcFrontend, RcLayout)> { let globals = WguiGlobals::new(Box::new(assets::Asset {}), wgui::globals::Defaults::default())?; let (layout, state) = wgui::parser::new_layout_from_assets( @@ -71,6 +77,7 @@ impl Frontend { tasks, ticks: 0, label_time_id, + settings: params.settings, })); Frontend::register_widgets(&res)?; diff --git a/dash-frontend/src/lib.rs b/dash-frontend/src/lib.rs index 2a1d3b6..00dd643 100644 --- a/dash-frontend/src/lib.rs +++ b/dash-frontend/src/lib.rs @@ -1,5 +1,6 @@ mod assets; pub mod frontend; +pub mod settings; mod tab; mod util; mod various; diff --git a/dash-frontend/src/settings.rs b/dash-frontend/src/settings.rs new file mode 100644 index 0000000..67376a9 --- /dev/null +++ b/dash-frontend/src/settings.rs @@ -0,0 +1,41 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Default, Serialize, Deserialize)] +pub struct HomeScreen { + pub hide_username: bool, +} + +#[derive(Default, Serialize, Deserialize)] +pub struct General { + pub am_pm_clock: bool, + pub opaque_background: bool, +} + +#[derive(Default, Serialize, Deserialize)] +pub enum ApplicationRunMode { + #[default] + Native, /* use Smithay compositor */ + XWaylandCage, +} + +#[derive(Default, Serialize, Deserialize)] +pub struct Tweaks { + pub default_run_mode: ApplicationRunMode, +} + +#[derive(Default, Serialize, Deserialize)] +pub struct Settings { + pub home_screen: HomeScreen, + pub general: General, + pub tweaks: Tweaks, +} + +impl Settings { + pub fn save(&self) -> String { + serde_json::to_string(&self).unwrap() /* want panic */ + } + + pub fn load(input: &str) -> anyhow::Result { + Ok(serde_json::from_str::(input)?) + } +} diff --git a/scripts/translator/description.txt b/scripts/translator/description.txt index 46bbc78..1522ed6 100644 --- a/scripts/translator/description.txt +++ b/scripts/translator/description.txt @@ -8,6 +8,8 @@ WayVR Dashboard: An application (and game) launcher which is displayed in front OpenVR: API made by Valve OpenXR: API made by Khronos OSC: OpenSoundControl +Space-drag: A feature which allows the user to move their HMD origin position via a controller +Passthrough: Some headsets have built-in cameras for displaying image on the HMD screen You will be given the input in the code blocks which needs to be translated to {TARGET_LANG} language. Write only the result in codeblocks, do not explain. Keep any newlines and other important formatting-required identifiers as-is. diff --git a/uidev/src/testbed/testbed_dashboard.rs b/uidev/src/testbed/testbed_dashboard.rs index c07bb7d..ad9b79e 100644 --- a/uidev/src/testbed/testbed_dashboard.rs +++ b/uidev/src/testbed/testbed_dashboard.rs @@ -9,7 +9,9 @@ pub struct TestbedDashboard { impl TestbedDashboard { pub fn new() -> anyhow::Result { - let (frontend, layout) = frontend::Frontend::new()?; + let (frontend, layout) = frontend::Frontend::new(frontend::InitParams { + settings: Default::default(), + })?; Ok(Self { frontend, layout }) } } diff --git a/wgui/src/components/button.rs b/wgui/src/components/button.rs index 529ac35..4c99064 100644 --- a/wgui/src/components/button.rs +++ b/wgui/src/components/button.rs @@ -1,6 +1,6 @@ use crate::{ animation::{Animation, AnimationEasing}, - components::{self, tooltip::ComponentTooltip, Component, ComponentBase, ComponentTrait, InitData}, + components::{self, Component, ComponentBase, ComponentTrait, InitData, tooltip::ComponentTooltip}, drawing::{self, Boundary, Color}, event::{CallbackDataCommon, EventListenerCollection, EventListenerID, EventListenerKind}, i18n::Translation, @@ -10,15 +10,15 @@ use crate::{ util::centered_matrix, }, widget::{ + ConstructEssentials, EventResult, WidgetData, label::{WidgetLabel, WidgetLabelParams}, rectangle::{WidgetRectangle, WidgetRectangleParams}, util::WLength, - ConstructEssentials, EventResult, WidgetData, }, }; use glam::{Mat4, Vec3}; use std::{cell::RefCell, rc::Rc}; -use taffy::{AlignItems, JustifyContent}; +use taffy::{AlignItems, JustifyContent, prelude::length}; pub struct Params { pub text: Option, // if unset, label will not be populated @@ -281,6 +281,7 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul style.justify_content = Some(JustifyContent::Center); style.overflow.x = taffy::Overflow::Hidden; style.overflow.y = taffy::Overflow::Hidden; + style.gap = length(4.0); // update colors to default ones if they are not specified let color = if let Some(color) = params.color { diff --git a/wgui/src/components/checkbox.rs b/wgui/src/components/checkbox.rs index ae1d639..f9e17c7 100644 --- a/wgui/src/components/checkbox.rs +++ b/wgui/src/components/checkbox.rs @@ -1,7 +1,7 @@ use std::{cell::RefCell, rc::Rc}; use taffy::{ - prelude::{length, percent}, AlignItems, JustifyContent, + prelude::{length, percent}, }; use crate::{ @@ -13,10 +13,10 @@ use crate::{ layout::{self, LayoutState, WidgetID, WidgetPair}, renderer_vk::text::{FontWeight, TextStyle}, widget::{ + ConstructEssentials, EventResult, label::{WidgetLabel, WidgetLabelParams}, rectangle::{WidgetRectangle, WidgetRectangleParams}, util::WLength, - ConstructEssentials, EventResult, }, }; @@ -223,6 +223,7 @@ fn register_event_mouse_release( ) } +#[allow(clippy::too_many_lines)] pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Result<(WidgetPair, Rc)> { let mut style = params.style; @@ -230,12 +231,21 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul style.flex_wrap = taffy::FlexWrap::NoWrap; style.align_items = Some(AlignItems::Center); style.justify_content = Some(JustifyContent::Center); + + // make checkbox interaction box larger by setting padding and negative margin style.padding = taffy::Rect { left: length(4.0), right: length(8.0), top: length(4.0), bottom: length(4.0), }; + + style.margin = taffy::Rect { + left: length(-4.0), + right: length(-8.0), + top: length(-4.0), + bottom: length(-4.0), + }; //style.align_self = Some(taffy::AlignSelf::Start); // do not stretch self to the parent style.gap = length(4.0); diff --git a/wgui/src/components/slider.rs b/wgui/src/components/slider.rs index a335ba1..7768cc7 100644 --- a/wgui/src/components/slider.rs +++ b/wgui/src/components/slider.rs @@ -15,11 +15,11 @@ use crate::{ util, }, widget::{ + ConstructEssentials, EventResult, div::WidgetDiv, label::{WidgetLabel, WidgetLabelParams}, rectangle::{WidgetRectangle, WidgetRectangleParams}, util::WLength, - ConstructEssentials, EventResult, }, }; @@ -149,7 +149,7 @@ impl State { } } -const BODY_COLOR: drawing::Color = drawing::Color::new(0.6, 0.65, 0.7, 1.0); +const BODY_COLOR: drawing::Color = drawing::Color::new(0.6, 0.65, 0.7, 0.2); const BODY_BORDER_COLOR: drawing::Color = drawing::Color::new(0.4, 0.45, 0.5, 1.0); const HANDLE_BORDER_COLOR: drawing::Color = drawing::Color::new(0.85, 0.85, 0.85, 1.0); const HANDLE_BORDER_COLOR_HOVERED: drawing::Color = drawing::Color::new(0.0, 0.0, 0.0, 1.0);