From 1cbae4c3ad2a2122a396ad12222e065386bcefd5 Mon Sep 17 00:00:00 2001 From: galister <22305755+galister@users.noreply.github.com> Date: Sun, 5 Jul 2026 03:45:29 +0900 Subject: [PATCH] refactor overlay spawning --- wayvr/src/backend/task.rs | 13 ++++++++++++- wayvr/src/backend/wayvr/mod.rs | 5 +++-- wayvr/src/gui/panel/button.rs | 8 +++++--- wayvr/src/overlays/toast.rs | 5 +++-- wayvr/src/windowing/manager.rs | 2 +- wayvr/src/windowing/window.rs | 8 ++++++++ 6 files changed, 32 insertions(+), 9 deletions(-) diff --git a/wayvr/src/backend/task.rs b/wayvr/src/backend/task.rs index 2bc86886..f841c18a 100644 --- a/wayvr/src/backend/task.rs +++ b/wayvr/src/backend/task.rs @@ -85,12 +85,23 @@ pub struct ModifyPanelTask { pub command: ModifyPanelCommand, } +#[derive(Clone, Copy)] pub enum ToggleMode { EnsureOn, EnsureOff, Toggle, } +#[derive(Clone)] +pub enum SpawnPos { + /// Always spawn at the designated pos + Fixed, + /// Automatically spread out for user experience + Spread, + /// Spawn relative to a different overlay + Parent(OverlaySelector), +} + pub type ModifyOverlayTask = dyn FnOnce(&mut AppState, &mut OverlayWindowConfig) + Send; pub type CreateOverlayTask = dyn FnOnce(&mut AppState) -> Option + Send; pub enum OverlayTask { @@ -107,7 +118,7 @@ pub enum OverlayTask { SettingsChanged, KeyboardChanged, Modify(OverlaySelector, Box), - Create(OverlaySelector, Box), + Spawn(OverlaySelector, SpawnPos, Box), ModifyPanel(ModifyPanelTask), Drop(OverlaySelector), } diff --git a/wayvr/src/backend/wayvr/mod.rs b/wayvr/src/backend/wayvr/mod.rs index 3ebfebba..425f6630 100644 --- a/wayvr/src/backend/wayvr/mod.rs +++ b/wayvr/src/backend/wayvr/mod.rs @@ -59,7 +59,7 @@ use xkbcommon::xkb; use crate::{ backend::{ - task::{OverlayTask, TaskContainer, TaskType, ToggleMode}, + task::{OverlayTask, SpawnPos, TaskContainer, TaskType, ToggleMode}, wayvr::{ image_importer::ImageImporter, process::{KillSignal, Process}, @@ -434,8 +434,9 @@ impl WvrServerState { None => DesktopFinder::create_icon(&title)?.into(), }; - app.tasks.enqueue(TaskType::Overlay(OverlayTask::Create( + app.tasks.enqueue(TaskType::Overlay(OverlayTask::Spawn( OverlaySelector::Nothing, + SpawnPos::Spread, Box::new(move |app: &mut AppState| { create_wl_window_overlay( title, diff --git a/wayvr/src/gui/panel/button.rs b/wayvr/src/gui/panel/button.rs index 81dec170..62384500 100644 --- a/wayvr/src/gui/panel/button.rs +++ b/wayvr/src/gui/panel/button.rs @@ -26,7 +26,7 @@ use wlx_common::{config::HandsfreePointer, overlays::ToastTopic}; use crate::{ RESTART, RUNNING, backend::{ - task::{OverlayTask, PlayspaceTask, TaskType, ToggleMode}, + task::{OverlayTask, PlayspaceTask, SpawnPos, TaskType, ToggleMode}, wayvr::process::KillSignal, }, gui::panel::{log_cmd_invalid_arg, log_cmd_missing_arg}, @@ -441,8 +441,9 @@ pub(super) fn setup_custom_button( app.tasks.enqueue(TaskType::Overlay(OverlayTask::Drop( OverlaySelector::Name(name.clone()), ))); - app.tasks.enqueue(TaskType::Overlay(OverlayTask::Create( + app.tasks.enqueue(TaskType::Overlay(OverlayTask::Spawn( OverlaySelector::Name(owc.name.clone()), + SpawnPos::Spread, Box::new(move |app| { if let Some(mut owc) = create_custom(app, name) { owc.show_on_spawn = true; @@ -534,8 +535,9 @@ pub(super) fn setup_custom_button( } let name = crate::overlays::screen::mirror::new_mirror_name(); - app.tasks.enqueue(TaskType::Overlay(OverlayTask::Create( + app.tasks.enqueue(TaskType::Overlay(OverlayTask::Spawn( OverlaySelector::Name(name.clone()), + SpawnPos::Spread, Box::new(move |app| { Some(crate::overlays::screen::mirror::new_mirror( name, diff --git a/wayvr/src/overlays/toast.rs b/wayvr/src/overlays/toast.rs index 76ac4567..13bd53fc 100644 --- a/wayvr/src/overlays/toast.rs +++ b/wayvr/src/overlays/toast.rs @@ -14,7 +14,7 @@ use wlx_common::{ }; use crate::{ - backend::task::{OverlayTask, TaskType}, + backend::task::{OverlayTask, SpawnPos, TaskType}, gui::panel::{GuiPanel, NewGuiPanelParams, OnCustomIdFunc}, state::AppState, windowing::{OverlaySelector, Z_ORDER_TOAST, window::OverlayWindowConfig}, @@ -88,8 +88,9 @@ impl Toast { // multiple toasts are submitted for the same // frame, only the first one gets created app.tasks.enqueue_at( - TaskType::Overlay(OverlayTask::Create( + TaskType::Overlay(OverlayTask::Spawn( selector.clone(), + SpawnPos::Fixed, Box::new(move |app| { let maybe_toast = new_toast(self, app); app.tasks.enqueue_at( diff --git a/wayvr/src/windowing/manager.rs b/wayvr/src/windowing/manager.rs index 2104b80b..069928db 100644 --- a/wayvr/src/windowing/manager.rs +++ b/wayvr/src/windowing/manager.rs @@ -345,7 +345,7 @@ where log::warn!("Overlay not found for task: {sel:?}"); } } - OverlayTask::Create(sel, f) => { + OverlayTask::Spawn(sel, pos, f) => { let None = self.mut_by_selector(&sel) else { log::debug!("Could not create {sel:?}: exists"); return Ok(()); diff --git a/wayvr/src/windowing/window.rs b/wayvr/src/windowing/window.rs index 0060a5e5..0f578060 100644 --- a/wayvr/src/windowing/window.rs +++ b/wayvr/src/windowing/window.rs @@ -309,3 +309,11 @@ 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; + + Affine3A::from_translation((parent.translation + world_offset).into()) +}