App launcher
[skip ci]
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
<template name="Subtext">
|
||||
<div flex_direction="row" gap="8">
|
||||
<label weight="bold" text="${title}" />
|
||||
<label text="foo" />
|
||||
<label id="${label_id}" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -14,26 +14,25 @@
|
||||
<include src="../t_group_box.xml" />
|
||||
|
||||
<elements>
|
||||
<div flex_direction="row" gap="16" width="100%">
|
||||
<rectangle macro="group_box" id="icon_parent" height="100%" padding="8" color="#0033aa66" color2="#00000022" gradient="vertical" justify_content="center">
|
||||
<div flex_direction="row" gap="16">
|
||||
<rectangle macro="group_box" id="icon_parent" padding="8" color="#0033aa66" color2="#00000022" gradient="vertical" justify_content="center">
|
||||
|
||||
</rectangle>
|
||||
<div flex_direction="column" gap="8" width="100%" align_items="baseline">
|
||||
<div flex_direction="column" gap="8">
|
||||
<label id="label_title" weight="bold" size="32" />
|
||||
<Subtext title="Exec:" />
|
||||
<Subtext title="Args:" />
|
||||
<Subtext title="Exec:" label_id="label_exec" />
|
||||
<Subtext title="Args:" label_id="label_args" />
|
||||
<Separator />
|
||||
<CheckBox text="Run in X11 mode (cage)" />
|
||||
<CheckBox text="Run in Wayland mode" checked="1" />
|
||||
<CheckBox id="cb_cage_mode" text="Run in X11 mode (cage)" />
|
||||
<CheckBox id="cb_wayland_mode" text="Run in Wayland mode" checked="1" />
|
||||
<Separator />
|
||||
<Button color="#44ce22FF" padding_top="4" padding_bottom="4" round="8" padding_right="12">
|
||||
<Button 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" />
|
||||
<label text="Launch embedded" weight="bold" size="17" shadow="#00000099" />
|
||||
<label text="Launch embedded (todo)" weight="bold" size="17" shadow="#00000099" />
|
||||
</Button>
|
||||
<Separator />
|
||||
<rectangle macro="group_box">
|
||||
<label size="16" weight="bold" text="Or launch it detached" />
|
||||
</rectangle>
|
||||
<label size="16" weight="bold" text="Or launch it detached" />
|
||||
<div id="display_list_parent" />
|
||||
</div>
|
||||
</div>
|
||||
</elements>
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
</rectangle>
|
||||
|
||||
<!-- Content -->
|
||||
<rectangle width="100%" height="100%"
|
||||
<rectangle height="100%"
|
||||
color="#010310ee"
|
||||
color2="#062a5eee"
|
||||
gradient="vertical"
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
<elements>
|
||||
<rectangle macro="group_box" flex_direction="row" align_items="center">
|
||||
<div id="list_parent" gap="8" flex_direction="row" flex_wrap="wrap" flex_grow="1" />
|
||||
<div id="list_parent" gap="8" flex_direction="column" flex_wrap="wrap" flex_grow="1" />
|
||||
</rectangle>
|
||||
</elements>
|
||||
</layout>
|
||||
@@ -62,6 +62,9 @@
|
||||
"DISPLAY_OPTIONS": "Anzeigeeinstellungen",
|
||||
"PROCESS_LIST": {
|
||||
"NO_PROCESSES_FOUND": "Keine Prozesse gefunden",
|
||||
"LOCATED_ON": "auf"
|
||||
}
|
||||
"LOCATED_ON": "auf",
|
||||
"TERMINATE_PROCESS_NAMED_X": "Prozess \"{PROCESS_NAME}\" beenden"
|
||||
},
|
||||
"FAILED_TO_LAUNCH_APPLICATION": "Fehler beim Starten der Anwendung:",
|
||||
"APPLICATION_LAUNCHED_ON": "Anwendung wurde auf {DISPLAY_NAME} gestartet."
|
||||
}
|
||||
@@ -22,6 +22,7 @@
|
||||
},
|
||||
"WLX_OVERLAY_S_SETTINGS": "WlxOverlay-S settings"
|
||||
},
|
||||
"APPLICATION_LAUNCHED_ON": "Application launched on {DISPLAY_NAME}.",
|
||||
"APPLICATION_LAUNCHER": "Application launcher",
|
||||
"APPLICATIONS": "Applications",
|
||||
"AUDIO": {
|
||||
@@ -41,6 +42,7 @@
|
||||
},
|
||||
"DISPLAY_OPTIONS": "Display options",
|
||||
"DISPLAY_PORTRAIT_MODE": "Portrait mode",
|
||||
"FAILED_TO_LAUNCH_APPLICATION": "Failed to launcha application:",
|
||||
"GAMES": "Games",
|
||||
"GENERAL_SETTINGS": "General settings",
|
||||
"HEIGHT": "Height",
|
||||
|
||||
@@ -62,6 +62,9 @@
|
||||
"DISPLAY_OPTIONS": "Opciones de pantalla",
|
||||
"PROCESS_LIST": {
|
||||
"NO_PROCESSES_FOUND": "No se encontraron procesos",
|
||||
"LOCATED_ON": "en"
|
||||
}
|
||||
"LOCATED_ON": "en",
|
||||
"TERMINATE_PROCESS_NAMED_X": "Terminar proceso \"{PROCESS_NAME}\""
|
||||
},
|
||||
"FAILED_TO_LAUNCH_APPLICATION": "No se pudo iniciar la aplicación:",
|
||||
"APPLICATION_LAUNCHED_ON": "Aplicación iniciada en {DISPLAY_NAME}."
|
||||
}
|
||||
@@ -62,6 +62,9 @@
|
||||
"DISPLAY_OPTIONS": "表示オプション",
|
||||
"PROCESS_LIST": {
|
||||
"NO_PROCESSES_FOUND": "プロセスが見つかりませんでした",
|
||||
"LOCATED_ON": "に"
|
||||
}
|
||||
}
|
||||
"LOCATED_ON": "に",
|
||||
"TERMINATE_PROCESS_NAMED_X": "プロセス \"{PROCESS_NAME}\" を終了します"
|
||||
},
|
||||
"FAILED_TO_LAUNCH_APPLICATION": "アプリケーションの起動に失敗しました:",
|
||||
"APPLICATION_LAUNCHED_ON": "{DISPLAY_NAME}でアプリケーションが起動しました。"
|
||||
}
|
||||
@@ -62,6 +62,9 @@
|
||||
"PROCESSES": "Procesy",
|
||||
"PROCESS_LIST": {
|
||||
"NO_PROCESSES_FOUND": "Nie znaleziono procesów",
|
||||
"LOCATED_ON": "na"
|
||||
}
|
||||
"LOCATED_ON": "na",
|
||||
"TERMINATE_PROCESS_NAMED_X": "Zakończ proces \"{PROCESS_NAME}\""
|
||||
},
|
||||
"FAILED_TO_LAUNCH_APPLICATION": "Nie udało się uruchomić aplikacji:",
|
||||
"APPLICATION_LAUNCHED_ON": "Aplikacja uruchomiona na {DISPLAY_NAME}."
|
||||
}
|
||||
@@ -232,9 +232,13 @@ impl Frontend {
|
||||
|
||||
fn mount_popup(&mut self, params: MountPopupParams) -> anyhow::Result<()> {
|
||||
let mut layout = self.layout.borrow_mut();
|
||||
self
|
||||
.popup_manager
|
||||
.mount_popup(self.globals.clone(), &mut layout, self.tasks.clone(), params)?;
|
||||
self.popup_manager.mount_popup(
|
||||
self.globals.clone(),
|
||||
self.settings.as_ref(),
|
||||
&mut layout,
|
||||
self.tasks.clone(),
|
||||
params,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -10,8 +10,9 @@ use wgui::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
frontend::{FrontendTask, RcFrontend},
|
||||
frontend::{FrontendTask, FrontendTasks, RcFrontend},
|
||||
tab::{Tab, TabParams, TabType},
|
||||
task::Tasks,
|
||||
util::{
|
||||
self,
|
||||
desktop_finder::DesktopEntry,
|
||||
@@ -20,6 +21,10 @@ use crate::{
|
||||
views::{self, app_launcher},
|
||||
};
|
||||
|
||||
enum Task {
|
||||
CloseLauncher,
|
||||
}
|
||||
|
||||
struct State {
|
||||
launcher: Option<(PopupHandle, views::app_launcher::View)>,
|
||||
}
|
||||
@@ -35,12 +40,29 @@ pub struct TabApps {
|
||||
entries: Vec<DesktopEntry>,
|
||||
#[allow(dead_code)]
|
||||
app_list: AppList,
|
||||
|
||||
tasks: Tasks<Task>,
|
||||
}
|
||||
|
||||
impl Tab for TabApps {
|
||||
fn get_type(&self) -> TabType {
|
||||
TabType::Apps
|
||||
}
|
||||
|
||||
fn update(&mut self, params: super::TabUpdateParams) -> anyhow::Result<()> {
|
||||
let mut state = self.state.borrow_mut();
|
||||
|
||||
for task in self.tasks.drain() {
|
||||
match task {
|
||||
Task::CloseLauncher => state.launcher = None,
|
||||
}
|
||||
}
|
||||
|
||||
if let Some((_, launcher)) = &mut state.launcher {
|
||||
launcher.update(params.layout, params.interface)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
@@ -51,9 +73,11 @@ struct AppList {
|
||||
// called after the user clicks any desktop entry
|
||||
fn on_app_click(
|
||||
frontend: RcFrontend,
|
||||
frontend_tasks: FrontendTasks,
|
||||
globals: WguiGlobals,
|
||||
entry: DesktopEntry,
|
||||
state: Rc<RefCell<State>>,
|
||||
tasks: Tasks<Task>,
|
||||
) -> ButtonClickCallback {
|
||||
Box::new(move |_common, _evt| {
|
||||
frontend
|
||||
@@ -62,15 +86,27 @@ fn on_app_click(
|
||||
.push(FrontendTask::MountPopup(MountPopupParams {
|
||||
title: Translation::from_raw_text(&entry.app_name),
|
||||
on_content: {
|
||||
// this is awful
|
||||
let state = state.clone();
|
||||
let entry = entry.clone();
|
||||
let globals = globals.clone();
|
||||
let frontend_tasks = frontend_tasks.clone();
|
||||
let tasks = tasks.clone();
|
||||
|
||||
Rc::new(move |data| {
|
||||
let on_launched = {
|
||||
let tasks = tasks.clone();
|
||||
Box::new(move || tasks.push(Task::CloseLauncher))
|
||||
};
|
||||
|
||||
let view = app_launcher::View::new(app_launcher::Params {
|
||||
entry: entry.clone(),
|
||||
globals: globals.clone(),
|
||||
globals: &globals,
|
||||
layout: data.layout,
|
||||
parent_id: data.id_content,
|
||||
frontend_tasks: &frontend_tasks,
|
||||
settings: data.settings,
|
||||
on_launched,
|
||||
})?;
|
||||
|
||||
state.borrow_mut().launcher = Some((data.handle, view));
|
||||
@@ -93,9 +129,11 @@ impl TabApps {
|
||||
gtk::init()?;
|
||||
let entries = util::desktop_finder::find_entries()?;
|
||||
|
||||
let frontend_tasks = tab_params.frontend_tasks.clone();
|
||||
let frontend = tab_params.frontend.clone();
|
||||
let globals = tab_params.globals.clone();
|
||||
|
||||
let tasks = Tasks::new();
|
||||
let state = Rc::new(RefCell::new(State { launcher: None }));
|
||||
|
||||
let mut parser_state = wgui::parser::parse_from_assets(doc_params, tab_params.layout, tab_params.parent_id)?;
|
||||
@@ -111,9 +149,11 @@ impl TabApps {
|
||||
// Set up the click handler for the app button
|
||||
button.on_click(on_app_click(
|
||||
frontend.clone(),
|
||||
frontend_tasks.clone(),
|
||||
globals.clone(),
|
||||
entry.clone(),
|
||||
state.clone(),
|
||||
tasks.clone(),
|
||||
));
|
||||
},
|
||||
)?;
|
||||
@@ -123,6 +163,7 @@ impl TabApps {
|
||||
parser_state,
|
||||
entries,
|
||||
state,
|
||||
tasks,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,8 +44,9 @@ impl TabProcesses {
|
||||
view_display_list: display_list::View::new(display_list::Params {
|
||||
layout: params.layout,
|
||||
parent_id: state.get_widget_id("display_list_parent")?,
|
||||
globals: params.globals.clone(),
|
||||
globals: params.globals,
|
||||
frontend_tasks: params.frontend_tasks.clone(),
|
||||
on_click: None,
|
||||
})?,
|
||||
view_process_list: process_list::View::new(process_list::Params {
|
||||
layout: params.layout,
|
||||
|
||||
@@ -3,6 +3,7 @@ use gtk::traits::IconThemeExt;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
// compatibility with wayvr-ipc
|
||||
// TODO: remove this after we're done with the old wayvr-dashboard and use DesktopEntry instead
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct DesktopFile {
|
||||
pub name: String,
|
||||
@@ -13,7 +14,6 @@ pub struct DesktopFile {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[allow(dead_code)] // TODO: remove this
|
||||
pub struct DesktopEntry {
|
||||
pub exec_path: String,
|
||||
pub exec_args: Vec<String>,
|
||||
@@ -140,3 +140,15 @@ pub fn find_entries() -> anyhow::Result<Vec<DesktopEntry>> {
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
impl DesktopEntry {
|
||||
pub fn to_desktop_file(&self) -> DesktopFile {
|
||||
DesktopFile {
|
||||
categories: self.categories.clone(),
|
||||
exec_args: self.exec_args.clone(),
|
||||
exec_path: self.exec_path.clone(),
|
||||
icon: self.icon_path.clone(),
|
||||
name: self.app_name.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,10 @@ use wgui::{
|
||||
widget::label::WidgetLabel,
|
||||
};
|
||||
|
||||
use crate::frontend::{FrontendTask, FrontendTasks};
|
||||
use crate::{
|
||||
frontend::{FrontendTask, FrontendTasks},
|
||||
settings::SettingsIO,
|
||||
};
|
||||
|
||||
pub struct PopupManagerParams {
|
||||
pub parent_id: WidgetID,
|
||||
@@ -55,6 +58,7 @@ pub struct PopupManager {
|
||||
|
||||
pub struct PopupContentFuncData<'a> {
|
||||
pub layout: &'a mut Layout,
|
||||
pub settings: &'a dyn SettingsIO,
|
||||
pub handle: PopupHandle,
|
||||
pub id_content: WidgetID,
|
||||
}
|
||||
@@ -119,6 +123,7 @@ impl PopupManager {
|
||||
pub fn mount_popup(
|
||||
&mut self,
|
||||
globals: WguiGlobals,
|
||||
settings: &dyn SettingsIO,
|
||||
layout: &mut Layout,
|
||||
frontend_tasks: FrontendTasks,
|
||||
params: MountPopupParams,
|
||||
@@ -175,6 +180,7 @@ impl PopupManager {
|
||||
layout,
|
||||
handle: popup_handle.clone(),
|
||||
id_content,
|
||||
settings,
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -130,7 +130,7 @@ impl ToastManager {
|
||||
// show-up animation
|
||||
layout.animations.add(Animation::new(
|
||||
rect.id,
|
||||
160, // does not use anim_mult
|
||||
(120.0 * globals.defaults.animation_mult) as u32,
|
||||
AnimationEasing::Linear,
|
||||
Box::new(move |common, data| {
|
||||
let pos_showup = AnimationEasing::OutQuint.interpolate((data.pos * 4.0).min(1.0));
|
||||
@@ -138,7 +138,7 @@ impl ToastManager {
|
||||
let scale = AnimationEasing::OutBack.interpolate((data.pos * 4.0).min(1.0));
|
||||
|
||||
{
|
||||
let mtx = Mat4::from_translation(Vec3::new(0.0, (1.0 - pos_showup) * 100.0, 0.0))
|
||||
let mtx = Mat4::from_translation(Vec3::new(0.0, (1.0 - pos_showup) * 20.0, 0.0))
|
||||
* Mat4::from_scale(Vec3::new(scale, scale, 1.0));
|
||||
data.data.transform = centered_matrix(data.widget_boundary.size, &mtx);
|
||||
}
|
||||
|
||||
@@ -1,27 +1,71 @@
|
||||
use std::{collections::HashMap, rc::Rc};
|
||||
|
||||
use anyhow::Context;
|
||||
use wayvr_ipc::{packet_client::WvrProcessLaunchParams, packet_server::WvrDisplayHandle};
|
||||
use wgui::{
|
||||
assets::AssetPath,
|
||||
components::checkbox::ComponentCheckbox,
|
||||
globals::WguiGlobals,
|
||||
i18n::Translation,
|
||||
layout::{Layout, WidgetID},
|
||||
parser::{Fetchable, ParseDocumentParams, ParserState},
|
||||
widget::label::WidgetLabel,
|
||||
};
|
||||
use wlx_common::dash_interface::BoxDashInterface;
|
||||
|
||||
use crate::util::desktop_finder::DesktopEntry;
|
||||
use crate::{
|
||||
frontend::{FrontendTask, FrontendTasks},
|
||||
settings::SettingsIO,
|
||||
task::Tasks,
|
||||
util::desktop_finder::DesktopEntry,
|
||||
views::display_list,
|
||||
};
|
||||
|
||||
#[derive(Clone, Eq, PartialEq)]
|
||||
enum RunMode {
|
||||
Cage,
|
||||
Wayland,
|
||||
}
|
||||
|
||||
enum Task {
|
||||
SetRunMode(RunMode),
|
||||
DisplayClick(WvrDisplayHandle),
|
||||
}
|
||||
|
||||
struct LaunchParams<'a> {
|
||||
display_handle: WvrDisplayHandle,
|
||||
application: &'a DesktopEntry,
|
||||
run_mode: RunMode,
|
||||
globals: &'a WguiGlobals,
|
||||
frontend_tasks: &'a FrontendTasks,
|
||||
interface: &'a mut BoxDashInterface,
|
||||
on_launched: &'a dyn Fn(),
|
||||
}
|
||||
|
||||
pub struct View {
|
||||
#[allow(dead_code)]
|
||||
pub state: ParserState,
|
||||
//entry: DesktopEntry,
|
||||
state: ParserState,
|
||||
entry: DesktopEntry,
|
||||
view_display_list: display_list::View,
|
||||
tasks: Tasks<Task>,
|
||||
frontend_tasks: FrontendTasks,
|
||||
globals: WguiGlobals,
|
||||
|
||||
cb_cage_mode: Rc<ComponentCheckbox>,
|
||||
cb_wayland_mode: Rc<ComponentCheckbox>,
|
||||
run_mode: RunMode,
|
||||
|
||||
on_launched: Box<dyn Fn()>,
|
||||
}
|
||||
|
||||
pub struct Params<'a> {
|
||||
pub globals: WguiGlobals,
|
||||
pub globals: &'a WguiGlobals,
|
||||
pub entry: DesktopEntry,
|
||||
pub layout: &'a mut Layout,
|
||||
pub parent_id: WidgetID,
|
||||
pub settings: &'a dyn SettingsIO,
|
||||
pub frontend_tasks: &'a FrontendTasks,
|
||||
pub on_launched: Box<dyn Fn()>,
|
||||
}
|
||||
|
||||
impl View {
|
||||
@@ -33,6 +77,44 @@ impl View {
|
||||
};
|
||||
|
||||
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 cb_wayland_mode = state.fetch_component_as::<ComponentCheckbox>("cb_wayland_mode")?;
|
||||
|
||||
{
|
||||
let mut label_exec = state.fetch_widget_as::<WidgetLabel>(¶ms.layout.state, "label_exec")?;
|
||||
let mut label_args = state.fetch_widget_as::<WidgetLabel>(¶ms.layout.state, "label_args")?;
|
||||
|
||||
label_exec.set_text_simple(
|
||||
&mut params.globals.get(),
|
||||
Translation::from_raw_text_string(params.entry.app_name.clone()),
|
||||
);
|
||||
|
||||
label_args.set_text_simple(
|
||||
&mut params.globals.get(),
|
||||
Translation::from_raw_text_string(params.entry.exec_args.join(" ")),
|
||||
);
|
||||
}
|
||||
|
||||
let display_list_parent = state.fetch_widget(¶ms.layout.state, "display_list_parent")?.id;
|
||||
|
||||
let tasks = Tasks::new();
|
||||
|
||||
let on_display_click = {
|
||||
let tasks = tasks.clone();
|
||||
Box::new(move |disp_handle: WvrDisplayHandle| {
|
||||
tasks.push(Task::DisplayClick(disp_handle));
|
||||
})
|
||||
};
|
||||
|
||||
let view_display_list = display_list::View::new(display_list::Params {
|
||||
frontend_tasks: params.frontend_tasks.clone(),
|
||||
globals: params.globals,
|
||||
layout: params.layout,
|
||||
parent_id: display_list_parent,
|
||||
on_click: Some(on_display_click),
|
||||
})?;
|
||||
|
||||
let id_icon_parent = state.get_widget_id("icon_parent")?;
|
||||
|
||||
// app icon
|
||||
@@ -48,6 +130,30 @@ impl View {
|
||||
)?;
|
||||
}
|
||||
|
||||
let run_mode = if params.settings.get().tweaks.xwayland_by_default {
|
||||
RunMode::Cage
|
||||
} else {
|
||||
RunMode::Wayland
|
||||
};
|
||||
|
||||
tasks.push(Task::SetRunMode(run_mode.clone()));
|
||||
|
||||
cb_cage_mode.on_toggle({
|
||||
let tasks = tasks.clone();
|
||||
Box::new(move |_, _| {
|
||||
tasks.push(Task::SetRunMode(RunMode::Cage));
|
||||
Ok(())
|
||||
})
|
||||
});
|
||||
|
||||
cb_wayland_mode.on_toggle({
|
||||
let tasks = tasks.clone();
|
||||
Box::new(move |_, _| {
|
||||
tasks.push(Task::SetRunMode(RunMode::Wayland));
|
||||
Ok(())
|
||||
})
|
||||
});
|
||||
|
||||
let mut label_title = state.fetch_widget_as::<WidgetLabel>(¶ms.layout.state, "label_title")?;
|
||||
|
||||
label_title.set_text_simple(
|
||||
@@ -56,8 +162,139 @@ impl View {
|
||||
);
|
||||
|
||||
Ok(Self {
|
||||
//entry: params.entry,
|
||||
state,
|
||||
view_display_list,
|
||||
tasks,
|
||||
cb_cage_mode,
|
||||
cb_wayland_mode,
|
||||
run_mode,
|
||||
entry: params.entry,
|
||||
frontend_tasks: params.frontend_tasks.clone(),
|
||||
globals: params.globals.clone(),
|
||||
on_launched: params.on_launched,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn update(&mut self, layout: &mut Layout, interface: &mut BoxDashInterface) -> anyhow::Result<()> {
|
||||
loop {
|
||||
let tasks = self.tasks.drain();
|
||||
if tasks.is_empty() {
|
||||
break;
|
||||
}
|
||||
for task in tasks {
|
||||
match task {
|
||||
Task::SetRunMode(run_mode) => self.action_set_run_mode(layout, run_mode)?,
|
||||
Task::DisplayClick(disp_handle) => self.action_display_click(disp_handle, interface),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.view_display_list.update(layout, interface)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn action_set_run_mode(&mut self, layout: &mut Layout, run_mode: RunMode) -> anyhow::Result<()> {
|
||||
let (n1, n2) = match run_mode {
|
||||
RunMode::Cage => (true, false),
|
||||
RunMode::Wayland => (false, true),
|
||||
};
|
||||
|
||||
let mut c = layout.start_common();
|
||||
self.cb_cage_mode.set_checked(&mut c.common(), n1);
|
||||
self.cb_wayland_mode.set_checked(&mut c.common(), n2);
|
||||
|
||||
c.finish()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn action_display_click(&mut self, handle: WvrDisplayHandle, interface: &mut BoxDashInterface) {
|
||||
View::try_launch(LaunchParams {
|
||||
application: &self.entry,
|
||||
display_handle: handle,
|
||||
frontend_tasks: &self.frontend_tasks,
|
||||
globals: &self.globals,
|
||||
run_mode: self.run_mode.clone(),
|
||||
interface,
|
||||
on_launched: &self.on_launched,
|
||||
});
|
||||
}
|
||||
|
||||
fn try_launch(params: LaunchParams) {
|
||||
let globals = params.globals.clone();
|
||||
let frontend_tasks = params.frontend_tasks.clone();
|
||||
|
||||
// launch app itself
|
||||
let Err(e) = View::launch(params) else { return };
|
||||
|
||||
let str_failed = globals.i18n().translate("FAILED_TO_LAUNCH_APPLICATION");
|
||||
frontend_tasks.push(FrontendTask::PushToast(Translation::from_raw_text_string(format!(
|
||||
"{} {:?}",
|
||||
str_failed, e
|
||||
))));
|
||||
}
|
||||
|
||||
fn launch(params: LaunchParams) -> anyhow::Result<()> {
|
||||
let mut env = Vec::<String>::new();
|
||||
|
||||
if params.run_mode == RunMode::Wayland {
|
||||
// This list could be larger, feel free to expand it
|
||||
env.push("QT_QPA_PLATFORM=wayland".into());
|
||||
env.push("GDK_BACKEND=wayland".into());
|
||||
env.push("SDL_VIDEODRIVER=wayland".into());
|
||||
env.push("XDG_SESSION_TYPE=wayland".into());
|
||||
env.push("ELECTRON_OZONE_PLATFORM_HINT=wayland".into());
|
||||
}
|
||||
|
||||
// TODO: refactor this after we ditch old wayvr-dashboard completely
|
||||
let desktop_file = params.application.to_desktop_file();
|
||||
let mut userdata = HashMap::<String, String>::new();
|
||||
userdata.insert("desktop_file".into(), serde_json::to_string(&desktop_file)?);
|
||||
|
||||
let exec_args_str = desktop_file.exec_args.join(" ");
|
||||
|
||||
params
|
||||
.interface
|
||||
.display_set_visible(params.display_handle.clone(), true)?;
|
||||
|
||||
let args = match params.run_mode {
|
||||
RunMode::Cage => format!("-- {} {}", desktop_file.exec_path, exec_args_str),
|
||||
RunMode::Wayland => exec_args_str,
|
||||
};
|
||||
|
||||
let exec = match params.run_mode {
|
||||
RunMode::Cage => "cage",
|
||||
RunMode::Wayland => &desktop_file.name,
|
||||
};
|
||||
|
||||
let display = params
|
||||
.interface
|
||||
.display_get(params.display_handle.clone())
|
||||
.context("Display not found")?;
|
||||
|
||||
params.interface.process_launch(WvrProcessLaunchParams {
|
||||
env,
|
||||
exec: String::from(exec),
|
||||
name: desktop_file.name,
|
||||
target_display: params.display_handle,
|
||||
args,
|
||||
userdata,
|
||||
})?;
|
||||
|
||||
let str_launched_on = params
|
||||
.globals
|
||||
.i18n()
|
||||
.translate_and_replace("APPLICATION_LAUNCHED_ON", ("{DISPLAY_NAME}", &display.name));
|
||||
|
||||
params
|
||||
.frontend_tasks
|
||||
.push(FrontendTask::PushToast(Translation::from_raw_text_string(
|
||||
str_launched_on,
|
||||
)));
|
||||
|
||||
(*params.on_launched)();
|
||||
|
||||
// we're done!
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
use wayvr_ipc::{
|
||||
packet_client::{self},
|
||||
packet_server::{self},
|
||||
packet_server::{self, WvrDisplayHandle},
|
||||
};
|
||||
use wgui::{
|
||||
assets::AssetPath,
|
||||
@@ -31,16 +31,17 @@ use crate::{
|
||||
enum Task {
|
||||
AddDisplay,
|
||||
AddDisplayFinish(add_display::Result),
|
||||
DisplayOptions(packet_server::WvrDisplay),
|
||||
DisplayClicked(packet_server::WvrDisplay),
|
||||
DisplayOptionsFinish,
|
||||
Refresh,
|
||||
}
|
||||
|
||||
pub struct Params<'a> {
|
||||
pub globals: WguiGlobals,
|
||||
pub globals: &'a WguiGlobals,
|
||||
pub frontend_tasks: FrontendTasks,
|
||||
pub layout: &'a mut Layout,
|
||||
pub parent_id: WidgetID,
|
||||
pub on_click: Option<Box<dyn Fn(WvrDisplayHandle)>>,
|
||||
}
|
||||
|
||||
struct State {
|
||||
@@ -56,6 +57,7 @@ pub struct View {
|
||||
globals: WguiGlobals,
|
||||
state: Rc<RefCell<State>>,
|
||||
id_list_parent: WidgetID,
|
||||
on_click: Option<Box<dyn Fn(WvrDisplayHandle)>>,
|
||||
}
|
||||
|
||||
impl View {
|
||||
@@ -84,9 +86,10 @@ impl View {
|
||||
parser_state,
|
||||
tasks,
|
||||
frontend_tasks: params.frontend_tasks,
|
||||
globals: params.globals,
|
||||
globals: params.globals.clone(),
|
||||
state,
|
||||
id_list_parent: list_parent.id,
|
||||
on_click: params.on_click,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -98,11 +101,11 @@ impl View {
|
||||
}
|
||||
for task in tasks {
|
||||
match task {
|
||||
Task::AddDisplay => self.add_display(),
|
||||
Task::AddDisplayFinish(result) => self.add_display_finish(interface, result)?,
|
||||
Task::DisplayOptionsFinish => self.display_options_finish(),
|
||||
Task::AddDisplay => self.action_add_display(),
|
||||
Task::AddDisplayFinish(result) => self.action_add_display_finish(interface, result)?,
|
||||
Task::DisplayOptionsFinish => self.action_display_options_finish(),
|
||||
Task::Refresh => self.refresh(layout, interface)?,
|
||||
Task::DisplayOptions(display) => self.display_options(display)?,
|
||||
Task::DisplayClicked(display) => self.action_display_clicked(display)?,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -189,7 +192,7 @@ fn fill_display_list(
|
||||
button.on_click({
|
||||
let tasks = tasks.clone();
|
||||
Box::new(move |_, _| {
|
||||
tasks.push(Task::DisplayOptions(entry.clone()));
|
||||
tasks.push(Task::DisplayClicked(entry.clone()));
|
||||
Ok(())
|
||||
})
|
||||
});
|
||||
@@ -199,7 +202,7 @@ fn fill_display_list(
|
||||
}
|
||||
|
||||
impl View {
|
||||
fn add_display(&mut self) {
|
||||
fn action_add_display(&mut self) {
|
||||
self.frontend_tasks.push(FrontendTask::MountPopup(MountPopupParams {
|
||||
title: Translation::from_translation_key("ADD_DISPLAY"),
|
||||
on_content: {
|
||||
@@ -230,7 +233,7 @@ impl View {
|
||||
}));
|
||||
}
|
||||
|
||||
fn add_display_finish(
|
||||
fn action_add_display_finish(
|
||||
&mut self,
|
||||
interface: &mut BoxDashInterface,
|
||||
result: add_display::Result,
|
||||
@@ -246,7 +249,7 @@ impl View {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn display_options_finish(&mut self) {
|
||||
fn action_display_options_finish(&mut self) {
|
||||
self.state.borrow_mut().view_display_options = None;
|
||||
self.tasks.push(Task::Refresh);
|
||||
}
|
||||
@@ -291,31 +294,35 @@ impl View {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn display_options(&mut self, display: packet_server::WvrDisplay) -> anyhow::Result<()> {
|
||||
self.frontend_tasks.push(FrontendTask::MountPopup(MountPopupParams {
|
||||
title: Translation::from_translation_key("DISPLAY_OPTIONS"),
|
||||
on_content: {
|
||||
let frontend_tasks = self.frontend_tasks.clone();
|
||||
let globals = self.globals.clone();
|
||||
let state = self.state.clone();
|
||||
let tasks = self.tasks.clone();
|
||||
fn action_display_clicked(&mut self, display: packet_server::WvrDisplay) -> anyhow::Result<()> {
|
||||
if let Some(on_click) = &mut self.on_click {
|
||||
(*on_click)(display.handle);
|
||||
} else {
|
||||
self.frontend_tasks.push(FrontendTask::MountPopup(MountPopupParams {
|
||||
title: Translation::from_translation_key("DISPLAY_OPTIONS"),
|
||||
on_content: {
|
||||
let frontend_tasks = self.frontend_tasks.clone();
|
||||
let globals = self.globals.clone();
|
||||
let state = self.state.clone();
|
||||
let tasks = self.tasks.clone();
|
||||
|
||||
Rc::new(move |data| {
|
||||
state.borrow_mut().view_display_options = Some((
|
||||
data.handle,
|
||||
display_options::View::new(display_options::Params {
|
||||
globals: globals.clone(),
|
||||
layout: data.layout,
|
||||
parent_id: data.id_content,
|
||||
on_submit: tasks.make_callback(Task::DisplayOptionsFinish),
|
||||
display: display.clone(),
|
||||
frontend_tasks: frontend_tasks.clone(),
|
||||
})?,
|
||||
));
|
||||
Ok(())
|
||||
})
|
||||
},
|
||||
}));
|
||||
Rc::new(move |data| {
|
||||
state.borrow_mut().view_display_options = Some((
|
||||
data.handle,
|
||||
display_options::View::new(display_options::Params {
|
||||
globals: globals.clone(),
|
||||
layout: data.layout,
|
||||
parent_id: data.id_content,
|
||||
on_submit: tasks.make_callback(Task::DisplayOptionsFinish),
|
||||
display: display.clone(),
|
||||
frontend_tasks: frontend_tasks.clone(),
|
||||
})?,
|
||||
));
|
||||
Ok(())
|
||||
})
|
||||
},
|
||||
}));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ impl View {
|
||||
for task in tasks {
|
||||
match task {
|
||||
Task::Refresh => self.refresh(layout, interface)?,
|
||||
Task::TerminateProcess(process) => self.terminate_process(interface, process)?,
|
||||
Task::TerminateProcess(process) => self.action_terminate_process(interface, process)?,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -100,7 +100,7 @@ fn get_desktop_file_from_process(
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: refactor this after we ditch wayvr-ipc completely
|
||||
// TODO: refactor this after we ditch old wayvr-dashboard completely
|
||||
let Some(dfile_str) = process.userdata.get("desktop_file") else {
|
||||
continue;
|
||||
};
|
||||
@@ -294,7 +294,7 @@ impl View {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn terminate_process(
|
||||
fn action_terminate_process(
|
||||
&mut self,
|
||||
interface: &mut BoxDashInterface,
|
||||
process: packet_server::WvrProcess,
|
||||
|
||||
@@ -205,11 +205,7 @@ impl EventResult {
|
||||
|
||||
#[must_use]
|
||||
pub fn merge(self, other: Self) -> Self {
|
||||
if self > other {
|
||||
self
|
||||
} else {
|
||||
other
|
||||
}
|
||||
if self > other { self } else { other }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -349,7 +345,6 @@ impl WidgetState {
|
||||
if (scrolling_cur.x - scrolling_target.x).abs() < epsilon
|
||||
&& (scrolling_cur.y - scrolling_target.y).abs() < epsilon
|
||||
{
|
||||
log::info!("stopped animating");
|
||||
*scrolling_cur = *scrolling_target;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user