This commit is contained in:
Aleksander 2026-05-12 21:59:54 +02:00
parent 5cf7b986f3
commit 20743f91eb
30 changed files with 126 additions and 165 deletions

View File

@ -11,7 +11,6 @@ use wgui::{
globals::WguiGlobals, globals::WguiGlobals,
layout::{WidgetID, WidgetPair}, layout::{WidgetID, WidgetPair},
parser::{Fetchable, ParseDocumentParams, ParserState}, parser::{Fetchable, ParseDocumentParams, ParserState},
task::Tasks,
}; };
use wlx_common::desktop_finder::DesktopEntry; use wlx_common::desktop_finder::DesktopEntry;
@ -22,9 +21,6 @@ use crate::{
views::{self}, views::{self},
}; };
#[derive(Clone)]
enum Task {}
struct State { struct State {
view_launcher: PopupHolder<views::app_launcher::View>, view_launcher: PopupHolder<views::app_launcher::View>,
} }
@ -35,7 +31,6 @@ pub struct TabApps<T> {
state: Rc<RefCell<State>>, state: Rc<RefCell<State>>,
app_list: AppList, app_list: AppList,
tasks: Tasks<Task>,
marker: PhantomData<T>, marker: PhantomData<T>,
} }
@ -47,10 +42,6 @@ impl<T> Tab<T> for TabApps<T> {
fn update(&mut self, frontend: &mut Frontend<T>, _time_ms: u32, data: &mut T) -> anyhow::Result<()> { fn update(&mut self, frontend: &mut Frontend<T>, _time_ms: u32, data: &mut T) -> anyhow::Result<()> {
let state = self.state.borrow_mut(); let state = self.state.borrow_mut();
for task in self.tasks.drain() {
match task {}
}
self.app_list.tick(frontend, &self.state, &mut self.parser_state)?; self.app_list.tick(frontend, &self.state, &mut self.parser_state)?;
state state
@ -96,7 +87,6 @@ fn doc_params(globals: WguiGlobals) -> ParseDocumentParams<'static> {
impl<T> TabApps<T> { impl<T> TabApps<T> {
pub fn new(frontend: &mut Frontend<T>, parent_id: WidgetID, data: &mut T) -> anyhow::Result<Self> { pub fn new(frontend: &mut Frontend<T>, parent_id: WidgetID, data: &mut T) -> anyhow::Result<Self> {
let globals = frontend.layout.state.globals.clone(); let globals = frontend.layout.state.globals.clone();
let tasks = Tasks::new();
let state = Rc::new(RefCell::new(State { let state = Rc::new(RefCell::new(State {
view_launcher: Default::default(), view_launcher: Default::default(),
})); }));
@ -127,7 +117,6 @@ impl<T> TabApps<T> {
app_list, app_list,
parser_state, parser_state,
state, state,
tasks,
marker: PhantomData, marker: PhantomData,
}) })
} }

View File

@ -333,12 +333,12 @@ impl SubtabGeneralSettings {
} }
}) })
} }
slider_keying_curve.on_value_changed(get_slider_callback(&tasks)); slider_keying_curve.on_value_changed(get_slider_callback(tasks));
slider_keying_despill.on_value_changed(get_slider_callback(&tasks)); slider_keying_despill.on_value_changed(get_slider_callback(tasks));
slider_keying_hue_range.on_value_changed(get_slider_callback(&tasks)); slider_keying_hue_range.on_value_changed(get_slider_callback(tasks));
slider_keying_saturation_range.on_value_changed(get_slider_callback(&tasks)); slider_keying_saturation_range.on_value_changed(get_slider_callback(tasks));
slider_keying_value_range.on_value_changed(get_slider_callback(&tasks)); slider_keying_value_range.on_value_changed(get_slider_callback(tasks));
cs_keying.on_changed(get_color_selector_callback(&tasks)); cs_keying.on_changed(get_color_selector_callback(tasks));
} }
Ok(Self { Ok(Self {

View File

@ -220,7 +220,7 @@ impl<T> Tab<T> for TabSettings<T> {
let mut common = frontend.layout.common(); let mut common = frontend.layout.common();
let mut label = self let mut label = self
.state .state
.fetch_widget_as::<WidgetLabel>(&common.state, &format!("{id}_value"))?; .fetch_widget_as::<WidgetLabel>(common.state, &format!("{id}_value"))?;
let translation = Translation { let translation = Translation {
text: text.into(), text: text.into(),

View File

@ -19,7 +19,7 @@ pub struct HttpClientResponse {
} }
impl HttpClientResponse { impl HttpClientResponse {
pub fn as_json<T>(self) -> anyhow::Result<T> pub fn into_json<T>(self) -> anyhow::Result<T>
where where
T: for<'a> serde::Deserialize<'a>, T: for<'a> serde::Deserialize<'a>,
{ {
@ -66,12 +66,11 @@ pub async fn get(params: GetParams<'_>) -> anyhow::Result<HttpClientResponse> {
let (parts, body) = resp.into_parts(); let (parts, body) = resp.into_parts();
// that's a pretty interesting way to get file size :] // that's a pretty interesting way to get file size :]
if let Some(val) = parts.headers.get("Content-Length") { if let Some(val) = parts.headers.get("Content-Length")
if let Ok(str) = val.to_str() { && let Ok(str) = val.to_str()
if let Ok(s) = str.parse() { && let Ok(s) = str.parse()
file_size = s; {
} file_size = s;
}
} }
let mut on_progress = params.on_progress; let mut on_progress = params.on_progress;

View File

@ -2,5 +2,5 @@ pub mod http_client;
pub mod image_fetch; pub mod image_fetch;
pub mod skymap_catalog; pub mod skymap_catalog;
// pub const WAYVR_ROOT_URL: &'static str = "https://wayvr.org"; // pub const WAYVR_ROOT_URL: &str = "https://wayvr.org";
pub const WAYVR_SKYMAPS_ROOT: &'static str = "https://wayvr.org/skymaps"; pub const WAYVR_SKYMAPS_ROOT: &str = "https://wayvr.org/skymaps";

View File

@ -67,10 +67,7 @@ impl SkymapCatalogEntryFiles {
// example result: "https://wayvr.org/skymaps/files/my_skymap_8k.dds" // example result: "https://wayvr.org/skymaps/files/my_skymap_8k.dds"
pub fn get_url_from_res(&self, res: SkymapResolution) -> Option<String> { pub fn get_url_from_res(&self, res: SkymapResolution) -> Option<String> {
let Some(filename) = self.get_filename_from_res(res) else { let filename = self.get_filename_from_res(res)?;
return None;
};
Some(format!("{}/files/{}", WAYVR_SKYMAPS_ROOT, filename)) Some(format!("{}/files/{}", WAYVR_SKYMAPS_ROOT, filename))
} }
@ -102,10 +99,7 @@ pub struct SkymapCatalogEntry {
impl SkymapCatalogEntry { impl SkymapCatalogEntry {
pub fn get_destination_path(&self, resolution: SkymapResolution) -> Option<PathBuf> { pub fn get_destination_path(&self, resolution: SkymapResolution) -> Option<PathBuf> {
let Some(filename) = self.files.get_filename_from_res(resolution) else { let filename = self.files.get_filename_from_res(resolution)?;
return None;
};
Some(config_io::get_skymaps_root().join(filename)) Some(config_io::get_skymaps_root().join(filename))
} }
@ -170,7 +164,7 @@ pub async fn request_catalog(executor: &AsyncExecutor) -> anyhow::Result<SkymapC
log::info!("Fetching skymap list"); log::info!("Fetching skymap list");
let res = http_client::get_simple(executor, &format!("{}/catalog.json", networking::WAYVR_SKYMAPS_ROOT)).await?; let res = http_client::get_simple(executor, &format!("{}/catalog.json", networking::WAYVR_SKYMAPS_ROOT)).await?;
let catalog = res.as_json::<SkymapCatalog>()?; let catalog = res.into_json::<SkymapCatalog>()?;
catalog.validate()?; catalog.validate()?;
Ok(catalog) Ok(catalog)

View File

@ -135,11 +135,7 @@ impl<ViewType: ViewTrait> PopupHolder<ViewType> {
F: FnOnce(&mut ViewType) -> R, F: FnOnce(&mut ViewType) -> R,
{ {
let mut state = self.state.borrow_mut(); let mut state = self.state.borrow_mut();
if let Some(view) = state.view.as_mut() { state.view.as_mut().map(f)
Some(f(view))
} else {
None
}
} }
// Same as with_view, but the closure expects a simple anyhow::Result<()> type // Same as with_view, but the closure expects a simple anyhow::Result<()> type
@ -190,20 +186,18 @@ pub struct PopupContentFuncData<'a> {
} }
type PopupClosedCallback = Box<dyn FnOnce()>; type PopupClosedCallback = Box<dyn FnOnce()>;
type OnContentCallback = Box<dyn FnOnce(PopupContentFuncData) -> anyhow::Result<PopupClosedCallback>>;
// we need to implement Clone here, but the underlying function can be called only once. // we need to implement Clone here, but the underlying function can be called only once.
// on_content will be cleared after the first call // on_content will be cleared after the first call
#[derive(Clone)] #[derive(Clone)]
pub struct MountPopupOnceParams { pub struct MountPopupOnceParams {
title: Translation, title: Translation,
on_content: Rc<RefCell<Option<Box<dyn FnOnce(PopupContentFuncData) -> anyhow::Result<PopupClosedCallback>>>>>, on_content: Rc<RefCell<Option<OnContentCallback>>>,
} }
impl MountPopupOnceParams { impl MountPopupOnceParams {
pub fn new( pub fn new(title: Translation, on_content: OnContentCallback) -> Self {
title: Translation,
on_content: Box<dyn FnOnce(PopupContentFuncData) -> anyhow::Result<PopupClosedCallback>>,
) -> Self {
Self { Self {
title, title,
on_content: Rc::new(RefCell::new(Some(on_content))), on_content: Rc::new(RefCell::new(Some(on_content))),
@ -313,15 +307,14 @@ impl PopupManager {
but_back.on_click({ but_back.on_click({
let popup_handle = Rc::downgrade(&popup_handle.state); let popup_handle = Rc::downgrade(&popup_handle.state);
Rc::new(move |_common, _evt| { Rc::new(move |_common, _evt| {
if let Some(popup_handle) = popup_handle.upgrade() { if let Some(popup_handle) = popup_handle.upgrade()
if let Some(closed_callback) = { && let Some(closed_callback) = {
let mut state = popup_handle.borrow_mut(); let mut state = popup_handle.borrow_mut();
state.mounted_popup = None; // will call Drop state.mounted_popup = None; // will call Drop
state.closed_callback.take() state.closed_callback.take()
} { } {
log::debug!("closed_callback called"); log::debug!("closed_callback called");
closed_callback(); closed_callback();
}
} }
Ok(()) Ok(())
}) })

View File

@ -97,9 +97,9 @@ pub fn create_icon(layout: &mut Layout, id_parent: WidgetID, size: Vec2, path: A
id_parent, id_parent,
widget_sprite, widget_sprite,
taffy::Style { taffy::Style {
min_size: size.clone(), min_size: size,
max_size: size.clone(), max_size: size,
size: size.clone(), size,
..Default::default() ..Default::default()
}, },
)?; )?;

View File

@ -158,7 +158,7 @@ impl View {
wgui_simple::create_loading(wgui_simple::CreateLoadingParams { wgui_simple::create_loading(wgui_simple::CreateLoadingParams {
parent_id: id_loading_parent, parent_id: id_loading_parent,
layout: layout, layout,
with_text: false, with_text: false,
})?; })?;

View File

@ -59,12 +59,12 @@ impl ViewTrait for View {
} }
for task in tasks { for task in tasks {
match task { match task {
Task::FillAppDetails(details) => self.action_fill_app_details(&mut par.layout, details)?, Task::FillAppDetails(details) => self.action_fill_app_details(par.layout, details)?,
Task::Launch => self.action_launch(), Task::Launch => self.action_launch(),
Task::SetCoverArt(cover_art) => { Task::SetCoverArt(cover_art) => {
let _ = self let _ = self
.view_cover .view_cover
.set_cover_art(&mut self.game_cover_view_common, &mut par.layout, &cover_art); .set_cover_art(&mut self.game_cover_view_common, par.layout, &cover_art);
} }
} }
} }
@ -145,8 +145,8 @@ impl View {
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
{ {
let mut c = layout.common(); let mut c = layout.common();
let label_author = self.state.fetch_widget(&c.state, "label_author")?.widget; let label_author = self.state.fetch_widget(c.state, "label_author")?.widget;
let label_description = self.state.fetch_widget(&c.state, "label_description")?.widget; let label_description = self.state.fetch_widget(c.state, "label_description")?.widget;
if let Some(developer) = details.developers.pop() { if let Some(developer) = details.developers.pop() {
label_author label_author

View File

@ -78,9 +78,9 @@ impl ViewTrait for View {
for task in tasks { for task in tasks {
match task { match task {
Task::LoadManifests => self.load_manifests(), Task::LoadManifests => self.load_manifests(),
Task::FillPage(page_idx) => self.fill_page(&mut par.layout, &mut par.executor, page_idx)?, Task::FillPage(page_idx) => self.fill_page(par.layout, par.executor, page_idx)?,
Task::AppManifestClicked(manifest) => self.action_app_manifest_clicked(manifest)?, Task::AppManifestClicked(manifest) => self.action_app_manifest_clicked(manifest)?,
Task::SetCoverArt(app_id, cover_art) => self.set_cover_art(&mut par.layout, app_id, cover_art), Task::SetCoverArt(app_id, cover_art) => self.set_cover_art(par.layout, app_id, cover_art),
Task::PrevPage => self.page_prev(), Task::PrevPage => self.page_prev(),
Task::NextPage => self.page_next(), Task::NextPage => self.page_next(),
} }

View File

@ -144,7 +144,7 @@ impl View {
pub fn new(par: Params) -> anyhow::Result<Self> { pub fn new(par: Params) -> anyhow::Result<Self> {
let tasks = Tasks::<Task>::new(); let tasks = Tasks::<Task>::new();
let parser_state = wgui::parser::parse_from_assets(&doc_params(&par.globals), par.layout, par.parent_id)?; let parser_state = wgui::parser::parse_from_assets(&doc_params(par.globals), par.layout, par.parent_id)?;
let id_resolution_buttons = parser_state.get_widget_id("resolution_buttons")?; let id_resolution_buttons = parser_state.get_widget_id("resolution_buttons")?;
let str_version = par.globals.i18n().translate("VERSION"); let str_version = par.globals.i18n().translate("VERSION");
@ -249,9 +249,9 @@ impl View {
} }
fn show_dialog_box_action(&mut self, resolution: SkymapResolution) -> anyhow::Result<()> { fn show_dialog_box_action(&mut self, resolution: SkymapResolution) -> anyhow::Result<()> {
const ACTION_REMOVE: &'static str = "remove"; const ACTION_REMOVE: &str = "remove";
const ACTION_DOWNLOAD_AGAIN: &'static str = "download_again"; const ACTION_DOWNLOAD_AGAIN: &str = "download_again";
const ACTION_APPLY: &'static str = "apply"; const ACTION_APPLY: &str = "apply";
let tasks = self.tasks.clone(); let tasks = self.tasks.clone();
@ -362,6 +362,7 @@ impl View {
} }
} }
#[allow(clippy::too_many_arguments)]
pub fn mount_popup( pub fn mount_popup(
frontend_tasks: FrontendTasks, frontend_tasks: FrontendTasks,
executor: AsyncExecutor, executor: AsyncExecutor,

View File

@ -34,18 +34,12 @@ pub struct Params<'a> {
pub on_updated_library: Rc<dyn Fn()>, pub on_updated_library: Rc<dyn Fn()>,
} }
type SetSkymapPreview = (Uuid, Option<(CustomGlyphData, Rc<Vec<u8>>)>);
#[derive(Clone)] #[derive(Clone)]
enum Task { enum Task {
SetSkymapCatalog(Rc<anyhow::Result<networking::skymap_catalog::SkymapCatalog>>), SetSkymapCatalog(Rc<anyhow::Result<networking::skymap_catalog::SkymapCatalog>>),
SetSkymapPreview( SetSkymapPreview(SetSkymapPreview),
(
SkymapUuid,
Option<(
CustomGlyphData, /* ready-to-use preview image data */
Rc<Vec<u8>>, /* compressed preview image data (should weigh about 10-15 KiB) */
)>,
),
),
ShowRemoteSkymapDownloader(SkymapUuid), ShowRemoteSkymapDownloader(SkymapUuid),
RefreshCells, RefreshCells,
} }
@ -70,9 +64,7 @@ pub struct View {
} }
fn get_entry_by_uuid(catalog: &SkymapCatalog, skymap_uuid: Uuid) -> Option<&SkymapCatalogEntry> { fn get_entry_by_uuid(catalog: &SkymapCatalog, skymap_uuid: Uuid) -> Option<&SkymapCatalogEntry> {
let Some(entry) = catalog.entries.iter().find(|entry| entry.uuid == skymap_uuid) else { let entry = catalog.entries.iter().find(|entry| entry.uuid == skymap_uuid)?;
return None;
};
Some(entry) Some(entry)
} }
@ -176,7 +168,7 @@ impl View {
}; };
for cell in &mut self.mounted_cells { for cell in &mut self.mounted_cells {
if let Some(entry) = get_entry_by_uuid(&catalog, cell.skymap_uuid) { if let Some(entry) = get_entry_by_uuid(catalog, cell.skymap_uuid) {
cell.view.refresh_resolution_pips(layout, entry)?; cell.view.refresh_resolution_pips(layout, entry)?;
} }
} }
@ -195,7 +187,7 @@ impl View {
extra: Default::default(), extra: Default::default(),
}; };
let parser_state = wgui::parser::parse_from_assets(&doc_params, layout, self.id_parent)?; let parser_state = wgui::parser::parse_from_assets(doc_params, layout, self.id_parent)?;
let id_list = parser_state.fetch_widget(&layout.state, "list")?.id; let id_list = parser_state.fetch_widget(&layout.state, "list")?.id;
@ -207,11 +199,11 @@ impl View {
self.tasks.clone(), self.tasks.clone(),
); );
let skymap_uuid = entry.uuid.clone(); let skymap_uuid = entry.uuid;
self.mounted_cells.push(MountedCell { self.mounted_cells.push(MountedCell {
preview_image_compressed: None, preview_image_compressed: None,
skymap_uuid: entry.uuid.clone(), skymap_uuid: entry.uuid,
view: views::skymap_list_cell::View::new(views::skymap_list_cell::Params { view: views::skymap_list_cell::View::new(views::skymap_list_cell::Params {
id_parent: id_list, id_parent: id_list,
layout, layout,
@ -240,7 +232,7 @@ impl View {
return Ok(()); return Ok(());
}; };
let Some(entry) = get_entry_by_uuid(&catalog, uuid) else { let Some(entry) = get_entry_by_uuid(catalog, uuid) else {
return Ok(()); return Ok(());
}; };
@ -273,13 +265,8 @@ impl View {
skymap_uuid: SkymapUuid, skymap_uuid: SkymapUuid,
) -> Option<(CustomGlyphData, Rc<Vec<u8>> /* preview_image_compressed */)> { ) -> Option<(CustomGlyphData, Rc<Vec<u8>> /* preview_image_compressed */)> {
if let Some(cell) = &self.mounted_cells.iter().find(|mc| mc.skymap_uuid == skymap_uuid) { if let Some(cell) = &self.mounted_cells.iter().find(|mc| mc.skymap_uuid == skymap_uuid) {
let Some(image) = cell.view.get_image() else { let image = cell.view.get_image()?;
return None; let preview_image_compressed = cell.preview_image_compressed.clone()?;
};
let Some(preview_image_compressed) = cell.preview_image_compressed.clone() else {
return None;
};
return Some((image, preview_image_compressed)); return Some((image, preview_image_compressed));
} }
None None

View File

@ -66,10 +66,10 @@ impl ViewTrait for View {
for task in tasks { for task in tasks {
match task { match task {
Task::DownloadSkymaps => { Task::DownloadSkymaps => {
self.download_skymaps(&par.executor)?; self.download_skymaps(par.executor)?;
} }
Task::Refresh => { Task::Refresh => {
self.refresh(&mut par.layout)?; self.refresh(par.layout)?;
} }
Task::ShowSkymapResolutionSelector(entry) => { Task::ShowSkymapResolutionSelector(entry) => {
self.show_skymap_resolution_selector(entry); self.show_skymap_resolution_selector(entry);
@ -236,10 +236,10 @@ impl View {
})?; })?;
// load preview image // load preview image
if let Ok(data) = std::fs::read(skymaps_root.join(&entry.files.preview)) { if let Ok(data) = std::fs::read(skymaps_root.join(&entry.files.preview))
if let Ok(glyph_data) = CustomGlyphData::from_bytes_raster(&self.globals, &entry.files.preview, &data) { && let Ok(glyph_data) = CustomGlyphData::from_bytes_raster(&self.globals, &entry.files.preview, &data)
view.set_image(layout, Some(glyph_data))?; {
} view.set_image(layout, Some(glyph_data))?;
} }
self.cells.push(Cell { view }); self.cells.push(Cell { view });

View File

@ -146,7 +146,7 @@ impl View {
} }
pub fn refresh_resolution_pips(&mut self, layout: &mut Layout, entry: &SkymapCatalogEntry) -> anyhow::Result<()> { pub fn refresh_resolution_pips(&mut self, layout: &mut Layout, entry: &SkymapCatalogEntry) -> anyhow::Result<()> {
populate_res_pips(layout, self.id_resolution_pips, &mut self.parser_state, &entry)?; populate_res_pips(layout, self.id_resolution_pips, &mut self.parser_state, entry)?;
Ok(()) Ok(())
} }
@ -163,6 +163,6 @@ impl View {
} }
pub fn get_image(&self) -> Option<CustomGlyphData> { pub fn get_image(&self) -> Option<CustomGlyphData> {
return self.image.clone(); self.image.clone()
} }
} }

View File

@ -30,7 +30,7 @@ impl PlayspaceMover {
Err(MndResult::ErrorInvalidVersion) Err(MndResult::ErrorInvalidVersion)
) { ) {
anyhow::bail!("Space offsets not supported."); anyhow::bail!("Space offsets not supported.");
}; }
Ok(Self { Ok(Self {
drag: None, drag: None,

View File

@ -23,6 +23,7 @@ use super::{
swapchain::{WlxSwapchain, create_swapchain}, swapchain::{WlxSwapchain, create_swapchain},
}; };
#[allow(clippy::struct_field_names)]
pub(super) struct Skybox { pub(super) struct Skybox {
view: Option<Arc<ImageView>>, view: Option<Arc<ImageView>>,
sky: Option<WlxSwapchain>, sky: Option<WlxSwapchain>,
@ -126,8 +127,7 @@ impl Skybox {
let extent = self let extent = self
.view .view
.as_ref() .as_ref()
.map(|v| v.extent_u32arr()) .map_or([4096, 4096], ExtentExt::extent_u32arr);
.unwrap_or([4096, 4096]);
let mut swapchain = create_swapchain(xr, app.gfx.clone(), extent, 1, opts)?; let mut swapchain = create_swapchain(xr, app.gfx.clone(), extent, 1, opts)?;
let tgt = swapchain let tgt = swapchain

View File

@ -48,7 +48,7 @@ where
panic!("No usable config found."); panic!("No usable config found.");
} }
const SUPPORTED_EXTESIONS: [&'static str; 4] = ["yaml", "yml", "json", "json5"]; const SUPPORTED_EXTESIONS: [&str; 4] = ["yaml", "yml", "json", "json5"];
fn is_supported_config_file(path: &Path) -> bool { fn is_supported_config_file(path: &Path) -> bool {
if path.is_dir() { if path.is_dir() {

View File

@ -498,7 +498,7 @@ pub fn apply_custom_command<T>(
ModifyPanelCommand::SetText(text) => { ModifyPanelCommand::SetText(text) => {
if let Ok(mut label) = panel if let Ok(mut label) = panel
.parser_state .parser_state
.fetch_widget_as::<WidgetLabel>(&com.state, element) .fetch_widget_as::<WidgetLabel>(com.state, element)
{ {
label.set_text(&mut com, Translation::from_raw_text(text)); label.set_text(&mut com, Translation::from_raw_text(text));
} else if let Ok(button) = panel } else if let Ok(button) = panel
@ -511,7 +511,7 @@ pub fn apply_custom_command<T>(
} }
} }
ModifyPanelCommand::SetImage(path) => { ModifyPanelCommand::SetImage(path) => {
if let Ok(pair) = panel.parser_state.fetch_widget(&com.state, element) { if let Ok(pair) = panel.parser_state.fetch_widget(com.state, element) {
let data = CustomGlyphData::from_assets( let data = CustomGlyphData::from_assets(
&app.wgui_globals, &app.wgui_globals,
wgui::assets::AssetPath::File(path), wgui::assets::AssetPath::File(path),
@ -533,7 +533,7 @@ pub fn apply_custom_command<T>(
let color = parse_color_hex(color) let color = parse_color_hex(color)
.context("Invalid color format, must be a html hex color!")?; .context("Invalid color format, must be a html hex color!")?;
if let Ok(pair) = panel.parser_state.fetch_widget(&com.state, element) { if let Ok(pair) = panel.parser_state.fetch_widget(com.state, element) {
if let Some(mut rect) = pair.widget.get_as::<WidgetRectangle>() { if let Some(mut rect) = pair.widget.get_as::<WidgetRectangle>() {
rect.set_color(&mut com, color); rect.set_color(&mut com, color);
} else if let Some(mut label) = pair.widget.get_as::<WidgetLabel>() { } else if let Some(mut label) = pair.widget.get_as::<WidgetLabel>() {

View File

@ -49,19 +49,19 @@ fn read_check(expected_size: u32, res: std::io::Result<usize>) -> anyhow::Result
anyhow::bail!("End of stream"); anyhow::bail!("End of stream");
} }
if count as u32 == expected_size { if count as u32 == expected_size {
return Ok(true); // read succeeded Ok(true) // read succeeded
} else { } else {
log::error!("count {count} is not {expected_size}"); log::error!("count {count} is not {expected_size}");
return Ok(false); Ok(false)
} }
} }
Err(e) => match e.kind() { Err(e) => match e.kind() {
std::io::ErrorKind::WouldBlock => { std::io::ErrorKind::WouldBlock => {
// no incoming data (this socket is non-blocking), try again later // no incoming data (this socket is non-blocking), try again later
return Ok(false); Ok(false)
} }
_ => { _ => {
anyhow::bail!("Connection error: {:?}", e); anyhow::bail!("Connection error: {e:?}");
} }
}, },
} }
@ -500,7 +500,7 @@ impl Connection {
} }
} }
Err(e) => { Err(e) => {
log::debug!("Disconnecting client: {:?}", e); log::debug!("Disconnecting client: {e:?}");
self.alive = false; self.alive = false;
break; break;
} }

View File

@ -74,7 +74,7 @@ impl DashFrontend {
let mut interface = DashInterfaceLive::new(); let mut interface = DashInterfaceLive::new();
if app.session.no_autostart { if app.session.no_autostart {
log::info!("Not starting apps due to --no-autostart") log::info!("Not starting apps due to --no-autostart");
} else { } else {
for p in app.session.config.autostart_apps.clone() { for p in app.session.config.autostart_apps.clone() {
let _ = interface.process_launch(app, false, p); let _ = interface.process_launch(app, false, p);

View File

@ -154,7 +154,6 @@ impl AppState {
desktop_finder.refresh(); desktop_finder.refresh();
let lang_provider = WayVRLangProvider::from_config(&session.config); let lang_provider = WayVRLangProvider::from_config(&session.config);
let executor = Rc::new(smol::LocalExecutor::new());
let mut app_state = Self { let mut app_state = Self {
session, session,

View File

@ -25,6 +25,14 @@ mod x11;
pub static USE_UINPUT: AtomicBool = AtomicBool::new(true); pub static USE_UINPUT: AtomicBool = AtomicBool::new(true);
pub(super) fn initialize() -> Result<UInputProvider, Toast> { pub(super) fn initialize() -> Result<UInputProvider, Toast> {
const CHECK_UINPUT_MESSAGE: &str =
"Could not create uinput provider. Keyboard/Mouse input will not work!
Check if the uinput kernel module is loaded: lsmod | grep uinput
- If not loaded, follow your distro's instructions to load the uinput kernel module.
Check if you're in input group, run: id -nG";
if !USE_UINPUT.load(std::sync::atomic::Ordering::Relaxed) { if !USE_UINPUT.load(std::sync::atomic::Ordering::Relaxed) {
const UINPUT_DISABLED: &str = "Uinput disabled by user."; const UINPUT_DISABLED: &str = "Uinput disabled by user.";
log::info!("{UINPUT_DISABLED}"); log::info!("{UINPUT_DISABLED}");
@ -40,13 +48,6 @@ pub(super) fn initialize() -> Result<UInputProvider, Toast> {
log::info!("Initialized uinput."); log::info!("Initialized uinput.");
return Ok(uinput); return Ok(uinput);
} }
const CHECK_UINPUT_MESSAGE: &str =
"Could not create uinput provider. Keyboard/Mouse input will not work!
Check if the uinput kernel module is loaded: lsmod | grep uinput
- If not loaded, follow your distro's instructions to load the uinput kernel module.
Check if you're in input group, run: id -nG";
let mut full_uinput_error = String::from(CHECK_UINPUT_MESSAGE); let mut full_uinput_error = String::from(CHECK_UINPUT_MESSAGE);
if let Ok(user) = std::env::var("USER") { if let Ok(user) = std::env::var("USER") {
let check_group_message = format!( let check_group_message = format!(

View File

@ -46,6 +46,7 @@ struct PopupState {
id_rect_color: WidgetID, id_rect_color: WidgetID,
} }
#[allow(clippy::struct_field_names)]
struct State { struct State {
color: drawing::Color, color: drawing::Color,
self_ref: Weak<ComponentColorSelector>, self_ref: Weak<ComponentColorSelector>,
@ -83,16 +84,16 @@ impl ComponentTrait for ComponentColorSelector {
fn refresh(&self, data: &mut RefreshData) { fn refresh(&self, data: &mut RefreshData) {
let mut state = self.state.borrow_mut(); let mut state = self.state.borrow_mut();
if let Some(wants_open) = state.wants_open.take() { if let Some(wants_open) = state.wants_open.take()
if let Err(e) = self.open(data.layout, &mut state, wants_open.position) { && let Err(e) = self.open(data.layout, &mut state, wants_open.position)
log::error!("{:?}", e); {
debug_assert!(false); log::error!("{e:?}");
} debug_assert!(false);
} }
self.data.button.set_text( self.data.button.set_text(
&mut data.layout.common(), &mut data.layout.common(),
Translation::from_raw_text_string(format!("{}", state.color.to_hex_rgb())), Translation::from_raw_text_string(state.color.to_hex_rgb()),
); );
self.data.button.set_color(&mut data.layout.common(), state.color); self.data.button.set_color(&mut data.layout.common(), state.color);
@ -111,7 +112,7 @@ fn set_color_internal(state: &mut State, common: &mut CallbackDataCommon, color:
} }
if let Some(on_changed) = &state.on_changed { if let Some(on_changed) = &state.on_changed {
on_changed(common, ColorSelectorChangedEvent { color }) on_changed(common, ColorSelectorChangedEvent { color });
} }
state.color = color; state.color = color;
@ -148,7 +149,7 @@ impl ComponentColorSelector {
let id_content = self.window.get_content().id; let id_content = self.window.get_content().id;
let parser_state = parser::parse_from_assets( let parser_state = parser::parse_from_assets(
&mut ParseDocumentParams { &ParseDocumentParams {
globals: layout.state.globals.clone(), globals: layout.state.globals.clone(),
path: AssetPath::WguiInternal("wgui/color_selector.xml"), path: AssetPath::WguiInternal("wgui/color_selector.xml"),
extra: Default::default(), extra: Default::default(),

View File

@ -40,7 +40,7 @@ pub struct Limits {
} }
impl Value { impl Value {
pub fn get(&self) -> f32 { pub const fn get(&self) -> f32 {
self.0 self.0
} }
@ -113,6 +113,7 @@ impl TooltipTrait for State {
} }
} }
#[allow(clippy::struct_field_names)]
struct SliderHandleData { struct SliderHandleData {
id_handle_rect: WidgetID, // Rectangle id_handle_rect: WidgetID, // Rectangle
id_text: Option<WidgetID>, // Text id_text: Option<WidgetID>, // Text
@ -146,7 +147,7 @@ impl ComponentTrait for ComponentSlider {
let value1 = state.value1.get(); let value1 = state.value1.get();
state.set_value(&mut common, &self.data, ValueIndex::Primary, value1); state.set_value(&mut common, &self.data, ValueIndex::Primary, value1);
if let Some(value2) = state.value2.as_ref().map(|v| v.get()) { if let Some(value2) = state.value2.as_ref().map(Value::get) {
state.set_value(&mut common, &self.data, ValueIndex::Secondary, value2); state.set_value(&mut common, &self.data, ValueIndex::Secondary, value2);
} }
} }
@ -169,7 +170,7 @@ impl ComponentSlider {
let state = self.state.borrow(); let state = self.state.borrow();
match index { match index {
ValueIndex::Primary => Some(state.value1.get()), ValueIndex::Primary => Some(state.value1.get()),
ValueIndex::Secondary => state.value2.as_ref().map(|v| v.get()), ValueIndex::Secondary => state.value2.as_ref().map(Value::get),
} }
} }
@ -231,7 +232,7 @@ const HANDLE_WIDTH: f32 = 32.0;
const HANDLE_HEIGHT: f32 = 24.0; const HANDLE_HEIGHT: f32 = 24.0;
impl State { impl State {
fn get_hovered_index(&self) -> Option<ValueIndex> { const fn get_hovered_index(&self) -> Option<ValueIndex> {
if self.hovered1 { if self.hovered1 {
Some(ValueIndex::Primary) Some(ValueIndex::Primary)
} else if self.hovered2 { } else if self.hovered2 {
@ -336,10 +337,10 @@ impl State {
on_value_changed( on_value_changed(
common, common,
SliderValueChangedEvent { SliderValueChangedEvent {
index: index, index,
value: value.get(), value: value.get(),
}, },
) );
} }
} }
} }
@ -447,17 +448,13 @@ fn update_handle_hovers(
let hovered1_prev = state.hovered1; let hovered1_prev = state.hovered1;
let hovered2_prev = state.hovered2; let hovered2_prev = state.hovered2;
if !state.hovered_body { if state.hovered_body {
state.hovered1 = false;
state.hovered2 = false;
} else {
let dist1 = get_handle_dist(common, &data.handle1, mouse_pos); let dist1 = get_handle_dist(common, &data.handle1, mouse_pos);
let dist2 = data let dist2 = data
.handle2 .handle2
.as_ref() .as_ref()
.map(|h| get_handle_dist(common, h, mouse_pos)) .map_or(f32::MAX, |h| get_handle_dist(common, h, mouse_pos));
.unwrap_or(std::f32::MAX);
state.hovered1 = dist1 <= MAX_HOVER_DIST; state.hovered1 = dist1 <= MAX_HOVER_DIST;
state.hovered2 = dist2 <= MAX_HOVER_DIST; state.hovered2 = dist2 <= MAX_HOVER_DIST;
@ -470,6 +467,9 @@ fn update_handle_hovers(
state.hovered1 = false; state.hovered1 = false;
} }
} }
} else {
state.hovered1 = false;
state.hovered2 = false;
} }
// hover state changed, run animations // hover state changed, run animations
@ -516,12 +516,12 @@ fn register_event_mouse_motion(
update_handle_hovers(common, &data, &mut state, anim_mult, pos_relative); update_handle_hovers(common, &data, &mut state, anim_mult, pos_relative);
if let Some(dragged_by) = &state.dragged_by { if let Some(dragged_by) = &state.dragged_by
if dragged_by.device == pos.device { && dragged_by.device == pos.device
let index = dragged_by.index; {
state.update_value_to_mouse(event_data, &data, common, index); let index = dragged_by.index;
return Ok(EventResult::Consumed); state.update_value_to_mouse(event_data, &data, common, index);
} return Ok(EventResult::Consumed);
} }
Ok(EventResult::Pass) Ok(EventResult::Pass)

View File

@ -207,6 +207,7 @@ pub struct HsvColor {
pub a: f32, pub a: f32,
} }
#[allow(clippy::many_single_char_names)]
impl HsvColor { impl HsvColor {
pub const fn new(h: f32, s: f32, v: f32, a: f32) -> Self { pub const fn new(h: f32, s: f32, v: f32, a: f32) -> Self {
Self { h, s, v, a } Self { h, s, v, a }

View File

@ -229,7 +229,7 @@ fn add_child_internal(
} }
impl Layout { impl Layout {
pub fn common(&mut self) -> CallbackDataCommon<'_> { pub const fn common(&mut self) -> CallbackDataCommon<'_> {
CallbackDataCommon { CallbackDataCommon {
alterables: &mut self.alterables, alterables: &mut self.alterables,
state: &self.state, state: &self.state,
@ -480,7 +480,7 @@ impl Layout {
Ok(()) Ok(())
} }
fn get_event_params<'a>( const fn get_event_params<'a>(
&'a self, &'a self,
l: &'a taffy::Layout, l: &'a taffy::Layout,
node_id: taffy::NodeId, node_id: taffy::NodeId,

View File

@ -69,7 +69,7 @@ pub fn parse_component_slider(
step, step,
}, },
value1: slider::Value(initial_value1), value1: slider::Value(initial_value1),
value2: initial_value2.map(|v| slider::Value(v)), value2: initial_value2.map(slider::Value),
show_value: show_value != 0, show_value: show_value != 0,
tooltip: tooltip.get_info(), tooltip: tooltip.get_info(),
}, },

View File

@ -225,7 +225,7 @@ impl ParserState {
/// but it keeps components data in this `ParserState` object for you. /// but it keeps components data in this `ParserState` object for you.
/// The result can be safely dropped, all required event listeners and components /// The result can be safely dropped, all required event listeners and components
/// will be kept intact in this `ParserState`. /// will be kept intact in this `ParserState`.
/// Resulting ParserData::components Vec will be left empty (they are moved into this `ParserState::data`) /// Resulting `ParserData::components` Vec will be left empty (they are moved into this `ParserState::data`)
pub fn realize_template( pub fn realize_template(
&mut self, &mut self,
doc_params: &ParseDocumentParams, doc_params: &ParseDocumentParams,
@ -245,7 +245,7 @@ impl ParserState {
/// Semi-internal - This function is suitable in cases if you don't want to pollute /// Semi-internal - This function is suitable in cases if you don't want to pollute
/// the main parser state state with dynamic IDs (this won't propagate components!) /// the main parser state state with dynamic IDs (this won't propagate components!)
/// Use `realize_template` (or in some rare cases: `instantiate_template`) instead unless you want to handle `components` results yourself. /// Use `realize_template` (or in some rare cases: `instantiate_template`) instead unless you want to handle `components` results yourself.
/// Make sure not to drop resulting ParserData if you want to have your listener handles valid /// Make sure not to drop resulting `ParserData` if you want to have your listener handles valid
/// (they are contained in components). Use `realize_template` instead if you don't want to think about it. /// (they are contained in components). Use `realize_template` instead if you don't want to think about it.
pub fn parse_template_only( pub fn parse_template_only(
&self, &self,
@ -282,7 +282,7 @@ impl ParserState {
/// Parse named <template> tag and process it. /// Parse named <template> tag and process it.
/// Instantiate template by saving all the results into the main `ParserState`. /// Instantiate template by saving all the results into the main `ParserState`.
/// Be aware you this function will save ALL parsed IDs and other metadata /// Be aware you this function will save ALL parsed IDs and other metadata
/// into your main ParserState context (deep move). /// into your main `ParserState` context (deep move).
/// You shouldn't instantiate the same template twice, to prevent ID name clash. /// You shouldn't instantiate the same template twice, to prevent ID name clash.
/// Consider using `parse_template_only` or `realize_template` instead if you want /// Consider using `parse_template_only` or `realize_template` instead if you want
/// to instantiate more than a single template of the same type. /// to instantiate more than a single template of the same type.

View File

@ -220,10 +220,7 @@ pub enum EventResult {
impl EventResult { impl EventResult {
#[must_use] #[must_use]
pub const fn can_propagate(&self) -> bool { pub const fn can_propagate(&self) -> bool {
match &self { !matches!(self, EventResult::Consumed | EventResult::ConsumedExclusive)
EventResult::Consumed | EventResult::ConsumedExclusive => false,
_ => true,
}
} }
#[must_use] #[must_use]
@ -582,15 +579,14 @@ impl WidgetState {
} }
Event::MouseMotion(e) => { Event::MouseMotion(e) => {
if let Some(start_mouse_pos) = &self.data.press_down_start_mouse_pos { if let Some(start_mouse_pos) = &self.data.press_down_start_mouse_pos {
let (active_x, active_y) = get_scroll_active_axis(&params.style, &params.taffy_layout); let (active_x, active_y) = get_scroll_active_axis(params.style, params.taffy_layout);
if !self.data.swipe_running { if !self.data.swipe_running
if (active_x && (e.pos.x - start_mouse_pos.x).abs() >= SWIPE_START_THRESHOLD_UNITS) && ((active_x && (e.pos.x - start_mouse_pos.x).abs() >= SWIPE_START_THRESHOLD_UNITS)
|| (active_y && (e.pos.y - start_mouse_pos.y).abs() >= SWIPE_START_THRESHOLD_UNITS) || (active_y && (e.pos.y - start_mouse_pos.y).abs() >= SWIPE_START_THRESHOLD_UNITS))
{ {
self.data.swipe_running = true; self.data.swipe_running = true;
params.alterables.emit_global_event(Event::MouseCancel); params.alterables.emit_global_event(Event::MouseCancel);
}
} }
if self.data.swipe_running if self.data.swipe_running
@ -600,8 +596,8 @@ impl WidgetState {
let mult = scrollbar_info.get_potential_scroll_axis_multiplier(params.taffy_layout); let mult = scrollbar_info.get_potential_scroll_axis_multiplier(params.taffy_layout);
let scroll_diff_x = if mult.x != 0.0 { -mouse_diff.x / mult.x } else { 0.0 }; let scroll_diff_x = if mult.x == 0.0 { 0.0 } else { -mouse_diff.x / mult.x };
let scroll_diff_y = if mult.y != 0.0 { -mouse_diff.y / mult.y } else { 0.0 }; let scroll_diff_y = if mult.y == 0.0 { 0.0 } else { -mouse_diff.y / mult.y };
self.data.scrolling_target = self.data.swipe_scroll_start + Vec2::new(scroll_diff_x, scroll_diff_y); self.data.scrolling_target = self.data.swipe_scroll_start + Vec2::new(scroll_diff_x, scroll_diff_y);
params.alterables.mark_tick(self.obj.get_id()); params.alterables.mark_tick(self.obj.get_id());
@ -622,7 +618,7 @@ impl WidgetState {
}; };
// firstly, check if this widget is scrollable at all // firstly, check if this widget is scrollable at all
let (active_x, active_y) = get_scroll_active_axis(&params.style, &params.taffy_layout); let (active_x, active_y) = get_scroll_active_axis(params.style, params.taffy_layout);
if active_x || active_y { if active_x || active_y {
self.data.press_down_start_mouse_pos = Some(e.pos); self.data.press_down_start_mouse_pos = Some(e.pos);
self.data.swipe_scroll_start = self.data.scrolling_target; self.data.swipe_scroll_start = self.data.scrolling_target;