AppLauncher radio boxes
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -1439,6 +1439,7 @@ dependencies = [
|
|||||||
"serde_json",
|
"serde_json",
|
||||||
"smol",
|
"smol",
|
||||||
"smol-hyper",
|
"smol-hyper",
|
||||||
|
"strum",
|
||||||
"walkdir",
|
"walkdir",
|
||||||
"wayvr-ipc",
|
"wayvr-ipc",
|
||||||
"wgui",
|
"wgui",
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ rust-embed = "8.9.0"
|
|||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
serde_json = "1.0.145"
|
serde_json = "1.0.145"
|
||||||
slotmap = "1.1.1"
|
slotmap = "1.1.1"
|
||||||
|
strum = { version = "0.27.2", features = ["derive"] }
|
||||||
vulkano = { version = "0.35.2", default-features = false, features = [
|
vulkano = { version = "0.35.2", default-features = false, features = [
|
||||||
"macros",
|
"macros",
|
||||||
] }
|
] }
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ xdg.workspace = true
|
|||||||
rust-embed.workspace = true
|
rust-embed.workspace = true
|
||||||
serde = { workspace = true, features = ["rc"] }
|
serde = { workspace = true, features = ["rc"] }
|
||||||
serde_json.workspace = true
|
serde_json.workspace = true
|
||||||
|
strum.workspace = true
|
||||||
|
|
||||||
chrono = "0.4.42"
|
chrono = "0.4.42"
|
||||||
keyvalues-parser = { git = "https://github.com/CosmicHorrorDev/vdf-rs.git", rev = "fc6dcbea9eb13cacb98dea40063f6f56cde6e145" }
|
keyvalues-parser = { git = "https://github.com/CosmicHorrorDev/vdf-rs.git", rev = "fc6dcbea9eb13cacb98dea40063f6f56cde6e145" }
|
||||||
|
|||||||
@@ -23,9 +23,27 @@
|
|||||||
<Subtext title="Exec:" label_id="label_exec" />
|
<Subtext title="Exec:" label_id="label_exec" />
|
||||||
<Subtext title="Args:" label_id="label_args" />
|
<Subtext title="Args:" label_id="label_args" />
|
||||||
<Separator />
|
<Separator />
|
||||||
<CheckBox id="cb_cage_mode" text="Run in X11 mode (cage)" />
|
<RadioGroup id="radio_compositor" flex_direction="row" gap="16">
|
||||||
<CheckBox id="cb_wayland_mode" text="Run in Wayland mode" checked="1" />
|
<RadioBox text="Native mode" value="Native" checked="1" />
|
||||||
|
<RadioBox text="Compatibility mode" value="Cage"/> <!-- TODO: tooltips -->
|
||||||
|
</RadioGroup>
|
||||||
<Separator />
|
<Separator />
|
||||||
|
<Separator />
|
||||||
|
<label text="Resolution" />
|
||||||
|
<RadioGroup id="radio_res" flex_direction="row" gap="16">
|
||||||
|
<RadioBox text="1440p" value="Res1440" />
|
||||||
|
<RadioBox text="1080p" value="Res1080" checked="1" />
|
||||||
|
<RadioBox text="720p" value="Res720" />
|
||||||
|
<RadioBox text="480p" value="Res480" />
|
||||||
|
</RadioGroup>
|
||||||
|
<label text="Orientation" />
|
||||||
|
<RadioGroup id="radio_orientation" flex_direction="row" gap="16">
|
||||||
|
<RadioBox text="Wide" value="Wide" tooltip="16:9" checked="1" />
|
||||||
|
<RadioBox text="Semi-Wide" value="SemiWide" tooltip="3:2" />
|
||||||
|
<RadioBox text="Square" value="Square" tooltip="1:1" />
|
||||||
|
<RadioBox text="Semi-Tall" value="SemiTall" tooltip="2:3" />
|
||||||
|
<RadioBox text="Tall" value="Tall" tooltip="9:16" />
|
||||||
|
</RadioGroup>
|
||||||
<Button id="btn_launch" align_self="baseline" color="#44ce22FF" padding_top="4" padding_bottom="4" round="8" padding_right="12" min_height="40">
|
<Button id="btn_launch" align_self="baseline" color="#44ce22FF" padding_top="4" padding_bottom="4" round="8" padding_right="12" min_height="40">
|
||||||
<sprite src_builtin="dashboard/play.svg" width="32" height="32" />
|
<sprite src_builtin="dashboard/play.svg" width="32" height="32" />
|
||||||
<label text="Launch" weight="bold" size="17" shadow="#00000099" />
|
<label text="Launch" weight="bold" size="17" shadow="#00000099" />
|
||||||
@@ -33,4 +51,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</elements>
|
</elements>
|
||||||
</layout>
|
</layout>
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ impl<T> Tab<T> for TabApps<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some((_, launcher)) = &mut state.view_launcher {
|
if let Some((_, launcher)) = &mut state.view_launcher {
|
||||||
launcher.update(&mut frontend.layout, &mut frontend.interface, data)?;
|
launcher.update(&mut frontend.interface, data)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
use std::{collections::HashMap, rc::Rc};
|
use std::{collections::HashMap, rc::Rc, str::FromStr};
|
||||||
|
|
||||||
|
use strum::{AsRefStr, EnumString, VariantNames};
|
||||||
use wayvr_ipc::packet_client::WvrProcessLaunchParams;
|
use wayvr_ipc::packet_client::WvrProcessLaunchParams;
|
||||||
use wgui::{
|
use wgui::{
|
||||||
assets::AssetPath,
|
assets::AssetPath,
|
||||||
components::{button::ComponentButton, checkbox::ComponentCheckbox},
|
components::{button::ComponentButton, radio_group::ComponentRadioGroup},
|
||||||
globals::WguiGlobals,
|
globals::WguiGlobals,
|
||||||
i18n::Translation,
|
i18n::Translation,
|
||||||
layout::{Layout, WidgetID},
|
layout::{Layout, WidgetID},
|
||||||
@@ -19,21 +20,40 @@ use crate::{
|
|||||||
util::desktop_finder::DesktopEntry,
|
util::desktop_finder::DesktopEntry,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Eq, PartialEq)]
|
#[derive(Clone, Copy, Eq, PartialEq, EnumString, VariantNames, AsRefStr)]
|
||||||
enum RunMode {
|
enum ResMode {
|
||||||
|
Res1440,
|
||||||
|
Res1080,
|
||||||
|
Res720,
|
||||||
|
Res480,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Eq, PartialEq, EnumString, VariantNames, AsRefStr)]
|
||||||
|
enum OrientationMode {
|
||||||
|
Wide,
|
||||||
|
SemiWide,
|
||||||
|
Square,
|
||||||
|
SemiTall,
|
||||||
|
Tall,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Eq, PartialEq, EnumString, VariantNames, AsRefStr)]
|
||||||
|
enum CompositorMode {
|
||||||
Cage,
|
Cage,
|
||||||
Wayland,
|
Native,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
enum Task {
|
enum Task {
|
||||||
SetRunMode(RunMode),
|
SetCompositor(CompositorMode),
|
||||||
|
SetRes(ResMode),
|
||||||
|
SetOrientation(OrientationMode),
|
||||||
Launch,
|
Launch,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LaunchParams<'a, T> {
|
struct LaunchParams<'a, T> {
|
||||||
application: &'a DesktopEntry,
|
application: &'a DesktopEntry,
|
||||||
run_mode: RunMode,
|
run_mode: CompositorMode,
|
||||||
globals: &'a WguiGlobals,
|
globals: &'a WguiGlobals,
|
||||||
frontend_tasks: &'a FrontendTasks,
|
frontend_tasks: &'a FrontendTasks,
|
||||||
interface: &'a mut BoxDashInterface<T>,
|
interface: &'a mut BoxDashInterface<T>,
|
||||||
@@ -49,9 +69,16 @@ pub struct View {
|
|||||||
frontend_tasks: FrontendTasks,
|
frontend_tasks: FrontendTasks,
|
||||||
globals: WguiGlobals,
|
globals: WguiGlobals,
|
||||||
|
|
||||||
cb_cage_mode: Rc<ComponentCheckbox>,
|
#[allow(dead_code)]
|
||||||
cb_wayland_mode: Rc<ComponentCheckbox>,
|
radio_compositor: Rc<ComponentRadioGroup>,
|
||||||
run_mode: RunMode,
|
#[allow(dead_code)]
|
||||||
|
radio_res: Rc<ComponentRadioGroup>,
|
||||||
|
#[allow(dead_code)]
|
||||||
|
radio_orientation: Rc<ComponentRadioGroup>,
|
||||||
|
|
||||||
|
compositor_mode: CompositorMode,
|
||||||
|
res_mode: ResMode,
|
||||||
|
orientation_mode: OrientationMode,
|
||||||
|
|
||||||
on_launched: Box<dyn Fn()>,
|
on_launched: Box<dyn Fn()>,
|
||||||
}
|
}
|
||||||
@@ -76,8 +103,10 @@ impl View {
|
|||||||
|
|
||||||
let mut state = wgui::parser::parse_from_assets(doc_params, params.layout, params.parent_id)?;
|
let mut state = wgui::parser::parse_from_assets(doc_params, params.layout, params.parent_id)?;
|
||||||
|
|
||||||
let cb_cage_mode = state.fetch_component_as::<ComponentCheckbox>("cb_cage_mode")?;
|
let radio_compositor = state.fetch_component_as::<ComponentRadioGroup>("radio_compositor")?;
|
||||||
let cb_wayland_mode = state.fetch_component_as::<ComponentCheckbox>("cb_wayland_mode")?;
|
let radio_res = state.fetch_component_as::<ComponentRadioGroup>("radio_res")?;
|
||||||
|
let radio_orientation = state.fetch_component_as::<ComponentRadioGroup>("radio_orientation")?;
|
||||||
|
|
||||||
let btn_launch = state.fetch_component_as::<ComponentButton>("btn_launch")?;
|
let btn_launch = state.fetch_component_as::<ComponentButton>("btn_launch")?;
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -114,26 +143,77 @@ impl View {
|
|||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let run_mode = if params.settings.get().tweaks.xwayland_by_default {
|
let compositor_mode = if params.settings.get().tweaks.xwayland_by_default {
|
||||||
RunMode::Cage
|
CompositorMode::Cage
|
||||||
} else {
|
} else {
|
||||||
RunMode::Wayland
|
CompositorMode::Native
|
||||||
};
|
};
|
||||||
|
radio_compositor.set_value(compositor_mode.as_ref())?;
|
||||||
|
tasks.push(Task::SetCompositor(compositor_mode));
|
||||||
|
|
||||||
tasks.push(Task::SetRunMode(run_mode.clone()));
|
let res_mode = ResMode::Res1080;
|
||||||
|
// TODO: configurable defaults ?
|
||||||
|
//radio_res.set_value(res_mode.as_ref())?;
|
||||||
|
//tasks.push(Task::SetRes(res_mode));
|
||||||
|
|
||||||
cb_cage_mode.on_toggle({
|
let orientation_mode = OrientationMode::SemiWide;
|
||||||
|
// TODO: configurable defaults ?
|
||||||
|
//radio_orientation.set_value(orientation_mode.as_ref())?;
|
||||||
|
//tasks.push(Task::SetOrientation(orientation_mode));
|
||||||
|
|
||||||
|
radio_compositor.on_value_changed({
|
||||||
let tasks = tasks.clone();
|
let tasks = tasks.clone();
|
||||||
Box::new(move |_, _| {
|
Box::new(move |_, ev| {
|
||||||
tasks.push(Task::SetRunMode(RunMode::Cage));
|
if let Some(mode) = ev.value.and_then(|v| {
|
||||||
|
CompositorMode::from_str(&*v)
|
||||||
|
.inspect_err(|_| {
|
||||||
|
log::error!(
|
||||||
|
"Invalid value for compositor: '{v}'. Valid values are: {:?}",
|
||||||
|
ResMode::VARIANTS
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.ok()
|
||||||
|
}) {
|
||||||
|
tasks.push(Task::SetCompositor(mode));
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
cb_wayland_mode.on_toggle({
|
radio_res.on_value_changed({
|
||||||
let tasks = tasks.clone();
|
let tasks = tasks.clone();
|
||||||
Box::new(move |_, _| {
|
Box::new(move |_, ev| {
|
||||||
tasks.push(Task::SetRunMode(RunMode::Wayland));
|
if let Some(mode) = ev.value.and_then(|v| {
|
||||||
|
ResMode::from_str(&*v)
|
||||||
|
.inspect_err(|_| {
|
||||||
|
log::error!(
|
||||||
|
"Invalid value for resolution: '{v}'. Valid values are: {:?}",
|
||||||
|
ResMode::VARIANTS
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.ok()
|
||||||
|
}) {
|
||||||
|
tasks.push(Task::SetRes(mode));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
radio_orientation.on_value_changed({
|
||||||
|
let tasks = tasks.clone();
|
||||||
|
Box::new(move |_, ev| {
|
||||||
|
if let Some(mode) = ev.value.and_then(|v| {
|
||||||
|
OrientationMode::from_str(&*v)
|
||||||
|
.inspect_err(|_| {
|
||||||
|
log::error!(
|
||||||
|
"Invalid value for orientation: '{v}'. Valid values are: {:?}",
|
||||||
|
OrientationMode::VARIANTS
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.ok()
|
||||||
|
}) {
|
||||||
|
tasks.push(Task::SetOrientation(mode));
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
@@ -148,9 +228,12 @@ impl View {
|
|||||||
Ok(Self {
|
Ok(Self {
|
||||||
state,
|
state,
|
||||||
tasks,
|
tasks,
|
||||||
cb_cage_mode,
|
radio_compositor,
|
||||||
cb_wayland_mode,
|
radio_res,
|
||||||
run_mode,
|
radio_orientation,
|
||||||
|
compositor_mode,
|
||||||
|
res_mode,
|
||||||
|
orientation_mode,
|
||||||
entry: params.entry,
|
entry: params.entry,
|
||||||
frontend_tasks: params.frontend_tasks.clone(),
|
frontend_tasks: params.frontend_tasks.clone(),
|
||||||
globals: params.globals.clone(),
|
globals: params.globals.clone(),
|
||||||
@@ -158,12 +241,7 @@ impl View {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update<T>(
|
pub fn update<T>(&mut self, interface: &mut BoxDashInterface<T>, data: &mut T) -> anyhow::Result<()> {
|
||||||
&mut self,
|
|
||||||
layout: &mut Layout,
|
|
||||||
interface: &mut BoxDashInterface<T>,
|
|
||||||
data: &mut T,
|
|
||||||
) -> anyhow::Result<()> {
|
|
||||||
loop {
|
loop {
|
||||||
let tasks = self.tasks.drain();
|
let tasks = self.tasks.drain();
|
||||||
if tasks.is_empty() {
|
if tasks.is_empty() {
|
||||||
@@ -171,7 +249,9 @@ impl View {
|
|||||||
}
|
}
|
||||||
for task in tasks {
|
for task in tasks {
|
||||||
match task {
|
match task {
|
||||||
Task::SetRunMode(run_mode) => self.action_set_run_mode(layout, run_mode)?,
|
Task::SetCompositor(mode) => self.compositor_mode = mode,
|
||||||
|
Task::SetRes(mode) => self.res_mode = mode,
|
||||||
|
Task::SetOrientation(mode) => self.orientation_mode = mode,
|
||||||
Task::Launch => self.action_launch(interface, data),
|
Task::Launch => self.action_launch(interface, data),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -180,28 +260,12 @@ impl View {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn action_set_run_mode(&mut self, layout: &mut Layout, run_mode: RunMode) -> anyhow::Result<()> {
|
|
||||||
let mut c = layout.start_common();
|
|
||||||
|
|
||||||
self
|
|
||||||
.cb_cage_mode
|
|
||||||
.set_checked(&mut c.common(), matches!(run_mode, RunMode::Cage));
|
|
||||||
self
|
|
||||||
.cb_wayland_mode
|
|
||||||
.set_checked(&mut c.common(), matches!(run_mode, RunMode::Wayland));
|
|
||||||
|
|
||||||
self.run_mode = run_mode;
|
|
||||||
|
|
||||||
c.finish()?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn action_launch<T>(&mut self, interface: &mut BoxDashInterface<T>, data: &mut T) {
|
fn action_launch<T>(&mut self, interface: &mut BoxDashInterface<T>, data: &mut T) {
|
||||||
View::try_launch(LaunchParams {
|
View::try_launch(LaunchParams {
|
||||||
application: &self.entry,
|
application: &self.entry,
|
||||||
frontend_tasks: &self.frontend_tasks,
|
frontend_tasks: &self.frontend_tasks,
|
||||||
globals: &self.globals,
|
globals: &self.globals,
|
||||||
run_mode: self.run_mode.clone(),
|
run_mode: self.compositor_mode.clone(),
|
||||||
interface,
|
interface,
|
||||||
data,
|
data,
|
||||||
on_launched: &self.on_launched,
|
on_launched: &self.on_launched,
|
||||||
@@ -225,7 +289,7 @@ impl View {
|
|||||||
fn launch<T>(params: LaunchParams<T>) -> anyhow::Result<()> {
|
fn launch<T>(params: LaunchParams<T>) -> anyhow::Result<()> {
|
||||||
let mut env = Vec::<String>::new();
|
let mut env = Vec::<String>::new();
|
||||||
|
|
||||||
if params.run_mode == RunMode::Wayland {
|
if params.run_mode == CompositorMode::Native {
|
||||||
// This list could be larger, feel free to expand it
|
// This list could be larger, feel free to expand it
|
||||||
env.push("QT_QPA_PLATFORM=wayland".into());
|
env.push("QT_QPA_PLATFORM=wayland".into());
|
||||||
env.push("GDK_BACKEND=wayland".into());
|
env.push("GDK_BACKEND=wayland".into());
|
||||||
@@ -235,13 +299,13 @@ impl View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let args = match params.run_mode {
|
let args = match params.run_mode {
|
||||||
RunMode::Cage => format!("-- {} {}", params.application.exec_path, params.application.exec_args),
|
CompositorMode::Cage => format!("-- {} {}", params.application.exec_path, params.application.exec_args),
|
||||||
RunMode::Wayland => params.application.exec_args.to_string(),
|
CompositorMode::Native => params.application.exec_args.to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let exec = match params.run_mode {
|
let exec = match params.run_mode {
|
||||||
RunMode::Cage => "cage".to_string(),
|
CompositorMode::Cage => "cage".to_string(),
|
||||||
RunMode::Wayland => params.application.exec_path.to_string(),
|
CompositorMode::Native => params.application.exec_path.to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut userdata = HashMap::new();
|
let mut userdata = HashMap::new();
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ regex.workspace = true
|
|||||||
slotmap.workspace = true
|
slotmap.workspace = true
|
||||||
serde = { workspace = true, features = ["rc"] }
|
serde = { workspace = true, features = ["rc"] }
|
||||||
serde_json.workspace = true
|
serde_json.workspace = true
|
||||||
|
strum.workspace = true
|
||||||
vulkano.workspace = true
|
vulkano.workspace = true
|
||||||
vulkano-shaders.workspace = true
|
vulkano-shaders.workspace = true
|
||||||
xdg.workspace = true
|
xdg.workspace = true
|
||||||
@@ -77,7 +78,6 @@ serde_json5 = "0.2.1"
|
|||||||
serde_yaml = "0.9.34"
|
serde_yaml = "0.9.34"
|
||||||
signal-hook = "0.3.18"
|
signal-hook = "0.3.18"
|
||||||
smallvec = "1.15.1"
|
smallvec = "1.15.1"
|
||||||
strum = { version = "0.27.2", features = ["derive"] }
|
|
||||||
sysinfo = { version = "0.37" }
|
sysinfo = { version = "0.37" }
|
||||||
thiserror = "2.0"
|
thiserror = "2.0"
|
||||||
tracing-subscriber = { version = "0.3.22", features = ["env-filter"] }
|
tracing-subscriber = { version = "0.3.22", features = ["env-filter"] }
|
||||||
|
|||||||
Reference in New Issue
Block a user