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