mirror of https://github.com/wayvr-org/wayvr.git
smarter overlay spawning
This commit is contained in:
parent
1cbae4c3ad
commit
a9c6599d63
|
|
@ -125,6 +125,7 @@ pub struct WvrServerState {
|
|||
mouse_freeze: Instant,
|
||||
window_to_overlay: HashMap<window::WindowHandle, OverlayID>,
|
||||
overlay_to_window: SecondaryMap<OverlayID, window::WindowHandle>,
|
||||
process_overlays: HashMap<process::ProcessHandle, Vec<OverlayID>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
|
|
@ -274,6 +275,7 @@ impl WvrServerState {
|
|||
mouse_freeze: Instant::now(),
|
||||
window_to_overlay: HashMap::new(),
|
||||
overlay_to_window: SecondaryMap::new(),
|
||||
process_overlays: HashMap::new(),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -379,6 +381,12 @@ impl WvrServerState {
|
|||
.unwrap_or_else(|| format!("P{}", client.pid))
|
||||
.into();
|
||||
|
||||
let spawn_pos = wvr_server
|
||||
.last_process_overlay(process_handle)
|
||||
.map_or(SpawnPos::Spread, |oid| {
|
||||
SpawnPos::Parent(OverlaySelector::Id(oid))
|
||||
});
|
||||
|
||||
let window_handle = wvr_server.wm.create_window(
|
||||
toplevel.clone(),
|
||||
process_handle,
|
||||
|
|
@ -436,7 +444,7 @@ impl WvrServerState {
|
|||
|
||||
app.tasks.enqueue(TaskType::Overlay(OverlayTask::Spawn(
|
||||
OverlaySelector::Nothing,
|
||||
SpawnPos::Spread,
|
||||
spawn_pos,
|
||||
Box::new(move |app: &mut AppState| {
|
||||
create_wl_window_overlay(
|
||||
title,
|
||||
|
|
@ -469,11 +477,31 @@ impl WvrServerState {
|
|||
continue;
|
||||
};
|
||||
|
||||
let process_handle = wvr_server
|
||||
.wm
|
||||
.windows
|
||||
.get(&window_handle)
|
||||
.map(|window| window.process);
|
||||
|
||||
if let Some(oid) = wvr_server.window_to_overlay.remove(&window_handle) {
|
||||
app.tasks.enqueue(TaskType::Overlay(OverlayTask::Drop(
|
||||
OverlaySelector::Id(oid),
|
||||
)));
|
||||
wvr_server.overlay_to_window.remove(oid);
|
||||
|
||||
if let Some(process_handle) = process_handle.as_ref() {
|
||||
let mut empty = false;
|
||||
if let Some(overlays) =
|
||||
wvr_server.process_overlays.get_mut(process_handle)
|
||||
{
|
||||
overlays.retain(|other| *other != oid);
|
||||
empty = overlays.is_empty();
|
||||
}
|
||||
|
||||
if empty {
|
||||
wvr_server.process_overlays.remove(process_handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wvr_server.wm.remove_window(window_handle);
|
||||
|
|
@ -566,6 +594,19 @@ impl WvrServerState {
|
|||
pub fn overlay_added(&mut self, oid: OverlayID, window: window::WindowHandle) {
|
||||
self.overlay_to_window.insert(oid, window);
|
||||
self.window_to_overlay.insert(window, oid);
|
||||
|
||||
if let Some(process_handle) = self.wm.windows.get(&window).map(|window| window.process) {
|
||||
let overlays = self.process_overlays.entry(process_handle).or_default();
|
||||
overlays.retain(|other| *other != oid);
|
||||
overlays.push(oid);
|
||||
}
|
||||
}
|
||||
|
||||
fn last_process_overlay(&self, process_handle: process::ProcessHandle) -> Option<OverlayID> {
|
||||
self.process_overlays
|
||||
.get(&process_handle)
|
||||
.and_then(|overlays| overlays.last())
|
||||
.copied()
|
||||
}
|
||||
|
||||
pub fn process_removed(&mut self, tasks: &mut TaskContainer, process: process::ProcessHandle) {
|
||||
|
|
@ -591,6 +632,8 @@ impl WvrServerState {
|
|||
for hnd in &to_remove {
|
||||
self.wm.windows.remove(hnd);
|
||||
}
|
||||
|
||||
self.process_overlays.remove(&process);
|
||||
}
|
||||
|
||||
pub fn get_overlay_id(&self, window: window::WindowHandle) -> Option<OverlayID> {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ use wlx_common::{
|
|||
|
||||
use crate::{
|
||||
FRAME_COUNTER,
|
||||
backend::task::{OverlayTask, ToggleMode},
|
||||
backend::task::{CreateOverlayTask, OverlayTask, SpawnPos, ToggleMode},
|
||||
config::save_state,
|
||||
overlays::{
|
||||
anchor::{create_anchor, create_grab_help},
|
||||
|
|
@ -34,7 +34,7 @@ use crate::{
|
|||
backend::{OverlayEventData, OverlayMeta},
|
||||
set::OverlayWindowSet,
|
||||
snap_upright,
|
||||
window::{OverlayCategory, OverlayWindowData},
|
||||
window::{OverlayCategory, OverlayWindowData, save_transform, spawn_transform_from_parent},
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -345,24 +345,8 @@ where
|
|||
log::warn!("Overlay not found for task: {sel:?}");
|
||||
}
|
||||
}
|
||||
OverlayTask::Spawn(sel, pos, f) => {
|
||||
let None = self.mut_by_selector(&sel) else {
|
||||
log::debug!("Could not create {sel:?}: exists");
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
let Some(overlay_config) = f(app) else {
|
||||
log::debug!("Could not create {sel:?}: empty config");
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
self.add(
|
||||
OverlayWindowData {
|
||||
birthframe: FRAME_COUNTER.load(Ordering::Relaxed),
|
||||
..OverlayWindowData::from_config(overlay_config)
|
||||
},
|
||||
app,
|
||||
);
|
||||
OverlayTask::Spawn(sel, spawn_pos, f) => {
|
||||
self.spawn_overlay(app, sel, spawn_pos, f)?;
|
||||
}
|
||||
OverlayTask::Drop(sel) => {
|
||||
if let Some(o) = self.mut_by_selector(&sel)
|
||||
|
|
@ -402,6 +386,35 @@ where
|
|||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn spawn_overlay(
|
||||
&mut self,
|
||||
app: &mut AppState,
|
||||
sel: OverlaySelector,
|
||||
spawn_pos: SpawnPos,
|
||||
f: Box<CreateOverlayTask>,
|
||||
) -> anyhow::Result<()> {
|
||||
let None = self.mut_by_selector(&sel) else {
|
||||
log::debug!("Could not spawn {sel:?}: exists");
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
let Some(overlay_config) = f(app) else {
|
||||
log::debug!("Could not spawn {sel:?}: empty config");
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
self.add_with_spawn_pos(
|
||||
OverlayWindowData {
|
||||
birthframe: FRAME_COUNTER.load(Ordering::Relaxed),
|
||||
..OverlayWindowData::from_config(overlay_config)
|
||||
},
|
||||
app,
|
||||
spawn_pos,
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
const SAVED_ATTRIBS: [BackendAttrib; 3] = [
|
||||
|
|
@ -734,7 +747,16 @@ impl<T> OverlayWindowManager<T> {
|
|||
.map(|(k, _)| k)
|
||||
}
|
||||
|
||||
pub fn add(&mut self, mut overlay: OverlayWindowData<T>, app: &mut AppState) -> OverlayID {
|
||||
pub fn add(&mut self, overlay: OverlayWindowData<T>, app: &mut AppState) -> OverlayID {
|
||||
self.add_with_spawn_pos(overlay, app, SpawnPos::Fixed)
|
||||
}
|
||||
|
||||
fn add_with_spawn_pos(
|
||||
&mut self,
|
||||
mut overlay: OverlayWindowData<T>,
|
||||
app: &mut AppState,
|
||||
spawn_pos: SpawnPos,
|
||||
) -> OverlayID {
|
||||
while self.lookup(&overlay.config.name).is_some() {
|
||||
log::error!(
|
||||
"An overlay with name {} already exists. Deduplicating, but things may break!",
|
||||
|
|
@ -778,6 +800,7 @@ impl<T> OverlayWindowManager<T> {
|
|||
if !shown && show_on_spawn {
|
||||
log::debug!("activating {name} due to show_on_spawn");
|
||||
self.overlays[oid].config.activate(app);
|
||||
self.apply_spawn_pos(app, oid, spawn_pos);
|
||||
}
|
||||
if !internal && let Err(e) = self.overlays_changed(app) {
|
||||
log::error!("Error while adding overlay: {e:?}");
|
||||
|
|
@ -788,6 +811,71 @@ impl<T> OverlayWindowManager<T> {
|
|||
oid
|
||||
}
|
||||
|
||||
fn apply_spawn_pos(&mut self, app: &mut AppState, oid: OverlayID, spawn_pos: SpawnPos) {
|
||||
match spawn_pos {
|
||||
SpawnPos::Fixed => {}
|
||||
SpawnPos::Spread => {
|
||||
let Some(parent_id) = self.spread_parent_for(oid) else {
|
||||
return;
|
||||
};
|
||||
let parent = OverlaySelector::Id(parent_id);
|
||||
let _ = self.offset_spawn_from_parent(app, oid, &parent);
|
||||
}
|
||||
SpawnPos::Parent(parent) => {
|
||||
let _ = self.offset_spawn_from_parent(app, oid, &parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: this just uses the last spawned overlay as parent, can probably do better?
|
||||
fn spread_parent_for(&self, oid: OverlayID) -> Option<OverlayID> {
|
||||
self.overlays
|
||||
.iter()
|
||||
.filter(|(id, overlay)| {
|
||||
*id != oid
|
||||
&& overlay.config.active_state.is_some()
|
||||
&& !matches!(
|
||||
overlay.config.category,
|
||||
OverlayCategory::Internal
|
||||
| OverlayCategory::Keyboard
|
||||
| OverlayCategory::Dashboard
|
||||
)
|
||||
})
|
||||
.max_by_key(|(_, overlay)| overlay.birthframe)
|
||||
.map(|(id, _)| id)
|
||||
}
|
||||
|
||||
fn offset_spawn_from_parent(
|
||||
&mut self,
|
||||
app: &mut AppState,
|
||||
oid: OverlayID,
|
||||
parent: &OverlaySelector,
|
||||
) -> Option<()> {
|
||||
let parent_id = self.id_by_selector(parent)?;
|
||||
|
||||
if parent_id == oid {
|
||||
return None;
|
||||
}
|
||||
|
||||
let parent_transform = self
|
||||
.overlays
|
||||
.get(parent_id)?
|
||||
.config
|
||||
.active_state
|
||||
.as_ref()?
|
||||
.transform;
|
||||
|
||||
let spawn_transform = spawn_transform_from_parent(&parent_transform, &app.input_state.hmd);
|
||||
let overlay = self.overlays.get_mut(oid)?;
|
||||
let state = overlay.config.active_state.as_mut()?;
|
||||
|
||||
state.transform = spawn_transform;
|
||||
save_transform(state, app);
|
||||
overlay.config.dirty = true;
|
||||
|
||||
Some(())
|
||||
}
|
||||
|
||||
pub fn switch_or_toggle_set(&mut self, app: &mut AppState, set: usize) {
|
||||
let new_set = if self.current_set.iter().any(|cur| *cur == set) {
|
||||
None
|
||||
|
|
|
|||
|
|
@ -310,10 +310,23 @@ pub fn save_transform(state: &mut OverlayWindowState, app: &mut AppState) {
|
|||
state.saved_transform = Some(parent_transform.inverse() * state.transform);
|
||||
}
|
||||
|
||||
pub fn spawn_transform_from_parent(parent: &Affine3A, _hmd: &Affine3A) -> Affine3A {
|
||||
let local_offset = Vec3A::new(0.08, -0.08, 0.06);
|
||||
let world_offset = parent.x_axis * local_offset.x - parent.y_axis * local_offset.y
|
||||
+ parent.z_axis * local_offset.z;
|
||||
pub fn spawn_transform_from_parent(parent: &Affine3A, hmd: &Affine3A) -> Affine3A {
|
||||
const LEFT: f32 = 0.08;
|
||||
const DOWN: f32 = 0.08;
|
||||
const CLOSER_TO_HMD: f32 = 0.06;
|
||||
|
||||
Affine3A::from_translation((parent.translation + world_offset).into())
|
||||
let x_axis = parent.x_axis.normalize();
|
||||
let y_axis = parent.y_axis.normalize();
|
||||
let z_axis = parent.z_axis.normalize();
|
||||
let to_hmd = hmd.translation - parent.translation;
|
||||
let toward_hmd = if z_axis.dot(to_hmd) >= 0.0 {
|
||||
z_axis
|
||||
} else {
|
||||
-z_axis
|
||||
};
|
||||
|
||||
let world_offset = -x_axis * LEFT - y_axis * DOWN + toward_hmd * CLOSER_TO_HMD;
|
||||
let mut transform = *parent;
|
||||
transform.translation += world_offset;
|
||||
transform
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue