WayVR: WayVRDisplayList ui type, toggle display visibility and pause rendering of them
This commit is contained in:
@@ -43,7 +43,7 @@ use crate::{
|
||||
};
|
||||
|
||||
#[cfg(feature = "wayvr")]
|
||||
use crate::overlays::wayvr::action_wayvr;
|
||||
use crate::overlays::wayvr::wayvr_action;
|
||||
|
||||
pub mod helpers;
|
||||
pub mod input;
|
||||
@@ -266,12 +266,8 @@ pub fn openvr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
|
||||
}
|
||||
},
|
||||
#[cfg(feature = "wayvr")]
|
||||
TaskType::WayVR(task) => {
|
||||
if let Some(overlay) =
|
||||
action_wayvr(&task.catalog_name, &task.app_name, &mut state)
|
||||
{
|
||||
overlays.add(overlay);
|
||||
}
|
||||
TaskType::WayVR(action) => {
|
||||
wayvr_action(&mut state, &mut overlays, &action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ use crate::{
|
||||
};
|
||||
|
||||
#[cfg(feature = "wayvr")]
|
||||
use crate::overlays::wayvr::action_wayvr;
|
||||
use crate::overlays::wayvr::wayvr_action;
|
||||
|
||||
mod helpers;
|
||||
mod input;
|
||||
@@ -491,12 +491,8 @@ pub fn openxr_run(running: Arc<AtomicBool>, show_by_default: bool) -> Result<(),
|
||||
_ => {}
|
||||
},
|
||||
#[cfg(feature = "wayvr")]
|
||||
TaskType::WayVR(task) => {
|
||||
if let Some(overlay) =
|
||||
action_wayvr(&task.catalog_name, &task.app_name, &mut app_state)
|
||||
{
|
||||
overlays.add(overlay);
|
||||
}
|
||||
TaskType::WayVR(action) => {
|
||||
wayvr_action(&mut app_state, &mut overlays, &action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,13 +5,13 @@ use std::{
|
||||
time::Instant,
|
||||
};
|
||||
|
||||
#[cfg(feature = "wayvr")]
|
||||
use std::sync::Arc;
|
||||
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::state::AppState;
|
||||
|
||||
#[cfg(feature = "wayvr")]
|
||||
use crate::overlays::wayvr::WayVRAction;
|
||||
|
||||
use super::{
|
||||
common::OverlaySelector,
|
||||
overlay::{OverlayBackend, OverlayState},
|
||||
@@ -52,12 +52,6 @@ pub enum SystemTask {
|
||||
ShowHide,
|
||||
}
|
||||
|
||||
#[cfg(feature = "wayvr")]
|
||||
pub struct WayVRTask {
|
||||
pub catalog_name: Arc<str>,
|
||||
pub app_name: Arc<str>,
|
||||
}
|
||||
|
||||
pub type OverlayTask = dyn FnOnce(&mut AppState, &mut OverlayState) + Send;
|
||||
pub type CreateOverlayTask =
|
||||
dyn FnOnce(&mut AppState) -> Option<(OverlayState, Box<dyn OverlayBackend>)> + Send;
|
||||
@@ -69,7 +63,7 @@ pub enum TaskType {
|
||||
DropOverlay(OverlaySelector),
|
||||
System(SystemTask),
|
||||
#[cfg(feature = "wayvr")]
|
||||
WayVR(WayVRTask),
|
||||
WayVR(WayVRAction),
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Clone, Copy)]
|
||||
|
||||
@@ -15,7 +15,7 @@ use smithay::{
|
||||
wayland::shell::xdg::ToplevelSurface,
|
||||
};
|
||||
|
||||
use crate::gen_id;
|
||||
use crate::{backend::overlay::OverlayID, gen_id};
|
||||
|
||||
use super::{
|
||||
client::WayVRManager, comp::send_frames_surface_tree, egl_data, smithay_wrapper, window,
|
||||
@@ -47,6 +47,8 @@ pub struct Display {
|
||||
pub width: u32,
|
||||
pub height: u32,
|
||||
pub name: String,
|
||||
pub visible: bool,
|
||||
pub overlay_id: Option<OverlayID>,
|
||||
wm: Rc<RefCell<window::WindowManager>>,
|
||||
displayed_windows: Vec<DisplayWindow>,
|
||||
wayland_env: super::WaylandEnv,
|
||||
@@ -112,6 +114,8 @@ impl Display {
|
||||
gles_texture,
|
||||
wayland_env,
|
||||
processes: Vec::new(),
|
||||
visible: true,
|
||||
overlay_id: None,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -216,6 +220,11 @@ impl Display {
|
||||
None
|
||||
}
|
||||
|
||||
pub fn set_visible(&mut self, visible: bool) {
|
||||
log::info!("Display \"{}\" visible: {}", self.name.as_str(), visible);
|
||||
self.visible = visible;
|
||||
}
|
||||
|
||||
pub fn send_mouse_move(&self, manager: &mut WayVRManager, x: u32, y: u32) {
|
||||
if let Some(window_handle) = self.get_hovered_window(x, y) {
|
||||
let wm = self.wm.borrow();
|
||||
|
||||
@@ -43,7 +43,7 @@ impl WaylandEnv {
|
||||
pub struct WayVR {
|
||||
time_start: u64,
|
||||
gles_renderer: GlesRenderer,
|
||||
displays: display::DisplayVec,
|
||||
pub displays: display::DisplayVec,
|
||||
manager: client::WayVRManager,
|
||||
wm: Rc<RefCell<window::WindowManager>>,
|
||||
egl_data: Rc<egl_data::EGLData>,
|
||||
@@ -102,13 +102,19 @@ impl WayVR {
|
||||
|
||||
pub fn tick_display(&mut self, display: display::DisplayHandle) -> anyhow::Result<()> {
|
||||
// millis since the start of wayvr
|
||||
let time_ms = get_millis() - self.time_start;
|
||||
|
||||
let display = self
|
||||
.displays
|
||||
.get(&display)
|
||||
.ok_or(anyhow::anyhow!("Invalid display handle"))?;
|
||||
|
||||
let time_ms = get_millis() - self.time_start;
|
||||
|
||||
if !display.visible {
|
||||
// Display is invisible, do not render
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
display.tick_render(&mut self.gles_renderer, time_ms)?;
|
||||
|
||||
Ok(())
|
||||
@@ -172,6 +178,12 @@ impl WayVR {
|
||||
self.manager.send_key(virtual_key, down);
|
||||
}
|
||||
|
||||
pub fn set_display_visible(&mut self, display: display::DisplayHandle, visible: bool) {
|
||||
if let Some(display) = self.displays.get_mut(&display) {
|
||||
display.set_visible(visible);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_dmabuf_data(&self, display: display::DisplayHandle) -> Option<egl_data::DMAbufData> {
|
||||
self.displays
|
||||
.get(&display)
|
||||
@@ -188,14 +200,6 @@ impl WayVR {
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn get_display_by_handle(
|
||||
&self,
|
||||
display: display::DisplayHandle,
|
||||
) -> Option<&display::Display> {
|
||||
self.displays.get(&display)
|
||||
}
|
||||
|
||||
pub fn create_display(
|
||||
&mut self,
|
||||
width: u32,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#[cfg(not(feature = "wayvr"))]
|
||||
compile_error!("WayVR feature is not enabled");
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
@@ -38,7 +38,7 @@ impl WayVRCatalog {
|
||||
pub struct WayVRConfig {
|
||||
pub version: u32,
|
||||
pub catalogs: HashMap<String, WayVRCatalog>,
|
||||
pub displays: HashMap<String, WayVRDisplay>,
|
||||
pub displays: BTreeMap<String, WayVRDisplay>, // sorted alphabetically
|
||||
}
|
||||
|
||||
impl WayVRConfig {
|
||||
|
||||
@@ -26,7 +26,7 @@ use crate::{
|
||||
};
|
||||
|
||||
#[cfg(feature = "wayvr")]
|
||||
use crate::backend::task::WayVRTask;
|
||||
use crate::overlays::wayvr::WayVRAction;
|
||||
|
||||
use super::{ExecArgs, ModularControl, ModularData};
|
||||
|
||||
@@ -138,10 +138,7 @@ pub enum ButtonAction {
|
||||
action: OverlayAction,
|
||||
},
|
||||
#[cfg(feature = "wayvr")]
|
||||
WayVR {
|
||||
catalog_name: Arc<str>,
|
||||
app_name: Arc<str>,
|
||||
},
|
||||
WayVR(WayVRAction),
|
||||
Window {
|
||||
target: Arc<str>,
|
||||
action: WindowAction,
|
||||
@@ -336,14 +333,8 @@ fn handle_action(action: &ButtonAction, press: &mut PressData, app: &mut AppStat
|
||||
ButtonAction::Overlay { target, action } => run_overlay(target, action, app),
|
||||
ButtonAction::Window { target, action } => run_window(target, action, app),
|
||||
#[cfg(feature = "wayvr")]
|
||||
ButtonAction::WayVR {
|
||||
catalog_name,
|
||||
app_name,
|
||||
} => {
|
||||
app.tasks.enqueue(TaskType::WayVR(WayVRTask {
|
||||
catalog_name: catalog_name.clone(),
|
||||
app_name: app_name.clone(),
|
||||
}));
|
||||
ButtonAction::WayVR(action) => {
|
||||
app.tasks.enqueue(TaskType::WayVR(action.clone()));
|
||||
}
|
||||
ButtonAction::VirtualKey { keycode, action } => app
|
||||
.hid_provider
|
||||
|
||||
@@ -12,6 +12,9 @@ use crate::{
|
||||
graphics::dds::WlxCommandBufferDds, state::AppState,
|
||||
};
|
||||
|
||||
#[cfg(feature = "wayvr")]
|
||||
use crate::overlays::wayvr::{WayVRAction, WayVRDisplayClickAction};
|
||||
|
||||
use self::{
|
||||
button::{modular_button_init, ButtonAction, ButtonData, OverlayAction},
|
||||
label::{modular_label_init, LabelContent, LabelData},
|
||||
@@ -119,6 +122,14 @@ pub enum ModularElement {
|
||||
bg_color: Arc<str>,
|
||||
catalog_name: Arc<str>,
|
||||
},
|
||||
// Ignored if "wayvr" feature is not enabled
|
||||
WayVRDisplayList {
|
||||
rect: [f32; 4],
|
||||
corner_radius: Option<f32>,
|
||||
font_size: isize,
|
||||
fg_color: Arc<str>,
|
||||
bg_color: Arc<str>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Clone)]
|
||||
@@ -440,10 +451,10 @@ pub fn modular_canvas(
|
||||
);
|
||||
|
||||
let data = ButtonData {
|
||||
click_down: Some(vec![ButtonAction::WayVR {
|
||||
click_up: Some(vec![ButtonAction::WayVR(WayVRAction::AppClick {
|
||||
catalog_name: catalog_name.clone(),
|
||||
app_name: Arc::from(app.name.as_str()),
|
||||
}]),
|
||||
})]),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
@@ -456,7 +467,60 @@ pub fn modular_canvas(
|
||||
}
|
||||
#[cfg(not(feature = "wayvr"))]
|
||||
{
|
||||
log::error!("WayVR feature is not available, ignoring");
|
||||
log::error!("WayVR feature is not enabled, ignoring");
|
||||
}
|
||||
}
|
||||
#[allow(unused_variables)]
|
||||
ModularElement::WayVRDisplayList {
|
||||
rect: [x, y, w, h],
|
||||
corner_radius,
|
||||
font_size,
|
||||
fg_color,
|
||||
bg_color,
|
||||
} => {
|
||||
#[cfg(feature = "wayvr")]
|
||||
{
|
||||
let mut button_x = *x;
|
||||
let button_y = *y;
|
||||
let displays = &state.session.wayvr_config.displays;
|
||||
for (display_name, display) in displays {
|
||||
let button_w: f32 = (*w / displays.len() as f32).min(80.0);
|
||||
let button_h: f32 = *h;
|
||||
|
||||
canvas.bg_color = color_parse(bg_color).unwrap_or(*FALLBACK_COLOR);
|
||||
canvas.fg_color = color_parse(fg_color).unwrap_or(*FALLBACK_COLOR);
|
||||
canvas.font_size = *font_size;
|
||||
|
||||
let button = canvas.button(
|
||||
button_x + 2.,
|
||||
button_y + 2.,
|
||||
button_w - 4.,
|
||||
button_h - 4.,
|
||||
corner_radius.unwrap_or_default(),
|
||||
Arc::from(display_name.as_str()),
|
||||
);
|
||||
|
||||
let data = ButtonData {
|
||||
click_up: Some(vec![ButtonAction::WayVR(WayVRAction::DisplayClick {
|
||||
display_name: Arc::from(display_name.as_str()),
|
||||
action: WayVRDisplayClickAction::ToggleVisibility,
|
||||
})]),
|
||||
long_click_up: Some(vec![ButtonAction::WayVR(
|
||||
WayVRAction::DisplayClick {
|
||||
display_name: Arc::from(display_name.as_str()),
|
||||
action: WayVRDisplayClickAction::Reset,
|
||||
},
|
||||
)]),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
modular_button_init(button, &data);
|
||||
button_x += button_w;
|
||||
}
|
||||
}
|
||||
#[cfg(not(feature = "wayvr"))]
|
||||
{
|
||||
log::error!("WayVR feature is not enabled, ignoring")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
use glam::{vec3a, Affine2};
|
||||
use serde::Deserialize;
|
||||
use std::{cell::RefCell, rc::Rc, sync::Arc};
|
||||
use vulkano::image::SubresourceLayout;
|
||||
use wlx_capture::frame::{DmabufFrame, FourCC, FrameFormat, FramePlane};
|
||||
|
||||
use crate::{
|
||||
backend::{
|
||||
common::OverlayContainer,
|
||||
input::{self, InteractionHandler},
|
||||
overlay::{ui_transform, OverlayData, OverlayRenderer, OverlayState, SplitOverlayBackend},
|
||||
wayvr,
|
||||
@@ -53,7 +55,7 @@ impl InteractionHandler for WayVRInteractionHandler {
|
||||
let ctx = self.context.borrow();
|
||||
|
||||
let mut wayvr = ctx.wayvr.borrow_mut();
|
||||
if let Some(disp) = wayvr.get_display_by_handle(ctx.display) {
|
||||
if let Some(disp) = wayvr.displays.get(&ctx.display) {
|
||||
let pos = self.mouse_transform.transform_point2(hit.uv);
|
||||
let x = ((pos.x * disp.width as f32) as i32).max(0);
|
||||
let y = ((pos.y * disp.height as f32) as i32).max(0);
|
||||
@@ -128,7 +130,7 @@ impl WayVRRenderer {
|
||||
|
||||
let ctx = self.context.borrow_mut();
|
||||
let wayvr = ctx.wayvr.borrow_mut();
|
||||
if let Some(disp) = wayvr.get_display_by_handle(ctx.display) {
|
||||
if let Some(disp) = wayvr.displays.get(&ctx.display) {
|
||||
let frame = DmabufFrame {
|
||||
format: FrameFormat {
|
||||
width: disp.width,
|
||||
@@ -175,10 +177,16 @@ impl OverlayRenderer for WayVRRenderer {
|
||||
}
|
||||
|
||||
fn pause(&mut self, _app: &mut state::AppState) -> anyhow::Result<()> {
|
||||
let ctx = self.context.borrow_mut();
|
||||
let mut wayvr = ctx.wayvr.borrow_mut();
|
||||
wayvr.set_display_visible(ctx.display, false);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn resume(&mut self, _app: &mut state::AppState) -> anyhow::Result<()> {
|
||||
let ctx = self.context.borrow_mut();
|
||||
let mut wayvr = ctx.wayvr.borrow_mut();
|
||||
wayvr.set_display_visible(ctx.display, true);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -212,17 +220,18 @@ impl OverlayRenderer for WayVRRenderer {
|
||||
#[allow(dead_code)]
|
||||
pub fn create_wayvr<O>(
|
||||
app: &mut state::AppState,
|
||||
display: &wayvr::display::Display,
|
||||
display_width: u32,
|
||||
display_height: u32,
|
||||
display_handle: wayvr::display::DisplayHandle,
|
||||
display_scale: f32,
|
||||
) -> anyhow::Result<OverlayData<O>>
|
||||
where
|
||||
O: Default,
|
||||
{
|
||||
let transform = ui_transform(&[display.width, display.height]);
|
||||
let transform = ui_transform(&[display_width, display_height]);
|
||||
|
||||
let state = OverlayState {
|
||||
name: format!("WayVR Screen ({}x{})", display.width, display.height).into(),
|
||||
name: format!("WayVR Screen ({}x{})", display_width, display_height).into(),
|
||||
keyboard_focus: Some(KeyboardFocus::WayVR),
|
||||
want_visible: true,
|
||||
interactable: true,
|
||||
@@ -250,10 +259,28 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
fn action_wayvr_internal<O>(
|
||||
#[derive(Deserialize, Clone)]
|
||||
pub enum WayVRDisplayClickAction {
|
||||
ToggleVisibility,
|
||||
Reset,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Clone)]
|
||||
pub enum WayVRAction {
|
||||
AppClick {
|
||||
catalog_name: Arc<str>,
|
||||
app_name: Arc<str>,
|
||||
},
|
||||
DisplayClick {
|
||||
display_name: Arc<str>,
|
||||
action: WayVRDisplayClickAction,
|
||||
},
|
||||
}
|
||||
|
||||
fn action_app_click<O>(
|
||||
app: &mut AppState,
|
||||
catalog_name: &Arc<str>,
|
||||
app_name: &Arc<str>,
|
||||
app: &mut AppState,
|
||||
) -> anyhow::Result<Option<OverlayData<O>>>
|
||||
where
|
||||
O: Default,
|
||||
@@ -294,13 +321,19 @@ where
|
||||
conf_display.height,
|
||||
&app_entry.target_display,
|
||||
)?;
|
||||
let display = wayvr.get_display_by_handle(display_handle).unwrap(); // Never fails
|
||||
created_overlay = Some(create_wayvr::<O>(
|
||||
|
||||
let overlay = create_wayvr::<O>(
|
||||
app,
|
||||
display,
|
||||
conf_display.width,
|
||||
conf_display.height,
|
||||
display_handle,
|
||||
conf_display.scale,
|
||||
)?);
|
||||
)?;
|
||||
|
||||
let display = wayvr.displays.get_mut(&display_handle).unwrap(); // Never fails
|
||||
display.overlay_id = Some(overlay.state.id);
|
||||
|
||||
created_overlay = Some(overlay);
|
||||
display_handle
|
||||
};
|
||||
|
||||
@@ -327,22 +360,70 @@ where
|
||||
Ok(created_overlay)
|
||||
}
|
||||
|
||||
// Returns newly created overlay (if needed)
|
||||
pub fn action_wayvr<O>(
|
||||
catalog_name: &Arc<str>,
|
||||
app_name: &Arc<str>,
|
||||
pub fn action_display_click<O>(
|
||||
app: &mut AppState,
|
||||
) -> Option<OverlayData<O>>
|
||||
overlays: &mut OverlayContainer<O>,
|
||||
display_name: &Arc<str>,
|
||||
action: &WayVRDisplayClickAction,
|
||||
) -> anyhow::Result<()>
|
||||
where
|
||||
O: Default,
|
||||
{
|
||||
match action_wayvr_internal(catalog_name, app_name, app) {
|
||||
Ok(res) => res,
|
||||
let wayvr = app.get_wayvr()?;
|
||||
let mut wayvr = wayvr.borrow_mut();
|
||||
|
||||
if let Some(handle) = wayvr.get_display_by_name(display_name) {
|
||||
if let Some(display) = wayvr.displays.get_mut(&handle) {
|
||||
if let Some(overlay_id) = display.overlay_id {
|
||||
if let Some(overlay) = overlays.mut_by_id(overlay_id) {
|
||||
match action {
|
||||
WayVRDisplayClickAction::ToggleVisibility => {
|
||||
// Toggle visibility
|
||||
overlay.state.want_visible = !overlay.state.want_visible;
|
||||
}
|
||||
WayVRDisplayClickAction::Reset => {
|
||||
// Show it at the front
|
||||
overlay.state.want_visible = true;
|
||||
overlay.state.reset(app, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn wayvr_action<O>(app: &mut AppState, overlays: &mut OverlayContainer<O>, action: &WayVRAction)
|
||||
where
|
||||
O: Default,
|
||||
{
|
||||
match action {
|
||||
WayVRAction::AppClick {
|
||||
catalog_name,
|
||||
app_name,
|
||||
} => {
|
||||
match action_app_click(app, catalog_name, app_name) {
|
||||
Ok(res) => {
|
||||
if let Some(created_overlay) = res {
|
||||
overlays.add(created_overlay);
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
// Happens if something went wrong with initialization
|
||||
// or input exec path is invalid. Do nothing, just print an error
|
||||
log::error!("action_wayvr failed: {}", e);
|
||||
None
|
||||
log::error!("action_app_click failed: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
WayVRAction::DisplayClick {
|
||||
display_name,
|
||||
action,
|
||||
} => {
|
||||
if let Err(e) = action_display_click::<O>(app, overlays, display_name, action) {
|
||||
log::error!("action_display_click failed: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,19 +6,11 @@
|
||||
version: 1
|
||||
|
||||
displays:
|
||||
disp_square:
|
||||
width: 500
|
||||
height: 350
|
||||
scale: 1.0
|
||||
disp_term:
|
||||
Disp1:
|
||||
width: 640
|
||||
height: 480
|
||||
scale: 1.25
|
||||
disp_browser:
|
||||
width: 1280
|
||||
height: 720
|
||||
scale: 2.0
|
||||
disp_plasma:
|
||||
Disp2:
|
||||
width: 1280
|
||||
height: 720
|
||||
scale: 2.0
|
||||
@@ -27,21 +19,17 @@ catalogs:
|
||||
default_catalog:
|
||||
apps:
|
||||
- name: "Calc"
|
||||
target_display: "disp_square"
|
||||
target_display: "Disp1"
|
||||
exec: "kcalc"
|
||||
env: ["FOO=bar"]
|
||||
|
||||
- name: "Terminal"
|
||||
target_display: "disp_term"
|
||||
- name: "htop"
|
||||
target_display: "Disp1"
|
||||
exec: "konsole"
|
||||
args: "-e htop"
|
||||
|
||||
- name: "Browser"
|
||||
target_display: "disp_browser"
|
||||
target_display: "Disp2"
|
||||
exec: "cage"
|
||||
args: "chromium -- --incognito"
|
||||
|
||||
- name: "Plasma"
|
||||
target_display: "disp_plasma"
|
||||
exec: "cage"
|
||||
args: "dbus-run-session -- kwin_wayland --xwayland plasmashell"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user