refactor tasks
This commit is contained in:
@@ -8,6 +8,7 @@ use idmap_derive::IntegerId;
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use wlx_common::windowing::{OverlayWindowState, Positioning};
|
||||
|
||||
use crate::backend::task::OverlayTask;
|
||||
use crate::overlays::anchor::ANCHOR_NAME;
|
||||
use crate::state::{AppSession, AppState};
|
||||
use crate::subsystem::hid::WheelDelta;
|
||||
@@ -630,12 +631,12 @@ fn start_grab(
|
||||
};
|
||||
|
||||
// Show anchor
|
||||
app.tasks.enqueue(TaskType::Overlay(
|
||||
app.tasks.enqueue(TaskType::Overlay(OverlayTask::Modify(
|
||||
OverlaySelector::Name(ANCHOR_NAME.clone()),
|
||||
Box::new(|app, o| {
|
||||
o.activate(app);
|
||||
}),
|
||||
));
|
||||
)));
|
||||
}
|
||||
|
||||
fn handle_scale(transform: &mut Affine3A, scroll_y: f32) {
|
||||
@@ -711,12 +712,12 @@ where
|
||||
}
|
||||
|
||||
// Hide anchor
|
||||
app.tasks.enqueue(TaskType::Overlay(
|
||||
app.tasks.enqueue(TaskType::Overlay(OverlayTask::Modify(
|
||||
OverlaySelector::Name(ANCHOR_NAME.clone()),
|
||||
Box::new(|_app, o| {
|
||||
o.deactivate();
|
||||
}),
|
||||
));
|
||||
)));
|
||||
log::debug!("Hand {}: dropped {}", idx, overlay.config.name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
use std::{
|
||||
collections::VecDeque,
|
||||
ops::Add,
|
||||
sync::{
|
||||
atomic::{AtomicBool, AtomicUsize, Ordering},
|
||||
Arc,
|
||||
},
|
||||
sync::atomic::Ordering,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
@@ -26,7 +23,7 @@ use crate::{
|
||||
manifest::{install_manifest, uninstall_manifest},
|
||||
overlay::OpenVrOverlayData,
|
||||
},
|
||||
task::{ManagerTask, SystemTask, TaskType},
|
||||
task::{OpenVrTask, OverlayTask, TaskType},
|
||||
BackendError,
|
||||
},
|
||||
config::save_state,
|
||||
@@ -40,8 +37,8 @@ use crate::{
|
||||
windowing::{
|
||||
backend::{RenderResources, ShouldRender},
|
||||
manager::OverlayWindowManager,
|
||||
window::OverlayWindowData,
|
||||
},
|
||||
RUNNING,
|
||||
};
|
||||
|
||||
#[cfg(feature = "wayvr")]
|
||||
@@ -54,8 +51,6 @@ pub mod manifest;
|
||||
pub mod overlay;
|
||||
pub mod playspace;
|
||||
|
||||
static FRAME_COUNTER: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
pub fn openvr_uninstall() {
|
||||
let app_type = EVRApplicationType::VRApplication_Overlay;
|
||||
let Ok(context) = ovr_overlay::Context::init(app_type) else {
|
||||
@@ -68,11 +63,7 @@ pub fn openvr_uninstall() {
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_lines, clippy::cognitive_complexity)]
|
||||
pub fn openvr_run(
|
||||
running: Arc<AtomicBool>,
|
||||
show_by_default: bool,
|
||||
headless: bool,
|
||||
) -> Result<(), BackendError> {
|
||||
pub fn openvr_run(show_by_default: bool, headless: bool) -> Result<(), BackendError> {
|
||||
let app_type = EVRApplicationType::VRApplication_Overlay;
|
||||
let Ok(context) = ovr_overlay::Context::init(app_type) else {
|
||||
log::warn!("Will not use OpenVR: Context init failed");
|
||||
@@ -107,7 +98,7 @@ pub fn openvr_run(
|
||||
|
||||
if show_by_default {
|
||||
app.tasks.enqueue_at(
|
||||
TaskType::Manager(ManagerTask::ShowHide),
|
||||
TaskType::Overlay(OverlayTask::ShowHide),
|
||||
Instant::now().add(Duration::from_secs(1)),
|
||||
);
|
||||
}
|
||||
@@ -159,13 +150,11 @@ pub fn openvr_run(
|
||||
'main_loop: loop {
|
||||
let _ = overlay_mgr.wait_frame_sync(frame_timeout);
|
||||
|
||||
if !running.load(Ordering::Relaxed) {
|
||||
if !RUNNING.load(Ordering::Relaxed) {
|
||||
log::warn!("Received shutdown signal.");
|
||||
break 'main_loop;
|
||||
}
|
||||
|
||||
let cur_frame = FRAME_COUNTER.fetch_add(1, Ordering::Relaxed);
|
||||
|
||||
while let Some(event) = system_mgr.poll_next_event() {
|
||||
match event.event_type {
|
||||
EVREventType::VREvent_Quit => {
|
||||
@@ -215,52 +204,17 @@ pub fn openvr_run(
|
||||
|
||||
while let Some(task) = due_tasks.pop_front() {
|
||||
match task {
|
||||
TaskType::Overlay(sel, f) => {
|
||||
if let Some(o) = overlays.mut_by_selector(&sel) {
|
||||
f(&mut app, &mut o.config);
|
||||
} else {
|
||||
log::warn!("Overlay not found for task: {sel:?}");
|
||||
}
|
||||
}
|
||||
TaskType::CreateOverlay(sel, f) => {
|
||||
let None = overlays.mut_by_selector(&sel) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let Some(overlay_config) = f(&mut app) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
overlays.add(
|
||||
OverlayWindowData {
|
||||
birthframe: cur_frame,
|
||||
..OverlayWindowData::from_config(overlay_config)
|
||||
},
|
||||
&mut app,
|
||||
);
|
||||
}
|
||||
TaskType::DropOverlay(sel) => {
|
||||
if let Some(o) = overlays.mut_by_selector(&sel)
|
||||
&& o.birthframe < cur_frame
|
||||
{
|
||||
o.destroy(&mut overlay_mgr);
|
||||
overlays.remove_by_selector(&sel, &mut app);
|
||||
}
|
||||
}
|
||||
TaskType::System(task) => match task {
|
||||
SystemTask::ColorGain(channel, value) => {
|
||||
let _ = adjust_gain(&mut settings_mgr, channel, value);
|
||||
}
|
||||
SystemTask::FixFloor => {
|
||||
playspace.fix_floor(&mut chaperone_mgr, &app.input_state);
|
||||
}
|
||||
SystemTask::ResetPlayspace => {
|
||||
playspace.reset_offset(&mut chaperone_mgr, &app.input_state);
|
||||
}
|
||||
},
|
||||
TaskType::Manager(task) => {
|
||||
TaskType::Overlay(task) => {
|
||||
overlays.handle_task(&mut app, task)?;
|
||||
}
|
||||
TaskType::Playspace(task) => {
|
||||
playspace.handle_task(&mut app, &mut chaperone_mgr, task);
|
||||
}
|
||||
TaskType::OpenVR(task) => match task {
|
||||
OpenVrTask::ColorGain(channel, value) => {
|
||||
let _ = adjust_gain(&mut settings_mgr, channel, value);
|
||||
}
|
||||
},
|
||||
#[cfg(feature = "wayvr")]
|
||||
TaskType::WayVR(action) => {
|
||||
wayvr_action(&mut app, &mut overlays, &action);
|
||||
@@ -268,6 +222,10 @@ pub fn openvr_run(
|
||||
}
|
||||
}
|
||||
|
||||
while let Some(mut o) = overlays.pop_dropped() {
|
||||
o.destroy(&mut overlay_mgr);
|
||||
}
|
||||
|
||||
let universe = playspace.get_universe();
|
||||
|
||||
app.input_state.pre_update();
|
||||
|
||||
@@ -6,7 +6,9 @@ use ovr_overlay::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
backend::input::InputState, state::AppState, windowing::manager::OverlayWindowManager,
|
||||
backend::{input::InputState, task::PlayspaceTask},
|
||||
state::AppState,
|
||||
windowing::manager::OverlayWindowManager,
|
||||
};
|
||||
|
||||
use super::{helpers::Affine3AConvert, overlay::OpenVrOverlayData};
|
||||
@@ -32,6 +34,22 @@ impl PlayspaceMover {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_task(
|
||||
&mut self,
|
||||
app: &AppState,
|
||||
chaperone_mgr: &mut ChaperoneSetupManager,
|
||||
task: PlayspaceTask,
|
||||
) {
|
||||
match task {
|
||||
PlayspaceTask::FixFloor => {
|
||||
self.fix_floor(chaperone_mgr, &app.input_state);
|
||||
}
|
||||
PlayspaceTask::ResetPlayspace => {
|
||||
self.reset_offset(chaperone_mgr, &app.input_state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_lines, clippy::cognitive_complexity)]
|
||||
pub fn update(
|
||||
&mut self,
|
||||
|
||||
@@ -2,7 +2,7 @@ use std::{
|
||||
collections::VecDeque,
|
||||
ops::Add,
|
||||
sync::{
|
||||
atomic::{AtomicBool, AtomicUsize, Ordering},
|
||||
atomic::{AtomicBool, Ordering},
|
||||
Arc,
|
||||
},
|
||||
time::{Duration, Instant},
|
||||
@@ -20,7 +20,7 @@ use crate::{
|
||||
backend::{
|
||||
input::interact,
|
||||
openxr::{lines::LinePool, overlay::OpenXrOverlayData},
|
||||
task::{ManagerTask, SystemTask, TaskType},
|
||||
task::{OverlayTask, TaskType},
|
||||
BackendError,
|
||||
},
|
||||
config::save_state,
|
||||
@@ -34,8 +34,8 @@ use crate::{
|
||||
windowing::{
|
||||
backend::{RenderResources, ShouldRender},
|
||||
manager::OverlayWindowManager,
|
||||
window::OverlayWindowData,
|
||||
},
|
||||
FRAME_COUNTER, RUNNING,
|
||||
};
|
||||
|
||||
#[cfg(feature = "wayvr")]
|
||||
@@ -51,7 +51,6 @@ mod skybox;
|
||||
mod swapchain;
|
||||
|
||||
const VIEW_TYPE: xr::ViewConfigurationType = xr::ViewConfigurationType::PRIMARY_STEREO;
|
||||
static FRAME_COUNTER: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
struct XrState {
|
||||
instance: xr::Instance,
|
||||
@@ -63,11 +62,7 @@ struct XrState {
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_lines, clippy::cognitive_complexity)]
|
||||
pub fn openxr_run(
|
||||
running: Arc<AtomicBool>,
|
||||
show_by_default: bool,
|
||||
headless: bool,
|
||||
) -> Result<(), BackendError> {
|
||||
pub fn openxr_run(show_by_default: bool, headless: bool) -> Result<(), BackendError> {
|
||||
let (xr_instance, system) = match helpers::init_xr() {
|
||||
Ok((xr_instance, system)) => (xr_instance, system),
|
||||
Err(e) => {
|
||||
@@ -95,7 +90,7 @@ pub fn openxr_run(
|
||||
|
||||
if show_by_default {
|
||||
app.tasks.enqueue_at(
|
||||
TaskType::Manager(ManagerTask::ShowHide),
|
||||
TaskType::Overlay(OverlayTask::ShowHide),
|
||||
Instant::now().add(Duration::from_secs(1)),
|
||||
);
|
||||
}
|
||||
@@ -178,7 +173,7 @@ pub fn openxr_run(
|
||||
'main_loop: loop {
|
||||
let cur_frame = FRAME_COUNTER.fetch_add(1, Ordering::Relaxed);
|
||||
|
||||
if !running.load(Ordering::Relaxed) {
|
||||
if !RUNNING.load(Ordering::Relaxed) {
|
||||
log::warn!("Received shutdown signal.");
|
||||
match xr_state.session.request_exit() {
|
||||
Ok(()) => log::info!("OpenXR session exit requested."),
|
||||
@@ -493,58 +488,16 @@ pub fn openxr_run(
|
||||
app.tasks.retrieve_due(&mut due_tasks);
|
||||
while let Some(task) = due_tasks.pop_front() {
|
||||
match task {
|
||||
TaskType::Overlay(sel, f) => {
|
||||
if let Some(o) = overlays.mut_by_selector(&sel) {
|
||||
f(&mut app, &mut o.config);
|
||||
} else {
|
||||
log::warn!("Overlay not found for task: {sel:?}");
|
||||
}
|
||||
}
|
||||
TaskType::CreateOverlay(sel, f) => {
|
||||
let None = overlays.mut_by_selector(&sel) else {
|
||||
continue;
|
||||
};
|
||||
let Some(overlay_config) = f(&mut app) else {
|
||||
continue;
|
||||
};
|
||||
overlays.add(
|
||||
OverlayWindowData {
|
||||
birthframe: cur_frame,
|
||||
..OverlayWindowData::from_config(overlay_config)
|
||||
},
|
||||
&mut app,
|
||||
);
|
||||
}
|
||||
TaskType::DropOverlay(sel) => {
|
||||
if let Some(o) = overlays.mut_by_selector(&sel)
|
||||
&& o.birthframe < cur_frame
|
||||
{
|
||||
log::debug!("{}: destroy", o.config.name);
|
||||
if let Some(o) = overlays.remove_by_selector(&sel, &mut app) {
|
||||
// set for deletion after all images are done showing
|
||||
delete_queue.push((o, cur_frame + 5));
|
||||
}
|
||||
}
|
||||
}
|
||||
TaskType::System(task) => match task {
|
||||
SystemTask::FixFloor => {
|
||||
if let Some(ref mut playspace) = playspace {
|
||||
playspace.fix_floor(
|
||||
&app.input_state,
|
||||
monado.as_mut().unwrap(), // safe
|
||||
);
|
||||
}
|
||||
}
|
||||
SystemTask::ResetPlayspace => {
|
||||
if let Some(ref mut playspace) = playspace {
|
||||
playspace.reset_offset(monado.as_mut().unwrap()); // safe
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
TaskType::Manager(task) => {
|
||||
TaskType::Overlay(task) => {
|
||||
overlays.handle_task(&mut app, task)?;
|
||||
}
|
||||
TaskType::Playspace(task) => {
|
||||
if let (Some(playspace), Some(monado)) = (playspace.as_mut(), monado.as_mut()) {
|
||||
playspace.handle_task(&mut app, monado, task);
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "openvr")]
|
||||
TaskType::OpenVR(_) => {}
|
||||
#[cfg(feature = "wayvr")]
|
||||
TaskType::WayVR(action) => {
|
||||
wayvr_action(&mut app, &mut overlays, &action);
|
||||
@@ -552,6 +505,10 @@ pub fn openxr_run(
|
||||
}
|
||||
}
|
||||
|
||||
while let Some(o) = overlays.pop_dropped() {
|
||||
delete_queue.push((o, cur_frame + 5));
|
||||
}
|
||||
|
||||
delete_queue.retain(|(_, frame)| *frame > cur_frame);
|
||||
|
||||
//FIXME: Temporary workaround for Monado bug
|
||||
|
||||
@@ -2,7 +2,9 @@ use glam::{Affine3A, Quat, Vec3A};
|
||||
use libmonado::{Monado, Pose, ReferenceSpaceType};
|
||||
|
||||
use crate::{
|
||||
backend::input::InputState, state::AppState, windowing::manager::OverlayWindowManager,
|
||||
backend::{input::InputState, task::PlayspaceTask},
|
||||
state::AppState,
|
||||
windowing::manager::OverlayWindowManager,
|
||||
};
|
||||
|
||||
use super::overlay::OpenXrOverlayData;
|
||||
@@ -41,6 +43,17 @@ impl PlayspaceMover {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn handle_task(&mut self, app: &AppState, monado: &mut Monado, task: PlayspaceTask) {
|
||||
match task {
|
||||
PlayspaceTask::FixFloor => {
|
||||
self.fix_floor(&app.input_state, monado);
|
||||
}
|
||||
PlayspaceTask::ResetPlayspace => {
|
||||
self.reset_offset(monado);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(
|
||||
&mut self,
|
||||
overlays: &mut OverlayWindowManager<OpenXrOverlayData>,
|
||||
|
||||
@@ -43,28 +43,34 @@ impl Ord for AppTask {
|
||||
}
|
||||
}
|
||||
|
||||
pub enum SystemTask {
|
||||
#[cfg(feature = "openvr")]
|
||||
pub enum OpenVrTask {
|
||||
ColorGain(ColorChannel, f32),
|
||||
}
|
||||
|
||||
pub enum PlayspaceTask {
|
||||
ResetPlayspace,
|
||||
FixFloor,
|
||||
}
|
||||
|
||||
pub type OverlayTask = dyn FnOnce(&mut AppState, &mut OverlayWindowConfig) + Send;
|
||||
pub type ModifyOverlayTask = dyn FnOnce(&mut AppState, &mut OverlayWindowConfig) + Send;
|
||||
pub type CreateOverlayTask = dyn FnOnce(&mut AppState) -> Option<OverlayWindowConfig> + Send;
|
||||
pub enum ManagerTask {
|
||||
pub enum OverlayTask {
|
||||
AddSet,
|
||||
ToggleSet(usize),
|
||||
DeleteActiveSet,
|
||||
ToggleEditMode,
|
||||
ShowHide,
|
||||
Modify(OverlaySelector, Box<ModifyOverlayTask>),
|
||||
Create(OverlaySelector, Box<CreateOverlayTask>),
|
||||
Drop(OverlaySelector),
|
||||
}
|
||||
|
||||
pub enum TaskType {
|
||||
Overlay(OverlaySelector, Box<OverlayTask>),
|
||||
CreateOverlay(OverlaySelector, Box<CreateOverlayTask>),
|
||||
DropOverlay(OverlaySelector),
|
||||
Manager(ManagerTask),
|
||||
System(SystemTask),
|
||||
Overlay(OverlayTask),
|
||||
Playspace(PlayspaceTask),
|
||||
#[cfg(feature = "openvr")]
|
||||
OpenVR(OpenVrTask),
|
||||
#[cfg(feature = "wayvr")]
|
||||
WayVR(WayVRAction),
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ use wgui::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
backend::task::{ManagerTask, TaskType},
|
||||
backend::task::{OverlayTask, TaskType},
|
||||
state::AppState,
|
||||
windowing::OverlaySelector,
|
||||
};
|
||||
@@ -58,7 +58,7 @@ pub(super) fn setup_custom_button<S: 'static>(
|
||||
};
|
||||
Box::new(move |_common, _data, app, _| {
|
||||
app.tasks
|
||||
.enqueue(TaskType::Manager(ManagerTask::ToggleSet(set_idx)));
|
||||
.enqueue(TaskType::Overlay(OverlayTask::ToggleSet(set_idx)));
|
||||
Ok(EventResult::Consumed)
|
||||
})
|
||||
}
|
||||
@@ -69,7 +69,7 @@ pub(super) fn setup_custom_button<S: 'static>(
|
||||
};
|
||||
|
||||
Box::new(move |_common, _data, app, _| {
|
||||
app.tasks.enqueue(TaskType::Overlay(
|
||||
app.tasks.enqueue(TaskType::Overlay(OverlayTask::Modify(
|
||||
OverlaySelector::Name(arg.clone()),
|
||||
Box::new(move |app, owc| {
|
||||
if owc.active_state.is_none() {
|
||||
@@ -78,13 +78,13 @@ pub(super) fn setup_custom_button<S: 'static>(
|
||||
owc.deactivate();
|
||||
}
|
||||
}),
|
||||
));
|
||||
)));
|
||||
Ok(EventResult::Consumed)
|
||||
})
|
||||
}
|
||||
"::EditToggle" => Box::new(move |_common, _data, app, _| {
|
||||
app.tasks
|
||||
.enqueue(TaskType::Manager(ManagerTask::ToggleEditMode));
|
||||
.enqueue(TaskType::Overlay(OverlayTask::ToggleEditMode));
|
||||
Ok(EventResult::Consumed)
|
||||
}),
|
||||
"::WatchHide" => todo!(),
|
||||
|
||||
@@ -33,10 +33,7 @@ mod config_wayvr;
|
||||
|
||||
use std::{
|
||||
path::PathBuf,
|
||||
sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
Arc,
|
||||
},
|
||||
sync::atomic::{AtomicBool, AtomicUsize, Ordering},
|
||||
};
|
||||
|
||||
use clap::Parser;
|
||||
@@ -45,6 +42,9 @@ use sysinfo::Pid;
|
||||
use tracing::level_filters::LevelFilter;
|
||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter};
|
||||
|
||||
pub static FRAME_COUNTER: AtomicUsize = AtomicUsize::new(0);
|
||||
pub static RUNNING: AtomicBool = AtomicBool::new(true);
|
||||
|
||||
/// The lightweight desktop overlay for OpenVR and OpenXR
|
||||
#[derive(Default, Parser, Debug)]
|
||||
#[command(version, about, long_about = None)]
|
||||
@@ -82,11 +82,6 @@ struct Args {
|
||||
/// Path to write logs to
|
||||
#[arg(short, long, value_name = "FILE_PATH")]
|
||||
log_to: Option<String>,
|
||||
|
||||
#[cfg(feature = "uidev")]
|
||||
/// Show a desktop window of a UI panel for development
|
||||
#[arg(short, long, value_name = "UI_NAME")]
|
||||
uidev: Option<String>,
|
||||
}
|
||||
|
||||
#[allow(clippy::unnecessary_wraps)]
|
||||
@@ -118,21 +113,19 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let running = Arc::new(AtomicBool::new(true));
|
||||
let _ = ctrlc::set_handler({
|
||||
let running = running.clone();
|
||||
move || {
|
||||
running.store(false, Ordering::Relaxed);
|
||||
|| {
|
||||
RUNNING.store(false, Ordering::Relaxed);
|
||||
}
|
||||
});
|
||||
|
||||
auto_run(running, args);
|
||||
auto_run(args);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(unused_mut, clippy::similar_names)]
|
||||
fn auto_run(running: Arc<AtomicBool>, args: Args) {
|
||||
fn auto_run(args: Args) {
|
||||
let mut tried_xr = false;
|
||||
let mut tried_vr = false;
|
||||
|
||||
@@ -140,7 +133,7 @@ fn auto_run(running: Arc<AtomicBool>, args: Args) {
|
||||
if !args_get_openvr(&args) {
|
||||
use crate::backend::{openxr::openxr_run, BackendError};
|
||||
tried_xr = true;
|
||||
match openxr_run(running.clone(), args.show, args.headless) {
|
||||
match openxr_run(args.show, args.headless) {
|
||||
Ok(()) => return,
|
||||
Err(BackendError::NotSupported) => (),
|
||||
Err(e) => {
|
||||
@@ -154,7 +147,7 @@ fn auto_run(running: Arc<AtomicBool>, args: Args) {
|
||||
if !args_get_openxr(&args) {
|
||||
use crate::backend::{openvr::openvr_run, BackendError};
|
||||
tried_vr = true;
|
||||
match openvr_run(running, args.show, args.headless) {
|
||||
match openvr_run(args.show, args.headless) {
|
||||
Ok(()) => return,
|
||||
Err(BackendError::NotSupported) => (),
|
||||
Err(e) => {
|
||||
|
||||
@@ -7,7 +7,7 @@ use wgui::{
|
||||
widget::rectangle::WidgetRectangle,
|
||||
};
|
||||
|
||||
use crate::{backend::task::OverlayTask, overlays::edit::EditModeWrapPanel, state::AppState};
|
||||
use crate::{backend::task::ModifyOverlayTask, overlays::edit::EditModeWrapPanel, state::AppState};
|
||||
|
||||
#[derive(Default)]
|
||||
pub(super) struct InteractLockHandler {
|
||||
@@ -53,7 +53,7 @@ impl InteractLockHandler {
|
||||
&mut self,
|
||||
common: &mut CallbackDataCommon,
|
||||
app: &mut AppState,
|
||||
) -> Box<OverlayTask> {
|
||||
) -> Box<ModifyOverlayTask> {
|
||||
let defaults = app.wgui_globals.get().defaults.clone();
|
||||
let rect_color = self.color;
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ use wgui::{
|
||||
use crate::{
|
||||
backend::{
|
||||
input::HoverResult,
|
||||
task::{TaskContainer, TaskType},
|
||||
task::{OverlayTask, TaskContainer, TaskType},
|
||||
},
|
||||
gui::panel::{button::BUTTON_EVENTS, GuiPanel, NewGuiPanelParams, OnCustomAttribFunc},
|
||||
overlays::edit::{
|
||||
@@ -247,7 +247,8 @@ fn make_edit_panel(app: &mut AppState) -> anyhow::Result<EditModeWrapPanel> {
|
||||
"::EditModeToggleLock" => Box::new(move |common, _data, app, state| {
|
||||
let sel = OverlaySelector::Id(*state.id.borrow());
|
||||
let task = state.lock.toggle(common, app);
|
||||
app.tasks.enqueue(TaskType::Overlay(sel, task));
|
||||
app.tasks
|
||||
.enqueue(TaskType::Overlay(OverlayTask::Modify(sel, task)));
|
||||
Ok(EventResult::Consumed)
|
||||
}),
|
||||
"::EditModeTab" => {
|
||||
@@ -262,7 +263,8 @@ fn make_edit_panel(app: &mut AppState) -> anyhow::Result<EditModeWrapPanel> {
|
||||
Box::new(move |common, _data, app, state| {
|
||||
let sel = OverlaySelector::Id(*state.id.borrow());
|
||||
let task = state.pos.pos_button_clicked(common, &pos_key);
|
||||
app.tasks.enqueue(TaskType::Overlay(sel, task));
|
||||
app.tasks
|
||||
.enqueue(TaskType::Overlay(OverlayTask::Modify(sel, task)));
|
||||
Ok(EventResult::Consumed)
|
||||
})
|
||||
}
|
||||
@@ -275,12 +277,12 @@ fn make_edit_panel(app: &mut AppState) -> anyhow::Result<EditModeWrapPanel> {
|
||||
if state.delete.pressed.elapsed() < Duration::from_secs(1) {
|
||||
return Ok(EventResult::Pass);
|
||||
}
|
||||
app.tasks.enqueue(TaskType::Overlay(
|
||||
app.tasks.enqueue(TaskType::Overlay(OverlayTask::Modify(
|
||||
OverlaySelector::Id(*state.id.borrow()),
|
||||
Box::new(move |_app, owc| {
|
||||
owc.active_state = None;
|
||||
}),
|
||||
));
|
||||
)));
|
||||
Ok(EventResult::Consumed)
|
||||
}),
|
||||
_ => return,
|
||||
@@ -384,10 +386,10 @@ fn set_up_slider(
|
||||
let mut tasks = tasks.borrow_mut();
|
||||
let e_value = e.value;
|
||||
|
||||
tasks.enqueue(TaskType::Overlay(
|
||||
tasks.enqueue(TaskType::Overlay(OverlayTask::Modify(
|
||||
OverlaySelector::Id(*overlay_id.borrow()),
|
||||
Box::new(move |app, owc| callback(app, owc, e_value)),
|
||||
));
|
||||
)));
|
||||
Ok(())
|
||||
}));
|
||||
|
||||
@@ -408,10 +410,10 @@ fn set_up_checkbox(
|
||||
let mut tasks = tasks.borrow_mut();
|
||||
let e_checked = e.checked;
|
||||
|
||||
tasks.enqueue(TaskType::Overlay(
|
||||
tasks.enqueue(TaskType::Overlay(OverlayTask::Modify(
|
||||
OverlaySelector::Id(*overlay_id.borrow()),
|
||||
Box::new(move |app, owc| callback(app, owc, e_checked)),
|
||||
));
|
||||
)));
|
||||
Ok(())
|
||||
}));
|
||||
|
||||
|
||||
@@ -7,7 +7,9 @@ use wgui::{
|
||||
};
|
||||
use wlx_common::{common::LeftRight, windowing::Positioning};
|
||||
|
||||
use crate::{backend::task::OverlayTask, overlays::edit::EditModeWrapPanel, windowing::window};
|
||||
use crate::{
|
||||
backend::task::ModifyOverlayTask, overlays::edit::EditModeWrapPanel, windowing::window,
|
||||
};
|
||||
|
||||
static POS_NAMES: [&str; 6] = ["static", "anchored", "floating", "hmd", "hand_l", "hand_r"];
|
||||
|
||||
@@ -89,7 +91,7 @@ impl PositioningHandler {
|
||||
&mut self,
|
||||
common: &mut CallbackDataCommon,
|
||||
key: &str,
|
||||
) -> Box<OverlayTask> {
|
||||
) -> Box<ModifyOverlayTask> {
|
||||
self.change_highlight(common, key);
|
||||
|
||||
let pos = key_to_pos(key);
|
||||
|
||||
@@ -11,7 +11,7 @@ use wlx_common::windowing::OverlayWindowState;
|
||||
use crate::{
|
||||
backend::{
|
||||
input::{HoverResult, PointerHit},
|
||||
task::TaskType,
|
||||
task::{OverlayTask, TaskType},
|
||||
},
|
||||
state::{AppSession, AppState},
|
||||
subsystem::hid::WheelDelta,
|
||||
@@ -73,21 +73,21 @@ impl OverlayBackend for MirrorBackend {
|
||||
let capture = PipewireCapture::new(self.name.clone(), node_id);
|
||||
self.renderer =
|
||||
Some(ScreenBackend::new_raw(self.name.clone(), Box::new(capture)));
|
||||
app.tasks.enqueue(TaskType::Overlay(
|
||||
app.tasks.enqueue(TaskType::Overlay(OverlayTask::Modify(
|
||||
OverlaySelector::Name(self.name.clone()),
|
||||
Box::new(|app, o| {
|
||||
o.activate(app);
|
||||
}),
|
||||
));
|
||||
)));
|
||||
}
|
||||
Err(e) => {
|
||||
log::warn!("Failed to create mirror due to PipeWire error: {e:?}");
|
||||
self.renderer = None;
|
||||
// drop self
|
||||
app.tasks
|
||||
.enqueue(TaskType::DropOverlay(OverlaySelector::Name(
|
||||
.enqueue(TaskType::Overlay(OverlayTask::Drop(OverlaySelector::Name(
|
||||
self.name.clone(),
|
||||
)));
|
||||
))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ use std::{
|
||||
time::Instant,
|
||||
};
|
||||
|
||||
use glam::{Affine3A, Quat, Vec3, vec3};
|
||||
use glam::{vec3, Affine3A, Quat, Vec3};
|
||||
use wgui::{
|
||||
i18n::Translation,
|
||||
parser::parse_color_hex,
|
||||
@@ -27,10 +27,10 @@ use wlx_common::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
backend::task::TaskType,
|
||||
backend::task::{OverlayTask, TaskType},
|
||||
gui::panel::GuiPanel,
|
||||
state::AppState,
|
||||
windowing::{OverlaySelector, Z_ORDER_TOAST, window::OverlayWindowConfig},
|
||||
windowing::{window::OverlayWindowConfig, OverlaySelector, Z_ORDER_TOAST},
|
||||
};
|
||||
|
||||
const FONT_SIZE: isize = 16;
|
||||
@@ -86,27 +86,29 @@ impl Toast {
|
||||
// drop any toast that was created before us.
|
||||
// (DropOverlay only drops overlays that were
|
||||
// created before current frame)
|
||||
app.tasks
|
||||
.enqueue_at(TaskType::DropOverlay(selector.clone()), instant);
|
||||
app.tasks.enqueue_at(
|
||||
TaskType::Overlay(OverlayTask::Drop(selector.clone())),
|
||||
instant,
|
||||
);
|
||||
|
||||
// CreateOverlay only creates the overlay if
|
||||
// the selector doesn't exist yet, so in case
|
||||
// multiple toasts are submitted for the same
|
||||
// frame, only the first one gets created
|
||||
app.tasks.enqueue_at(
|
||||
TaskType::CreateOverlay(
|
||||
TaskType::Overlay(OverlayTask::Create(
|
||||
selector.clone(),
|
||||
Box::new(move |app| {
|
||||
let maybe_toast = new_toast(self, app);
|
||||
app.tasks.enqueue_at(
|
||||
// at timeout, drop the overlay by ID instead
|
||||
// in order to avoid dropping any newer toasts
|
||||
TaskType::DropOverlay(selector),
|
||||
TaskType::Overlay(OverlayTask::Drop(selector)),
|
||||
destroy_at,
|
||||
);
|
||||
maybe_toast
|
||||
}),
|
||||
),
|
||||
)),
|
||||
instant,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -14,26 +14,26 @@ use wgui::{
|
||||
parser::Fetchable,
|
||||
renderer_vk::text::custom_glyph::CustomGlyphData,
|
||||
taffy,
|
||||
widget::{EventResult, sprite::WidgetSprite},
|
||||
widget::{sprite::WidgetSprite, EventResult},
|
||||
};
|
||||
use wlx_common::windowing::{OverlayWindowState, Positioning};
|
||||
|
||||
use crate::{
|
||||
backend::{
|
||||
input::TrackedDeviceRole,
|
||||
task::{ManagerTask, TaskType},
|
||||
task::{OverlayTask, TaskType},
|
||||
},
|
||||
gui::{
|
||||
panel::{GuiPanel, NewGuiPanelParams, OnCustomAttribFunc, button::BUTTON_EVENTS},
|
||||
panel::{button::BUTTON_EVENTS, GuiPanel, NewGuiPanelParams, OnCustomAttribFunc},
|
||||
timer::GuiTimer,
|
||||
},
|
||||
overlays::edit::LongPressButtonState,
|
||||
state::AppState,
|
||||
windowing::{
|
||||
OverlaySelector, Z_ORDER_WATCH,
|
||||
backend::{OverlayEventData, OverlayMeta},
|
||||
manager::MAX_OVERLAY_SETS,
|
||||
window::{OverlayWindowConfig, OverlayWindowData},
|
||||
OverlaySelector, Z_ORDER_WATCH,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -81,11 +81,11 @@ pub fn create_watch(app: &mut AppState) -> anyhow::Result<OverlayWindowConfig> {
|
||||
return Ok(EventResult::Consumed);
|
||||
}
|
||||
app.tasks
|
||||
.enqueue(TaskType::Manager(ManagerTask::DeleteActiveSet));
|
||||
.enqueue(TaskType::Overlay(OverlayTask::DeleteActiveSet));
|
||||
Ok(EventResult::Consumed)
|
||||
}),
|
||||
"::EditModeAddSet" => Box::new(move |_common, _data, app, _state| {
|
||||
app.tasks.enqueue(TaskType::Manager(ManagerTask::AddSet));
|
||||
app.tasks.enqueue(TaskType::Overlay(OverlayTask::AddSet));
|
||||
Ok(EventResult::Consumed)
|
||||
}),
|
||||
"::EditModeOverlayToggle" => {
|
||||
@@ -100,7 +100,7 @@ pub fn create_watch(app: &mut AppState) -> anyhow::Result<OverlayWindowConfig> {
|
||||
return Ok(EventResult::Consumed);
|
||||
};
|
||||
|
||||
app.tasks.enqueue(TaskType::Overlay(
|
||||
app.tasks.enqueue(TaskType::Overlay(OverlayTask::Modify(
|
||||
OverlaySelector::Id(overlay.id),
|
||||
Box::new(move |app, owc| {
|
||||
if owc.active_state.is_none() {
|
||||
@@ -109,7 +109,7 @@ pub fn create_watch(app: &mut AppState) -> anyhow::Result<OverlayWindowConfig> {
|
||||
owc.deactivate();
|
||||
}
|
||||
}),
|
||||
));
|
||||
)));
|
||||
Ok(EventResult::Consumed)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ use wlx_common::windowing::OverlayWindowState;
|
||||
use crate::{
|
||||
backend::{
|
||||
input::{self, HoverResult},
|
||||
task::TaskType,
|
||||
task::{OverlayTask, TaskType},
|
||||
wayvr::{
|
||||
self, display,
|
||||
server_ipc::{gen_args_vec, gen_env_vec},
|
||||
@@ -332,12 +332,12 @@ where
|
||||
WvrStateChanged::DashboardHidden
|
||||
}));
|
||||
|
||||
app.tasks.enqueue(TaskType::Overlay(
|
||||
app.tasks.enqueue(TaskType::Overlay(OverlayTask::Modify(
|
||||
OverlaySelector::Id(overlay_id),
|
||||
Box::new(move |app, o| {
|
||||
o.toggle(app);
|
||||
}),
|
||||
));
|
||||
)));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -429,12 +429,12 @@ where
|
||||
.data
|
||||
.state
|
||||
.set_display_visible(display_handle, visible);
|
||||
app.tasks.enqueue(TaskType::Overlay(
|
||||
app.tasks.enqueue(TaskType::Overlay(OverlayTask::Modify(
|
||||
OverlaySelector::Id(overlay_id),
|
||||
Box::new(move |app, o| {
|
||||
o.toggle(app);
|
||||
}),
|
||||
));
|
||||
)));
|
||||
}
|
||||
}
|
||||
wayvr::WayVRSignal::DisplayWindowLayout(display_handle, layout) => {
|
||||
@@ -448,7 +448,9 @@ where
|
||||
}
|
||||
wayvr::WayVRSignal::DropOverlay(overlay_id) => {
|
||||
app.tasks
|
||||
.enqueue(TaskType::DropOverlay(OverlaySelector::Id(overlay_id)));
|
||||
.enqueue(TaskType::Overlay(OverlayTask::Drop(OverlaySelector::Id(
|
||||
overlay_id,
|
||||
))));
|
||||
}
|
||||
wayvr::WayVRSignal::Haptics(haptics) => {
|
||||
wayvr.pending_haptics = Some(haptics);
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
use std::collections::HashMap;
|
||||
use std::{
|
||||
collections::{HashMap, VecDeque},
|
||||
sync::atomic::Ordering,
|
||||
};
|
||||
|
||||
use glam::{Affine3A, Vec3, Vec3A};
|
||||
use slotmap::{HopSlotMap, Key, SecondaryMap};
|
||||
use wlx_common::{config::SerializedWindowSet, overlays::ToastTopic};
|
||||
|
||||
use crate::{
|
||||
backend::task::ManagerTask,
|
||||
backend::task::OverlayTask,
|
||||
overlays::{
|
||||
anchor::create_anchor, edit::EditWrapperManager, keyboard::builder::create_keyboard,
|
||||
screen::create_screens, toast::Toast, watch::create_watch,
|
||||
@@ -18,6 +21,7 @@ use crate::{
|
||||
window::{OverlayCategory, OverlayWindowData},
|
||||
OverlayID, OverlaySelector,
|
||||
},
|
||||
FRAME_COUNTER,
|
||||
};
|
||||
|
||||
pub const MAX_OVERLAY_SETS: usize = 7;
|
||||
@@ -34,6 +38,7 @@ pub struct OverlayWindowManager<T> {
|
||||
anchor_local: Affine3A,
|
||||
watch_id: OverlayID,
|
||||
edit_mode: bool,
|
||||
dropped_overlays: VecDeque<OverlayWindowData<T>>,
|
||||
}
|
||||
|
||||
impl<T> OverlayWindowManager<T>
|
||||
@@ -52,6 +57,7 @@ where
|
||||
anchor_local: Affine3A::from_translation(Vec3::NEG_Z),
|
||||
watch_id: OverlayID::null(), // set down below
|
||||
edit_mode: false,
|
||||
dropped_overlays: VecDeque::with_capacity(8),
|
||||
};
|
||||
|
||||
if headless {
|
||||
@@ -119,9 +125,104 @@ where
|
||||
|
||||
Ok(me)
|
||||
}
|
||||
|
||||
pub fn handle_task(&mut self, app: &mut AppState, task: OverlayTask) -> anyhow::Result<()> {
|
||||
match task {
|
||||
OverlayTask::ShowHide => self.show_hide(app),
|
||||
OverlayTask::ToggleSet(set) => {
|
||||
self.switch_or_toggle_set(app, set);
|
||||
}
|
||||
OverlayTask::ToggleEditMode => {
|
||||
self.set_edit_mode(!self.edit_mode, app)?;
|
||||
}
|
||||
OverlayTask::AddSet => {
|
||||
self.sets.push(OverlayWindowSet::default());
|
||||
let len = self.sets.len();
|
||||
if let Some(watch) = self.mut_by_id(self.watch_id) {
|
||||
watch
|
||||
.config
|
||||
.backend
|
||||
.notify(app, OverlayEventData::NumSetsChanged(len))?;
|
||||
}
|
||||
}
|
||||
OverlayTask::DeleteActiveSet => {
|
||||
let Some(set) = self.current_set else {
|
||||
Toast::new(
|
||||
ToastTopic::System,
|
||||
"Can't remove set".into(),
|
||||
"No set is selected!".into(),
|
||||
)
|
||||
.with_timeout(5.)
|
||||
.with_sound(true)
|
||||
.submit(app);
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
if self.sets.len() <= 1 {
|
||||
Toast::new(
|
||||
ToastTopic::System,
|
||||
"Can't remove set".into(),
|
||||
"This is the last existing set!".into(),
|
||||
)
|
||||
.with_timeout(5.)
|
||||
.with_sound(true)
|
||||
.submit(app);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
self.switch_to_set(app, None);
|
||||
self.sets.remove(set);
|
||||
let len = self.sets.len();
|
||||
if let Some(watch) = self.mut_by_id(self.watch_id) {
|
||||
watch
|
||||
.config
|
||||
.backend
|
||||
.notify(app, OverlayEventData::NumSetsChanged(len))?;
|
||||
}
|
||||
}
|
||||
OverlayTask::Modify(sel, f) => {
|
||||
if let Some(o) = self.mut_by_selector(&sel) {
|
||||
f(app, &mut o.config);
|
||||
} else {
|
||||
log::warn!("Overlay not found for task: {sel:?}");
|
||||
}
|
||||
}
|
||||
OverlayTask::Create(sel, f) => {
|
||||
let None = self.mut_by_selector(&sel) else {
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
let Some(overlay_config) = f(app) else {
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
self.add(
|
||||
OverlayWindowData {
|
||||
birthframe: FRAME_COUNTER.load(Ordering::Relaxed),
|
||||
..OverlayWindowData::from_config(overlay_config)
|
||||
},
|
||||
app,
|
||||
);
|
||||
}
|
||||
OverlayTask::Drop(sel) => {
|
||||
if let Some(o) = self.mut_by_selector(&sel)
|
||||
&& o.birthframe < FRAME_COUNTER.load(Ordering::Relaxed)
|
||||
{
|
||||
if let Some(o) = self.remove_by_selector(&sel, app) {
|
||||
self.dropped_overlays.push_back(o);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> OverlayWindowManager<T> {
|
||||
pub fn pop_dropped(&mut self) -> Option<OverlayWindowData<T>> {
|
||||
self.dropped_overlays.pop_front()
|
||||
}
|
||||
|
||||
pub fn persist_layout(&mut self, app: &mut AppState) {
|
||||
app.session.config.sets.clear();
|
||||
app.session.config.sets.reserve(self.sets.len());
|
||||
@@ -390,65 +491,6 @@ impl<T> OverlayWindowManager<T> {
|
||||
self.mut_by_id(self.watch_id).unwrap().config.activate(app);
|
||||
}
|
||||
|
||||
pub fn handle_task(&mut self, app: &mut AppState, task: ManagerTask) -> anyhow::Result<()> {
|
||||
match task {
|
||||
ManagerTask::ShowHide => self.show_hide(app),
|
||||
ManagerTask::ToggleSet(set) => {
|
||||
self.switch_or_toggle_set(app, set);
|
||||
}
|
||||
ManagerTask::ToggleEditMode => {
|
||||
self.set_edit_mode(!self.edit_mode, app)?;
|
||||
}
|
||||
ManagerTask::AddSet => {
|
||||
self.sets.push(OverlayWindowSet::default());
|
||||
let len = self.sets.len();
|
||||
if let Some(watch) = self.mut_by_id(self.watch_id) {
|
||||
watch
|
||||
.config
|
||||
.backend
|
||||
.notify(app, OverlayEventData::NumSetsChanged(len))?;
|
||||
}
|
||||
}
|
||||
ManagerTask::DeleteActiveSet => {
|
||||
let Some(set) = self.current_set else {
|
||||
Toast::new(
|
||||
ToastTopic::System,
|
||||
"Can't remove set".into(),
|
||||
"No set is selected!".into(),
|
||||
)
|
||||
.with_timeout(5.)
|
||||
.with_sound(true)
|
||||
.submit(app);
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
if self.sets.len() <= 1 {
|
||||
Toast::new(
|
||||
ToastTopic::System,
|
||||
"Can't remove set".into(),
|
||||
"This is the last existing set!".into(),
|
||||
)
|
||||
.with_timeout(5.)
|
||||
.with_sound(true)
|
||||
.submit(app);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
self.switch_to_set(app, None);
|
||||
self.sets.remove(set);
|
||||
let len = self.sets.len();
|
||||
if let Some(watch) = self.mut_by_id(self.watch_id) {
|
||||
watch
|
||||
.config
|
||||
.backend
|
||||
.notify(app, OverlayEventData::NumSetsChanged(len))?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn overlays_changed(&mut self, app: &mut AppState) -> anyhow::Result<()> {
|
||||
let mut meta = Vec::with_capacity(self.overlays.len());
|
||||
for (id, data) in &self.overlays {
|
||||
|
||||
Reference in New Issue
Block a user