refactor overlay windowing
This commit is contained in:
@@ -1,30 +1,31 @@
|
||||
use glam::Vec3A;
|
||||
use glam::{Affine3A, Quat, Vec3};
|
||||
use std::sync::{Arc, LazyLock};
|
||||
|
||||
use crate::backend::overlay::{OverlayData, OverlayState, Positioning, Z_ORDER_ANCHOR};
|
||||
use crate::gui::panel::GuiPanel;
|
||||
use crate::state::AppState;
|
||||
use crate::windowing::window::{OverlayWindowConfig, OverlayWindowState, Positioning};
|
||||
use crate::windowing::Z_ORDER_ANCHOR;
|
||||
|
||||
pub static ANCHOR_NAME: LazyLock<Arc<str>> = LazyLock::new(|| Arc::from("anchor"));
|
||||
|
||||
pub fn create_anchor<O>(app: &mut AppState) -> anyhow::Result<OverlayData<O>>
|
||||
where
|
||||
O: Default,
|
||||
{
|
||||
pub fn create_anchor(app: &mut AppState) -> anyhow::Result<OverlayWindowConfig> {
|
||||
let panel = GuiPanel::new_from_template(app, "gui/anchor.xml", (), None)?;
|
||||
|
||||
Ok(OverlayData {
|
||||
state: OverlayState {
|
||||
name: ANCHOR_NAME.clone(),
|
||||
want_visible: false,
|
||||
Ok(OverlayWindowConfig {
|
||||
name: ANCHOR_NAME.clone(),
|
||||
z_order: Z_ORDER_ANCHOR,
|
||||
default_state: OverlayWindowState {
|
||||
interactable: false,
|
||||
grabbable: false,
|
||||
z_order: Z_ORDER_ANCHOR,
|
||||
spawn_scale: 0.1,
|
||||
spawn_point: Vec3A::NEG_Z * 0.5,
|
||||
positioning: Positioning::Static,
|
||||
..Default::default()
|
||||
transform: Affine3A::from_scale_rotation_translation(
|
||||
Vec3::ONE * 0.1,
|
||||
Quat::IDENTITY,
|
||||
Vec3::NEG_Z * 0.5,
|
||||
),
|
||||
..OverlayWindowState::default()
|
||||
},
|
||||
..OverlayData::from_backend(Box::new(panel))
|
||||
global: true,
|
||||
..OverlayWindowConfig::from_backend(Box::new(panel))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
use glam::{Affine3A, Vec3};
|
||||
|
||||
use crate::{
|
||||
backend::overlay::{OverlayData, OverlayState},
|
||||
gui::panel::GuiPanel,
|
||||
state::AppState,
|
||||
windowing::window::{OverlayWindowConfig, OverlayWindowState},
|
||||
};
|
||||
|
||||
pub const BAR_NAME: &str = "bar";
|
||||
@@ -11,7 +13,7 @@ struct BarState {}
|
||||
#[allow(clippy::significant_drop_tightening)]
|
||||
#[allow(clippy::for_kv_map)] // TODO: remove later
|
||||
#[allow(clippy::match_same_arms)] // TODO: remove later
|
||||
pub fn create_bar<O>(app: &mut AppState) -> anyhow::Result<OverlayData<O>>
|
||||
pub fn create_bar<O>(app: &mut AppState) -> anyhow::Result<OverlayWindowConfig>
|
||||
where
|
||||
O: Default,
|
||||
{
|
||||
@@ -34,14 +36,14 @@ where
|
||||
|
||||
panel.update_layout()?;
|
||||
|
||||
Ok(OverlayData {
|
||||
state: OverlayState {
|
||||
name: BAR_NAME.into(),
|
||||
want_visible: true,
|
||||
Ok(OverlayWindowConfig {
|
||||
name: BAR_NAME.into(),
|
||||
default_state: OverlayWindowState {
|
||||
interactable: true,
|
||||
spawn_scale: 0.15,
|
||||
..Default::default()
|
||||
transform: Affine3A::from_scale(Vec3::ONE * 0.15),
|
||||
..OverlayWindowState::default()
|
||||
},
|
||||
..OverlayData::from_backend(Box::new(panel))
|
||||
global: true,
|
||||
..OverlayWindowConfig::from_backend(Box::new(panel))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use glam::Vec3A;
|
||||
use glam::{vec3, Affine3A, Quat, Vec3};
|
||||
|
||||
use crate::{
|
||||
backend::overlay::{OverlayBackend, OverlayState},
|
||||
gui::panel::GuiPanel,
|
||||
state::AppState,
|
||||
windowing::window::{OverlayWindowConfig, OverlayWindowState},
|
||||
};
|
||||
|
||||
const SETTINGS_NAME: &str = "settings";
|
||||
@@ -13,10 +13,7 @@ const SETTINGS_NAME: &str = "settings";
|
||||
#[allow(unreachable_code)]
|
||||
#[allow(unused_variables)]
|
||||
#[allow(dead_code)]
|
||||
pub fn create_custom(
|
||||
app: &mut AppState,
|
||||
name: Arc<str>,
|
||||
) -> Option<(OverlayState, Box<dyn OverlayBackend>)> {
|
||||
pub fn create_custom(app: &mut AppState, name: Arc<str>) -> Option<OverlayWindowConfig> {
|
||||
return None;
|
||||
|
||||
unreachable!();
|
||||
@@ -24,17 +21,18 @@ pub fn create_custom(
|
||||
let panel = GuiPanel::new_blank(app, ()).ok()?;
|
||||
panel.update_layout().ok()?;
|
||||
|
||||
let state = OverlayState {
|
||||
Some(OverlayWindowConfig {
|
||||
name,
|
||||
want_visible: true,
|
||||
interactable: true,
|
||||
grabbable: true,
|
||||
spawn_scale: 0.1, //TODO: this
|
||||
spawn_point: Vec3A::from_array([0., 0., -0.5]),
|
||||
//interaction_transform: ui_transform(config.size),
|
||||
..Default::default()
|
||||
};
|
||||
let backend = Box::new(panel);
|
||||
|
||||
Some((state, backend))
|
||||
default_state: OverlayWindowState {
|
||||
interactable: true,
|
||||
grabbable: true,
|
||||
transform: Affine3A::from_scale_rotation_translation(
|
||||
Vec3::ONE * 0.1, // TODO scale
|
||||
Quat::IDENTITY,
|
||||
vec3(0.0, 0.0, -0.5),
|
||||
),
|
||||
..OverlayWindowState::default()
|
||||
},
|
||||
..OverlayWindowConfig::from_backend(Box::new(panel))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::{collections::HashMap, rc::Rc};
|
||||
|
||||
use glam::{vec2, vec3a, Mat4, Vec2, Vec3};
|
||||
use glam::{vec2, vec3, Affine3A, Mat4, Quat, Vec2, Vec3};
|
||||
use wgui::{
|
||||
animation::{Animation, AnimationEasing},
|
||||
drawing::Color,
|
||||
@@ -17,10 +17,10 @@ use wgui::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
backend::overlay::{OverlayData, OverlayState, Positioning},
|
||||
gui::panel::GuiPanel,
|
||||
state::AppState,
|
||||
subsystem::hid::{XkbKeymap, ALT, CTRL, META, SHIFT, SUPER},
|
||||
windowing::window::{OverlayWindowConfig, OverlayWindowState, Positioning},
|
||||
};
|
||||
|
||||
use super::{
|
||||
@@ -33,13 +33,10 @@ const BACKGROUND_PADDING: f32 = 4.;
|
||||
const PIXELS_PER_UNIT: f32 = 80.;
|
||||
|
||||
#[allow(clippy::too_many_lines, clippy::significant_drop_tightening)]
|
||||
pub fn create_keyboard<O>(
|
||||
pub fn create_keyboard(
|
||||
app: &mut AppState,
|
||||
mut keymap: Option<XkbKeymap>,
|
||||
) -> anyhow::Result<OverlayData<O>>
|
||||
where
|
||||
O: Default,
|
||||
{
|
||||
) -> anyhow::Result<OverlayWindowConfig> {
|
||||
let layout = layout::Layout::load_from_disk();
|
||||
let state = KeyboardState {
|
||||
modifiers: 0,
|
||||
@@ -278,18 +275,21 @@ where
|
||||
|
||||
let width = layout.row_size * 0.05 * app.session.config.keyboard_scale;
|
||||
|
||||
Ok(OverlayData {
|
||||
state: OverlayState {
|
||||
name: KEYBOARD_NAME.into(),
|
||||
Ok(OverlayWindowConfig {
|
||||
name: KEYBOARD_NAME.into(),
|
||||
default_state: OverlayWindowState {
|
||||
grabbable: true,
|
||||
recenter: true,
|
||||
positioning: Positioning::Anchored,
|
||||
interactable: true,
|
||||
spawn_scale: width,
|
||||
spawn_point: vec3a(0., -0.5, 0.),
|
||||
..Default::default()
|
||||
curvature: Some(0.15),
|
||||
transform: Affine3A::from_scale_rotation_translation(
|
||||
Vec3::ONE * width,
|
||||
Quat::from_rotation_x(-10f32.to_radians()),
|
||||
vec3(0.0, -0.5, -0.5),
|
||||
),
|
||||
..OverlayWindowState::default()
|
||||
},
|
||||
..OverlayData::from_backend(Box::new(KeyboardBackend { panel }))
|
||||
..OverlayWindowConfig::from_backend(Box::new(KeyboardBackend { panel }))
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -11,14 +11,12 @@ use wgui::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
backend::{
|
||||
input::{Haptics, PointerHit},
|
||||
overlay::{FrameMeta, OverlayBackend, ShouldRender},
|
||||
},
|
||||
backend::input::{Haptics, PointerHit},
|
||||
graphics::CommandBuffers,
|
||||
gui::panel::GuiPanel,
|
||||
state::AppState,
|
||||
subsystem::hid::{ALT, CTRL, KeyModifier, META, SHIFT, SUPER, VirtualKey},
|
||||
windowing::backend::{FrameMeta, OverlayBackend, ShouldRender},
|
||||
};
|
||||
|
||||
pub mod builder;
|
||||
|
||||
@@ -4,19 +4,22 @@ use std::{
|
||||
};
|
||||
|
||||
use futures::{Future, FutureExt};
|
||||
use glam::Affine2;
|
||||
use glam::{Affine2, Affine3A, Vec3};
|
||||
use vulkano::image::view::ImageView;
|
||||
use wlx_capture::pipewire::{PipewireCapture, PipewireSelectScreenResult, pipewire_select_screen};
|
||||
use wlx_capture::pipewire::{pipewire_select_screen, PipewireCapture, PipewireSelectScreenResult};
|
||||
|
||||
use crate::{
|
||||
backend::{
|
||||
common::OverlaySelector,
|
||||
input::{Haptics, PointerHit},
|
||||
overlay::{FrameMeta, OverlayBackend, OverlayState, ShouldRender, ui_transform},
|
||||
task::TaskType,
|
||||
},
|
||||
graphics::CommandBuffers,
|
||||
state::{AppSession, AppState},
|
||||
windowing::{
|
||||
backend::{ui_transform, FrameMeta, OverlayBackend, ShouldRender},
|
||||
window::{OverlayWindowConfig, OverlayWindowState},
|
||||
OverlaySelector,
|
||||
},
|
||||
};
|
||||
|
||||
use super::screen::backend::ScreenBackend;
|
||||
@@ -70,9 +73,7 @@ impl OverlayBackend for MirrorBackend {
|
||||
app.tasks.enqueue(TaskType::Overlay(
|
||||
OverlaySelector::Name(self.name.clone()),
|
||||
Box::new(|app, o| {
|
||||
o.grabbable = true;
|
||||
o.interactable = true;
|
||||
o.reset(app, false);
|
||||
o.activate(app);
|
||||
}),
|
||||
));
|
||||
}
|
||||
@@ -140,19 +141,15 @@ impl OverlayBackend for MirrorBackend {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_mirror(
|
||||
name: Arc<str>,
|
||||
show_hide: bool,
|
||||
session: &AppSession,
|
||||
) -> (OverlayState, Box<dyn OverlayBackend>) {
|
||||
let state = OverlayState {
|
||||
pub fn new_mirror(name: Arc<str>, session: &AppSession) -> OverlayWindowConfig {
|
||||
OverlayWindowConfig {
|
||||
name: name.clone(),
|
||||
show_hide,
|
||||
want_visible: true,
|
||||
spawn_scale: 0.5 * session.config.desktop_view_scale,
|
||||
..Default::default()
|
||||
};
|
||||
let backend = Box::new(MirrorBackend::new(name));
|
||||
|
||||
(state, backend)
|
||||
default_state: OverlayWindowState {
|
||||
interactable: true,
|
||||
grabbable: true,
|
||||
transform: Affine3A::from_scale(Vec3::ONE * 0.5 * session.config.desktop_view_scale),
|
||||
..OverlayWindowState::default()
|
||||
},
|
||||
..OverlayWindowConfig::from_backend(Box::new(MirrorBackend::new(name)))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,21 @@
|
||||
use std::{
|
||||
sync::{atomic::AtomicU64, Arc, LazyLock},
|
||||
sync::{Arc, LazyLock, atomic::AtomicU64},
|
||||
time::Instant,
|
||||
};
|
||||
|
||||
use glam::{vec2, Affine2, Vec2};
|
||||
use glam::{Affine2, Vec2, vec2};
|
||||
use vulkano::image::view::ImageView;
|
||||
use wlx_capture::{frame::Transform, WlxCapture};
|
||||
use wlx_capture::{WlxCapture, frame::Transform};
|
||||
|
||||
use crate::{
|
||||
backend::{
|
||||
input::{Haptics, PointerHit, PointerMode},
|
||||
overlay::{FrameMeta, OverlayBackend, ShouldRender},
|
||||
},
|
||||
backend::input::{Haptics, PointerHit, PointerMode},
|
||||
graphics::{CommandBuffers, ExtentExt},
|
||||
state::AppState,
|
||||
subsystem::hid::{MOUSE_LEFT, MOUSE_MIDDLE, MOUSE_RIGHT},
|
||||
windowing::backend::{FrameMeta, OverlayBackend, ShouldRender},
|
||||
};
|
||||
|
||||
use super::capture::{receive_callback, ScreenPipeline, WlxCaptureIn, WlxCaptureOut};
|
||||
use super::capture::{ScreenPipeline, WlxCaptureIn, WlxCaptureOut, receive_callback};
|
||||
|
||||
const CURSOR_SIZE: f32 = 16. / 1440.;
|
||||
|
||||
|
||||
@@ -7,28 +7,29 @@ use vulkano::{
|
||||
command_buffer::CommandBufferUsage,
|
||||
device::Queue,
|
||||
format::Format,
|
||||
image::{sampler::Filter, view::ImageView, Image},
|
||||
image::{Image, sampler::Filter, view::ImageView},
|
||||
pipeline::graphics::color_blend::AttachmentBlend,
|
||||
};
|
||||
use wgui::gfx::{
|
||||
WGfx,
|
||||
cmd::WGfxClearMode,
|
||||
pass::WGfxPass,
|
||||
pipeline::{WGfxPipeline, WPipelineCreateInfo},
|
||||
WGfx,
|
||||
};
|
||||
use wlx_capture::{
|
||||
frame::{self as wlx_frame, DrmFormat, FrameFormat, MouseMeta, Transform, WlxFrame},
|
||||
WlxCapture,
|
||||
frame::{self as wlx_frame, DrmFormat, FrameFormat, MouseMeta, Transform, WlxFrame},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
backend::overlay::FrameMeta,
|
||||
config::GeneralConfig,
|
||||
graphics::{
|
||||
dmabuf::{fourcc_to_vk, WGfxDmabuf},
|
||||
upload_quad_vertices, CommandBuffers, Vert2Uv,
|
||||
CommandBuffers, Vert2Uv,
|
||||
dmabuf::{WGfxDmabuf, fourcc_to_vk},
|
||||
upload_quad_vertices,
|
||||
},
|
||||
state::AppState,
|
||||
windowing::backend::FrameMeta,
|
||||
};
|
||||
|
||||
const CURSOR_SIZE: f32 = 16. / 1440.;
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
use std::{f32::consts::PI, sync::Arc};
|
||||
|
||||
use backend::ScreenBackend;
|
||||
use glam::{vec3a, Quat, Vec3};
|
||||
use wl::create_screens_wayland;
|
||||
use glam::{vec3, Affine3A, Quat, Vec3};
|
||||
use wlx_capture::frame::Transform;
|
||||
|
||||
use crate::{
|
||||
backend::overlay::{OverlayState, Positioning},
|
||||
state::{AppSession, AppState, ScreenMeta},
|
||||
subsystem::{hid::XkbKeymap, input::KeyboardFocus},
|
||||
windowing::{
|
||||
backend::OverlayBackend,
|
||||
window::{OverlayWindowConfig, OverlayWindowState, Positioning},
|
||||
},
|
||||
};
|
||||
|
||||
pub mod backend;
|
||||
@@ -20,7 +21,12 @@ pub mod wl;
|
||||
#[cfg(feature = "x11")]
|
||||
pub mod x11;
|
||||
|
||||
fn create_screen_state(name: Arc<str>, transform: Transform, session: &AppSession) -> OverlayState {
|
||||
fn create_screen_from_backend(
|
||||
name: Arc<str>,
|
||||
transform: Transform,
|
||||
session: &AppSession,
|
||||
backend: Box<dyn OverlayBackend>,
|
||||
) -> OverlayWindowConfig {
|
||||
let angle = if session.config.upright_screen_fix {
|
||||
match transform {
|
||||
Transform::Rotated90 | Transform::Flipped90 => PI / 2.,
|
||||
@@ -32,22 +38,27 @@ fn create_screen_state(name: Arc<str>, transform: Transform, session: &AppSessio
|
||||
0.
|
||||
};
|
||||
|
||||
OverlayState {
|
||||
OverlayWindowConfig {
|
||||
name,
|
||||
default_state: OverlayWindowState {
|
||||
grabbable: true,
|
||||
positioning: Positioning::Anchored,
|
||||
interactable: true,
|
||||
curvature: Some(0.15),
|
||||
transform: Affine3A::from_scale_rotation_translation(
|
||||
Vec3::ONE * 1.5 * session.config.desktop_view_scale,
|
||||
Quat::from_rotation_z(angle),
|
||||
vec3(0.0, 0.2, -0.5),
|
||||
),
|
||||
..OverlayWindowState::default()
|
||||
},
|
||||
keyboard_focus: Some(KeyboardFocus::PhysicalScreen),
|
||||
grabbable: true,
|
||||
recenter: true,
|
||||
positioning: Positioning::Anchored,
|
||||
interactable: true,
|
||||
spawn_scale: 1.5 * session.config.desktop_view_scale,
|
||||
spawn_point: vec3a(0., 0.5, 0.),
|
||||
spawn_rotation: Quat::from_axis_angle(Vec3::Z, angle),
|
||||
..Default::default()
|
||||
..OverlayWindowConfig::from_backend(backend)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ScreenCreateData {
|
||||
pub screens: Vec<(ScreenMeta, OverlayState, Box<ScreenBackend>)>,
|
||||
pub screens: Vec<(ScreenMeta, OverlayWindowConfig)>,
|
||||
}
|
||||
|
||||
pub fn create_screens(app: &mut AppState) -> anyhow::Result<(ScreenCreateData, Option<XkbKeymap>)> {
|
||||
@@ -61,7 +72,7 @@ pub fn create_screens(app: &mut AppState) -> anyhow::Result<(ScreenCreateData, O
|
||||
.map_err(|f| log::warn!("Could not load keyboard layout: {f}"))
|
||||
.ok();
|
||||
|
||||
return Ok((create_screens_wayland(&mut wl, app), keymap));
|
||||
return Ok((wl::create_screens_wayland(&mut wl, app), keymap));
|
||||
}
|
||||
log::info!("Wayland not detected, assuming X11.");
|
||||
}
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
use glam::vec2;
|
||||
use wlx_capture::{
|
||||
WlxCapture,
|
||||
wayland::{WlxClient, WlxOutput},
|
||||
wlr_dmabuf::WlrDmabufCapture,
|
||||
wlr_screencopy::WlrScreencopyCapture,
|
||||
WlxCapture,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
config::{AStrMapExt, PwTokenMap},
|
||||
overlays::screen::create_screen_state,
|
||||
overlays::screen::create_screen_from_backend,
|
||||
state::{AppState, ScreenMeta},
|
||||
};
|
||||
|
||||
use super::{
|
||||
backend::ScreenBackend,
|
||||
capture::{new_wlx_capture, MainThreadWlxCapture},
|
||||
pw::{load_pw_token_config, save_pw_token_config},
|
||||
ScreenCreateData,
|
||||
backend::ScreenBackend,
|
||||
capture::{MainThreadWlxCapture, new_wlx_capture},
|
||||
pw::{load_pw_token_config, save_pw_token_config},
|
||||
};
|
||||
|
||||
impl ScreenBackend {
|
||||
@@ -130,15 +130,19 @@ pub fn create_screens_wayland(wl: &mut WlxClient, app: &mut AppState) -> ScreenC
|
||||
|
||||
backend.set_mouse_transform(logical_pos, logical_size, transform);
|
||||
|
||||
let state = create_screen_state(output.name.clone(), transform, &app.session);
|
||||
let window_config = create_screen_from_backend(
|
||||
output.name.clone(),
|
||||
transform,
|
||||
&app.session,
|
||||
Box::new(backend),
|
||||
);
|
||||
|
||||
let meta = ScreenMeta {
|
||||
name: wl.outputs[id].name.clone(),
|
||||
native_handle: *id,
|
||||
};
|
||||
|
||||
let backend = Box::new(backend);
|
||||
screens.push((meta, state, backend));
|
||||
screens.push((meta, window_config));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,20 +2,20 @@ use std::sync::Arc;
|
||||
|
||||
use glam::vec2;
|
||||
use wlx_capture::{
|
||||
WlxCapture,
|
||||
frame::Transform,
|
||||
xshm::{XshmCapture, XshmScreen},
|
||||
WlxCapture,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
overlays::screen::create_screen_state,
|
||||
overlays::screen::create_screen_from_backend,
|
||||
state::{AppState, ScreenMeta},
|
||||
};
|
||||
|
||||
use super::{
|
||||
backend::ScreenBackend,
|
||||
capture::{new_wlx_capture, MainThreadWlxCapture},
|
||||
ScreenCreateData,
|
||||
backend::ScreenBackend,
|
||||
capture::{MainThreadWlxCapture, new_wlx_capture},
|
||||
};
|
||||
|
||||
#[cfg(feature = "pipewire")]
|
||||
@@ -39,7 +39,7 @@ pub fn create_screens_x11pw(app: &mut AppState) -> anyhow::Result<ScreenCreateDa
|
||||
use crate::{
|
||||
config::{AStrMapExt, PwTokenMap},
|
||||
overlays::screen::{
|
||||
create_screen_state,
|
||||
create_screen_from_backend,
|
||||
pw::{load_pw_token_config, save_pw_token_config, select_pw_screen},
|
||||
},
|
||||
state::ScreenMeta,
|
||||
@@ -108,15 +108,19 @@ pub fn create_screens_x11pw(app: &mut AppState) -> anyhow::Result<ScreenCreateDa
|
||||
Transform::Normal,
|
||||
);
|
||||
|
||||
let state = create_screen_state(m.name.clone(), Transform::Normal, &app.session);
|
||||
let window_data = create_screen_from_backend(
|
||||
m.name.clone(),
|
||||
Transform::Normal,
|
||||
&app.session,
|
||||
Box::new(backend),
|
||||
);
|
||||
|
||||
let meta = ScreenMeta {
|
||||
name: m.name.clone(),
|
||||
native_handle: 0,
|
||||
};
|
||||
|
||||
let backend = Box::new(backend);
|
||||
(meta, state, backend)
|
||||
(meta, window_data)
|
||||
})
|
||||
.collect();
|
||||
|
||||
@@ -189,15 +193,19 @@ pub fn create_screens_xshm(app: &mut AppState) -> anyhow::Result<ScreenCreateDat
|
||||
Transform::Normal,
|
||||
);
|
||||
|
||||
let state = create_screen_state(s.name.clone(), Transform::Normal, &app.session);
|
||||
let window_data = create_screen_from_backend(
|
||||
s.name.clone(),
|
||||
Transform::Normal,
|
||||
&app.session,
|
||||
Box::new(backend),
|
||||
);
|
||||
|
||||
let meta = ScreenMeta {
|
||||
name: s.name.clone(),
|
||||
native_handle: 0,
|
||||
};
|
||||
|
||||
let backend = Box::new(backend);
|
||||
(meta, state, backend)
|
||||
(meta, window_data)
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ use std::{
|
||||
time::Instant,
|
||||
};
|
||||
|
||||
use glam::{vec3a, Quat};
|
||||
use glam::{vec3, Affine3A, Quat, Vec3};
|
||||
use idmap_derive::IntegerId;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use wgui::{
|
||||
@@ -24,13 +24,13 @@ use wgui::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
backend::{
|
||||
common::OverlaySelector,
|
||||
overlay::{OverlayBackend, OverlayState, Positioning, Z_ORDER_TOAST},
|
||||
task::TaskType,
|
||||
},
|
||||
backend::task::TaskType,
|
||||
gui::panel::GuiPanel,
|
||||
state::{AppState, LeftRight},
|
||||
windowing::{
|
||||
window::{OverlayWindowConfig, OverlayWindowState, Positioning},
|
||||
OverlaySelector, Z_ORDER_TOAST,
|
||||
},
|
||||
};
|
||||
|
||||
const FONT_SIZE: isize = 16;
|
||||
@@ -112,16 +112,13 @@ impl Toast {
|
||||
TaskType::CreateOverlay(
|
||||
selector.clone(),
|
||||
Box::new(move |app| {
|
||||
let mut maybe_toast = new_toast(self, app);
|
||||
if let Some((state, _)) = maybe_toast.as_mut() {
|
||||
state.auto_movement(app);
|
||||
app.tasks.enqueue_at(
|
||||
// at timeout, drop the overlay by ID instead
|
||||
// in order to avoid dropping any newer toasts
|
||||
TaskType::DropOverlay(selector),
|
||||
destroy_at,
|
||||
);
|
||||
}
|
||||
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),
|
||||
destroy_at,
|
||||
);
|
||||
maybe_toast
|
||||
}),
|
||||
),
|
||||
@@ -131,7 +128,7 @@ impl Toast {
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_lines)]
|
||||
fn new_toast(toast: Toast, app: &mut AppState) -> Option<(OverlayState, Box<dyn OverlayBackend>)> {
|
||||
fn new_toast(toast: Toast, app: &mut AppState) -> Option<OverlayWindowConfig> {
|
||||
let current_method = app
|
||||
.session
|
||||
.toast_topics
|
||||
@@ -142,12 +139,13 @@ fn new_toast(toast: Toast, app: &mut AppState) -> Option<(OverlayState, Box<dyn
|
||||
let (spawn_point, spawn_rotation, positioning) = match current_method {
|
||||
DisplayMethod::Hide => return None,
|
||||
DisplayMethod::Center => (
|
||||
vec3a(0., -0.2, -0.5),
|
||||
vec3(0., -0.2, -0.5),
|
||||
Quat::IDENTITY,
|
||||
Positioning::FollowHead { lerp: 0.1 },
|
||||
),
|
||||
DisplayMethod::Watch => {
|
||||
let mut watch_pos = app.session.config.watch_pos + vec3a(-0.005, -0.05, 0.02);
|
||||
let mut watch_pos =
|
||||
Vec3::from(app.session.config.watch_pos) + vec3(-0.005, -0.05, 0.02);
|
||||
let mut watch_rot = app.session.config.watch_rot;
|
||||
let relative_to = match app.session.config.watch_hand {
|
||||
LeftRight::Left => Positioning::FollowHand { hand: 0, lerp: 1.0 },
|
||||
@@ -239,19 +237,21 @@ fn new_toast(toast: Toast, app: &mut AppState) -> Option<(OverlayState, Box<dyn
|
||||
|
||||
panel.update_layout().ok()?;
|
||||
|
||||
let state = OverlayState {
|
||||
Some(OverlayWindowConfig {
|
||||
name: TOAST_NAME.clone(),
|
||||
want_visible: true,
|
||||
spawn_scale: panel.layout.content_size.x * PIXELS_TO_METERS,
|
||||
spawn_rotation,
|
||||
spawn_point,
|
||||
default_state: OverlayWindowState {
|
||||
positioning,
|
||||
transform: Affine3A::from_scale_rotation_translation(
|
||||
Vec3::ONE * panel.layout.content_size.x * PIXELS_TO_METERS,
|
||||
spawn_rotation,
|
||||
spawn_point,
|
||||
),
|
||||
..OverlayWindowState::default()
|
||||
},
|
||||
global: true,
|
||||
z_order: Z_ORDER_TOAST,
|
||||
positioning,
|
||||
..Default::default()
|
||||
};
|
||||
let backend = Box::new(panel);
|
||||
|
||||
Some((state, backend))
|
||||
..OverlayWindowConfig::from_backend(Box::new(panel))
|
||||
})
|
||||
}
|
||||
|
||||
fn msg_err(app: &mut AppState, message: &str) {
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
use glam::{Affine3A, Quat, Vec3A};
|
||||
use wgui::{
|
||||
i18n::Translation,
|
||||
parser::parse_color_hex,
|
||||
renderer_vk::text::TextStyle,
|
||||
taffy::{
|
||||
self,
|
||||
prelude::{auto, length, percent},
|
||||
},
|
||||
widget::{
|
||||
rectangle::{Rectangle, RectangleParams},
|
||||
text::{TextLabel, TextParams},
|
||||
util::WLength,
|
||||
},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
backend::overlay::{OverlayBackend, OverlayState, Z_ORDER_TOAST},
|
||||
gui::panel::GuiPanel,
|
||||
state::AppState,
|
||||
};
|
||||
|
||||
const FONT_SIZE: isize = 16;
|
||||
const PADDING: (f32, f32) = (25., 7.);
|
||||
const PIXELS_TO_METERS: f32 = 1. / 2000.;
|
||||
|
||||
#[allow(clippy::too_many_lines)]
|
||||
fn new_tooltip(
|
||||
text: &str,
|
||||
transform: Affine3A,
|
||||
app: &mut AppState,
|
||||
) -> Option<(OverlayState, Box<dyn OverlayBackend>)> {
|
||||
let mut panel = GuiPanel::new_blank(app, ()).ok()?;
|
||||
|
||||
let globals = panel.layout.state.globals.clone();
|
||||
let mut i18n = globals.i18n();
|
||||
|
||||
let (rect, _) = panel
|
||||
.layout
|
||||
.add_child(
|
||||
panel.layout.root_widget,
|
||||
Rectangle::create(RectangleParams {
|
||||
color: parse_color_hex("#1e2030").unwrap(),
|
||||
border_color: parse_color_hex("#5e7090").unwrap(),
|
||||
border: 1.0,
|
||||
round: WLength::Units(4.0),
|
||||
..Default::default()
|
||||
})
|
||||
.unwrap(),
|
||||
taffy::Style {
|
||||
align_items: Some(taffy::AlignItems::Center),
|
||||
justify_content: Some(taffy::JustifyContent::Center),
|
||||
flex_direction: taffy::FlexDirection::Column,
|
||||
padding: length(4.0),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.ok()?;
|
||||
|
||||
let _ = panel.layout.add_child(
|
||||
rect.id,
|
||||
TextLabel::create(
|
||||
&mut i18n,
|
||||
TextParams {
|
||||
content: Translation::from_raw_text(text),
|
||||
style: TextStyle {
|
||||
color: parse_color_hex("#ffffff"),
|
||||
..Default::default()
|
||||
},
|
||||
},
|
||||
)
|
||||
.unwrap(),
|
||||
taffy::Style {
|
||||
size: taffy::Size {
|
||||
width: percent(1.0),
|
||||
height: auto(),
|
||||
},
|
||||
padding: length(8.0),
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
|
||||
panel.update_layout().ok()?;
|
||||
|
||||
let state = OverlayState {
|
||||
name: "tooltip".into(),
|
||||
want_visible: true,
|
||||
spawn_scale: panel.layout.content_size.x * PIXELS_TO_METERS,
|
||||
spawn_rotation: Quat::IDENTITY,
|
||||
spawn_point: Vec3A::ZERO,
|
||||
z_order: Z_ORDER_TOAST,
|
||||
positioning: crate::backend::overlay::Positioning::Static,
|
||||
..Default::default()
|
||||
};
|
||||
let backend = Box::new(panel);
|
||||
|
||||
Some((state, backend))
|
||||
}
|
||||
@@ -1,12 +1,14 @@
|
||||
use std::{collections::HashMap, rc::Rc, sync::Arc, time::Duration};
|
||||
use std::{collections::HashMap, rc::Rc, time::Duration};
|
||||
|
||||
use glam::Vec3A;
|
||||
use smallvec::SmallVec;
|
||||
use glam::{Affine3A, Vec3, Vec3A};
|
||||
|
||||
use crate::{
|
||||
backend::overlay::{OverlayData, OverlayState, Positioning, Z_ORDER_WATCH},
|
||||
gui::{panel::GuiPanel, timer::GuiTimer},
|
||||
state::AppState,
|
||||
windowing::{
|
||||
window::{OverlayWindowConfig, OverlayWindowData, OverlayWindowState, Positioning},
|
||||
Z_ORDER_WATCH,
|
||||
},
|
||||
};
|
||||
|
||||
pub const WATCH_NAME: &str = "watch";
|
||||
@@ -14,16 +16,7 @@ pub const WATCH_NAME: &str = "watch";
|
||||
struct WatchState {}
|
||||
|
||||
#[allow(clippy::significant_drop_tightening)]
|
||||
pub fn create_watch<O>(app: &mut AppState) -> anyhow::Result<OverlayData<O>>
|
||||
where
|
||||
O: Default,
|
||||
{
|
||||
let screens = app
|
||||
.screens
|
||||
.iter()
|
||||
.map(|s| s.name.clone())
|
||||
.collect::<SmallVec<[Arc<str>; 8]>>();
|
||||
|
||||
pub fn create_watch(app: &mut AppState, num_sets: usize) -> anyhow::Result<OverlayWindowConfig> {
|
||||
let state = WatchState {};
|
||||
let mut panel = GuiPanel::new_from_template(
|
||||
app,
|
||||
@@ -35,10 +28,10 @@ where
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
for (idx, handle) in screens.iter().enumerate() {
|
||||
for idx in 0..num_sets {
|
||||
let mut params: HashMap<Rc<str>, Rc<str>> = HashMap::new();
|
||||
params.insert("display".into(), (idx + 1).to_string().into());
|
||||
params.insert("handle".into(), handle.as_ref().into());
|
||||
params.insert("handle".into(), idx.to_string().into());
|
||||
parser_state.instantiate_template(
|
||||
doc_params, "Set", layout, listeners, widget, params,
|
||||
)?;
|
||||
@@ -59,47 +52,36 @@ where
|
||||
|
||||
panel.update_layout()?;
|
||||
|
||||
Ok(OverlayData {
|
||||
state: OverlayState {
|
||||
name: WATCH_NAME.into(),
|
||||
want_visible: true,
|
||||
Ok(OverlayWindowConfig {
|
||||
name: WATCH_NAME.into(),
|
||||
z_order: Z_ORDER_WATCH,
|
||||
default_state: OverlayWindowState {
|
||||
interactable: true,
|
||||
z_order: Z_ORDER_WATCH,
|
||||
spawn_scale: 0.115, //TODO:configurable
|
||||
spawn_point: app.session.config.watch_pos,
|
||||
spawn_rotation: app.session.config.watch_rot,
|
||||
positioning,
|
||||
..Default::default()
|
||||
transform: Affine3A::from_scale_rotation_translation(
|
||||
Vec3::ONE * 0.115,
|
||||
app.session.config.watch_rot,
|
||||
app.session.config.watch_pos,
|
||||
),
|
||||
..OverlayWindowState::default()
|
||||
},
|
||||
..OverlayData::from_backend(Box::new(panel))
|
||||
show_on_spawn: true,
|
||||
global: true,
|
||||
..OverlayWindowConfig::from_backend(Box::new(panel))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn watch_fade<D>(app: &mut AppState, watch: &mut OverlayData<D>)
|
||||
where
|
||||
D: Default,
|
||||
{
|
||||
if watch.state.saved_transform.is_some() {
|
||||
watch.state.want_visible = false;
|
||||
pub fn watch_fade<D>(app: &mut AppState, watch: &mut OverlayWindowData<D>) {
|
||||
let Some(state) = watch.config.active_state.as_mut() else {
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let to_hmd = (watch.state.transform.translation - app.input_state.hmd.translation).normalize();
|
||||
let watch_normal = watch
|
||||
.state
|
||||
.transform
|
||||
.transform_vector3a(Vec3A::NEG_Z)
|
||||
.normalize();
|
||||
let to_hmd = (state.transform.translation - app.input_state.hmd.translation).normalize();
|
||||
let watch_normal = state.transform.transform_vector3a(Vec3A::NEG_Z).normalize();
|
||||
let dot = to_hmd.dot(watch_normal);
|
||||
|
||||
if dot < app.session.config.watch_view_angle_min {
|
||||
watch.state.want_visible = false;
|
||||
} else {
|
||||
watch.state.want_visible = true;
|
||||
|
||||
watch.state.alpha = (dot - app.session.config.watch_view_angle_min)
|
||||
/ (app.session.config.watch_view_angle_max - app.session.config.watch_view_angle_min);
|
||||
watch.state.alpha += 0.1;
|
||||
watch.state.alpha = watch.state.alpha.clamp(0., 1.);
|
||||
}
|
||||
state.alpha = (dot - app.session.config.watch_view_angle_min)
|
||||
/ (app.session.config.watch_view_angle_max - app.session.config.watch_view_angle_min);
|
||||
state.alpha += 0.1;
|
||||
state.alpha = state.alpha.clamp(0., 1.);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use glam::{vec3a, Affine2, Vec3, Vec3A};
|
||||
use glam::{vec3, Affine2, Affine3A, Quat, Vec3};
|
||||
use smallvec::smallvec;
|
||||
use std::{cell::RefCell, collections::HashMap, rc::Rc, sync::Arc};
|
||||
use vulkano::{
|
||||
@@ -17,12 +17,7 @@ use wlx_capture::frame::{DmabufFrame, FourCC, FrameFormat, FramePlane};
|
||||
|
||||
use crate::{
|
||||
backend::{
|
||||
common::{OverlayContainer, OverlaySelector},
|
||||
input::{self},
|
||||
overlay::{
|
||||
ui_transform, FrameMeta, OverlayBackend, OverlayData, OverlayID, OverlayState,
|
||||
ShouldRender, Z_ORDER_DASHBOARD,
|
||||
},
|
||||
task::TaskType,
|
||||
wayvr::{
|
||||
self, display,
|
||||
@@ -34,6 +29,12 @@ use crate::{
|
||||
graphics::{dmabuf::WGfxDmabuf, CommandBuffers, Vert2Uv},
|
||||
state::{self, AppState},
|
||||
subsystem::input::KeyboardFocus,
|
||||
windowing::{
|
||||
backend::{ui_transform, FrameMeta, OverlayBackend, ShouldRender},
|
||||
manager::OverlayWindowManager,
|
||||
window::{OverlayWindowConfig, OverlayWindowData, OverlayWindowState},
|
||||
OverlayID, OverlaySelector, Z_ORDER_DASHBOARD,
|
||||
},
|
||||
};
|
||||
|
||||
use super::toast::error_toast;
|
||||
@@ -222,7 +223,7 @@ pub fn executable_exists_in_path(command: &str) -> bool {
|
||||
|
||||
fn toggle_dashboard<O>(
|
||||
app: &mut AppState,
|
||||
overlays: &mut OverlayContainer<O>,
|
||||
overlays: &mut OverlayWindowManager<O>,
|
||||
wayvr: &mut WayVRData,
|
||||
) -> anyhow::Result<()>
|
||||
where
|
||||
@@ -245,31 +246,39 @@ where
|
||||
if newly_created {
|
||||
log::info!("Creating dashboard overlay");
|
||||
|
||||
let mut overlay = create_overlay::<O>(
|
||||
app,
|
||||
DASHBOARD_DISPLAY_NAME,
|
||||
OverlayToCreate {
|
||||
disp_handle,
|
||||
conf_display: config_wayvr::WayVRDisplay {
|
||||
attach_to: None,
|
||||
width: DASHBOARD_WIDTH,
|
||||
height: DASHBOARD_HEIGHT,
|
||||
scale: None,
|
||||
rotation: None,
|
||||
pos: None,
|
||||
primary: None,
|
||||
},
|
||||
let mut overlay = OverlayWindowData::from_config(OverlayWindowConfig {
|
||||
default_state: OverlayWindowState {
|
||||
curvature: Some(0.15),
|
||||
transform: Affine3A::from_scale_rotation_translation(
|
||||
Vec3::ONE * 2.0,
|
||||
Quat::IDENTITY,
|
||||
vec3(0.0, -0.35, -1.75),
|
||||
),
|
||||
..OverlayWindowState::default()
|
||||
},
|
||||
)?;
|
||||
z_order: Z_ORDER_DASHBOARD,
|
||||
show_on_spawn: true,
|
||||
..create_overlay(
|
||||
app,
|
||||
DASHBOARD_DISPLAY_NAME,
|
||||
OverlayToCreate {
|
||||
disp_handle,
|
||||
conf_display: config_wayvr::WayVRDisplay {
|
||||
attach_to: None,
|
||||
width: DASHBOARD_WIDTH,
|
||||
height: DASHBOARD_HEIGHT,
|
||||
scale: None,
|
||||
rotation: None,
|
||||
pos: None,
|
||||
primary: None,
|
||||
},
|
||||
},
|
||||
)?
|
||||
});
|
||||
|
||||
overlay.state.curvature = Some(0.15);
|
||||
overlay.state.want_visible = true;
|
||||
overlay.state.spawn_scale = 2.0;
|
||||
overlay.state.spawn_point = vec3a(0.0, -0.35, -1.75);
|
||||
overlay.state.z_order = Z_ORDER_DASHBOARD;
|
||||
overlay.state.reset(app, true);
|
||||
overlay.config.reset(app, true);
|
||||
|
||||
let overlay_id = overlays.add(overlay);
|
||||
let overlay_id = overlays.add(overlay, app);
|
||||
wayvr.set_overlay_display_handle(overlay_id, disp_handle);
|
||||
|
||||
let args_vec = &conf_dash
|
||||
@@ -319,29 +328,22 @@ where
|
||||
app.tasks.enqueue(TaskType::Overlay(
|
||||
OverlaySelector::Id(overlay_id),
|
||||
Box::new(move |app, o| {
|
||||
// Toggle visibility
|
||||
o.want_visible = cur_visibility;
|
||||
if cur_visibility {
|
||||
o.reset(app, true);
|
||||
}
|
||||
o.toggle(app);
|
||||
}),
|
||||
));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn create_overlay<O>(
|
||||
fn create_overlay(
|
||||
app: &mut AppState,
|
||||
name: &str,
|
||||
cell: OverlayToCreate,
|
||||
) -> anyhow::Result<OverlayData<O>>
|
||||
where
|
||||
O: Default,
|
||||
{
|
||||
) -> anyhow::Result<OverlayWindowConfig> {
|
||||
let conf_display = &cell.conf_display;
|
||||
let disp_handle = cell.disp_handle;
|
||||
|
||||
let mut overlay = create_wayvr_display_overlay::<O>(
|
||||
let mut overlay = create_wayvr_display_overlay(
|
||||
app,
|
||||
conf_display.width,
|
||||
conf_display.height,
|
||||
@@ -351,17 +353,22 @@ where
|
||||
)?;
|
||||
|
||||
if let Some(attach_to) = &conf_display.attach_to {
|
||||
overlay.state.positioning = attach_to.get_positioning();
|
||||
overlay.default_state.positioning = attach_to.get_positioning();
|
||||
}
|
||||
|
||||
if let Some(rot) = &conf_display.rotation {
|
||||
overlay.state.spawn_rotation =
|
||||
glam::Quat::from_axis_angle(Vec3::from_slice(&rot.axis), f32::to_radians(rot.angle));
|
||||
}
|
||||
let rot = if let Some(rot) = &conf_display.rotation {
|
||||
glam::Quat::from_axis_angle(Vec3::from_slice(&rot.axis), f32::to_radians(rot.angle))
|
||||
} else {
|
||||
glam::Quat::IDENTITY
|
||||
};
|
||||
|
||||
if let Some(pos) = &conf_display.pos {
|
||||
overlay.state.spawn_point = Vec3A::from_slice(pos);
|
||||
}
|
||||
let pos = if let Some(pos) = &conf_display.pos {
|
||||
Vec3::from_slice(pos)
|
||||
} else {
|
||||
Vec3::NEG_Z
|
||||
};
|
||||
|
||||
overlay.default_state.transform = Affine3A::from_rotation_translation(rot, pos);
|
||||
|
||||
Ok(overlay)
|
||||
}
|
||||
@@ -369,7 +376,7 @@ where
|
||||
fn create_queued_displays<O>(
|
||||
app: &mut AppState,
|
||||
data: &mut WayVRData,
|
||||
overlays: &mut OverlayContainer<O>,
|
||||
overlays: &mut OverlayWindowManager<O>,
|
||||
) -> anyhow::Result<()>
|
||||
where
|
||||
O: Default,
|
||||
@@ -384,8 +391,8 @@ where
|
||||
let name = disp.name.clone();
|
||||
|
||||
let disp_handle = cell.disp_handle;
|
||||
let overlay = create_overlay::<O>(app, name.as_str(), cell)?;
|
||||
let overlay_id = overlays.add(overlay); // Insert freshly created WayVR overlay into wlx stack
|
||||
let overlay = OverlayWindowData::from_config(create_overlay(app, name.as_str(), cell)?);
|
||||
let overlay_id = overlays.add(overlay, app); // Insert freshly created WayVR overlay into wlx stack
|
||||
data.set_overlay_display_handle(overlay_id, disp_handle);
|
||||
}
|
||||
|
||||
@@ -393,7 +400,10 @@ where
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_lines)]
|
||||
pub fn tick_events<O>(app: &mut AppState, overlays: &mut OverlayContainer<O>) -> anyhow::Result<()>
|
||||
pub fn tick_events<O>(
|
||||
app: &mut AppState,
|
||||
overlays: &mut OverlayWindowManager<O>,
|
||||
) -> anyhow::Result<()>
|
||||
where
|
||||
O: Default,
|
||||
{
|
||||
@@ -414,8 +424,8 @@ where
|
||||
.set_display_visible(display_handle, visible);
|
||||
app.tasks.enqueue(TaskType::Overlay(
|
||||
OverlaySelector::Id(overlay_id),
|
||||
Box::new(move |_app, o| {
|
||||
o.want_visible = visible;
|
||||
Box::new(move |app, o| {
|
||||
o.toggle(app);
|
||||
}),
|
||||
));
|
||||
}
|
||||
@@ -775,28 +785,14 @@ impl OverlayBackend for WayVRBackend {
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn create_wayvr_display_overlay<O>(
|
||||
pub fn create_wayvr_display_overlay(
|
||||
app: &mut state::AppState,
|
||||
display_width: u16,
|
||||
display_height: u16,
|
||||
display_handle: wayvr::display::DisplayHandle,
|
||||
display_scale: f32,
|
||||
name: &str,
|
||||
) -> anyhow::Result<OverlayData<O>>
|
||||
where
|
||||
O: Default,
|
||||
{
|
||||
let state = OverlayState {
|
||||
name: format!("WayVR - {name}").into(),
|
||||
keyboard_focus: Some(KeyboardFocus::WayVR),
|
||||
want_visible: true,
|
||||
interactable: true,
|
||||
grabbable: true,
|
||||
spawn_scale: display_scale,
|
||||
spawn_point: vec3a(0.0, -0.1, -1.0),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
) -> anyhow::Result<OverlayWindowConfig> {
|
||||
let wayvr = app.get_wayvr()?;
|
||||
|
||||
let backend = Box::new(WayVRBackend::new(
|
||||
@@ -806,21 +802,36 @@ where
|
||||
[display_width, display_height],
|
||||
)?);
|
||||
|
||||
Ok(OverlayData {
|
||||
state,
|
||||
..OverlayData::from_backend(backend)
|
||||
Ok(OverlayWindowConfig {
|
||||
name: format!("WayVR - {name}").into(),
|
||||
keyboard_focus: Some(KeyboardFocus::WayVR),
|
||||
default_state: OverlayWindowState {
|
||||
interactable: true,
|
||||
grabbable: true,
|
||||
transform: Affine3A::from_scale_rotation_translation(
|
||||
Vec3::ONE * display_scale,
|
||||
Quat::IDENTITY,
|
||||
vec3(0.0, -0.1, -1.0),
|
||||
),
|
||||
..OverlayWindowState::default()
|
||||
},
|
||||
..OverlayWindowConfig::from_backend(backend)
|
||||
})
|
||||
}
|
||||
|
||||
fn show_display<O>(wayvr: &mut WayVRData, overlays: &mut OverlayContainer<O>, display_name: &str)
|
||||
where
|
||||
fn show_display<O>(
|
||||
wayvr: &mut WayVRData,
|
||||
overlays: &mut OverlayWindowManager<O>,
|
||||
app: &mut AppState,
|
||||
display_name: &str,
|
||||
) where
|
||||
O: Default,
|
||||
{
|
||||
if let Some(display) = WayVR::get_display_by_name(&wayvr.data.state.displays, display_name) {
|
||||
if let Some(overlay_id) = wayvr.display_handle_map.get(&display)
|
||||
&& let Some(overlay) = overlays.mut_by_id(*overlay_id)
|
||||
{
|
||||
overlay.state.want_visible = true;
|
||||
overlay.config.activate(app);
|
||||
}
|
||||
|
||||
wayvr.data.state.set_display_visible(display, true);
|
||||
@@ -829,7 +840,7 @@ where
|
||||
|
||||
fn action_app_click<O>(
|
||||
app: &mut AppState,
|
||||
overlays: &mut OverlayContainer<O>,
|
||||
overlays: &mut OverlayWindowManager<O>,
|
||||
catalog_name: &Arc<str>,
|
||||
app_name: &Arc<str>,
|
||||
) -> anyhow::Result<()>
|
||||
@@ -884,7 +895,7 @@ where
|
||||
HashMap::default(),
|
||||
)?;
|
||||
|
||||
show_display::<O>(&mut wayvr, overlays, app_entry.target_display.as_str());
|
||||
show_display::<O>(&mut wayvr, overlays, app, app_entry.target_display.as_str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -893,7 +904,7 @@ where
|
||||
|
||||
pub fn action_display_click<O>(
|
||||
app: &mut AppState,
|
||||
overlays: &mut OverlayContainer<O>,
|
||||
overlays: &mut OverlayWindowManager<O>,
|
||||
display_name: &Arc<str>,
|
||||
action: &WayVRDisplayClickAction,
|
||||
) -> anyhow::Result<()>
|
||||
@@ -922,20 +933,22 @@ where
|
||||
match action {
|
||||
WayVRDisplayClickAction::ToggleVisibility => {
|
||||
// Toggle visibility
|
||||
overlay.state.want_visible = !overlay.state.want_visible;
|
||||
overlay.config.toggle(app);
|
||||
}
|
||||
WayVRDisplayClickAction::Reset => {
|
||||
// Show it at the front
|
||||
overlay.state.want_visible = true;
|
||||
overlay.state.reset(app, true);
|
||||
overlay.config.reset(app, true);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn wayvr_action<O>(app: &mut AppState, overlays: &mut OverlayContainer<O>, action: &WayVRAction)
|
||||
where
|
||||
pub fn wayvr_action<O>(
|
||||
app: &mut AppState,
|
||||
overlays: &mut OverlayWindowManager<O>,
|
||||
action: &WayVRAction,
|
||||
) where
|
||||
O: Default,
|
||||
{
|
||||
match action {
|
||||
|
||||
Reference in New Issue
Block a user