From b56aa1a8de6b0c8292ecf3a3678221ef7b2fe2ab Mon Sep 17 00:00:00 2001 From: galister <22305755+galister@users.noreply.github.com> Date: Mon, 5 Jan 2026 15:45:19 +0900 Subject: [PATCH] bar app icons & tooltips --- Cargo.lock | 8 +-- dash-frontend/Cargo.toml | 4 -- dash-frontend/src/frontend.rs | 17 ++--- dash-frontend/src/tab/apps.rs | 12 ++-- dash-frontend/src/util/mod.rs | 1 - dash-frontend/src/util/various.rs | 3 +- dash-frontend/src/views/app_launcher.rs | 4 +- dash-frontend/src/views/process_list.rs | 12 ++-- wayvr-ipc/src/packet_client.rs | 1 + wgui/src/i18n.rs | 64 +++++++++++++++---- wgui/src/lib.rs | 1 + wgui/src/log.rs | 53 +++++++++++++++ wlx-common/Cargo.toml | 4 ++ wlx-common/src/common.rs | 30 --------- wlx-common/src/dash_interface.rs | 3 + wlx-common/src/dash_interface_emulated.rs | 16 ++++- .../util => wlx-common/src}/desktop_finder.rs | 31 +++++---- wlx-common/src/lib.rs | 1 + wlx-common/src/overlays.rs | 5 ++ wlx-overlay-s/src/assets/gui/keyboard.xml | 18 +++--- wlx-overlay-s/src/assets/lang/en.json | 6 ++ wlx-overlay-s/src/backend/wayvr/mod.rs | 62 ++++++++++++++---- wlx-overlay-s/src/backend/wayvr/process.rs | 15 +++-- wlx-overlay-s/src/ipc/ipc_server.rs | 2 + wlx-overlay-s/src/overlays/dashboard.rs | 10 ++- .../src/overlays/keyboard/builder.rs | 3 +- wlx-overlay-s/src/overlays/wayvr.rs | 16 +++-- wlx-overlay-s/src/state.rs | 7 ++ wlx-overlay-s/src/windowing/backend.rs | 1 + wlx-overlay-s/src/windowing/manager.rs | 10 ++- 30 files changed, 291 insertions(+), 129 deletions(-) create mode 100644 wgui/src/log.rs rename {dash-frontend/src/util => wlx-common/src}/desktop_finder.rs (88%) diff --git a/Cargo.lock b/Cargo.lock index e1a1253..63953b4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1428,20 +1428,16 @@ dependencies = [ "async-native-tls", "chrono", "glam", - "glob", "http-body-util", "hyper", - "identicons-svg", "keyvalues-parser", "log", "rust-embed", - "rust-ini", "serde", "serde_json", "smol", "smol-hyper", "strum", - "walkdir", "wayvr-ipc", "wgui", "wlx-common", @@ -6923,12 +6919,16 @@ dependencies = [ "anyhow", "chrono", "glam", + "glob", + "identicons-svg", "idmap", "idmap-derive", "log", "rodio", + "rust-ini", "serde", "smol", + "walkdir", "wayvr-ipc", "wgui", "xdg 3.0.0", diff --git a/dash-frontend/Cargo.toml b/dash-frontend/Cargo.toml index 3e75f67..2405247 100644 --- a/dash-frontend/Cargo.toml +++ b/dash-frontend/Cargo.toml @@ -24,7 +24,3 @@ hyper = { version = "1.8.1", features = ["client", "http1", "http2"] } http-body-util = "0.1.3" async-native-tls = "0.5.0" smol-hyper = "0.1.1" -glob = "0.3.3" -walkdir = "2.5.0" -rust-ini = "0.21.3" -identicons-svg = "0.1.0" diff --git a/dash-frontend/src/frontend.rs b/dash-frontend/src/frontend.rs index 10f30a0..c898d0b 100644 --- a/dash-frontend/src/frontend.rs +++ b/dash-frontend/src/frontend.rs @@ -19,11 +19,10 @@ use wlx_common::{audio, dash_interface::BoxDashInterface, timestep::Timestep}; use crate::{ assets, settings, tab::{ - Tab, TabType, apps::TabApps, games::TabGames, home::TabHome, monado::TabMonado, processes::TabProcesses, - settings::TabSettings, + apps::TabApps, games::TabGames, home::TabHome, monado::TabMonado, processes::TabProcesses, settings::TabSettings, + Tab, TabType, }, util::{ - desktop_finder::DesktopFinder, popup_manager::{MountPopupParams, PopupManager, PopupManagerParams}, toast_manager::ToastManager, various::AsyncExecutor, @@ -64,8 +63,6 @@ pub struct Frontend { window_audio_settings: WguiWindow, view_audio_settings: Option, - - pub(crate) desktop_finder: DesktopFinder, } pub struct FrontendUpdateParams<'a, T> { @@ -137,9 +134,6 @@ impl Frontend { let timestep = Timestep::new(60.0); - let mut desktop_finder = DesktopFinder::new(); - desktop_finder.refresh(); - let mut frontend = Self { layout, state, @@ -159,7 +153,6 @@ impl Frontend { window_audio_settings: WguiWindow::default(), view_audio_settings: None, executor: Rc::new(smol::LocalExecutor::new()), - desktop_finder, }; // init some things first @@ -292,7 +285,7 @@ impl Frontend { fn process_task(&mut self, data: &mut T, task: FrontendTask) -> anyhow::Result<()> { match task { - FrontendTask::SetTab(tab_type) => self.set_tab(tab_type)?, + FrontendTask::SetTab(tab_type) => self.set_tab(data, tab_type)?, FrontendTask::RefreshClock => self.update_time()?, FrontendTask::RefreshBackground => self.update_background()?, FrontendTask::MountPopup(params) => self.mount_popup(params)?, @@ -305,14 +298,14 @@ impl Frontend { Ok(()) } - fn set_tab(&mut self, tab_type: TabType) -> anyhow::Result<()> { + fn set_tab(&mut self, data: &mut T, tab_type: TabType) -> anyhow::Result<()> { log::info!("Setting tab to {tab_type:?}"); let widget_content = self.state.fetch_widget(&self.layout.state, "content")?; self.layout.remove_children(widget_content.id); let tab: Box> = match tab_type { TabType::Home => Box::new(TabHome::new(self, widget_content.id)?), - TabType::Apps => Box::new(TabApps::new(self, widget_content.id)?), + TabType::Apps => Box::new(TabApps::new(self, widget_content.id, data)?), TabType::Games => Box::new(TabGames::new(self, widget_content.id)?), TabType::Monado => Box::new(TabMonado::new(self, widget_content.id)?), TabType::Processes => Box::new(TabProcesses::new(self, widget_content.id)?), diff --git a/dash-frontend/src/tab/apps.rs b/dash-frontend/src/tab/apps.rs index 4c58f77..aa52a27 100644 --- a/dash-frontend/src/tab/apps.rs +++ b/dash-frontend/src/tab/apps.rs @@ -14,14 +14,12 @@ use wgui::{ parser::{Fetchable, ParseDocumentParams, ParserState}, task::Tasks, }; +use wlx_common::desktop_finder::DesktopEntry; use crate::{ frontend::{Frontend, FrontendTask, FrontendTasks}, tab::{Tab, TabType}, - util::{ - desktop_finder::DesktopEntry, - popup_manager::{MountPopupParams, PopupHandle}, - }, + util::popup_manager::{MountPopupParams, PopupHandle}, views::{self, app_launcher}, }; @@ -127,16 +125,16 @@ fn doc_params(globals: WguiGlobals) -> ParseDocumentParams<'static> { } impl TabApps { - pub fn new(frontend: &mut Frontend, parent_id: WidgetID) -> anyhow::Result { + pub fn new(frontend: &mut Frontend, parent_id: WidgetID, data: &mut T) -> anyhow::Result { let globals = frontend.layout.state.globals.clone(); let tasks = Tasks::new(); let state = Rc::new(RefCell::new(State { view_launcher: None })); - let mut entries = frontend.desktop_finder.find_entries(); + let mut entries = frontend.interface.desktop_finder(data).find_entries(); let parser_state = wgui::parser::parse_from_assets(&doc_params(globals.clone()), &mut frontend.layout, parent_id)?; let app_list_parent = parser_state.fetch_widget(&frontend.layout.state, "app_list_parent")?; let app_list = AppList { - entries_to_mount: entries.drain(..).collect(), + entries_to_mount: entries.into_values().collect(), list_parent: app_list_parent, }; diff --git a/dash-frontend/src/util/mod.rs b/dash-frontend/src/util/mod.rs index 4314dbe..c263cde 100644 --- a/dash-frontend/src/util/mod.rs +++ b/dash-frontend/src/util/mod.rs @@ -1,5 +1,4 @@ pub mod cached_fetcher; -pub mod desktop_finder; pub mod http_client; pub mod pactl_wrapper; pub mod popup_manager; diff --git a/dash-frontend/src/util/various.rs b/dash-frontend/src/util/various.rs index a8eae18..df2cb05 100644 --- a/dash-frontend/src/util/various.rs +++ b/dash-frontend/src/util/various.rs @@ -11,11 +11,10 @@ use wgui::{ sprite::{WidgetSprite, WidgetSpriteParams}, }, }; +use wlx_common::desktop_finder; pub type AsyncExecutor = Rc>; -use crate::util::desktop_finder; - // the compiler wants to scream #[allow(irrefutable_let_patterns)] pub fn get_desktop_file_icon_path(desktop_file: &desktop_finder::DesktopEntry) -> AssetPathOwned { diff --git a/dash-frontend/src/views/app_launcher.rs b/dash-frontend/src/views/app_launcher.rs index ca8268c..942337c 100644 --- a/dash-frontend/src/views/app_launcher.rs +++ b/dash-frontend/src/views/app_launcher.rs @@ -12,12 +12,11 @@ use wgui::{ task::Tasks, widget::label::WidgetLabel, }; -use wlx_common::dash_interface::BoxDashInterface; +use wlx_common::{dash_interface::BoxDashInterface, desktop_finder::DesktopEntry}; use crate::{ frontend::{FrontendTask, FrontendTasks}, settings::SettingsIO, - util::desktop_finder::DesktopEntry, }; #[derive(Clone, Copy, Eq, PartialEq, EnumString, VariantNames, AsRefStr)] @@ -325,6 +324,7 @@ impl View { name: params.application.app_name.to_string(), args, resolution, + icon: params.application.icon_path.as_ref().map(|x| x.as_ref().to_string()), userdata, }, )?; diff --git a/dash-frontend/src/views/process_list.rs b/dash-frontend/src/views/process_list.rs index 4be9746..2062778 100644 --- a/dash-frontend/src/views/process_list.rs +++ b/dash-frontend/src/views/process_list.rs @@ -20,13 +20,9 @@ use wgui::{ ConstructEssentials, }, }; -use wlx_common::dash_interface::BoxDashInterface; +use wlx_common::{dash_interface::BoxDashInterface, desktop_finder::DesktopEntry}; -use crate::util::{ - self, - desktop_finder::{self}, - various::get_desktop_file_icon_path, -}; +use crate::util::{self, various::get_desktop_file_icon_path}; #[derive(Clone)] enum Task { @@ -94,13 +90,13 @@ impl View { } } -fn get_desktop_entry_from_process(process: &packet_server::WvrProcess) -> Option { +fn get_desktop_entry_from_process(process: &packet_server::WvrProcess) -> Option { // TODO: refactor this after we ditch old wayvr-dashboard completely let Some(dfile_str) = process.userdata.get("desktop-entry") else { return None; }; - let Ok(desktop_file) = serde_json::from_str::(dfile_str) else { + let Ok(desktop_file) = serde_json::from_str::(dfile_str) else { debug_assert!(false); // invalid json??? return None; }; diff --git a/wayvr-ipc/src/packet_client.rs b/wayvr-ipc/src/packet_client.rs index 7825687..f32c4d4 100644 --- a/wayvr-ipc/src/packet_client.rs +++ b/wayvr-ipc/src/packet_client.rs @@ -28,6 +28,7 @@ pub struct WvrProcessLaunchParams { pub exec: String, pub env: Vec, pub args: String, + pub icon: Option, pub resolution: [u32; 2], pub userdata: HashMap, } diff --git a/wgui/src/i18n.rs b/wgui/src/i18n.rs index f15c3ec..baa2440 100644 --- a/wgui/src/i18n.rs +++ b/wgui/src/i18n.rs @@ -1,5 +1,7 @@ use std::rc::Rc; +use anyhow::Context; + use crate::assets::AssetProvider; // a string which optionally has translation key in it @@ -98,10 +100,27 @@ impl I18n { } let data_english = provider.load_from_path("lang/en.json")?; - let data_translated = provider.load_from_path(&format!("lang/{lang}.json"))?; + let path = format!("lang/{lang}.json"); + let data_translated = provider + .load_from_path(&path) + .with_context(|| path.clone()) + .context("Could not load translation file")?; - let json_root_fallback = serde_json::from_str(str::from_utf8(&data_english)?)?; - let json_root_translated = serde_json::from_str(str::from_utf8(&data_translated)?)?; + let json_root_fallback = serde_json::from_str( + str::from_utf8(&data_english) + .with_context(|| path.clone()) + .context("Translation file not valid UTF-8")?, + ) + .with_context(|| path.clone()) + .context("Translation file not valid JSON")?; + + let json_root_translated = serde_json::from_str( + str::from_utf8(&data_translated) + .with_context(|| path.clone()) + .context("Translation file not valid UTF-8")?, + ) + .with_context(|| path.clone()) + .context("Translation file not valid JSON")?; Ok(Self { json_root_translated, @@ -110,22 +129,16 @@ impl I18n { } pub fn translate(&mut self, translation_key_full: &str) -> Rc { - let translation_key = translation_key_full - .split_once(';') - .map_or(translation_key_full, |(a, _)| a); + let mut sections = translation_key_full.split(';'); + let translation_key = sections.next().map_or(translation_key_full, |a| a); if let Some(translated) = find_translation(translation_key, &self.json_root_translated) { - return Rc::from(translated); + return Rc::from(format_translated(translated, sections)); } if let Some(translated_fallback) = find_translation(translation_key, &self.json_root_fallback) { log::warn!("missing translation for key \"{translation_key}\", using \"en\" instead"); - return Rc::from(translated_fallback); - } - - // not even found in fallback, check if the translation contains ";" (to be used as "MY_TRANSLATION_KEY;A fallback text") - if let Some((idx, _)) = translation_key_full.match_indices(';').next() { - return Rc::from(&translation_key_full[idx + 1..]); + return Rc::from(format_translated(translated_fallback, sections)); } log::error!("missing translation for key \"{translation_key}\""); @@ -137,3 +150,28 @@ impl I18n { translated.replace(to_replace.0, to_replace.1) } } + +fn format_translated<'a, I>(format: &str, args: I) -> String +where + I: IntoIterator, +{ + let mut result = String::new(); + let mut args = args.into_iter(); + + let mut chars = format.chars().peekable(); + while let Some(c) = chars.next() { + if c == '{' && chars.peek() == Some(&'}') { + chars.next(); //consume } + if let Some(arg) = args.next() { + result.push_str(arg); + } else { + // no more args → keep literal {} + result.push_str("{}"); + } + } else { + result.push(c); + } + } + + result +} diff --git a/wgui/src/lib.rs b/wgui/src/lib.rs index 24c12fb..c956783 100644 --- a/wgui/src/lib.rs +++ b/wgui/src/lib.rs @@ -32,6 +32,7 @@ pub mod gfx; pub mod globals; pub mod i18n; pub mod layout; +pub mod log; pub mod parser; pub mod renderer_vk; pub mod sound; diff --git a/wgui/src/log.rs b/wgui/src/log.rs new file mode 100644 index 0000000..2e680e6 --- /dev/null +++ b/wgui/src/log.rs @@ -0,0 +1,53 @@ +use std::fmt::Debug; + +pub trait LogErr { + fn log_err(self) -> Self; + fn log_err_with(self, additional: &str) -> Self; + fn log_warn(self) -> Self; + fn log_warn_with(self, additional: &str) -> Self; +} + +impl LogErr for Result +where + E: Debug + Send + Sync + 'static, +{ + fn log_warn(self) -> Result { + match self { + Ok(ok) => Ok(ok), + Err(error) => { + log::warn!("{error:?}"); + Err(error) + } + } + } + + fn log_warn_with(self, additional: &str) -> Result { + match self { + Ok(ok) => Ok(ok), + Err(error) => { + log::warn!("{additional}: {error:?}"); + Err(error) + } + } + } + + fn log_err(self) -> Result { + match self { + Ok(ok) => Ok(ok), + Err(error) => { + log::error!("{error:?}"); + Err(error) + } + } + } + + fn log_err_with(self, additional: &str) -> Result { + match self { + Ok(ok) => Ok(ok), + Err(error) => { + log::error!("{additional}: {error:?}"); + Err(error) + } + } + } +} diff --git a/wlx-common/Cargo.toml b/wlx-common/Cargo.toml index 75bedef..c2a0fc0 100644 --- a/wlx-common/Cargo.toml +++ b/wlx-common/Cargo.toml @@ -22,3 +22,7 @@ rodio = { version = "0.21.1", default-features = false, features = [ "mp3", "hound", ] } +glob = "0.3.3" +walkdir = "2.5.0" +rust-ini = "0.21.3" +identicons-svg = "0.1.0" diff --git a/wlx-common/src/common.rs b/wlx-common/src/common.rs index a9b469d..a8c07d2 100644 --- a/wlx-common/src/common.rs +++ b/wlx-common/src/common.rs @@ -9,33 +9,3 @@ pub enum LeftRight { Left, Right, } - -pub trait LogErr { - fn log_err(self) -> Self; - fn log_warn(self) -> Self; -} - -impl LogErr for Result -where - E: Debug + Send + Sync + 'static, -{ - fn log_warn(self) -> Result { - match self { - Ok(ok) => Ok(ok), - Err(error) => { - log::warn!("{error:?}"); - Err(error) - } - } - } - - fn log_err(self) -> Result { - match self { - Ok(ok) => Ok(ok), - Err(error) => { - log::error!("{error:?}"); - Err(error) - } - } - } -} diff --git a/wlx-common/src/dash_interface.rs b/wlx-common/src/dash_interface.rs index fd97cb8..f9d3541 100644 --- a/wlx-common/src/dash_interface.rs +++ b/wlx-common/src/dash_interface.rs @@ -3,6 +3,8 @@ use wayvr_ipc::{ packet_server::{WvrProcess, WvrProcessHandle, WvrWindow, WvrWindowHandle}, }; +use crate::desktop_finder::DesktopFinder; + pub trait DashInterface { fn window_list(&mut self, data: &mut T) -> anyhow::Result>; fn window_set_visible(&mut self, data: &mut T, handle: WvrWindowHandle, visible: bool) -> anyhow::Result<()>; @@ -12,6 +14,7 @@ pub trait DashInterface { fn process_list(&mut self, data: &mut T) -> anyhow::Result>; fn process_terminate(&mut self, data: &mut T, handle: WvrProcessHandle) -> anyhow::Result<()>; fn recenter_playspace(&mut self, data: &mut T) -> anyhow::Result<()>; + fn desktop_finder<'a>(&'a mut self, data: &'a mut T) -> &'a mut DesktopFinder; } pub type BoxDashInterface = Box>; diff --git a/wlx-common/src/dash_interface_emulated.rs b/wlx-common/src/dash_interface_emulated.rs index 164de2e..3b44ae8 100644 --- a/wlx-common/src/dash_interface_emulated.rs +++ b/wlx-common/src/dash_interface_emulated.rs @@ -3,7 +3,7 @@ use wayvr_ipc::{ packet_server::{WvrProcess, WvrProcessHandle, WvrWindow, WvrWindowHandle}, }; -use crate::{dash_interface::DashInterface, gen_id}; +use crate::{dash_interface::DashInterface, desktop_finder::DesktopFinder, gen_id}; #[derive(Debug)] pub struct EmuProcess { @@ -54,6 +54,7 @@ gen_id!(EmuProcessVec, EmuProcess, EmuProcessCell, EmuProcessHandle); pub struct DashInterfaceEmulated { processes: EmuProcessVec, windows: EmuWindowVec, + desktop_finder: DesktopFinder, } impl DashInterfaceEmulated { @@ -69,7 +70,14 @@ impl DashInterfaceEmulated { visible: true, }); - Self { processes, windows } + let mut desktop_finder = DesktopFinder::new(); + desktop_finder.refresh(); + + Self { + processes, + windows, + desktop_finder, + } } } @@ -157,4 +165,8 @@ impl DashInterface<()> for DashInterfaceEmulated { // stub! Ok(()) } + + fn desktop_finder<'a>(&'a mut self, _: &'a mut ()) -> &'a mut DesktopFinder { + &mut self.desktop_finder + } } diff --git a/dash-frontend/src/util/desktop_finder.rs b/wlx-common/src/desktop_finder.rs similarity index 88% rename from dash-frontend/src/util/desktop_finder.rs rename to wlx-common/src/desktop_finder.rs index e950eba..3e39b20 100644 --- a/dash-frontend/src/util/desktop_finder.rs +++ b/wlx-common/src/desktop_finder.rs @@ -1,12 +1,12 @@ use std::{ - collections::HashSet, ffi::OsStr, fmt::Debug, fs::exists, path::Path, rc::Rc, sync::Arc, thread::JoinHandle, + collections::{HashMap, HashSet}, ffi::OsStr, fmt::Debug, fs::exists, path::Path, rc::Rc, sync::Arc, thread::JoinHandle, time::Instant, }; use ini::Ini; use serde::{Deserialize, Serialize}; use walkdir::WalkDir; -use wlx_common::cache_dir; +use crate::cache_dir; struct DesktopEntryOwned { exec_path: String, @@ -50,8 +50,8 @@ struct DesktopFinderParams { pub struct DesktopFinder { params: Arc, - entry_cache: Vec, - bg_task: Option>>, + entry_cache: HashMap, + bg_task: Option>>, } impl DesktopFinder { @@ -98,16 +98,16 @@ impl DesktopFinder { icon_folders, size_preferences, }), - entry_cache: Vec::new(), + entry_cache: HashMap::new(), bg_task: None, } } - fn build_cache(params: Arc) -> Vec { + fn build_cache(params: Arc) -> HashMap { let start = Instant::now(); let mut known_files = HashSet::new(); - let mut entries = Vec::::new(); + let mut entries = HashMap::::new(); let icons_folder = cache_dir::get_path("icons"); if !std::fs::exists(&icons_folder).unwrap_or(false) { @@ -131,6 +131,9 @@ impl DesktopFinder { } let file_name = entry.file_name().to_string_lossy(); + let Some(app_id) = Path::new(entry.file_name()).file_stem().map(|x| x.to_string_lossy().to_string()) else { + continue; + }; if known_files.contains(file_name.as_ref()) { // as per xdg spec, user entries of the same filename will override system entries @@ -220,7 +223,7 @@ impl DesktopFinder { known_files.insert(file_name.to_string()); - entries.push(DesktopEntryOwned { + entries.insert(app_id, DesktopEntryOwned { app_name: String::from(app_name), exec_path: String::from(exec_path), exec_args: exec_args.join(" "), @@ -265,7 +268,7 @@ impl DesktopFinder { None } - fn create_icon(desktop_entry_name: &str) -> anyhow::Result { + pub fn create_icon(desktop_entry_name: &str) -> anyhow::Result { let relative_path = format!("icons/{}.svg", desktop_entry_name); let file_path = cache_dir::get_path(&relative_path).to_string_lossy().to_string(); @@ -295,12 +298,16 @@ impl DesktopFinder { }; self.entry_cache.clear(); - for entry in entries { - self.entry_cache.push(entry.into()); + for (app_id, entry) in entries { + self.entry_cache.insert(app_id, entry.into()); } } - pub fn find_entries(&mut self) -> Vec { + pub fn get_cached_entry(&self, app_id: &str) -> Option<&DesktopEntry> { + self.entry_cache.get(app_id) + } + + pub fn find_entries(&mut self) -> HashMap { self.wait_for_entries(); self.entry_cache.clone() } diff --git a/wlx-common/src/lib.rs b/wlx-common/src/lib.rs index a5697a4..0a5cdd2 100644 --- a/wlx-common/src/lib.rs +++ b/wlx-common/src/lib.rs @@ -5,6 +5,7 @@ pub mod common; pub mod config; pub mod dash_interface; pub mod dash_interface_emulated; +pub mod desktop_finder; mod handle; pub mod overlays; pub mod timestep; diff --git a/wlx-common/src/overlays.rs b/wlx-common/src/overlays.rs index 1b82d44..633d2be 100644 --- a/wlx-common/src/overlays.rs +++ b/wlx-common/src/overlays.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use idmap_derive::IntegerId; use serde::{Deserialize, Serialize}; @@ -21,12 +23,15 @@ pub enum ToastDisplayMethod { pub enum BackendAttrib { Stereo, MouseTransform, + Icon, } #[derive(Debug, Clone, Serialize, Deserialize)] pub enum BackendAttribValue { Stereo(StereoMode), MouseTransform(MouseTransform), + #[serde(skip_serializing, skip_deserializing)] + Icon(Arc), } #[derive(Default, Debug, Clone, Copy, Serialize, Deserialize)] diff --git a/wlx-overlay-s/src/assets/gui/keyboard.xml b/wlx-overlay-s/src/assets/gui/keyboard.xml index b692fb3..22873d2 100644 --- a/wlx-overlay-s/src/assets/gui/keyboard.xml +++ b/wlx-overlay-s/src/assets/gui/keyboard.xml @@ -88,14 +88,14 @@